VLC 4.0.0-dev
vlc_bits.h
Go to the documentation of this file.
1/*****************************************************************************
2 * vlc_bits.h : Bit handling helpers
3 *****************************************************************************
4 * Copyright (C) 2001, 2002, 2003, 2006, 2015 VLC authors and VideoLAN
5 *
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>
9 *
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.
14 *
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.
19 *
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 *****************************************************************************/
24#ifndef VLC_BITS_H
25#define VLC_BITS_H 1
26
27#include <vlc_common.h>
28
29/**
30 * \file
31 * This file defines functions, structures for handling streams of bits in vlc
32 */
33
34typedef struct bs_s bs_t;
36typedef struct
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 *);
42
43typedef struct bs_s
45 uint8_t *p_start;
46 uint8_t *p; /* points to currently read/written byte */
47 uint8_t *p_end;
49 uint8_t i_left; /* i_count number of available bits */
51 bool b_error;
54 void *p_priv;
56
57static size_t bs_impl_bytes_forward( bs_t *s, size_t i_count )
59 if( s->p == NULL )
60 {
61 s->p = s->p_start;
62 return 1;
63 }
64
65 if( s->p >= s->p_end )
66 return 0;
67
68 if( (size_t) (s->p_end - s->p) < i_count )
69 i_count = s->p_end - s->p;
70 s->p += i_count;
71 return i_count;
72}
73
74static size_t bs_impl_bytes_pos( const bs_t *s )
76 if( s->p )
77 return s->p < s->p_end ? s->p - s->p_start + 1 : s->p - s->p_start;
78 else
79 return 0;
80}
81
82static 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 )
84{
85 s->p_start = (uint8_t *)p_data;
86 s->p = NULL;
87 s->p_end = s->p_start + i_data;
88 s->i_left = 0;
89 s->b_read_only = true;
90 s->b_error = false;
91 s->p_priv = priv;
92 s->cb = *cb;
93}
94
95static inline void bs_init( bs_t *s, const void *p_data, size_t i_data )
100 };
101 bs_init_custom( s, p_data, i_data, &cb, NULL );
102}
103
104static 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;
108}
109
110static inline int bs_refill( bs_t *s )
112 if( s->i_left == 0 )
113 {
114 if( s->cb.pf_byte_forward( s, 1 ) != 1 )
115 return -1;
116
117 if( s->p < s->p_end )
118 s->i_left = 8;
119 }
120 return s->i_left > 0 ? 0 : 1;
121}
122
123static inline bool bs_error( const bs_t *s )
125 return s->b_error;
126}
127
128static inline bool bs_eof( bs_t *s )
130 return bs_refill( s ) != 0;
131}
132
133static inline size_t bs_pos( const bs_t *s )
135 return 8 * s->cb.pf_byte_pos( s ) - s->i_left;
136}
137
138static inline void bs_skip( bs_t *s, size_t i_count )
140 if( i_count == 0 )
141 return;
142
143 if( bs_refill( s ) )
144 {
145 s->b_error = true;
146 return;
147 }
148
149 if( i_count > s->i_left )
150 {
151 i_count -= s->i_left;
152 s->i_left = 0;
153 size_t bytes = i_count / 8;
154 if( bytes && s->cb.pf_byte_forward( s, bytes ) != bytes )
155 {
156 s->b_error = true;
157 return;
158 }
159 i_count = i_count % 8;
160 if( i_count > 0 )
161 {
162 if( !bs_refill( s ) )
163 s->i_left = 8 - i_count;
164 else
165 s->b_error = true;
166 }
167 }
168 else s->i_left -= i_count;
169}
170
171static 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;
175
176 if( i_count > 32 )
177 {
178 i_drop = i_count - 32;
179 i_count = 32;
180 }
181
182 while( i_count > 0 )
183 {
184 if( bs_refill( s ) )
185 {
186 s->b_error = true;
187 break;
188 }
189
190 if( s->i_left > i_count )
191 {
192 uint_fast32_t mask = (UINT64_C(1) << i_count) - 1;
193
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;
198 break;
199 }
200 else
201 {
202 uint_fast32_t mask = (UINT64_C(1) << s->i_left) - 1;
203
204 i_shr = i_count - s->i_left;
205 /* less in the buffer than requested */
206 if( i_shr >= 32 )
207 i_result = 0;
208 else
209 i_result |= (*s->p & mask) << i_shr;
210 i_count -= s->i_left;
211 s->i_left = 0;
212 }
213 }
214
215 if( i_drop )
216 bs_skip( s, i_drop );
217
218 return( i_result );
219}
220
221static inline uint32_t bs_read1( bs_t *s )
223 if( bs_refill( s ) )
224 {
225 s->b_error = true;
226 return 0;
227 }
228 s->i_left--;
229 return ( *s->p >> s->i_left )&0x01;
230}
231
232static inline void bs_write( bs_t *s, uint8_t i_count, uint32_t i_bits )
234 if( s->b_read_only )
235 return;
236
237 while( i_count > 0 )
238 {
239 if( bs_refill( s ) )
240 {
241 s->b_error = true;
242 break;
243 }
244
245 i_count--;
246
247 if( ( i_bits >> i_count )&0x01 )
248 {
249 *s->p |= 1 << ( s->i_left - 1 );
250 }
251 else
252 {
253 *s->p &= ~( 1 << ( s->i_left - 1 ) );
254 }
255 s->i_left--;
256 }
257}
258
259static inline bool bs_aligned( bs_t *s )
261 return s->i_left % 8 == 0;
262}
263
264static inline void bs_align( bs_t *s )
266 if( s->i_left % 8 )
267 s->i_left = 0;
268}
269
270static 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 );
274}
275
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 */
280static inline uint_fast32_t bs_read_ue( bs_t * bs )
282 unsigned i = 0;
283
284 while( !bs->b_error &&
285 bs_read1( bs ) == 0 &&
286 bs->p < bs->p_end && i < 31 )
287 i++;
288
289 return (1U << i) - 1 + bs_read( bs, i );
290}
291
292/* Read signed Exp-Golomb code */
293static inline int_fast32_t bs_read_se( bs_t *s )
295 uint_fast32_t val = bs_read_ue( s );
296
297 return (val & 0x01) ? (int_fast32_t)((val + 1) / 2)
298 : -(int_fast32_t)(val / 2);
299}
300
301#undef bs_forward
302
303#endif
Definition: vlc_bits.h:38
size_t(* pf_byte_pos)(const bs_t *)
Definition: vlc_bits.h:41
size_t(* pf_byte_forward)(bs_t *, size_t)
Definition: vlc_bits.h:40
Definition: vlc_bits.h:45
uint8_t * p_end
Definition: vlc_bits.h:48
uint8_t * p
Definition: vlc_bits.h:47
uint8_t * p_start
Definition: vlc_bits.h:46
uint8_t i_left
Definition: vlc_bits.h:50
bs_byte_callbacks_t cb
Definition: vlc_bits.h:54
bool b_read_only
Definition: vlc_bits.h:51
void * p_priv
Definition: vlc_bits.h:55
bool b_error
Definition: vlc_bits.h:52
static void bs_init_custom(bs_t *s, const void *p_data, size_t i_data, const bs_byte_callbacks_t *cb, void *priv)
Definition: vlc_bits.h:83
static size_t bs_impl_bytes_pos(const bs_t *s)
Definition: vlc_bits.h:75
static void bs_write(bs_t *s, uint8_t i_count, uint32_t i_bits)
Definition: vlc_bits.h:233
struct bs_s bs_t
Definition: vlc_bits.h:35
static uint_fast32_t bs_read_ue(bs_t *bs)
Definition: vlc_bits.h:281
static uint32_t bs_read1(bs_t *s)
Definition: vlc_bits.h:222
static bool bs_aligned(bs_t *s)
Definition: vlc_bits.h:260
static size_t bs_impl_bytes_forward(bs_t *s, size_t i_count)
Definition: vlc_bits.h:58
static void bs_skip(bs_t *s, size_t i_count)
Definition: vlc_bits.h:139
static void bs_write_init(bs_t *s, void *p_data, size_t i_data)
Definition: vlc_bits.h:105
static uint32_t bs_read(bs_t *s, uint8_t i_count)
Definition: vlc_bits.h:172
static void bs_align(bs_t *s)
Definition: vlc_bits.h:265
static bool bs_error(const bs_t *s)
Definition: vlc_bits.h:124
static size_t bs_pos(const bs_t *s)
Definition: vlc_bits.h:134
static void bs_write_align(bs_t *s, uint8_t v)
Definition: vlc_bits.h:271
static int bs_refill(bs_t *s)
Definition: vlc_bits.h:111
static bool bs_eof(bs_t *s)
Definition: vlc_bits.h:129
static void bs_init(bs_t *s, const void *p_data, size_t i_data)
Definition: vlc_bits.h:96
static int_fast32_t bs_read_se(bs_t *s)
Definition: vlc_bits.h:294
This file is a collection of common definitions and types.