From 0ff569d408c13e4e9657ba62b6b6bd490129462e Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Sun, 5 Sep 2021 11:57:18 +0200 Subject: [PATCH] tsdemux: Handle "negative" timestamps 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: --- .../gst-plugins-bad/gst/mpegtsdemux/mpegtspacketizer.c | 3 ++- .../gst-plugins-bad/gst/mpegtsdemux/mpegtspacketizer.h | 4 ++++ subprojects/gst-plugins-bad/gst/mpegtsdemux/tsdemux.c | 10 ++++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/subprojects/gst-plugins-bad/gst/mpegtsdemux/mpegtspacketizer.c b/subprojects/gst-plugins-bad/gst/mpegtsdemux/mpegtspacketizer.c index 0d00ed72da..de8b57119d 100644 --- a/subprojects/gst-plugins-bad/gst/mpegtsdemux/mpegtspacketizer.c +++ b/subprojects/gst-plugins-bad/gst/mpegtsdemux/mpegtspacketizer.c @@ -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 && diff --git a/subprojects/gst-plugins-bad/gst/mpegtsdemux/mpegtspacketizer.h b/subprojects/gst-plugins-bad/gst/mpegtsdemux/mpegtspacketizer.h index b2bfcfb50d..f8ee1b96e2 100644 --- a/subprojects/gst-plugins-bad/gst/mpegtsdemux/mpegtspacketizer.h +++ b/subprojects/gst-plugins-bad/gst/mpegtsdemux/mpegtspacketizer.h @@ -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 { diff --git a/subprojects/gst-plugins-bad/gst/mpegtsdemux/tsdemux.c b/subprojects/gst-plugins-bad/gst/mpegtsdemux/tsdemux.c index 17655d1984..bf6ad586f2 100644 --- a/subprojects/gst-plugins-bad/gst/mpegtsdemux/tsdemux.c +++ b/subprojects/gst-plugins-bad/gst/mpegtsdemux/tsdemux.c @@ -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;