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
45 * @bit_capacity: Capacity of the allocated @data
46 * @auto_grow: @data space can auto grow
47 * @destroy_data: The #GDestroyNotify function called with #data when the memory
50 * A bit writer instance.
61 gpointer _gst_reserved[GST_PADDING];
65 GstBitWriter * gst_bit_writer_new (void) G_GNUC_MALLOC;
68 GstBitWriter * gst_bit_writer_new_with_size (guint32 size, gboolean fixed) G_GNUC_MALLOC;
71 GstBitWriter * gst_bit_writer_new_with_data (guint8 *data, guint size,
72 gboolean initialized) G_GNUC_MALLOC;
75 void gst_bit_writer_free (GstBitWriter *bitwriter);
78 guint8 * gst_bit_writer_free_and_get_data (GstBitWriter *bitwriter);
81 GstBuffer * gst_bit_writer_free_and_get_buffer (GstBitWriter *bitwriter);
84 void gst_bit_writer_init (GstBitWriter *bitwriter);
87 void gst_bit_writer_init_with_size (GstBitWriter *bitwriter,
88 guint32 size, gboolean fixed);
91 void gst_bit_writer_init_with_data (GstBitWriter *bitwriter, guint8 *data,
92 guint size, gboolean initialized);
95 void gst_bit_writer_reset (GstBitWriter *bitwriter);
98 guint8 * gst_bit_writer_reset_and_get_data (GstBitWriter *bitwriter);
101 GstBuffer * gst_bit_writer_reset_and_get_buffer (GstBitWriter *bitwriter);
104 guint gst_bit_writer_get_size (const GstBitWriter *bitwriter);
107 guint8 * gst_bit_writer_get_data (const GstBitWriter *bitwriter);
110 gboolean gst_bit_writer_set_pos (GstBitWriter *bitwriter, guint pos);
113 guint gst_bit_writer_get_remaining (const GstBitWriter *bitwriter);
116 gboolean gst_bit_writer_put_bits_uint8 (GstBitWriter *bitwriter, guint8 value,
120 gboolean gst_bit_writer_put_bits_uint16 (GstBitWriter *bitwriter, guint16 value,
124 gboolean gst_bit_writer_put_bits_uint32 (GstBitWriter *bitwriter, guint32 value,
128 gboolean gst_bit_writer_put_bits_uint64 (GstBitWriter *bitwriter, guint64 value,
132 gboolean gst_bit_writer_put_bytes (GstBitWriter *bitwriter, const guint8 *data,
136 gboolean gst_bit_writer_align_bytes (GstBitWriter *bitwriter, guint8 trailing_bit);
138 static const guint8 _gst_bit_writer_bit_filling_mask[9] = {
139 0x00, 0x01, 0x03, 0x07,
140 0x0F, 0x1F, 0x3F, 0x7F,
144 /* Aligned to 256 bytes */
145 #define __GST_BITS_WRITER_ALIGNMENT_MASK 2047
146 #define __GST_BITS_WRITER_ALIGNED(bitsize) \
147 (((bitsize) + __GST_BITS_WRITER_ALIGNMENT_MASK)&(~__GST_BITS_WRITER_ALIGNMENT_MASK))
149 static inline gboolean
150 _gst_bit_writer_check_remaining (GstBitWriter * bitwriter, guint32 bits)
152 guint32 new_bit_size = bits + bitwriter->bit_size;
155 g_assert (bitwriter->bit_size <= bitwriter->bit_capacity);
156 if (new_bit_size <= bitwriter->bit_capacity)
159 if (!bitwriter->auto_grow)
162 /* auto grow space */
163 new_bit_size = __GST_BITS_WRITER_ALIGNED (new_bit_size);
164 g_assert (new_bit_size
165 && ((new_bit_size & __GST_BITS_WRITER_ALIGNMENT_MASK) == 0));
166 clear_pos = ((bitwriter->bit_size + 7) >> 3);
167 bitwriter->data = g_realloc (bitwriter->data, (new_bit_size >> 3));
168 memset (bitwriter->data + clear_pos, 0, (new_bit_size >> 3) - clear_pos);
169 bitwriter->bit_capacity = new_bit_size;
173 #undef __GST_BITS_WRITER_ALIGNMENT_MASK
174 #undef __GST_BITS_WRITER_ALIGNED
176 #define __GST_BIT_WRITER_WRITE_BITS_UNCHECKED(bits) \
178 gst_bit_writer_put_bits_uint##bits##_unchecked( \
179 GstBitWriter *bitwriter, \
184 guint byte_pos, bit_offset; \
188 byte_pos = (bitwriter->bit_size >> 3); \
189 bit_offset = (bitwriter->bit_size & 0x07); \
190 cur_byte = bitwriter->data + byte_pos; \
191 g_assert (nbits <= bits); \
192 g_assert( bit_offset < 8 && \
193 bitwriter->bit_size <= bitwriter->bit_capacity); \
196 fill_bits = ((8 - bit_offset) < nbits ? (8 - bit_offset) : nbits); \
197 nbits -= fill_bits; \
198 bitwriter->bit_size += fill_bits; \
200 *cur_byte |= (((value >> nbits) & _gst_bit_writer_bit_filling_mask[fill_bits]) \
201 << (8 - bit_offset - fill_bits)); \
205 g_assert(cur_byte <= \
206 (bitwriter->data + (bitwriter->bit_capacity >> 3))); \
209 __GST_BIT_WRITER_WRITE_BITS_UNCHECKED (8)
210 __GST_BIT_WRITER_WRITE_BITS_UNCHECKED (16)
211 __GST_BIT_WRITER_WRITE_BITS_UNCHECKED (32)
212 __GST_BIT_WRITER_WRITE_BITS_UNCHECKED (64)
213 #undef __GST_BIT_WRITER_WRITE_BITS_UNCHECKED
216 gst_bit_writer_get_size_unchecked (const GstBitWriter * bitwriter)
218 return GST_BIT_WRITER_BIT_SIZE (bitwriter);
221 static inline guint8 *
222 gst_bit_writer_get_data_unchecked (const GstBitWriter * bitwriter)
224 return GST_BIT_WRITER_DATA (bitwriter);
227 static inline gboolean
228 gst_bit_writer_set_pos_unchecked (GstBitWriter * bitwriter, guint pos)
230 GST_BIT_WRITER_BIT_SIZE (bitwriter) = pos;
235 gst_bit_writer_get_remaining_unchecked (const GstBitWriter * bitwriter)
237 return bitwriter->bit_capacity - bitwriter->bit_size;
241 gst_bit_writer_put_bytes_unchecked (GstBitWriter * bitwriter,
242 const guint8 * data, guint nbytes)
244 if ((bitwriter->bit_size & 0x07) == 0) {
245 memcpy (&bitwriter->data[bitwriter->bit_size >> 3], data, nbytes);
246 bitwriter->bit_size += (nbytes << 3);
250 gst_bit_writer_put_bits_uint8_unchecked (bitwriter, *data, 8);
258 gst_bit_writer_align_bytes_unchecked (GstBitWriter * bitwriter,
261 guint32 bit_offset, bit_left;
264 bit_offset = (bitwriter->bit_size & 0x07);
268 bit_left = 8 - bit_offset;
270 value = _gst_bit_writer_bit_filling_mask[bit_left];
271 return gst_bit_writer_put_bits_uint8_unchecked (bitwriter, value, bit_left);
274 #define __GST_BIT_WRITER_WRITE_BITS_INLINE(bits) \
275 static inline gboolean \
276 _gst_bit_writer_put_bits_uint##bits##_inline( \
277 GstBitWriter *bitwriter, \
282 g_return_val_if_fail(bitwriter != NULL, FALSE); \
283 g_return_val_if_fail(nbits != 0, FALSE); \
284 g_return_val_if_fail(nbits <= bits, FALSE); \
286 if (!_gst_bit_writer_check_remaining(bitwriter, nbits)) \
288 gst_bit_writer_put_bits_uint##bits##_unchecked(bitwriter, value, nbits); \
292 __GST_BIT_WRITER_WRITE_BITS_INLINE (8)
293 __GST_BIT_WRITER_WRITE_BITS_INLINE (16)
294 __GST_BIT_WRITER_WRITE_BITS_INLINE (32)
295 __GST_BIT_WRITER_WRITE_BITS_INLINE (64)
296 #undef __GST_BIT_WRITER_WRITE_BITS_INLINE
299 _gst_bit_writer_get_size_inline (const GstBitWriter * bitwriter)
301 g_return_val_if_fail (bitwriter != NULL, 0);
303 return gst_bit_writer_get_size_unchecked (bitwriter);
306 static inline guint8 *
307 _gst_bit_writer_get_data_inline (const GstBitWriter * bitwriter)
309 g_return_val_if_fail (bitwriter != NULL, NULL);
311 return gst_bit_writer_get_data_unchecked (bitwriter);
314 static inline gboolean
315 _gst_bit_writer_set_pos_inline (GstBitWriter * bitwriter, guint pos)
317 g_return_val_if_fail (bitwriter != NULL, FALSE);
318 g_return_val_if_fail (pos <= bitwriter->bit_capacity, FALSE);
320 return gst_bit_writer_set_pos_unchecked (bitwriter, pos);
324 _gst_bit_writer_get_remaining_inline (const GstBitWriter * bitwriter)
326 g_return_val_if_fail (bitwriter != NULL, 0);
327 g_return_val_if_fail (bitwriter->bit_size < bitwriter->bit_capacity, 0);
329 return gst_bit_writer_get_remaining_unchecked (bitwriter);
332 static inline gboolean
333 _gst_bit_writer_put_bytes_inline (GstBitWriter * bitwriter,
334 const guint8 * data, guint nbytes)
336 g_return_val_if_fail (bitwriter != NULL, FALSE);
337 g_return_val_if_fail (data != NULL, FALSE);
338 g_return_val_if_fail (nbytes, FALSE);
340 if (!_gst_bit_writer_check_remaining (bitwriter, nbytes * 8))
343 gst_bit_writer_put_bytes_unchecked (bitwriter, data, nbytes);
347 static inline gboolean
348 _gst_bit_writer_align_bytes_inline (GstBitWriter * bitwriter,
351 g_return_val_if_fail (bitwriter != NULL, FALSE);
352 g_return_val_if_fail ((trailing_bit == 0 || trailing_bit == 1), FALSE);
353 g_return_val_if_fail (((bitwriter->bit_size + 7) & (~7)) <=
354 bitwriter->bit_capacity, FALSE);
356 gst_bit_writer_align_bytes_unchecked (bitwriter, trailing_bit);
360 #ifndef GST_BIT_WRITER_DISABLE_INLINES
361 #define gst_bit_writer_get_size(bitwriter) \
362 _gst_bit_writer_get_size_inline(bitwriter)
363 #define gst_bit_writer_get_data(bitwriter) \
364 _gst_bit_writer_get_data_inline(bitwriter)
365 #define gst_bit_writer_set_pos(bitwriter, pos) \
366 G_LIKELY (_gst_bit_writer_set_pos_inline (bitwriter, pos))
367 #define gst_bit_writer_get_remaining(bitwriter) \
368 _gst_bit_writer_get_remaining_inline(bitwriter)
370 #define gst_bit_writer_put_bits_uint8(bitwriter, value, nbits) \
371 G_LIKELY (_gst_bit_writer_put_bits_uint8_inline (bitwriter, value, nbits))
372 #define gst_bit_writer_put_bits_uint16(bitwriter, value, nbits) \
373 G_LIKELY (_gst_bit_writer_put_bits_uint16_inline (bitwriter, value, nbits))
374 #define gst_bit_writer_put_bits_uint32(bitwriter, value, nbits) \
375 G_LIKELY (_gst_bit_writer_put_bits_uint32_inline (bitwriter, value, nbits))
376 #define gst_bit_writer_put_bits_uint64(bitwriter, value, nbits) \
377 G_LIKELY (_gst_bit_writer_put_bits_uint64_inline (bitwriter, value, nbits))
379 #define gst_bit_writer_put_bytes(bitwriter, data, nbytes) \
380 G_LIKELY (_gst_bit_writer_put_bytes_inline (bitwriter, data, nbytes))
382 #define gst_bit_writer_align_bytes(bitwriter, trailing_bit) \
383 G_LIKELY (_gst_bit_writer_align_bytes_inline(bitwriter, trailing_bit))
388 #endif /* GST_BIT_WRITER_H */