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 }, }; _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".