[FFmpeg-devel] [PATCH v2] Patch for memory optimization with QuickTime/MP4
Jörg Beckmann
Joerg.Beckmann at scisys.com
Mon Dec 2 16:12:14 EET 2019
After discussion with Carl Eugen, I replaced the "if" in line 7737 with an assert().
There is still the question, whether mov_switch_root() might be called when reading from a file. If someone is really really sure that it cannot happen at all, the check in mov_read_seek() could be removed.
Jörg
---
libavformat/isom.h | 1 +
libavformat/mov.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 50 insertions(+), 1 deletion(-)
diff --git a/libavformat/isom.h b/libavformat/isom.h
index 4943b80ccf..9b4753f4d7 100644
--- a/libavformat/isom.h
+++ b/libavformat/isom.h
@@ -268,6 +268,7 @@ typedef struct MOVContext {
int advanced_editlist;
int ignore_chapters;
int seek_individually;
+ int discard_fragments;
int64_t next_root_atom; ///< offset of the next root atom
int export_all;
int export_xmp;
diff --git a/libavformat/mov.c b/libavformat/mov.c
index 7553a7fdfc..97c02725c5 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -7698,8 +7698,11 @@ static int should_retry(AVIOContext *pb, int error_code) {
static int mov_switch_root(AVFormatContext *s, int64_t target, int index)
{
- int ret;
+ int ret, i;
MOVContext *mov = s->priv_data;
+ AVStream *st = NULL;
+ MOVStreamContext *sc;
+ MOVFragment *frag;
if (index >= 0 && index < mov->frag_index.nb_items)
target = mov->frag_index.item[index].moof_offset;
@@ -7721,6 +7724,44 @@ static int mov_switch_root(AVFormatContext *s, int64_t target, int index)
mov->found_mdat = 0;
+ if (mov->discard_fragments) {
+ frag = &mov->fragment;
+
+ for (i = 0; i < mov->fc->nb_streams; i++) {
+ if (mov->fc->streams[i]->id == frag->track_id) {
+ st = mov->fc->streams[i];
+ break;
+ }
+ }
+
+ av_assert0(st);
+
+ sc = st->priv_data;
+
+ switch (st->codecpar->codec_type) {
+ case AVMEDIA_TYPE_AUDIO:
+ case AVMEDIA_TYPE_SUBTITLE:
+ /* Freeing VIDEO tables leads to corrupted video when writing to eg. MKV */
+ av_freep(&st->index_entries);
+ st->nb_index_entries = 0;
+ st->index_entries_allocated_size = 0;
+
+ sc->current_index = 0;
+ sc->current_sample = 0;
+
+ av_freep(&sc->ctts_data);
+ sc->ctts_data = NULL;
+ sc->ctts_allocated_size = 0;
+ sc->ctts_count = 0;
+ break;
+ }
+
+ av_free(mov->frag_index.item->stream_info);
+ av_freep(&mov->frag_index.item);
+ mov->frag_index.allocated_size = 0;
+ mov->frag_index.nb_items = 0;
+ }
+
ret = mov_read_default(mov, s->pb, (MOVAtom){ AV_RL32("root"), INT64_MAX });
if (ret < 0)
return ret;
@@ -7975,6 +8016,9 @@ static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_ti
int sample;
int i;
+ if (mc->discard_fragments) // Seeking is not possible if fragments are discarded.
+ return AVERROR(ENOTSUP);
+
if (stream_index >= s->nb_streams)
return AVERROR_INVALIDDATA;
@@ -8063,6 +8107,10 @@ static const AVOption mov_options[] = {
{ "decryption_key", "The media decryption key (hex)", OFFSET(decryption_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
{ "enable_drefs", "Enable external track support.", OFFSET(enable_drefs), AV_OPT_TYPE_BOOL,
{.i64 = 0}, 0, 1, FLAGS },
+ {"discard_fragments",
+ "Discards fragments after they have been read to support live streams.",
+ OFFSET(discard_fragments), AV_OPT_TYPE_BOOL, { .i64 = 0 },
+ 0, 1, FLAGS },
{ NULL },
};
More information about the ffmpeg-devel
mailing list