From: Stefano Sabatini <stefasab@gmail.com> To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org> Cc: Stefano Sabatini <stefasab@gmail.com> Subject: [FFmpeg-devel] [PATCH 2/3] ffmpeg: review -dts_delta_threshold and -dts_delta_error options Date: Sat, 11 Feb 2023 17:29:00 +0100 Message-ID: <20230211162900.125018-1-stefasab@gmail.com> (raw) Review handling of -dts_delta_threshold and -dts_delta_error options in order to simplify a bit the logic and improve logging. --- fftools/ffmpeg.c | 101 +++++++++++++++++++++++++---------------- fftools/ffmpeg.h | 2 + fftools/ffmpeg_demux.c | 3 ++ 3 files changed, 68 insertions(+), 38 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 064ec6d4b3..22287f6a5e 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -3671,62 +3671,87 @@ static void decode_flush(InputFile *ifile) static void ts_discontinuity_detect(InputFile *ifile, InputStream *ist, AVPacket *pkt) { - const int fmt_is_discont = ifile->ctx->iformat->flags & AVFMT_TS_DISCONT; + const int fmt_is_discont = !!(ifile->ctx->iformat->flags & AVFMT_TS_DISCONT); int disable_discontinuity_correction = copy_ts; int64_t pkt_dts = av_rescale_q_rnd(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q, AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX); + char ist_desc[32]; + snprintf(ist_desc, sizeof(ist_desc), "input stream #%d:%d", ist->file_index, ist->st->index); + +#define BASE_TS(ts_) av_ts2timestr(ts_, &AV_TIME_BASE_Q) +#define PKT_TS(ts_) av_ts2timestr(ts_, &ist->st->time_base) + + av_log(NULL, AV_LOG_TRACE, + "ts discontinuity detection on %s pkt_dts:%s pkt_pts:%s next_dts:%s last_ts:%s fmt_discont:%d copy_ts:%d\n", + ist_desc, PKT_TS(pkt->dts), PKT_TS(pkt->pts), + BASE_TS(ist->next_dts), BASE_TS(ifile->last_ts), + fmt_is_discont, copy_ts); if (copy_ts && ist->next_dts != AV_NOPTS_VALUE && fmt_is_discont && ist->st->pts_wrap_bits < 60) { int64_t wrap_dts = av_rescale_q_rnd(pkt->dts + (1LL<<ist->st->pts_wrap_bits), ist->st->time_base, AV_TIME_BASE_Q, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); - if (FFABS(wrap_dts - ist->next_dts) < FFABS(pkt_dts - ist->next_dts)/10) + if (FFABS(wrap_dts - ist->next_dts) < FFABS(pkt_dts - ist->next_dts)/10) { disable_discontinuity_correction = 0; + av_log(NULL, AV_LOG_DEBUG, + "wrapped ts detected in copy_ts, enabled discontinuity correction\n"); + } } - if (ist->next_dts != AV_NOPTS_VALUE && !disable_discontinuity_correction) { - int64_t delta = pkt_dts - ist->next_dts; +#define CHECK_INVALID_TS(delta_, ts_type_, ts_) \ + if (FFABS(delta_) > ist->dts_error_threshold) { \ + av_log(NULL, AV_LOG_WARNING, \ + "drop invalid " #ts_type_ ":%s on %s delta:%s > dts_error_threshold:%s on %s\n", \ + PKT_TS(ts_), BASE_TS(delta), ist_desc, BASE_TS(ist->dts_error_threshold), ist_desc); \ + ts_ = AV_NOPTS_VALUE; \ + } + + if (!disable_discontinuity_correction) { + int64_t delta; + if (fmt_is_discont) { - if (FFABS(delta) > 1LL * dts_delta_threshold * AV_TIME_BASE || - pkt_dts + AV_TIME_BASE/10 < FFMAX(ist->pts, ist->dts)) { - ifile->ts_offset_discont -= delta; - av_log(NULL, AV_LOG_DEBUG, - "timestamp discontinuity for stream #%d:%d " - "(id=%d, type=%s): %"PRId64", new offset= %"PRId64"\n", - ist->file_index, ist->st->index, ist->st->id, - av_get_media_type_string(ist->par->codec_type), - delta, ifile->ts_offset_discont); - pkt->dts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base); - if (pkt->pts != AV_NOPTS_VALUE) - pkt->pts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base); - } - } else { - if (FFABS(delta) > 1LL * dts_error_threshold * AV_TIME_BASE) { - av_log(NULL, AV_LOG_WARNING, "DTS %"PRId64", next:%"PRId64" st:%d invalid dropping\n", pkt->dts, ist->next_dts, pkt->stream_index); - pkt->dts = AV_NOPTS_VALUE; + delta = + ist->next_dts != AV_NOPTS_VALUE ? pkt_dts - ist->next_dts : + ifile->last_ts != AV_NOPTS_VALUE ? pkt_dts - ifile->last_ts : + AV_NOPTS_VALUE; + + if (delta != AV_NOPTS_VALUE) { + char fix_delta = 0; + int64_t dts_limit = FFMAX(ist->pts, ist->dts) - AV_TIME_BASE/10; + + if (FFABS(delta) > ist->dts_delta_threshold) { + av_log(NULL, AV_LOG_DEBUG, + "detected dts:%s delta:%s > dts_delta_threshold:%s on %s\n", + BASE_TS(pkt_dts), BASE_TS(delta), BASE_TS(ist->dts_delta_threshold), + ist_desc); + fix_delta = 1; + } else if (ist->next_dts != AV_NOPTS_VALUE && pkt_dts < dts_limit) { + av_log(NULL, AV_LOG_DEBUG, "detected dts:%s < dts_limit:%s on %s\n", + BASE_TS(pkt_dts), BASE_TS(dts_limit), ist_desc); + fix_delta = 1; + } + + if (fix_delta) { + ifile->ts_offset_discont -= delta; + pkt->dts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base); + if (pkt->pts != AV_NOPTS_VALUE) + pkt->pts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base); + av_log(NULL, AV_LOG_DEBUG, + "ts delta:%s applied -> ts_offset_discont:%s dts:%s pts:%s on %s\n", + BASE_TS(-delta), BASE_TS(ifile->ts_offset_discont), + PKT_TS(pkt->dts), PKT_TS(pkt->pts), ist_desc); + } } - if (pkt->pts != AV_NOPTS_VALUE){ + } else if (ist->next_dts != AV_NOPTS_VALUE) { + delta = pkt_dts - ist->next_dts; + CHECK_INVALID_TS(delta, dts, pkt->dts); + if (pkt->pts != AV_NOPTS_VALUE) { int64_t pkt_pts = av_rescale_q(pkt->pts, ist->st->time_base, AV_TIME_BASE_Q); delta = pkt_pts - ist->next_dts; - if (FFABS(delta) > 1LL * dts_error_threshold * AV_TIME_BASE) { - av_log(NULL, AV_LOG_WARNING, "PTS %"PRId64", next:%"PRId64" invalid dropping st:%d\n", pkt->pts, ist->next_dts, pkt->stream_index); - pkt->pts = AV_NOPTS_VALUE; - } + CHECK_INVALID_TS(delta, pts, pkt->pts); } } - } else if (ist->next_dts == AV_NOPTS_VALUE && !copy_ts && - fmt_is_discont && ifile->last_ts != AV_NOPTS_VALUE) { - int64_t delta = pkt_dts - ifile->last_ts; - if (FFABS(delta) > 1LL * dts_delta_threshold * AV_TIME_BASE) { - ifile->ts_offset_discont -= delta; - av_log(NULL, AV_LOG_DEBUG, - "Inter stream timestamp discontinuity %"PRId64", new offset= %"PRId64"\n", - delta, ifile->ts_offset_discont); - pkt->dts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base); - if (pkt->pts != AV_NOPTS_VALUE) - pkt->pts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base); - } } ifile->last_ts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q); diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index f1412f6446..686d38c934 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -368,6 +368,8 @@ typedef struct InputStream { int64_t next_pts; ///< synthetic pts for the next decode frame (in AV_TIME_BASE units) int64_t pts; ///< current pts of the decoded frame (in AV_TIME_BASE units) int wrap_correction_done; + int64_t dts_delta_threshold; ///< dts_delta_threshold value rescaled to AV_TIME_BASE units + int64_t dts_error_threshold; ///< dts_error_threshold value rescaled to AV_TIME_BASE units // the value of AVCodecParserContext.repeat_pict from the AVStream parser // for the last packet returned from ifile_get_packet() diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 98da0678f5..18f8ed8946 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -736,6 +736,9 @@ static void add_input_streams(const OptionsContext *o, Demuxer *d) ist->filter_in_rescale_delta_last = AV_NOPTS_VALUE; ist->prev_pkt_pts = AV_NOPTS_VALUE; + ist->dts_delta_threshold = 1LL * dts_delta_threshold * AV_TIME_BASE; + ist->dts_error_threshold = 1LL * dts_error_threshold * AV_TIME_BASE; + ist->dec_ctx = avcodec_alloc_context3(ist->dec); if (!ist->dec_ctx) report_and_exit(AVERROR(ENOMEM)); -- 2.25.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
reply other threads:[~2023-02-11 16:29 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20230211162900.125018-1-stefasab@gmail.com \ --to=stefasab@gmail.com \ --cc=ffmpeg-devel@ffmpeg.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel This inbox may be cloned and mirrored by anyone: git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \ ffmpegdev@gitmailbox.com public-inbox-index ffmpegdev Example config snippet for mirrors. AGPL code for this site: git clone https://public-inbox.org/public-inbox.git