]> git.sesse.net Git - vlc/blob - include/vlc_bits.h
1eba5e9ae655106fb7df9e759849f2c53f953d84
[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      len;
40     size_t      basesize;
41 } bo_t;
42
43 typedef struct bs_s
44 {
45     uint8_t *p_start;
46     uint8_t *p;
47     uint8_t *p_end;
48
49     ssize_t  i_left;    /* i_count number of available bits */
50 } bs_t;
51
52 static inline void bs_init( bs_t *s, const void *p_data, size_t i_data )
53 {
54     s->p_start = (void *)p_data;
55     s->p       = s->p_start;
56     s->p_end   = s->p_start + i_data;
57     s->i_left  = 8;
58 }
59
60 static inline int bs_pos( const bs_t *s )
61 {
62     return( 8 * ( s->p - s->p_start ) + 8 - s->i_left );
63 }
64
65 static inline int bs_eof( const bs_t *s )
66 {
67     return( s->p >= s->p_end ? 1: 0 );
68 }
69
70 static inline uint32_t bs_read( bs_t *s, int i_count )
71 {
72      static const uint32_t i_mask[33] =
73      {  0x00,
74         0x01,      0x03,      0x07,      0x0f,
75         0x1f,      0x3f,      0x7f,      0xff,
76         0x1ff,     0x3ff,     0x7ff,     0xfff,
77         0x1fff,    0x3fff,    0x7fff,    0xffff,
78         0x1ffff,   0x3ffff,   0x7ffff,   0xfffff,
79         0x1fffff,  0x3fffff,  0x7fffff,  0xffffff,
80         0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff,
81         0x1fffffff,0x3fffffff,0x7fffffff,0xffffffff};
82     int      i_shr;
83     uint32_t i_result = 0;
84
85     while( i_count > 0 )
86     {
87         if( s->p >= s->p_end )
88         {
89             break;
90         }
91
92         if( ( i_shr = s->i_left - i_count ) >= 0 )
93         {
94             /* more in the buffer than requested */
95             i_result |= ( *s->p >> i_shr )&i_mask[i_count];
96             s->i_left -= i_count;
97             if( s->i_left == 0 )
98             {
99                 s->p++;
100                 s->i_left = 8;
101             }
102             return( i_result );
103         }
104         else
105         {
106             /* less in the buffer than requested */
107            i_result |= (*s->p&i_mask[s->i_left]) << -i_shr;
108            i_count  -= s->i_left;
109            s->p++;
110            s->i_left = 8;
111         }
112     }
113
114     return( i_result );
115 }
116
117 static inline uint32_t bs_read1( bs_t *s )
118 {
119     if( s->p < s->p_end )
120     {
121         unsigned int i_result;
122
123         s->i_left--;
124         i_result = ( *s->p >> s->i_left )&0x01;
125         if( s->i_left == 0 )
126         {
127             s->p++;
128             s->i_left = 8;
129         }
130         return i_result;
131     }
132
133     return 0;
134 }
135
136 static inline uint32_t bs_show( bs_t *s, int i_count )
137 {
138     bs_t     s_tmp = *s;
139     return bs_read( &s_tmp, i_count );
140 }
141
142 static inline void bs_skip( bs_t *s, ssize_t i_count )
143 {
144     s->i_left -= i_count;
145
146     if( s->i_left <= 0 )
147     {
148         const int i_bytes = ( -s->i_left + 8 ) / 8;
149
150         s->p += i_bytes;
151         s->i_left += 8 * i_bytes;
152     }
153 }
154
155 static inline void bs_write( bs_t *s, int i_count, uint32_t i_bits )
156 {
157     while( i_count > 0 )
158     {
159         if( s->p >= s->p_end )
160         {
161             break;
162         }
163
164         i_count--;
165
166         if( ( i_bits >> i_count )&0x01 )
167         {
168             *s->p |= 1 << ( s->i_left - 1 );
169         }
170         else
171         {
172             *s->p &= ~( 1 << ( s->i_left - 1 ) );
173         }
174         s->i_left--;
175         if( s->i_left == 0 )
176         {
177             s->p++;
178             s->i_left = 8;
179         }
180     }
181 }
182
183 static inline void bs_align( bs_t *s )
184 {
185     if( s->i_left != 8 )
186     {
187         s->i_left = 8;
188         s->p++;
189     }
190 }
191
192 static inline void bs_align_0( bs_t *s )
193 {
194     if( s->i_left != 8 )
195     {
196         bs_write( s, s->i_left, 0 );
197     }
198 }
199
200 static inline void bs_align_1( bs_t *s )
201 {
202     while( s->i_left != 8 )
203     {
204         bs_write( s, 1, 1 );
205     }
206 }
207
208 static inline int bo_init(bo_t *p_bo, int i_size)
209 {
210     p_bo->b = block_Alloc(i_size);
211     if (!p_bo->b)
212         return VLC_ENOMEM;
213
214     p_bo->b->i_buffer = 0;
215     p_bo->len = p_bo->basesize = i_size;
216
217     return VLC_SUCCESS;
218 }
219
220 static inline void bo_set_8(bo_t *p_bo, size_t i_offset, uint8_t i)
221 {
222     if (i_offset >= p_bo->len)
223     {
224         int i_growth = p_bo->basesize;
225         while(i_offset >= p_bo->len + 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, p_bo->len + i_growth);
230         if (!p_bo->b)
231             return;
232         p_bo->b->i_buffer = i;
233         p_bo->len += i_growth;
234     }
235     p_bo->b->p_buffer[i_offset] = i;
236 }
237
238 static inline void bo_add_8(bo_t *p_bo, uint8_t i)
239 {
240     bo_set_8( p_bo, p_bo->b->i_buffer, i );
241     p_bo->b->i_buffer++;
242 }
243
244 static inline void bo_add_16be(bo_t *p_bo, uint16_t i)
245 {
246     bo_add_8(p_bo, ((i >> 8) &0xff));
247     bo_add_8(p_bo, i &0xff);
248 }
249
250 static inline void bo_add_16le(bo_t *p_bo, uint16_t i)
251 {
252     bo_add_8(p_bo, i &0xff);
253     bo_add_8(p_bo, ((i >> 8) &0xff));
254 }
255
256 static inline void bo_set_16be(bo_t *p_bo, int i_offset, uint16_t i)
257 {
258     bo_set_8(p_bo, i_offset, ((i >> 8) &0xff));
259     bo_set_8(p_bo, i_offset + 1, i &0xff);
260 }
261
262 static inline void bo_set_16le(bo_t *p_bo, int i_offset, uint16_t i)
263 {
264     bo_set_8(p_bo, i_offset, i &0xff);
265     bo_set_8(p_bo, i_offset + 1, ((i >> 8) &0xff));
266 }
267
268 static inline void bo_add_24be(bo_t *p_bo, uint32_t i)
269 {
270     bo_add_8(p_bo, ((i >> 16) &0xff));
271     bo_add_8(p_bo, ((i >> 8) &0xff));
272     bo_add_8(p_bo, (i &0xff));
273 }
274
275 static inline void bo_add_32be(bo_t *p_bo, uint32_t i)
276 {
277     bo_add_16be(p_bo, ((i >> 16) &0xffff));
278     bo_add_16be(p_bo, i &0xffff);
279 }
280
281 static inline void bo_add_32le(bo_t *p_bo, uint32_t i)
282 {
283     bo_add_16le(p_bo, i &0xffff);
284     bo_add_16le(p_bo, ((i >> 16) &0xffff));
285 }
286
287 static inline void bo_set_32be(bo_t *p_bo, int i_offset, uint32_t i)
288 {
289     bo_set_16be(p_bo, i_offset, ((i >> 16) &0xffff));
290     bo_set_16be(p_bo, i_offset + 2, i &0xffff);
291 }
292
293 static inline void bo_set_32le(bo_t *p_bo, int i_offset, uint32_t i)
294 {
295     bo_set_16le(p_bo, i_offset, i &0xffff);
296     bo_set_16le(p_bo, i_offset + 2, ((i >> 16) &0xffff));
297 }
298
299 static inline void bo_swap_32be (bo_t *p_bo, int i_pos, uint32_t i)
300 {
301     p_bo->b->p_buffer[i_pos    ] = (i >> 24)&0xff;
302     p_bo->b->p_buffer[i_pos + 1] = (i >> 16)&0xff;
303     p_bo->b->p_buffer[i_pos + 2] = (i >>  8)&0xff;
304     p_bo->b->p_buffer[i_pos + 3] = (i      )&0xff;
305 }
306
307 static inline void bo_set_64be(bo_t *p_bo, int i_offset, uint64_t i)
308 {
309     bo_set_32be(p_bo, i_offset, ((i >> 32) &0xffffffff));
310     bo_set_32be(p_bo, i_offset + 4, i &0xffffffff);
311 }
312
313 static inline void bo_add_64be(bo_t *p_bo, uint64_t i)
314 {
315     bo_add_32be(p_bo, ((i >> 32) &0xffffffff));
316     bo_add_32be(p_bo, i &0xffffffff);
317 }
318
319 static inline void bo_add_64le(bo_t *p_bo, uint64_t i)
320 {
321     bo_add_32le(p_bo, i &0xffffffff);
322     bo_add_32le(p_bo, ((i >> 32) &0xffffffff));
323 }
324
325 static inline void bo_add_fourcc(bo_t *p_bo, const char *fcc)
326 {
327     bo_add_8(p_bo, fcc[0]);
328     bo_add_8(p_bo, fcc[1]);
329     bo_add_8(p_bo, fcc[2]);
330     bo_add_8(p_bo, fcc[3]);
331 }
332
333 static inline void bo_add_mem(bo_t *p_bo, int i_size, const uint8_t *p_mem)
334 {
335     for (int i = 0; i < i_size; i++)
336         bo_add_8(p_bo, p_mem[i]);
337 }
338
339 static inline void bo_add_mp4_tag_descr(bo_t *p_bo, uint8_t tag, uint32_t size)
340 {
341     bo_add_8(p_bo, tag);
342     for (int i = 3; i>0; i--)
343         bo_add_8(p_bo, (size>>(7*i)) | 0x80);
344     bo_add_8(p_bo, size & 0x7F);
345 }
346
347 #endif