mpegtsparse: detect packetsize and don't just assume 188 bytes.
authorZaheer Abbas Merali <zaheerabbas@merali.org>
Sun, 20 Sep 2009 11:38:00 +0000 (12:38 +0100)
committerZaheer Abbas Merali <zaheerabbas@merali.org>
Sun, 20 Sep 2009 12:25:34 +0000 (13:25 +0100)
gst/mpegdemux/mpegtspacketizer.c
gst/mpegdemux/mpegtspacketizer.h

index eeb56529d21c7fa6410a9a266cf41023af5c0b1e..58e379af6305fc8ef396839004a23230ed0c8446 100644 (file)
@@ -167,6 +167,7 @@ mpegts_packetizer_init (MpegTSPacketizer * packetizer)
   packetizer->adapter = gst_adapter_new ();
   packetizer->streams = g_hash_table_new_full (g_direct_hash, g_direct_equal,
       NULL, mpegts_packetizer_destroy_streams_value);
+  packetizer->know_packet_size = FALSE;
 }
 
 static void
@@ -1965,10 +1966,61 @@ mpegts_packetizer_push (MpegTSPacketizer * packetizer, GstBuffer * buffer)
   gst_adapter_push (packetizer->adapter, buffer);
 }
 
+void
+mpegts_try_discover_packet_size (MpegTSPacketizer * packetizer)
+{
+  guint8 *dest;
+  int i, pos, j;
+  const guint psizes[] = { MPEGTS_NORMAL_PACKETSIZE,
+    MPEGTS_M2TS_PACKETSIZE,
+    MPEGTS_DVB_ASI_PACKETSIZE,
+    MPEGTS_ATSC_PACKETSIZE
+  };
+  /* wait for 3 sync bytes */
+  /* so first return if there is not enough data for 4 * max packetsize */
+  if (gst_adapter_available_fast (packetizer->adapter) <
+      MPEGTS_MAX_PACKETSIZE * 4)
+    return;
+  /* check for sync bytes */
+  dest = g_malloc (MPEGTS_MAX_PACKETSIZE * 4);
+  gst_adapter_copy (packetizer->adapter, dest, 0, MPEGTS_MAX_PACKETSIZE * 4);
+  /* find first sync byte */
+  pos = -1;
+  for (i = 0; i < MPEGTS_MAX_PACKETSIZE; i++) {
+    if (dest[i] == 0x47) {
+      for (j = 0; j < 4; j++) {
+        guint packetsize = psizes[j];
+        /* check each of the packet size possibilities in turn */
+        if (dest[i] == 0x47 && dest[i + packetsize] == 0x47 &&
+            dest[i + packetsize * 2] == 0x47 &&
+            dest[i + packetsize * 3] == 0x47) {
+          packetizer->know_packet_size = TRUE;
+          packetizer->packet_size = packetsize;
+          pos = i;
+          break;
+        }
+      }
+      break;
+    }
+  }
+  GST_DEBUG ("have packetsize detected: %d of %u bytes",
+      packetizer->know_packet_size, packetizer->packet_size);
+  /* flush to sync byte */
+  if (pos > 0)
+    gst_adapter_flush (packetizer->adapter, pos);
+  g_free (dest);
+}
+
+
 gboolean
 mpegts_packetizer_has_packets (MpegTSPacketizer * packetizer)
 {
-  return gst_adapter_available (packetizer->adapter) >= 188;
+  if (G_UNLIKELY (packetizer->know_packet_size == FALSE)) {
+    mpegts_try_discover_packet_size (packetizer);
+    if (!packetizer->know_packet_size)
+      return FALSE;
+  }
+  return gst_adapter_available (packetizer->adapter) >= packetizer->packet_size;
 }
 
 MpegTSPacketizerPacketReturn
@@ -1979,7 +2031,13 @@ mpegts_packetizer_next_packet (MpegTSPacketizer * packetizer,
   guint avail;
 
   packet->buffer = NULL;
-  while ((avail = gst_adapter_available (packetizer->adapter)) >= 188) {
+  if (G_UNLIKELY (!packetizer->know_packet_size)) {
+    mpegts_try_discover_packet_size (packetizer);
+    if (!packetizer->know_packet_size)
+      return PACKET_NEED_MORE;
+  }
+  while ((avail = gst_adapter_available (packetizer->adapter)) >=
+      packetizer->packet_size) {
     sync_byte = *gst_adapter_peek (packetizer->adapter, 1);
     if (G_UNLIKELY (sync_byte != 0x47)) {
       GST_DEBUG ("lost sync %02x", sync_byte);
@@ -1987,7 +2045,8 @@ mpegts_packetizer_next_packet (MpegTSPacketizer * packetizer,
       continue;
     }
 
-    packet->buffer = gst_adapter_take_buffer (packetizer->adapter, 188);
+    packet->buffer = gst_adapter_take_buffer (packetizer->adapter,
+        packetizer->packet_size);
     packet->data_start = GST_BUFFER_DATA (packet->buffer);
     packet->data_end =
         GST_BUFFER_DATA (packet->buffer) + GST_BUFFER_SIZE (packet->buffer);
index f2e47a8711a13029e715d8ffff0c1b9dd92527de..f30231ff27e7bbc06858b18566f4368271ed85e3 100644 (file)
 #include <gst/base/gstadapter.h>
 #include <glib.h>
 
+#define MPEGTS_NORMAL_PACKETSIZE  188
+#define MPEGTS_M2TS_PACKETSIZE    192
+#define MPEGTS_DVB_ASI_PACKETSIZE 204
+#define MPEGTS_ATSC_PACKETSIZE    208
+
+#define MPEGTS_MIN_PACKETSIZE MPEGTS_NORMAL_PACKETSIZE
+#define MPEGTS_MAX_PACKETSIZE MPEGTS_ATSC_PACKETSIZE
+
 G_BEGIN_DECLS
 
 #define GST_TYPE_MPEGTS_PACKETIZER \
@@ -52,6 +60,8 @@ struct _MpegTSPacketizer {
   /* streams hashed by pid */
   GHashTable *streams;
   gboolean disposed;
+  gboolean know_packet_size;
+  guint16 packet_size;
 };
 
 struct _MpegTSPacketizerClass {