Fixes issues when a subtitle packet is received before PCR for the program has been received, leading to wildly jumping timestamps on the lavf client side as well as in the re-ordering logic.
This usually happens in case of multiplexes where the PCR of a program is not taken into account with subtitle tracks' DTS/PTS. In case someone actually wants to pass through all received packets, the behavior can be controlled with an AVOption. --- libavformat/mpegts.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index edf6b5701d..50404e8272 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -59,6 +59,12 @@ enum MpegTSFilterType { MPEGTS_PCR, }; +enum MpegTSPESSkipMode { + MPEGTS_PES_SKIP_MODE_SUBTITLES = 0, + MPEGTS_PES_SKIP_MODE_NONE, + MPEGTS_PES_SKIP_MODE_MAX, +}; + typedef struct MpegTSFilter MpegTSFilter; typedef int PESCallback (MpegTSFilter *f, const uint8_t *buf, int len, @@ -150,6 +156,8 @@ struct MpegTSContext { int resync_size; int merge_pmt_versions; + enum MpegTSPESSkipMode pes_packet_skip_mode; + /******************************************/ /* private mpegts data */ /* scan context */ @@ -182,6 +190,10 @@ static const AVOption options[] = { {.i64 = 0}, 0, 1, 0 }, {"skip_clear", "skip clearing programs", offsetof(MpegTSContext, skip_clear), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, 0 }, + {"skip_pes_packets_without_pcr", "Skip PES packets without PCR matching to rule", offsetof(MpegTSContext, pes_packet_skip_mode), AV_OPT_TYPE_INT, + {.i64 = MPEGTS_PES_SKIP_MODE_SUBTITLES}, MPEGTS_PES_SKIP_MODE_SUBTITLES, MPEGTS_PES_SKIP_MODE_MAX - 1, AV_OPT_FLAG_DECODING_PARAM , "skip_pes_packets_without_pcr"}, + { "subtitles", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_PES_SKIP_MODE_SUBTITLES }, INT_MIN, INT_MAX, AV_OPT_FLAG_DECODING_PARAM, "skip_pes_packets_without_pcr" }, + { "none", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_PES_SKIP_MODE_NONE }, INT_MIN, INT_MAX, AV_OPT_FLAG_DECODING_PARAM, "skip_pes_packets_without_pcr" }, { NULL }, }; @@ -1219,6 +1231,7 @@ skip: || pes->st->codecpar->codec_id == AV_CODEC_ID_DVB_SUBTITLE) ) { AVProgram *p = NULL; + int pcr_found = 0; while ((p = av_find_program_from_stream(pes->stream, p, pes->st->index))) { if (p->pcr_pid != -1 && p->discard != AVDISCARD_ALL) { MpegTSFilter *f = pes->ts->pids[p->pcr_pid]; @@ -1242,6 +1255,7 @@ skip: // and the pcr error to this packet should be no more than 100 ms. // TODO: we should interpolate the PCR, not just use the last one int64_t pcr = f->last_pcr / 300; + pcr_found = 1; pes->st->pts_wrap_reference = st->pts_wrap_reference; pes->st->pts_wrap_behavior = st->pts_wrap_behavior; if (pes->dts == AV_NOPTS_VALUE || pes->dts < pcr) { @@ -1258,6 +1272,14 @@ skip: } } } + + if (!pcr_found && + ts->pes_packet_skip_mode != MPEGTS_PES_SKIP_MODE_NONE) { + av_log(pes->stream, AV_LOG_VERBOSE, + "Skipping non-trustworthy PES packet for PID %d as PCR hasn't been received yet.\n", + pes->pid); + pes->state = MPEGTS_SKIP; + } } } break; -- 2.20.0 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel