diff --git a/docs/libs/gstreamer-libs-sections.txt b/docs/libs/gstreamer-libs-sections.txt index 83b19db701..a27b372a38 100644 --- a/docs/libs/gstreamer-libs-sections.txt +++ b/docs/libs/gstreamer-libs-sections.txt @@ -442,6 +442,9 @@ gst_byte_reader_free gst_byte_reader_init +gst_byte_reader_peek_sub_reader +gst_byte_reader_get_sub_reader + gst_byte_reader_get_pos gst_byte_reader_get_remaining gst_byte_reader_set_pos diff --git a/libs/gst/base/gstbytereader.c b/libs/gst/base/gstbytereader.c index 6931841199..75dfd08db0 100644 --- a/libs/gst/base/gstbytereader.c +++ b/libs/gst/base/gstbytereader.c @@ -1,7 +1,7 @@ /* GStreamer byte reader * * Copyright (C) 2008 Sebastian Dröge . - * Copyright (C) 2009 Tim-Philipp Müller + * Copyright (C) 2009,2014 Tim-Philipp Müller * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -99,6 +99,56 @@ gst_byte_reader_init (GstByteReader * reader, const guint8 * data, guint size) reader->byte = 0; } +/** + * gst_byte_reader_peek_sub_reader: (skip) + * @reader: an existing and initialized #GstByteReader instance + * @sub_reader: a #GstByteReader instance to initialize as sub-reader + * @size: size of @sub_reader in bytes + * + * Initializes a #GstByteReader sub-reader instance to contain @size bytes of + * data from the current position of @reader. This is useful to read chunked + * formats and make sure that one doesn't read beyond the size of the sub-chunk. + * + * Unlike gst_byte_reader_get_sub_reader(), this function does not modify the + * current position of @reader. + * + * Returns: FALSE on error or if @reader does not contain @size more bytes from + * the current position, and otherwise TRUE + * + * Since: 1.6 + */ +gboolean +gst_byte_reader_peek_sub_reader (GstByteReader * reader, + GstByteReader * sub_reader, guint size) +{ + return _gst_byte_reader_peek_sub_reader_inline (reader, sub_reader, size); +} + +/** + * gst_byte_reader_get_sub_reader: (skip) + * @reader: an existing and initialized #GstByteReader instance + * @sub_reader: a #GstByteReader instance to initialize as sub-reader + * @size: size of @sub_reader in bytes + * + * Initializes a #GstByteReader sub-reader instance to contain @size bytes of + * data from the current position of @reader. This is useful to read chunked + * formats and make sure that one doesn't read beyond the size of the sub-chunk. + * + * Unlike gst_byte_reader_peek_sub_reader(), this function also modifies the + * position of @reader and moves it forward by @size bytes. + * + * Returns: FALSE on error or if @reader does not contain @size more bytes from + * the current position, and otherwise TRUE + * + * Since: 1.6 + */ +gboolean +gst_byte_reader_get_sub_reader (GstByteReader * reader, + GstByteReader * sub_reader, guint size) +{ + return _gst_byte_reader_get_sub_reader_inline (reader, sub_reader, size); +} + /** * gst_byte_reader_set_pos: * @reader: a #GstByteReader instance diff --git a/libs/gst/base/gstbytereader.h b/libs/gst/base/gstbytereader.h index 5b68837439..dd66011a96 100644 --- a/libs/gst/base/gstbytereader.h +++ b/libs/gst/base/gstbytereader.h @@ -52,6 +52,14 @@ void gst_byte_reader_free (GstByteReader *reader); void gst_byte_reader_init (GstByteReader *reader, const guint8 *data, guint size); +gboolean gst_byte_reader_peek_sub_reader (GstByteReader * reader, + GstByteReader * sub_reader, + guint size); + +gboolean gst_byte_reader_get_sub_reader (GstByteReader * reader, + GstByteReader * sub_reader, + guint size); + gboolean gst_byte_reader_set_pos (GstByteReader *reader, guint pos); guint gst_byte_reader_get_pos (const GstByteReader *reader); @@ -455,6 +463,32 @@ _gst_byte_reader_init_inline (GstByteReader * reader, const guint8 * data, guint reader->byte = 0; } +static inline gboolean +_gst_byte_reader_peek_sub_reader_inline (GstByteReader * reader, + GstByteReader * sub_reader, guint size) +{ + g_return_val_if_fail (reader != NULL, FALSE); + g_return_val_if_fail (sub_reader != NULL, FALSE); + + if (_gst_byte_reader_get_remaining_unchecked (reader) < size) + return FALSE; + + sub_reader->data = reader->data + reader->byte; + sub_reader->byte = 0; + sub_reader->size = size; + return TRUE; +} + +static inline gboolean +_gst_byte_reader_get_sub_reader_inline (GstByteReader * reader, + GstByteReader * sub_reader, guint size) +{ + if (!_gst_byte_reader_peek_sub_reader_inline (reader, sub_reader, size)) + return FALSE; + gst_byte_reader_skip_unchecked (reader, size); + return TRUE; +} + static inline gboolean _gst_byte_reader_dup_data_inline (GstByteReader * reader, guint size, guint8 ** val) { diff --git a/tests/check/libs/bytereader.c b/tests/check/libs/bytereader.c index d2a63cc11f..471e6a64b4 100644 --- a/tests/check/libs/bytereader.c +++ b/tests/check/libs/bytereader.c @@ -696,6 +696,87 @@ GST_START_TEST (test_dup_string) GST_END_TEST; +GST_START_TEST (test_sub_reader) +{ + const guint8 memdata[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f + }; + GstByteReader reader = GST_BYTE_READER_INIT (memdata, sizeof (memdata)); + GstByteReader sub; + const guint8 *data = NULL, *sub_data = NULL; + guint16 v = 0; + + /* init sub reader */ + fail_if (gst_byte_reader_peek_sub_reader (&reader, &sub, 17)); + fail_unless (gst_byte_reader_peek_sub_reader (&reader, &sub, 16)); + fail_unless_equals_int (gst_byte_reader_get_remaining (&sub), 16); + fail_unless (gst_byte_reader_peek_data (&reader, 16, &data)); + fail_unless (gst_byte_reader_peek_data (&sub, 16, &sub_data)); + fail_unless (memcmp (data, sub_data, 16) == 0); + + fail_unless_equals_int (gst_byte_reader_get_remaining (&reader), 16); + fail_unless (gst_byte_reader_skip (&reader, 3)); + fail_if (gst_byte_reader_peek_sub_reader (&reader, &sub, 14)); + fail_unless (gst_byte_reader_peek_sub_reader (&reader, &sub, 13)); + fail_unless_equals_int (gst_byte_reader_get_remaining (&sub), 13); + fail_unless (gst_byte_reader_peek_data (&reader, 13, &data)); + fail_unless (gst_byte_reader_peek_data (&sub, 13, &sub_data)); + fail_unless (memcmp (data, sub_data, 16) == 0); + + fail_unless_equals_int (gst_byte_reader_get_remaining (&reader), 13); + fail_unless (gst_byte_reader_peek_sub_reader (&reader, &sub, 3)); + fail_unless_equals_int (gst_byte_reader_get_remaining (&sub), 3); + fail_if (gst_byte_reader_peek_data (&sub, 10, &sub_data)); + fail_unless (gst_byte_reader_get_uint16_be (&sub, &v)); + fail_unless_equals_int (v, 0x0304); + fail_if (gst_byte_reader_get_uint16_be (&sub, &v)); + fail_unless_equals_int (gst_byte_reader_get_remaining (&sub), 1); + + fail_unless (gst_byte_reader_get_uint16_be (&reader, &v)); + fail_unless_equals_int (v, 0x0304); + fail_unless (gst_byte_reader_get_uint16_be (&reader, &v)); + fail_unless_equals_int (v, 0x0506); + fail_unless_equals_int (gst_byte_reader_get_remaining (&reader), 9); + + /* get sub reader */ + gst_byte_reader_init (&reader, memdata, sizeof (memdata)); + fail_if (gst_byte_reader_get_sub_reader (&reader, &sub, 17)); + fail_unless (gst_byte_reader_get_sub_reader (&reader, &sub, 16)); + fail_if (gst_byte_reader_get_sub_reader (&reader, &sub, 1)); + fail_unless (gst_byte_reader_get_sub_reader (&reader, &sub, 0)); + + gst_byte_reader_init (&reader, memdata, sizeof (memdata)); + fail_unless (gst_byte_reader_get_sub_reader (&reader, &sub, 2)); + fail_unless (gst_byte_reader_get_uint16_be (&sub, &v)); + fail_unless_equals_int (v, 0x0001); + fail_if (gst_byte_reader_get_uint16_be (&sub, &v)); + fail_unless (gst_byte_reader_get_sub_reader (&reader, &sub, 3)); + fail_unless (gst_byte_reader_get_uint16_be (&sub, &v)); + fail_unless_equals_int (v, 0x0203); + fail_if (gst_byte_reader_get_uint16_be (&sub, &v)); + fail_unless_equals_int (gst_byte_reader_get_uint8_unchecked (&sub), 0x04); + fail_unless (gst_byte_reader_get_sub_reader (&reader, &sub, 9)); + fail_unless (gst_byte_reader_get_uint16_be (&sub, &v)); + fail_unless_equals_int (v, 0x0506); + fail_unless (gst_byte_reader_get_uint16_be (&sub, &v)); + fail_unless_equals_int (v, 0x0708); + fail_unless (gst_byte_reader_get_uint16_be (&sub, &v)); + fail_unless_equals_int (v, 0x090a); + fail_unless (gst_byte_reader_get_uint16_be (&sub, &v)); + fail_unless_equals_int (v, 0x0b0c); + fail_if (gst_byte_reader_get_uint16_be (&sub, &v)); + fail_unless_equals_int (gst_byte_reader_get_uint8_unchecked (&sub), 0x0d); + fail_if (gst_byte_reader_get_sub_reader (&reader, &sub, 3)); + fail_unless (gst_byte_reader_get_sub_reader (&reader, &sub, 2)); + fail_unless (gst_byte_reader_get_uint16_be (&sub, &v)); + fail_unless_equals_int (v, 0x0e0f); + fail_if (gst_byte_reader_get_uint16_be (&sub, &v)); + fail_if (gst_byte_reader_get_uint16_be (&reader, &v)); +} + +GST_END_TEST; + static Suite * gst_byte_reader_suite (void) { @@ -715,6 +796,7 @@ gst_byte_reader_suite (void) tcase_add_test (tc_chain, test_scan); tcase_add_test (tc_chain, test_string_funcs); tcase_add_test (tc_chain, test_dup_string); + tcase_add_test (tc_chain, test_sub_reader); return s; } diff --git a/win32/common/libgstbase.def b/win32/common/libgstbase.def index bd31d95bd9..92c35007ab 100644 --- a/win32/common/libgstbase.def +++ b/win32/common/libgstbase.def @@ -142,6 +142,7 @@ EXPORTS gst_byte_reader_get_remaining gst_byte_reader_get_size gst_byte_reader_get_string_utf8 + gst_byte_reader_get_sub_reader gst_byte_reader_get_uint16_be gst_byte_reader_get_uint16_le gst_byte_reader_get_uint24_be @@ -170,6 +171,7 @@ EXPORTS gst_byte_reader_peek_int64_le gst_byte_reader_peek_int8 gst_byte_reader_peek_string_utf8 + gst_byte_reader_peek_sub_reader gst_byte_reader_peek_uint16_be gst_byte_reader_peek_uint16_le gst_byte_reader_peek_uint24_be