Update for g_type_class_add_private() deprecation in recent GLib
[platform/upstream/gstreamer.git] / libs / gst / base / gstbitwriter.h
1 /*
2  *  gstbitwriter.h - bitstream writer
3  *
4  *  Copyright (C) 2013 Intel Corporation
5  *  Copyright (C) 2018 Igalia, S. L.
6  *
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.
11  *
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.
16  *
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
21  */
22
23 #ifndef GST_BIT_WRITER_H
24 #define GST_BIT_WRITER_H
25
26 #include <gst/gst.h>
27 #include <gst/base/base-prelude.h>
28
29 #include <string.h>
30
31 G_BEGIN_DECLS
32
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))
36
37 typedef struct _GstBitWriter GstBitWriter;
38
39 /**
40  * GstBitWriter:
41  * @data: Allocated @data for bit writer to write
42  * @bit_size: Size of written @data in bits
43  *
44  * Private:
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
48  *                is freed
49  *
50  * A bit writer instance.
51  */
52 struct _GstBitWriter
53 {
54   guint8 *data;
55   guint bit_size;
56
57   /*< private >*/
58   guint bit_capacity;
59   gboolean auto_grow;
60   gboolean owned;
61   gpointer _gst_reserved[GST_PADDING];
62 };
63
64 GST_BASE_API
65 GstBitWriter *  gst_bit_writer_new              (void) G_GNUC_MALLOC;
66
67 GST_BASE_API
68 GstBitWriter *  gst_bit_writer_new_with_size    (guint32 size, gboolean fixed) G_GNUC_MALLOC;
69
70 GST_BASE_API
71 GstBitWriter *  gst_bit_writer_new_with_data    (guint8 *data, guint size,
72                                                  gboolean initialized) G_GNUC_MALLOC;
73
74 GST_BASE_API
75 void            gst_bit_writer_free             (GstBitWriter *bitwriter);
76
77 GST_BASE_API
78 guint8 *        gst_bit_writer_free_and_get_data (GstBitWriter *bitwriter);
79
80 GST_BASE_API
81 GstBuffer *     gst_bit_writer_free_and_get_buffer (GstBitWriter *bitwriter);
82
83 GST_BASE_API
84 void            gst_bit_writer_init             (GstBitWriter *bitwriter);
85
86 GST_BASE_API
87 void            gst_bit_writer_init_with_size   (GstBitWriter *bitwriter,
88                                                  guint32 size, gboolean fixed);
89
90 GST_BASE_API
91 void            gst_bit_writer_init_with_data   (GstBitWriter *bitwriter,  guint8 *data,
92                                                  guint size, gboolean initialized);
93
94 GST_BASE_API
95 void            gst_bit_writer_reset            (GstBitWriter *bitwriter);
96
97 GST_BASE_API
98 guint8 *        gst_bit_writer_reset_and_get_data (GstBitWriter *bitwriter);
99
100 GST_BASE_API
101 GstBuffer *     gst_bit_writer_reset_and_get_buffer (GstBitWriter *bitwriter);
102
103 GST_BASE_API
104 guint           gst_bit_writer_get_size         (const GstBitWriter *bitwriter);
105
106 GST_BASE_API
107 guint8 *        gst_bit_writer_get_data         (const GstBitWriter *bitwriter);
108
109 GST_BASE_API
110 gboolean        gst_bit_writer_set_pos          (GstBitWriter *bitwriter, guint pos);
111
112 GST_BASE_API
113 guint           gst_bit_writer_get_remaining    (const GstBitWriter *bitwriter);
114
115 GST_BASE_API
116 gboolean        gst_bit_writer_put_bits_uint8   (GstBitWriter *bitwriter, guint8 value,
117                                                  guint nbits);
118
119 GST_BASE_API
120 gboolean        gst_bit_writer_put_bits_uint16  (GstBitWriter *bitwriter, guint16 value,
121                                                  guint nbits);
122
123 GST_BASE_API
124 gboolean        gst_bit_writer_put_bits_uint32  (GstBitWriter *bitwriter, guint32 value,
125                                                  guint nbits);
126
127 GST_BASE_API
128 gboolean        gst_bit_writer_put_bits_uint64  (GstBitWriter *bitwriter, guint64 value,
129                                                  guint nbits);
130
131 GST_BASE_API
132 gboolean        gst_bit_writer_put_bytes        (GstBitWriter *bitwriter, const guint8 *data,
133                                                  guint nbytes);
134
135 GST_BASE_API
136 gboolean        gst_bit_writer_align_bytes      (GstBitWriter *bitwriter, guint8 trailing_bit);
137
138 static const guint8 _gst_bit_writer_bit_filling_mask[9] = {
139     0x00, 0x01, 0x03, 0x07,
140     0x0F, 0x1F, 0x3F, 0x7F,
141     0xFF
142 };
143
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))
148
149 static inline gboolean
150 _gst_bit_writer_check_remaining (GstBitWriter * bitwriter, guint32 bits)
151 {
152   guint32 new_bit_size = bits + bitwriter->bit_size;
153   guint32 clear_pos;
154
155   g_assert (bitwriter->bit_size <= bitwriter->bit_capacity);
156   if (new_bit_size <= bitwriter->bit_capacity)
157     return TRUE;
158
159   if (!bitwriter->auto_grow)
160     return FALSE;
161
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;
170   return TRUE;
171 }
172
173 #undef __GST_BITS_WRITER_ALIGNMENT_MASK
174 #undef __GST_BITS_WRITER_ALIGNED
175
176 #define __GST_BIT_WRITER_WRITE_BITS_UNCHECKED(bits) \
177 static inline void \
178 gst_bit_writer_put_bits_uint##bits##_unchecked( \
179     GstBitWriter *bitwriter, \
180     guint##bits value, \
181     guint nbits \
182 ) \
183 { \
184     guint byte_pos, bit_offset; \
185     guint8  *cur_byte; \
186     guint fill_bits; \
187     \
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); \
194     \
195     while (nbits) { \
196         fill_bits = ((8 - bit_offset) < nbits ? (8 - bit_offset) : nbits); \
197         nbits -= fill_bits; \
198         bitwriter->bit_size += fill_bits; \
199         \
200         *cur_byte |= (((value >> nbits) & _gst_bit_writer_bit_filling_mask[fill_bits]) \
201                       << (8 - bit_offset - fill_bits)); \
202         ++cur_byte; \
203         bit_offset = 0; \
204     } \
205     g_assert(cur_byte <= \
206            (bitwriter->data + (bitwriter->bit_capacity >> 3))); \
207 }
208
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
214
215 static inline guint
216 gst_bit_writer_get_size_unchecked (const GstBitWriter * bitwriter)
217 {
218   return GST_BIT_WRITER_BIT_SIZE (bitwriter);
219 }
220
221 static inline guint8 *
222 gst_bit_writer_get_data_unchecked (const GstBitWriter * bitwriter)
223 {
224   return GST_BIT_WRITER_DATA (bitwriter);
225 }
226
227 static inline gboolean
228 gst_bit_writer_set_pos_unchecked (GstBitWriter * bitwriter, guint pos)
229 {
230   GST_BIT_WRITER_BIT_SIZE (bitwriter) = pos;
231   return TRUE;
232 }
233
234 static inline guint
235 gst_bit_writer_get_remaining_unchecked (const GstBitWriter * bitwriter)
236 {
237   return bitwriter->bit_capacity - bitwriter->bit_size;
238 }
239
240 static inline void
241 gst_bit_writer_put_bytes_unchecked (GstBitWriter * bitwriter,
242     const guint8 * data, guint nbytes)
243 {
244   if ((bitwriter->bit_size & 0x07) == 0) {
245     memcpy (&bitwriter->data[bitwriter->bit_size >> 3], data, nbytes);
246     bitwriter->bit_size += (nbytes << 3);
247   } else {
248     g_assert (0);
249     while (nbytes) {
250       gst_bit_writer_put_bits_uint8_unchecked (bitwriter, *data, 8);
251       --nbytes;
252       ++data;
253     }
254   }
255 }
256
257 static inline void
258 gst_bit_writer_align_bytes_unchecked (GstBitWriter * bitwriter,
259     guint8 trailing_bit)
260 {
261   guint32 bit_offset, bit_left;
262   guint8 value = 0;
263
264   bit_offset = (bitwriter->bit_size & 0x07);
265   if (!bit_offset)
266     return;
267
268   bit_left = 8 - bit_offset;
269   if (trailing_bit)
270     value = _gst_bit_writer_bit_filling_mask[bit_left];
271   return gst_bit_writer_put_bits_uint8_unchecked (bitwriter, value, bit_left);
272 }
273
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, \
278     guint##bits value, \
279     guint nbits \
280 ) \
281 { \
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); \
285     \
286     if (!_gst_bit_writer_check_remaining(bitwriter, nbits)) \
287         return FALSE; \
288     gst_bit_writer_put_bits_uint##bits##_unchecked(bitwriter, value, nbits); \
289     return TRUE; \
290 }
291
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
297
298 static inline guint
299 _gst_bit_writer_get_size_inline (const GstBitWriter * bitwriter)
300 {
301   g_return_val_if_fail (bitwriter != NULL, 0);
302
303   return gst_bit_writer_get_size_unchecked (bitwriter);
304 }
305
306 static inline guint8 *
307 _gst_bit_writer_get_data_inline (const GstBitWriter * bitwriter)
308 {
309   g_return_val_if_fail (bitwriter != NULL, NULL);
310
311   return gst_bit_writer_get_data_unchecked (bitwriter);
312 }
313
314 static inline gboolean
315 _gst_bit_writer_set_pos_inline (GstBitWriter * bitwriter, guint pos)
316 {
317   g_return_val_if_fail (bitwriter != NULL, FALSE);
318   g_return_val_if_fail (pos <= bitwriter->bit_capacity, FALSE);
319
320   return gst_bit_writer_set_pos_unchecked (bitwriter, pos);
321 }
322
323 static inline guint
324 _gst_bit_writer_get_remaining_inline (const GstBitWriter * bitwriter)
325 {
326   g_return_val_if_fail (bitwriter != NULL, 0);
327   g_return_val_if_fail (bitwriter->bit_size < bitwriter->bit_capacity, 0);
328
329   return gst_bit_writer_get_remaining_unchecked (bitwriter);
330 }
331
332 static inline gboolean
333 _gst_bit_writer_put_bytes_inline (GstBitWriter * bitwriter,
334     const guint8 * data, guint nbytes)
335 {
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);
339
340   if (!_gst_bit_writer_check_remaining (bitwriter, nbytes * 8))
341     return FALSE;
342
343   gst_bit_writer_put_bytes_unchecked (bitwriter, data, nbytes);
344   return TRUE;
345 }
346
347 static inline gboolean
348 _gst_bit_writer_align_bytes_inline (GstBitWriter * bitwriter,
349     guint8 trailing_bit)
350 {
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);
355
356   gst_bit_writer_align_bytes_unchecked (bitwriter, trailing_bit);
357   return TRUE;
358 }
359
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)
369
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))
378
379 #define gst_bit_writer_put_bytes(bitwriter, data, nbytes) \
380     G_LIKELY (_gst_bit_writer_put_bytes_inline (bitwriter, data, nbytes))
381
382 #define gst_bit_writer_align_bytes(bitwriter, trailing_bit) \
383     G_LIKELY (_gst_bit_writer_align_bytes_inline(bitwriter, trailing_bit))
384 #endif
385
386 G_END_DECLS
387
388 #endif /* GST_BIT_WRITER_H */