mpegtsdemux: handle pads with no data
authorVincent Penquerc'h <vincent.penquerch@collabora.co.uk>
Mon, 26 Sep 2011 11:43:27 +0000 (12:43 +0100)
committerVincent Penquerc'h <vincent.penquerch@collabora.co.uk>
Mon, 28 Nov 2011 15:08:13 +0000 (15:08 +0000)
Some streams declare PIDs but will not send data for them.
Ensure we time out on those, and both send new segments to
keep their time synchronized with the rest, and do not wait
forever before deciding to signal no-more-pads.

https://bugzilla.gnome.org/show_bug.cgi?id=659924

gst/mpegdemux/gstmpegtsdemux.c

index 1fab2b0bd61011948aa203b9f04d6cb7d6df3c2c..b4cae0711fb4380b577a470087004658ff2c1eca 100644 (file)
@@ -1051,6 +1051,48 @@ done:
   return ret;
 }
 
+static void
+gst_mpegts_demux_sync_streams (GstMpegTSDemux * demux, GstClockTime time)
+{
+  gint i;
+
+  for (i = 0; i < MPEGTS_MAX_PID + 1; i++) {
+    GstMpegTSStream *stream = demux->streams[i];
+    if (!stream)
+      continue;
+
+    /* Theoretically, we should be doing this for all streams, but we're only
+     * doing it for non A/V streams, for which data might not be forthcoming. */
+    if (stream->flags & (MPEGTS_STREAM_FLAG_IS_AUDIO |
+            MPEGTS_STREAM_FLAG_IS_VIDEO))
+      continue;
+
+    /* at start, lock all streams onto the first timestamp */
+    if (G_UNLIKELY (stream->last_time == 0))
+      stream->last_time = time;
+
+    /* Does this stream lag? Random threshold of 2 seconds */
+    if (GST_CLOCK_DIFF (stream->last_time, time) > (2 * GST_SECOND)) {
+      /* If the pad was not added yet, do not wait any longer for
+         any pad that might be waiting for data */
+      if (!stream->pad && demux->pending_pads > 0) {
+        demux->pending_pads = 0;
+        gst_element_no_more_pads (GST_ELEMENT (demux));
+      }
+
+      if (stream->pad) {
+        GST_DEBUG_OBJECT (stream, "synchronizing stream with others by "
+            "advancing time from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
+            GST_TIME_ARGS (stream->last_time), GST_TIME_ARGS (time));
+        stream->last_time = time;
+        /* advance stream time (FIXME: is this right, esp. time_pos?) */
+        gst_pad_push_event (stream->pad,
+            gst_event_new_new_segment (TRUE, 1.0,
+                GST_FORMAT_TIME, stream->last_time, -1, stream->last_time));
+      }
+    }
+  }
+}
 
 static GstFlowReturn
 gst_mpegts_demux_data_cb (GstPESFilter * filter, gboolean first,
@@ -1271,6 +1313,9 @@ gst_mpegts_demux_data_cb (GstPESFilter * filter, gboolean first,
   ret = gst_pad_push (srcpad, buffer);
   ret = gst_mpegts_demux_combine_flows (demux, stream, ret);
 
+  if (GST_CLOCK_TIME_IS_VALID (time))
+    gst_mpegts_demux_sync_streams (demux, time);
+
   return ret;
 
   /* ERROR */