• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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