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 
34 typedef struct bs_s bs_t;
35 
36 typedef struct
37 {
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 
43 typedef struct bs_s
44 {
45  uint8_t *p_start;
46  uint8_t *p; /* points to currently read/written byte */
47  uint8_t *p_end;
48 
49  uint8_t i_left; /* i_count number of available bits */
51  bool b_error;
52 
54  void *p_priv;
55 } bs_t;
56 
57 static size_t bs_impl_bytes_forward( bs_t *s, size_t i_count )
58 {
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 
74 static size_t bs_impl_bytes_pos( const bs_t *s )
75 {
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 
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 )
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 
95 static inline void bs_init( bs_t *s, const void *p_data, size_t i_data )
96 {
97  bs_byte_callbacks_t cb = {
100  };
101  bs_init_custom( s, p_data, i_data, &cb, NULL );
102 }
103 
104 static inline void bs_write_init( bs_t *s, void *p_data, size_t i_data )
105 {
106  bs_init( s, (const void *) p_data, i_data );
107  s->b_read_only = false;
108 }
109 
110 static inline int bs_refill( bs_t *s )
111 {
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 
123 static inline bool bs_error( const bs_t *s )
124 {
125  return s->b_error;
126 }
127 
128 static inline bool bs_eof( bs_t *s )
129 {
130  return bs_refill( s ) != 0;
131 }
132 
133 static inline size_t bs_pos( const bs_t *s )
134 {
135  return 8 * s->cb.pf_byte_pos( s ) - s->i_left;
136 }
137 
138 static inline void bs_skip( bs_t *s, size_t i_count )
139 {
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 
171 static inline uint32_t bs_read( bs_t *s, uint8_t i_count )
172 {
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 
221 static inline uint32_t bs_read1( bs_t *s )
222 {
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 
232 static inline void bs_write( bs_t *s, uint8_t i_count, uint32_t i_bits )
233 {
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 
259 static inline bool bs_aligned( bs_t *s )
260 {
261  return s->i_left % 8 == 0;
262 }
263 
264 static inline void bs_align( bs_t *s )
265 {
266  if( s->i_left % 8 )
267  s->i_left = 0;
268 }
269 
270 static inline void bs_write_align( bs_t *s, uint8_t v )
271 {
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 )
278 
279 /* Read unsigned Exp-Golomb code */
280 static inline uint_fast32_t bs_read_ue( bs_t * bs )
281 {
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 */
293 static inline int_fast32_t bs_read_se( bs_t *s )
294 {
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
bs_read1
static uint32_t bs_read1(bs_t *s)
Definition: vlc_bits.h:222
bs_s::p_start
uint8_t * p_start
Definition: vlc_bits.h:46
bs_align
static void bs_align(bs_t *s)
Definition: vlc_bits.h:265
bs_pos
static size_t bs_pos(const bs_t *s)
Definition: vlc_bits.h:134
bs_read
static uint32_t bs_read(bs_t *s, uint8_t i_count)
Definition: vlc_bits.h:172
bs_init
static void bs_init(bs_t *s, const void *p_data, size_t i_data)
Definition: vlc_bits.h:96
bs_error
static bool bs_error(const bs_t *s)
Definition: vlc_bits.h:124
vlc_common.h
bs_impl_bytes_pos
static size_t bs_impl_bytes_pos(const bs_t *s)
Definition: vlc_bits.h:75
bs_skip
static void bs_skip(bs_t *s, size_t i_count)
Definition: vlc_bits.h:139
bs_s
Definition: vlc_bits.h:44
bs_s::b_read_only
bool b_read_only
Definition: vlc_bits.h:51
bs_s::b_error
bool b_error
Definition: vlc_bits.h:52
bs_write_align
static void bs_write_align(bs_t *s, uint8_t v)
Definition: vlc_bits.h:271
bs_write_init
static void bs_write_init(bs_t *s, void *p_data, size_t i_data)
Definition: vlc_bits.h:105
bs_read_ue
static uint_fast32_t bs_read_ue(bs_t *bs)
Definition: vlc_bits.h:281
bs_aligned
static bool bs_aligned(bs_t *s)
Definition: vlc_bits.h:260
bs_byte_callbacks_t
Definition: vlc_bits.h:37
bs_s::i_left
uint8_t i_left
Definition: vlc_bits.h:50
bs_write
static void bs_write(bs_t *s, uint8_t i_count, uint32_t i_bits)
Definition: vlc_bits.h:233
bs_s::p
uint8_t * p
Definition: vlc_bits.h:47
bs_eof
static bool bs_eof(bs_t *s)
Definition: vlc_bits.h:129
bs_s::cb
bs_byte_callbacks_t cb
Definition: vlc_bits.h:54
bs_t
struct bs_s bs_t
Definition: vlc_bits.h:35
bs_s::p_end
uint8_t * p_end
Definition: vlc_bits.h:48
bs_init_custom
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
bs_byte_callbacks_t::pf_byte_pos
size_t(* pf_byte_pos)(const bs_t *)
Definition: vlc_bits.h:41
bs_byte_callbacks_t::pf_byte_forward
size_t(* pf_byte_forward)(bs_t *, size_t)
Definition: vlc_bits.h:40
bs_refill
static int bs_refill(bs_t *s)
Definition: vlc_bits.h:111
bs_impl_bytes_forward
static size_t bs_impl_bytes_forward(bs_t *s, size_t i_count)
Definition: vlc_bits.h:58
bs_read_se
static int_fast32_t bs_read_se(bs_t *s)
Definition: vlc_bits.h:294
bs_s::p_priv
void * p_priv
Definition: vlc_bits.h:55