Needs sample. Not a huge fan of heuristics like this - surely there's a way to tell within the first mdat/moov/moof seen?
Spotify comments ---------------- Failure to parse non-fragmented file with many mdat-boxes /Tomas
From 1c67cfd91cc3d18a2e4e1402bb439fe4db0f76b2 Mon Sep 17 00:00:00 2001 From: Ulrik <ulr...@spotify.com> Date: Mon, 13 Dec 2021 22:30:42 +0100 Subject: [PATCH 08/15] avformat/mov:Do not set `next_root_atom` for unfragmented files "Root boxes" in the mp4 demuxer denotes groups of boxes in a fragmented file that works self-contained. Example of such "root boxes" `ftyp,moov,sidx', `ftyp,moov,mdat`, `moof,mdat`... Therefore, if `next_root_atom` is 0, that can be seen as a sign that the file is fragmented, and we should avoid setting it when assuming the file is not fragmented. --- libavformat/mov.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index f58f8f3102..73d337c882 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -90,6 +90,9 @@ static void mov_free_stream_context(AVFormatContext *s, AVStream *st); static int64_t add_ctts_entry(MOVCtts** ctts_data, unsigned int* ctts_count, unsigned int* allocated_size, int count, int duration); +// Number of mdats we see without moof, before we assume non-fragmented file with lots of mdats +#define FRAG_HEURISTIC_THRESHOLD_MDAT_WITHOUT_MOOx 5 + static int mov_metadata_track_or_disc_number(MOVContext *c, AVIOContext *pb, unsigned len, const char *key) { @@ -1363,7 +1366,7 @@ static int mov_read_mdat(MOVContext *c, AVIOContext *pb, MOVAtom atom) if (atom.size == 0) /* wrong one (MP4) */ return 0; c->found_mdat+=1; - if (c->found_mdat == 5 && !c->found_moov) { + if (c->found_mdat == FRAG_HEURISTIC_THRESHOLD_MDAT_WITHOUT_MOOx && !c->found_moov) { /* Some mp4:s consist of 100s or even 1000s of mdats, with a moov at the end. To avoid a ton of seeking, we heuristically look for a moov at the end of the file instead */ mov_heuristic_scan_moov(c, pb); @@ -1647,7 +1650,7 @@ static int mov_try_read_moov(MOVContext *c, AVIOContext *pb, int64_t offset, int break; } if (child.size - ret + avio_tell(pb) > filesize) { - av_log(c->fc, AV_LOG_TRACE, "Remaining boxes does not align with EOF", offset); + av_log(c->fc, AV_LOG_TRACE, "Remaining boxes does not align with EOF"); return -1; } avio_seek(pb, child.size - ret, SEEK_CUR); @@ -9496,20 +9499,20 @@ static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom) } else { int64_t start_pos = avio_tell(pb); int64_t left; - uint8_t index_satisfied, at_end; + uint8_t might_be_fragmented, index_satisfied, at_end; int err = parse(c, pb, a); if (err < 0) { c->atom_depth --; return err; } + /* If we've seen 5 mdats, with no fragments seen, we assume file is not fragmented */ + might_be_fragmented = (c->found_mdat < FRAG_HEURISTIC_THRESHOLD_MDAT_WITHOUT_MOOx) || (c->frag_index.nb_items > 0); index_satisfied = (!(pb->seekable & AVIO_SEEKABLE_NORMAL)) || (c->fc->flags & AVFMT_FLAG_IGNIDX) - || c->frag_index.complete - || (c->found_mdat > 2 && (c->frag_index.nb_items == 0)); /* If we've read past 2 - mdats, with no fragments in fragment-index, we assume file is not fragmented */ + || c->frag_index.complete; at_end = (start_pos + a.size) == avio_size(pb); - if (c->found_moov && c->found_mdat && (a.size <= INT64_MAX - start_pos) && (index_satisfied || at_end)) { - if (!at_end) + if (c->found_moov && c->found_mdat && (a.size <= INT64_MAX - start_pos) && (index_satisfied || at_end || !might_be_fragmented)) { + if (!at_end && might_be_fragmented) c->next_root_atom = start_pos + a.size; c->atom_depth --; return 0; -- 2.39.2
_______________________________________________ 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".