]> git.sesse.net Git - vlc/blob - include/vlc_bits.h
ee3cfedb03935df1fcc96444db5ec3bd037ba664
[vlc] / include / vlc_bits.h
1 /*****************************************************************************
2  * vlc_bits.h : Bit handling helpers
3  *****************************************************************************
4  * Copyright (C) 2001, 2002, 2003, 2006, 2015 VLC authors and VideoLAN
5  * $Id$
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *          Gildas Bazin <gbazin at videolan dot org>
9  *          Rafaël Carré <funman at videolan dot org>
10  *
11  * This program is free software; you can redistribute it and/or modify it
12  * under the terms of the GNU Lesser General Public License as published by
13  * the Free Software Foundation; either version 2.1 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24  *****************************************************************************/
25
26 #ifndef VLC_BITS_H
27 #define VLC_BITS_H 1
28
29 #include <vlc_block.h>
30
31 /**
32  * \file
33  * This file defines functions, structures for handling streams of bits in vlc
34  */
35
36 typedef struct bo_t
37 {
38     block_t     *b;
39     size_t      basesize;
40 } bo_t;
41
42 typedef struct bs_s
43 {
44     uint8_t *p_start;
45     uint8_t *p;
46     uint8_t *p_end;
47
48     ssize_t  i_left;    /* i_count number of available bits */
49 } bs_t;
50
51 static inline void bs_init( bs_t *s, const void *p_data, size_t i_data )
52 {
53     s->p_start = (void *)p_data;
54     s->p       = s->p_start;
55     s->p_end   = s->p_start + i_data;
56     s->i_left  = 8;
57 }
58
59 static inline int bs_pos( const bs_t *s )
60 {
61     return( 8 * ( s->p - s->p_start ) + 8 - s->i_left );
62 }
63
64 static inline int bs_eof( const bs_t *s )
65 {
66     return( s->p >= s->p_end ? 1: 0 );
67 }
68
69 static inline uint32_t bs_read( bs_t *s, int i_count )
70 {
71      static const uint32_t i_mask[33] =
72      {  0x00,
73         0x01,      0x03,      0x07,      0x0f,
74         0x1f,      0x3f,      0x7f,      0xff,
75         0x1ff,     0x3ff,     0x7ff,     0xfff,
76         0x1fff,    0x3fff,    0x7fff,    0xffff,
77         0x1ffff,   0x3ffff,   0x7ffff,   0xfffff,
78         0x1fffff,  0x3fffff,  0x7fffff,  0xffffff,
79         0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff,
80         0x1fffffff,0x3fffffff,0x7fffffff,0xffffffff};
81     int      i_shr;
82     uint32_t i_result = 0;
83
84     while( i_count > 0 )
85     {
86         if( s->p >= s->p_end )
87         {
88             break;
89         }
90
91         if( ( i_shr = s->i_left - i_count ) >= 0 )
92         {
93             /* more in the buffer than requested */
94             i_result |= ( *s->p >> i_shr )&i_mask[i_count];
95             s->i_left -= i_count;
96             if( s->i_left == 0 )
97             {
98                 s->p++;
99                 s->i_left = 8;
100             }
101             return( i_result );
102         }
103         else
104         {
105             /* less in the buffer than requested */
106            i_result |= (*s->p&i_mask[s->i_left]) << -i_shr;
107            i_count  -= s->i_left;
108            s->p++;
109            s->i_left = 8;
110         }
111     }
112
113     return( i_result );
114 }
115
116 static inline uint32_t bs_read1( bs_t *s )
117 {
118     if( s->p < s->p_end )
119     {
120         unsigned int i_result;
121
122         s->i_left--;
123         i_result = ( *s->p >> s->i_left )&0x01;
124         if( s->i_left == 0 )
125         {
126             s->p++;
127             s->i_left = 8;
128         }
129         return i_result;
130     }
131
132     return 0;
133 }
134
135 static inline uint32_t bs_show( bs_t *s, int i_count )
136 {
137     bs_t     s_tmp = *s;
138     return bs_read( &s_tmp, i_count );
139 }
140
141 static inline void bs_skip( bs_t *s, ssize_t i_count )
142 {
143     s->i_left -= i_count;
144
145     if( s->i_left <= 0 )
146     {
147         const int i_bytes = ( -s->i_left + 8 ) / 8;
148
149         s->p += i_bytes;
150         s->i_left += 8 * i_bytes;
151     }
152 }
153
154 static inline void bs_write( bs_t *s, int i_count, uint32_t i_bits )
155 {
156     while( i_count > 0 )
157     {
158         if( s->p >= s->p_end )
159         {
160             break;
161         }
162
163         i_count--;
164
165         if( ( i_bits >> i_count )&0x01 )
166         {
167             *s->p |= 1 << ( s->i_left - 1 );
168         }
169         else
170         {
171             *s->p &= ~( 1 << ( s->i_left - 1 ) );
172         }
173         s->i_left--;
174         if( s->i_left == 0 )
175         {
176             s->p++;
177             s->i_left = 8;
178         }
179     }
180 }
181
182 static inline void bs_align( bs_t *s )
183 {
184     if( s->i_left != 8 )
185     {
186         s->i_left = 8;
187         s->p++;
188     }
189 }
190
191 static inline void bs_align_0( bs_t *s )
192 {
193     if( s->i_left != 8 )
194     {
195         bs_write( s, s->i_left, 0 );
196     }
197 }
198
199 static inline void bs_align_1( bs_t *s )
200 {
201     while( s->i_left != 8 )
202     {
203         bs_write( s, 1, 1 );
204     }
205 }
206
207 static inline int bo_init(bo_t *p_bo, int i_size)
208 {
209     p_bo->b = block_Alloc(i_size);
210     if (!p_bo->b)
211         return VLC_ENOMEM;
212
213     p_bo->b->i_buffer = 0;
214     p_bo->basesize = i_size;
215
216     return VLC_SUCCESS;
217 }
218
219 static inline void bo_set_8(bo_t *p_bo, size_t i_offset, uint8_t i)
220 {
221     size_t i_size = p_bo->b->i_size - (p_bo->b->p_buffer - p_bo->b->p_start);
222     if (i_offset >= i_size)
223     {
224         int i_growth = p_bo->basesize;
225         while(i_offset >= i_size + i_growth)
226             i_growth += p_bo->basesize;
227
228         int i = p_bo->b->i_buffer; /* Realloc would set payload size == buffer size */
229         p_bo->b = block_Realloc(p_bo->b, 0, i_size + i_growth);
230         if (!p_bo->b)
231             return;
232         p_bo->b->i_buffer = i;
233     }
234     p_bo->b->p_buffer[i_offset] = i;
235 }
236
237 static inline void bo_add_8(bo_t *p_bo, uint8_t i)
238 {
239     bo_set_8( p_bo, p_bo->b->i_buffer, i );
240     p_bo->b->i_buffer++;
241 }
242
243 static inline void bo_add_16be(bo_t *p_bo, uint16_t i)
244 {
245     bo_add_8(p_bo, ((i >> 8) &0xff));
246     bo_add_8(p_bo, i &0xff);
247 }
248
249 static inline void bo_add_16le(bo_t *p_bo, uint16_t i)
250 {
251     bo_add_8(p_bo, i &0xff);
252     bo_add_8(p_bo, ((i >> 8) &0xff));
253 }
254
255 static inline void bo_set_16be(bo_t *p_bo, int i_offset, uint16_t i)
256 {
257     bo_set_8(p_bo, i_offset, ((i >> 8) &0xff));
258     bo_set_8(p_bo, i_offset + 1, i &0xff);
259 }
260
261 static inline void bo_set_16le(bo_t *p_bo, int i_offset, uint16_t i)
262 {
263     bo_set_8(p_bo, i_offset, i &0xff);
264     bo_set_8(p_bo, i_offset + 1, ((i >> 8) &0xff));
265 }
266
267 static inline void bo_add_24be(bo_t *p_bo, uint32_t i)
268 {
269     bo_add_8(p_bo, ((i >> 16) &0xff));
270     bo_add_8(p_bo, ((i >> 8) &0xff));
271     bo_add_8(p_bo, (i &0xff));
272 }
273
274 static inline void bo_add_32be(bo_t *p_bo, uint32_t i)
275 {
276     bo_add_16be(p_bo, ((i >> 16) &0xffff));
277     bo_add_16be(p_bo, i &0xffff);
278 }
279
280 static inline void bo_add_32le(bo_t *p_bo, uint32_t i)
281 {
282     bo_add_16le(p_bo, i &0xffff);
283     bo_add_16le(p_bo, ((i >> 16) &0xffff));
284 }
285
286 static inline void bo_set_32be(bo_t *p_bo, int i_offset, uint32_t i)
287 {
288     bo_set_16be(p_bo, i_offset, ((i >> 16) &0xffff));
289     bo_set_16be(p_bo, i_offset + 2, i &0xffff);
290 }
291
292 static inline void bo_set_32le(bo_t *p_bo, int i_offset, uint32_t i)
293 {
294     bo_set_16le(p_bo, i_offset, i &0xffff);
295     bo_set_16le(p_bo, i_offset + 2, ((i >> 16) &0xffff));
296 }
297
298 static inline void bo_swap_32be (bo_t *p_bo, int i_pos, uint32_t i)
299 {
300     p_bo->b->p_buffer[i_pos    ] = (i >> 24)&0xff;
301     p_bo->b->p_buffer[i_pos + 1] = (i >> 16)&0xff;
302     p_bo->b->p_buffer[i_pos + 2] = (i >>  8)&0xff;
303     p_bo->b->p_buffer[i_pos + 3] = (i      )&0xff;
304 }
305
306 static inline void bo_set_64be(bo_t *p_bo, int i_offset, uint64_t i)
307 {
308     bo_set_32be(p_bo, i_offset, ((i >> 32) &0xffffffff));
309     bo_set_32be(p_bo, i_offset + 4, i &0xffffffff);
310 }
311
312 static inline void bo_add_64be(bo_t *p_bo, uint64_t i)
313 {
314     bo_add_32be(p_bo, ((i >> 32) &0xffffffff));
315     bo_add_32be(p_bo, i &0xffffffff);
316 }
317
318 static inline void bo_add_64le(bo_t *p_bo, uint64_t i)
319 {
320     bo_add_32le(p_bo, i &0xffffffff);
321     bo_add_32le(p_bo, ((i >> 32) &0xffffffff));
322 }
323
324 static inline void bo_add_fourcc(bo_t *p_bo, const char *fcc)
325 {
326     bo_add_8(p_bo, fcc[0]);
327     bo_add_8(p_bo, fcc[1]);
328     bo_add_8(p_bo, fcc[2]);
329     bo_add_8(p_bo, fcc[3]);
330 }
331
332 static inline void bo_add_mem(bo_t *p_bo, int i_size, const uint8_t *p_mem)
333 {
334     for (int i = 0; i < i_size; i++)
335         bo_add_8(p_bo, p_mem[i]);
336 }
337
338 #endif