mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 01:00:37 +00:00
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
This commit is contained in:
parent
fbe2477fae
commit
f8323b17fb
4 changed files with 99 additions and 35 deletions
|
@ -794,6 +794,55 @@ _scan_for_start_code (const guint8 * data, guint offset, guint size)
|
||||||
return -1;
|
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:
|
* gst_byte_reader_masked_scan_uint32:
|
||||||
* @reader: a #GstByteReader
|
* @reader: a #GstByteReader
|
||||||
|
@ -840,41 +889,39 @@ guint
|
||||||
gst_byte_reader_masked_scan_uint32 (const GstByteReader * reader, guint32 mask,
|
gst_byte_reader_masked_scan_uint32 (const GstByteReader * reader, guint32 mask,
|
||||||
guint32 pattern, guint offset, guint size)
|
guint32 pattern, guint offset, guint size)
|
||||||
{
|
{
|
||||||
const guint8 *data;
|
return _masked_scan_uint32_peek (reader, mask, pattern, offset, size, NULL);
|
||||||
guint32 state;
|
}
|
||||||
guint i;
|
|
||||||
|
|
||||||
g_return_val_if_fail (size > 0, -1);
|
/**
|
||||||
g_return_val_if_fail ((guint64) offset + size <= reader->size - reader->byte,
|
* gst_byte_reader_masked_scan_uint32_peek:
|
||||||
-1);
|
* @reader: a #GstByteReader
|
||||||
|
* @mask: mask to apply to data before matching against @pattern
|
||||||
/* we can't find the pattern with less than 4 bytes */
|
* @pattern: pattern to match (after mask is applied)
|
||||||
if (G_UNLIKELY (size < 4))
|
* @offset: offset from which to start scanning, relative to the current
|
||||||
return -1;
|
* position
|
||||||
|
* @size: number of bytes to scan from offset
|
||||||
data = reader->data + reader->byte + offset;
|
* @value: pointer to uint32 to return matching data
|
||||||
|
*
|
||||||
/* Handle special case found in MPEG and H264 */
|
* Scan for pattern @pattern with applied mask @mask in the byte reader data,
|
||||||
if ((pattern == 0x00000100) && (mask == 0xffffff00))
|
* starting from offset @offset relative to the current position.
|
||||||
return _scan_for_start_code (data, offset, size);
|
*
|
||||||
|
* The bytes in @pattern and @mask are interpreted left-to-right, regardless
|
||||||
/* set the state to something that does not match */
|
* of endianness. All four bytes of the pattern must be present in the
|
||||||
state = ~pattern;
|
* byte reader data for it to match, even if the first or last bytes are masked
|
||||||
|
* out.
|
||||||
/* now find data */
|
*
|
||||||
for (i = 0; i < size; i++) {
|
* It is an error to call this function without making sure that there is
|
||||||
/* throw away one byte and move in the next byte */
|
* enough data (offset+size bytes) in the byte reader.
|
||||||
state = ((state << 8) | data[i]);
|
*
|
||||||
if (G_UNLIKELY ((state & mask) == pattern)) {
|
* Returns: offset of the first match, or -1 if no match was found.
|
||||||
/* we have a match but we need to have skipped at
|
*
|
||||||
* least 4 bytes to fill the state. */
|
* Since: 1.6
|
||||||
if (G_LIKELY (i >= 3))
|
*/
|
||||||
return offset + i - 3;
|
guint
|
||||||
}
|
gst_byte_reader_masked_scan_uint32_peek (const GstByteReader * reader,
|
||||||
}
|
guint32 mask, guint32 pattern, guint offset, guint size, guint32 * value)
|
||||||
|
{
|
||||||
/* nothing found */
|
return _masked_scan_uint32_peek (reader, mask, pattern, offset, size, value);
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define GST_BYTE_READER_SCAN_STRING(bits) \
|
#define GST_BYTE_READER_SCAN_STRING(bits) \
|
||||||
|
|
|
@ -141,6 +141,12 @@ guint gst_byte_reader_masked_scan_uint32 (const GstByteReader * reader
|
||||||
guint32 pattern,
|
guint32 pattern,
|
||||||
guint offset,
|
guint offset,
|
||||||
guint size);
|
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:
|
* GST_BYTE_READER_INIT:
|
||||||
|
|
|
@ -467,7 +467,17 @@ GST_START_TEST (test_position_tracking)
|
||||||
GST_END_TEST;
|
GST_END_TEST;
|
||||||
|
|
||||||
#define do_scan(r,m,p,o,s,x) \
|
#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)
|
GST_START_TEST (test_scan)
|
||||||
{
|
{
|
||||||
|
|
|
@ -153,6 +153,7 @@ EXPORTS
|
||||||
gst_byte_reader_get_uint8
|
gst_byte_reader_get_uint8
|
||||||
gst_byte_reader_init
|
gst_byte_reader_init
|
||||||
gst_byte_reader_masked_scan_uint32
|
gst_byte_reader_masked_scan_uint32
|
||||||
|
gst_byte_reader_masked_scan_uint32_peek
|
||||||
gst_byte_reader_new
|
gst_byte_reader_new
|
||||||
gst_byte_reader_peek_data
|
gst_byte_reader_peek_data
|
||||||
gst_byte_reader_peek_float32_be
|
gst_byte_reader_peek_float32_be
|
||||||
|
|
Loading…
Reference in a new issue