Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
From: Stefano Sabatini <stefasab@gmail.com>
To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org>
Subject: Re: [FFmpeg-devel] [PATCH] doc/ffmpeg: extend -dts_delta_threshold option description
Date: Sat, 11 Feb 2023 03:30:00 +0100
Message-ID: <20230211023000.GE338325@mariano> (raw)
In-Reply-To: <20230208234118.GU1949656@pb2>

[-- Attachment #1: Type: text/plain, Size: 2065 bytes --]

On date Thursday 2023-02-09 00:41:18 +0100, Michael Niedermayer wrote:
> On Mon, Feb 06, 2023 at 02:25:23AM +0100, Stefano Sabatini wrote:
[...]
> > Subject: [PATCH 2/2] ffmpeg: review -dts_delta_threshold and -dts_delta_error
> >  options
> > 
> > Review handling of -dts_delta_threshold and -dts_delta_error options,
> > specify them as floating point expressed in seconds.
> > 
> > Also, review and simplify logic. Adjust values for tests, since in
> > some cases the new values does not trigger the correction logic.
> > 
> > PR: https://patchwork.ffmpeg.org/project/ffmpeg/list/?series=8252
> > ---
> >  doc/ffmpeg.texi             | 36 ++++++++++++++++---
> >  fftools/ffmpeg.c            | 72 ++++++++++++++++++++-----------------
> >  fftools/ffmpeg.h            |  2 ++
> >  fftools/ffmpeg_demux.c      |  3 ++
> >  tests/fate/filter-audio.mak |  2 +-
> >  tests/fate/mpeg4.mak        |  2 +-
> >  6 files changed, 77 insertions(+), 40 deletions(-)
> 
> This seems to break a case with concat and vsync
> ./ffmpeg -y -i 'concat:///home/michael/videos/angels.mpg|/home/michael/videos/angels.mpg'  -vsync 0 -an file.avi
> 
> ...
> cpb: bitrate max/min/avg: 0/0/200000 buffer size: 0 vbv_delay: N/A
> [mpeg4 @ 0x55e051b8d4c0] Invalid pts (0) <= last (11)00.00 bitrate=N/A speed=   0x    
> [vost#0:0/mpeg4 @ 0x55e051b9d700] Error submitting video frame to the encoder
> Conversion failed!
>
> 
> Ill mail you the angels.mpg, i think its online somewhere but i cant
> find it

Fixed, now the code should be equivalent to the previous
implementation.

What happened in this case (and apparently in the other fate tests
failing), is that some sort of limit correction is applied:

detected dts:-0.041711 < dts_limit:0.358789
ts delta 0.5005 applied => ts_offset_discont:0.5005 dts:0.458789

preventing the invalid pts error.

The limit correction, hardcoded in the ffmpeg.c code, is completely
unrelated to the dts_delta_threshold value, no idea if it would make
sense to make this parametric (but at least now it should be a bit
more clear from the code/logs).

[-- Attachment #2: 0001-ffmpeg-review-dts_delta_threshold-and-dts_delta_erro.patch --]
[-- Type: text/x-diff, Size: 10917 bytes --]

From 8e23638cbcfcf1e47d4b7d582d4eb12a29ad4f57 Mon Sep 17 00:00:00 2001
From: Stefano Sabatini <stefasab@gmail.com>
Date: Fri, 1 Apr 2011 01:13:35 +0200
Subject: [PATCH] ffmpeg: review -dts_delta_threshold and -dts_delta_error
 options

Review handling of -dts_delta_threshold and -dts_delta_error options
in order to simplify a bit the logic and improve logging.

Also extend documentation.

PR: https://patchwork.ffmpeg.org/project/ffmpeg/list/?series=8252
---
 doc/ffmpeg.texi        | 36 +++++++++++++---
 fftools/ffmpeg.c       | 98 ++++++++++++++++++++++++++----------------
 fftools/ffmpeg.h       |  2 +
 fftools/ffmpeg_demux.c |  3 ++
 4 files changed, 96 insertions(+), 43 deletions(-)

diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi
index d9d4b75567..63be7951e6 100644
--- a/doc/ffmpeg.texi
+++ b/doc/ffmpeg.texi
@@ -1837,12 +1837,38 @@ results, but increase memory use and latency.
 
 The default value is 10 seconds.
 
-@item -dts_delta_threshold
-Timestamp discontinuity delta threshold.
+@item -dts_delta_threshold @var{threshold}
+Timestamp discontinuity delta threshold, expressed as a floating point
+number of seconds.
+
+The timestamp discontinuity correction enabled by this option is only
+applied to input formats accepting timestamp discontinuity (for which
+the @code{AV_FMT_DISCONT} flag is enabled), e.g. MPEG-TS and HLS, and
+is automatically disabled when employing the @code{-copy_ts} option
+(unless wrapping is detected).
+
+If a timestamp discontinuity is detected whose absolute value is
+greater than @var{threshold}, ffmpeg will remove the discontinuity by
+decreasing/increasing the current DTS and PTS by the corresponding
+delta value.
+
+The default value is 10.
+
 @item -dts_error_threshold @var{seconds}
-Timestamp error delta threshold. This threshold use to discard crazy/damaged
-timestamps and the default is 30 hours which is arbitrarily picked and quite
-conservative.
+Timestamp error delta threshold, expressed as a floating point number
+of seconds.
+
+The timestamp correction enabled by this option is only applied to
+input formats not accepting timestamp discontinuity (for which the
+@code{AV_FMT_DISCONT} flag is not enabled).
+
+If a timestamp discontinuity is detected whose absolute value is
+greater than @var{threshold}, ffmpeg will drop the PTS/DTS timestamp
+value.
+
+The default value is @code{3600*30} (30 hours), which is arbitrarily
+picked and quite conservative.
+
 @item -muxdelay @var{seconds} (@emph{output})
 Set the maximum demux-decode delay.
 @item -muxpreload @var{seconds} (@emph{output})
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 064ec6d4b3..e88a78872a 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -3671,62 +3671,84 @@ 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);
 
+#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 stream #%d:%d pkt_dts:%s pkt_pts:%s next_dts:%s last_ts:%s fmt_discont:%d copy_ts:%d\n",
+           ist->file_index, ist->st->index,
+           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 delta:%s > dts_error_threshold:%s\n", \
+               PKT_TS(ts_), BASE_TS(delta), BASE_TS(ist->dts_error_threshold)); \
+        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\n",
+                           BASE_TS(pkt_dts), BASE_TS(delta), BASE_TS(ist->dts_delta_threshold));
+                    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\n",
+                           BASE_TS(pkt_dts), BASE_TS(dts_limit));
+                    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\n",
+                           BASE_TS(-delta), BASE_TS(ifile->ts_offset_discont), PKT_TS(pkt->dts));
+                }
             }
-            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


[-- Attachment #3: Type: text/plain, Size: 251 bytes --]

_______________________________________________
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  2:30 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-01-25  1:07 Stefano Sabatini
2023-01-25  5:17 ` Gyan Doshi
2023-02-06  1:25   ` Stefano Sabatini
2023-02-06  4:31     ` Gyan Doshi
2023-02-08 23:41     ` Michael Niedermayer
2023-02-11  2:30       ` Stefano Sabatini [this message]
2023-02-11 16:28         ` Stefano Sabatini
2023-02-11 16:56           ` Gyan Doshi
2023-02-20 17:57         ` Anton Khirnov
2023-02-28 21:32           ` Stefano Sabatini

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=20230211023000.GE338325@mariano \
    --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