From f8323b17fb2640e90b10dbe98ac7516bbf381908 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Thu, 24 Jul 2014 14:39:11 -0300 Subject: [PATCH] bytereader: add gst_byte_reader_masked_scan_uint32_peek Adds gst_byte_reader_masked_scan_uint32_peek just like GstAdapter has a _peek and non _peek version Upgraded tests to check that the returned value is correct in the _peek version API: gst_byte_reader_masked_scan_uint32_peek https://bugzilla.gnome.org/show_bug.cgi?id=728356 --- libs/gst/base/gstbytereader.c | 115 ++++++++++++++++++++++++---------- libs/gst/base/gstbytereader.h | 6 ++ tests/check/libs/bytereader.c | 12 +++- win32/common/libgstbase.def | 1 + 4 files changed, 99 insertions(+), 35 deletions(-) diff --git a/libs/gst/base/gstbytereader.c b/libs/gst/base/gstbytereader.c index b73a679326..6931841199 100644 --- a/libs/gst/base/gstbytereader.c +++ b/libs/gst/base/gstbytereader.c @@ -794,6 +794,55 @@ _scan_for_start_code (const guint8 * data, guint offset, guint size) return -1; } +static inline guint +_masked_scan_uint32_peek (const GstByteReader * reader, + guint32 mask, guint32 pattern, guint offset, guint size, guint32 * value) +{ + const guint8 *data; + guint32 state; + guint i; + + g_return_val_if_fail (size > 0, -1); + g_return_val_if_fail ((guint64) offset + size <= reader->size - reader->byte, + -1); + + /* we can't find the pattern with less than 4 bytes */ + if (G_UNLIKELY (size < 4)) + return -1; + + data = reader->data + reader->byte + offset; + + /* Handle special case found in MPEG and H264 */ + if ((pattern == 0x00000100) && (mask == 0xffffff00)) { + guint ret = _scan_for_start_code (data, offset, size); + if (G_UNLIKELY (value)) + *value = (1 << 8) | data[ret + 3]; + return ret; + } + + /* set the state to something that does not match */ + state = ~pattern; + + /* now find data */ + for (i = 0; i < size; i++) { + /* throw away one byte and move in the next byte */ + state = ((state << 8) | data[i]); + if (G_UNLIKELY ((state & mask) == pattern)) { + /* we have a match but we need to have skipped at + * least 4 bytes to fill the state. */ + if (G_LIKELY (i >= 3)) { + if (value) + *value = state; + return offset + i - 3; + } + } + } + + /* nothing found */ + return -1; +} + + /** * gst_byte_reader_masked_scan_uint32: * @reader: a #GstByteReader @@ -840,41 +889,39 @@ guint gst_byte_reader_masked_scan_uint32 (const GstByteReader * reader, guint32 mask, guint32 pattern, guint offset, guint size) { - const guint8 *data; - guint32 state; - guint i; + return _masked_scan_uint32_peek (reader, mask, pattern, offset, size, NULL); +} - g_return_val_if_fail (size > 0, -1); - g_return_val_if_fail ((guint64) offset + size <= reader->size - reader->byte, - -1); - - /* we can't find the pattern with less than 4 bytes */ - if (G_UNLIKELY (size < 4)) - return -1; - - data = reader->data + reader->byte + offset; - - /* Handle special case found in MPEG and H264 */ - if ((pattern == 0x00000100) && (mask == 0xffffff00)) - return _scan_for_start_code (data, offset, size); - - /* set the state to something that does not match */ - state = ~pattern; - - /* now find data */ - for (i = 0; i < size; i++) { - /* throw away one byte and move in the next byte */ - state = ((state << 8) | data[i]); - if (G_UNLIKELY ((state & mask) == pattern)) { - /* we have a match but we need to have skipped at - * least 4 bytes to fill the state. */ - if (G_LIKELY (i >= 3)) - return offset + i - 3; - } - } - - /* nothing found */ - return -1; +/** + * gst_byte_reader_masked_scan_uint32_peek: + * @reader: a #GstByteReader + * @mask: mask to apply to data before matching against @pattern + * @pattern: pattern to match (after mask is applied) + * @offset: offset from which to start scanning, relative to the current + * position + * @size: number of bytes to scan from offset + * @value: pointer to uint32 to return matching data + * + * Scan for pattern @pattern with applied mask @mask in the byte reader data, + * starting from offset @offset relative to the current position. + * + * The bytes in @pattern and @mask are interpreted left-to-right, regardless + * of endianness. All four bytes of the pattern must be present in the + * byte reader data for it to match, even if the first or last bytes are masked + * out. + * + * It is an error to call this function without making sure that there is + * enough data (offset+size bytes) in the byte reader. + * + * Returns: offset of the first match, or -1 if no match was found. + * + * Since: 1.6 + */ +guint +gst_byte_reader_masked_scan_uint32_peek (const GstByteReader * reader, + guint32 mask, guint32 pattern, guint offset, guint size, guint32 * value) +{ + return _masked_scan_uint32_peek (reader, mask, pattern, offset, size, value); } #define GST_BYTE_READER_SCAN_STRING(bits) \ diff --git a/libs/gst/base/gstbytereader.h b/libs/gst/base/gstbytereader.h index 8745ef654e..7182d27872 100644 --- a/libs/gst/base/gstbytereader.h +++ b/libs/gst/base/gstbytereader.h @@ -141,6 +141,12 @@ guint gst_byte_reader_masked_scan_uint32 (const GstByteReader * reader guint32 pattern, guint offset, guint size); +guint gst_byte_reader_masked_scan_uint32_peek (const GstByteReader * reader, + guint32 mask, + guint32 pattern, + guint offset, + guint size, + guint32 * value); /** * GST_BYTE_READER_INIT: diff --git a/tests/check/libs/bytereader.c b/tests/check/libs/bytereader.c index ecb3ddbd38..d2a63cc11f 100644 --- a/tests/check/libs/bytereader.c +++ b/tests/check/libs/bytereader.c @@ -467,7 +467,17 @@ GST_START_TEST (test_position_tracking) GST_END_TEST; #define do_scan(r,m,p,o,s,x) \ - fail_unless_equals_int (gst_byte_reader_masked_scan_uint32 (r,m,p,o,s), x); +G_STMT_START { \ + fail_unless_equals_int (gst_byte_reader_masked_scan_uint32 (r,m,p,o,s), x); \ + if (x != -1) { \ + guint32 v, res_v; \ + const guint8 *rdata = NULL; \ + fail_unless (gst_byte_reader_peek_data (r, x + 4, &rdata)); \ + res_v = GST_READ_UINT32_BE (rdata + x); \ + fail_unless_equals_int (gst_byte_reader_masked_scan_uint32_peek (r,m,p,o,s,&v), x); \ + fail_unless_equals_int (v, res_v); \ + } \ +} G_STMT_END; GST_START_TEST (test_scan) { diff --git a/win32/common/libgstbase.def b/win32/common/libgstbase.def index 2713a09b0d..bd31d95bd9 100644 --- a/win32/common/libgstbase.def +++ b/win32/common/libgstbase.def @@ -153,6 +153,7 @@ EXPORTS gst_byte_reader_get_uint8 gst_byte_reader_init gst_byte_reader_masked_scan_uint32 + gst_byte_reader_masked_scan_uint32_peek gst_byte_reader_new gst_byte_reader_peek_data gst_byte_reader_peek_float32_be