1*61046927SAndroid Build Coastguard Worker /**************************************************************************
2*61046927SAndroid Build Coastguard Worker *
3*61046927SAndroid Build Coastguard Worker * Copyright 2011 Christian König.
4*61046927SAndroid Build Coastguard Worker * All Rights Reserved.
5*61046927SAndroid Build Coastguard Worker *
6*61046927SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a
7*61046927SAndroid Build Coastguard Worker * copy of this software and associated documentation files (the
8*61046927SAndroid Build Coastguard Worker * "Software"), to deal in the Software without restriction, including
9*61046927SAndroid Build Coastguard Worker * without limitation the rights to use, copy, modify, merge, publish,
10*61046927SAndroid Build Coastguard Worker * distribute, sub license, and/or sell copies of the Software, and to
11*61046927SAndroid Build Coastguard Worker * permit persons to whom the Software is furnished to do so, subject to
12*61046927SAndroid Build Coastguard Worker * the following conditions:
13*61046927SAndroid Build Coastguard Worker *
14*61046927SAndroid Build Coastguard Worker * The above copyright notice and this permission notice (including the
15*61046927SAndroid Build Coastguard Worker * next paragraph) shall be included in all copies or substantial portions
16*61046927SAndroid Build Coastguard Worker * of the Software.
17*61046927SAndroid Build Coastguard Worker *
18*61046927SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19*61046927SAndroid Build Coastguard Worker * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20*61046927SAndroid Build Coastguard Worker * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21*61046927SAndroid Build Coastguard Worker * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22*61046927SAndroid Build Coastguard Worker * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23*61046927SAndroid Build Coastguard Worker * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24*61046927SAndroid Build Coastguard Worker * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25*61046927SAndroid Build Coastguard Worker *
26*61046927SAndroid Build Coastguard Worker **************************************************************************/
27*61046927SAndroid Build Coastguard Worker
28*61046927SAndroid Build Coastguard Worker /*
29*61046927SAndroid Build Coastguard Worker * Functions for fast bitwise access to multiple probably unaligned input buffers
30*61046927SAndroid Build Coastguard Worker */
31*61046927SAndroid Build Coastguard Worker
32*61046927SAndroid Build Coastguard Worker #ifndef vl_vlc_h
33*61046927SAndroid Build Coastguard Worker #define vl_vlc_h
34*61046927SAndroid Build Coastguard Worker
35*61046927SAndroid Build Coastguard Worker #include "util/u_math.h"
36*61046927SAndroid Build Coastguard Worker
37*61046927SAndroid Build Coastguard Worker struct vl_vlc
38*61046927SAndroid Build Coastguard Worker {
39*61046927SAndroid Build Coastguard Worker uint64_t buffer;
40*61046927SAndroid Build Coastguard Worker signed invalid_bits;
41*61046927SAndroid Build Coastguard Worker const uint8_t *data;
42*61046927SAndroid Build Coastguard Worker const uint8_t *end;
43*61046927SAndroid Build Coastguard Worker
44*61046927SAndroid Build Coastguard Worker const void *const *inputs;
45*61046927SAndroid Build Coastguard Worker const unsigned *sizes;
46*61046927SAndroid Build Coastguard Worker unsigned bytes_left;
47*61046927SAndroid Build Coastguard Worker };
48*61046927SAndroid Build Coastguard Worker
49*61046927SAndroid Build Coastguard Worker struct vl_vlc_entry
50*61046927SAndroid Build Coastguard Worker {
51*61046927SAndroid Build Coastguard Worker int8_t length;
52*61046927SAndroid Build Coastguard Worker int8_t value;
53*61046927SAndroid Build Coastguard Worker };
54*61046927SAndroid Build Coastguard Worker
55*61046927SAndroid Build Coastguard Worker struct vl_vlc_compressed
56*61046927SAndroid Build Coastguard Worker {
57*61046927SAndroid Build Coastguard Worker uint16_t bitcode;
58*61046927SAndroid Build Coastguard Worker struct vl_vlc_entry entry;
59*61046927SAndroid Build Coastguard Worker };
60*61046927SAndroid Build Coastguard Worker
61*61046927SAndroid Build Coastguard Worker /**
62*61046927SAndroid Build Coastguard Worker * initalize and decompress a lookup table
63*61046927SAndroid Build Coastguard Worker */
64*61046927SAndroid Build Coastguard Worker static inline void
vl_vlc_init_table(struct vl_vlc_entry * dst,unsigned dst_size,const struct vl_vlc_compressed * src,unsigned src_size)65*61046927SAndroid Build Coastguard Worker vl_vlc_init_table(struct vl_vlc_entry *dst, unsigned dst_size, const struct vl_vlc_compressed *src, unsigned src_size)
66*61046927SAndroid Build Coastguard Worker {
67*61046927SAndroid Build Coastguard Worker unsigned i, bits = util_logbase2(dst_size);
68*61046927SAndroid Build Coastguard Worker
69*61046927SAndroid Build Coastguard Worker assert(dst && dst_size);
70*61046927SAndroid Build Coastguard Worker assert(src && src_size);
71*61046927SAndroid Build Coastguard Worker
72*61046927SAndroid Build Coastguard Worker for (i=0;i<dst_size;++i) {
73*61046927SAndroid Build Coastguard Worker dst[i].length = 0;
74*61046927SAndroid Build Coastguard Worker dst[i].value = 0;
75*61046927SAndroid Build Coastguard Worker }
76*61046927SAndroid Build Coastguard Worker
77*61046927SAndroid Build Coastguard Worker for(; src_size > 0; --src_size, ++src) {
78*61046927SAndroid Build Coastguard Worker for(i = 0; i < (1u << (bits - src->entry.length)); ++i)
79*61046927SAndroid Build Coastguard Worker dst[src->bitcode >> (16 - bits) | i] = src->entry;
80*61046927SAndroid Build Coastguard Worker }
81*61046927SAndroid Build Coastguard Worker }
82*61046927SAndroid Build Coastguard Worker
83*61046927SAndroid Build Coastguard Worker /**
84*61046927SAndroid Build Coastguard Worker * switch over to next input buffer
85*61046927SAndroid Build Coastguard Worker */
86*61046927SAndroid Build Coastguard Worker static inline void
vl_vlc_next_input(struct vl_vlc * vlc)87*61046927SAndroid Build Coastguard Worker vl_vlc_next_input(struct vl_vlc *vlc)
88*61046927SAndroid Build Coastguard Worker {
89*61046927SAndroid Build Coastguard Worker unsigned len = vlc->sizes[0];
90*61046927SAndroid Build Coastguard Worker
91*61046927SAndroid Build Coastguard Worker assert(vlc);
92*61046927SAndroid Build Coastguard Worker assert(vlc->bytes_left);
93*61046927SAndroid Build Coastguard Worker
94*61046927SAndroid Build Coastguard Worker if (len < vlc->bytes_left)
95*61046927SAndroid Build Coastguard Worker vlc->bytes_left -= len;
96*61046927SAndroid Build Coastguard Worker else {
97*61046927SAndroid Build Coastguard Worker len = vlc->bytes_left;
98*61046927SAndroid Build Coastguard Worker vlc->bytes_left = 0;
99*61046927SAndroid Build Coastguard Worker }
100*61046927SAndroid Build Coastguard Worker
101*61046927SAndroid Build Coastguard Worker vlc->data = (const uint8_t *) vlc->inputs[0];
102*61046927SAndroid Build Coastguard Worker vlc->end = vlc->data + len;
103*61046927SAndroid Build Coastguard Worker
104*61046927SAndroid Build Coastguard Worker ++vlc->inputs;
105*61046927SAndroid Build Coastguard Worker ++vlc->sizes;
106*61046927SAndroid Build Coastguard Worker }
107*61046927SAndroid Build Coastguard Worker
108*61046927SAndroid Build Coastguard Worker /**
109*61046927SAndroid Build Coastguard Worker * align the data pointer to the next dword
110*61046927SAndroid Build Coastguard Worker */
111*61046927SAndroid Build Coastguard Worker static inline void
vl_vlc_align_data_ptr(struct vl_vlc * vlc)112*61046927SAndroid Build Coastguard Worker vl_vlc_align_data_ptr(struct vl_vlc *vlc)
113*61046927SAndroid Build Coastguard Worker {
114*61046927SAndroid Build Coastguard Worker /* align the data pointer */
115*61046927SAndroid Build Coastguard Worker while (vlc->data != vlc->end && ((uintptr_t)vlc->data) & 3) {
116*61046927SAndroid Build Coastguard Worker vlc->buffer |= (uint64_t)*vlc->data << (24 + vlc->invalid_bits);
117*61046927SAndroid Build Coastguard Worker ++vlc->data;
118*61046927SAndroid Build Coastguard Worker vlc->invalid_bits -= 8;
119*61046927SAndroid Build Coastguard Worker }
120*61046927SAndroid Build Coastguard Worker }
121*61046927SAndroid Build Coastguard Worker
122*61046927SAndroid Build Coastguard Worker /**
123*61046927SAndroid Build Coastguard Worker * fill the bit buffer, so that at least 32 bits are valid
124*61046927SAndroid Build Coastguard Worker */
125*61046927SAndroid Build Coastguard Worker static inline void
vl_vlc_fillbits(struct vl_vlc * vlc)126*61046927SAndroid Build Coastguard Worker vl_vlc_fillbits(struct vl_vlc *vlc)
127*61046927SAndroid Build Coastguard Worker {
128*61046927SAndroid Build Coastguard Worker assert(vlc);
129*61046927SAndroid Build Coastguard Worker
130*61046927SAndroid Build Coastguard Worker /* as long as the buffer needs to be filled */
131*61046927SAndroid Build Coastguard Worker while (vlc->invalid_bits > 0) {
132*61046927SAndroid Build Coastguard Worker unsigned bytes_left = vlc->end - vlc->data;
133*61046927SAndroid Build Coastguard Worker
134*61046927SAndroid Build Coastguard Worker /* if this input is depleted */
135*61046927SAndroid Build Coastguard Worker if (bytes_left == 0) {
136*61046927SAndroid Build Coastguard Worker
137*61046927SAndroid Build Coastguard Worker if (vlc->bytes_left) {
138*61046927SAndroid Build Coastguard Worker /* go on to next input */
139*61046927SAndroid Build Coastguard Worker vl_vlc_next_input(vlc);
140*61046927SAndroid Build Coastguard Worker vl_vlc_align_data_ptr(vlc);
141*61046927SAndroid Build Coastguard Worker } else
142*61046927SAndroid Build Coastguard Worker /* or give up since we don't have anymore inputs */
143*61046927SAndroid Build Coastguard Worker return;
144*61046927SAndroid Build Coastguard Worker
145*61046927SAndroid Build Coastguard Worker } else if (bytes_left >= 4) {
146*61046927SAndroid Build Coastguard Worker
147*61046927SAndroid Build Coastguard Worker /* enough bytes in buffer, read in a whole dword */
148*61046927SAndroid Build Coastguard Worker uint64_t value = *(const uint32_t*)vlc->data;
149*61046927SAndroid Build Coastguard Worker
150*61046927SAndroid Build Coastguard Worker #if !UTIL_ARCH_BIG_ENDIAN
151*61046927SAndroid Build Coastguard Worker value = util_bswap32(value);
152*61046927SAndroid Build Coastguard Worker #endif
153*61046927SAndroid Build Coastguard Worker
154*61046927SAndroid Build Coastguard Worker vlc->buffer |= value << vlc->invalid_bits;
155*61046927SAndroid Build Coastguard Worker vlc->data += 4;
156*61046927SAndroid Build Coastguard Worker vlc->invalid_bits -= 32;
157*61046927SAndroid Build Coastguard Worker
158*61046927SAndroid Build Coastguard Worker /* buffer is now definitely filled up avoid the loop test */
159*61046927SAndroid Build Coastguard Worker break;
160*61046927SAndroid Build Coastguard Worker
161*61046927SAndroid Build Coastguard Worker } else while (vlc->data < vlc->end) {
162*61046927SAndroid Build Coastguard Worker
163*61046927SAndroid Build Coastguard Worker /* not enough bytes left in buffer, read single bytes */
164*61046927SAndroid Build Coastguard Worker vlc->buffer |= (uint64_t)*vlc->data << (24 + vlc->invalid_bits);
165*61046927SAndroid Build Coastguard Worker ++vlc->data;
166*61046927SAndroid Build Coastguard Worker vlc->invalid_bits -= 8;
167*61046927SAndroid Build Coastguard Worker }
168*61046927SAndroid Build Coastguard Worker }
169*61046927SAndroid Build Coastguard Worker }
170*61046927SAndroid Build Coastguard Worker
171*61046927SAndroid Build Coastguard Worker /**
172*61046927SAndroid Build Coastguard Worker * initialize vlc structure and start reading from first input buffer
173*61046927SAndroid Build Coastguard Worker */
174*61046927SAndroid Build Coastguard Worker static inline void
vl_vlc_init(struct vl_vlc * vlc,unsigned num_inputs,const void * const * inputs,const unsigned * sizes)175*61046927SAndroid Build Coastguard Worker vl_vlc_init(struct vl_vlc *vlc, unsigned num_inputs,
176*61046927SAndroid Build Coastguard Worker const void *const *inputs, const unsigned *sizes)
177*61046927SAndroid Build Coastguard Worker {
178*61046927SAndroid Build Coastguard Worker unsigned i;
179*61046927SAndroid Build Coastguard Worker
180*61046927SAndroid Build Coastguard Worker assert(vlc);
181*61046927SAndroid Build Coastguard Worker assert(num_inputs);
182*61046927SAndroid Build Coastguard Worker
183*61046927SAndroid Build Coastguard Worker vlc->buffer = 0;
184*61046927SAndroid Build Coastguard Worker vlc->invalid_bits = 32;
185*61046927SAndroid Build Coastguard Worker vlc->inputs = inputs;
186*61046927SAndroid Build Coastguard Worker vlc->sizes = sizes;
187*61046927SAndroid Build Coastguard Worker vlc->bytes_left = 0;
188*61046927SAndroid Build Coastguard Worker vlc->data = NULL;
189*61046927SAndroid Build Coastguard Worker vlc->end = NULL;
190*61046927SAndroid Build Coastguard Worker
191*61046927SAndroid Build Coastguard Worker for (i = 0; i < num_inputs; ++i)
192*61046927SAndroid Build Coastguard Worker vlc->bytes_left += sizes[i];
193*61046927SAndroid Build Coastguard Worker
194*61046927SAndroid Build Coastguard Worker if (vlc->bytes_left) {
195*61046927SAndroid Build Coastguard Worker vl_vlc_next_input(vlc);
196*61046927SAndroid Build Coastguard Worker vl_vlc_align_data_ptr(vlc);
197*61046927SAndroid Build Coastguard Worker vl_vlc_fillbits(vlc);
198*61046927SAndroid Build Coastguard Worker }
199*61046927SAndroid Build Coastguard Worker }
200*61046927SAndroid Build Coastguard Worker
201*61046927SAndroid Build Coastguard Worker /**
202*61046927SAndroid Build Coastguard Worker * number of bits still valid in bit buffer
203*61046927SAndroid Build Coastguard Worker */
204*61046927SAndroid Build Coastguard Worker static inline unsigned
vl_vlc_valid_bits(struct vl_vlc * vlc)205*61046927SAndroid Build Coastguard Worker vl_vlc_valid_bits(struct vl_vlc *vlc)
206*61046927SAndroid Build Coastguard Worker {
207*61046927SAndroid Build Coastguard Worker return 32 - vlc->invalid_bits;
208*61046927SAndroid Build Coastguard Worker }
209*61046927SAndroid Build Coastguard Worker
210*61046927SAndroid Build Coastguard Worker /**
211*61046927SAndroid Build Coastguard Worker * number of bits left over all inbut buffers
212*61046927SAndroid Build Coastguard Worker */
213*61046927SAndroid Build Coastguard Worker static inline unsigned
vl_vlc_bits_left(struct vl_vlc * vlc)214*61046927SAndroid Build Coastguard Worker vl_vlc_bits_left(struct vl_vlc *vlc)
215*61046927SAndroid Build Coastguard Worker {
216*61046927SAndroid Build Coastguard Worker signed bytes_left = vlc->end - vlc->data;
217*61046927SAndroid Build Coastguard Worker bytes_left += vlc->bytes_left;
218*61046927SAndroid Build Coastguard Worker return bytes_left * 8 + vl_vlc_valid_bits(vlc);
219*61046927SAndroid Build Coastguard Worker }
220*61046927SAndroid Build Coastguard Worker
221*61046927SAndroid Build Coastguard Worker /**
222*61046927SAndroid Build Coastguard Worker * get num_bits from bit buffer without removing them
223*61046927SAndroid Build Coastguard Worker */
224*61046927SAndroid Build Coastguard Worker static inline unsigned
vl_vlc_peekbits(struct vl_vlc * vlc,unsigned num_bits)225*61046927SAndroid Build Coastguard Worker vl_vlc_peekbits(struct vl_vlc *vlc, unsigned num_bits)
226*61046927SAndroid Build Coastguard Worker {
227*61046927SAndroid Build Coastguard Worker assert(vl_vlc_valid_bits(vlc) >= num_bits || vlc->data >= vlc->end);
228*61046927SAndroid Build Coastguard Worker return vlc->buffer >> (64 - num_bits);
229*61046927SAndroid Build Coastguard Worker }
230*61046927SAndroid Build Coastguard Worker
231*61046927SAndroid Build Coastguard Worker /**
232*61046927SAndroid Build Coastguard Worker * remove num_bits from bit buffer
233*61046927SAndroid Build Coastguard Worker */
234*61046927SAndroid Build Coastguard Worker static inline void
vl_vlc_eatbits(struct vl_vlc * vlc,unsigned num_bits)235*61046927SAndroid Build Coastguard Worker vl_vlc_eatbits(struct vl_vlc *vlc, unsigned num_bits)
236*61046927SAndroid Build Coastguard Worker {
237*61046927SAndroid Build Coastguard Worker assert(vl_vlc_valid_bits(vlc) >= num_bits);
238*61046927SAndroid Build Coastguard Worker
239*61046927SAndroid Build Coastguard Worker vlc->buffer <<= num_bits;
240*61046927SAndroid Build Coastguard Worker vlc->invalid_bits += num_bits;
241*61046927SAndroid Build Coastguard Worker }
242*61046927SAndroid Build Coastguard Worker
243*61046927SAndroid Build Coastguard Worker /**
244*61046927SAndroid Build Coastguard Worker * get num_bits from bit buffer with removing them
245*61046927SAndroid Build Coastguard Worker */
246*61046927SAndroid Build Coastguard Worker static inline unsigned
vl_vlc_get_uimsbf(struct vl_vlc * vlc,unsigned num_bits)247*61046927SAndroid Build Coastguard Worker vl_vlc_get_uimsbf(struct vl_vlc *vlc, unsigned num_bits)
248*61046927SAndroid Build Coastguard Worker {
249*61046927SAndroid Build Coastguard Worker unsigned value;
250*61046927SAndroid Build Coastguard Worker
251*61046927SAndroid Build Coastguard Worker assert(vl_vlc_valid_bits(vlc) >= num_bits);
252*61046927SAndroid Build Coastguard Worker
253*61046927SAndroid Build Coastguard Worker value = vlc->buffer >> (64 - num_bits);
254*61046927SAndroid Build Coastguard Worker vl_vlc_eatbits(vlc, num_bits);
255*61046927SAndroid Build Coastguard Worker
256*61046927SAndroid Build Coastguard Worker return value;
257*61046927SAndroid Build Coastguard Worker }
258*61046927SAndroid Build Coastguard Worker
259*61046927SAndroid Build Coastguard Worker /**
260*61046927SAndroid Build Coastguard Worker * treat num_bits as signed value and remove them from bit buffer
261*61046927SAndroid Build Coastguard Worker */
262*61046927SAndroid Build Coastguard Worker static inline signed
vl_vlc_get_simsbf(struct vl_vlc * vlc,unsigned num_bits)263*61046927SAndroid Build Coastguard Worker vl_vlc_get_simsbf(struct vl_vlc *vlc, unsigned num_bits)
264*61046927SAndroid Build Coastguard Worker {
265*61046927SAndroid Build Coastguard Worker signed value;
266*61046927SAndroid Build Coastguard Worker
267*61046927SAndroid Build Coastguard Worker assert(vl_vlc_valid_bits(vlc) >= num_bits);
268*61046927SAndroid Build Coastguard Worker
269*61046927SAndroid Build Coastguard Worker value = ((int64_t)vlc->buffer) >> (64 - num_bits);
270*61046927SAndroid Build Coastguard Worker vl_vlc_eatbits(vlc, num_bits);
271*61046927SAndroid Build Coastguard Worker
272*61046927SAndroid Build Coastguard Worker return value;
273*61046927SAndroid Build Coastguard Worker }
274*61046927SAndroid Build Coastguard Worker
275*61046927SAndroid Build Coastguard Worker /**
276*61046927SAndroid Build Coastguard Worker * lookup a value and length in a decompressed table
277*61046927SAndroid Build Coastguard Worker */
278*61046927SAndroid Build Coastguard Worker static inline int8_t
vl_vlc_get_vlclbf(struct vl_vlc * vlc,const struct vl_vlc_entry * tbl,unsigned num_bits)279*61046927SAndroid Build Coastguard Worker vl_vlc_get_vlclbf(struct vl_vlc *vlc, const struct vl_vlc_entry *tbl, unsigned num_bits)
280*61046927SAndroid Build Coastguard Worker {
281*61046927SAndroid Build Coastguard Worker tbl += vl_vlc_peekbits(vlc, num_bits);
282*61046927SAndroid Build Coastguard Worker vl_vlc_eatbits(vlc, tbl->length);
283*61046927SAndroid Build Coastguard Worker return tbl->value;
284*61046927SAndroid Build Coastguard Worker }
285*61046927SAndroid Build Coastguard Worker
286*61046927SAndroid Build Coastguard Worker /**
287*61046927SAndroid Build Coastguard Worker * fast forward search for a specific byte value
288*61046927SAndroid Build Coastguard Worker */
289*61046927SAndroid Build Coastguard Worker static inline bool
vl_vlc_search_byte(struct vl_vlc * vlc,unsigned num_bits,uint8_t value)290*61046927SAndroid Build Coastguard Worker vl_vlc_search_byte(struct vl_vlc *vlc, unsigned num_bits, uint8_t value)
291*61046927SAndroid Build Coastguard Worker {
292*61046927SAndroid Build Coastguard Worker /* make sure we are on a byte boundary */
293*61046927SAndroid Build Coastguard Worker assert((vl_vlc_valid_bits(vlc) % 8) == 0);
294*61046927SAndroid Build Coastguard Worker assert(num_bits == ~0u || (num_bits % 8) == 0);
295*61046927SAndroid Build Coastguard Worker
296*61046927SAndroid Build Coastguard Worker /* deplete the bit buffer */
297*61046927SAndroid Build Coastguard Worker while (vl_vlc_valid_bits(vlc) > 0) {
298*61046927SAndroid Build Coastguard Worker
299*61046927SAndroid Build Coastguard Worker if (vl_vlc_peekbits(vlc, 8) == value) {
300*61046927SAndroid Build Coastguard Worker vl_vlc_fillbits(vlc);
301*61046927SAndroid Build Coastguard Worker return true;
302*61046927SAndroid Build Coastguard Worker }
303*61046927SAndroid Build Coastguard Worker
304*61046927SAndroid Build Coastguard Worker vl_vlc_eatbits(vlc, 8);
305*61046927SAndroid Build Coastguard Worker
306*61046927SAndroid Build Coastguard Worker if (num_bits != ~0u) {
307*61046927SAndroid Build Coastguard Worker num_bits -= 8;
308*61046927SAndroid Build Coastguard Worker if (num_bits == 0)
309*61046927SAndroid Build Coastguard Worker return false;
310*61046927SAndroid Build Coastguard Worker }
311*61046927SAndroid Build Coastguard Worker }
312*61046927SAndroid Build Coastguard Worker
313*61046927SAndroid Build Coastguard Worker /* deplete the byte buffers */
314*61046927SAndroid Build Coastguard Worker while (1) {
315*61046927SAndroid Build Coastguard Worker
316*61046927SAndroid Build Coastguard Worker /* if this input is depleted */
317*61046927SAndroid Build Coastguard Worker if (vlc->data == vlc->end) {
318*61046927SAndroid Build Coastguard Worker if (vlc->bytes_left)
319*61046927SAndroid Build Coastguard Worker /* go on to next input */
320*61046927SAndroid Build Coastguard Worker vl_vlc_next_input(vlc);
321*61046927SAndroid Build Coastguard Worker else
322*61046927SAndroid Build Coastguard Worker /* or give up since we don't have anymore inputs */
323*61046927SAndroid Build Coastguard Worker return false;
324*61046927SAndroid Build Coastguard Worker }
325*61046927SAndroid Build Coastguard Worker
326*61046927SAndroid Build Coastguard Worker if (*vlc->data == value) {
327*61046927SAndroid Build Coastguard Worker vl_vlc_align_data_ptr(vlc);
328*61046927SAndroid Build Coastguard Worker vl_vlc_fillbits(vlc);
329*61046927SAndroid Build Coastguard Worker return true;
330*61046927SAndroid Build Coastguard Worker }
331*61046927SAndroid Build Coastguard Worker
332*61046927SAndroid Build Coastguard Worker ++vlc->data;
333*61046927SAndroid Build Coastguard Worker if (num_bits != ~0u) {
334*61046927SAndroid Build Coastguard Worker num_bits -= 8;
335*61046927SAndroid Build Coastguard Worker if (num_bits == 0) {
336*61046927SAndroid Build Coastguard Worker vl_vlc_align_data_ptr(vlc);
337*61046927SAndroid Build Coastguard Worker return false;
338*61046927SAndroid Build Coastguard Worker }
339*61046927SAndroid Build Coastguard Worker }
340*61046927SAndroid Build Coastguard Worker }
341*61046927SAndroid Build Coastguard Worker }
342*61046927SAndroid Build Coastguard Worker
343*61046927SAndroid Build Coastguard Worker /**
344*61046927SAndroid Build Coastguard Worker * remove num_bits bits starting at pos from the bitbuffer
345*61046927SAndroid Build Coastguard Worker */
346*61046927SAndroid Build Coastguard Worker static inline void
vl_vlc_removebits(struct vl_vlc * vlc,unsigned pos,unsigned num_bits)347*61046927SAndroid Build Coastguard Worker vl_vlc_removebits(struct vl_vlc *vlc, unsigned pos, unsigned num_bits)
348*61046927SAndroid Build Coastguard Worker {
349*61046927SAndroid Build Coastguard Worker #if defined(_MSC_VER)
350*61046927SAndroid Build Coastguard Worker /* MSVC Compiler defines unsigned long as 4 bytes so use explicit 64 bits mask */
351*61046927SAndroid Build Coastguard Worker uint64_t lo = (vlc->buffer & (UINT64_MAX >> (pos + num_bits))) << num_bits;
352*61046927SAndroid Build Coastguard Worker uint64_t hi = (vlc->buffer & (UINT64_MAX << (64 - pos)));
353*61046927SAndroid Build Coastguard Worker #else
354*61046927SAndroid Build Coastguard Worker uint64_t lo = (vlc->buffer & (~0UL >> (pos + num_bits))) << num_bits;
355*61046927SAndroid Build Coastguard Worker uint64_t hi = (vlc->buffer & (~0UL << (64 - pos)));
356*61046927SAndroid Build Coastguard Worker #endif
357*61046927SAndroid Build Coastguard Worker vlc->buffer = lo | hi;
358*61046927SAndroid Build Coastguard Worker vlc->invalid_bits += num_bits;
359*61046927SAndroid Build Coastguard Worker }
360*61046927SAndroid Build Coastguard Worker
361*61046927SAndroid Build Coastguard Worker /**
362*61046927SAndroid Build Coastguard Worker * limit the number of bits left for fetching
363*61046927SAndroid Build Coastguard Worker */
364*61046927SAndroid Build Coastguard Worker static inline void
vl_vlc_limit(struct vl_vlc * vlc,unsigned bits_left)365*61046927SAndroid Build Coastguard Worker vl_vlc_limit(struct vl_vlc *vlc, unsigned bits_left)
366*61046927SAndroid Build Coastguard Worker {
367*61046927SAndroid Build Coastguard Worker assert(bits_left <= vl_vlc_bits_left(vlc));
368*61046927SAndroid Build Coastguard Worker
369*61046927SAndroid Build Coastguard Worker vl_vlc_fillbits(vlc);
370*61046927SAndroid Build Coastguard Worker if (bits_left < vl_vlc_valid_bits(vlc)) {
371*61046927SAndroid Build Coastguard Worker vlc->invalid_bits = 32 - bits_left;
372*61046927SAndroid Build Coastguard Worker vlc->buffer &= ~0L << (vlc->invalid_bits + 32);
373*61046927SAndroid Build Coastguard Worker vlc->end = vlc->data;
374*61046927SAndroid Build Coastguard Worker vlc->bytes_left = 0;
375*61046927SAndroid Build Coastguard Worker } else {
376*61046927SAndroid Build Coastguard Worker assert((bits_left - vl_vlc_valid_bits(vlc)) % 8 == 0);
377*61046927SAndroid Build Coastguard Worker vlc->bytes_left = (bits_left - vl_vlc_valid_bits(vlc)) / 8;
378*61046927SAndroid Build Coastguard Worker if (vlc->bytes_left < (vlc->end - vlc->data)) {
379*61046927SAndroid Build Coastguard Worker vlc->end = vlc->data + vlc->bytes_left;
380*61046927SAndroid Build Coastguard Worker vlc->bytes_left = 0;
381*61046927SAndroid Build Coastguard Worker } else
382*61046927SAndroid Build Coastguard Worker vlc->bytes_left -= vlc->end - vlc->data;
383*61046927SAndroid Build Coastguard Worker }
384*61046927SAndroid Build Coastguard Worker }
385*61046927SAndroid Build Coastguard Worker
386*61046927SAndroid Build Coastguard Worker #endif /* vl_vlc_h */
387