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 //#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