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: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1179>
This commit is contained in:
Edward Hervey 2021-09-05 11:57:18 +02:00 committed by GStreamer Marge Bot
parent 74e9d44db3
commit 0ff569d408
3 changed files with 16 additions and 1 deletions

View 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 &&

View 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 {

View 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;