diff mbox series

[FFmpeg-devel] avformat/mov: add io_order option to disable demuxer level interleave

Message ID tencent_D2E7FEEA9A930C1C4C4BA9A60B509BE6D906@qq.com
State New
Headers show
Series [FFmpeg-devel] avformat/mov: add io_order option to disable demuxer level interleave | expand

Checks

Context Check Description
yinshiyou/make_loongarch64 success Make finished
yinshiyou/make_fate_loongarch64 success Make fate finished
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished

Commit Message

Zhao Zhili Aug. 28, 2023, 4:06 p.m. UTC
From: Zhao Zhili <zhilizhao@tencent.com>

For bad interleaved files, manually interleave multiple tracks at the
demuxer level can trigger seeking back and forth, which can be
dramatically slow depending on the protocol. Demuxer level interleave
can be useless sometimes, e.g., reading mp4 via http and then
transcoding/remux to DASH. Enable this option when you don't need the
demuxer level interleave, and want to avoid the IO penalizes.

This issue is well known. Two samples can be found at here
http://ffmpeg.org/pipermail/ffmpeg-devel/2022-December/304951.html

Signed-off-by: Zhao Zhili <zhilizhao@tencent.com>
---
 doc/demuxers.texi     | 6 ++++++
 libavformat/isom.h    | 1 +
 libavformat/mov.c     | 5 ++++-
 libavformat/version.h | 2 +-
 4 files changed, 12 insertions(+), 2 deletions(-)

Comments

Derek Buitenhuis Aug. 31, 2023, 3:59 p.m. UTC | #1
On 8/28/2023 5:06 PM, Zhao Zhili wrote:
> -            if (!sample || (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL) && current_sample->pos < sample->pos) ||
> +            if (!sample || (force_io_order && current_sample->pos < sample->pos) ||

Hmm, I think the name `io_order` is a misnomer: It still will not, for example,
output packets in I/O order if the mdat has backwards packets (i.e. mdat starts
with the last packet, and ends with the first packet, which is very stupid, but
technically legal in ISOBMFF/QTFF).

Maybe something like `no_reinterleaving`? Naming is hard, and I am not much
better at it.

- Derek
Zhao Zhili Aug. 31, 2023, 5:59 p.m. UTC | #2
> From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of Derek Buitenhuis
> Sent: 2023年8月31日 23:59
> To: ffmpeg-devel@ffmpeg.org
> Subject: Re: [FFmpeg-devel] [PATCH] avformat/mov: add io_order option to disable demuxer level interleave
> 
> On 8/28/2023 5:06 PM, Zhao Zhili wrote:
> > -            if (!sample || (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL) && current_sample->pos < sample->pos) ||
> > +            if (!sample || (force_io_order && current_sample->pos < sample->pos) ||
> 
> Hmm, I think the name `io_order` is a misnomer: It still will not, for example,
> output packets in I/O order if the mdat has backwards packets (i.e. mdat starts
> with the last packet, and ends with the first packet, which is very stupid, but
> technically legal in ISOBMFF/QTFF).
> 
> Maybe something like `no_reinterleaving`? Naming is hard, and I am not much
> better at it.

It takes me more time to naming and write the doc than coding. The idea is plain and simple, but
hard to describe with a phrase.

Is `reinterleaving` a word? How about `interleave` or `interleaved_read` with default value to true?

> 
> - Derek
> _______________________________________________
> 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".
diff mbox series

Patch

diff --git a/doc/demuxers.texi b/doc/demuxers.texi
index 2d33b47a56..11366875f0 100644
--- a/doc/demuxers.texi
+++ b/doc/demuxers.texi
@@ -779,6 +779,12 @@  cast to int32 are used to adjust onward dts.
 
 Unit is the track time scale. Range is 0 to UINT_MAX. Default is @code{UINT_MAX - 48000*10} which allows upto
 a 10 second dts correction for 48 kHz audio streams while accommodating 99.9% of @code{uint32} range.
+
+@item io_order
+Force reading in IO order. For bad interleaved files, manually interleave multiple tracks at the demuxer level can
+trigger seeking back and forth, which can be dramatically slow depending on the protocol. Enable this option when
+you don't need the demuxer level interleave, and want to avoid the IO penalizes.
+
 @end table
 
 @subsection Audible AAX
diff --git a/libavformat/isom.h b/libavformat/isom.h
index 4b1cd42f0f..843ea2b2e5 100644
--- a/libavformat/isom.h
+++ b/libavformat/isom.h
@@ -327,6 +327,7 @@  typedef struct MOVContext {
         int64_t extent_offset;
     } *avif_info;
     int avif_info_size;
+    int force_io_order;
 } MOVContext;
 
 int ff_mp4_read_descr_len(AVIOContext *pb);
diff --git a/libavformat/mov.c b/libavformat/mov.c
index be9975f297..5ce9b83262 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -8780,6 +8780,8 @@  static AVIndexEntry *mov_find_next_sample(AVFormatContext *s, AVStream **st)
     AVIndexEntry *sample = NULL;
     int64_t best_dts = INT64_MAX;
     int i;
+    MOVContext *mov = s->priv_data;
+    int force_io_order = mov->force_io_order || !(s->pb->seekable & AVIO_SEEKABLE_NORMAL);
     for (i = 0; i < s->nb_streams; i++) {
         AVStream *avst = s->streams[i];
         FFStream *const avsti = ffstream(avst);
@@ -8788,7 +8790,7 @@  static AVIndexEntry *mov_find_next_sample(AVFormatContext *s, AVStream **st)
             AVIndexEntry *current_sample = &avsti->index_entries[msc->current_sample];
             int64_t dts = av_rescale(current_sample->timestamp, AV_TIME_BASE, msc->time_scale);
             av_log(s, AV_LOG_TRACE, "stream %d, sample %d, dts %"PRId64"\n", i, msc->current_sample, dts);
-            if (!sample || (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL) && current_sample->pos < sample->pos) ||
+            if (!sample || (force_io_order && current_sample->pos < sample->pos) ||
                 ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) &&
                  ((msc->pb != s->pb && dts < best_dts) || (msc->pb == s->pb && dts != AV_NOPTS_VALUE &&
                  ((FFABS(best_dts - dts) <= AV_TIME_BASE && current_sample->pos < sample->pos) ||
@@ -9282,6 +9284,7 @@  static const AVOption mov_options[] = {
     { "enable_drefs", "Enable external track support.", OFFSET(enable_drefs), AV_OPT_TYPE_BOOL,
         {.i64 = 0}, 0, 1, FLAGS },
     { "max_stts_delta", "treat offsets above this value as invalid", OFFSET(max_stts_delta), AV_OPT_TYPE_INT, {.i64 = UINT_MAX-48000*10 }, 0, UINT_MAX, .flags = AV_OPT_FLAG_DECODING_PARAM },
+    { "io_order", "Force reading in IO order, disable manually interleave between multiple tracks", OFFSET(force_io_order), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, .flags = AV_OPT_FLAG_DECODING_PARAM },
 
     { NULL },
 };
diff --git a/libavformat/version.h b/libavformat/version.h
index 787ee8c90b..248cce002b 100644
--- a/libavformat/version.h
+++ b/libavformat/version.h
@@ -32,7 +32,7 @@ 
 #include "version_major.h"
 
 #define LIBAVFORMAT_VERSION_MINOR  10
-#define LIBAVFORMAT_VERSION_MICRO 101
+#define LIBAVFORMAT_VERSION_MICRO 102
 
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
                                                LIBAVFORMAT_VERSION_MINOR, \