2 * gstbitwriter.h - bitstream writer
4 * Copyright (C) 2013 Intel Corporation
5 * Copyright (C) 2018 Igalia, S. L.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public License
9 * as published by the Free Software Foundation; either version 2.1
10 * of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301 USA
23 #ifndef GST_BIT_WRITER_H
24 #define GST_BIT_WRITER_H
27 #include <gst/base/base-prelude.h>
33 #define GST_BIT_WRITER_DATA(writer) ((writer)->data)
34 #define GST_BIT_WRITER_BIT_SIZE(writer) ((writer)->bit_size)
35 #define GST_BIT_WRITER(writer) ((GstBitWriter *) (writer))
37 typedef struct _GstBitWriter GstBitWriter;
41 * @data: Allocated @data for bit writer to write
42 * @bit_size: Size of written @data in bits
44 * A bit writer instance.
54 guint bit_capacity; /* Capacity of the allocated data */
55 gboolean auto_grow; /* Whether space can auto grow */
57 gpointer _gst_reserved[GST_PADDING];
61 GstBitWriter * gst_bit_writer_new (void) G_GNUC_MALLOC;
64 GstBitWriter * gst_bit_writer_new_with_size (guint32 size, gboolean fixed) G_GNUC_MALLOC;
67 GstBitWriter * gst_bit_writer_new_with_data (guint8 *data, guint size,
68 gboolean initialized) G_GNUC_MALLOC;
71 void gst_bit_writer_free (GstBitWriter *bitwriter);
74 guint8 * gst_bit_writer_free_and_get_data (GstBitWriter *bitwriter);
77 GstBuffer * gst_bit_writer_free_and_get_buffer (GstBitWriter *bitwriter);
80 void gst_bit_writer_init (GstBitWriter *bitwriter);
83 void gst_bit_writer_init_with_size (GstBitWriter *bitwriter,
84 guint32 size, gboolean fixed);
87 void gst_bit_writer_init_with_data (GstBitWriter *bitwriter, guint8 *data,
88 guint size, gboolean initialized);
91 void gst_bit_writer_reset (GstBitWriter *bitwriter);
94 guint8 * gst_bit_writer_reset_and_get_data (GstBitWriter *bitwriter);
97 GstBuffer * gst_bit_writer_reset_and_get_buffer (GstBitWriter *bitwriter);
100 guint gst_bit_writer_get_size (const GstBitWriter *bitwriter);
103 guint8 * gst_bit_writer_get_data (const GstBitWriter *bitwriter);
106 gboolean gst_bit_writer_set_pos (GstBitWriter *bitwriter, guint pos);
109 guint gst_bit_writer_get_remaining (const GstBitWriter *bitwriter);
112 gboolean gst_bit_writer_put_bits_uint8 (GstBitWriter *bitwriter, guint8 value,
116 gboolean gst_bit_writer_put_bits_uint16 (GstBitWriter *bitwriter, guint16 value,
120 gboolean gst_bit_writer_put_bits_uint32 (GstBitWriter *bitwriter, guint32 value,
124 gboolean gst_bit_writer_put_bits_uint64 (GstBitWriter *bitwriter, guint64 value,
128 gboolean gst_bit_writer_put_bytes (GstBitWriter *bitwriter, const guint8 *data,
132 gboolean gst_bit_writer_align_bytes (GstBitWriter *bitwriter, guint8 trailing_bit);
134 static const guint8 _gst_bit_writer_bit_filling_mask[9] = {
135 0x00, 0x01, 0x03, 0x07,
136 0x0F, 0x1F, 0x3F, 0x7F,
140 /* Aligned to 256 bytes */
141 #define __GST_BITS_WRITER_ALIGNMENT_MASK 2047
142 #define __GST_BITS_WRITER_ALIGNED(bitsize) \
143 (((bitsize) + __GST_BITS_WRITER_ALIGNMENT_MASK)&(~__GST_BITS_WRITER_ALIGNMENT_MASK))
145 static inline gboolean
146 _gst_bit_writer_check_remaining (GstBitWriter * bitwriter, guint32 bits)
148 guint32 new_bit_size = bits + bitwriter->bit_size;
151 g_assert (bitwriter->bit_size <= bitwriter->bit_capacity);
152 if (new_bit_size <= bitwriter->bit_capacity)
155 if (!bitwriter->auto_grow)
158 /* auto grow space */
159 new_bit_size = __GST_BITS_WRITER_ALIGNED (new_bit_size);
160 g_assert (new_bit_size
161 && ((new_bit_size & __GST_BITS_WRITER_ALIGNMENT_MASK) == 0));
162 clear_pos = ((bitwriter->bit_size + 7) >> 3);
163 bitwriter->data = (guint8 *) g_realloc (bitwriter->data, (new_bit_size >> 3));
164 memset (bitwriter->data + clear_pos, 0, (new_bit_size >> 3) - clear_pos);
165 bitwriter->bit_capacity = new_bit_size;
169 #undef __GST_BITS_WRITER_ALIGNMENT_MASK
170 #undef __GST_BITS_WRITER_ALIGNED
172 #define __GST_BIT_WRITER_WRITE_BITS_UNCHECKED(bits) \
174 gst_bit_writer_put_bits_uint##bits##_unchecked( \
175 GstBitWriter *bitwriter, \
180 guint byte_pos, bit_offset; \
184 byte_pos = (bitwriter->bit_size >> 3); \
185 bit_offset = (bitwriter->bit_size & 0x07); \
186 cur_byte = bitwriter->data + byte_pos; \
187 g_assert (nbits <= bits); \
188 g_assert( bit_offset < 8 && \
189 bitwriter->bit_size <= bitwriter->bit_capacity); \
192 fill_bits = ((8 - bit_offset) < nbits ? (8 - bit_offset) : nbits); \
193 nbits -= fill_bits; \
194 bitwriter->bit_size += fill_bits; \
196 *cur_byte |= (((value >> nbits) & _gst_bit_writer_bit_filling_mask[fill_bits]) \
197 << (8 - bit_offset - fill_bits)); \
201 g_assert(cur_byte <= \
202 (bitwriter->data + (bitwriter->bit_capacity >> 3))); \
205 __GST_BIT_WRITER_WRITE_BITS_UNCHECKED (8)
206 __GST_BIT_WRITER_WRITE_BITS_UNCHECKED (16)
207 __GST_BIT_WRITER_WRITE_BITS_UNCHECKED (32)
208 __GST_BIT_WRITER_WRITE_BITS_UNCHECKED (64)
209 #undef __GST_BIT_WRITER_WRITE_BITS_UNCHECKED
212 gst_bit_writer_get_size_unchecked (const GstBitWriter * bitwriter)
214 return GST_BIT_WRITER_BIT_SIZE (bitwriter);
217 static inline guint8 *
218 gst_bit_writer_get_data_unchecked (const GstBitWriter * bitwriter)
220 return GST_BIT_WRITER_DATA (bitwriter);
223 static inline gboolean
224 gst_bit_writer_set_pos_unchecked (GstBitWriter * bitwriter, guint pos)
226 GST_BIT_WRITER_BIT_SIZE (bitwriter) = pos;
231 gst_bit_writer_get_remaining_unchecked (const GstBitWriter * bitwriter)
233 return bitwriter->bit_capacity - bitwriter->bit_size;
237 gst_bit_writer_put_bytes_unchecked (GstBitWriter * bitwriter,
238 const guint8 * data, guint nbytes)
240 if ((bitwriter->bit_size & 0x07) == 0) {
241 memcpy (&bitwriter->data[bitwriter->bit_size >> 3], data, nbytes);
242 bitwriter->bit_size += (nbytes << 3);
246 gst_bit_writer_put_bits_uint8_unchecked (bitwriter, *data, 8);
254 gst_bit_writer_align_bytes_unchecked (GstBitWriter * bitwriter,
257 guint32 bit_offset, bit_left;
260 bit_offset = (bitwriter->bit_size & 0x07);
264 bit_left = 8 - bit_offset;
266 value = _gst_bit_writer_bit_filling_mask[bit_left];
267 gst_bit_writer_put_bits_uint8_unchecked (bitwriter, value, bit_left);
270 #define __GST_BIT_WRITER_WRITE_BITS_INLINE(bits) \
271 static inline gboolean \
272 _gst_bit_writer_put_bits_uint##bits##_inline( \
273 GstBitWriter *bitwriter, \
278 g_return_val_if_fail(bitwriter != NULL, FALSE); \
279 g_return_val_if_fail(nbits != 0, FALSE); \
280 g_return_val_if_fail(nbits <= bits, FALSE); \
282 if (!_gst_bit_writer_check_remaining(bitwriter, nbits)) \
284 gst_bit_writer_put_bits_uint##bits##_unchecked(bitwriter, value, nbits); \
288 __GST_BIT_WRITER_WRITE_BITS_INLINE (8)
289 __GST_BIT_WRITER_WRITE_BITS_INLINE (16)
290 __GST_BIT_WRITER_WRITE_BITS_INLINE (32)
291 __GST_BIT_WRITER_WRITE_BITS_INLINE (64)
292 #undef __GST_BIT_WRITER_WRITE_BITS_INLINE
295 _gst_bit_writer_get_size_inline (const GstBitWriter * bitwriter)
297 g_return_val_if_fail (bitwriter != NULL, 0);
299 return gst_bit_writer_get_size_unchecked (bitwriter);
302 static inline guint8 *
303 _gst_bit_writer_get_data_inline (const GstBitWriter * bitwriter)
305 g_return_val_if_fail (bitwriter != NULL, NULL);
307 return gst_bit_writer_get_data_unchecked (bitwriter);
310 static inline gboolean
311 _gst_bit_writer_set_pos_inline (GstBitWriter * bitwriter, guint pos)
313 g_return_val_if_fail (bitwriter != NULL, FALSE);
314 g_return_val_if_fail (pos <= bitwriter->bit_capacity, FALSE);
316 return gst_bit_writer_set_pos_unchecked (bitwriter, pos);
320 _gst_bit_writer_get_remaining_inline (const GstBitWriter * bitwriter)
322 g_return_val_if_fail (bitwriter != NULL, 0);
323 g_return_val_if_fail (bitwriter->bit_size < bitwriter->bit_capacity, 0);
325 return gst_bit_writer_get_remaining_unchecked (bitwriter);
328 static inline gboolean
329 _gst_bit_writer_put_bytes_inline (GstBitWriter * bitwriter,
330 const guint8 * data, guint nbytes)
332 g_return_val_if_fail (bitwriter != NULL, FALSE);
333 g_return_val_if_fail (data != NULL, FALSE);
334 g_return_val_if_fail (nbytes, FALSE);
336 if (!_gst_bit_writer_check_remaining (bitwriter, nbytes * 8))
339 gst_bit_writer_put_bytes_unchecked (bitwriter, data, nbytes);
343 static inline gboolean
344 _gst_bit_writer_align_bytes_inline (GstBitWriter * bitwriter,
347 g_return_val_if_fail (bitwriter != NULL, FALSE);
348 g_return_val_if_fail ((trailing_bit == 0 || trailing_bit == 1), FALSE);
349 g_return_val_if_fail (((bitwriter->bit_size + 7) & (~7)) <=
350 bitwriter->bit_capacity, FALSE);
352 gst_bit_writer_align_bytes_unchecked (bitwriter, trailing_bit);
356 #ifndef GST_BIT_WRITER_DISABLE_INLINES
357 #define gst_bit_writer_get_size(bitwriter) \
358 _gst_bit_writer_get_size_inline(bitwriter)
359 #define gst_bit_writer_get_data(bitwriter) \
360 _gst_bit_writer_get_data_inline(bitwriter)
361 #define gst_bit_writer_set_pos(bitwriter, pos) \
362 G_LIKELY (_gst_bit_writer_set_pos_inline (bitwriter, pos))
363 #define gst_bit_writer_get_remaining(bitwriter) \
364 _gst_bit_writer_get_remaining_inline(bitwriter)
366 #define gst_bit_writer_put_bits_uint8(bitwriter, value, nbits) \
367 G_LIKELY (_gst_bit_writer_put_bits_uint8_inline (bitwriter, value, nbits))
368 #define gst_bit_writer_put_bits_uint16(bitwriter, value, nbits) \
369 G_LIKELY (_gst_bit_writer_put_bits_uint16_inline (bitwriter, value, nbits))
370 #define gst_bit_writer_put_bits_uint32(bitwriter, value, nbits) \
371 G_LIKELY (_gst_bit_writer_put_bits_uint32_inline (bitwriter, value, nbits))
372 #define gst_bit_writer_put_bits_uint64(bitwriter, value, nbits) \
373 G_LIKELY (_gst_bit_writer_put_bits_uint64_inline (bitwriter, value, nbits))
375 #define gst_bit_writer_put_bytes(bitwriter, data, nbytes) \
376 G_LIKELY (_gst_bit_writer_put_bytes_inline (bitwriter, data, nbytes))
378 #define gst_bit_writer_align_bytes(bitwriter, trailing_bit) \
379 G_LIKELY (_gst_bit_writer_align_bytes_inline(bitwriter, trailing_bit))
384 #endif /* GST_BIT_WRITER_H */