diff --git a/libavformat/isom.h b/libavformat/isom.h index 32c4b3fd1da3cf3a8a7b722a95f3d270eadf324f..214af589a546bb63d60ec409d249ff9de4562648 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -143,6 +143,7 @@ typedef struct MOVContext { unsigned trex_count; int itunes_metadata; ///< metadata are itunes style int chapter_track; + int64_t next_root_atom; ///< offset of the next root atom } MOVContext; int ff_mp4_read_descr_len(AVIOContext *pb); diff --git a/libavformat/mov.c b/libavformat/mov.c index 2242ba76364eec32b6f20c8b2d69c5da3290568f..a2b2da0a223a4c29800a48629d7658377c38e2de 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -350,8 +350,11 @@ static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom) if (err < 0) return err; if (c->found_moov && c->found_mdat && - (!pb->seekable || start_pos + a.size == avio_size(pb))) + (!pb->seekable || start_pos + a.size == avio_size(pb))) { + if (!pb->seekable) + c->next_root_atom = start_pos + a.size; return 0; + } left = a.size - avio_tell(pb) + start_pos; if (left > 0) /* skip garbage at atom end */ avio_skip(pb, left); @@ -2667,8 +2670,11 @@ static int mov_read_packet(AVFormatContext *s, AVPacket *pkt) sample = mov_find_next_sample(s, &st); if (!sample) { mov->found_mdat = 0; - if (s->pb->seekable|| - mov_read_default(mov, s->pb, (MOVAtom){ AV_RL32("root"), INT64_MAX }) < 0 || + if (!mov->next_root_atom) + return AVERROR_EOF; + avio_seek(s->pb, mov->next_root_atom, SEEK_SET); + mov->next_root_atom = 0; + if (mov_read_default(mov, s->pb, (MOVAtom){ AV_RL32("root"), INT64_MAX }) < 0 || s->pb->eof_reached) return AVERROR_EOF; av_dlog(s, "read fragments, offset 0x%"PRIx64"\n", avio_tell(s->pb));