1 /*****************************************************************************
2 * vlc_bits.h : Bit handling helpers
3 *****************************************************************************
4 * Copyright (C) 2001, 2002, 2003, 2006, 2015 VLC authors and VideoLAN
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>
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.
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.
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 *****************************************************************************/
29 #include <vlc_common.h>
30 #include <vlc_block.h>
34 * This file defines functions, structures for handling streams of bits in vlc
49 ssize_t i_left
; /* i_count number of available bits */
52 static inline void bs_init( bs_t
*s
, const void *p_data
, size_t i_data
)
54 s
->p_start
= (void *)p_data
;
56 s
->p_end
= s
->p_start
+ i_data
;
60 static inline int bs_pos( const bs_t
*s
)
62 return( 8 * ( s
->p
- s
->p_start
) + 8 - s
->i_left
);
65 static inline int bs_eof( const bs_t
*s
)
67 return( s
->p
>= s
->p_end
? 1: 0 );
70 static inline uint32_t bs_read( bs_t
*s
, int i_count
)
72 static const uint32_t i_mask
[33] =
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};
83 uint32_t i_result
= 0;
87 if( s
->p
>= s
->p_end
)
92 if( ( i_shr
= s
->i_left
- i_count
) >= 0 )
94 /* more in the buffer than requested */
95 i_result
|= ( *s
->p
>> i_shr
)&i_mask
[i_count
];
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
;
117 static inline uint32_t bs_read1( bs_t
*s
)
119 if( s
->p
< s
->p_end
)
121 unsigned int i_result
;
124 i_result
= ( *s
->p
>> s
->i_left
)&0x01;
136 static inline uint32_t bs_show( bs_t
*s
, int i_count
)
139 return bs_read( &s_tmp
, i_count
);
142 static inline void bs_skip( bs_t
*s
, ssize_t i_count
)
144 s
->i_left
-= i_count
;
148 const int i_bytes
= ( -s
->i_left
+ 8 ) / 8;
151 s
->i_left
+= 8 * i_bytes
;
155 static inline void bs_write( bs_t
*s
, int i_count
, uint32_t i_bits
)
159 if( s
->p
>= s
->p_end
)
166 if( ( i_bits
>> i_count
)&0x01 )
168 *s
->p
|= 1 << ( s
->i_left
- 1 );
172 *s
->p
&= ~( 1 << ( s
->i_left
- 1 ) );
183 static inline void bs_align( bs_t
*s
)
192 static inline void bs_align_0( bs_t
*s
)
196 bs_write( s
, s
->i_left
, 0 );
200 static inline void bs_align_1( bs_t
*s
)
202 while( s
->i_left
!= 8 )
208 static inline bool bo_init(bo_t
*p_bo
, int i_size
)
210 p_bo
->b
= block_Alloc(i_size
);
214 p_bo
->b
->i_buffer
= 0;
215 p_bo
->basesize
= i_size
;
220 static inline void bo_deinit(bo_t
*p_bo
)
223 block_Release(p_bo
->b
);
226 static inline void bo_free(bo_t
*p_bo
)
234 static inline int bo_extend(bo_t
*p_bo
, size_t i_total
)
238 const size_t i_size
= p_bo
->b
->i_size
- (p_bo
->b
->p_buffer
- p_bo
->b
->p_start
);
239 if (i_total
>= i_size
)
241 int i_growth
= p_bo
->basesize
;
242 while(i_total
>= i_size
+ i_growth
)
243 i_growth
+= p_bo
->basesize
;
245 int i
= p_bo
->b
->i_buffer
; /* Realloc would set payload size == buffer size */
246 p_bo
->b
= block_Realloc(p_bo
->b
, 0, i_size
+ i_growth
);
249 p_bo
->b
->i_buffer
= i
;
254 #define BO_SET_DECL_S(func, handler, type) static inline bool func(bo_t *p_bo, size_t i_offset, type val)\
256 if (!bo_extend(p_bo, i_offset + sizeof(type)))\
258 handler(&p_bo->b->p_buffer[i_offset], val);\
262 #define BO_ADD_DECL_S(func, handler, type) static inline bool func(bo_t *p_bo, type val)\
264 if(!p_bo->b || !handler(p_bo, p_bo->b->i_buffer, val))\
266 p_bo->b->i_buffer += sizeof(type);\
270 #define BO_FUNC_DECL(suffix, handler, type ) \
271 BO_SET_DECL_S( bo_set_ ## suffix ## be, handler ## BE, type )\
272 BO_SET_DECL_S( bo_set_ ## suffix ## le, handler ## LE, type )\
273 BO_ADD_DECL_S( bo_add_ ## suffix ## be, bo_set_ ## suffix ## be, type )\
274 BO_ADD_DECL_S( bo_add_ ## suffix ## le, bo_set_ ## suffix ## le, type )
276 static inline bool bo_set_8(bo_t
*p_bo
, size_t i_offset
, uint8_t i
)
278 if (!bo_extend(p_bo
, i_offset
+ 1))
280 p_bo
->b
->p_buffer
[i_offset
] = i
;
284 static inline bool bo_add_8(bo_t
*p_bo
, uint8_t i
)
286 if(!p_bo
->b
|| !bo_set_8( p_bo
, p_bo
->b
->i_buffer
, i
))
292 /* declares all bo_[set,add]_[16,32,64] */
293 BO_FUNC_DECL( 16, SetW
, uint16_t )
294 BO_FUNC_DECL( 32, SetDW
, uint32_t )
295 BO_FUNC_DECL( 64, SetQW
, uint64_t )
301 static inline bool bo_add_24be(bo_t
*p_bo
, uint32_t i
)
303 if(!p_bo
->b
|| !bo_extend(p_bo
, p_bo
->b
->i_buffer
+ 3))
305 p_bo
->b
->p_buffer
[p_bo
->b
->i_buffer
++] = ((i
>> 16) & 0xff);
306 p_bo
->b
->p_buffer
[p_bo
->b
->i_buffer
++] = ((i
>> 8) & 0xff);
307 p_bo
->b
->p_buffer
[p_bo
->b
->i_buffer
++] = (i
& 0xff);
311 static inline void bo_swap_32be (bo_t
*p_bo
, size_t i_pos
, uint32_t i
)
313 if (!p_bo
->b
|| p_bo
->b
->i_buffer
< i_pos
+ 4)
315 p_bo
->b
->p_buffer
[i_pos
] = (i
>> 24)&0xff;
316 p_bo
->b
->p_buffer
[i_pos
+ 1] = (i
>> 16)&0xff;
317 p_bo
->b
->p_buffer
[i_pos
+ 2] = (i
>> 8)&0xff;
318 p_bo
->b
->p_buffer
[i_pos
+ 3] = (i
)&0xff;
321 static inline bool bo_add_mem(bo_t
*p_bo
, size_t i_size
, const void *p_mem
)
323 if(!p_bo
->b
|| !bo_extend(p_bo
, p_bo
->b
->i_buffer
+ i_size
))
325 memcpy(&p_bo
->b
->p_buffer
[p_bo
->b
->i_buffer
], p_mem
, i_size
);
326 p_bo
->b
->i_buffer
+= i_size
;
330 #define bo_add_fourcc(p_bo, fcc) bo_add_mem(p_bo, 4, fcc)