John Koleszar | 0ea50ce | 2010-05-18 11:58:33 -0400 | [diff] [blame] | 1 | /* |
John Koleszar | c2140b8 | 2010-09-09 08:16:39 -0400 | [diff] [blame] | 2 | * Copyright (c) 2010 The WebM project authors. All Rights Reserved. |
John Koleszar | 0ea50ce | 2010-05-18 11:58:33 -0400 | [diff] [blame] | 3 | * |
John Koleszar | 94c52e4 | 2010-06-18 12:39:21 -0400 | [diff] [blame] | 4 | * Use of this source code is governed by a BSD-style license |
John Koleszar | 09202d8 | 2010-06-04 16:19:40 -0400 | [diff] [blame] | 5 | * that can be found in the LICENSE file in the root of the source |
| 6 | * tree. An additional intellectual property rights grant can be found |
John Koleszar | 94c52e4 | 2010-06-18 12:39:21 -0400 | [diff] [blame] | 7 | * in the file PATENTS. All contributing project authors may |
John Koleszar | 09202d8 | 2010-06-04 16:19:40 -0400 | [diff] [blame] | 8 | * be found in the AUTHORS file in the root of the source tree. |
John Koleszar | 0ea50ce | 2010-05-18 11:58:33 -0400 | [diff] [blame] | 9 | */ |
| 10 | |
| 11 | |
| 12 | #ifndef DBOOLHUFF_H |
| 13 | #define DBOOLHUFF_H |
Timothy B. Terriberry | c17b62e | 2010-05-05 17:58:19 -0400 | [diff] [blame] | 14 | #include <stddef.h> |
| 15 | #include <limits.h> |
John Koleszar | 0ea50ce | 2010-05-18 11:58:33 -0400 | [diff] [blame] | 16 | #include "vpx_ports/config.h" |
| 17 | #include "vpx_ports/mem.h" |
John Koleszar | b749234 | 2010-05-24 11:39:59 -0400 | [diff] [blame] | 18 | #include "vpx/vpx_integer.h" |
John Koleszar | 0ea50ce | 2010-05-18 11:58:33 -0400 | [diff] [blame] | 19 | |
Timothy B. Terriberry | c17b62e | 2010-05-05 17:58:19 -0400 | [diff] [blame] | 20 | typedef size_t VP8_BD_VALUE; |
| 21 | |
| 22 | # define VP8_BD_VALUE_SIZE ((int)sizeof(VP8_BD_VALUE)*CHAR_BIT) |
| 23 | /*This is meant to be a large, positive constant that can still be efficiently |
| 24 | loaded as an immediate (on platforms like ARM, for example). |
| 25 | Even relatively modest values like 100 would work fine.*/ |
| 26 | # define VP8_LOTS_OF_BITS (0x40000000) |
| 27 | |
John Koleszar | 0ea50ce | 2010-05-18 11:58:33 -0400 | [diff] [blame] | 28 | typedef struct |
| 29 | { |
Timothy B. Terriberry | c17b62e | 2010-05-05 17:58:19 -0400 | [diff] [blame] | 30 | const unsigned char *user_buffer_end; |
John Koleszar | 0ea50ce | 2010-05-18 11:58:33 -0400 | [diff] [blame] | 31 | const unsigned char *user_buffer; |
Timothy B. Terriberry | c17b62e | 2010-05-05 17:58:19 -0400 | [diff] [blame] | 32 | VP8_BD_VALUE value; |
| 33 | int count; |
| 34 | unsigned int range; |
John Koleszar | 0ea50ce | 2010-05-18 11:58:33 -0400 | [diff] [blame] | 35 | } BOOL_DECODER; |
| 36 | |
Scott LaVarnway | a25f6a9 | 2011-07-19 09:17:25 -0400 | [diff] [blame] | 37 | DECLARE_ALIGNED(16, extern const unsigned char, vp8_norm[256]); |
John Koleszar | 0ea50ce | 2010-05-18 11:58:33 -0400 | [diff] [blame] | 38 | |
Johann | bb9c95e | 2011-02-04 16:00:00 -0500 | [diff] [blame] | 39 | int vp8dx_start_decode(BOOL_DECODER *br, |
| 40 | const unsigned char *source, |
| 41 | unsigned int source_sz); |
| 42 | |
| 43 | void vp8dx_bool_decoder_fill(BOOL_DECODER *br); |
Timothy B. Terriberry | c17b62e | 2010-05-05 17:58:19 -0400 | [diff] [blame] | 44 | |
Deb Mukherjee | c6f1bf4 | 2012-04-12 09:24:03 -0700 | [diff] [blame^] | 45 | #if CONFIG_NEWUPDATE |
| 46 | int vp8_decode_uniform(BOOL_DECODER *br, int n); |
| 47 | int vp8_decode_term_subexp(BOOL_DECODER *br, int k, int num_syms); |
| 48 | int inv_recenter_nonneg(int v, int m); |
| 49 | #endif |
| 50 | |
Timothy B. Terriberry | c17b62e | 2010-05-05 17:58:19 -0400 | [diff] [blame] | 51 | /*The refill loop is used in several places, so define it in a macro to make |
| 52 | sure they're all consistent. |
| 53 | An inline function would be cleaner, but has a significant penalty, because |
| 54 | multiple BOOL_DECODER fields must be modified, and the compiler is not smart |
| 55 | enough to eliminate the stores to those fields and the subsequent reloads |
| 56 | from them when inlining the function.*/ |
| 57 | #define VP8DX_BOOL_DECODER_FILL(_count,_value,_bufptr,_bufend) \ |
| 58 | do \ |
| 59 | { \ |
John Koleszar | 5e1fd41 | 2011-04-26 12:52:17 -0400 | [diff] [blame] | 60 | int shift = VP8_BD_VALUE_SIZE - 8 - ((_count) + 8); \ |
| 61 | int loop_end, x; \ |
| 62 | size_t bits_left = ((_bufend)-(_bufptr))*CHAR_BIT; \ |
| 63 | \ |
| 64 | x = shift + CHAR_BIT - bits_left; \ |
| 65 | loop_end = 0; \ |
| 66 | if(x >= 0) \ |
Timothy B. Terriberry | c17b62e | 2010-05-05 17:58:19 -0400 | [diff] [blame] | 67 | { \ |
John Koleszar | 5e1fd41 | 2011-04-26 12:52:17 -0400 | [diff] [blame] | 68 | (_count) += VP8_LOTS_OF_BITS; \ |
| 69 | loop_end = x; \ |
| 70 | if(!bits_left) break; \ |
| 71 | } \ |
| 72 | while(shift >= loop_end) \ |
| 73 | { \ |
| 74 | (_count) += CHAR_BIT; \ |
Timothy B. Terriberry | c17b62e | 2010-05-05 17:58:19 -0400 | [diff] [blame] | 75 | (_value) |= (VP8_BD_VALUE)*(_bufptr)++ << shift; \ |
John Koleszar | 5e1fd41 | 2011-04-26 12:52:17 -0400 | [diff] [blame] | 76 | shift -= CHAR_BIT; \ |
Timothy B. Terriberry | c17b62e | 2010-05-05 17:58:19 -0400 | [diff] [blame] | 77 | } \ |
| 78 | } \ |
John Koleszar | 5e1fd41 | 2011-04-26 12:52:17 -0400 | [diff] [blame] | 79 | while(0) \ |
Timothy B. Terriberry | c17b62e | 2010-05-05 17:58:19 -0400 | [diff] [blame] | 80 | |
| 81 | |
John Koleszar | 0ea50ce | 2010-05-18 11:58:33 -0400 | [diff] [blame] | 82 | static int vp8dx_decode_bool(BOOL_DECODER *br, int probability) { |
John Koleszar | 0ea50ce | 2010-05-18 11:58:33 -0400 | [diff] [blame] | 83 | unsigned int bit = 0; |
Timothy B. Terriberry | c17b62e | 2010-05-05 17:58:19 -0400 | [diff] [blame] | 84 | VP8_BD_VALUE value; |
John Koleszar | 0ea50ce | 2010-05-18 11:58:33 -0400 | [diff] [blame] | 85 | unsigned int split; |
Timothy B. Terriberry | c17b62e | 2010-05-05 17:58:19 -0400 | [diff] [blame] | 86 | VP8_BD_VALUE bigsplit; |
| 87 | int count; |
| 88 | unsigned int range; |
| 89 | |
Scott LaVarnway | 67a1f98 | 2011-06-20 14:44:16 -0400 | [diff] [blame] | 90 | split = 1 + (((br->range - 1) * probability) >> 8); |
| 91 | |
| 92 | if(br->count < 0) |
| 93 | vp8dx_bool_decoder_fill(br); |
| 94 | |
Timothy B. Terriberry | c17b62e | 2010-05-05 17:58:19 -0400 | [diff] [blame] | 95 | value = br->value; |
| 96 | count = br->count; |
John Koleszar | 0ea50ce | 2010-05-18 11:58:33 -0400 | [diff] [blame] | 97 | |
Timothy B. Terriberry | c17b62e | 2010-05-05 17:58:19 -0400 | [diff] [blame] | 98 | bigsplit = (VP8_BD_VALUE)split << (VP8_BD_VALUE_SIZE - 8); |
John Koleszar | 0ea50ce | 2010-05-18 11:58:33 -0400 | [diff] [blame] | 99 | |
| 100 | range = split; |
| 101 | |
| 102 | if (value >= bigsplit) |
| 103 | { |
| 104 | range = br->range - split; |
| 105 | value = value - bigsplit; |
| 106 | bit = 1; |
| 107 | } |
| 108 | |
John Koleszar | 0ea50ce | 2010-05-18 11:58:33 -0400 | [diff] [blame] | 109 | { |
Scott LaVarnway | a25f6a9 | 2011-07-19 09:17:25 -0400 | [diff] [blame] | 110 | register unsigned int shift = vp8_norm[range]; |
John Koleszar | 0ea50ce | 2010-05-18 11:58:33 -0400 | [diff] [blame] | 111 | range <<= shift; |
| 112 | value <<= shift; |
| 113 | count -= shift; |
John Koleszar | 0ea50ce | 2010-05-18 11:58:33 -0400 | [diff] [blame] | 114 | } |
| 115 | br->value = value; |
Timothy B. Terriberry | c17b62e | 2010-05-05 17:58:19 -0400 | [diff] [blame] | 116 | br->count = count; |
John Koleszar | 0ea50ce | 2010-05-18 11:58:33 -0400 | [diff] [blame] | 117 | br->range = range; |
Scott LaVarnway | 67a1f98 | 2011-06-20 14:44:16 -0400 | [diff] [blame] | 118 | |
John Koleszar | 0ea50ce | 2010-05-18 11:58:33 -0400 | [diff] [blame] | 119 | return bit; |
| 120 | } |
| 121 | |
| 122 | static int vp8_decode_value(BOOL_DECODER *br, int bits) |
| 123 | { |
John Koleszar | 0ea50ce | 2010-05-18 11:58:33 -0400 | [diff] [blame] | 124 | int z = 0; |
| 125 | int bit; |
| 126 | |
| 127 | for (bit = bits - 1; bit >= 0; bit--) |
| 128 | { |
| 129 | z |= (vp8dx_decode_bool(br, 0x80) << bit); |
| 130 | } |
| 131 | |
| 132 | return z; |
| 133 | } |
Henrik Lundin | 67fb3a5 | 2010-12-16 16:46:31 +0100 | [diff] [blame] | 134 | |
| 135 | static int vp8dx_bool_error(BOOL_DECODER *br) |
| 136 | { |
John Koleszar | 9594370 | 2011-04-26 12:36:03 -0400 | [diff] [blame] | 137 | /* Check if we have reached the end of the buffer. |
| 138 | * |
| 139 | * Variable 'count' stores the number of bits in the 'value' buffer, minus |
| 140 | * 8. The top byte is part of the algorithm, and the remainder is buffered |
| 141 | * to be shifted into it. So if count == 8, the top 16 bits of 'value' are |
| 142 | * occupied, 8 for the algorithm and 8 in the buffer. |
| 143 | * |
| 144 | * When reading a byte from the user's buffer, count is filled with 8 and |
| 145 | * one byte is filled into the value buffer. When we reach the end of the |
| 146 | * data, count is additionally filled with VP8_LOTS_OF_BITS. So when |
| 147 | * count == VP8_LOTS_OF_BITS - 1, the user's data has been exhausted. |
| 148 | */ |
| 149 | if ((br->count > VP8_BD_VALUE_SIZE) && (br->count < VP8_LOTS_OF_BITS)) |
Henrik Lundin | 67fb3a5 | 2010-12-16 16:46:31 +0100 | [diff] [blame] | 150 | { |
| 151 | /* We have tried to decode bits after the end of |
| 152 | * stream was encountered. |
| 153 | */ |
| 154 | return 1; |
| 155 | } |
| 156 | |
| 157 | /* No error. */ |
| 158 | return 0; |
| 159 | } |
Deb Mukherjee | c6f1bf4 | 2012-04-12 09:24:03 -0700 | [diff] [blame^] | 160 | |
John Koleszar | 0ea50ce | 2010-05-18 11:58:33 -0400 | [diff] [blame] | 161 | #endif |