diff --git a/docs/libs/gstreamer-libs-docs.sgml b/docs/libs/gstreamer-libs-docs.sgml index 8225f134bd..620db5b4cd 100644 --- a/docs/libs/gstreamer-libs-docs.sgml +++ b/docs/libs/gstreamer-libs-docs.sgml @@ -44,6 +44,7 @@ + diff --git a/docs/libs/gstreamer-libs-sections.txt b/docs/libs/gstreamer-libs-sections.txt index 1da69cea0c..19b331a85d 100644 --- a/docs/libs/gstreamer-libs-sections.txt +++ b/docs/libs/gstreamer-libs-sections.txt @@ -516,6 +516,62 @@ gst_bit_reader_peek_bits_uint8_unchecked GST_BIT_READER +
+gstbitwriter +GstBitWriter +gst/base/gstbitwriter.h +GstBitWriter + +gst_bit_writer_new +gst_bit_writer_new_with_size +gst_bit_writer_new_with_data + +gst_bit_writer_free +gst_bit_writer_free_and_get_buffer +gst_bit_writer_free_and_get_data + +gst_bit_writer_init +gst_bit_writer_init_with_size +gst_bit_writer_init_with_data + +gst_bit_writer_reset +gst_bit_writer_reset_and_get_buffer +gst_bit_writer_reset_and_get_data + +gst_bit_writer_set_pos + +gst_bit_writer_get_size +gst_bit_writer_get_data +gst_bit_writer_get_remaining + +gst_bit_writer_get_size_unchecked +gst_bit_writer_get_data_unchecked +gst_bit_writer_set_pos_unchecked +gst_bit_writer_get_remaining_unchecked + +gst_bit_writer_put_bits_uint16 +gst_bit_writer_put_bits_uint32 +gst_bit_writer_put_bits_uint64 +gst_bit_writer_put_bits_uint8 +gst_bit_writer_put_bytes + +gst_bit_writer_put_bits_uint16_unchecked +gst_bit_writer_put_bits_uint32_unchecked +gst_bit_writer_put_bits_uint64_unchecked +gst_bit_writer_put_bits_uint8_unchecked +gst_bit_writer_put_bytes_unchecked + +gst_bit_writer_align_bytes +gst_bit_writer_align_bytes_unchecked + + +GST_BIT_WRITER_BIT_SIZE +GST_BIT_WRITER_DATA + + +GST_BIT_WRITER +
+
gstbytereader GstByteReader diff --git a/libs/gst/base/Makefile.am b/libs/gst/base/Makefile.am index 76551f8ccb..199a25a2b3 100644 --- a/libs/gst/base/Makefile.am +++ b/libs/gst/base/Makefile.am @@ -10,6 +10,7 @@ libgstbase_@GST_API_VERSION@_la_SOURCES = \ gstbasesrc.c \ gstbasetransform.c \ gstbitreader.c \ + gstbitwriter.c \ gstbytereader.c \ gstbytewriter.c \ gstcollectpads.c \ @@ -36,6 +37,7 @@ libgstbase_@GST_API_VERSION@include_HEADERS = \ gstbasesrc.h \ gstbasetransform.h \ gstbitreader.h \ + gstbitwriter.h \ gstbytereader.h \ gstbytewriter.h \ gstcollectpads.h \ @@ -49,6 +51,7 @@ noinst_HEADERS = \ gstbytereader-docs.h \ gstbytewriter-docs.h \ gstbitreader-docs.h \ + gstbitwriter-docs.h \ gstindex.h EXTRA_DIST = gstindex.c gstmemindex.c diff --git a/libs/gst/base/gstbitwriter-docs.h b/libs/gst/base/gstbitwriter-docs.h new file mode 100644 index 0000000000..bc44db86a9 --- /dev/null +++ b/libs/gst/base/gstbitwriter-docs.h @@ -0,0 +1,92 @@ +/* + * GStreamer bit writer dummy header for gtk-doc + * + * Copyright (C) 2013 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +/* This header is not installed, it just contains stuff for gtk-doc to parse, + * in particular docs and some dummy function declarations for the static + * inline functions we generate via macros in gstbitwriter.h. + */ + +#error "This header should never be included in code, it is only for gtk-doc" + +/** + * gst_bit_writer_put_bits_uint8_unchecked: + * @bitwriter: a #GstBitWriter instance + * @value: value of #guint8 to write + * @nbits: number of bits to write + * + * Write @nbits bits of @value to #GstBitWriter without checking whether + * there is enough space + */ +void gst_bit_writer_put_bits_uint8_unchecked (GstBitWriter *bitwriter, guint8 value, guint nbits); + +/** + * gst_bit_writer_put_bits_uint16_unchecked: + * @bitwriter: a #GstBitWriter instance + * @value: value of #guint16 to write + * @nbits: number of bits to write + * + * Write @nbits bits of @value to #GstBitWriter without checking whether + * there is enough space + */ +void gst_bit_writer_put_bits_uint16_unchecked (GstBitWriter *bitwriter, guint16 value, guint nbits); + +/** + * gst_bit_writer_put_bits_uint32_unchecked: + * @bitwriter: a #GstBitWriter instance + * @value: value of #guint32 to write + * @nbits: number of bits to write + * + * Write @nbits bits of @value to #GstBitWriter without checking whether + * there is enough space + */ +void gst_bit_writer_put_bits_uint32_unchecked (GstBitWriter *bitwriter, guint32 value, guint nbits); + +/** + * gst_bit_writer_put_bits_uint64_unchecked: + * @bitwriter: a #GstBitWriter instance + * @value: value of #guint64 to write + * @nbits: number of bits to write + * + * Write @nbits bits of @value to #GstBitWriter without checking whether + * there is enough space + */ +void gst_bit_writer_put_bits_uint64_unchecked (GstBitWriter *bitwriter, guint64 value, guint nbits); + +/** + * gst_bit_writer_put_bytes_unchecked: + * @bitwriter: a #GstBitWriter instance + * @data: pointer of data to write + * @nbytes: number of bytes to write + * + * Write @nbytes bytes of @data to #GstBitWriter without checking whether + * there is enough space + */ +void gst_bit_writer_put_bytes_unchecked (GstBitWriter *bitwriter, const guint8 *data, guint nbytes); + +/** + * gst_bit_writer_align_bytes_unchecked: + * @bitwriter: a #GstBitWriter instance + * @trailing_bit: trailing bits of last byte, 0 or 1 + * + * Write trailing bit to align last byte of @data without checking whether there + * is enough space + */ +void gst_bit_writer_align_bytes_unchecked (GstBitWriter *bitwriter, guint8 trailing_bit); diff --git a/libs/gst/base/gstbitwriter.c b/libs/gst/base/gstbitwriter.c new file mode 100644 index 0000000000..89e9fbca21 --- /dev/null +++ b/libs/gst/base/gstbitwriter.c @@ -0,0 +1,444 @@ +/* + * gstbitwriter.c - bitstream writer + * + * Copyright (C) 2013 Intel Corporation + * Copyright (C) 2018 Igalia, S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#define GST_BIT_WRITER_DISABLE_INLINES +#include "gstbitwriter.h" + +/** + * SECTION:gstbitwriter + * @title: GstBitWriter + * @short_description: Writes any number of bits into a memory buffer + * + * #GstBitWriter provides a bit writer that can write any number of + * bits into a memory buffer. It provides functions for writing any + * number of bits into 8, 16, 32 and 64 bit variables. + */ + +/** + * gst_bit_writer_new: + * + * Creates a new, empty #GstBitWriter instance. + * + * Free-function: gst_bit_writer_free + * + * Returns: (transfer full): a new, empty #GstByteWriter instance + **/ +GstBitWriter * +gst_bit_writer_new (void) +{ + GstBitWriter *ret = g_slice_new0 (GstBitWriter); + + ret->owned = TRUE; + ret->auto_grow = TRUE; + return ret; +} + +/** + * gst_bit_writer_new_size: + * @size: Initial size of data in bytes + * @fixed: If %TRUE the data can't be reallocated + * + * Creates a #GstBitWriter instance with the given initial data size. + * + * Free-function: gst_bit_writer_free + * + * Returns: (transfer full): a new #GstBitWriter instance + */ +GstBitWriter * +gst_bit_writer_new_with_size (guint size, gboolean fixed) +{ + GstBitWriter *ret = g_slice_new0 (GstBitWriter); + + gst_bit_writer_init_with_size (ret, size, fixed); + return ret; +} + +/** + * gst_bit_writer_new_with_data: + * @data: Memory area for writing + * @size: Size of @data in bytes + * @initialized: if %TRUE the complete data can be read from the beginning + * + * Creates a new #GstBitWriter instance with the given memory area. If + * @initialized is %TRUE it is possible to read @size bits from the + * #GstBitWriter from the beginnig. + * + * Free-function: gst_bit_writer_free + * + * Returns: (transfer full): a new #GstBitWriter instance + */ +GstBitWriter * +gst_bit_writer_new_with_data (guint8 * data, guint size, gboolean initialized) +{ + GstBitWriter *ret = g_slice_new0 (GstBitWriter); + + gst_bit_writer_init_with_data (ret, data, size, initialized); + + return ret; +} + +/** + * gst_bit_writer_init: + * @bitwriter: #GstBitWriter instance + * + * Initializes @bitwriter to an empty instance. + **/ +void +gst_bit_writer_init (GstBitWriter * bitwriter) +{ + g_return_if_fail (bitwriter != NULL); + + memset (bitwriter, 0, sizeof (GstBitWriter)); + bitwriter->owned = TRUE; + bitwriter->auto_grow = TRUE; +} + +/** + * gst_bit_writer_init_with_size: + * @bitwriter: #GstBitWriter instance + * @size: the size on bytes to allocate for data + * @fixed: If %TRUE the data can't be reallocated + * + * Initializes a #GstBitWriter instance and allocates the given data + * @size. + */ +void +gst_bit_writer_init_with_size (GstBitWriter * bitwriter, guint size, + gboolean fixed) +{ + g_return_if_fail (bitwriter != NULL); + + gst_bit_writer_init (bitwriter); + + _gst_bit_writer_check_remaining (bitwriter, size << 3); + + bitwriter->auto_grow = !fixed; +} + +/** + * gst_bit_writer_init_with_data: + * @bitwriter: #GstBitWriter instance + * @data: (array length=size) (transfer none): Memory area for writing + * @size: Size of @data in bytes + * @initialized: If %TRUE the complete data can be read from the beginning + * + * Initializes @bitwriter with the given memory area @data. IF + * @initialized is %TRUE it is possible to read @size bits from the + * #GstBitWriter from the beginning. + */ +void +gst_bit_writer_init_with_data (GstBitWriter * bitwriter, guint8 * data, + guint size, gboolean initialized) +{ + g_return_if_fail (bitwriter != NULL); + + gst_bit_writer_init (bitwriter); + + bitwriter->data = data; + bitwriter->bit_capacity = size * 8; + bitwriter->bit_size = (initialized) ? size << 3 : 0; + bitwriter->auto_grow = FALSE; + bitwriter->owned = FALSE; +} + +/** + * gst_bit_writer_reset: + * @bitwriter: #GstBitWriter instance + * + * Resets @bitwriter and frees the data if it's owned by @bitwriter. + */ +void +gst_bit_writer_reset (GstBitWriter * bitwriter) +{ + g_return_if_fail (bitwriter != NULL); + + if (bitwriter->owned) + g_free (bitwriter->data); + memset (bitwriter, 0, sizeof (GstBitWriter)); +} + +/** + * gst_bit_writer_reset_and_get_data: + * @bitwriter: a #GstBitWriter instance + * + * Resets @bitwriter and returns the current data. + * + * Free-function: g_free + * + * Returns: (array) (transfer full): the current data. g_free() after + * usage. + **/ +guint8 * +gst_bit_writer_reset_and_get_data (GstBitWriter * bitwriter) +{ + guint8 *data; + + g_return_val_if_fail (bitwriter != NULL, NULL); + + data = bitwriter->data; + if (bitwriter->owned) + data = g_memdup (data, bitwriter->bit_size >> 3); + gst_bit_writer_reset (bitwriter); + + return data; +} + +/** + * gst_bit_writer_reset_and_get_buffer: + * @bitwriter: a #GstBitWriter instance + * + * Resets @bitwriter and returns the current data as #GstBuffer. + * + * Free-function: gst_buffer_unref + * + * Returns: (transfer full): a new allocated #GstBuffer wrapping the + * current data. gst_buffer_unref() after usage. + **/ +GstBuffer * +gst_bit_writer_reset_and_get_buffer (GstBitWriter * bitwriter) +{ + GstBuffer *buffer; + gpointer data; + gsize size; + + g_return_val_if_fail (bitwriter != NULL, NULL); + + size = bitwriter->bit_size >> 3; + data = gst_bit_writer_reset_and_get_data (bitwriter); + + /* we cannot rely on buffers allocated externally, thus let's dup + * the data */ + if (data && !bitwriter->owned) + data = g_memdup (data, size); + + buffer = gst_buffer_new (); + if (data != NULL) { + gst_buffer_append_memory (buffer, + gst_memory_new_wrapped (0, data, size, 0, size, data, g_free)); + } + + return buffer; +} + +/** + * gst_bit_writer_free: + * @bitwriter: (in) (transfer full): #GstBitWriter instance + * + * Frees @bitwriter and the allocated data inside. + */ +void +gst_bit_writer_free (GstBitWriter * bitwriter) +{ + g_return_if_fail (bitwriter != NULL); + + gst_bit_writer_reset (bitwriter); + g_slice_free (GstBitWriter, bitwriter); +} + +/** + * gst_bit_writer_free_and_get_data: + * @bitwriter: (in) (transfer full): #GstBitWriter instance + * + * Frees @bitwriter without destroying the internal data, which is + * returned. + * + * Free-function: g_free + * + * Returns: (array) (transfer full): the current data. g_free() after + * usage. + **/ +guint8 * +gst_bit_writer_free_and_get_data (GstBitWriter * bitwriter) +{ + guint8 *data; + + g_return_val_if_fail (bitwriter != NULL, NULL); + + data = gst_bit_writer_reset_and_get_data (bitwriter); + g_slice_free (GstBitWriter, bitwriter); + + return data; +} + +/** + * gst_bit_writer_free_and_get_buffer: + * @bitwriter: (in) (transfer full): #GstBitWriter instance + * + * Frees @bitwriter without destroying the internal data, which is + * returned as #GstBuffer. + * + * Free-function: gst_buffer_unref + * + * Returns: (transfer full): a new allocated #GstBuffer wrapping the + * data inside. gst_buffer_unref() after usage. + **/ +GstBuffer * +gst_bit_writer_free_and_get_buffer (GstBitWriter * bitwriter) +{ + GstBuffer *buffer; + + g_return_val_if_fail (bitwriter != NULL, NULL); + + buffer = gst_bit_writer_reset_and_get_buffer (bitwriter); + g_slice_free (GstBitWriter, bitwriter); + + return buffer; +} + +/** + * gst_bit_writer_get_size: + * @bitwriter: a #GstBitWriter instance + * + * Get size of written @data + * + * Returns: size of bits written in @data + */ +guint +gst_bit_writer_get_size (const GstBitWriter * bitwriter) +{ + return _gst_bit_writer_get_size_inline (bitwriter); +} + +/** + * gst_bit_writer_get_data: + * @bitwriter: a #GstBitWriter instance + * + * Get written data pointer + * + * Returns: data pointer + */ +guint8 * +gst_bit_writer_get_data (const GstBitWriter * bitwriter) +{ + return _gst_bit_writer_get_data_inline (bitwriter); +} + +/** + * gst_bit_writer_get_pos: + * @bitwriter: a #GstBitWriter instance + * @pos: The new position in bits + * + * Set the new postion of data end which should be the new size of @data. + * + * Returns: %TRUE if successful, %FALSE otherwise + */ +gboolean +gst_bit_writer_set_pos (GstBitWriter * bitwriter, guint pos) +{ + return _gst_bit_writer_set_pos_inline (bitwriter, pos); +} + +/** + * gst_bit_writer_put_bits_uint8: + * @bitwriter: a #GstBitWriter instance + * @value: value of #guint8 to write + * @nbits: number of bits to write + * + * Write @nbits bits of @value to #GstBitWriter. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_bit_writer_put_bits_uint16: + * @bitwriter: a #GstBitWriter instance + * @value: value of #guint16 to write + * @nbits: number of bits to write + * + * Write @nbits bits of @value to #GstBitWriter. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_bit_writer_put_bits_uint32: + * @bitwriter: a #GstBitWriter instance + * @value: value of #guint32 to write + * @nbits: number of bits to write + * + * Write @nbits bits of @value to #GstBitWriter. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_bit_writer_put_bits_uint64: + * @bitwriter: a #GstBitWriter instance + * @value: value of #guint64 to write + * @nbits: number of bits to write + * + * Write @nbits bits of @value to #GstBitWriter. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/* *INDENT-OFF* */ +#define GST_BIT_WRITER_WRITE_BITS(bits) \ +gboolean \ +gst_bit_writer_put_bits_uint##bits (GstBitWriter *bitwriter, guint##bits value, guint nbits) \ +{ \ + return _gst_bit_writer_put_bits_uint##bits##_inline (bitwriter, value, nbits); \ +} + +GST_BIT_WRITER_WRITE_BITS (8) +GST_BIT_WRITER_WRITE_BITS (16) +GST_BIT_WRITER_WRITE_BITS (32) +GST_BIT_WRITER_WRITE_BITS (64) +#undef GST_BIT_WRITER_WRITE_BITS +/* *INDENT-ON* */ + +/** + * gst_bit_writer_put_bytes: + * @bitwriter: a #GstBitWriter instance + * @data: pointer of data to write + * @nbytes: number of bytes to write + * + * Write @nbytes bytes of @data to #GstBitWriter. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ +gboolean +gst_bit_writer_put_bytes (GstBitWriter * bitwriter, const guint8 * data, + guint nbytes) +{ + return _gst_bit_writer_put_bytes_inline (bitwriter, data, nbytes); +} + +/** + * gst_bit_writer_align_bytes: + * @bitwriter: a #GstBitWriter instance + * @trailing_bit: trailing bits of last byte, 0 or 1 + * + * Write trailing bit to align last byte of @data. @trailing_bit can + * only be 1 or 0. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ +gboolean +gst_bit_writer_align_bytes (GstBitWriter * bitwriter, guint8 trailing_bit) +{ + return _gst_bit_writer_align_bytes_inline (bitwriter, trailing_bit); +} diff --git a/libs/gst/base/gstbitwriter.h b/libs/gst/base/gstbitwriter.h new file mode 100644 index 0000000000..9e0b7c8907 --- /dev/null +++ b/libs/gst/base/gstbitwriter.h @@ -0,0 +1,386 @@ +/* + * gstbitwriter.h - bitstream writer + * + * Copyright (C) 2013 Intel Corporation + * Copyright (C) 2018 Igalia, S. L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef GST_BIT_WRITER_H +#define GST_BIT_WRITER_H + +#include +#include + +G_BEGIN_DECLS + +#define GST_BIT_WRITER_DATA(writer) ((writer)->data) +#define GST_BIT_WRITER_BIT_SIZE(writer) ((writer)->bit_size) +#define GST_BIT_WRITER(writer) ((GstBitWriter *) (writer)) + +typedef struct _GstBitWriter GstBitWriter; + +/** + * GstBitWriter: + * @data: Allocated @data for bit writer to write + * @bit_size: Size of written @data in bits + * + * Private: + * @bit_capacity: Capacity of the allocated @data + * @auto_grow: @data space can auto grow + * @destroy_data: The #GDestroyNotify function called with #data when the memory + * is freed + * + * A bit writer instance. + */ +struct _GstBitWriter +{ + guint8 *data; + guint bit_size; + + /*< private >*/ + guint bit_capacity; + gboolean auto_grow; + gboolean owned; + gpointer _gst_reserved[GST_PADDING]; +}; + +GST_BASE_API +GstBitWriter * gst_bit_writer_new (void) G_GNUC_MALLOC; + +GST_BASE_API +GstBitWriter * gst_bit_writer_new_with_size (guint32 size, gboolean fixed) G_GNUC_MALLOC; + +GST_BASE_API +GstBitWriter * gst_bit_writer_new_with_data (guint8 *data, guint size, + gboolean initialized) G_GNUC_MALLOC; + +GST_BASE_API +void gst_bit_writer_free (GstBitWriter *bitwriter); + +GST_BASE_API +guint8 * gst_bit_writer_free_and_get_data (GstBitWriter *bitwriter); + +GST_BASE_API +GstBuffer * gst_bit_writer_free_and_get_buffer (GstBitWriter *bitwriter); + +GST_BASE_API +void gst_bit_writer_init (GstBitWriter *bitwriter); + +GST_BASE_API +void gst_bit_writer_init_with_size (GstBitWriter *bitwriter, + guint32 size, gboolean fixed); + +GST_BASE_API +void gst_bit_writer_init_with_data (GstBitWriter *bitwriter, guint8 *data, + guint size, gboolean initialized); + +GST_BASE_API +void gst_bit_writer_reset (GstBitWriter *bitwriter); + +GST_BASE_API +guint8 * gst_bit_writer_reset_and_get_data (GstBitWriter *bitwriter); + +GST_BASE_API +GstBuffer * gst_bit_writer_reset_and_get_buffer (GstBitWriter *bitwriter); + +GST_BASE_API +guint gst_bit_writer_get_size (const GstBitWriter *bitwriter); + +GST_BASE_API +guint8 * gst_bit_writer_get_data (const GstBitWriter *bitwriter); + +GST_BASE_API +gboolean gst_bit_writer_set_pos (GstBitWriter *bitwriter, guint pos); + +GST_BASE_API +guint gst_bit_writer_get_remaining (const GstBitWriter *bitwriter); + +GST_BASE_API +gboolean gst_bit_writer_put_bits_uint8 (GstBitWriter *bitwriter, guint8 value, + guint nbits); + +GST_BASE_API +gboolean gst_bit_writer_put_bits_uint16 (GstBitWriter *bitwriter, guint16 value, + guint nbits); + +GST_BASE_API +gboolean gst_bit_writer_put_bits_uint32 (GstBitWriter *bitwriter, guint32 value, + guint nbits); + +GST_BASE_API +gboolean gst_bit_writer_put_bits_uint64 (GstBitWriter *bitwriter, guint64 value, + guint nbits); + +GST_BASE_API +gboolean gst_bit_writer_put_bytes (GstBitWriter *bitwriter, const guint8 *data, + guint nbytes); + +GST_BASE_API +gboolean gst_bit_writer_align_bytes (GstBitWriter *bitwriter, guint8 trailing_bit); + +static const guint8 _gst_bit_writer_bit_filling_mask[9] = { + 0x00, 0x01, 0x03, 0x07, + 0x0F, 0x1F, 0x3F, 0x7F, + 0xFF +}; + +/* Aligned to 256 bytes */ +#define __GST_BITS_WRITER_ALIGNMENT_MASK 2047 +#define __GST_BITS_WRITER_ALIGNED(bitsize) \ + (((bitsize) + __GST_BITS_WRITER_ALIGNMENT_MASK)&(~__GST_BITS_WRITER_ALIGNMENT_MASK)) + +static inline gboolean +_gst_bit_writer_check_remaining (GstBitWriter * bitwriter, guint32 bits) +{ + guint32 new_bit_size = bits + bitwriter->bit_size; + guint32 clear_pos; + + g_assert (bitwriter->bit_size <= bitwriter->bit_capacity); + if (new_bit_size <= bitwriter->bit_capacity) + return TRUE; + + if (!bitwriter->auto_grow) + return FALSE; + + /* auto grow space */ + new_bit_size = __GST_BITS_WRITER_ALIGNED (new_bit_size); + g_assert (new_bit_size + && ((new_bit_size & __GST_BITS_WRITER_ALIGNMENT_MASK) == 0)); + clear_pos = ((bitwriter->bit_size + 7) >> 3); + bitwriter->data = g_realloc (bitwriter->data, (new_bit_size >> 3)); + memset (bitwriter->data + clear_pos, 0, (new_bit_size >> 3) - clear_pos); + bitwriter->bit_capacity = new_bit_size; + return TRUE; +} + +#undef __GST_BITS_WRITER_ALIGNMENT_MASK +#undef __GST_BITS_WRITER_ALIGNED + +#define __GST_BIT_WRITER_WRITE_BITS_UNCHECKED(bits) \ +static inline void \ +gst_bit_writer_put_bits_uint##bits##_unchecked( \ + GstBitWriter *bitwriter, \ + guint##bits value, \ + guint nbits \ +) \ +{ \ + guint byte_pos, bit_offset; \ + guint8 *cur_byte; \ + guint fill_bits; \ + \ + byte_pos = (bitwriter->bit_size >> 3); \ + bit_offset = (bitwriter->bit_size & 0x07); \ + cur_byte = bitwriter->data + byte_pos; \ + g_assert (nbits <= bits); \ + g_assert( bit_offset < 8 && \ + bitwriter->bit_size <= bitwriter->bit_capacity); \ + \ + while (nbits) { \ + fill_bits = ((8 - bit_offset) < nbits ? (8 - bit_offset) : nbits); \ + nbits -= fill_bits; \ + bitwriter->bit_size += fill_bits; \ + \ + *cur_byte |= (((value >> nbits) & _gst_bit_writer_bit_filling_mask[fill_bits]) \ + << (8 - bit_offset - fill_bits)); \ + ++cur_byte; \ + bit_offset = 0; \ + } \ + g_assert(cur_byte <= \ + (bitwriter->data + (bitwriter->bit_capacity >> 3))); \ +} + +__GST_BIT_WRITER_WRITE_BITS_UNCHECKED (8) +__GST_BIT_WRITER_WRITE_BITS_UNCHECKED (16) +__GST_BIT_WRITER_WRITE_BITS_UNCHECKED (32) +__GST_BIT_WRITER_WRITE_BITS_UNCHECKED (64) +#undef __GST_BIT_WRITER_WRITE_BITS_UNCHECKED + +static inline guint +gst_bit_writer_get_size_unchecked (const GstBitWriter * bitwriter) +{ + return GST_BIT_WRITER_BIT_SIZE (bitwriter); +} + +static inline guint8 * +gst_bit_writer_get_data_unchecked (const GstBitWriter * bitwriter) +{ + return GST_BIT_WRITER_DATA (bitwriter); +} + +static inline gboolean +gst_bit_writer_set_pos_unchecked (GstBitWriter * bitwriter, guint pos) +{ + GST_BIT_WRITER_BIT_SIZE (bitwriter) = pos; + return TRUE; +} + +static inline guint +gst_bit_writer_get_remaining_unchecked (const GstBitWriter * bitwriter) +{ + return bitwriter->bit_capacity - bitwriter->bit_size; +} + +static inline void +gst_bit_writer_put_bytes_unchecked (GstBitWriter * bitwriter, + const guint8 * data, guint nbytes) +{ + if ((bitwriter->bit_size & 0x07) == 0) { + memcpy (&bitwriter->data[bitwriter->bit_size >> 3], data, nbytes); + bitwriter->bit_size += (nbytes << 3); + } else { + g_assert (0); + while (nbytes) { + gst_bit_writer_put_bits_uint8_unchecked (bitwriter, *data, 8); + --nbytes; + ++data; + } + } +} + +static inline void +gst_bit_writer_align_bytes_unchecked (GstBitWriter * bitwriter, + guint8 trailing_bit) +{ + guint32 bit_offset, bit_left; + guint8 value = 0; + + bit_offset = (bitwriter->bit_size & 0x07); + if (!bit_offset) + return; + + bit_left = 8 - bit_offset; + if (trailing_bit) + value = _gst_bit_writer_bit_filling_mask[bit_left]; + return gst_bit_writer_put_bits_uint8_unchecked (bitwriter, value, bit_left); +} + +#define __GST_BIT_WRITER_WRITE_BITS_INLINE(bits) \ +static inline gboolean \ +_gst_bit_writer_put_bits_uint##bits##_inline( \ + GstBitWriter *bitwriter, \ + guint##bits value, \ + guint nbits \ +) \ +{ \ + g_return_val_if_fail(bitwriter != NULL, FALSE); \ + g_return_val_if_fail(nbits != 0, FALSE); \ + g_return_val_if_fail(nbits <= bits, FALSE); \ + \ + if (!_gst_bit_writer_check_remaining(bitwriter, nbits)) \ + return FALSE; \ + gst_bit_writer_put_bits_uint##bits##_unchecked(bitwriter, value, nbits); \ + return TRUE; \ +} + +__GST_BIT_WRITER_WRITE_BITS_INLINE (8) +__GST_BIT_WRITER_WRITE_BITS_INLINE (16) +__GST_BIT_WRITER_WRITE_BITS_INLINE (32) +__GST_BIT_WRITER_WRITE_BITS_INLINE (64) +#undef __GST_BIT_WRITER_WRITE_BITS_INLINE + +static inline guint +_gst_bit_writer_get_size_inline (const GstBitWriter * bitwriter) +{ + g_return_val_if_fail (bitwriter != NULL, 0); + + return gst_bit_writer_get_size_unchecked (bitwriter); +} + +static inline guint8 * +_gst_bit_writer_get_data_inline (const GstBitWriter * bitwriter) +{ + g_return_val_if_fail (bitwriter != NULL, NULL); + + return gst_bit_writer_get_data_unchecked (bitwriter); +} + +static inline gboolean +_gst_bit_writer_set_pos_inline (GstBitWriter * bitwriter, guint pos) +{ + g_return_val_if_fail (bitwriter != NULL, FALSE); + g_return_val_if_fail (pos <= bitwriter->bit_capacity, FALSE); + + return gst_bit_writer_set_pos_unchecked (bitwriter, pos); +} + +static inline guint +_gst_bit_writer_get_remaining_inline (const GstBitWriter * bitwriter) +{ + g_return_val_if_fail (bitwriter != NULL, 0); + g_return_val_if_fail (bitwriter->bit_size < bitwriter->bit_capacity, 0); + + return gst_bit_writer_get_remaining_unchecked (bitwriter); +} + +static inline gboolean +_gst_bit_writer_put_bytes_inline (GstBitWriter * bitwriter, + const guint8 * data, guint nbytes) +{ + g_return_val_if_fail (bitwriter != NULL, FALSE); + g_return_val_if_fail (data != NULL, FALSE); + g_return_val_if_fail (nbytes, FALSE); + + if (!_gst_bit_writer_check_remaining (bitwriter, nbytes * 8)) + return FALSE; + + gst_bit_writer_put_bytes_unchecked (bitwriter, data, nbytes); + return TRUE; +} + +static inline gboolean +_gst_bit_writer_align_bytes_inline (GstBitWriter * bitwriter, + guint8 trailing_bit) +{ + g_return_val_if_fail (bitwriter != NULL, FALSE); + g_return_val_if_fail ((trailing_bit == 0 || trailing_bit == 1), FALSE); + g_return_val_if_fail (((bitwriter->bit_size + 7) & (~7)) <= + bitwriter->bit_capacity, FALSE); + + gst_bit_writer_align_bytes_unchecked (bitwriter, trailing_bit); + return TRUE; +} + +#ifndef GST_BIT_WRITER_DISABLE_INLINES +#define gst_bit_writer_get_size(bitwriter) \ + _gst_bit_writer_get_size_inline(bitwriter) +#define gst_bit_writer_get_data(bitwriter) \ + _gst_bit_writer_get_data_inline(bitwriter) +#define gst_bit_writer_set_pos(bitwriter, pos) \ + G_LIKELY (_gst_bit_writer_set_pos_inline (bitwriter, pos)) +#define gst_bit_writer_get_remaining(bitwriter) \ + _gst_bit_writer_get_remaining_inline(bitwriter) + +#define gst_bit_writer_put_bits_uint8(bitwriter, value, nbits) \ + G_LIKELY (_gst_bit_writer_put_bits_uint8_inline (bitwriter, value, nbits)) +#define gst_bit_writer_put_bits_uint16(bitwriter, value, nbits) \ + G_LIKELY (_gst_bit_writer_put_bits_uint16_inline (bitwriter, value, nbits)) +#define gst_bit_writer_put_bits_uint32(bitwriter, value, nbits) \ + G_LIKELY (_gst_bit_writer_put_bits_uint32_inline (bitwriter, value, nbits)) +#define gst_bit_writer_put_bits_uint64(bitwriter, value, nbits) \ + G_LIKELY (_gst_bit_writer_put_bits_uint64_inline (bitwriter, value, nbits)) + +#define gst_bit_writer_put_bytes(bitwriter, data, nbytes) \ + G_LIKELY (_gst_bit_writer_put_bytes_inline (bitwriter, data, nbytes)) + +#define gst_bit_writer_align_bytes(bitwriter, trailing_bit) \ + G_LIKELY (_gst_bit_writer_align_bytes_inline(bitwriter, trailing_bit)) +#endif + +G_END_DECLS + +#endif /* GST_BIT_WRITER_H */ diff --git a/libs/gst/base/meson.build b/libs/gst/base/meson.build index a7a9435414..bc2a926a21 100644 --- a/libs/gst/base/meson.build +++ b/libs/gst/base/meson.build @@ -6,6 +6,7 @@ gst_base_sources = [ 'gstbasesrc.c', 'gstbasetransform.c', 'gstbitreader.c', + 'gstbitwriter.c', 'gstbytereader.c', 'gstbytewriter.c', 'gstcollectpads.c', @@ -26,6 +27,7 @@ gst_base_headers = [ 'gstbasesrc.h', 'gstbasetransform.h', 'gstbitreader.h', + 'gstbitwriter.h', 'gstbytereader.h', 'gstbytewriter.h', 'gstcollectpads.h', @@ -79,6 +81,7 @@ install_headers('base.h', 'gstbasesrc.h', 'gstbasetransform.h', 'gstbitreader.h', + 'gstbitwriter.h', 'gstbytereader.h', 'gstbytewriter.h', 'gstcollectpads.h', diff --git a/win32/common/libgstbase.def b/win32/common/libgstbase.def index 49cd755d02..0725298bce 100644 --- a/win32/common/libgstbase.def +++ b/win32/common/libgstbase.def @@ -149,6 +149,27 @@ EXPORTS gst_bit_reader_set_pos gst_bit_reader_skip gst_bit_reader_skip_to_byte + gst_bit_writer_align_bytes + gst_bit_writer_free + gst_bit_writer_free_and_get_buffer + gst_bit_writer_free_and_get_data + gst_bit_writer_get_data + gst_bit_writer_get_size + gst_bit_writer_init + gst_bit_writer_init_with_data + gst_bit_writer_init_with_size + gst_bit_writer_new + gst_bit_writer_new_with_data + gst_bit_writer_new_with_size + gst_bit_writer_put_bits_uint16 + gst_bit_writer_put_bits_uint32 + gst_bit_writer_put_bits_uint64 + gst_bit_writer_put_bits_uint8 + gst_bit_writer_put_bytes + gst_bit_writer_reset + gst_bit_writer_reset_and_get_buffer + gst_bit_writer_reset_and_get_data + gst_bit_writer_set_pos gst_byte_reader_dup_data gst_byte_reader_dup_string_utf16 gst_byte_reader_dup_string_utf32