tsdemux: Handle "negative" timestamps
authorEdward Hervey <edward@centricular.com>
Sun, 5 Sep 2021 09:57:18 +0000 (11:57 +0200)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Mon, 18 Oct 2021 11:23:25 +0000 (11:23 +0000)
This is only enabled in push time mode. Furthermore it's only enabled for now if
PCR is to be ignored.

The problem is dealing with streams where the initial PTS/DTS observation might
be greater than following ones (from other PID for example). Before this patch,
this would result in sending buffers without any timestamp which would cause a
wide variety of issues.

Instead, pad segment and buffer timestamps with an extra
value (packetizer->extra_shift, default to 2s), to ensure that we can get valid
timestamps on outgoing buffers (even if that means they are before the segment
start).

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1179>

subprojects/gst-plugins-bad/gst/mpegtsdemux/mpegtspacketizer.c
subprojects/gst-plugins-bad/gst/mpegtsdemux/mpegtspacketizer.h
subprojects/gst-plugins-bad/gst/mpegtsdemux/tsdemux.c

index 0d00ed7..de8b571 100644 (file)
@@ -285,6 +285,7 @@ mpegts_packetizer_init (MpegTSPacketizer2 * packetizer)
   packetizer->pcr_discont_threshold = GST_SECOND;
   packetizer->last_pts = GST_CLOCK_TIME_NONE;
   packetizer->last_dts = GST_CLOCK_TIME_NONE;
+  packetizer->extra_shift = 0;
 }
 
 static void
@@ -2277,7 +2278,7 @@ mpegts_packetizer_pts_to_ts (MpegTSPacketizer2 * packetizer,
         GST_TIME_ARGS (pcrtable->base_pcrtime),
         GST_TIME_ARGS (pcrtable->base_time),
         GST_TIME_ARGS (pcrtable->pcroffset));
-    res = pts + pcrtable->pcroffset;
+    res = pts + pcrtable->pcroffset + packetizer->extra_shift;
 
     /* Don't return anything if we differ too much against last seen PCR */
     if (G_UNLIKELY (pcr_pid != 0x1fff &&
index b2bfcfb..f8ee1b9 100644 (file)
@@ -287,6 +287,10 @@ struct _MpegTSPacketizer2 {
   /* PTS/DTS of last buffer */
   GstClockTime last_pts;
   GstClockTime last_dts;
+
+  /* Extra time offset to handle values before initial PCR.
+   * This will be added to all converted timestamps */
+  GstClockTime extra_shift;
 };
 
 struct _MpegTSPacketizer2Class {
index 17655d1..bf6ad58 100644 (file)
@@ -1051,6 +1051,16 @@ push_event (MpegTSBase * base, GstEvent * event)
   gboolean early_ret = FALSE;
 
   if (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT) {
+    if (base->segment.format == GST_FORMAT_TIME && base->ignore_pcr) {
+      /* Shift start/stop values by 2s */
+      base->packetizer->extra_shift = 2 * GST_SECOND;
+      if (GST_CLOCK_TIME_IS_VALID (base->segment.start))
+        base->segment.start += 2 * GST_SECOND;
+      if (GST_CLOCK_TIME_IS_VALID (base->segment.stop))
+        base->segment.stop += 2 * GST_SECOND;
+      if (GST_CLOCK_TIME_IS_VALID (base->segment.position))
+        base->segment.position += 2 * GST_SECOND;
+    }
     GST_DEBUG_OBJECT (base, "Ignoring segment event (recreated later)");
     gst_event_unref (event);
     return TRUE;