gst/typefind/gsttypefindfunctions.c: Use data scan helper in aac typefinder and stop...
authorTim-Philipp Müller <tim@centricular.net>
Mon, 19 May 2008 15:59:40 +0000 (15:59 +0000)
committerTim-Philipp Müller <tim@centricular.net>
Mon, 19 May 2008 15:59:40 +0000 (15:59 +0000)
Original commit message from CVS:
* gst/typefind/gsttypefindfunctions.c: (aac_type_find):
Use data scan helper in aac typefinder and stop scanning
for headers when we've found a type. Also fix potential invalid
memory access when calculating the frame length.

ChangeLog
gst/typefind/gsttypefindfunctions.c

index 3807f6f1ecc1d7c71693dff1f6a6cac3e9d04729..320fb722df26ab0f64e854865dd3e5cc2e900913 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2008-05-19  Tim-Philipp Müller  <tim.muller at collabora co uk>
+
+       * gst/typefind/gsttypefindfunctions.c: (aac_type_find):
+         Use data scan helper in aac typefinder and stop scanning
+         for headers when we've found a type. Also fix potential invalid
+         memory access when calculating the frame length.
+
 2008-05-19  Tim-Philipp Müller  <tim.muller at collabora co uk>
 
        * gst/typefind/gsttypefindfunctions.c: (data_scan_ctx_ensure_data),
index d9eae0ecef1fc09a8dcc08d85c8938da2b46f675..c42842228da7ea09bac66d87a530493f4e3e297a 100644 (file)
@@ -547,68 +547,65 @@ static GstStaticCaps aac_caps = GST_STATIC_CAPS ("audio/mpeg, "
 static void
 aac_type_find (GstTypeFind * tf, gpointer unused)
 {
-  guint8 *data = gst_type_find_peek (tf, 0, AAC_AMOUNT);
-  gint snc;
-
-  /* detect adts header or adif header.
-   * The ADIF header is 4 bytes, that should be OK. The ADTS header, on
-   * the other hand, is 14 bits only, so we require one valid frame with
-   * again a valid syncpoint on the next one (28 bits) for certainty. We
-   * require 4 kB, which is quite a lot, since frames are generally 200-400
-   * bytes.
-   */
-  if (data) {
-    gint n;
-
-    for (n = 0; n < AAC_AMOUNT - 3; n++) {
-      snc = GST_READ_UINT16_BE (&data[n]);
-      if ((snc & 0xfff6) == 0xfff0) {
-        /* ADTS header - find frame length */
-        gint len;
-
-        GST_DEBUG ("Found one ADTS syncpoint at offset 0x%x, tracing next...",
-            n);
-        if (AAC_AMOUNT - n < 5) {
-          GST_DEBUG ("Not enough data to parse ADTS header");
-          break;
-        }
-        len = ((data[n + 3] & 0x03) << 11) |
-            (data[n + 4] << 3) | ((data[n + 5] & 0xe0) >> 5);
-        if (n + len + 2 >= AAC_AMOUNT) {
-          GST_DEBUG ("Next frame is not within reach");
-          break;
-        } else if (len == 0) {
-          continue;
-        }
-
-        snc = GST_READ_UINT16_BE (&data[n + len]);
-        if ((snc & 0xfff6) == 0xfff0) {
-          gint mpegversion = (data[n + 1] & 0x08) ? 2 : 4;
-          GstCaps *caps = gst_caps_new_simple ("audio/mpeg",
-              "framed", G_TYPE_BOOLEAN, FALSE,
-              "mpegversion", G_TYPE_INT, mpegversion,
-              NULL);
+  DataScanCtx c = { 0, NULL, 0 };
 
-          gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, caps);
-          gst_caps_unref (caps);
+  while (c.offset < AAC_AMOUNT) {
+    guint snc, len;
+
+    /* detect adts header or adif header.
+     * The ADIF header is 4 bytes, that should be OK. The ADTS header, on
+     * the other hand, is 14 bits only, so we require one valid frame with
+     * again a valid syncpoint on the next one (28 bits) for certainty. We
+     * require 4 kB, which is quite a lot, since frames are generally 200-400
+     * bytes.
+     */
+    if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 6)))
+      break;
 
-          GST_DEBUG ("Found ADTS-%d syncpoint at offset 0x%x (framelen %u)",
-              mpegversion, n, len);
-          break;
-        }
+    snc = GST_READ_UINT16_BE (c.data);
+    if (G_UNLIKELY ((snc & 0xfff6) == 0xfff0)) {
+      /* ADTS header - find frame length */
+      GST_DEBUG ("Found one ADTS syncpoint at offset 0x%x, tracing next...",
+          c.offset);
+      len = ((c.data[3] & 0x03) << 11) |
+          (c.data[4] << 3) | ((c.data[5] & 0xe0) >> 5);
+
+      if (len == 0 || !data_scan_ctx_ensure_data (tf, &c, len + 2)) {
+        GST_DEBUG ("Wrong sync or next frame not within reach, len=%u", len);
+        goto next;
+      }
 
-        GST_DEBUG ("No next frame found... (should be at 0x%x)", n + len);
-      } else if (!memcmp (&data[n], "ADIF", 4)) {
-        /* ADIF header */
+      snc = GST_READ_UINT16_BE (c.data + len);
+      if ((snc & 0xfff6) == 0xfff0) {
+        gint mpegversion = (c.data[1] & 0x08) ? 2 : 4;
         GstCaps *caps = gst_caps_new_simple ("audio/mpeg",
             "framed", G_TYPE_BOOLEAN, FALSE,
-            "mpegversion", G_TYPE_INT, 4,
+            "mpegversion", G_TYPE_INT, mpegversion,
             NULL);
 
         gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, caps);
         gst_caps_unref (caps);
+        GST_DEBUG ("Found second ADTS-%d syncpoint at offset 0x%x, framelen %u",
+            mpegversion, c.offset, len);
+        break;
       }
+
+      GST_DEBUG ("No next frame found... (should have been at 0x%x)", len);
+    } else if (!memcmp (c.data, "ADIF", 4)) {
+      /* ADIF header */
+      GstCaps *caps = gst_caps_new_simple ("audio/mpeg",
+          "framed", G_TYPE_BOOLEAN, FALSE,
+          "mpegversion", G_TYPE_INT, 4,
+          NULL);
+
+      gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, caps);
+      gst_caps_unref (caps);
+      break;
     }
+
+  next:
+
+    data_scan_ctx_advance (tf, &c, 1);
   }
 }