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