dboolhuff.h 5.77 KB
Newer Older
John Koleszar's avatar
John Koleszar committed
1
/*
2
 *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
John Koleszar's avatar
John Koleszar committed
3
 *
4
 *  Use of this source code is governed by a BSD-style license
5
6
 *  that can be found in the LICENSE file in the root of the source
 *  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.
John Koleszar's avatar
John Koleszar committed
9
10
11
12
13
 */


#ifndef DBOOLHUFF_H
#define DBOOLHUFF_H
14
15
#include <stddef.h>
#include <limits.h>
John Koleszar's avatar
John Koleszar committed
16
17
#include "vpx_ports/config.h"
#include "vpx_ports/mem.h"
18
#include "vpx/vpx_integer.h"
John Koleszar's avatar
John Koleszar committed
19

20
21
22
23
24
25
26
27
28
typedef size_t VP8_BD_VALUE;

# define VP8_BD_VALUE_SIZE ((int)sizeof(VP8_BD_VALUE)*CHAR_BIT)
/*This is meant to be a large, positive constant that can still be efficiently
   loaded as an immediate (on platforms like ARM, for example).
  Even relatively modest values like 100 would work fine.*/
# define VP8_LOTS_OF_BITS (0x40000000)


John Koleszar's avatar
John Koleszar committed
29
30
31
32
33

struct vp8_dboolhuff_rtcd_vtable;

typedef struct
{
34
    const unsigned char *user_buffer_end;
John Koleszar's avatar
John Koleszar committed
35
    const unsigned char *user_buffer;
36
37
38
    VP8_BD_VALUE         value;
    int                  count;
    unsigned int         range;
John Koleszar's avatar
John Koleszar committed
39
40
41
42
43
44
45
46
47
#if CONFIG_RUNTIME_CPU_DETECT
    struct vp8_dboolhuff_rtcd_vtable *rtcd;
#endif
} BOOL_DECODER;

#define prototype_dbool_start(sym) int sym(BOOL_DECODER *br, \
    const unsigned char *source, unsigned int source_sz)
#define prototype_dbool_fill(sym) void sym(BOOL_DECODER *br)
#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)
John Koleszar's avatar
John Koleszar committed
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

#if ARCH_ARM
#include "arm/dboolhuff_arm.h"
#endif

#ifndef vp8_dbool_start
#define vp8_dbool_start vp8dx_start_decode_c
#endif

#ifndef vp8_dbool_fill
#define vp8_dbool_fill vp8dx_bool_decoder_fill_c
#endif

#ifndef vp8_dbool_debool
#define vp8_dbool_debool vp8dx_decode_bool_c
#endif

#ifndef vp8_dbool_devalue
#define vp8_dbool_devalue vp8dx_decode_value_c
#endif

extern prototype_dbool_start(vp8_dbool_start);
extern prototype_dbool_fill(vp8_dbool_fill);
extern prototype_dbool_debool(vp8_dbool_debool);
extern prototype_dbool_devalue(vp8_dbool_devalue);

typedef prototype_dbool_start((*vp8_dbool_start_fn_t));
typedef prototype_dbool_fill((*vp8_dbool_fill_fn_t));
typedef prototype_dbool_debool((*vp8_dbool_debool_fn_t));
typedef prototype_dbool_devalue((*vp8_dbool_devalue_fn_t));

typedef struct vp8_dboolhuff_rtcd_vtable {
    vp8_dbool_start_fn_t   start;
    vp8_dbool_fill_fn_t    fill;
    vp8_dbool_debool_fn_t  debool;
    vp8_dbool_devalue_fn_t devalue;
} vp8_dboolhuff_rtcd_vtable_t;

87
88
89
90
91
92
93
94
/* There are no processor-specific versions of these
 * functions right now. Disable RTCD to avoid using
 * function pointers which gives a speed boost
 */
/*#ifdef ENABLE_RUNTIME_CPU_DETECT
#define DBOOLHUFF_INVOKE(ctx,fn) (ctx)->fn
#define IF_RTCD(x) (x)
#else*/
John Koleszar's avatar
John Koleszar committed
95
96
#define DBOOLHUFF_INVOKE(ctx,fn) vp8_dbool_##fn
#define IF_RTCD(x) NULL
97
/*#endif*/
John Koleszar's avatar
John Koleszar committed
98

99
DECLARE_ALIGNED(16, extern const unsigned char, vp8dx_bitreader_norm[256]);
John Koleszar's avatar
John Koleszar committed
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114

/* wrapper functions to hide RTCD. static means inline means hopefully no
 * penalty
 */
static int vp8dx_start_decode(BOOL_DECODER *br,
        struct vp8_dboolhuff_rtcd_vtable *rtcd,
        const unsigned char *source, unsigned int source_sz) {
#if CONFIG_RUNTIME_CPU_DETECT
    br->rtcd = rtcd;
#endif
    return DBOOLHUFF_INVOKE(rtcd, start)(br, source, source_sz);
}
static void vp8dx_bool_decoder_fill(BOOL_DECODER *br) {
    DBOOLHUFF_INVOKE(br->rtcd, fill)(br);
}
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139

/*The refill loop is used in several places, so define it in a macro to make
   sure they're all consistent.
  An inline function would be cleaner, but has a significant penalty, because
   multiple BOOL_DECODER fields must be modified, and the compiler is not smart
   enough to eliminate the stores to those fields and the subsequent reloads
   from them when inlining the function.*/
#define VP8DX_BOOL_DECODER_FILL(_count,_value,_bufptr,_bufend) \
    do \
    { \
        int shift; \
        for(shift = VP8_BD_VALUE_SIZE - 8 - ((_count) + 8); shift >= 0; ) \
        { \
            if((_bufptr) >= (_bufend)) { \
                (_count) = VP8_LOTS_OF_BITS; \
                break; \
            } \
            (_count) += 8; \
            (_value) |= (VP8_BD_VALUE)*(_bufptr)++ << shift; \
            shift -= 8; \
        } \
    } \
    while(0)


John Koleszar's avatar
John Koleszar committed
140
141
142
143
144
145
146
147
static int vp8dx_decode_bool(BOOL_DECODER *br, int probability) {
  /*
   * Until optimized versions of this function are available, we
   * keep the implementation in the header to allow inlining.
   *
   *return DBOOLHUFF_INVOKE(br->rtcd, debool)(br, probability);
   */
    unsigned int bit = 0;
148
    VP8_BD_VALUE value;
John Koleszar's avatar
John Koleszar committed
149
    unsigned int split;
150
151
152
153
154
155
156
    VP8_BD_VALUE bigsplit;
    int count;
    unsigned int range;

    value = br->value;
    count = br->count;
    range = br->range;
John Koleszar's avatar
John Koleszar committed
157
158

    split = 1 + (((range - 1) * probability) >> 8);
159
    bigsplit = (VP8_BD_VALUE)split << (VP8_BD_VALUE_SIZE - 8);
John Koleszar's avatar
John Koleszar committed
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183

    range = split;

    if (value >= bigsplit)
    {
        range = br->range - split;
        value = value - bigsplit;
        bit = 1;
    }

    /*if(range>=0x80)
    {
        br->value = value;
        br->range = range;
        return bit
    }*/

    {
        register unsigned int shift = vp8dx_bitreader_norm[range];
        range <<= shift;
        value <<= shift;
        count -= shift;
    }
    br->value = value;
184
    br->count = count;
John Koleszar's avatar
John Koleszar committed
185
    br->range = range;
186
187
    if(count < 0)
        vp8dx_bool_decoder_fill(br);
John Koleszar's avatar
John Koleszar committed
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
    return bit;
}

static int vp8_decode_value(BOOL_DECODER *br, int bits)
{
  /*
   * Until optimized versions of this function are available, we
   * keep the implementation in the header to allow inlining.
   *
   *return DBOOLHUFF_INVOKE(br->rtcd, devalue)(br, bits);
   */
    int z = 0;
    int bit;

    for (bit = bits - 1; bit >= 0; bit--)
    {
        z |= (vp8dx_decode_bool(br, 0x80) << bit);
    }

    return z;
}
#endif