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.
52 guint bit_capacity; /* Capacity of the allocated data */
53 gboolean auto_grow; /* Whether space can auto grow */
55 gpointer _gst_reserved[GST_PADDING];
59 GstBitWriter * gst_bit_writer_new (void) G_GNUC_MALLOC;
62 GstBitWriter * gst_bit_writer_new_with_size (guint32 size, gboolean fixed) G_GNUC_MALLOC;
65 GstBitWriter * gst_bit_writer_new_with_data (guint8 *data, guint size,
66 gboolean initialized) G_GNUC_MALLOC;
69 void gst_bit_writer_free (GstBitWriter *bitwriter);
72 guint8 * gst_bit_writer_free_and_get_data (GstBitWriter *bitwriter);
75 GstBuffer * gst_bit_writer_free_and_get_buffer (GstBitWriter *bitwriter);
78 void gst_bit_writer_init (GstBitWriter *bitwriter);
81 void gst_bit_writer_init_with_size (GstBitWriter *bitwriter,
82 guint32 size, gboolean fixed);
85 void gst_bit_writer_init_with_data (GstBitWriter *bitwriter, guint8 *data,
86 guint size, gboolean initialized);
89 void gst_bit_writer_reset (GstBitWriter *bitwriter);
92 guint8 * gst_bit_writer_reset_and_get_data (GstBitWriter *bitwriter);
95 GstBuffer * gst_bit_writer_reset_and_get_buffer (GstBitWriter *bitwriter);
98 guint gst_bit_writer_get_size (const GstBitWriter *bitwriter);
101 guint8 * gst_bit_writer_get_data (const GstBitWriter *bitwriter);
104 gboolean gst_bit_writer_set_pos (GstBitWriter *bitwriter, guint pos);
107 guint gst_bit_writer_get_remaining (const GstBitWriter *bitwriter);
110 gboolean gst_bit_writer_put_bits_uint8 (GstBitWriter *bitwriter, guint8 value,
114 gboolean gst_bit_writer_put_bits_uint16 (GstBitWriter *bitwriter, guint16 value,
118 gboolean gst_bit_writer_put_bits_uint32 (GstBitWriter *bitwriter, guint32 value,
122 gboolean gst_bit_writer_put_bits_uint64 (GstBitWriter *bitwriter, guint64 value,
126 gboolean gst_bit_writer_put_bytes (GstBitWriter *bitwriter, const guint8 *data,
130 gboolean gst_bit_writer_align_bytes (GstBitWriter *bitwriter, guint8 trailing_bit);
132 static const guint8 _gst_bit_writer_bit_filling_mask[9] = {
133 0x00, 0x01, 0x03, 0x07,
134 0x0F, 0x1F, 0x3F, 0x7F,
138 /* Aligned to 256 bytes */
139 #define __GST_BITS_WRITER_ALIGNMENT_MASK 2047
140 #define __GST_BITS_WRITER_ALIGNED(bitsize) \
141 (((bitsize) + __GST_BITS_WRITER_ALIGNMENT_MASK)&(~__GST_BITS_WRITER_ALIGNMENT_MASK))
143 static inline gboolean
144 _gst_bit_writer_check_remaining (GstBitWriter * bitwriter, guint32 bits)
146 guint32 new_bit_size = bits + bitwriter->bit_size;
149 g_assert (bitwriter->bit_size <= bitwriter->bit_capacity);
150 if (new_bit_size <= bitwriter->bit_capacity)
153 if (!bitwriter->auto_grow)
156 /* auto grow space */
157 new_bit_size = __GST_BITS_WRITER_ALIGNED (new_bit_size);
158 g_assert (new_bit_size
159 && ((new_bit_size & __GST_BITS_WRITER_ALIGNMENT_MASK) == 0));
160 clear_pos = ((bitwriter->bit_size + 7) >> 3);
161 bitwriter->data = g_realloc (bitwriter->data, (new_bit_size >> 3));
162 memset (bitwriter->data + clear_pos, 0, (new_bit_size >> 3) - clear_pos);
163 bitwriter->bit_capacity = new_bit_size;
167 #undef __GST_BITS_WRITER_ALIGNMENT_MASK
168 #undef __GST_BITS_WRITER_ALIGNED
170 #define __GST_BIT_WRITER_WRITE_BITS_UNCHECKED(bits) \
172 gst_bit_writer_put_bits_uint##bits##_unchecked( \
173 GstBitWriter *bitwriter, \
178 guint byte_pos, bit_offset; \
182 byte_pos = (bitwriter->bit_size >> 3); \
183 bit_offset = (bitwriter->bit_size & 0x07); \
184 cur_byte = bitwriter->data + byte_pos; \
185 g_assert (nbits <= bits); \
186 g_assert( bit_offset < 8 && \
187 bitwriter->bit_size <= bitwriter->bit_capacity); \
190 fill_bits = ((8 - bit_offset) < nbits ? (8 - bit_offset) : nbits); \
191 nbits -= fill_bits; \
192 bitwriter->bit_size += fill_bits; \
194 *cur_byte |= (((value >> nbits) & _gst_bit_writer_bit_filling_mask[fill_bits]) \
195 << (8 - bit_offset - fill_bits)); \
199 g_assert(cur_byte <= \
200 (bitwriter->data + (bitwriter->bit_capacity >> 3))); \
203 __GST_BIT_WRITER_WRITE_BITS_UNCHECKED (8)
204 __GST_BIT_WRITER_WRITE_BITS_UNCHECKED (16)
205 __GST_BIT_WRITER_WRITE_BITS_UNCHECKED (32)
206 __GST_BIT_WRITER_WRITE_BITS_UNCHECKED (64)
207 #undef __GST_BIT_WRITER_WRITE_BITS_UNCHECKED
210 gst_bit_writer_get_size_unchecked (const GstBitWriter * bitwriter)
212 return GST_BIT_WRITER_BIT_SIZE (bitwriter);
215 static inline guint8 *
216 gst_bit_writer_get_data_unchecked (const GstBitWriter * bitwriter)
218 return GST_BIT_WRITER_DATA (bitwriter);
221 static inline gboolean
222 gst_bit_writer_set_pos_unchecked (GstBitWriter * bitwriter, guint pos)
224 GST_BIT_WRITER_BIT_SIZE (bitwriter) = pos;
229 gst_bit_writer_get_remaining_unchecked (const GstBitWriter * bitwriter)
231 return bitwriter->bit_capacity - bitwriter->bit_size;
235 gst_bit_writer_put_bytes_unchecked (GstBitWriter * bitwriter,
236 const guint8 * data, guint nbytes)
238 if ((bitwriter->bit_size & 0x07) == 0) {
239 memcpy (&bitwriter->data[bitwriter->bit_size >> 3], data, nbytes);
240 bitwriter->bit_size += (nbytes << 3);
244 gst_bit_writer_put_bits_uint8_unchecked (bitwriter, *data, 8);
252 gst_bit_writer_align_bytes_unchecked (GstBitWriter * bitwriter,
255 guint32 bit_offset, bit_left;
258 bit_offset = (bitwriter->bit_size & 0x07);
262 bit_left = 8 - bit_offset;
264 value = _gst_bit_writer_bit_filling_mask[bit_left];
265 return gst_bit_writer_put_bits_uint8_unchecked (bitwriter, value, bit_left);
268 #define __GST_BIT_WRITER_WRITE_BITS_INLINE(bits) \
269 static inline gboolean \
270 _gst_bit_writer_put_bits_uint##bits##_inline( \
271 GstBitWriter *bitwriter, \
276 g_return_val_if_fail(bitwriter != NULL, FALSE); \
277 g_return_val_if_fail(nbits != 0, FALSE); \
278 g_return_val_if_fail(nbits <= bits, FALSE); \
280 if (!_gst_bit_writer_check_remaining(bitwriter, nbits)) \
282 gst_bit_writer_put_bits_uint##bits##_unchecked(bitwriter, value, nbits); \
286 __GST_BIT_WRITER_WRITE_BITS_INLINE (8)
287 __GST_BIT_WRITER_WRITE_BITS_INLINE (16)
288 __GST_BIT_WRITER_WRITE_BITS_INLINE (32)
289 __GST_BIT_WRITER_WRITE_BITS_INLINE (64)
290 #undef __GST_BIT_WRITER_WRITE_BITS_INLINE
293 _gst_bit_writer_get_size_inline (const GstBitWriter * bitwriter)
295 g_return_val_if_fail (bitwriter != NULL, 0);
297 return gst_bit_writer_get_size_unchecked (bitwriter);
300 static inline guint8 *
301 _gst_bit_writer_get_data_inline (const GstBitWriter * bitwriter)
303 g_return_val_if_fail (bitwriter != NULL, NULL);
305 return gst_bit_writer_get_data_unchecked (bitwriter);
308 static inline gboolean
309 _gst_bit_writer_set_pos_inline (GstBitWriter * bitwriter, guint pos)
311 g_return_val_if_fail (bitwriter != NULL, FALSE);
312 g_return_val_if_fail (pos <= bitwriter->bit_capacity, FALSE);
314 return gst_bit_writer_set_pos_unchecked (bitwriter, pos);
318 _gst_bit_writer_get_remaining_inline (const GstBitWriter * bitwriter)
320 g_return_val_if_fail (bitwriter != NULL, 0);
321 g_return_val_if_fail (bitwriter->bit_size < bitwriter->bit_capacity, 0);
323 return gst_bit_writer_get_remaining_unchecked (bitwriter);
326 static inline gboolean
327 _gst_bit_writer_put_bytes_inline (GstBitWriter * bitwriter,
328 const guint8 * data, guint nbytes)
330 g_return_val_if_fail (bitwriter != NULL, FALSE);
331 g_return_val_if_fail (data != NULL, FALSE);
332 g_return_val_if_fail (nbytes, FALSE);
334 if (!_gst_bit_writer_check_remaining (bitwriter, nbytes * 8))
337 gst_bit_writer_put_bytes_unchecked (bitwriter, data, nbytes);
341 static inline gboolean
342 _gst_bit_writer_align_bytes_inline (GstBitWriter * bitwriter,
345 g_return_val_if_fail (bitwriter != NULL, FALSE);
346 g_return_val_if_fail ((trailing_bit == 0 || trailing_bit == 1), FALSE);
347 g_return_val_if_fail (((bitwriter->bit_size + 7) & (~7)) <=
348 bitwriter->bit_capacity, FALSE);
350 gst_bit_writer_align_bytes_unchecked (bitwriter, trailing_bit);
354 #ifndef GST_BIT_WRITER_DISABLE_INLINES
355 #define gst_bit_writer_get_size(bitwriter) \
356 _gst_bit_writer_get_size_inline(bitwriter)
357 #define gst_bit_writer_get_data(bitwriter) \
358 _gst_bit_writer_get_data_inline(bitwriter)
359 #define gst_bit_writer_set_pos(bitwriter, pos) \
360 G_LIKELY (_gst_bit_writer_set_pos_inline (bitwriter, pos))
361 #define gst_bit_writer_get_remaining(bitwriter) \
362 _gst_bit_writer_get_remaining_inline(bitwriter)
364 #define gst_bit_writer_put_bits_uint8(bitwriter, value, nbits) \
365 G_LIKELY (_gst_bit_writer_put_bits_uint8_inline (bitwriter, value, nbits))
366 #define gst_bit_writer_put_bits_uint16(bitwriter, value, nbits) \
367 G_LIKELY (_gst_bit_writer_put_bits_uint16_inline (bitwriter, value, nbits))
368 #define gst_bit_writer_put_bits_uint32(bitwriter, value, nbits) \
369 G_LIKELY (_gst_bit_writer_put_bits_uint32_inline (bitwriter, value, nbits))
370 #define gst_bit_writer_put_bits_uint64(bitwriter, value, nbits) \
371 G_LIKELY (_gst_bit_writer_put_bits_uint64_inline (bitwriter, value, nbits))
373 #define gst_bit_writer_put_bytes(bitwriter, data, nbytes) \
374 G_LIKELY (_gst_bit_writer_put_bytes_inline (bitwriter, data, nbytes))
376 #define gst_bit_writer_align_bytes(bitwriter, trailing_bit) \
377 G_LIKELY (_gst_bit_writer_align_bytes_inline(bitwriter, trailing_bit))
382 #endif /* GST_BIT_WRITER_H */