• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer
2  *
3  * Copyright (C) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20 
21 #ifndef __GST_BIT_READER_H__
22 #define __GST_BIT_READER_H__
23 
24 #include <gst/gst.h>
25 #include <gst/base/base-prelude.h>
26 
27 /* FIXME: inline functions */
28 
29 G_BEGIN_DECLS
30 
31 #define GST_BIT_READER(reader) ((GstBitReader *) (reader))
32 
33 /**
34  * GstBitReader:
35  * @data: (array length=size): Data from which the bit reader will
36  *   read
37  * @size: Size of @data in bytes
38  * @byte: Current byte position
39  * @bit: Bit position in the current byte
40  *
41  * A bit reader instance.
42  */
43 typedef struct {
44   const guint8 *data;
45   guint size;
46 
47   guint byte;  /* Byte position */
48   guint bit;   /* Bit position in the current byte */
49 
50   /* < private > */
51   gpointer _gst_reserved[GST_PADDING];
52 } GstBitReader;
53 
54 GST_BASE_API
55 GstBitReader *  gst_bit_reader_new              (const guint8 *data, guint size) G_GNUC_MALLOC;
56 
57 GST_BASE_API
58 void            gst_bit_reader_free             (GstBitReader *reader);
59 
60 GST_BASE_API
61 void            gst_bit_reader_init             (GstBitReader *reader, const guint8 *data, guint size);
62 
63 GST_BASE_API
64 gboolean        gst_bit_reader_set_pos          (GstBitReader *reader, guint pos);
65 
66 GST_BASE_API
67 guint           gst_bit_reader_get_pos          (const GstBitReader *reader);
68 
69 GST_BASE_API
70 guint           gst_bit_reader_get_remaining    (const GstBitReader *reader);
71 
72 GST_BASE_API
73 guint           gst_bit_reader_get_size         (const GstBitReader *reader);
74 
75 GST_BASE_API
76 gboolean        gst_bit_reader_skip             (GstBitReader *reader, guint nbits);
77 
78 GST_BASE_API
79 gboolean        gst_bit_reader_skip_to_byte     (GstBitReader *reader);
80 
81 GST_BASE_API
82 gboolean        gst_bit_reader_get_bits_uint8   (GstBitReader *reader, guint8 *val, guint nbits);
83 
84 GST_BASE_API
85 gboolean        gst_bit_reader_get_bits_uint16  (GstBitReader *reader, guint16 *val, guint nbits);
86 
87 GST_BASE_API
88 gboolean        gst_bit_reader_get_bits_uint32  (GstBitReader *reader, guint32 *val, guint nbits);
89 
90 GST_BASE_API
91 gboolean        gst_bit_reader_get_bits_uint64  (GstBitReader *reader, guint64 *val, guint nbits);
92 
93 GST_BASE_API
94 gboolean        gst_bit_reader_peek_bits_uint8  (const GstBitReader *reader, guint8 *val, guint nbits);
95 
96 GST_BASE_API
97 gboolean        gst_bit_reader_peek_bits_uint16 (const GstBitReader *reader, guint16 *val, guint nbits);
98 
99 GST_BASE_API
100 gboolean        gst_bit_reader_peek_bits_uint32 (const GstBitReader *reader, guint32 *val, guint nbits);
101 
102 GST_BASE_API
103 gboolean        gst_bit_reader_peek_bits_uint64 (const GstBitReader *reader, guint64 *val, guint nbits);
104 
105 /**
106  * GST_BIT_READER_INIT:
107  * @data: Data from which the #GstBitReader should read
108  * @size: Size of @data in bytes
109  *
110  * A #GstBitReader must be initialized with this macro, before it can be
111  * used. This macro can used be to initialize a variable, but it cannot
112  * be assigned to a variable. In that case you have to use
113  * gst_bit_reader_init().
114  */
115 #define GST_BIT_READER_INIT(data, size) {data, size, 0, 0}
116 
117 /* Unchecked variants */
118 
119 static inline void
gst_bit_reader_skip_unchecked(GstBitReader * reader,guint nbits)120 gst_bit_reader_skip_unchecked (GstBitReader * reader, guint nbits)
121 {
122   reader->bit += nbits;
123   reader->byte += reader->bit / 8;
124   reader->bit = reader->bit % 8;
125 }
126 
127 static inline void
gst_bit_reader_skip_to_byte_unchecked(GstBitReader * reader)128 gst_bit_reader_skip_to_byte_unchecked (GstBitReader * reader)
129 {
130   if (reader->bit) {
131     reader->bit = 0;
132     reader->byte++;
133   }
134 }
135 
136 #define __GST_BIT_READER_READ_BITS_UNCHECKED(bits) \
137 static inline guint##bits \
138 gst_bit_reader_peek_bits_uint##bits##_unchecked (const GstBitReader *reader, guint nbits) \
139 { \
140   guint##bits ret = 0; \
141   const guint8 *data; \
142   guint byte, bit; \
143   \
144   data = reader->data; \
145   byte = reader->byte; \
146   bit = reader->bit; \
147   \
148   while (nbits > 0) { \
149     guint toread = MIN (nbits, 8 - bit); \
150     \
151     ret <<= toread; \
152     ret |= (data[byte] & (0xff >> bit)) >> (8 - toread - bit); \
153     \
154     bit += toread; \
155     if (bit >= 8) { \
156       byte++; \
157       bit = 0; \
158     } \
159     nbits -= toread; \
160   } \
161   \
162   return ret; \
163 } \
164 \
165 static inline guint##bits \
166 gst_bit_reader_get_bits_uint##bits##_unchecked (GstBitReader *reader, guint nbits) \
167 { \
168   guint##bits ret; \
169   \
170   ret = gst_bit_reader_peek_bits_uint##bits##_unchecked (reader, nbits); \
171   \
172   gst_bit_reader_skip_unchecked (reader, nbits); \
173   \
174   return ret; \
175 }
176 
177 __GST_BIT_READER_READ_BITS_UNCHECKED (8)
178 __GST_BIT_READER_READ_BITS_UNCHECKED (16)
179 __GST_BIT_READER_READ_BITS_UNCHECKED (32)
180 __GST_BIT_READER_READ_BITS_UNCHECKED (64)
181 
182 #undef __GST_BIT_READER_READ_BITS_UNCHECKED
183 
184 /* unchecked variants -- do not use */
185 
186 static inline guint
_gst_bit_reader_get_size_unchecked(const GstBitReader * reader)187 _gst_bit_reader_get_size_unchecked (const GstBitReader * reader)
188 {
189   return reader->size * 8;
190 }
191 
192 static inline guint
_gst_bit_reader_get_pos_unchecked(const GstBitReader * reader)193 _gst_bit_reader_get_pos_unchecked (const GstBitReader * reader)
194 {
195   return reader->byte * 8 + reader->bit;
196 }
197 
198 static inline guint
_gst_bit_reader_get_remaining_unchecked(const GstBitReader * reader)199 _gst_bit_reader_get_remaining_unchecked (const GstBitReader * reader)
200 {
201   return reader->size * 8 - (reader->byte * 8 + reader->bit);
202 }
203 
204 /* inlined variants -- do not use directly */
205 static inline guint
_gst_bit_reader_get_size_inline(const GstBitReader * reader)206 _gst_bit_reader_get_size_inline (const GstBitReader * reader)
207 {
208   g_return_val_if_fail (reader != NULL, 0);
209 
210   return _gst_bit_reader_get_size_unchecked (reader);
211 }
212 
213 static inline guint
_gst_bit_reader_get_pos_inline(const GstBitReader * reader)214 _gst_bit_reader_get_pos_inline (const GstBitReader * reader)
215 {
216   g_return_val_if_fail (reader != NULL, 0);
217 
218   return _gst_bit_reader_get_pos_unchecked (reader);
219 }
220 
221 static inline guint
_gst_bit_reader_get_remaining_inline(const GstBitReader * reader)222 _gst_bit_reader_get_remaining_inline (const GstBitReader * reader)
223 {
224   g_return_val_if_fail (reader != NULL, 0);
225 
226   return _gst_bit_reader_get_remaining_unchecked (reader);
227 }
228 
229 static inline gboolean
_gst_bit_reader_skip_inline(GstBitReader * reader,guint nbits)230 _gst_bit_reader_skip_inline (GstBitReader * reader, guint nbits)
231 {
232   g_return_val_if_fail (reader != NULL, FALSE);
233 
234   if (_gst_bit_reader_get_remaining_unchecked (reader) < nbits)
235     return FALSE;
236 
237   gst_bit_reader_skip_unchecked (reader, nbits);
238 
239   return TRUE;
240 }
241 
242 static inline gboolean
_gst_bit_reader_skip_to_byte_inline(GstBitReader * reader)243 _gst_bit_reader_skip_to_byte_inline (GstBitReader * reader)
244 {
245   g_return_val_if_fail (reader != NULL, FALSE);
246 
247   if (reader->byte > reader->size)
248     return FALSE;
249 
250   gst_bit_reader_skip_to_byte_unchecked (reader);
251 
252   return TRUE;
253 }
254 
255 #define __GST_BIT_READER_READ_BITS_INLINE(bits) \
256 static inline gboolean \
257 _gst_bit_reader_get_bits_uint##bits##_inline (GstBitReader *reader, guint##bits *val, guint nbits) \
258 { \
259   g_return_val_if_fail (reader != NULL, FALSE); \
260   g_return_val_if_fail (val != NULL, FALSE); \
261   g_return_val_if_fail (nbits <= bits, FALSE); \
262   \
263   if (_gst_bit_reader_get_remaining_unchecked (reader) < nbits) \
264     return FALSE; \
265 \
266   *val = gst_bit_reader_get_bits_uint##bits##_unchecked (reader, nbits); \
267   return TRUE; \
268 } \
269 \
270 static inline gboolean \
271 _gst_bit_reader_peek_bits_uint##bits##_inline (const GstBitReader *reader, guint##bits *val, guint nbits) \
272 { \
273   g_return_val_if_fail (reader != NULL, FALSE); \
274   g_return_val_if_fail (val != NULL, FALSE); \
275   g_return_val_if_fail (nbits <= bits, FALSE); \
276   \
277   if (_gst_bit_reader_get_remaining_unchecked (reader) < nbits) \
278     return FALSE; \
279 \
280   *val = gst_bit_reader_peek_bits_uint##bits##_unchecked (reader, nbits); \
281   return TRUE; \
282 }
283 
284 __GST_BIT_READER_READ_BITS_INLINE (8)
285 __GST_BIT_READER_READ_BITS_INLINE (16)
286 __GST_BIT_READER_READ_BITS_INLINE (32)
287 __GST_BIT_READER_READ_BITS_INLINE (64)
288 
289 #undef __GST_BIT_READER_READ_BITS_INLINE
290 
291 #ifndef GST_BIT_READER_DISABLE_INLINES
292 
293 #define gst_bit_reader_get_size(reader) \
294     _gst_bit_reader_get_size_inline (reader)
295 #define gst_bit_reader_get_pos(reader) \
296     _gst_bit_reader_get_pos_inline (reader)
297 #define gst_bit_reader_get_remaining(reader) \
298     _gst_bit_reader_get_remaining_inline (reader)
299 
300 /* we use defines here so we can add the G_LIKELY() */
301 
302 #define gst_bit_reader_skip(reader, nbits)\
303     G_LIKELY (_gst_bit_reader_skip_inline(reader, nbits))
304 #define gst_bit_reader_skip_to_byte(reader)\
305     G_LIKELY (_gst_bit_reader_skip_to_byte_inline(reader))
306 
307 #define gst_bit_reader_get_bits_uint8(reader, val, nbits) \
308     G_LIKELY (_gst_bit_reader_get_bits_uint8_inline (reader, val, nbits))
309 #define gst_bit_reader_get_bits_uint16(reader, val, nbits) \
310     G_LIKELY (_gst_bit_reader_get_bits_uint16_inline (reader, val, nbits))
311 #define gst_bit_reader_get_bits_uint32(reader, val, nbits) \
312     G_LIKELY (_gst_bit_reader_get_bits_uint32_inline (reader, val, nbits))
313 #define gst_bit_reader_get_bits_uint64(reader, val, nbits) \
314     G_LIKELY (_gst_bit_reader_get_bits_uint64_inline (reader, val, nbits))
315 
316 #define gst_bit_reader_peek_bits_uint8(reader, val, nbits) \
317     G_LIKELY (_gst_bit_reader_peek_bits_uint8_inline (reader, val, nbits))
318 #define gst_bit_reader_peek_bits_uint16(reader, val, nbits) \
319     G_LIKELY (_gst_bit_reader_peek_bits_uint16_inline (reader, val, nbits))
320 #define gst_bit_reader_peek_bits_uint32(reader, val, nbits) \
321     G_LIKELY (_gst_bit_reader_peek_bits_uint32_inline (reader, val, nbits))
322 #define gst_bit_reader_peek_bits_uint64(reader, val, nbits) \
323     G_LIKELY (_gst_bit_reader_peek_bits_uint64_inline (reader, val, nbits))
324 #endif
325 
326 G_END_DECLS
327 
328 #endif /* __GST_BIT_READER_H__ */
329