1 /*****************************************************************************
2 * vlc_bits.h : Bit handling helpers
3 *****************************************************************************
4 * Copyright (C) 2001, 2002, 2003, 2006, 2015 VLC authors and VideoLAN
6 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
7 * Gildas Bazin <gbazin at videolan dot org>
8 * Rafaël Carré <funman at videolan dot org>
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2.1 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this program; if not, write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
27 #include <vlc_common.h>
31 * This file defines functions, structures for handling streams of bits in vlc
34 typedef struct bs_s bs_t
;
38 /* forward read modifier (p_start, p_end, p_fwpriv, count, pos) */
39 size_t (*pf_byte_forward
)(bs_t
*, size_t);
40 size_t (*pf_byte_pos
)(const bs_t
*);
41 } bs_byte_callbacks_t
;
46 uint8_t *p
; /* points to currently read/written byte */
49 uint8_t i_left
; /* i_count number of available bits */
53 bs_byte_callbacks_t cb
;
57 static size_t bs_impl_bytes_forward( bs_t
*s
, size_t i_count
)
65 if( s
->p
>= s
->p_end
)
68 if( (size_t) (s
->p_end
- s
->p
) < i_count
)
69 i_count
= s
->p_end
- s
->p
;
74 static size_t bs_impl_bytes_pos( const bs_t
*s
)
77 return s
->p
< s
->p_end
? s
->p
- s
->p_start
+ 1 : s
->p
- s
->p_start
;
82 static inline void bs_init_custom( bs_t
*s
, const void *p_data
, size_t i_data
,
83 const bs_byte_callbacks_t
*cb
, void *priv
)
85 s
->p_start
= (uint8_t *)p_data
;
87 s
->p_end
= s
->p_start
+ i_data
;
89 s
->b_read_only
= true;
95 static inline void bs_init( bs_t
*s
, const void *p_data
, size_t i_data
)
97 bs_byte_callbacks_t cb
= {
98 bs_impl_bytes_forward
,
101 bs_init_custom( s
, p_data
, i_data
, &cb
, NULL
);
104 static inline void bs_write_init( bs_t
*s
, void *p_data
, size_t i_data
)
106 bs_init( s
, (const void *) p_data
, i_data
);
107 s
->b_read_only
= false;
110 static inline int bs_refill( bs_t
*s
)
114 if( s
->cb
.pf_byte_forward( s
, 1 ) != 1 )
117 if( s
->p
< s
->p_end
)
120 return s
->i_left
> 0 ? 0 : 1;
123 static inline bool bs_error( const bs_t
*s
)
128 static inline bool bs_eof( bs_t
*s
)
130 return bs_refill( s
) != 0;
133 static inline size_t bs_pos( const bs_t
*s
)
135 return 8 * s
->cb
.pf_byte_pos( s
) - s
->i_left
;
138 static inline void bs_skip( bs_t
*s
, size_t i_count
)
149 if( i_count
> s
->i_left
)
151 i_count
-= s
->i_left
;
153 size_t bytes
= i_count
/ 8;
154 if( bytes
&& s
->cb
.pf_byte_forward( s
, bytes
) != bytes
)
159 i_count
= i_count
% 8;
162 if( !bs_refill( s
) )
163 s
->i_left
= 8 - i_count
;
168 else s
->i_left
-= i_count
;
171 static inline uint32_t bs_read( bs_t
*s
, uint8_t i_count
)
173 uint8_t i_shr
, i_drop
= 0;
174 uint32_t i_result
= 0;
178 i_drop
= i_count
- 32;
190 if( s
->i_left
> i_count
)
192 uint_fast32_t mask
= (UINT64_C(1) << i_count
) - 1;
194 i_shr
= s
->i_left
- i_count
;
195 /* more in the buffer than requested */
196 i_result
|= ( *s
->p
>> i_shr
) & mask
;
197 s
->i_left
-= i_count
;
202 uint_fast32_t mask
= (UINT64_C(1) << s
->i_left
) - 1;
204 i_shr
= i_count
- s
->i_left
;
205 /* less in the buffer than requested */
209 i_result
|= (*s
->p
& mask
) << i_shr
;
210 i_count
-= s
->i_left
;
216 bs_skip( s
, i_drop
);
221 static inline uint32_t bs_read1( bs_t
*s
)
229 return ( *s
->p
>> s
->i_left
)&0x01;
232 static inline void bs_write( bs_t
*s
, uint8_t i_count
, uint32_t i_bits
)
247 if( ( i_bits
>> i_count
)&0x01 )
249 *s
->p
|= 1 << ( s
->i_left
- 1 );
253 *s
->p
&= ~( 1 << ( s
->i_left
- 1 ) );
259 static inline bool bs_aligned( bs_t
*s
)
261 return s
->i_left
% 8 == 0;
264 static inline void bs_align( bs_t
*s
)
270 static inline void bs_write_align( bs_t
*s
, uint8_t v
)
272 if( !s
->b_read_only
&& (s
->i_left
% 8) )
273 bs_write( s
, s
->i_left
, v
? 0xFF : 0 );
276 #define bs_align_0( s ) bs_write_align( s, 0 )
277 #define bs_align_1( s ) bs_write_align( s, 1 )
279 /* Read unsigned Exp-Golomb code */
280 static inline uint_fast32_t bs_read_ue( bs_t
* bs
)
284 while( !bs
->b_error
&&
285 bs_read1( bs
) == 0 &&
286 bs
->p
< bs
->p_end
&& i
< 31 )
289 return (1U << i
) - 1 + bs_read( bs
, i
);
292 /* Read signed Exp-Golomb code */
293 static inline int_fast32_t bs_read_se( bs_t
*s
)
295 uint_fast32_t val
= bs_read_ue( s
);
297 return (val
& 0x01) ? (int_fast32_t)((val
+ 1) / 2)
298 : -(int_fast32_t)(val
/ 2);