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 *****************************************************************************/
28 #include <vlc_common.h>
32 * This file defines functions, structures for handling streams of bits in vlc
35 typedef struct bs_s bs_t
;
39 /* forward read modifier (p_start, p_end, p_fwpriv, count, pos, remain) */
40 size_t (*pf_byte_forward
)(bs_t
*, size_t);
41 size_t (*pf_byte_pos
)(const bs_t
*);
42 size_t (*pf_byte_remain
)(const bs_t
*);
43 } bs_byte_callbacks_t
;
48 uint8_t *p
; /* points to currently read/written byte */
51 uint8_t i_left
; /* i_count number of available bits */
54 bs_byte_callbacks_t cb
;
58 static size_t bs_impl_bytes_forward( bs_t
*s
, size_t i_count
)
66 if( s
->p
>= s
->p_end
)
69 if( (size_t) (s
->p_end
- s
->p
) < i_count
)
70 i_count
= s
->p_end
- s
->p
;
75 static size_t bs_impl_bytes_remain( const bs_t
*s
)
78 return s
->p
< s
->p_end
? s
->p_end
- s
->p
- 1: 0;
80 return s
->p_end
- s
->p_start
;
83 static size_t bs_impl_bytes_pos( const bs_t
*s
)
86 return s
->p
< s
->p_end
? s
->p
- s
->p_start
+ 1 : s
->p
- s
->p_start
;
91 static inline void bs_init_custom( bs_t
*s
, const void *p_data
, size_t i_data
,
92 const bs_byte_callbacks_t
*cb
, void *priv
)
94 s
->p_start
= (uint8_t *)p_data
;
96 s
->p_end
= s
->p_start
+ i_data
;
98 s
->b_read_only
= true;
103 static inline void bs_init( bs_t
*s
, const void *p_data
, size_t i_data
)
105 bs_byte_callbacks_t cb
= {
106 bs_impl_bytes_forward
,
108 bs_impl_bytes_remain
,
110 bs_init_custom( s
, p_data
, i_data
, &cb
, NULL
);
113 static inline void bs_write_init( bs_t
*s
, void *p_data
, size_t i_data
)
115 bs_init( s
, (const void *) p_data
, i_data
);
116 s
->b_read_only
= false;
119 static inline int bs_refill( bs_t
*s
)
123 if( s
->cb
.pf_byte_forward( s
, 1 ) != 1 )
126 if( s
->p
< s
->p_end
)
129 return s
->i_left
> 0 ? 0 : 1;
132 static inline bool bs_eof( bs_t
*s
)
134 return bs_refill( s
) != 0;
137 static inline size_t bs_pos( const bs_t
*s
)
139 return 8 * s
->cb
.pf_byte_pos( s
) - s
->i_left
;
142 static inline size_t bs_remain( const bs_t
*s
)
144 return 8 * s
->cb
.pf_byte_remain( s
) + s
->i_left
;
147 static inline void bs_skip( bs_t
*s
, size_t i_count
)
155 if( i_count
> s
->i_left
)
157 i_count
-= s
->i_left
;
160 s
->cb
.pf_byte_forward( s
, i_count
/ 8 );
161 i_count
= i_count
% 8;
162 if( i_count
> 0 && !bs_refill( s
) )
163 s
->i_left
= 8 - i_count
;
165 else s
->i_left
-= i_count
;
168 static inline uint32_t bs_read( bs_t
*s
, uint8_t i_count
)
170 static const uint32_t i_mask
[33] =
172 0x01, 0x03, 0x07, 0x0f,
173 0x1f, 0x3f, 0x7f, 0xff,
174 0x1ff, 0x3ff, 0x7ff, 0xfff,
175 0x1fff, 0x3fff, 0x7fff, 0xffff,
176 0x1ffff, 0x3ffff, 0x7ffff, 0xfffff,
177 0x1fffff, 0x3fffff, 0x7fffff, 0xffffff,
178 0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff,
179 0x1fffffff,0x3fffffff,0x7fffffff,0xffffffff};
180 uint8_t i_shr
, i_drop
= 0;
181 uint32_t i_result
= 0;
185 i_drop
= i_count
- 32;
194 if( s
->i_left
> i_count
)
196 i_shr
= s
->i_left
- i_count
;
197 /* more in the buffer than requested */
198 i_result
|= ( *s
->p
>> i_shr
)&i_mask
[i_count
];
199 s
->i_left
-= i_count
;
204 i_shr
= i_count
- s
->i_left
;
205 /* less in the buffer than requested */
209 i_result
|= (*s
->p
&i_mask
[s
->i_left
]) << i_shr
;
210 i_count
-= s
->i_left
;
216 bs_skip( s
, i_drop
);
221 static inline uint32_t bs_read1( bs_t
*s
)
226 return ( *s
->p
>> s
->i_left
)&0x01;
229 static inline void bs_write( bs_t
*s
, uint8_t i_count
, uint32_t i_bits
)
241 if( ( i_bits
>> i_count
)&0x01 )
243 *s
->p
|= 1 << ( s
->i_left
- 1 );
247 *s
->p
&= ~( 1 << ( s
->i_left
- 1 ) );
253 static inline bool bs_aligned( bs_t
*s
)
255 return s
->i_left
% 8 == 0;
258 static inline void bs_align( bs_t
*s
)
264 static inline void bs_write_align( bs_t
*s
, uint8_t v
)
266 if( !s
->b_read_only
&& (s
->i_left
% 8) )
267 bs_write( s
, s
->i_left
, v
? 0xFF : 0 );
270 #define bs_align_0( s ) bs_write_align( s, 0 )
271 #define bs_align_1( s ) bs_write_align( s, 1 )
273 /* Read unsigned Exp-Golomb code */
274 static inline uint_fast32_t bs_read_ue( bs_t
* bs
)
278 while( bs_read1( bs
) == 0 && bs
->p
< bs
->p_end
&& i
< 31 )
281 return (1U << i
) - 1 + bs_read( bs
, i
);
284 /* Read signed Exp-Golomb code */
285 static inline int_fast32_t bs_read_se( bs_t
*s
)
287 uint_fast32_t val
= bs_read_ue( s
);
289 return (val
& 0x01) ? (int_fast32_t)((val
+ 1) / 2)
290 : -(int_fast32_t)(val
/ 2);