movdec: Restart parsing root-level atoms at the right spot
authorMartin Storsjö <martin@martin.st>
Tue, 21 Feb 2012 10:03:56 +0000 (12:03 +0200)
committerMartin Storsjö <martin@martin.st>
Wed, 22 Feb 2012 08:39:14 +0000 (10:39 +0200)
If parsing moov+mdat in a non-seekable file, we currently
abort parsing directly after parsing the header of the mdat
atom. If we want to continue parsing later (if looking to
parse later fragments), we need to skip past the content of the
mdat atom, otherwise we end up parsing the content of the mdat
atom as root level atoms.

Signed-off-by: Martin Storsjö <martin@martin.st>
libavformat/isom.h
libavformat/mov.c

index 32c4b3fd1da3cf3a8a7b722a95f3d270eadf324f..214af589a546bb63d60ec409d249ff9de4562648 100644 (file)
@@ -143,6 +143,7 @@ typedef struct MOVContext {
     unsigned trex_count;
     int itunes_metadata;  ///< metadata are itunes style
     int chapter_track;
     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);
 } MOVContext;
 
 int ff_mp4_read_descr_len(AVIOContext *pb);
index 2242ba76364eec32b6f20c8b2d69c5da3290568f..a2b2da0a223a4c29800a48629d7658377c38e2de 100644 (file)
@@ -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 &&
             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;
                 return 0;
+            }
             left = a.size - avio_tell(pb) + start_pos;
             if (left > 0) /* skip garbage at atom end */
                 avio_skip(pb, left);
             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;
     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));
             s->pb->eof_reached)
             return AVERROR_EOF;
         av_dlog(s, "read fragments, offset 0x%"PRIx64"\n", avio_tell(s->pb));