From b377c58e433070f577403d99833cc18e0f209d44 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 6 Oct 2008 12:41:53 +0000 Subject: [PATCH] Add bit reader and byte reader classes, including documentation and an extensive unit test suite. Fixes bug #553554. Original commit message from CVS: * docs/libs/gstreamer-libs-docs.sgml: * docs/libs/gstreamer-libs-sections.txt: * libs/gst/base/Makefile.am: * libs/gst/base/gstbitreader.c: (gst_bit_reader_new), (gst_bit_reader_new_from_buffer), (gst_bit_reader_free), (gst_bit_reader_init), (gst_bit_reader_init_from_buffer), (gst_bit_reader_set_pos), (gst_bit_reader_get_pos), (gst_bit_reader_get_remaining), (gst_bit_reader_skip), (gst_bit_reader_skip_to_byte): * libs/gst/base/gstbitreader.h: * libs/gst/base/gstbytereader.c: (GDOUBLE_SWAP_LE_BE), (GFLOAT_SWAP_LE_BE), (gst_byte_reader_new), (gst_byte_reader_new_from_buffer), (gst_byte_reader_free), (gst_byte_reader_init), (gst_byte_reader_init_from_buffer), (gst_byte_reader_set_pos), (gst_byte_reader_get_pos), (gst_byte_reader_get_remaining), (gst_byte_reader_skip), (gst_byte_reader_get_uint8), (gst_byte_reader_get_int8), (gst_byte_reader_peek_uint8), (gst_byte_reader_peek_int8), (gst_byte_reader_get_uint24_le), (gst_byte_reader_get_uint24_be), (gst_byte_reader_get_int24_le), (gst_byte_reader_get_int24_be), (gst_byte_reader_peek_uint24_le), (gst_byte_reader_peek_uint24_be), (gst_byte_reader_peek_int24_le), (gst_byte_reader_peek_int24_be): * libs/gst/base/gstbytereader.h: * tests/check/Makefile.am: * tests/check/libs/bitreader.c: (GST_START_TEST), (gst_bit_reader_suite): * tests/check/libs/bytereader.c: (GST_START_TEST), (gst_byte_reader_suite): Add bit reader and byte reader classes, including documentation and an extensive unit test suite. Fixes bug #553554. --- ChangeLog | 33 + docs/libs/gstreamer-libs-docs.sgml | 4 + docs/libs/gstreamer-libs-sections.txt | 107 ++- libs/gst/base/Makefile.am | 4 + libs/gst/base/gstbitreader.c | 400 +++++++++++ libs/gst/base/gstbitreader.h | 99 +++ libs/gst/base/gstbytereader.c | 1231 +++++++++++++++++++++++++++++++++ libs/gst/base/gstbytereader.h | 134 ++++ tests/check/Makefile.am | 8 + tests/check/libs/bitreader.c | 248 +++++++ tests/check/libs/bytereader.c | 484 +++++++++++++ 11 files changed, 2751 insertions(+), 1 deletion(-) create mode 100644 libs/gst/base/gstbitreader.c create mode 100644 libs/gst/base/gstbitreader.h create mode 100644 libs/gst/base/gstbytereader.c create mode 100644 libs/gst/base/gstbytereader.h create mode 100644 tests/check/libs/bitreader.c create mode 100644 tests/check/libs/bytereader.c diff --git a/ChangeLog b/ChangeLog index f249bc4..235b1cc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,36 @@ +2008-10-06 Sebastian Dröge + + * docs/libs/gstreamer-libs-docs.sgml: + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/Makefile.am: + * libs/gst/base/gstbitreader.c: (gst_bit_reader_new), + (gst_bit_reader_new_from_buffer), (gst_bit_reader_free), + (gst_bit_reader_init), (gst_bit_reader_init_from_buffer), + (gst_bit_reader_set_pos), (gst_bit_reader_get_pos), + (gst_bit_reader_get_remaining), (gst_bit_reader_skip), + (gst_bit_reader_skip_to_byte): + * libs/gst/base/gstbitreader.h: + * libs/gst/base/gstbytereader.c: (GDOUBLE_SWAP_LE_BE), + (GFLOAT_SWAP_LE_BE), (gst_byte_reader_new), + (gst_byte_reader_new_from_buffer), (gst_byte_reader_free), + (gst_byte_reader_init), (gst_byte_reader_init_from_buffer), + (gst_byte_reader_set_pos), (gst_byte_reader_get_pos), + (gst_byte_reader_get_remaining), (gst_byte_reader_skip), + (gst_byte_reader_get_uint8), (gst_byte_reader_get_int8), + (gst_byte_reader_peek_uint8), (gst_byte_reader_peek_int8), + (gst_byte_reader_get_uint24_le), (gst_byte_reader_get_uint24_be), + (gst_byte_reader_get_int24_le), (gst_byte_reader_get_int24_be), + (gst_byte_reader_peek_uint24_le), (gst_byte_reader_peek_uint24_be), + (gst_byte_reader_peek_int24_le), (gst_byte_reader_peek_int24_be): + * libs/gst/base/gstbytereader.h: + * tests/check/Makefile.am: + * tests/check/libs/bitreader.c: (GST_START_TEST), + (gst_bit_reader_suite): + * tests/check/libs/bytereader.c: (GST_START_TEST), + (gst_byte_reader_suite): + Add bit reader and byte reader classes, including documentation + and an extensive unit test suite. Fixes bug #553554. + 2008-10-06 Wim Taymans * libs/gst/base/gstbasesink.c: (gst_base_sink_get_position), diff --git a/docs/libs/gstreamer-libs-docs.sgml b/docs/libs/gstreamer-libs-docs.sgml index ce0c597..3daaa2d 100644 --- a/docs/libs/gstreamer-libs-docs.sgml +++ b/docs/libs/gstreamer-libs-docs.sgml @@ -8,6 +8,8 @@ + + @@ -64,6 +66,8 @@ &GstPushSrc; &GstAdapter; + &GstBitReader; + &GstByteReader; &GstCollectPads; &GstTypeFindHelper; &GstDataQueue; diff --git a/docs/libs/gstreamer-libs-sections.txt b/docs/libs/gstreamer-libs-sections.txt index 1efd3a3..385026a 100644 --- a/docs/libs/gstreamer-libs-sections.txt +++ b/docs/libs/gstreamer-libs-sections.txt @@ -217,7 +217,6 @@ GST_ADAPTER_GET_CLASS gst_adapter_get_type -
gstbasesrc GstBaseSrc @@ -333,6 +332,112 @@ gst_base_transform_get_type
+gstbitreader +GstBitReader +gst/base/gstbitreader.h +GstBitReader + +GST_BIT_READER_INIT +GST_BIT_READER_INIT_FROM_BUFFER + +gst_bit_reader_new +gst_bit_reader_new_from_buffer +gst_bit_reader_free + +gst_bit_reader_init +gst_bit_reader_init_from_buffer + +gst_bit_reader_get_pos +gst_bit_reader_get_remaining +gst_bit_reader_set_pos +gst_bit_reader_skip +gst_bit_reader_skip_to_byte + +gst_bit_reader_get_bits_uint16 +gst_bit_reader_get_bits_uint32 +gst_bit_reader_get_bits_uint64 +gst_bit_reader_get_bits_uint8 + +gst_bit_reader_peek_bits_uint16 +gst_bit_reader_peek_bits_uint32 +gst_bit_reader_peek_bits_uint64 +gst_bit_reader_peek_bits_uint8 +
+ +
+gstbytereader +GstByteReader +gst/base/gstbytereader.h +GstByteReader + +GST_BYTE_READER_INIT +GST_BYTE_READER_INIT_FROM_BUFFER + +gst_byte_reader_new +gst_byte_reader_new_from_buffer +gst_byte_reader_free + +gst_byte_reader_init +gst_byte_reader_init_from_buffer + +gst_byte_reader_get_pos +gst_byte_reader_get_remaining +gst_byte_reader_set_pos +gst_byte_reader_skip + +gst_byte_reader_get_int8 +gst_byte_reader_get_int16_be +gst_byte_reader_get_int16_le +gst_byte_reader_get_int24_be +gst_byte_reader_get_int24_le +gst_byte_reader_get_int32_be +gst_byte_reader_get_int32_le +gst_byte_reader_get_int64_be +gst_byte_reader_get_int64_le + +gst_byte_reader_get_uint8 +gst_byte_reader_get_uint16_be +gst_byte_reader_get_uint16_le +gst_byte_reader_get_uint24_be +gst_byte_reader_get_uint24_le +gst_byte_reader_get_uint32_be +gst_byte_reader_get_uint32_le +gst_byte_reader_get_uint64_be +gst_byte_reader_get_uint64_le + +gst_byte_reader_peek_int8 +gst_byte_reader_peek_int16_be +gst_byte_reader_peek_int16_le +gst_byte_reader_peek_int24_be +gst_byte_reader_peek_int24_le +gst_byte_reader_peek_int32_be +gst_byte_reader_peek_int32_le +gst_byte_reader_peek_int64_be +gst_byte_reader_peek_int64_le + +gst_byte_reader_peek_uint8 +gst_byte_reader_peek_uint16_be +gst_byte_reader_peek_uint16_le +gst_byte_reader_peek_uint24_be +gst_byte_reader_peek_uint24_le +gst_byte_reader_peek_uint32_be +gst_byte_reader_peek_uint32_le +gst_byte_reader_peek_uint64_be +gst_byte_reader_peek_uint64_le + + +gst_byte_reader_get_float32_le +gst_byte_reader_get_float32_be +gst_byte_reader_get_float64_le +gst_byte_reader_get_float64_be + +gst_byte_reader_peek_float32_le +gst_byte_reader_peek_float32_be +gst_byte_reader_peek_float64_le +gst_byte_reader_peek_float64_be +
+ +
gstcollectpads GstCollectPads gst/base/gstcollectpads.h diff --git a/libs/gst/base/Makefile.am b/libs/gst/base/Makefile.am index 0c72e5d..be657a8 100644 --- a/libs/gst/base/Makefile.am +++ b/libs/gst/base/Makefile.am @@ -7,6 +7,8 @@ libgstbase_@GST_MAJORMINOR@_la_SOURCES = \ gstbasesink.c \ gstbasesrc.c \ gstbasetransform.c \ + gstbitreader.c \ + gstbytereader.c \ gstcollectpads.c \ gstpushsrc.c \ gsttypefindhelper.c \ @@ -24,6 +26,8 @@ libgstbase_@GST_MAJORMINOR@include_HEADERS = \ gstbasesink.h \ gstbasesrc.h \ gstbasetransform.h \ + gstbitreader.h \ + gstbytereader.h \ gstcollectpads.h \ gstpushsrc.h \ gsttypefindhelper.h \ diff --git a/libs/gst/base/gstbitreader.c b/libs/gst/base/gstbitreader.c new file mode 100644 index 0000000..7647ab9 --- /dev/null +++ b/libs/gst/base/gstbitreader.c @@ -0,0 +1,400 @@ +/* GStreamer + * + * Copyright (C) 2008 Sebastian Dröge . + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstbitreader.h" + +#include + +/** + * SECTION:gstbitreader + * @short_description: Reads any number of bits from a memory buffer + * + * #GstBitReader provides a bit reader that can read any number of bits + * from a memory buffer. It provides functions for reading any number of bits + * into 8, 16, 32 and 64 bit variables. + */ + +/** + * gst_bit_reader_new: + * @data: Data from which the #GstBitReader should read + * @size: Size of @data in bytes + * + * Create a new #GstBitReader instance, which will read from @data. + * + * Returns: a new #GstBitReader instance + * + * Since: 0.10.22 + */ +GstBitReader * +gst_bit_reader_new (const guint8 * data, guint size) +{ + GstBitReader *ret = g_slice_new0 (GstBitReader); + + ret->data = data; + ret->size = size; + + return ret; +} + +/** + * gst_bit_reader_new_from_buffer: + * @buffer: Buffer from which the #GstBitReader should read + * + * Create a new #GstBitReader instance, which will read from the + * #GstBuffer @buffer. + * + * Returns: a new #GstBitReader instance + * + * Since: 0.10.22 + */ +GstBitReader * +gst_bit_reader_new_from_buffer (const GstBuffer * buffer) +{ + g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL); + + return gst_bit_reader_new (GST_BUFFER_DATA (buffer), + GST_BUFFER_SIZE (buffer)); +} + +/** + * gst_bit_reader_free: + * @reader: a #GstBitReader instance + * + * Frees a #GstBitReader instance, which was previously allocated by + * gst_bit_reader_new() or gst_bit_reader_new_from_buffer(). + * + * Since: 0.10.22 + */ +void +gst_bit_reader_free (GstBitReader * reader) +{ + g_return_if_fail (reader != NULL); + + g_slice_free (GstBitReader, reader); +} + +/** + * gst_bit_reader_init: + * @reader: a #GstBitReader instance + * @data: Data from which the #GstBitReader should read + * @size: Size of @data in bytes + * + * Initializes a #GstBitReader instance to read from @data. This function + * can be called on already initialized instances. + * + * Since: 0.10.22 + */ +void +gst_bit_reader_init (GstBitReader * reader, const guint8 * data, guint size) +{ + g_return_if_fail (reader != NULL); + + reader->data = data; + reader->size = size; + reader->byte = reader->bit = 0; +} + +/** + * gst_bit_reader_init: + * @reader: a #GstBitReader instance + * @buffer: Buffer from which the #GstBitReader should read + * + * Initializes a #GstBitReader instance to read from @buffer. This function + * can be called on already initialized instances. + * + * Since: 0.10.22 + */ +void +gst_bit_reader_init_from_buffer (GstBitReader * reader, + const GstBuffer * buffer) +{ + g_return_if_fail (GST_IS_BUFFER (buffer)); + + gst_bit_reader_init (reader, GST_BUFFER_DATA (buffer), + GST_BUFFER_SIZE (buffer)); +} + +/** + * gst_bit_reader_set_pos: + * @reader: a #GstBitReader instance + * @pos: The new position in bits + * + * Sets the new position of a #GstBitReader instance to @pos in bits. + * + * Returns: %TRUE if the position could be set successfully, %FALSE + * otherwise. + * + * Since: 0.10.22 + */ +gboolean +gst_bit_reader_set_pos (GstBitReader * reader, guint pos) +{ + g_return_val_if_fail (reader != NULL, FALSE); + + if (pos > reader->size * 8) + return FALSE; + + reader->byte = pos / 8; + reader->bit = pos % 8; + + return TRUE; +} + +/** + * gst_bit_reader_get_pos: + * @reader: a #GstBitReader instance + * + * Returns the current position of a #GstBitReader instance in bits. + * + * Returns: The current position of @reader in bits. + * + * Since: 0.10.22 + */ +guint +gst_bit_reader_get_pos (const GstBitReader * reader) +{ + g_return_val_if_fail (reader != NULL, 0); + + return reader->byte * 8 + reader->bit; +} + +/** + * gst_bit_reader_get_remaining: + * @reader: a #GstBitReader instance + * + * Returns the remaining number of bits of a #GstBitReader instance. + * + * Returns: The remaining number of bits of @reader instance. + * + * Since: 0.10.22 + */ +guint +gst_bit_reader_get_remaining (const GstBitReader * reader) +{ + g_return_val_if_fail (reader != NULL, 0); + + return reader->size * 8 - (reader->byte * 8 + reader->bit); +} + +/** + * gst_bit_reader_skip: + * @reader: a #GstBitReader instance + * @nbits: the number of bits to skip + * + * Skips @nbits bits of the #GstBitReader instance. + * + * Returns: %TRUE if @nbits bits could be skipped, %FALSE otherwise. + * + * Since: 0.10.22 + */ +gboolean +gst_bit_reader_skip (GstBitReader * reader, guint nbits) +{ + g_return_val_if_fail (reader != NULL, FALSE); + + if (gst_bit_reader_get_remaining (reader) < nbits) + return FALSE; + + reader->bit += nbits; + reader->byte += reader->bit / 8; + reader->bit = reader->bit % 8; + + return TRUE; +} + +/** + * gst_bit_reader_skip_to_byte: + * @reader: a #GstBitReader instance + * + * Skips until the next byte. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ +gboolean +gst_bit_reader_skip_to_byte (GstBitReader * reader) +{ + g_return_val_if_fail (reader != NULL, FALSE); + + if (reader->byte > reader->size) + return FALSE; + + if (reader->bit) { + reader->bit = 0; + reader->byte++; + } + + return TRUE; +} + +/** + * gst_bit_reader_get_bits_uint8: + * @reader: a #GstBitReader instance + * @val: Pointer to a #guint8 to store the result + * @nbits: number of bits to read + * + * Read @nbits bits into @val and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_bit_reader_get_bits_uint16: + * @reader: a #GstBitReader instance + * @val: Pointer to a #guint16 to store the result + * @nbits: number of bits to read + * + * Read @nbits bits into @val and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_bit_reader_get_bits_uint32: + * @reader: a #GstBitReader instance + * @val: Pointer to a #guint32 to store the result + * @nbits: number of bits to read + * + * Read @nbits bits into @val and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_bit_reader_get_bits_uint64: + * @reader: a #GstBitReader instance + * @val: Pointer to a #guint64 to store the result + * @nbits: number of bits to read + * + * Read @nbits bits into @val and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_bit_reader_peek_bits_uint8: + * @reader: a #GstBitReader instance + * @val: Pointer to a #guint8 to store the result + * @nbits: number of bits to read + * + * Read @nbits bits into @val but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_bit_reader_peek_bits_uint16: + * @reader: a #GstBitReader instance + * @val: Pointer to a #guint16 to store the result + * @nbits: number of bits to read + * + * Read @nbits bits into @val but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_bit_reader_peek_bits_uint32: + * @reader: a #GstBitReader instance + * @val: Pointer to a #guint32 to store the result + * @nbits: number of bits to read + * + * Read @nbits bits into @val but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_bit_reader_peek_bits_uint64: + * @reader: a #GstBitReader instance + * @val: Pointer to a #guint64 to store the result + * @nbits: number of bits to read + * + * Read @nbits bits into @val but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +#define GST_BIT_READER_READ_BITS(bits) \ +gboolean \ +gst_bit_reader_get_bits_uint##bits (GstBitReader *reader, guint##bits *val, guint nbits) \ +{ \ + guint##bits ret = 0; \ + \ + g_return_val_if_fail (reader != NULL, FALSE); \ + g_return_val_if_fail (val != NULL, FALSE); \ + g_return_val_if_fail (nbits <= bits, FALSE); \ + \ + if (reader->byte * 8 + reader->bit + nbits > reader->size * 8) \ + return FALSE; \ + \ + while (nbits > 0) { \ + guint toread = MIN (nbits, 8 - reader->bit); \ + \ + ret <<= toread; \ + ret |= (reader->data[reader->byte] & (0xff >> reader->bit)) >> (8 - toread - reader->bit); \ + \ + reader->bit += toread; \ + if (reader->bit >= 8) { \ + reader->byte++; \ + reader->bit = 0; \ + } \ + nbits -= toread; \ + } \ + \ + *val = ret; \ + return TRUE; \ +} \ +\ +gboolean \ +gst_bit_reader_peek_bits_uint##bits (const GstBitReader *reader, guint##bits *val, guint nbits) \ +{ \ + GstBitReader tmp; \ + \ + g_return_val_if_fail (reader != NULL, FALSE); \ + tmp = *reader; \ + return gst_bit_reader_get_bits_uint##bits (&tmp, val, nbits); \ +} + +GST_BIT_READER_READ_BITS (8); +GST_BIT_READER_READ_BITS (16); +GST_BIT_READER_READ_BITS (32); +GST_BIT_READER_READ_BITS (64); diff --git a/libs/gst/base/gstbitreader.h b/libs/gst/base/gstbitreader.h new file mode 100644 index 0000000..5dc16a3 --- /dev/null +++ b/libs/gst/base/gstbitreader.h @@ -0,0 +1,99 @@ +/* GStreamer + * + * Copyright (C) 2008 Sebastian Dröge . + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_BIT_READER_H__ +#define __GST_BIT_READER_H__ + +#include + +G_BEGIN_DECLS + +/** + * GstBitReader: + * @data: Data from which the bit reader will read + * @size: Size of @data in bytes + * @byte: Current byte position + * @bit: Bit position in the current byte + * + * A bit reader instance. + */ +typedef struct { + const guint8 *data; + guint size; + + guint byte; /* Byte position */ + guint bit; /* Bit position in the current byte */ +} GstBitReader; + +GstBitReader * gst_bit_reader_new (const guint8 *data, guint size); +GstBitReader * gst_bit_reader_new_from_buffer (const GstBuffer *buffer); +void gst_bit_reader_free (GstBitReader *reader); + +void gst_bit_reader_init (GstBitReader *reader, const guint8 *data, guint size); +void gst_bit_reader_init_from_buffer (GstBitReader *reader, const GstBuffer *buffer); + +gboolean gst_bit_reader_set_pos (GstBitReader *reader, guint pos); + +guint gst_bit_reader_get_pos (const GstBitReader *reader); +guint gst_bit_reader_get_remaining (const GstBitReader *reader); + +gboolean gst_bit_reader_skip (GstBitReader *reader, guint nbits); +gboolean gst_bit_reader_skip_to_byte (GstBitReader *reader); + +gboolean gst_bit_reader_get_bits_uint8 (GstBitReader *reader, guint8 *val, guint nbits); +gboolean gst_bit_reader_get_bits_uint16 (GstBitReader *reader, guint16 *val, guint nbits); +gboolean gst_bit_reader_get_bits_uint32 (GstBitReader *reader, guint32 *val, guint nbits); +gboolean gst_bit_reader_get_bits_uint64 (GstBitReader *reader, guint64 *val, guint nbits); + +gboolean gst_bit_reader_peek_bits_uint8 (const GstBitReader *reader, guint8 *val, guint nbits); +gboolean gst_bit_reader_peek_bits_uint16 (const GstBitReader *reader, guint16 *val, guint nbits); +gboolean gst_bit_reader_peek_bits_uint32 (const GstBitReader *reader, guint32 *val, guint nbits); +gboolean gst_bit_reader_peek_bits_uint64 (const GstBitReader *reader, guint64 *val, guint nbits); + +/** + * GST_BIT_READER_INIT: + * @data: Data from which the #GstBitReader should read + * @size: Size of @data in bytes + * + * A #GstBitReader must be initialized with this macro, before it can be + * used. This macro can used be to initialize a variable, but it cannot + * be assigned to a variable. In that case you have to use + * gst_bit_reader_init(). + * + * Since: 0.10.22 + */ +#define GST_BIT_READER_INIT(data, size) {data, size, 0, 0} + +/** + * GST_BIT_READER_INIT_FROM_BUFFER: + * @buffer: Buffer from which the #GstBitReader should read + * + * A #GstBitReader must be initialized with this macro, before it can be + * used. This macro can used be to initialize a variable, but it cannot + * be assigned to a variable. In that case you have to use + * gst_bit_reader_init(). + * + * Since: 0.10.22 + */ +#define GST_BIT_READER_INIT_FROM_BUFFER(buffer) {GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer), 0, 0} + +G_END_DECLS + +#endif /* __GST_BIT_READER_H__ */ diff --git a/libs/gst/base/gstbytereader.c b/libs/gst/base/gstbytereader.c new file mode 100644 index 0000000..cb91ea7 --- /dev/null +++ b/libs/gst/base/gstbytereader.c @@ -0,0 +1,1231 @@ +/* GStreamer + * + * Copyright (C) 2008 Sebastian Dröge . + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstbytereader.h" + +#include + +/** + * SECTION:gstbytereader + * @short_description: Reads different integer and floating point types from a memory buffer + * + * #GstByteReader provides a byte reader that can read different integer and + * floating point types from a memory buffer. It provides functions for reading + * signed/unsigned, little/big endian integers of 8, 16, 24, 32 and 64 bits + * and functions for reading little/big endian floating points numbers of + * 32 and 64 bits. + */ + + +/* Copied from gst/floatcast/floatcast.h as this is in gst-plugins-base */ + +inline static gdouble +GDOUBLE_SWAP_LE_BE (gdouble in) +{ + union + { + guint64 i; + gdouble d; + } u; + + u.d = in; + u.i = GUINT64_SWAP_LE_BE (u.i); + return u.d; +} + +inline static gfloat +GFLOAT_SWAP_LE_BE (gfloat in) +{ + union + { + guint32 i; + gfloat f; + } u; + + u.f = in; + u.i = GUINT32_SWAP_LE_BE (u.i); + return u.f; +} + +#if G_BYTE_ORDER == G_LITTLE_ENDIAN +#define GFLOAT_TO_LE(val) ((gfloat) (val)) +#define GFLOAT_TO_BE(val) (GFLOAT_SWAP_LE_BE (val)) +#define GDOUBLE_TO_LE(val) ((gdouble) (val)) +#define GDOUBLE_TO_BE(val) (GDOUBLE_SWAP_LE_BE (val)) + +#elif G_BYTE_ORDER == G_BIG_ENDIAN +#define GFLOAT_TO_LE(val) (GFLOAT_SWAP_LE_BE (val)) +#define GFLOAT_TO_BE(val) ((gfloat) (val)) +#define GDOUBLE_TO_LE(val) (GDOUBLE_SWAP_LE_BE (val)) +#define GDOUBLE_TO_BE(val) ((gdouble) (val)) + +#else /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */ +#error unknown ENDIAN type +#endif /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */ + +#define GFLOAT_FROM_LE(val) (GFLOAT_TO_LE (val)) +#define GFLOAT_FROM_BE(val) (GFLOAT_TO_BE (val)) +#define GDOUBLE_FROM_LE(val) (GDOUBLE_TO_LE (val)) +#define GDOUBLE_FROM_BE(val) (GDOUBLE_TO_BE (val)) + + +/** + * gst_byte_reader_new: + * @data: Data from which the #GstByteReader should read + * @size: Size of @data in bytes + * + * Create a new #GstByteReader instance, which will read from @data. + * + * Returns: a new #GstByteReader instance + * + * Since: 0.10.22 + */ +GstByteReader * +gst_byte_reader_new (const guint8 * data, guint size) +{ + GstByteReader *ret = g_slice_new0 (GstByteReader); + + ret->data = data; + ret->size = size; + + return ret; +} + +/** + * gst_byte_reader_new_from_buffer: + * @buffer: Buffer from which the #GstByteReader should read + * + * Create a new #GstByteReader instance, which will read from the + * #GstBuffer @buffer. + * + * Returns: a new #GstByteReader instance + * + * Since: 0.10.22 + */ +GstByteReader * +gst_byte_reader_new_from_buffer (const GstBuffer * buffer) +{ + g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL); + + return gst_byte_reader_new (GST_BUFFER_DATA (buffer), + GST_BUFFER_SIZE (buffer)); +} + +/** + * gst_byte_reader_free: + * @reader: a #GstByteReader instance + * + * Frees a #GstByteReader instance, which was previously allocated by + * gst_byte_reader_new() or gst_byte_reader_new_from_buffer(). + * + * Since: 0.10.22 + */ +void +gst_byte_reader_free (GstByteReader * reader) +{ + g_return_if_fail (reader != NULL); + + g_slice_free (GstByteReader, reader); +} + +/** + * gst_byte_reader_init: + * @reader: a #GstByteReader instance + * @data: Data from which the #GstByteReader should read + * @size: Size of @data in bytes + * + * Initializes a #GstByteReader instance to read from @data. This function + * can be called on already initialized instances. + * + * Since: 0.10.22 + */ +void +gst_byte_reader_init (GstByteReader * reader, const guint8 * data, guint size) +{ + g_return_if_fail (reader != NULL); + + reader->data = data; + reader->size = size; + reader->byte = 0; +} + +/** + * gst_byte_reader_init: + * @reader: a #GstByteReader instance + * @buffer: Buffer from which the #GstByteReader should read + * + * Initializes a #GstByteReader instance to read from @buffer. This function + * can be called on already initialized instances. + * + * Since: 0.10.22 + */ +void +gst_byte_reader_init_from_buffer (GstByteReader * reader, + const GstBuffer * buffer) +{ + g_return_if_fail (GST_IS_BUFFER (buffer)); + + gst_byte_reader_init (reader, GST_BUFFER_DATA (buffer), + GST_BUFFER_SIZE (buffer)); +} + +/** + * gst_byte_reader_set_pos: + * @reader: a #GstByteReader instance + * @pos: The new position in bytes + * + * Sets the new position of a #GstByteReader instance to @pos in bytes. + * + * Returns: %TRUE if the position could be set successfully, %FALSE + * otherwise. + * + * Since: 0.10.22 + */ +gboolean +gst_byte_reader_set_pos (GstByteReader * reader, guint pos) +{ + g_return_val_if_fail (reader != NULL, FALSE); + + if (pos > reader->size) + return FALSE; + + reader->byte = pos; + + return TRUE; +} + +/** + * gst_byte_reader_get_pos: + * @reader: a #GstByteReader instance + * + * Returns the current position of a #GstByteReader instance in bytes. + * + * Returns: The current position of @reader in bytes. + * + * Since: 0.10.22 + */ +guint +gst_byte_reader_get_pos (const GstByteReader * reader) +{ + g_return_val_if_fail (reader != NULL, 0); + + return reader->byte; +} + +/** + * gst_byte_reader_get_remaining: + * @reader: a #GstByteReader instance + * + * Returns the remaining number of bytes of a #GstByteReader instance. + * + * Returns: The remaining number of bytes of @reader instance. + * + * Since: 0.10.22 + */ +guint +gst_byte_reader_get_remaining (const GstByteReader * reader) +{ + g_return_val_if_fail (reader != NULL, 0); + + return reader->size - reader->byte; +} + +/** + * gst_byte_reader_skip: + * @reader: a #GstByteReader instance + * @nbytes: the number of bytes to skip + * + * Skips @nbytes bytes of the #GstByteReader instance. + * + * Returns: %TRUE if @nbytes bytes could be skipped, %FALSE otherwise. + * + * Since: 0.10.22 + */ +gboolean +gst_byte_reader_skip (GstByteReader * reader, guint nbytes) +{ + g_return_val_if_fail (reader != NULL, FALSE); + + if (gst_byte_reader_get_remaining (reader) < nbytes) + return FALSE; + + reader->byte += nbytes; + + return TRUE; +} + +/** + * gst_byte_reader_get_uint8: + * @reader: a #GstByteReader instance + * @val: Pointer to a #guint8 to store the result + * + * Read an unsigned 8 bit integer into @val and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_get_int8: + * @reader: a #GstByteReader instance + * @val: Pointer to a #gint8 to store the result + * + * Read a signed 8 bit integer into @val and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_peek_uint8: + * @reader: a #GstByteReader instance + * @val: Pointer to a #guint8 to store the result + * + * Read a signed 8 bit integer into @val but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_peek_int8: + * @reader: a #GstByteReader instance + * @val: Pointer to a #gint8 to store the result + * + * Read a signed 8 bit integer into @val but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_get_uint16_le: + * @reader: a #GstByteReader instance + * @val: Pointer to a #guint16 to store the result + * + * Read an unsigned 16 bit little endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_get_int16_le: + * @reader: a #GstByteReader instance + * @val: Pointer to a #gint16 to store the result + * + * Read a signed 16 bit little endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_peek_uint16_le: + * @reader: a #GstByteReader instance + * @val: Pointer to a #guint16 to store the result + * + * Read a signed 16 bit little endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_peek_int16_le: + * @reader: a #GstByteReader instance + * @val: Pointer to a #gint16 to store the result + * + * Read a signed 16 bit little endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_get_uint16_be: + * @reader: a #GstByteReader instance + * @val: Pointer to a #guint16 to store the result + * + * Read an unsigned 16 bit big endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_get_int16_be: + * @reader: a #GstByteReader instance + * @val: Pointer to a #gint16 to store the result + * + * Read a signed 16 bit big endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_peek_uint16_be: + * @reader: a #GstByteReader instance + * @val: Pointer to a #guint16 to store the result + * + * Read a signed 16 bit big endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_peek_int16_be: + * @reader: a #GstByteReader instance + * @val: Pointer to a #gint16 to store the result + * + * Read a signed 16 bit big endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_get_uint24_le: + * @reader: a #GstByteReader instance + * @val: Pointer to a #guint32 to store the result + * + * Read an unsigned 24 bit little endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_get_int24_le: + * @reader: a #GstByteReader instance + * @val: Pointer to a #gint32 to store the result + * + * Read a signed 24 bit little endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_peek_uint24_le: + * @reader: a #GstByteReader instance + * @val: Pointer to a #guint32 to store the result + * + * Read a signed 24 bit little endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_peek_int24_le: + * @reader: a #GstByteReader instance + * @val: Pointer to a #gint32 to store the result + * + * Read a signed 24 bit little endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_get_uint24_be: + * @reader: a #GstByteReader instance + * @val: Pointer to a #guint32 to store the result + * + * Read an unsigned 24 bit big endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_get_int24_be: + * @reader: a #GstByteReader instance + * @val: Pointer to a #gint32 to store the result + * + * Read a signed 24 bit big endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_peek_uint24_be: + * @reader: a #GstByteReader instance + * @val: Pointer to a #guint32 to store the result + * + * Read a signed 24 bit big endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_peek_int24_be: + * @reader: a #GstByteReader instance + * @val: Pointer to a #gint32 to store the result + * + * Read a signed 24 bit big endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + + +/** + * gst_byte_reader_get_uint32_le: + * @reader: a #GstByteReader instance + * @val: Pointer to a #guint32 to store the result + * + * Read an unsigned 32 bit little endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_get_int32_le: + * @reader: a #GstByteReader instance + * @val: Pointer to a #gint32 to store the result + * + * Read a signed 32 bit little endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_peek_uint32_le: + * @reader: a #GstByteReader instance + * @val: Pointer to a #guint32 to store the result + * + * Read a signed 32 bit little endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_peek_int32_le: + * @reader: a #GstByteReader instance + * @val: Pointer to a #gint32 to store the result + * + * Read a signed 32 bit little endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_get_uint32_be: + * @reader: a #GstByteReader instance + * @val: Pointer to a #guint32 to store the result + * + * Read an unsigned 32 bit big endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_get_int32_be: + * @reader: a #GstByteReader instance + * @val: Pointer to a #gint32 to store the result + * + * Read a signed 32 bit big endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_peek_uint32_be: + * @reader: a #GstByteReader instance + * @val: Pointer to a #guint32 to store the result + * + * Read a signed 32 bit big endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_peek_int32_be: + * @reader: a #GstByteReader instance + * @val: Pointer to a #gint32 to store the result + * + * Read a signed 32 bit big endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_get_uint64_le: + * @reader: a #GstByteReader instance + * @val: Pointer to a #guint64 to store the result + * + * Read an unsigned 64 bit little endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_get_int64_le: + * @reader: a #GstByteReader instance + * @val: Pointer to a #gint64 to store the result + * + * Read a signed 64 bit little endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_peek_uint64_le: + * @reader: a #GstByteReader instance + * @val: Pointer to a #guint64 to store the result + * + * Read a signed 64 bit little endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_peek_int64_le: + * @reader: a #GstByteReader instance + * @val: Pointer to a #gint64 to store the result + * + * Read a signed 64 bit little endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_get_uint64_be: + * @reader: a #GstByteReader instance + * @val: Pointer to a #guint64 to store the result + * + * Read an unsigned 64 bit big endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_get_int64_be: + * @reader: a #GstByteReader instance + * @val: Pointer to a #gint64 to store the result + * + * Read a signed 64 bit big endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_peek_uint64_be: + * @reader: a #GstByteReader instance + * @val: Pointer to a #guint64 to store the result + * + * Read a signed 64 bit big endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_peek_int64_be: + * @reader: a #GstByteReader instance + * @val: Pointer to a #gint64 to store the result + * + * Read a signed 64 bit big endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +#define GST_BYTE_READER_READ_INTS(bits) \ +gboolean \ +gst_byte_reader_get_uint##bits##_le (GstByteReader *reader, guint##bits *val) \ +{ \ + g_return_val_if_fail (reader != NULL, FALSE); \ + g_return_val_if_fail (val != NULL, FALSE); \ + \ + if (reader->byte + bits / 8 > reader->size) \ + return FALSE; \ + \ + *val = GST_READ_UINT##bits##_LE (&reader->data[reader->byte]); \ + reader->byte += bits / 8; \ + return TRUE; \ +} \ +\ +gboolean \ +gst_byte_reader_get_uint##bits##_be (GstByteReader *reader, guint##bits *val) \ +{ \ + g_return_val_if_fail (reader != NULL, FALSE); \ + g_return_val_if_fail (val != NULL, FALSE); \ + \ + if (reader->byte + bits / 8 > reader->size) \ + return FALSE; \ + \ + *val = GST_READ_UINT##bits##_BE (&reader->data[reader->byte]); \ + reader->byte += bits / 8; \ + return TRUE; \ +} \ +\ +gboolean \ +gst_byte_reader_get_int##bits##_le (GstByteReader *reader, gint##bits *val) \ +{ \ + g_return_val_if_fail (reader != NULL, FALSE); \ + g_return_val_if_fail (val != NULL, FALSE); \ + \ + if (reader->byte + bits / 8 > reader->size) \ + return FALSE; \ + \ + *val = GST_READ_UINT##bits##_LE (&reader->data[reader->byte]); \ + reader->byte += bits / 8; \ + return TRUE; \ +} \ +\ +gboolean \ +gst_byte_reader_get_int##bits##_be (GstByteReader *reader, gint##bits *val) \ +{ \ + g_return_val_if_fail (reader != NULL, FALSE); \ + g_return_val_if_fail (val != NULL, FALSE); \ + \ + if (reader->byte + bits / 8 > reader->size) \ + return FALSE; \ + \ + *val = GST_READ_UINT##bits##_BE (&reader->data[reader->byte]); \ + reader->byte += bits / 8; \ + return TRUE; \ +} \ +gboolean \ +gst_byte_reader_peek_uint##bits##_le (GstByteReader *reader, guint##bits *val) \ +{ \ + g_return_val_if_fail (reader != NULL, FALSE); \ + g_return_val_if_fail (val != NULL, FALSE); \ + \ + if (reader->byte + bits / 8 > reader->size) \ + return FALSE; \ + \ + *val = GST_READ_UINT##bits##_LE (&reader->data[reader->byte]); \ + return TRUE; \ +} \ +\ +gboolean \ +gst_byte_reader_peek_uint##bits##_be (GstByteReader *reader, guint##bits *val) \ +{ \ + g_return_val_if_fail (reader != NULL, FALSE); \ + g_return_val_if_fail (val != NULL, FALSE); \ + \ + if (reader->byte + bits / 8 > reader->size) \ + return FALSE; \ + \ + *val = GST_READ_UINT##bits##_BE (&reader->data[reader->byte]); \ + return TRUE; \ +} \ +\ +gboolean \ +gst_byte_reader_peek_int##bits##_le (GstByteReader *reader, gint##bits *val) \ +{ \ + g_return_val_if_fail (reader != NULL, FALSE); \ + g_return_val_if_fail (val != NULL, FALSE); \ + \ + if (reader->byte + bits / 8 > reader->size) \ + return FALSE; \ + \ + *val = GST_READ_UINT##bits##_LE (&reader->data[reader->byte]); \ + return TRUE; \ +} \ +\ +gboolean \ +gst_byte_reader_peek_int##bits##_be (GstByteReader *reader, gint##bits *val) \ +{ \ + g_return_val_if_fail (reader != NULL, FALSE); \ + g_return_val_if_fail (val != NULL, FALSE); \ + \ + if (reader->byte + bits / 8 > reader->size) \ + return FALSE; \ + \ + *val = GST_READ_UINT##bits##_BE (&reader->data[reader->byte]); \ + return TRUE; \ +} + + +GST_BYTE_READER_READ_INTS (16); +GST_BYTE_READER_READ_INTS (32); +GST_BYTE_READER_READ_INTS (64); + +gboolean +gst_byte_reader_get_uint8 (GstByteReader * reader, guint8 * val) +{ + g_return_val_if_fail (reader != NULL, FALSE); + g_return_val_if_fail (val != NULL, FALSE); + + if (reader->byte + 1 > reader->size) + return FALSE; + + *val = GST_READ_UINT8 (&reader->data[reader->byte]); + reader->byte++; + return TRUE; +} + +gboolean +gst_byte_reader_get_int8 (GstByteReader * reader, gint8 * val) +{ + g_return_val_if_fail (reader != NULL, FALSE); + g_return_val_if_fail (val != NULL, FALSE); + + if (reader->byte + 1 > reader->size) + return FALSE; + + *val = GST_READ_UINT8 (&reader->data[reader->byte]); + reader->byte++; + return TRUE; +} + +gboolean +gst_byte_reader_peek_uint8 (GstByteReader * reader, guint8 * val) +{ + g_return_val_if_fail (reader != NULL, FALSE); + g_return_val_if_fail (val != NULL, FALSE); + + if (reader->byte + 1 > reader->size) + return FALSE; + + *val = GST_READ_UINT8 (&reader->data[reader->byte]); + return TRUE; +} + +gboolean +gst_byte_reader_peek_int8 (GstByteReader * reader, gint8 * val) +{ + g_return_val_if_fail (reader != NULL, FALSE); + g_return_val_if_fail (val != NULL, FALSE); + + if (reader->byte + 1 > reader->size) + return FALSE; + + *val = GST_READ_UINT8 (&reader->data[reader->byte]); + return TRUE; +} + +gboolean +gst_byte_reader_get_uint24_le (GstByteReader * reader, guint32 * val) +{ + g_return_val_if_fail (reader != NULL, FALSE); + g_return_val_if_fail (val != NULL, FALSE); + + if (reader->byte + 3 > reader->size) + return FALSE; + + *val = + (reader->data[reader->byte] | (reader->data[reader->byte + + 1] << 8) | (reader->data[reader->byte + 2] << 16)); + reader->byte += 3; + return TRUE; +} + +gboolean +gst_byte_reader_get_uint24_be (GstByteReader * reader, guint32 * val) +{ + g_return_val_if_fail (reader != NULL, FALSE); + g_return_val_if_fail (val != NULL, FALSE); + + if (reader->byte + 3 > reader->size) + return FALSE; + + *val = + (reader->data[reader->byte + 2] | (reader->data[reader->byte + + 1] << 8) | (reader->data[reader->byte] << 16)); + reader->byte += 3; + return TRUE; +} + +gboolean +gst_byte_reader_get_int24_le (GstByteReader * reader, gint32 * val) +{ + guint32 ret; + + g_return_val_if_fail (reader != NULL, FALSE); + g_return_val_if_fail (val != NULL, FALSE); + + if (reader->byte + 3 > reader->size) + return FALSE; + + ret = + (reader->data[reader->byte] | (reader->data[reader->byte + + 1] << 8) | (reader->data[reader->byte + 2] << 16)); + + if (ret & 0x00800000) + ret |= 0xff000000; + + reader->byte += 3; + + *val = ret; + return TRUE; +} + +gboolean +gst_byte_reader_get_int24_be (GstByteReader * reader, gint32 * val) +{ + guint32 ret; + + g_return_val_if_fail (reader != NULL, FALSE); + g_return_val_if_fail (val != NULL, FALSE); + + if (reader->byte + 3 > reader->size) + return FALSE; + + ret = + (reader->data[reader->byte + 2] | (reader->data[reader->byte + + 1] << 8) | (reader->data[reader->byte] << 16)); + if (ret & 0x00800000) + ret |= 0xff000000; + + reader->byte += 3; + + *val = ret; + return TRUE; +} + +gboolean +gst_byte_reader_peek_uint24_le (GstByteReader * reader, guint32 * val) +{ + g_return_val_if_fail (reader != NULL, FALSE); + g_return_val_if_fail (val != NULL, FALSE); + + if (reader->byte + 3 > reader->size) + return FALSE; + + *val = + (reader->data[reader->byte] | (reader->data[reader->byte + + 1] << 8) | (reader->data[reader->byte + 2] << 16)); + return TRUE; +} + +gboolean +gst_byte_reader_peek_uint24_be (GstByteReader * reader, guint32 * val) +{ + g_return_val_if_fail (reader != NULL, FALSE); + g_return_val_if_fail (val != NULL, FALSE); + + if (reader->byte + 3 > reader->size) + return FALSE; + + *val = + (reader->data[reader->byte + 2] | (reader->data[reader->byte + + 1] << 8) | (reader->data[reader->byte] << 16)); + return TRUE; +} + +gboolean +gst_byte_reader_peek_int24_le (GstByteReader * reader, gint32 * val) +{ + guint32 ret; + + g_return_val_if_fail (reader != NULL, FALSE); + g_return_val_if_fail (val != NULL, FALSE); + + if (reader->byte + 3 > reader->size) + return FALSE; + + ret = + (reader->data[reader->byte] | (reader->data[reader->byte + + 1] << 8) | (reader->data[reader->byte + 2] << 16)); + + if (ret & 0x00800000) + ret |= 0xff000000; + + *val = ret; + return TRUE; +} + +gboolean +gst_byte_reader_peek_int24_be (GstByteReader * reader, gint32 * val) +{ + guint32 ret; + + g_return_val_if_fail (reader != NULL, FALSE); + g_return_val_if_fail (val != NULL, FALSE); + + if (reader->byte + 3 > reader->size) + return FALSE; + + ret = + (reader->data[reader->byte + 2] | (reader->data[reader->byte + + 1] << 8) | (reader->data[reader->byte] << 16)); + if (ret & 0x00800000) + ret |= 0xff000000; + + *val = ret; + return TRUE; +} + +/** + * gst_byte_reader_get_float32_le: + * @reader: a #GstByteReader instance + * @val: Pointer to a #gfloat to store the result + * + * Read a 32 bit little endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_peek_float32_le: + * @reader: a #GstByteReader instance + * @val: Pointer to a #gfloat to store the result + * + * Read a 32 bit little endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_get_float32_be: + * @reader: a #GstByteReader instance + * @val: Pointer to a #gfloat to store the result + * + * Read a 32 bit big endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_peek_float32_be: + * @reader: a #GstByteReader instance + * @val: Pointer to a #gfloat to store the result + * + * Read a 32 bit big endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_get_float64_le: + * @reader: a #GstByteReader instance + * @val: Pointer to a #gdouble to store the result + * + * Read a 64 bit little endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_peek_float64_le: + * @reader: a #GstByteReader instance + * @val: Pointer to a #gdouble to store the result + * + * Read a 64 bit little endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_get_float64_be: + * @reader: a #GstByteReader instance + * @val: Pointer to a #gdouble to store the result + * + * Read a 64 bit big endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +/** + * gst_byte_reader_peek_float64_be: + * @reader: a #GstByteReader instance + * @val: Pointer to a #gdouble to store the result + * + * Read a 64 bit big endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + * + * Since: 0.10.22 + */ + +#define GST_BYTE_READER_READ_FLOATS(bits, type, TYPE) \ +gboolean \ +gst_byte_reader_get_float##bits##_le (GstByteReader *reader, g##type *val) \ +{ \ + g##type ret; \ + \ + g_return_val_if_fail (reader != NULL, FALSE); \ + g_return_val_if_fail (val != NULL, FALSE); \ + \ + if (reader->byte + bits / 8 > reader->size) \ + return FALSE; \ + \ + memcpy (&ret, &reader->data[reader->byte], bits / 8); \ + *val = G##TYPE##_FROM_LE (ret); \ + reader->byte += bits / 8; \ + return TRUE; \ +} \ +gboolean \ +gst_byte_reader_get_float##bits##_be (GstByteReader *reader, g##type *val) \ +{ \ + g##type ret; \ + \ + g_return_val_if_fail (reader != NULL, FALSE); \ + g_return_val_if_fail (val != NULL, FALSE); \ + \ + if (reader->byte + bits / 8 > reader->size) \ + return FALSE; \ + \ + memcpy (&ret, &reader->data[reader->byte], bits / 8); \ + *val = G##TYPE##_FROM_BE (ret); \ + reader->byte += bits / 8; \ + return TRUE; \ +} \ +gboolean \ +gst_byte_reader_peek_float##bits##_le (GstByteReader *reader, g##type *val) \ +{ \ + g##type ret; \ + \ + g_return_val_if_fail (reader != NULL, FALSE); \ + g_return_val_if_fail (val != NULL, FALSE); \ + \ + if (reader->byte + bits / 8 > reader->size) \ + return FALSE; \ + \ + memcpy (&ret, &reader->data[reader->byte], bits / 8); \ + *val = G##TYPE##_FROM_LE (ret); \ + return TRUE; \ +} \ +gboolean \ +gst_byte_reader_peek_float##bits##_be (GstByteReader *reader, g##type *val) \ +{ \ + g##type ret; \ + \ + g_return_val_if_fail (reader != NULL, FALSE); \ + g_return_val_if_fail (val != NULL, FALSE); \ + \ + if (reader->byte + bits / 8 > reader->size) \ + return FALSE; \ + \ + memcpy (&ret, &reader->data[reader->byte], bits / 8); \ + *val = G##TYPE##_FROM_BE (ret); \ + return TRUE; \ +} + +GST_BYTE_READER_READ_FLOATS (32, float, FLOAT); +GST_BYTE_READER_READ_FLOATS (64, double, DOUBLE); diff --git a/libs/gst/base/gstbytereader.h b/libs/gst/base/gstbytereader.h new file mode 100644 index 0000000..28534c0 --- /dev/null +++ b/libs/gst/base/gstbytereader.h @@ -0,0 +1,134 @@ +/* GStreamer + * + * Copyright (C) 2008 Sebastian Dröge . + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_BYTE_READER_H__ +#define __GST_BYTE_READER_H__ + +#include + +G_BEGIN_DECLS + +/** + * GstByteReader: + * @data: Data from which the bit reader will read + * @size: Size of @data in bytes + * @byte: Current byte position + * + * A byte reader instance. + */ +typedef struct { + const guint8 *data; + guint size; + + guint byte; /* Byte position */ +} GstByteReader; + +GstByteReader * gst_byte_reader_new (const guint8 *data, guint size); +GstByteReader * gst_byte_reader_new_from_buffer (const GstBuffer *buffer); +void gst_byte_reader_free (GstByteReader *reader); + +void gst_byte_reader_init (GstByteReader *reader, const guint8 *data, guint size); +void gst_byte_reader_init_from_buffer (GstByteReader *reader, const GstBuffer *buffer); + +gboolean gst_byte_reader_set_pos (GstByteReader *reader, guint pos); + +guint gst_byte_reader_get_pos (const GstByteReader *reader); +guint gst_byte_reader_get_remaining (const GstByteReader *reader); + +gboolean gst_byte_reader_skip (GstByteReader *reader, guint nbytes); + +gboolean gst_byte_reader_get_uint8 (GstByteReader *reader, guint8 *val); +gboolean gst_byte_reader_get_int8 (GstByteReader *reader, gint8 *val); +gboolean gst_byte_reader_get_uint16_le (GstByteReader *reader, guint16 *val); +gboolean gst_byte_reader_get_int16_le (GstByteReader *reader, gint16 *val); +gboolean gst_byte_reader_get_uint16_be (GstByteReader *reader, guint16 *val); +gboolean gst_byte_reader_get_int16_be (GstByteReader *reader, gint16 *val); +gboolean gst_byte_reader_get_uint24_le (GstByteReader *reader, guint32 *val); +gboolean gst_byte_reader_get_int24_le (GstByteReader *reader, gint32 *val); +gboolean gst_byte_reader_get_uint24_be (GstByteReader *reader, guint32 *val); +gboolean gst_byte_reader_get_int24_be (GstByteReader *reader, gint32 *val); +gboolean gst_byte_reader_get_uint32_le (GstByteReader *reader, guint32 *val); +gboolean gst_byte_reader_get_int32_le (GstByteReader *reader, gint32 *val); +gboolean gst_byte_reader_get_uint32_be (GstByteReader *reader, guint32 *val); +gboolean gst_byte_reader_get_int32_be (GstByteReader *reader, gint32 *val); +gboolean gst_byte_reader_get_uint64_le (GstByteReader *reader, guint64 *val); +gboolean gst_byte_reader_get_int64_le (GstByteReader *reader, gint64 *val); +gboolean gst_byte_reader_get_uint64_be (GstByteReader *reader, guint64 *val); +gboolean gst_byte_reader_get_int64_be (GstByteReader *reader, gint64 *val); + +gboolean gst_byte_reader_peek_uint8 (GstByteReader *reader, guint8 *val); +gboolean gst_byte_reader_peek_int8 (GstByteReader *reader, gint8 *val); +gboolean gst_byte_reader_peek_uint16_le (GstByteReader *reader, guint16 *val); +gboolean gst_byte_reader_peek_int16_le (GstByteReader *reader, gint16 *val); +gboolean gst_byte_reader_peek_uint16_be (GstByteReader *reader, guint16 *val); +gboolean gst_byte_reader_peek_int16_be (GstByteReader *reader, gint16 *val); +gboolean gst_byte_reader_peek_uint24_le (GstByteReader *reader, guint32 *val); +gboolean gst_byte_reader_peek_int24_le (GstByteReader *reader, gint32 *val); +gboolean gst_byte_reader_peek_uint24_be (GstByteReader *reader, guint32 *val); +gboolean gst_byte_reader_peek_int24_be (GstByteReader *reader, gint32 *val); +gboolean gst_byte_reader_peek_uint32_le (GstByteReader *reader, guint32 *val); +gboolean gst_byte_reader_peek_int32_le (GstByteReader *reader, gint32 *val); +gboolean gst_byte_reader_peek_uint32_be (GstByteReader *reader, guint32 *val); +gboolean gst_byte_reader_peek_int32_be (GstByteReader *reader, gint32 *val); +gboolean gst_byte_reader_peek_uint64_le (GstByteReader *reader, guint64 *val); +gboolean gst_byte_reader_peek_int64_le (GstByteReader *reader, gint64 *val); +gboolean gst_byte_reader_peek_uint64_be (GstByteReader *reader, guint64 *val); +gboolean gst_byte_reader_peek_int64_be (GstByteReader *reader, gint64 *val); + +gboolean gst_byte_reader_get_float32_le (GstByteReader *reader, gfloat *val); +gboolean gst_byte_reader_get_float32_be (GstByteReader *reader, gfloat *val); +gboolean gst_byte_reader_get_float64_le (GstByteReader *reader, gdouble *val); +gboolean gst_byte_reader_get_float64_be (GstByteReader *reader, gdouble *val); + +gboolean gst_byte_reader_peek_float32_le (GstByteReader *reader, gfloat *val); +gboolean gst_byte_reader_peek_float32_be (GstByteReader *reader, gfloat *val); +gboolean gst_byte_reader_peek_float64_le (GstByteReader *reader, gdouble *val); +gboolean gst_byte_reader_peek_float64_be (GstByteReader *reader, gdouble *val); + +/** + * GST_BYTE_READER_INIT: + * @data: Data from which the #GstByteReader should read + * @size: Size of @data in bytes + * + * A #GstByteReader must be initialized with this macro, before it can be + * used. This macro can used be to initialize a variable, but it cannot + * be assigned to a variable. In that case you have to use + * gst_byte_reader_init(). + * + * Since: 0.10.22 + */ +#define GST_BYTE_READER_INIT(data, size) {data, size, 0} + +/** + * GST_BYTE_READER_INIT_FROM_BUFFER: + * @buffer: Buffer from which the #GstByteReader should read + * + * A #GstByteReader must be initialized with this macro, before it can be + * used. This macro can used be to initialize a variable, but it cannot + * be assigned to a variable. In that case you have to use + * gst_byte_reader_init(). + * + * Since: 0.10.22 + */ +#define GST_BYTE_READER_INIT_FROM_BUFFER(buffer) {GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer), 0} + +G_END_DECLS + +#endif /* __GST_BYTE_READER_H__ */ diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am index 2dddc93..b9a9767 100644 --- a/tests/check/Makefile.am +++ b/tests/check/Makefile.am @@ -100,6 +100,8 @@ check_PROGRAMS = \ libs/libsabi \ libs/gdp \ libs/adapter \ + libs/bitreader \ + libs/bytereader \ libs/gstnetclientclock \ libs/gstnettimeprovider \ libs/transform1 @@ -150,6 +152,12 @@ elements_filesrc_CFLAGS=$(GST_OBJ_CFLAGS) $(CHECK_CFLAGS) -DTESTFILE=\"$(top_src libs_basesrc_LDADD = \ $(top_builddir)/libs/gst/base/libgstbase-@GST_MAJORMINOR@.la \ $(LDADD) +libs_bitreader_LDADD = \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_MAJORMINOR@.la \ + $(LDADD) +libs_bytereader_LDADD = \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_MAJORMINOR@.la \ + $(LDADD) libs_adapter_LDADD = \ $(top_builddir)/libs/gst/base/libgstbase-@GST_MAJORMINOR@.la \ $(LDADD) diff --git a/tests/check/libs/bitreader.c b/tests/check/libs/bitreader.c new file mode 100644 index 0000000..3b93742 --- /dev/null +++ b/tests/check/libs/bitreader.c @@ -0,0 +1,248 @@ +/* GStreamer + * + * unit test for GstBitReader + * + * Copyright (C) <2008> Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#ifndef fail_unless_equals_int64 +#define fail_unless_equals_int64(a, b) \ +G_STMT_START { \ + gint64 first = a; \ + gint64 second = b; \ + fail_unless(first == second, \ + "'" #a "' (%" G_GINT64_FORMAT ") is not equal to '" #b"' (%" \ + G_GINT64_FORMAT ")", first, second); \ +} G_STMT_END; +#endif + +GST_START_TEST (test_initialization) +{ + guint8 data[] = { 0x01, 0x02, 0x03, 0x04 }; + GstBuffer *buffer = gst_buffer_new (); + GstBitReader reader = GST_BIT_READER_INIT (data, 4); + GstBitReader *reader2; + guint8 x; + + GST_BUFFER_DATA (buffer) = data; + GST_BUFFER_SIZE (buffer) = 4; + + fail_unless (gst_bit_reader_get_bits_uint8 (&reader, &x, 8)); + fail_unless_equals_int (x, 0x01); + fail_unless (gst_bit_reader_get_bits_uint8 (&reader, &x, 8)); + fail_unless_equals_int (x, 0x02); + + memset (&reader, 0, sizeof (GstBitReader)); + + gst_bit_reader_init (&reader, data, 4); + fail_unless (gst_bit_reader_get_bits_uint8 (&reader, &x, 8)); + fail_unless_equals_int (x, 0x01); + fail_unless (gst_bit_reader_get_bits_uint8 (&reader, &x, 8)); + fail_unless_equals_int (x, 0x02); + + gst_bit_reader_init_from_buffer (&reader, buffer); + fail_unless (gst_bit_reader_get_bits_uint8 (&reader, &x, 8)); + fail_unless_equals_int (x, 0x01); + fail_unless (gst_bit_reader_get_bits_uint8 (&reader, &x, 8)); + fail_unless_equals_int (x, 0x02); + + reader2 = gst_bit_reader_new (data, 4); + fail_unless (gst_bit_reader_get_bits_uint8 (reader2, &x, 8)); + fail_unless_equals_int (x, 0x01); + fail_unless (gst_bit_reader_get_bits_uint8 (reader2, &x, 8)); + fail_unless_equals_int (x, 0x02); + gst_bit_reader_free (reader2); + + reader2 = gst_bit_reader_new_from_buffer (buffer); + fail_unless (gst_bit_reader_get_bits_uint8 (reader2, &x, 8)); + fail_unless_equals_int (x, 0x01); + fail_unless (gst_bit_reader_get_bits_uint8 (reader2, &x, 8)); + fail_unless_equals_int (x, 0x02); + gst_bit_reader_free (reader2); + + gst_buffer_unref (buffer); +} + +GST_END_TEST; + +#define GET_CHECK(reader, dest, bits, nbits, val) { \ + fail_unless (gst_bit_reader_get_bits_uint##bits (reader, &dest, nbits)); \ + fail_unless_equals_uint64 (dest, val); \ +} + +#define PEEK_CHECK(reader, dest, bits, nbits, val) { \ + fail_unless (gst_bit_reader_peek_bits_uint##bits (reader, &dest, nbits)); \ + fail_unless_equals_uint64 (dest, val); \ +} + +#define GET_CHECK_FAIL(reader, dest, bits, nbits) { \ + fail_if (gst_bit_reader_get_bits_uint##bits (reader, &dest, nbits)); \ +} + +#define PEEK_CHECK_FAIL(reader, dest, bits, nbits) { \ + fail_if (gst_bit_reader_peek_bits_uint##bits (reader, &dest, nbits)); \ +} + +GST_START_TEST (test_get_bits) +{ + guint8 data[] = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x09, 0x87, 0x65, 0x43, 0x21 + }; + GstBitReader reader = GST_BIT_READER_INIT (data, 16); + guint8 a; + guint16 b; + guint32 c; + guint64 d; + + /* 8 bit */ + GET_CHECK (&reader, a, 8, 8, 0x12); + GET_CHECK (&reader, a, 8, 4, 0x03); + GET_CHECK (&reader, a, 8, 4, 0x04); + GET_CHECK (&reader, a, 8, 3, 0x02); + GET_CHECK (&reader, a, 8, 1, 0x01); + GET_CHECK (&reader, a, 8, 2, 0x01); + GET_CHECK (&reader, a, 8, 2, 0x02); + + PEEK_CHECK (&reader, a, 8, 8, 0x78); + PEEK_CHECK (&reader, a, 8, 8, 0x78); + fail_unless (gst_bit_reader_skip (&reader, 8)); + + PEEK_CHECK (&reader, a, 8, 8, 0x90); + GET_CHECK (&reader, a, 8, 1, 0x01); + GET_CHECK (&reader, a, 8, 1, 0x00); + GET_CHECK (&reader, a, 8, 1, 0x00); + GET_CHECK (&reader, a, 8, 1, 0x01); + fail_unless (gst_bit_reader_skip (&reader, 4)); + + fail_unless (gst_bit_reader_skip (&reader, 10 * 8)); + GET_CHECK (&reader, a, 8, 8, 0x21); + GET_CHECK_FAIL (&reader, a, 8, 1); + PEEK_CHECK_FAIL (&reader, a, 8, 1); + + /* 16 bit */ + gst_bit_reader_init (&reader, data, 16); + + GET_CHECK (&reader, b, 16, 16, 0x1234); + PEEK_CHECK (&reader, b, 16, 13, 0x0acf); + GET_CHECK (&reader, b, 16, 8, 0x56); + GET_CHECK (&reader, b, 16, 4, 0x07); + GET_CHECK (&reader, b, 16, 2, 0x02); + GET_CHECK (&reader, b, 16, 2, 0x00); + PEEK_CHECK (&reader, b, 16, 8, 0x90); + fail_unless (gst_bit_reader_skip (&reader, 11 * 8)); + GET_CHECK (&reader, b, 16, 8, 0x21); + GET_CHECK_FAIL (&reader, b, 16, 16); + PEEK_CHECK_FAIL (&reader, b, 16, 16); + + /* 32 bit */ + gst_bit_reader_init (&reader, data, 16); + + GET_CHECK (&reader, c, 32, 32, 0x12345678); + GET_CHECK (&reader, c, 32, 24, 0x90abcd); + GET_CHECK (&reader, c, 32, 16, 0xeffe); + GET_CHECK (&reader, c, 32, 8, 0xdc); + GET_CHECK (&reader, c, 32, 4, 0x0b); + GET_CHECK (&reader, c, 32, 2, 0x02); + GET_CHECK (&reader, c, 32, 2, 0x02); + PEEK_CHECK (&reader, c, 32, 8, 0x09); + fail_unless (gst_bit_reader_skip (&reader, 3 * 8)); + GET_CHECK (&reader, c, 32, 15, 0x2190); + GET_CHECK (&reader, c, 32, 1, 0x1); + GET_CHECK_FAIL (&reader, c, 32, 1); + + /* 64 bit */ + gst_bit_reader_init (&reader, data, 16); + + GET_CHECK (&reader, d, 64, 64, G_GINT64_CONSTANT (0x1234567890abcdef)); + GET_CHECK (&reader, d, 64, 7, 0xfe >> 1); + GET_CHECK (&reader, d, 64, 1, 0x00); + GET_CHECK (&reader, d, 64, 24, 0xdcba09); + GET_CHECK (&reader, d, 64, 32, 0x87654321); + GET_CHECK_FAIL (&reader, d, 64, 32); +} + +GST_END_TEST; + +#undef GET_CHECK +#undef PEEK_CHECK +#undef GET_CHECK_FAIL +#undef PEEK_CHECK_FAIL + +GST_START_TEST (test_position_tracking) +{ + guint8 data[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; + GstBitReader reader = GST_BIT_READER_INIT (data, 16); + guint8 a; + + fail_unless_equals_int (gst_bit_reader_get_pos (&reader), 0); + fail_unless_equals_int (gst_bit_reader_get_remaining (&reader), 16 * 8); + + fail_unless (gst_bit_reader_get_bits_uint8 (&reader, &a, 3)); + fail_unless_equals_int (gst_bit_reader_get_pos (&reader), 3); + fail_unless_equals_int (gst_bit_reader_get_remaining (&reader), 16 * 8 - 3); + + fail_unless (gst_bit_reader_set_pos (&reader, 9)); + fail_unless_equals_int (gst_bit_reader_get_pos (&reader), 9); + fail_unless_equals_int (gst_bit_reader_get_remaining (&reader), 16 * 8 - 9); + + fail_unless (gst_bit_reader_skip (&reader, 3)); + fail_unless_equals_int (gst_bit_reader_get_pos (&reader), 12); + fail_unless_equals_int (gst_bit_reader_get_remaining (&reader), 16 * 8 - 12); + + fail_unless (gst_bit_reader_skip_to_byte (&reader)); + fail_unless_equals_int (gst_bit_reader_get_pos (&reader), 16); + fail_unless_equals_int (gst_bit_reader_get_remaining (&reader), 16 * 8 - 16); + + fail_unless (gst_bit_reader_set_pos (&reader, 16 * 8)); + fail_unless_equals_int (gst_bit_reader_get_pos (&reader), 16 * 8); + fail_unless_equals_int (gst_bit_reader_get_remaining (&reader), 0); + + fail_unless (gst_bit_reader_skip (&reader, 0)); + fail_if (gst_bit_reader_skip (&reader, 1)); + fail_unless (gst_bit_reader_skip_to_byte (&reader)); +} + +GST_END_TEST; + +static Suite * +gst_bit_reader_suite (void) +{ + Suite *s = suite_create ("GstBitReader"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + + tcase_add_test (tc_chain, test_initialization); + tcase_add_test (tc_chain, test_get_bits); + tcase_add_test (tc_chain, test_position_tracking); + + return s; +} + + +GST_CHECK_MAIN (gst_bit_reader); diff --git a/tests/check/libs/bytereader.c b/tests/check/libs/bytereader.c new file mode 100644 index 0000000..c4ba8f9 --- /dev/null +++ b/tests/check/libs/bytereader.c @@ -0,0 +1,484 @@ +/* GStreamer + * + * unit test for GstByteReader + * + * Copyright (C) <2008> Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#ifndef fail_unless_equals_int64 +#define fail_unless_equals_int64(a, b) \ +G_STMT_START { \ + gint64 first = a; \ + gint64 second = b; \ + fail_unless(first == second, \ + "'" #a "' (%" G_GINT64_FORMAT ") is not equal to '" #b"' (%" \ + G_GINT64_FORMAT ")", first, second); \ +} G_STMT_END; +#endif + +GST_START_TEST (test_initialization) +{ + guint8 data[] = { 0x01, 0x02, 0x03, 0x04 }; + GstBuffer *buffer = gst_buffer_new (); + GstByteReader reader = GST_BYTE_READER_INIT (data, 4); + GstByteReader *reader2; + guint8 x; + + GST_BUFFER_DATA (buffer) = data; + GST_BUFFER_SIZE (buffer) = 4; + + fail_unless (gst_byte_reader_get_uint8 (&reader, &x)); + fail_unless_equals_int (x, 0x01); + fail_unless (gst_byte_reader_get_uint8 (&reader, &x)); + fail_unless_equals_int (x, 0x02); + + memset (&reader, 0, sizeof (GstByteReader)); + + gst_byte_reader_init (&reader, data, 4); + fail_unless (gst_byte_reader_get_uint8 (&reader, &x)); + fail_unless_equals_int (x, 0x01); + fail_unless (gst_byte_reader_get_uint8 (&reader, &x)); + fail_unless_equals_int (x, 0x02); + + gst_byte_reader_init_from_buffer (&reader, buffer); + fail_unless (gst_byte_reader_get_uint8 (&reader, &x)); + fail_unless_equals_int (x, 0x01); + fail_unless (gst_byte_reader_get_uint8 (&reader, &x)); + fail_unless_equals_int (x, 0x02); + + reader2 = gst_byte_reader_new (data, 4); + fail_unless (gst_byte_reader_get_uint8 (reader2, &x)); + fail_unless_equals_int (x, 0x01); + fail_unless (gst_byte_reader_get_uint8 (reader2, &x)); + fail_unless_equals_int (x, 0x02); + gst_byte_reader_free (reader2); + + reader2 = gst_byte_reader_new_from_buffer (buffer); + fail_unless (gst_byte_reader_get_uint8 (reader2, &x)); + fail_unless_equals_int (x, 0x01); + fail_unless (gst_byte_reader_get_uint8 (reader2, &x)); + fail_unless_equals_int (x, 0x02); + gst_byte_reader_free (reader2); + + gst_buffer_unref (buffer); +} + +GST_END_TEST; + +#define GET_CHECK8(reader, dest, val) { \ + fail_unless (gst_byte_reader_get_uint8 (reader, &dest)); \ + fail_unless_equals_uint64 (dest, val); \ +} + +#define GET_CHECK(reader, dest, bits, endianness, val) { \ + fail_unless (gst_byte_reader_get_uint##bits##_##endianness (reader, &dest)); \ + fail_unless_equals_uint64 (dest, val); \ +} + +#define GET_CHECK_FAIL8(reader, dest) { \ + fail_if (gst_byte_reader_get_uint8 (reader, &dest)); \ +} + +#define GET_CHECK_FAIL(reader, dest, bits, endianness) { \ + fail_if (gst_byte_reader_get_uint##bits##_##endianness (reader, &dest)); \ +} + +#define PEEK_CHECK8(reader, dest, val) { \ + fail_unless (gst_byte_reader_peek_uint8 (reader, &dest)); \ + fail_unless_equals_uint64 (dest, val); \ +} + +#define PEEK_CHECK(reader, dest, bits, endianness, val) { \ + fail_unless (gst_byte_reader_peek_uint##bits##_##endianness (reader, &dest)); \ + fail_unless_equals_uint64 (dest, val); \ +} + +#define PEEK_CHECK_FAIL8(reader, dest) { \ + fail_if (gst_byte_reader_peek_uint8 (reader, &dest)); \ +} + +#define PEEK_CHECK_FAIL(reader, dest, bits, endianness) { \ + fail_if (gst_byte_reader_peek_uint##bits##_##endianness (reader, &dest)); \ +} + +GST_START_TEST (test_get_uint_le) +{ + guint8 data[] = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x09, 0x87, 0x65, 0x43, 0x21 + }; + GstByteReader reader = GST_BYTE_READER_INIT (data, 16); + guint8 a; + guint16 b; + guint32 c; + guint64 d; + + GET_CHECK8 (&reader, a, 0x12); + GET_CHECK (&reader, b, 16, le, 0x5634); + GET_CHECK (&reader, c, 24, le, 0xab9078); + GET_CHECK (&reader, c, 32, le, 0xdcfeefcd); + fail_unless (gst_byte_reader_set_pos (&reader, 0)); + GET_CHECK (&reader, d, 64, le, G_GINT64_CONSTANT (0xefcdab9078563412)); + GET_CHECK (&reader, d, 64, le, G_GINT64_CONSTANT (0x2143658709badcfe)); + + GET_CHECK_FAIL8 (&reader, a); + GET_CHECK_FAIL (&reader, b, 16, le); + GET_CHECK_FAIL (&reader, c, 24, le); + GET_CHECK_FAIL (&reader, c, 32, le); + GET_CHECK_FAIL (&reader, d, 64, le); + + fail_unless (gst_byte_reader_set_pos (&reader, 0)); + + PEEK_CHECK8 (&reader, a, 0x12); + PEEK_CHECK (&reader, b, 16, le, 0x3412); + PEEK_CHECK (&reader, c, 24, le, 0x563412); + PEEK_CHECK (&reader, c, 32, le, 0x78563412); + PEEK_CHECK (&reader, d, 64, le, G_GINT64_CONSTANT (0xefcdab9078563412)); + + fail_unless (gst_byte_reader_set_pos (&reader, 16)); + PEEK_CHECK_FAIL8 (&reader, a); + PEEK_CHECK_FAIL (&reader, b, 16, le); + PEEK_CHECK_FAIL (&reader, c, 24, le); + PEEK_CHECK_FAIL (&reader, c, 32, le); + PEEK_CHECK_FAIL (&reader, d, 64, le); +} + +GST_END_TEST; + +GST_START_TEST (test_get_uint_be) +{ + guint8 data[] = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x09, 0x87, 0x65, 0x43, 0x21 + }; + GstByteReader reader = GST_BYTE_READER_INIT (data, 16); + guint8 a; + guint16 b; + guint32 c; + guint64 d; + + GET_CHECK8 (&reader, a, 0x12); + GET_CHECK (&reader, b, 16, be, 0x3456); + GET_CHECK (&reader, c, 24, be, 0x7890ab); + GET_CHECK (&reader, c, 32, be, 0xcdeffedc); + fail_unless (gst_byte_reader_set_pos (&reader, 0)); + GET_CHECK (&reader, d, 64, be, G_GINT64_CONSTANT (0x1234567890abcdef)); + GET_CHECK (&reader, d, 64, be, G_GINT64_CONSTANT (0xfedcba0987654321)); + + GET_CHECK_FAIL8 (&reader, a); + GET_CHECK_FAIL (&reader, b, 16, be); + GET_CHECK_FAIL (&reader, c, 24, be); + GET_CHECK_FAIL (&reader, c, 32, be); + GET_CHECK_FAIL (&reader, d, 64, be); + + fail_unless (gst_byte_reader_set_pos (&reader, 0)); + + PEEK_CHECK8 (&reader, a, 0x12); + PEEK_CHECK (&reader, b, 16, be, 0x1234); + PEEK_CHECK (&reader, c, 24, be, 0x123456); + PEEK_CHECK (&reader, c, 32, be, 0x12345678); + PEEK_CHECK (&reader, d, 64, be, G_GINT64_CONSTANT (0x1234567890abcdef)); + + fail_unless (gst_byte_reader_set_pos (&reader, 16)); + PEEK_CHECK_FAIL8 (&reader, a); + PEEK_CHECK_FAIL (&reader, b, 16, be); + PEEK_CHECK_FAIL (&reader, c, 24, be); + PEEK_CHECK_FAIL (&reader, c, 32, be); + PEEK_CHECK_FAIL (&reader, d, 64, be); +} + +GST_END_TEST; + +#undef GET_CHECK8 +#undef GET_CHECK +#undef PEEK_CHECK8 +#undef PEEK_CHECK +#undef GET_CHECK_FAIL8 +#undef GET_CHECK_FAIL +#undef PEEK_CHECK_FAIL8 +#undef PEEK_CHECK_FAIL + +#define GET_CHECK8(reader, dest, val) { \ + fail_unless (gst_byte_reader_get_int8 (reader, &dest)); \ + fail_unless_equals_int64 (dest, val); \ +} + +#define GET_CHECK(reader, dest, bits, endianness, val) { \ + fail_unless (gst_byte_reader_get_int##bits##_##endianness (reader, &dest)); \ + fail_unless_equals_int64 (dest, val); \ +} + +#define GET_CHECK_FAIL8(reader, dest) { \ + fail_if (gst_byte_reader_get_int8 (reader, &dest)); \ +} + +#define GET_CHECK_FAIL(reader, dest, bits, endianness) { \ + fail_if (gst_byte_reader_get_int##bits##_##endianness (reader, &dest)); \ +} + +#define PEEK_CHECK8(reader, dest, val) { \ + fail_unless (gst_byte_reader_peek_int8 (reader, &dest)); \ + fail_unless_equals_int64 (dest, val); \ +} + +#define PEEK_CHECK(reader, dest, bits, endianness, val) { \ + fail_unless (gst_byte_reader_peek_int##bits##_##endianness (reader, &dest)); \ + fail_unless_equals_int64 (dest, val); \ +} + +#define PEEK_CHECK_FAIL8(reader, dest) { \ + fail_if (gst_byte_reader_peek_int8 (reader, &dest)); \ +} + +#define PEEK_CHECK_FAIL(reader, dest, bits, endianness) { \ + fail_if (gst_byte_reader_peek_int##bits##_##endianness (reader, &dest)); \ +} + +GST_START_TEST (test_get_int_le) +{ + guint8 data[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; + GstByteReader reader = GST_BYTE_READER_INIT (data, 16); + gint8 a; + gint16 b; + gint32 c; + gint64 d; + + GET_CHECK8 (&reader, a, -1); + GET_CHECK (&reader, b, 16, le, -1); + GET_CHECK (&reader, c, 24, le, -1); + GET_CHECK (&reader, c, 32, le, -1); + fail_unless (gst_byte_reader_set_pos (&reader, 0)); + GET_CHECK (&reader, d, 64, le, G_GINT64_CONSTANT (-1)); + GET_CHECK (&reader, d, 64, le, G_GINT64_CONSTANT (-1)); + + GET_CHECK_FAIL8 (&reader, a); + GET_CHECK_FAIL (&reader, b, 16, le); + GET_CHECK_FAIL (&reader, c, 24, le); + GET_CHECK_FAIL (&reader, c, 32, le); + GET_CHECK_FAIL (&reader, d, 64, le); + + fail_unless (gst_byte_reader_set_pos (&reader, 0)); + + PEEK_CHECK8 (&reader, a, -1); + PEEK_CHECK (&reader, b, 16, le, -1); + PEEK_CHECK (&reader, c, 24, le, -1); + PEEK_CHECK (&reader, c, 32, le, -1); + PEEK_CHECK (&reader, d, 64, le, G_GINT64_CONSTANT (-1)); + + fail_unless (gst_byte_reader_set_pos (&reader, 16)); + PEEK_CHECK_FAIL8 (&reader, a); + PEEK_CHECK_FAIL (&reader, b, 16, le); + PEEK_CHECK_FAIL (&reader, c, 24, le); + PEEK_CHECK_FAIL (&reader, c, 32, le); + PEEK_CHECK_FAIL (&reader, d, 64, le); + +} + +GST_END_TEST; + +GST_START_TEST (test_get_int_be) +{ + guint8 data[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; + GstByteReader reader = GST_BYTE_READER_INIT (data, 16); + gint8 a; + gint16 b; + gint32 c; + gint64 d; + + GET_CHECK8 (&reader, a, -1); + GET_CHECK (&reader, b, 16, be, -1); + GET_CHECK (&reader, c, 24, be, -1); + GET_CHECK (&reader, c, 32, be, -1); + fail_unless (gst_byte_reader_set_pos (&reader, 0)); + GET_CHECK (&reader, d, 64, be, G_GINT64_CONSTANT (-1)); + GET_CHECK (&reader, d, 64, be, G_GINT64_CONSTANT (-1)); + + GET_CHECK_FAIL8 (&reader, a); + GET_CHECK_FAIL (&reader, b, 16, be); + GET_CHECK_FAIL (&reader, c, 24, be); + GET_CHECK_FAIL (&reader, c, 32, be); + GET_CHECK_FAIL (&reader, d, 64, be); + + fail_unless (gst_byte_reader_set_pos (&reader, 0)); + + PEEK_CHECK8 (&reader, a, -1); + PEEK_CHECK (&reader, b, 16, be, -1); + PEEK_CHECK (&reader, c, 24, be, -1); + PEEK_CHECK (&reader, c, 32, be, -1); + PEEK_CHECK (&reader, d, 64, be, G_GINT64_CONSTANT (-1)); + + fail_unless (gst_byte_reader_set_pos (&reader, 16)); + PEEK_CHECK_FAIL8 (&reader, a); + PEEK_CHECK_FAIL (&reader, b, 16, be); + PEEK_CHECK_FAIL (&reader, c, 24, be); + PEEK_CHECK_FAIL (&reader, c, 32, be); + PEEK_CHECK_FAIL (&reader, d, 64, be); + +} + +GST_END_TEST; + +#undef GET_CHECK8 +#undef GET_CHECK +#undef PEEK_CHECK8 +#undef PEEK_CHECK +#undef GET_CHECK_FAIL8 +#undef GET_CHECK_FAIL +#undef PEEK_CHECK_FAIL8 +#undef PEEK_CHECK_FAIL + +#define GET_CHECK(reader, dest, bits, endianness, val) { \ + fail_unless (gst_byte_reader_get_float##bits##_##endianness (reader, &dest)); \ + fail_unless_equals_float (dest, val); \ +} + +#define GET_CHECK_FAIL(reader, dest, bits, endianness) { \ + fail_if (gst_byte_reader_get_float##bits##_##endianness (reader, &dest)); \ +} + +#define PEEK_CHECK(reader, dest, bits, endianness, val) { \ + fail_unless (gst_byte_reader_peek_float##bits##_##endianness (reader, &dest)); \ + fail_unless_equals_float (dest, val); \ +} + +#define PEEK_CHECK_FAIL(reader, dest, bits, endianness) { \ + fail_if (gst_byte_reader_peek_float##bits##_##endianness (reader, &dest)); \ +} + +GST_START_TEST (test_get_float_le) +{ + guint8 data[] = { + 0x00, 0x00, 0x80, 0x3f, + 0x00, 0x00, 0x80, 0xbf, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xbf, + }; + GstByteReader reader = GST_BYTE_READER_INIT (data, 24); + gfloat a; + gdouble b; + + PEEK_CHECK (&reader, a, 32, le, 1.0); + GET_CHECK (&reader, a, 32, le, 1.0); + GET_CHECK (&reader, a, 32, le, -1.0); + PEEK_CHECK (&reader, b, 64, le, 1.0); + GET_CHECK (&reader, b, 64, le, 1.0); + GET_CHECK (&reader, b, 64, le, -1.0); + GET_CHECK_FAIL (&reader, a, 32, le); + GET_CHECK_FAIL (&reader, b, 64, le); + PEEK_CHECK_FAIL (&reader, a, 32, le); + PEEK_CHECK_FAIL (&reader, b, 64, le); +} + +GST_END_TEST; + +GST_START_TEST (test_get_float_be) +{ + guint8 data[] = { + 0x3f, 0x80, 0x00, 0x00, + 0xbf, 0x80, 0x00, 0x00, + 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xbf, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + GstByteReader reader = GST_BYTE_READER_INIT (data, 24); + gfloat a; + gdouble b; + + PEEK_CHECK (&reader, a, 32, be, 1.0); + GET_CHECK (&reader, a, 32, be, 1.0); + GET_CHECK (&reader, a, 32, be, -1.0); + PEEK_CHECK (&reader, b, 64, be, 1.0); + GET_CHECK (&reader, b, 64, be, 1.0); + GET_CHECK (&reader, b, 64, be, -1.0); + GET_CHECK_FAIL (&reader, a, 32, be); + GET_CHECK_FAIL (&reader, b, 64, be); + PEEK_CHECK_FAIL (&reader, a, 32, be); + PEEK_CHECK_FAIL (&reader, b, 64, be); +} + +GST_END_TEST; + +#undef GET_CHECK +#undef PEEK_CHECK +#undef GET_CHECK_FAIL +#undef PEEK_CHECK_FAIL + +GST_START_TEST (test_position_tracking) +{ + guint8 data[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; + GstByteReader reader = GST_BYTE_READER_INIT (data, 16); + guint8 a; + + fail_unless_equals_int (gst_byte_reader_get_pos (&reader), 0); + fail_unless_equals_int (gst_byte_reader_get_remaining (&reader), 16); + + fail_unless (gst_byte_reader_get_uint8 (&reader, &a)); + fail_unless_equals_int (gst_byte_reader_get_pos (&reader), 1); + fail_unless_equals_int (gst_byte_reader_get_remaining (&reader), 16 - 1); + + fail_unless (gst_byte_reader_set_pos (&reader, 8)); + fail_unless_equals_int (gst_byte_reader_get_pos (&reader), 8); + fail_unless_equals_int (gst_byte_reader_get_remaining (&reader), 16 - 8); + + fail_unless (gst_byte_reader_skip (&reader, 4)); + fail_unless_equals_int (gst_byte_reader_get_pos (&reader), 12); + fail_unless_equals_int (gst_byte_reader_get_remaining (&reader), 16 - 12); + + fail_unless (gst_byte_reader_set_pos (&reader, 16)); + fail_unless_equals_int (gst_byte_reader_get_pos (&reader), 16); + fail_unless_equals_int (gst_byte_reader_get_remaining (&reader), 0); + + fail_unless (gst_byte_reader_skip (&reader, 0)); + fail_if (gst_byte_reader_skip (&reader, 1)); +} + +GST_END_TEST; + +static Suite * +gst_byte_reader_suite (void) +{ + Suite *s = suite_create ("GstByteReader"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + + tcase_add_test (tc_chain, test_initialization); + tcase_add_test (tc_chain, test_get_uint_le); + tcase_add_test (tc_chain, test_get_uint_be); + tcase_add_test (tc_chain, test_get_int_le); + tcase_add_test (tc_chain, test_get_int_be); + tcase_add_test (tc_chain, test_get_float_le); + tcase_add_test (tc_chain, test_get_float_be); + tcase_add_test (tc_chain, test_position_tracking); + + return s; +} + + +GST_CHECK_MAIN (gst_byte_reader); -- 2.7.4