[gst-cvs] gst-plugins-bad: mpegtsparse: detect packetsize and don' t just assume 188 bytes.

Zaheer Abbas Merali zaheer at kemper.freedesktop.org
Sun Sep 20 05:27:13 PDT 2009


Module: gst-plugins-bad
Branch: master
Commit: bdf11016fa4cbc2d5cdf8f974b07e23fe1dbbc49
URL:    http://cgit.freedesktop.org/gstreamer/gst-plugins-bad/commit/?id=bdf11016fa4cbc2d5cdf8f974b07e23fe1dbbc49

Author: Zaheer Abbas Merali <zaheerabbas at merali.org>
Date:   Sun Sep 20 12:38:00 2009 +0100

mpegtsparse: detect packetsize and don't just assume 188 bytes.

---

 gst/mpegdemux/mpegtspacketizer.c |   65 ++++++++++++++++++++++++++++++++++++--
 gst/mpegdemux/mpegtspacketizer.h |   10 ++++++
 2 files changed, 72 insertions(+), 3 deletions(-)

diff --git a/gst/mpegdemux/mpegtspacketizer.c b/gst/mpegdemux/mpegtspacketizer.c
index eeb5652..58e379a 100644
--- a/gst/mpegdemux/mpegtspacketizer.c
+++ b/gst/mpegdemux/mpegtspacketizer.c
@@ -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);
diff --git a/gst/mpegdemux/mpegtspacketizer.h b/gst/mpegdemux/mpegtspacketizer.h
index f2e47a8..f30231f 100644
--- a/gst/mpegdemux/mpegtspacketizer.h
+++ b/gst/mpegdemux/mpegtspacketizer.h
@@ -28,6 +28,14 @@
 #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 {





More information about the Gstreamer-commits mailing list