Skip to content

Instantly share code, notes, and snippets.

@Sam0230
Last active July 27, 2021 11:55
Show Gist options
  • Save Sam0230/1ba6cf8a8a23cbb6f42d0df0101f8ede to your computer and use it in GitHub Desktop.
Save Sam0230/1ba6cf8a8a23cbb6f42d0df0101f8ede to your computer and use it in GitHub Desktop.
ffmpeg: allow non-monotonous DTS with alwnmodts fflag
curl -fsSL https://gist.githubusercontent.com/Sam0230/1ba6cf8a8a23cbb6f42d0df0101f8ede/raw/02ef89ae544e1c8fd6ba9bed47f21730df41eb7a/patch.patch | patch -p 1
./configure \
--prefix=/usr/local \
--enable-shared \
--enable-pthreads \
--enable-version3 \
--enable-nonfree \
--cc=clang \
--enable-ffplay \
--enable-gnutls \
--enable-gpl \
--enable-libaom \
--enable-libbluray \
--enable-libdav1d \
--enable-libmp3lame \
--enable-libopus \
--enable-librav1e \
--enable-librubberband \
--enable-libsnappy \
--enable-libsrt \
--enable-libtesseract \
--enable-libtheora \
--enable-libvidstab \
--enable-libvorbis \
--enable-libvpx \
--enable-libwebp \
--enable-libx264 \
--enable-libx265 \
--enable-libxml2 \
--enable-libxvid \
--enable-lzma \
--enable-libfontconfig \
--enable-libfreetype \
--enable-frei0r \
--enable-libass \
--enable-libopencore-amrnb \
--enable-libopencore-amrwb \
--enable-libopenjpeg \
--enable-libspeex \
--enable-libsoxr \
--enable-libzmq \
--enable-libzimg \
--disable-libjack \
--disable-indev=jack \
--enable-videotoolbox \
make -j 10
From 20266f9008471f5bf8b2d873211a26e823e14972 Mon Sep 17 00:00:00 2001
From: Sam0230 <>
Date: Sun, 6 Jun 2021 21:10:13 +0800
Subject: [PATCH] allow non-monotonous DTS with alwnmodts fflag
---
doc/formats.texi | 2 ++
fftools/ffmpeg.c | 24 ++++++++++++++----------
libavformat/avformat.h | 1 +
libavformat/mux.c | 31 ++++++++++++++++++++++---------
libavformat/options_table.h | 1 +
5 files changed, 40 insertions(+), 19 deletions(-)
diff --git a/doc/formats.texi b/doc/formats.texi
index 640b23b7906a..3bd09adb931b 100644
--- a/doc/formats.texi
+++ b/doc/formats.texi
@@ -69,6 +69,8 @@ This ensures that file and data checksums are reproducible and match between
platforms. Its primary use is for regression testing.
@item flush_packets
Write out packets immediately.
+@item alwnmodts
+Allow Non-monotonous DTS.
@item shortest
Stop muxing at the end of the shortest stream.
It may be needed to increase max_interleave_delta to avoid flushing the longer
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 04ddc9e60b44..ab2e5e2faf8b 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -831,18 +831,22 @@ static void write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int u
if (exit_on_error)
loglevel = AV_LOG_ERROR;
av_log(s, loglevel, "Non-monotonous DTS in output stream "
- "%d:%d; previous: %"PRId64", current: %"PRId64"; ",
+ "%d:%d; previous: %"PRId64", current: %"PRId64"",
ost->file_index, ost->st->index, ost->last_mux_dts, pkt->dts);
- if (exit_on_error) {
- av_log(NULL, AV_LOG_FATAL, "aborting.\n");
- exit_program(1);
+ if (s->flags & AVFMT_FLAG_ALWNMODTS)
+ av_log(s, loglevel, ".\n");
+ else {
+ if (exit_on_error) {
+ av_log(NULL, AV_LOG_FATAL, "; aborting.\n");
+ exit_program(1);
+ }
+ av_log(s, loglevel, "; changing to %"PRId64". This may result "
+ "in incorrect timestamps in the output file.\n",
+ max);
+ if (pkt->pts >= pkt->dts)
+ pkt->pts = FFMAX(pkt->pts, max);
+ pkt->dts = max;
}
- av_log(s, loglevel, "changing to %"PRId64". This may result "
- "in incorrect timestamps in the output file.\n",
- max);
- if (pkt->pts >= pkt->dts)
- pkt->pts = FFMAX(pkt->pts, max);
- pkt->dts = max;
}
}
}
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index a28ac372da7d..f47067cf8ae7 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -1248,6 +1248,7 @@ typedef struct AVFormatContext {
#define AVFMT_FLAG_FAST_SEEK 0x80000 ///< Enable fast, but inaccurate seeks for some formats
#define AVFMT_FLAG_SHORTEST 0x100000 ///< Stop muxing when the shortest stream stops.
#define AVFMT_FLAG_AUTO_BSF 0x200000 ///< Add bitstream filters as requested by the muxer
+#define AVFMT_FLAG_ALWNMODTS 0x400000 ///< Allow Non-monotonous DTS
/**
* Maximum size of the data read from input for determining
diff --git a/libavformat/mux.c b/libavformat/mux.c
index eab58aa225f2..eb21b23caf37 100644
--- a/libavformat/mux.c
+++ b/libavformat/mux.c
@@ -558,10 +558,16 @@ static int compute_muxer_pkt_fields(AVFormatContext *s, AVStream *st, AVPacket *
st->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE &&
st->codecpar->codec_type != AVMEDIA_TYPE_DATA &&
st->internal->cur_dts >= pkt->dts) || st->internal->cur_dts > pkt->dts)) {
- av_log(s, AV_LOG_ERROR,
- "Application provided invalid, non monotonically increasing dts to muxer in stream %d: %s >= %s\n",
- st->index, av_ts2str(st->internal->cur_dts), av_ts2str(pkt->dts));
- return AVERROR(EINVAL);
+ if (s->flags & AVFMT_FLAG_ALWNMODTS)
+ av_log(s, AV_LOG_WARNING,
+ "Application provided invalid, non monotonically increasing dts to muxer in stream %d: %s >= %s\n",
+ st->index, av_ts2str(st->internal->cur_dts), av_ts2str(pkt->dts));
+ else {
+ av_log(s, AV_LOG_ERROR,
+ "Application provided invalid, non monotonically increasing dts to muxer in stream %d: %s >= %s\n",
+ st->index, av_ts2str(st->internal->cur_dts), av_ts2str(pkt->dts));
+ return AVERROR(EINVAL);
+ }
}
if (pkt->dts != AV_NOPTS_VALUE && pkt->pts != AV_NOPTS_VALUE && pkt->pts < pkt->dts) {
av_log(s, AV_LOG_ERROR,
@@ -766,11 +772,18 @@ static int prepare_input_packet(AVFormatContext *s, AVStream *st, AVPacket *pkt)
if (st->internal->cur_dts != AV_NOPTS_VALUE &&
((!(s->oformat->flags & AVFMT_TS_NONSTRICT) && st->internal->cur_dts >= pkt->dts) ||
st->internal->cur_dts > pkt->dts)) {
- av_log(s, AV_LOG_ERROR,
- "Application provided invalid, non monotonically increasing "
- "dts to muxer in stream %d: %" PRId64 " >= %" PRId64 "\n",
- st->index, st->internal->cur_dts, pkt->dts);
- return AVERROR(EINVAL);
+ if (s->flags & AVFMT_FLAG_ALWNMODTS)
+ av_log(s, AV_LOG_WARNING,
+ "Application provided invalid, non monotonically increasing "
+ "dts to muxer in stream %d: %" PRId64 " >= %" PRId64 "\n",
+ st->index, st->internal->cur_dts, pkt->dts);
+ else {
+ av_log(s, AV_LOG_ERROR,
+ "Application provided invalid, non monotonically increasing "
+ "dts to muxer in stream %d: %" PRId64 " >= %" PRId64 "\n",
+ st->index, st->internal->cur_dts, pkt->dts);
+ return AVERROR(EINVAL);
+ }
}
if (pkt->pts < pkt->dts) {
diff --git a/libavformat/options_table.h b/libavformat/options_table.h
index 62c5bb40a397..3b5f1598f43e 100644
--- a/libavformat/options_table.h
+++ b/libavformat/options_table.h
@@ -52,6 +52,7 @@ static const AVOption avformat_options[] = {
{"nobuffer", "reduce the latency introduced by optional buffering", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_NOBUFFER }, 0, INT_MAX, D, "fflags"},
{"bitexact", "do not write random/volatile data", 0, AV_OPT_TYPE_CONST, { .i64 = AVFMT_FLAG_BITEXACT }, 0, 0, E, "fflags" },
{"shortest", "stop muxing with the shortest stream", 0, AV_OPT_TYPE_CONST, { .i64 = AVFMT_FLAG_SHORTEST }, 0, 0, E, "fflags" },
+{"alwnmodts", "allow non-monotonous dts", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_ALWNMODTS }, 0, 0, E, "fflags"},
{"autobsf", "add needed bsfs automatically", 0, AV_OPT_TYPE_CONST, { .i64 = AVFMT_FLAG_AUTO_BSF }, 0, 0, E, "fflags" },
{"seek2any", "allow seeking to non-keyframes on demuxer level when supported", OFFSET(seek2any), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, D},
{"analyzeduration", "specify how many microseconds are analyzed to probe the input", OFFSET(max_analyze_duration), AV_OPT_TYPE_INT64, {.i64 = 0 }, 0, INT64_MAX, D},
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment