bytereader: add gst_byte_reader_masked_scan_uint32_peek
authorThiago Santos <ts.santos@osg.sisa.samsung.com>
Thu, 24 Jul 2014 17:39:11 +0000 (14:39 -0300)
committerThiago Santos <ts.santos@osg.sisa.samsung.com>
Thu, 24 Jul 2014 20:00:09 +0000 (17:00 -0300)
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
libs/gst/base/gstbytereader.h
tests/check/libs/bytereader.c
win32/common/libgstbase.def

index b73a6793263554daebcd08c9fdfe4bff8c99ea86..69318411998af8e90c6b1d3ad2fb49dfab3303c4 100644 (file)
@@ -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;
-
-  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;
-    }
-  }
+  return _masked_scan_uint32_peek (reader, mask, pattern, offset, size, NULL);
+}
 
-  /* 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) \
index 8745ef654e52d44512d670dee4138e3a2e2c9540..7182d27872a86b7f3ed6bc16355ab9beb81e0e43 100644 (file)
@@ -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:
index ecb3ddbd38827d6ae79ceaf50a261c5ade940eca..d2a63cc11f48ec5c0dea6444ee18adb6add98a2e 100644 (file)
@@ -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)
 {
index 2713a09b0d98c9c275c2d4ba1feba52cd7e89e7f..bd31d95bd9541560b7a0b309d4bbe5b6262e700b 100644 (file)
@@ -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