From 2e4315ab5cb63b9f20e370b73f1ac4ff19a4d3d0 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 30 Sep 2024 15:51:04 +0300 Subject: [PATCH] mpegtsdemux: Handle PTS/DTS wraparound with ignore-pcr=true The wraparound handling code assumes that the PCR gets updated regularly for being able to detect wraparounds. With ignore-pcr=true that was not the case and it stayed initialized at 1h forever. To avoid this problem, update the fake PCR whenever the PTS advanced by more than 5s, and also detect wraparounds in these fake PCRs. Problem can be reproduced with $ gst-launch-1.0 videotestsrc pattern=black ! video/x-raw,framerate=1/5 ! \ x264enc speed-preset=ultrafast tune=zerolatency ! mpegtsmux ! \ tsdemux ignore-pcr=true ! fakesink which restarts timestamps at 0 after around 26h30m. Part-of: --- .../gst/mpegtsdemux/mpegtspacketizer.c | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/subprojects/gst-plugins-bad/gst/mpegtsdemux/mpegtspacketizer.c b/subprojects/gst-plugins-bad/gst/mpegtsdemux/mpegtspacketizer.c index fdc7851dcd..c50dec31e0 100644 --- a/subprojects/gst-plugins-bad/gst/mpegtsdemux/mpegtspacketizer.c +++ b/subprojects/gst-plugins-bad/gst/mpegtsdemux/mpegtspacketizer.c @@ -2261,10 +2261,24 @@ mpegts_packetizer_pts_to_ts_internal (MpegTSPacketizer2 * packetizer, PACKETIZER_GROUP_LOCK (packetizer); pcrtable = get_pcr_table (packetizer, pcr_pid); - if (!GST_CLOCK_TIME_IS_VALID (pcrtable->base_time) && pcr_pid == 0x1fff && - GST_CLOCK_TIME_IS_VALID (packetizer->last_in_time)) { - pcrtable->base_time = packetizer->last_in_time; - pcrtable->base_pcrtime = pts; + if (pcr_pid == 0x1fff && GST_CLOCK_TIME_IS_VALID (packetizer->last_in_time)) { + if (!GST_CLOCK_TIME_IS_VALID (pcrtable->base_time)) { + pcrtable->base_time = packetizer->last_in_time; + pcrtable->base_pcrtime = pts; + } else if (check_diff) { + /* Handle discont and wraparound */ + guint64 tmp_pts = pts + pcrtable->pcroffset + packetizer->extra_shift; + if (pcrtable->base_pcrtime < tmp_pts + && tmp_pts - pcrtable->base_pcrtime >= 5 * GST_SECOND) { + guint64 diff = tmp_pts - pcrtable->base_pcrtime - 2 * GST_SECOND; + + pcrtable->base_time += diff; + pcrtable->base_pcrtime += diff; + } else if (pcrtable->base_pcrtime > tmp_pts + && pcrtable->base_pcrtime > PCR_GST_MAX_VALUE / 2) { + pcrtable->pcroffset += PCR_GST_MAX_VALUE; + } + } } /* Use clock skew if present */ -- 2.34.1