Home | History | Annotate | Download | only in decoder
      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  */
     91 /*#ifdef ENABLE_RUNTIME_CPU_DETECT
     92 #define DBOOLHUFF_INVOKE(ctx,fn) (ctx)->fn
     93 #define IF_RTCD(x) (x)
     94 #else*/
     95 #define DBOOLHUFF_INVOKE(ctx,fn) vp8_dbool_##fn
     96 #define IF_RTCD(x) NULL
     97 /*#endif*/
     98 
     99 DECLARE_ALIGNED(16, extern const unsigned char, vp8dx_bitreader_norm[256]);
    100 
    101 /* wrapper functions to hide RTCD. static means inline means hopefully no
    102  * penalty
    103  */
    104 static int vp8dx_start_decode(BOOL_DECODER *br,
    105         struct vp8_dboolhuff_rtcd_vtable *rtcd,
    106         const unsigned char *source, unsigned int source_sz) {
    107 #if CONFIG_RUNTIME_CPU_DETECT
    108     br->rtcd = rtcd;
    109 #endif
    110     return DBOOLHUFF_INVOKE(rtcd, start)(br, source, source_sz);
    111 }
    112 static void vp8dx_bool_decoder_fill(BOOL_DECODER *br) {
    113     DBOOLHUFF_INVOKE(br->rtcd, fill)(br);
    114 }
    115 
    116 /*The refill loop is used in several places, so define it in a macro to make
    117    sure they're all consistent.
    118   An inline function would be cleaner, but has a significant penalty, because
    119    multiple BOOL_DECODER fields must be modified, and the compiler is not smart
    120    enough to eliminate the stores to those fields and the subsequent reloads
    121    from them when inlining the function.*/
    122 #define VP8DX_BOOL_DECODER_FILL(_count,_value,_bufptr,_bufend) \
    123     do \
    124     { \
    125         int shift; \
    126         for(shift = VP8_BD_VALUE_SIZE - 8 - ((_count) + 8); shift >= 0; ) \
    127         { \
    128             if((_bufptr) >= (_bufend)) { \
    129                 (_count) = VP8_LOTS_OF_BITS; \
    130                 break; \
    131             } \
    132             (_count) += 8; \
    133             (_value) |= (VP8_BD_VALUE)*(_bufptr)++ << shift; \
    134             shift -= 8; \
    135         } \
    136     } \
    137     while(0)
    138 
    139 
    140 static int vp8dx_decode_bool(BOOL_DECODER *br, int probability) {
    141   /*
    142    * Until optimized versions of this function are available, we
    143    * keep the implementation in the header to allow inlining.
    144    *
    145    *return DBOOLHUFF_INVOKE(br->rtcd, debool)(br, probability);
    146    */
    147     unsigned int bit = 0;
    148     VP8_BD_VALUE value;
    149     unsigned int split;
    150     VP8_BD_VALUE bigsplit;
    151     int count;
    152     unsigned int range;
    153 
    154     value = br->value;
    155     count = br->count;
    156     range = br->range;
    157 
    158     split = 1 + (((range - 1) * probability) >> 8);
    159     bigsplit = (VP8_BD_VALUE)split << (VP8_BD_VALUE_SIZE - 8);
    160 
    161     range = split;
    162 
    163     if (value >= bigsplit)
    164     {
    165         range = br->range - split;
    166         value = value - bigsplit;
    167         bit = 1;
    168     }
    169 
    170     /*if(range>=0x80)
    171     {
    172         br->value = value;
    173         br->range = range;
    174         return bit
    175     }*/
    176 
    177     {
    178         register unsigned int shift = vp8dx_bitreader_norm[range];
    179         range <<= shift;
    180         value <<= shift;
    181         count -= shift;
    182     }
    183     br->value = value;
    184     br->count = count;
    185     br->range = range;
    186     if(count < 0)
    187         vp8dx_bool_decoder_fill(br);
    188     return bit;
    189 }
    190 
    191 static int vp8_decode_value(BOOL_DECODER *br, int bits)
    192 {
    193   /*
    194    * Until optimized versions of this function are available, we
    195    * keep the implementation in the header to allow inlining.
    196    *
    197    *return DBOOLHUFF_INVOKE(br->rtcd, devalue)(br, bits);
    198    */
    199     int z = 0;
    200     int bit;
    201 
    202     for (bit = bits - 1; bit >= 0; bit--)
    203     {
    204         z |= (vp8dx_decode_bool(br, 0x80) << bit);
    205     }
    206 
    207     return z;
    208 }
    209 #endif
    210