Branch data Line data Source code
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., 59 Temple Place - Suite 330,
18 : : * Boston, MA 02111-1307, USA.
19 : : */
20 : :
21 : : #ifndef __GST_BIT_READER_H__
22 : : #define __GST_BIT_READER_H__
23 : :
24 : : #include <gst/gst.h>
25 : :
26 : : /* FIXME: inline functions */
27 : :
28 : : G_BEGIN_DECLS
29 : :
30 : : #define GST_BIT_READER(reader) ((GstBitReader *) (reader))
31 : :
32 : : /**
33 : : * GstBitReader:
34 : : * @data: Data from which the bit reader will read
35 : : * @size: Size of @data in bytes
36 : : * @byte: Current byte position
37 : : * @bit: Bit position in the current byte
38 : : *
39 : : * A bit reader instance.
40 : : */
41 : : typedef struct {
42 : : const guint8 *data;
43 : : guint size;
44 : :
45 : : guint byte; /* Byte position */
46 : : guint bit; /* Bit position in the current byte */
47 : : } GstBitReader;
48 : :
49 : : GstBitReader * gst_bit_reader_new (const guint8 *data, guint size);
50 : : GstBitReader * gst_bit_reader_new_from_buffer (const GstBuffer *buffer);
51 : : void gst_bit_reader_free (GstBitReader *reader);
52 : :
53 : : void gst_bit_reader_init (GstBitReader *reader, const guint8 *data, guint size);
54 : : void gst_bit_reader_init_from_buffer (GstBitReader *reader, const GstBuffer *buffer);
55 : :
56 : : gboolean gst_bit_reader_set_pos (GstBitReader *reader, guint pos);
57 : :
58 : : guint gst_bit_reader_get_pos (const GstBitReader *reader);
59 : : guint gst_bit_reader_get_remaining (const GstBitReader *reader);
60 : :
61 : : guint gst_bit_reader_get_size (const GstBitReader *reader);
62 : :
63 : : gboolean gst_bit_reader_skip (GstBitReader *reader, guint nbits);
64 : : gboolean gst_bit_reader_skip_to_byte (GstBitReader *reader);
65 : :
66 : : gboolean gst_bit_reader_get_bits_uint8 (GstBitReader *reader, guint8 *val, guint nbits);
67 : : gboolean gst_bit_reader_get_bits_uint16 (GstBitReader *reader, guint16 *val, guint nbits);
68 : : gboolean gst_bit_reader_get_bits_uint32 (GstBitReader *reader, guint32 *val, guint nbits);
69 : : gboolean gst_bit_reader_get_bits_uint64 (GstBitReader *reader, guint64 *val, guint nbits);
70 : :
71 : : gboolean gst_bit_reader_peek_bits_uint8 (const GstBitReader *reader, guint8 *val, guint nbits);
72 : : gboolean gst_bit_reader_peek_bits_uint16 (const GstBitReader *reader, guint16 *val, guint nbits);
73 : : gboolean gst_bit_reader_peek_bits_uint32 (const GstBitReader *reader, guint32 *val, guint nbits);
74 : : gboolean gst_bit_reader_peek_bits_uint64 (const GstBitReader *reader, guint64 *val, guint nbits);
75 : :
76 : : /**
77 : : * GST_BIT_READER_INIT:
78 : : * @data: Data from which the #GstBitReader should read
79 : : * @size: Size of @data in bytes
80 : : *
81 : : * A #GstBitReader must be initialized with this macro, before it can be
82 : : * used. This macro can used be to initialize a variable, but it cannot
83 : : * be assigned to a variable. In that case you have to use
84 : : * gst_bit_reader_init().
85 : : *
86 : : * Since: 0.10.22
87 : : */
88 : : #define GST_BIT_READER_INIT(data, size) {data, size, 0, 0}
89 : :
90 : : /**
91 : : * GST_BIT_READER_INIT_FROM_BUFFER:
92 : : * @buffer: Buffer from which the #GstBitReader should read
93 : : *
94 : : * A #GstBitReader must be initialized with this macro, before it can be
95 : : * used. This macro can used be to initialize a variable, but it cannot
96 : : * be assigned to a variable. In that case you have to use
97 : : * gst_bit_reader_init().
98 : : *
99 : : * Since: 0.10.22
100 : : */
101 : : #define GST_BIT_READER_INIT_FROM_BUFFER(buffer) {GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer), 0, 0}
102 : :
103 : : /* Unchecked variants */
104 : :
105 : : static inline void
106 : 50 : gst_bit_reader_skip_unchecked (GstBitReader * reader, guint nbits)
107 : : {
108 : 50 : reader->bit += nbits;
109 : 50 : reader->byte += reader->bit / 8;
110 : 50 : reader->bit = reader->bit % 8;
111 : 50 : }
112 : :
113 : : static inline void
114 : 2 : gst_bit_reader_skip_to_byte_unchecked (GstBitReader * reader)
115 : : {
116 [ + + ]: 2 : if (reader->bit) {
117 : 1 : reader->bit = 0;
118 : 1 : reader->byte++;
119 : : }
120 : 2 : }
121 : :
122 : : #define __GST_BIT_READER_READ_BITS_UNCHECKED(bits) \
123 : : static inline guint##bits \
124 : : gst_bit_reader_peek_bits_uint##bits##_unchecked (const GstBitReader *reader, guint nbits) \
125 : : { \
126 : : guint##bits ret = 0; \
127 : : const guint8 *data; \
128 : : guint byte, bit; \
129 : : \
130 : : data = reader->data; \
131 : : byte = reader->byte; \
132 : : bit = reader->bit; \
133 : : \
134 : : while (nbits > 0) { \
135 : : guint toread = MIN (nbits, 8 - bit); \
136 : : \
137 : : ret <<= toread; \
138 : : ret |= (data[byte] & (0xff >> bit)) >> (8 - toread - bit); \
139 : : \
140 : : bit += toread; \
141 : : if (bit >= 8) { \
142 : : byte++; \
143 : : bit = 0; \
144 : : } \
145 : : nbits -= toread; \
146 : : } \
147 : : \
148 : : return ret; \
149 : : } \
150 : : \
151 : : static inline guint##bits \
152 : : gst_bit_reader_get_bits_uint##bits##_unchecked (GstBitReader *reader, guint nbits) \
153 : : { \
154 : : guint##bits ret; \
155 : : \
156 : : ret = gst_bit_reader_peek_bits_uint##bits##_unchecked (reader, nbits); \
157 : : \
158 : : gst_bit_reader_skip_unchecked (reader, nbits); \
159 : : \
160 : : return ret; \
161 : : }
162 : :
163 [ + + ][ + + ]: 75 : __GST_BIT_READER_READ_BITS_UNCHECKED (8)
164 [ + + ][ + + ]: 24 : __GST_BIT_READER_READ_BITS_UNCHECKED (16)
165 [ + + ][ + + ]: 36 : __GST_BIT_READER_READ_BITS_UNCHECKED (32)
166 [ + + ][ + + ]: 27 : __GST_BIT_READER_READ_BITS_UNCHECKED (64)
167 : :
168 : : #undef __GST_BIT_READER_READ_BITS_UNCHECKED
169 : :
170 : : /* unchecked variants -- do not use */
171 : :
172 : : static inline guint
173 : 0 : _gst_bit_reader_get_size_unchecked (const GstBitReader * reader)
174 : : {
175 : 0 : return reader->size * 8;
176 : : }
177 : :
178 : : static inline guint
179 : 6 : _gst_bit_reader_get_pos_unchecked (const GstBitReader * reader)
180 : : {
181 : 6 : return reader->byte * 8 + reader->bit;
182 : : }
183 : :
184 : : static inline guint
185 : 69 : _gst_bit_reader_get_remaining_unchecked (const GstBitReader * reader)
186 : : {
187 : 69 : return reader->size * 8 - (reader->byte * 8 + reader->bit);
188 : : }
189 : :
190 : : /* inlined variants -- do not use directly */
191 : : static inline guint
192 : 0 : _gst_bit_reader_get_size_inline (const GstBitReader * reader)
193 : : {
194 [ # # ]: 0 : g_return_val_if_fail (reader != NULL, 0);
195 : :
196 : 0 : return _gst_bit_reader_get_size_unchecked (reader);
197 : : }
198 : :
199 : : static inline guint
200 : 6 : _gst_bit_reader_get_pos_inline (const GstBitReader * reader)
201 : : {
202 [ - + ]: 6 : g_return_val_if_fail (reader != NULL, 0);
203 : :
204 : 6 : return _gst_bit_reader_get_pos_unchecked (reader);
205 : : }
206 : :
207 : : static inline guint
208 : 6 : _gst_bit_reader_get_remaining_inline (const GstBitReader * reader)
209 : : {
210 [ - + ]: 6 : g_return_val_if_fail (reader != NULL, 0);
211 : :
212 : 6 : return _gst_bit_reader_get_remaining_unchecked (reader);
213 : : }
214 : :
215 : : static inline gboolean
216 : 8 : _gst_bit_reader_skip_inline (GstBitReader * reader, guint nbits)
217 : : {
218 [ - + ]: 8 : g_return_val_if_fail (reader != NULL, FALSE);
219 : :
220 [ + + ]: 8 : if (_gst_bit_reader_get_remaining_unchecked (reader) < nbits)
221 : 1 : return FALSE;
222 : :
223 : 7 : gst_bit_reader_skip_unchecked (reader, nbits);
224 : :
225 : 8 : return TRUE;
226 : : }
227 : :
228 : : static inline gboolean
229 : 2 : _gst_bit_reader_skip_to_byte_inline (GstBitReader * reader)
230 : : {
231 [ - + ]: 2 : g_return_val_if_fail (reader != NULL, FALSE);
232 : :
233 [ - + ]: 2 : if (reader->byte > reader->size)
234 : 0 : return FALSE;
235 : :
236 : 2 : gst_bit_reader_skip_to_byte_unchecked (reader);
237 : :
238 : 2 : return TRUE;
239 : : }
240 : :
241 : : #define __GST_BIT_READER_READ_BITS_INLINE(bits) \
242 : : static inline gboolean \
243 : : _gst_bit_reader_get_bits_uint##bits##_inline (GstBitReader *reader, guint##bits *val, guint nbits) \
244 : : { \
245 : : g_return_val_if_fail (reader != NULL, FALSE); \
246 : : g_return_val_if_fail (val != NULL, FALSE); \
247 : : g_return_val_if_fail (nbits <= bits, FALSE); \
248 : : \
249 : : if (_gst_bit_reader_get_remaining_unchecked (reader) < nbits) \
250 : : return FALSE; \
251 : : \
252 : : *val = gst_bit_reader_get_bits_uint##bits##_unchecked (reader, nbits); \
253 : : return TRUE; \
254 : : } \
255 : : \
256 : : static inline gboolean \
257 : : _gst_bit_reader_peek_bits_uint##bits##_inline (const 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_peek_bits_uint##bits##_unchecked (reader, nbits); \
267 : : return TRUE; \
268 : : }
269 : :
270 [ - + ][ - + ]: 28 : __GST_BIT_READER_READ_BITS_INLINE (8)
[ - + ][ + + ]
[ - + ][ - + ]
[ - + ][ + + ]
271 [ - + ][ - + ]: 10 : __GST_BIT_READER_READ_BITS_INLINE (16)
[ - + ][ + + ]
[ - + ][ - + ]
[ - + ][ + + ]
272 [ - + ][ - + ]: 11 : __GST_BIT_READER_READ_BITS_INLINE (32)
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ + + ]
273 [ - + ][ - + ]: 6 : __GST_BIT_READER_READ_BITS_INLINE (64)
[ - + ][ + + ]
[ # # ][ # # ]
[ # # ][ # # ]
274 : :
275 : : #undef __GST_BIT_READER_READ_BITS_INLINE
276 : :
277 : : #ifndef GST_BIT_READER_DISABLE_INLINES
278 : :
279 : : #define gst_bit_reader_get_size(reader) \
280 : : _gst_bit_reader_get_size_inline (reader)
281 : : #define gst_bit_reader_get_pos(reader) \
282 : : _gst_bit_reader_get_pos_inline (reader)
283 : : #define gst_bit_reader_get_remaining(reader) \
284 : : _gst_bit_reader_get_remaining_inline (reader)
285 : :
286 : : /* we use defines here so we can add the G_LIKELY() */
287 : :
288 : : #define gst_bit_reader_skip(reader, nbits)\
289 : : G_LIKELY (_gst_bit_reader_skip_inline(reader, nbits))
290 : : #define gst_bit_reader_skip_to_byte(reader)\
291 : : G_LIKELY (_gst_bit_reader_skip_to_byte_inline(reader))
292 : :
293 : : #define gst_bit_reader_get_bits_uint8(reader, val, nbits) \
294 : : G_LIKELY (_gst_bit_reader_get_bits_uint8_inline (reader, val, nbits))
295 : : #define gst_bit_reader_get_bits_uint16(reader, val, nbits) \
296 : : G_LIKELY (_gst_bit_reader_get_bits_uint16_inline (reader, val, nbits))
297 : : #define gst_bit_reader_get_bits_uint32(reader, val, nbits) \
298 : : G_LIKELY (_gst_bit_reader_get_bits_uint32_inline (reader, val, nbits))
299 : : #define gst_bit_reader_get_bits_uint64(reader, val, nbits) \
300 : : G_LIKELY (_gst_bit_reader_get_bits_uint64_inline (reader, val, nbits))
301 : :
302 : : #define gst_bit_reader_peek_bits_uint8(reader, val, nbits) \
303 : : G_LIKELY (_gst_bit_reader_peek_bits_uint8_inline (reader, val, nbits))
304 : : #define gst_bit_reader_peek_bits_uint16(reader, val, nbits) \
305 : : G_LIKELY (_gst_bit_reader_peek_bits_uint16_inline (reader, val, nbits))
306 : : #define gst_bit_reader_peek_bits_uint32(reader, val, nbits) \
307 : : G_LIKELY (_gst_bit_reader_peek_bits_uint32_inline (reader, val, nbits))
308 : : #define gst_bit_reader_peek_bits_uint64(reader, val, nbits) \
309 : : G_LIKELY (_gst_bit_reader_peek_bits_uint64_inline (reader, val, nbits))
310 : : #endif
311 : :
312 : : G_END_DECLS
313 : :
314 : : #endif /* __GST_BIT_READER_H__ */
|