gst/typefind/gsttypefindfunctions.c: Fix MPEG-1 stream typefinding.
authorRonald S. Bultje <rbultje@ronald.bitfreak.net>
Fri, 23 Jan 2004 16:55:21 +0000 (16:55 +0000)
committerRonald S. Bultje <rbultje@ronald.bitfreak.net>
Fri, 23 Jan 2004 16:55:21 +0000 (16:55 +0000)
Original commit message from CVS:
2004-01-23  Ronald Bultje  <rbultje@ronald.bitfreak.net>

* gst/typefind/gsttypefindfunctions.c: (mpeg1_parse_header),
(mpeg1_sys_type_find):
Fix MPEG-1 stream typefinding.

ChangeLog
gst/typefind/gsttypefindfunctions.c

index 04b65a9..210572e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2004-01-23  Ronald Bultje  <rbultje@ronald.bitfreak.net>
 
+       * gst/typefind/gsttypefindfunctions.c: (mpeg1_parse_header),
+       (mpeg1_sys_type_find):
+         Fix MPEG-1 stream typefinding.
+
+2004-01-23  Ronald Bultje  <rbultje@ronald.bitfreak.net>
+
        * gst/typefind/gsttypefindfunctions.c: (mpeg2_sys_type_find):
          Fix typefinding for MPEG-1 system streams, similar to MPEG-2.
 
index 8b1db63..6183e6b 100644 (file)
@@ -449,74 +449,94 @@ mpeg2_sys_type_find (GstTypeFind *tf, gpointer unused)
 static guint
 mpeg1_parse_header (GstTypeFind *tf, guint64 offset)
 {
-  guint8 *data = gst_type_find_peek (tf, offset, 18);
+  guint8 *data = gst_type_find_peek (tf, offset, 4);
   guint size;
   
   if (!data) {
-    GST_LOG ("couldn't get 18 bytes to parse MPEG header");
+    GST_LOG ("couldn't get MPEG header bytes");
     return 1;
   }
-  
-  /* check header */
-  if (!IS_MPEG_HEADER (data)) {
-    GST_LOG ("This isn't an MPEG header");
-    return 0;
-  }
-  data += 4;
 
-  /* check marker bits */
-  if ((*data & 0xF1) != 0x21) {
-    GST_LOG ("marker bits in byte 4 don't match");
-    return 0;
-  }
-  data += 2;
-  if ((*data & 0x01) != 0x01) {
-    GST_LOG ("marker bits in byte 6 don't match");
-    return 0;
-  }
-  data += 2;
-  if ((*data & 0x01) != 0x01) {
-    GST_LOG ("marker bits in byte 8 don't match");
+  if (data[0] != 0 || data[1] != 0 || data[2] != 1) {
     return 0;
   }
-  data ++;
-  if ((*data & 0x80) != 0x80) {
-    GST_LOG ("marker bits in byte 9 don't match");
-    return 0;
-  }
-  data += 2;
-  if ((*data & 0x01) != 0x01) {
-    GST_LOG ("marker bits in byte 11 don't match");
-    return 0;
-  }
-  data++;
-  
-  if (!IS_MPEG_PACKET_HEADER (data) &&
-      !IS_MPEG_SYSTEM_HEADER (data)) {
-    GST_LOG ("MPEG packet header doesn't match: %8.8X", GUINT32_FROM_BE (*((guint32 *) data)));
-    return 0;
+  offset += 4;
+
+  switch (data[3]) {
+    case 0xBA: /* pack header */
+      data = gst_type_find_peek (tf, offset, 8);
+      if (!data) {
+        GST_LOG ("couldn't get MPEG pack header bytes");
+        return 1;
+      }
+      size = 12;
+      /* check marker bits */
+      if ((data[0] & 0xF1) != 0x21 ||
+          (data[2] & 0x01) != 0x01 ||
+          (data[4] & 0x01) != 0x01 ||
+          (data[5] & 0x80) != 0x80 ||
+          (data[7] & 0x01) != 0x01)
+        return 0;
+      break;
+
+    case 0xB9: /* ISO end code */
+      size = 4;
+      break;
+
+    case 0xBB: /* system header */
+      data = gst_type_find_peek (tf, offset, 2);
+      if (!data) {
+        GST_LOG ("couldn't get MPEG pack header bytes");
+        return 1;
+      }
+      size = GUINT16_FROM_BE (* (guint16 *) data) + 6;
+      offset += 2;
+      data = gst_type_find_peek (tf, offset, size - 6);
+      if (!data) {
+        GST_LOG ("couldn't get MPEG pack header bytes");
+        return 1;
+      }
+      /* check marker bits */
+      if ((data[0] & 0x80) != 0x80 ||
+          (data[2] & 0x01) != 0x01 ||
+          (data[4] & 0x20) != 0x20)
+        return 0;
+      /* check stream marker bits */
+      for (offset = 6; offset < (size - 6); offset += 3) {
+        if (data[offset] <= 0xBB ||
+            (data[offset + 1] & 0xC0) != 0xC0)
+          return 0;
+      }
+      break;
+
+    default:
+      if (data[3] < 0xB9)
+        return 0;
+      data = gst_type_find_peek (tf, offset, 2);
+      if (!data) {
+        GST_LOG ("couldn't get MPEG pack header bytes");
+        return 1;
+      }
+      size = GUINT16_FROM_BE (* (guint16 *) data) + 6;
+      /* FIXME: we could check PTS/DTS marker bits here... (bit overkill) */
+      break;
   }
-    
-  data += 4;
-  
-  size = GUINT16_FROM_BE (*((guint16 *) data)) + 18;
 
-  GST_DEBUG ("found mpeg1 packet at offset %"G_GUINT64_FORMAT" with size %u", offset, size);
   return size;
 }
 /* calculation of possibility to identify random data as mpeg systemstream:
- * bits that must match in header detection:           65
- * chance that random data is identifed:               1/2^65
+ * bits that must match in header detection:           32 (or more)
+ * chance that random data is identifed:               1/2^32
  * chance that GST_MPEG_TYPEFIND_TRY_HEADERS headers are identified:   
- *                                     1/2^(65*GST_MPEG_TYPEFIND_TRY_HEADERS)
+ *                                     1/2^(32*GST_MPEG_TYPEFIND_TRY_HEADERS)
  * chance that this happens in GST_MPEG_TYPEFIND_TRY_SYNC bytes:
- *                                     1-(1-1/2^(65*GST_MPEG_TYPEFIND_TRY_HEADERS))^GST_MPEG_TYPEFIND_TRY_SYNC
+ *                                     1-(1+1/2^(32*GST_MPEG_TYPEFIND_TRY_HEADERS)^GST_MPEG_TYPEFIND_TRY_SYNC)
  * for current values:
- *                                     1-(1-1/2^(65*2)^50000
- *                                   = 3.6734..*10^-35
+ *                                     1-(1+1/2^(32*4)^101024)
+ *                                   = <some_number>
  */
-#define GST_MPEG_TYPEFIND_TRY_HEADERS 2
-#define GST_MPEG_TYPEFIND_TRY_SYNC (GST_TYPE_FIND_MAXIMUM * 500) /* 50kB */
+#define GST_MPEG_TYPEFIND_TRY_HEADERS 4
+#define GST_MPEG_TYPEFIND_TRY_SYNC (100 * 1024) /* 100kB */
 #define GST_MPEG_TYPEFIND_SYNC_SIZE 2048
 static void
 mpeg1_sys_type_find (GstTypeFind *tf, gpointer unused)
@@ -538,7 +558,7 @@ mpeg1_sys_type_find (GstTypeFind *tf, gpointer unused)
       guint found = 0;
       guint packet_size = 0;
       guint64 offset = skipped;
-      
+
       while (found < GST_MPEG_TYPEFIND_TRY_HEADERS) {
        packet_size = mpeg1_parse_header (tf, offset);
        if (packet_size <= 1)