Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
michael@0 | 1 | /* |
michael@0 | 2 | * Copyright (c) 2010 The WebM project authors. All Rights Reserved. |
michael@0 | 3 | * |
michael@0 | 4 | * Use of this source code is governed by a BSD-style license |
michael@0 | 5 | * that can be found in the LICENSE file in the root of the source |
michael@0 | 6 | * tree. An additional intellectual property rights grant can be found |
michael@0 | 7 | * in the file PATENTS. All contributing project authors may |
michael@0 | 8 | * be found in the AUTHORS file in the root of the source tree. |
michael@0 | 9 | */ |
michael@0 | 10 | |
michael@0 | 11 | |
michael@0 | 12 | #ifndef DBOOLHUFF_H_ |
michael@0 | 13 | #define DBOOLHUFF_H_ |
michael@0 | 14 | |
michael@0 | 15 | #include <stddef.h> |
michael@0 | 16 | #include <limits.h> |
michael@0 | 17 | |
michael@0 | 18 | #include "vpx_config.h" |
michael@0 | 19 | #include "vpx_ports/mem.h" |
michael@0 | 20 | #include "vpx/vpx_integer.h" |
michael@0 | 21 | |
michael@0 | 22 | typedef size_t VP8_BD_VALUE; |
michael@0 | 23 | |
michael@0 | 24 | #define VP8_BD_VALUE_SIZE ((int)sizeof(VP8_BD_VALUE)*CHAR_BIT) |
michael@0 | 25 | |
michael@0 | 26 | /*This is meant to be a large, positive constant that can still be efficiently |
michael@0 | 27 | loaded as an immediate (on platforms like ARM, for example). |
michael@0 | 28 | Even relatively modest values like 100 would work fine.*/ |
michael@0 | 29 | #define VP8_LOTS_OF_BITS (0x40000000) |
michael@0 | 30 | |
michael@0 | 31 | /*Decrypt n bytes of data from input -> output, using the decrypt_state |
michael@0 | 32 | passed in VP8D_SET_DECRYPTOR. |
michael@0 | 33 | */ |
michael@0 | 34 | typedef void (vp8_decrypt_cb)(void *decrypt_state, const unsigned char *input, |
michael@0 | 35 | unsigned char *output, int count); |
michael@0 | 36 | |
michael@0 | 37 | typedef struct |
michael@0 | 38 | { |
michael@0 | 39 | const unsigned char *user_buffer_end; |
michael@0 | 40 | const unsigned char *user_buffer; |
michael@0 | 41 | VP8_BD_VALUE value; |
michael@0 | 42 | int count; |
michael@0 | 43 | unsigned int range; |
michael@0 | 44 | vp8_decrypt_cb *decrypt_cb; |
michael@0 | 45 | void *decrypt_state; |
michael@0 | 46 | } BOOL_DECODER; |
michael@0 | 47 | |
michael@0 | 48 | DECLARE_ALIGNED(16, extern const unsigned char, vp8_norm[256]); |
michael@0 | 49 | |
michael@0 | 50 | int vp8dx_start_decode(BOOL_DECODER *br, |
michael@0 | 51 | const unsigned char *source, |
michael@0 | 52 | unsigned int source_sz, |
michael@0 | 53 | vp8_decrypt_cb *decrypt_cb, |
michael@0 | 54 | void *decrypt_state); |
michael@0 | 55 | |
michael@0 | 56 | void vp8dx_bool_decoder_fill(BOOL_DECODER *br); |
michael@0 | 57 | |
michael@0 | 58 | |
michael@0 | 59 | static int vp8dx_decode_bool(BOOL_DECODER *br, int probability) { |
michael@0 | 60 | unsigned int bit = 0; |
michael@0 | 61 | VP8_BD_VALUE value; |
michael@0 | 62 | unsigned int split; |
michael@0 | 63 | VP8_BD_VALUE bigsplit; |
michael@0 | 64 | int count; |
michael@0 | 65 | unsigned int range; |
michael@0 | 66 | |
michael@0 | 67 | split = 1 + (((br->range - 1) * probability) >> 8); |
michael@0 | 68 | |
michael@0 | 69 | if(br->count < 0) |
michael@0 | 70 | vp8dx_bool_decoder_fill(br); |
michael@0 | 71 | |
michael@0 | 72 | value = br->value; |
michael@0 | 73 | count = br->count; |
michael@0 | 74 | |
michael@0 | 75 | bigsplit = (VP8_BD_VALUE)split << (VP8_BD_VALUE_SIZE - 8); |
michael@0 | 76 | |
michael@0 | 77 | range = split; |
michael@0 | 78 | |
michael@0 | 79 | if (value >= bigsplit) |
michael@0 | 80 | { |
michael@0 | 81 | range = br->range - split; |
michael@0 | 82 | value = value - bigsplit; |
michael@0 | 83 | bit = 1; |
michael@0 | 84 | } |
michael@0 | 85 | |
michael@0 | 86 | { |
michael@0 | 87 | register unsigned int shift = vp8_norm[range]; |
michael@0 | 88 | range <<= shift; |
michael@0 | 89 | value <<= shift; |
michael@0 | 90 | count -= shift; |
michael@0 | 91 | } |
michael@0 | 92 | br->value = value; |
michael@0 | 93 | br->count = count; |
michael@0 | 94 | br->range = range; |
michael@0 | 95 | |
michael@0 | 96 | return bit; |
michael@0 | 97 | } |
michael@0 | 98 | |
michael@0 | 99 | static int vp8_decode_value(BOOL_DECODER *br, int bits) |
michael@0 | 100 | { |
michael@0 | 101 | int z = 0; |
michael@0 | 102 | int bit; |
michael@0 | 103 | |
michael@0 | 104 | for (bit = bits - 1; bit >= 0; bit--) |
michael@0 | 105 | { |
michael@0 | 106 | z |= (vp8dx_decode_bool(br, 0x80) << bit); |
michael@0 | 107 | } |
michael@0 | 108 | |
michael@0 | 109 | return z; |
michael@0 | 110 | } |
michael@0 | 111 | |
michael@0 | 112 | static int vp8dx_bool_error(BOOL_DECODER *br) |
michael@0 | 113 | { |
michael@0 | 114 | /* Check if we have reached the end of the buffer. |
michael@0 | 115 | * |
michael@0 | 116 | * Variable 'count' stores the number of bits in the 'value' buffer, minus |
michael@0 | 117 | * 8. The top byte is part of the algorithm, and the remainder is buffered |
michael@0 | 118 | * to be shifted into it. So if count == 8, the top 16 bits of 'value' are |
michael@0 | 119 | * occupied, 8 for the algorithm and 8 in the buffer. |
michael@0 | 120 | * |
michael@0 | 121 | * When reading a byte from the user's buffer, count is filled with 8 and |
michael@0 | 122 | * one byte is filled into the value buffer. When we reach the end of the |
michael@0 | 123 | * data, count is additionally filled with VP8_LOTS_OF_BITS. So when |
michael@0 | 124 | * count == VP8_LOTS_OF_BITS - 1, the user's data has been exhausted. |
michael@0 | 125 | */ |
michael@0 | 126 | if ((br->count > VP8_BD_VALUE_SIZE) && (br->count < VP8_LOTS_OF_BITS)) |
michael@0 | 127 | { |
michael@0 | 128 | /* We have tried to decode bits after the end of |
michael@0 | 129 | * stream was encountered. |
michael@0 | 130 | */ |
michael@0 | 131 | return 1; |
michael@0 | 132 | } |
michael@0 | 133 | |
michael@0 | 134 | /* No error. */ |
michael@0 | 135 | return 0; |
michael@0 | 136 | } |
michael@0 | 137 | |
michael@0 | 138 | #endif // DBOOLHUFF_H_ |