1 /* 2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 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 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 12 #ifndef DBOOLHUFF_H 13 #define DBOOLHUFF_H 14 #include <stddef.h> 15 #include <limits.h> 16 #include "vpx_ports/config.h" 17 #include "vpx_ports/mem.h" 18 #include "vpx/vpx_integer.h" 19 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 28 29 30 struct vp8_dboolhuff_rtcd_vtable; 31 32 typedef struct 33 { 34 const unsigned char *user_buffer_end; 35 const unsigned char *user_buffer; 36 VP8_BD_VALUE value; 37 int count; 38 unsigned int range; 39 #if CONFIG_RUNTIME_CPU_DETECT 40 struct vp8_dboolhuff_rtcd_vtable *rtcd; 41 #endif 42 } BOOL_DECODER; 43 44 #define prototype_dbool_start(sym) int sym(BOOL_DECODER *br, \ 45 const unsigned char *source, unsigned int source_sz) 46 #define prototype_dbool_fill(sym) void sym(BOOL_DECODER *br) 47 #define prototype_dbool_debool(sym) int sym(BOOL_DECODER *br, int probability) 48 #define prototype_dbool_devalue(sym) int sym(BOOL_DECODER *br, int bits); 49 50 #if ARCH_ARM 51 #include "arm/dboolhuff_arm.h" 52 #endif 53 54 #ifndef vp8_dbool_start 55 #define vp8_dbool_start vp8dx_start_decode_c 56 #endif 57 58 #ifndef vp8_dbool_fill 59 #define vp8_dbool_fill vp8dx_bool_decoder_fill_c 60 #endif 61 62 #ifndef vp8_dbool_debool 63 #define vp8_dbool_debool vp8dx_decode_bool_c 64 #endif 65 66 #ifndef vp8_dbool_devalue 67 #define vp8_dbool_devalue vp8dx_decode_value_c 68 #endif 69 70 extern prototype_dbool_start(vp8_dbool_start); 71 extern prototype_dbool_fill(vp8_dbool_fill); 72 extern prototype_dbool_debool(vp8_dbool_debool); 73 extern prototype_dbool_devalue(vp8_dbool_devalue); 74 75 typedef prototype_dbool_start((*vp8_dbool_start_fn_t)); 76 typedef prototype_dbool_fill((*vp8_dbool_fill_fn_t)); 77 typedef prototype_dbool_debool((*vp8_dbool_debool_fn_t)); 78 typedef prototype_dbool_devalue((*vp8_dbool_devalue_fn_t)); 79 80 typedef struct vp8_dboolhuff_rtcd_vtable { 81 vp8_dbool_start_fn_t start; 82 vp8_dbool_fill_fn_t fill; 83 vp8_dbool_debool_fn_t debool; 84 vp8_dbool_devalue_fn_t devalue; 85 } vp8_dboolhuff_rtcd_vtable_t; 86 87 // There are no processor-specific versions of these 88 // functions right now. Disable RTCD to avoid using 89 // function pointers which gives a speed boost 90 //#ifdef ENABLE_RUNTIME_CPU_DETECT 91 //#define DBOOLHUFF_INVOKE(ctx,fn) (ctx)->fn 92 //#define IF_RTCD(x) (x) 93 //#else 94 #define DBOOLHUFF_INVOKE(ctx,fn) vp8_dbool_##fn 95 #define IF_RTCD(x) NULL 96 //#endif 97 98 DECLARE_ALIGNED(16, extern const unsigned char, vp8dx_bitreader_norm[256]); 99 100 /* wrapper functions to hide RTCD. static means inline means hopefully no 101 * penalty 102 */ 103 static int vp8dx_start_decode(BOOL_DECODER *br, 104 struct vp8_dboolhuff_rtcd_vtable *rtcd, 105 const unsigned char *source, unsigned int source_sz) { 106 #if CONFIG_RUNTIME_CPU_DETECT 107 br->rtcd = rtcd; 108 #endif 109 return DBOOLHUFF_INVOKE(rtcd, start)(br, source, source_sz); 110 } 111 static void vp8dx_bool_decoder_fill(BOOL_DECODER *br) { 112 DBOOLHUFF_INVOKE(br->rtcd, fill)(br); 113 } 114 115 /*The refill loop is used in several places, so define it in a macro to make 116 sure they're all consistent. 117 An inline function would be cleaner, but has a significant penalty, because 118 multiple BOOL_DECODER fields must be modified, and the compiler is not smart 119 enough to eliminate the stores to those fields and the subsequent reloads 120 from them when inlining the function.*/ 121 #define VP8DX_BOOL_DECODER_FILL(_count,_value,_bufptr,_bufend) \ 122 do \ 123 { \ 124 int shift; \ 125 for(shift = VP8_BD_VALUE_SIZE - 8 - ((_count) + 8); shift >= 0; ) \ 126 { \ 127 if((_bufptr) >= (_bufend)) { \ 128 (_count) = VP8_LOTS_OF_BITS; \ 129 break; \ 130 } \ 131 (_count) += 8; \ 132 (_value) |= (VP8_BD_VALUE)*(_bufptr)++ << shift; \ 133 shift -= 8; \ 134 } \ 135 } \ 136 while(0) 137 138 139 static int vp8dx_decode_bool(BOOL_DECODER *br, int probability) { 140 /* 141 * Until optimized versions of this function are available, we 142 * keep the implementation in the header to allow inlining. 143 * 144 *return DBOOLHUFF_INVOKE(br->rtcd, debool)(br, probability); 145 */ 146 unsigned int bit = 0; 147 VP8_BD_VALUE value; 148 unsigned int split; 149 VP8_BD_VALUE bigsplit; 150 int count; 151 unsigned int range; 152 153 value = br->value; 154 count = br->count; 155 range = br->range; 156 157 split = 1 + (((range - 1) * probability) >> 8); 158 bigsplit = (VP8_BD_VALUE)split << (VP8_BD_VALUE_SIZE - 8); 159 160 range = split; 161 162 if (value >= bigsplit) 163 { 164 range = br->range - split; 165 value = value - bigsplit; 166 bit = 1; 167 } 168 169 /*if(range>=0x80) 170 { 171 br->value = value; 172 br->range = range; 173 return bit 174 }*/ 175 176 { 177 register unsigned int shift = vp8dx_bitreader_norm[range]; 178 range <<= shift; 179 value <<= shift; 180 count -= shift; 181 } 182 br->value = value; 183 br->count = count; 184 br->range = range; 185 if(count < 0) 186 vp8dx_bool_decoder_fill(br); 187 return bit; 188 } 189 190 static int vp8_decode_value(BOOL_DECODER *br, int bits) 191 { 192 /* 193 * Until optimized versions of this function are available, we 194 * keep the implementation in the header to allow inlining. 195 * 196 *return DBOOLHUFF_INVOKE(br->rtcd, devalue)(br, bits); 197 */ 198 int z = 0; 199 int bit; 200 201 for (bit = bits - 1; bit >= 0; bit--) 202 { 203 z |= (vp8dx_decode_bool(br, 0x80) << bit); 204 } 205 206 return z; 207 } 208 #endif 209