michael@0: /* michael@0: * Copyright (c) 2010 The WebM project authors. All Rights Reserved. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license michael@0: * that can be found in the LICENSE file in the root of the source michael@0: * tree. An additional intellectual property rights grant can be found michael@0: * in the file PATENTS. All contributing project authors may michael@0: * be found in the AUTHORS file in the root of the source tree. michael@0: */ michael@0: michael@0: michael@0: #ifndef DBOOLHUFF_H_ michael@0: #define DBOOLHUFF_H_ michael@0: michael@0: #include michael@0: #include michael@0: michael@0: #include "vpx_config.h" michael@0: #include "vpx_ports/mem.h" michael@0: #include "vpx/vpx_integer.h" michael@0: michael@0: typedef size_t VP8_BD_VALUE; michael@0: michael@0: #define VP8_BD_VALUE_SIZE ((int)sizeof(VP8_BD_VALUE)*CHAR_BIT) michael@0: michael@0: /*This is meant to be a large, positive constant that can still be efficiently michael@0: loaded as an immediate (on platforms like ARM, for example). michael@0: Even relatively modest values like 100 would work fine.*/ michael@0: #define VP8_LOTS_OF_BITS (0x40000000) michael@0: michael@0: /*Decrypt n bytes of data from input -> output, using the decrypt_state michael@0: passed in VP8D_SET_DECRYPTOR. michael@0: */ michael@0: typedef void (vp8_decrypt_cb)(void *decrypt_state, const unsigned char *input, michael@0: unsigned char *output, int count); michael@0: michael@0: typedef struct michael@0: { michael@0: const unsigned char *user_buffer_end; michael@0: const unsigned char *user_buffer; michael@0: VP8_BD_VALUE value; michael@0: int count; michael@0: unsigned int range; michael@0: vp8_decrypt_cb *decrypt_cb; michael@0: void *decrypt_state; michael@0: } BOOL_DECODER; michael@0: michael@0: DECLARE_ALIGNED(16, extern const unsigned char, vp8_norm[256]); michael@0: michael@0: int vp8dx_start_decode(BOOL_DECODER *br, michael@0: const unsigned char *source, michael@0: unsigned int source_sz, michael@0: vp8_decrypt_cb *decrypt_cb, michael@0: void *decrypt_state); michael@0: michael@0: void vp8dx_bool_decoder_fill(BOOL_DECODER *br); michael@0: michael@0: michael@0: static int vp8dx_decode_bool(BOOL_DECODER *br, int probability) { michael@0: unsigned int bit = 0; michael@0: VP8_BD_VALUE value; michael@0: unsigned int split; michael@0: VP8_BD_VALUE bigsplit; michael@0: int count; michael@0: unsigned int range; michael@0: michael@0: split = 1 + (((br->range - 1) * probability) >> 8); michael@0: michael@0: if(br->count < 0) michael@0: vp8dx_bool_decoder_fill(br); michael@0: michael@0: value = br->value; michael@0: count = br->count; michael@0: michael@0: bigsplit = (VP8_BD_VALUE)split << (VP8_BD_VALUE_SIZE - 8); michael@0: michael@0: range = split; michael@0: michael@0: if (value >= bigsplit) michael@0: { michael@0: range = br->range - split; michael@0: value = value - bigsplit; michael@0: bit = 1; michael@0: } michael@0: michael@0: { michael@0: register unsigned int shift = vp8_norm[range]; michael@0: range <<= shift; michael@0: value <<= shift; michael@0: count -= shift; michael@0: } michael@0: br->value = value; michael@0: br->count = count; michael@0: br->range = range; michael@0: michael@0: return bit; michael@0: } michael@0: michael@0: static int vp8_decode_value(BOOL_DECODER *br, int bits) michael@0: { michael@0: int z = 0; michael@0: int bit; michael@0: michael@0: for (bit = bits - 1; bit >= 0; bit--) michael@0: { michael@0: z |= (vp8dx_decode_bool(br, 0x80) << bit); michael@0: } michael@0: michael@0: return z; michael@0: } michael@0: michael@0: static int vp8dx_bool_error(BOOL_DECODER *br) michael@0: { michael@0: /* Check if we have reached the end of the buffer. michael@0: * michael@0: * Variable 'count' stores the number of bits in the 'value' buffer, minus michael@0: * 8. The top byte is part of the algorithm, and the remainder is buffered michael@0: * to be shifted into it. So if count == 8, the top 16 bits of 'value' are michael@0: * occupied, 8 for the algorithm and 8 in the buffer. michael@0: * michael@0: * When reading a byte from the user's buffer, count is filled with 8 and michael@0: * one byte is filled into the value buffer. When we reach the end of the michael@0: * data, count is additionally filled with VP8_LOTS_OF_BITS. So when michael@0: * count == VP8_LOTS_OF_BITS - 1, the user's data has been exhausted. michael@0: */ michael@0: if ((br->count > VP8_BD_VALUE_SIZE) && (br->count < VP8_LOTS_OF_BITS)) michael@0: { michael@0: /* We have tried to decode bits after the end of michael@0: * stream was encountered. michael@0: */ michael@0: return 1; michael@0: } michael@0: michael@0: /* No error. */ michael@0: return 0; michael@0: } michael@0: michael@0: #endif // DBOOLHUFF_H_