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, remain) */
39 size_t (*pf_byte_forward
)(bs_t
*, size_t);
40 size_t (*pf_byte_pos
)(const bs_t
*);
41 size_t (*pf_byte_remain
)(const bs_t
*);
42 } bs_byte_callbacks_t
;
47 uint8_t *p
; /* points to currently read/written byte */
50 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_remain( const bs_t
*s
)
77 return s
->p
< s
->p_end
? s
->p_end
- s
->p
- 1: 0;
79 return s
->p_end
- s
->p_start
;
82 static size_t bs_impl_bytes_pos( const bs_t
*s
)
85 return s
->p
< s
->p_end
? s
->p
- s
->p_start
+ 1 : s
->p
- s
->p_start
;
90 static inline void bs_init_custom( bs_t
*s
, const void *p_data
, size_t i_data
,
91 const bs_byte_callbacks_t
*cb
, void *priv
)
93 s
->p_start
= (uint8_t *)p_data
;
95 s
->p_end
= s
->p_start
+ i_data
;
97 s
->b_read_only
= true;
102 static inline void bs_init( bs_t
*s
, const void *p_data
, size_t i_data
)
104 bs_byte_callbacks_t cb
= {
105 bs_impl_bytes_forward
,
107 bs_impl_bytes_remain
,
109 bs_init_custom( s
, p_data
, i_data
, &cb
, NULL
);
112 static inline void bs_write_init( bs_t
*s
, void *p_data
, size_t i_data
)
114 bs_init( s
, (const void *) p_data
, i_data
);
115 s
->b_read_only
= false;
118 static inline int bs_refill( bs_t
*s
)
122 if( s
->cb
.pf_byte_forward( s
, 1 ) != 1 )
125 if( s
->p
< s
->p_end
)
128 return s
->i_left
> 0 ? 0 : 1;
131 static inline bool bs_eof( bs_t
*s
)
133 return bs_refill( s
) != 0;
136 static inline size_t bs_pos( const bs_t
*s
)
138 return 8 * s
->cb
.pf_byte_pos( s
) - s
->i_left
;
141 static inline size_t bs_remain( const bs_t
*s
)
143 return 8 * s
->cb
.pf_byte_remain( s
) + s
->i_left
;
146 static inline void bs_skip( bs_t
*s
, size_t i_count
)
154 if( i_count
> s
->i_left
)
156 i_count
-= s
->i_left
;
159 s
->cb
.pf_byte_forward( s
, i_count
/ 8 );
160 i_count
= i_count
% 8;
161 if( i_count
> 0 && !bs_refill( s
) )
162 s
->i_left
= 8 - i_count
;
164 else s
->i_left
-= i_count
;
167 static inline uint32_t bs_read( bs_t
*s
, uint8_t i_count
)
169 static const uint32_t i_mask
[33] =
171 0x01, 0x03, 0x07, 0x0f,
172 0x1f, 0x3f, 0x7f, 0xff,
173 0x1ff, 0x3ff, 0x7ff, 0xfff,
174 0x1fff, 0x3fff, 0x7fff, 0xffff,
175 0x1ffff, 0x3ffff, 0x7ffff, 0xfffff,
176 0x1fffff, 0x3fffff, 0x7fffff, 0xffffff,
177 0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff,
178 0x1fffffff,0x3fffffff,0x7fffffff,0xffffffff};
179 uint8_t i_shr
, i_drop
= 0;
180 uint32_t i_result
= 0;
184 i_drop
= i_count
- 32;
193 if( s
->i_left
> i_count
)
195 i_shr
= s
->i_left
- i_count
;
196 /* more in the buffer than requested */
197 i_result
|= ( *s
->p
>> i_shr
)&i_mask
[i_count
];
198 s
->i_left
-= i_count
;
203 i_shr
= i_count
- s
->i_left
;
204 /* less in the buffer than requested */
208 i_result
|= (*s
->p
&i_mask
[s
->i_left
]) << i_shr
;
209 i_count
-= s
->i_left
;
215 bs_skip( s
, i_drop
);
220 static inline uint32_t bs_read1( bs_t
*s
)
225 return ( *s
->p
>> s
->i_left
)&0x01;
228 static inline void bs_write( bs_t
*s
, uint8_t i_count
, uint32_t i_bits
)
240 if( ( i_bits
>> i_count
)&0x01 )
242 *s
->p
|= 1 << ( s
->i_left
- 1 );
246 *s
->p
&= ~( 1 << ( s
->i_left
- 1 ) );
252 static inline bool bs_aligned( bs_t
*s
)
254 return s
->i_left
% 8 == 0;
257 static inline void bs_align( bs_t
*s
)
263 static inline void bs_write_align( bs_t
*s
, uint8_t v
)
265 if( !s
->b_read_only
&& (s
->i_left
% 8) )
266 bs_write( s
, s
->i_left
, v
? 0xFF : 0 );
269 #define bs_align_0( s ) bs_write_align( s, 0 )
270 #define bs_align_1( s ) bs_write_align( s, 1 )
272 /* Read unsigned Exp-Golomb code */
273 static inline uint_fast32_t bs_read_ue( bs_t
* bs
)
277 while( bs_read1( bs
) == 0 && bs
->p
< bs
->p_end
&& i
< 31 )
280 return (1U << i
) - 1 + bs_read( bs
, i
);
283 /* Read signed Exp-Golomb code */
284 static inline int_fast32_t bs_read_se( bs_t
*s
)
286 uint_fast32_t val
= bs_read_ue( s
);
288 return (val
& 0x01) ? (int_fast32_t)((val
+ 1) / 2)
289 : -(int_fast32_t)(val
/ 2);