1 /*
2 * gstbitwriter.c - 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 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #define GST_BIT_WRITER_DISABLE_INLINES
28 #include "gstbitwriter.h"
29
30 #include "gst/glib-compat-private.h"
31
32 /**
33 * SECTION:gstbitwriter
34 * @title: GstBitWriter
35 * @short_description: Writes any number of bits into a memory buffer
36 *
37 * #GstBitWriter provides a bit writer that can write any number of
38 * bits into a memory buffer. It provides functions for writing any
39 * number of bits into 8, 16, 32 and 64 bit variables.
40 */
41
42 /**
43 * gst_bit_writer_new: (skip)
44 *
45 * Creates a new, empty #GstBitWriter instance.
46 *
47 * Free-function: gst_bit_writer_free
48 *
49 * Returns: (transfer full): a new, empty #GstByteWriter instance
50 **/
51 GstBitWriter *
gst_bit_writer_new(void)52 gst_bit_writer_new (void)
53 {
54 GstBitWriter *ret = g_slice_new0 (GstBitWriter);
55
56 ret->owned = TRUE;
57 ret->auto_grow = TRUE;
58 return ret;
59 }
60
61 /**
62 * gst_bit_writer_new_with_size: (skip)
63 * @size: Initial size of data in bytes
64 * @fixed: If %TRUE the data can't be reallocated
65 *
66 * Creates a #GstBitWriter instance with the given initial data size.
67 *
68 * Free-function: gst_bit_writer_free
69 *
70 * Returns: (transfer full): a new #GstBitWriter instance
71 */
72 GstBitWriter *
gst_bit_writer_new_with_size(guint size,gboolean fixed)73 gst_bit_writer_new_with_size (guint size, gboolean fixed)
74 {
75 GstBitWriter *ret = g_slice_new0 (GstBitWriter);
76
77 gst_bit_writer_init_with_size (ret, size, fixed);
78 return ret;
79 }
80
81 /**
82 * gst_bit_writer_new_with_data: (skip)
83 * @data: (array length=size) (transfer none): Memory area for writing
84 * @size: Size of @data in bytes
85 * @initialized: if %TRUE the complete data can be read from the beginning
86 *
87 * Creates a new #GstBitWriter instance with the given memory area. If
88 * @initialized is %TRUE it is possible to read @size bits from the
89 * #GstBitWriter from the beginning.
90 *
91 * Free-function: gst_bit_writer_free
92 *
93 * Returns: (transfer full): a new #GstBitWriter instance
94 */
95 GstBitWriter *
gst_bit_writer_new_with_data(guint8 * data,guint size,gboolean initialized)96 gst_bit_writer_new_with_data (guint8 * data, guint size, gboolean initialized)
97 {
98 GstBitWriter *ret = g_slice_new0 (GstBitWriter);
99
100 gst_bit_writer_init_with_data (ret, data, size, initialized);
101
102 return ret;
103 }
104
105 /**
106 * gst_bit_writer_init: (skip)
107 * @bitwriter: #GstBitWriter instance
108 *
109 * Initializes @bitwriter to an empty instance.
110 **/
111 void
gst_bit_writer_init(GstBitWriter * bitwriter)112 gst_bit_writer_init (GstBitWriter * bitwriter)
113 {
114 g_return_if_fail (bitwriter != NULL);
115
116 memset (bitwriter, 0, sizeof (GstBitWriter));
117 bitwriter->owned = TRUE;
118 bitwriter->auto_grow = TRUE;
119 }
120
121 /**
122 * gst_bit_writer_init_with_size: (skip)
123 * @bitwriter: #GstBitWriter instance
124 * @size: the size on bytes to allocate for data
125 * @fixed: If %TRUE the data can't be reallocated
126 *
127 * Initializes a #GstBitWriter instance and allocates the given data
128 * @size.
129 */
130 void
gst_bit_writer_init_with_size(GstBitWriter * bitwriter,guint size,gboolean fixed)131 gst_bit_writer_init_with_size (GstBitWriter * bitwriter, guint size,
132 gboolean fixed)
133 {
134 g_return_if_fail (bitwriter != NULL);
135
136 gst_bit_writer_init (bitwriter);
137
138 _gst_bit_writer_check_remaining (bitwriter, size << 3);
139
140 bitwriter->auto_grow = !fixed;
141 }
142
143 /**
144 * gst_bit_writer_init_with_data: (skip)
145 * @bitwriter: #GstBitWriter instance
146 * @data: (array length=size) (transfer none): Memory area for writing
147 * @size: Size of @data in bytes
148 * @initialized: If %TRUE the complete data can be read from the beginning
149 *
150 * Initializes @bitwriter with the given memory area @data. IF
151 * @initialized is %TRUE it is possible to read @size bits from the
152 * #GstBitWriter from the beginning.
153 */
154 void
gst_bit_writer_init_with_data(GstBitWriter * bitwriter,guint8 * data,guint size,gboolean initialized)155 gst_bit_writer_init_with_data (GstBitWriter * bitwriter, guint8 * data,
156 guint size, gboolean initialized)
157 {
158 g_return_if_fail (bitwriter != NULL);
159
160 gst_bit_writer_init (bitwriter);
161
162 bitwriter->data = data;
163 bitwriter->bit_capacity = size * 8;
164 bitwriter->bit_size = (initialized) ? size << 3 : 0;
165 bitwriter->auto_grow = FALSE;
166 bitwriter->owned = FALSE;
167 }
168
169 /**
170 * gst_bit_writer_reset:
171 * @bitwriter: #GstBitWriter instance
172 *
173 * Resets @bitwriter and frees the data if it's owned by @bitwriter.
174 */
175 void
gst_bit_writer_reset(GstBitWriter * bitwriter)176 gst_bit_writer_reset (GstBitWriter * bitwriter)
177 {
178 g_return_if_fail (bitwriter != NULL);
179
180 if (bitwriter->owned)
181 g_free (bitwriter->data);
182 memset (bitwriter, 0, sizeof (GstBitWriter));
183 }
184
185 /**
186 * gst_bit_writer_reset_and_get_data:
187 * @bitwriter: a #GstBitWriter instance
188 *
189 * Resets @bitwriter and returns the current data.
190 *
191 * Free-function: g_free
192 *
193 * Returns: (array) (transfer full): the current data. g_free() after
194 * usage.
195 **/
196 guint8 *
gst_bit_writer_reset_and_get_data(GstBitWriter * bitwriter)197 gst_bit_writer_reset_and_get_data (GstBitWriter * bitwriter)
198 {
199 guint8 *data;
200
201 g_return_val_if_fail (bitwriter != NULL, NULL);
202
203 data = bitwriter->data;
204 if (bitwriter->owned)
205 data = g_memdup2 (data, GST_ROUND_UP_8 (bitwriter->bit_size) >> 3);
206 gst_bit_writer_reset (bitwriter);
207
208 return data;
209 }
210
211 /**
212 * gst_bit_writer_reset_and_get_buffer:
213 * @bitwriter: a #GstBitWriter instance
214 *
215 * Resets @bitwriter and returns the current data as #GstBuffer.
216 *
217 * Free-function: gst_buffer_unref
218 *
219 * Returns: (transfer full): a new allocated #GstBuffer wrapping the
220 * current data. gst_buffer_unref() after usage.
221 **/
222 GstBuffer *
gst_bit_writer_reset_and_get_buffer(GstBitWriter * bitwriter)223 gst_bit_writer_reset_and_get_buffer (GstBitWriter * bitwriter)
224 {
225 GstBuffer *buffer;
226 gpointer data;
227 gsize size;
228 gboolean owned;
229
230 g_return_val_if_fail (bitwriter != NULL, NULL);
231
232 owned = bitwriter->owned;
233
234 size = GST_ROUND_UP_8 (bitwriter->bit_size) >> 3;
235 data = gst_bit_writer_reset_and_get_data (bitwriter);
236
237 /* we cannot rely on buffers allocated externally, thus let's dup
238 * the data */
239 if (data && !owned)
240 data = g_memdup2 (data, size);
241
242 buffer = gst_buffer_new ();
243 if (data != NULL) {
244 gst_buffer_append_memory (buffer,
245 gst_memory_new_wrapped (0, data, size, 0, size, data, g_free));
246 }
247
248 return buffer;
249 }
250
251 /**
252 * gst_bit_writer_free:
253 * @bitwriter: (in) (transfer full): #GstBitWriter instance
254 *
255 * Frees @bitwriter and the allocated data inside.
256 */
257 void
gst_bit_writer_free(GstBitWriter * bitwriter)258 gst_bit_writer_free (GstBitWriter * bitwriter)
259 {
260 g_return_if_fail (bitwriter != NULL);
261
262 gst_bit_writer_reset (bitwriter);
263 g_slice_free (GstBitWriter, bitwriter);
264 }
265
266 /**
267 * gst_bit_writer_free_and_get_data:
268 * @bitwriter: (in) (transfer full): #GstBitWriter instance
269 *
270 * Frees @bitwriter without destroying the internal data, which is
271 * returned.
272 *
273 * Free-function: g_free
274 *
275 * Returns: (array) (transfer full): the current data. g_free() after
276 * usage.
277 **/
278 guint8 *
gst_bit_writer_free_and_get_data(GstBitWriter * bitwriter)279 gst_bit_writer_free_and_get_data (GstBitWriter * bitwriter)
280 {
281 guint8 *data;
282
283 g_return_val_if_fail (bitwriter != NULL, NULL);
284
285 data = gst_bit_writer_reset_and_get_data (bitwriter);
286 g_slice_free (GstBitWriter, bitwriter);
287
288 return data;
289 }
290
291 /**
292 * gst_bit_writer_free_and_get_buffer:
293 * @bitwriter: (in) (transfer full): #GstBitWriter instance
294 *
295 * Frees @bitwriter without destroying the internal data, which is
296 * returned as #GstBuffer.
297 *
298 * Free-function: gst_buffer_unref
299 *
300 * Returns: (transfer full): a new allocated #GstBuffer wrapping the
301 * data inside. gst_buffer_unref() after usage.
302 **/
303 GstBuffer *
gst_bit_writer_free_and_get_buffer(GstBitWriter * bitwriter)304 gst_bit_writer_free_and_get_buffer (GstBitWriter * bitwriter)
305 {
306 GstBuffer *buffer;
307
308 g_return_val_if_fail (bitwriter != NULL, NULL);
309
310 buffer = gst_bit_writer_reset_and_get_buffer (bitwriter);
311 g_slice_free (GstBitWriter, bitwriter);
312
313 return buffer;
314 }
315
316 /**
317 * gst_bit_writer_get_size:
318 * @bitwriter: a #GstBitWriter instance
319 *
320 * Get size of written @data
321 *
322 * Returns: size of bits written in @data
323 */
324 guint
gst_bit_writer_get_size(const GstBitWriter * bitwriter)325 gst_bit_writer_get_size (const GstBitWriter * bitwriter)
326 {
327 return _gst_bit_writer_get_size_inline (bitwriter);
328 }
329
330 /**
331 * gst_bit_writer_get_data:
332 * @bitwriter: a #GstBitWriter instance
333 *
334 * Get written data pointer
335 *
336 * Returns: (array) (transfer none): data pointer
337 */
338 guint8 *
gst_bit_writer_get_data(const GstBitWriter * bitwriter)339 gst_bit_writer_get_data (const GstBitWriter * bitwriter)
340 {
341 return _gst_bit_writer_get_data_inline (bitwriter);
342 }
343
344 /**
345 * gst_bit_writer_get_pos:
346 * @bitwriter: a #GstBitWriter instance
347 * @pos: The new position in bits
348 *
349 * Set the new position of data end which should be the new size of @data.
350 *
351 * Returns: %TRUE if successful, %FALSE otherwise
352 */
353 gboolean
gst_bit_writer_set_pos(GstBitWriter * bitwriter,guint pos)354 gst_bit_writer_set_pos (GstBitWriter * bitwriter, guint pos)
355 {
356 return _gst_bit_writer_set_pos_inline (bitwriter, pos);
357 }
358
359 /**
360 * gst_bit_writer_put_bits_uint8:
361 * @bitwriter: a #GstBitWriter instance
362 * @value: value of #guint8 to write
363 * @nbits: number of bits to write
364 *
365 * Write @nbits bits of @value to #GstBitWriter.
366 *
367 * Returns: %TRUE if successful, %FALSE otherwise.
368 */
369
370 /**
371 * gst_bit_writer_put_bits_uint16:
372 * @bitwriter: a #GstBitWriter instance
373 * @value: value of #guint16 to write
374 * @nbits: number of bits to write
375 *
376 * Write @nbits bits of @value to #GstBitWriter.
377 *
378 * Returns: %TRUE if successful, %FALSE otherwise.
379 */
380
381 /**
382 * gst_bit_writer_put_bits_uint32:
383 * @bitwriter: a #GstBitWriter instance
384 * @value: value of #guint32 to write
385 * @nbits: number of bits to write
386 *
387 * Write @nbits bits of @value to #GstBitWriter.
388 *
389 * Returns: %TRUE if successful, %FALSE otherwise.
390 */
391
392 /**
393 * gst_bit_writer_put_bits_uint64:
394 * @bitwriter: a #GstBitWriter instance
395 * @value: value of #guint64 to write
396 * @nbits: number of bits to write
397 *
398 * Write @nbits bits of @value to #GstBitWriter.
399 *
400 * Returns: %TRUE if successful, %FALSE otherwise.
401 */
402
403 /* *INDENT-OFF* */
404 #define GST_BIT_WRITER_WRITE_BITS(bits) \
405 gboolean \
406 gst_bit_writer_put_bits_uint##bits (GstBitWriter *bitwriter, guint##bits value, guint nbits) \
407 { \
408 return _gst_bit_writer_put_bits_uint##bits##_inline (bitwriter, value, nbits); \
409 }
410
411 GST_BIT_WRITER_WRITE_BITS (8)
412 GST_BIT_WRITER_WRITE_BITS (16)
413 GST_BIT_WRITER_WRITE_BITS (32)
414 GST_BIT_WRITER_WRITE_BITS (64)
415 #undef GST_BIT_WRITER_WRITE_BITS
416 /* *INDENT-ON* */
417
418 /**
419 * gst_bit_writer_put_bytes:
420 * @bitwriter: a #GstBitWriter instance
421 * @data: (array): pointer of data to write
422 * @nbytes: number of bytes to write
423 *
424 * Write @nbytes bytes of @data to #GstBitWriter.
425 *
426 * Returns: %TRUE if successful, %FALSE otherwise.
427 */
428 gboolean
gst_bit_writer_put_bytes(GstBitWriter * bitwriter,const guint8 * data,guint nbytes)429 gst_bit_writer_put_bytes (GstBitWriter * bitwriter, const guint8 * data,
430 guint nbytes)
431 {
432 return _gst_bit_writer_put_bytes_inline (bitwriter, data, nbytes);
433 }
434
435 /**
436 * gst_bit_writer_align_bytes:
437 * @bitwriter: a #GstBitWriter instance
438 * @trailing_bit: trailing bits of last byte, 0 or 1
439 *
440 * Write trailing bit to align last byte of @data. @trailing_bit can
441 * only be 1 or 0.
442 *
443 * Returns: %TRUE if successful, %FALSE otherwise.
444 */
445 gboolean
gst_bit_writer_align_bytes(GstBitWriter * bitwriter,guint8 trailing_bit)446 gst_bit_writer_align_bytes (GstBitWriter * bitwriter, guint8 trailing_bit)
447 {
448 return _gst_bit_writer_align_bytes_inline (bitwriter, trailing_bit);
449 }
450