]> git.sesse.net Git - ffmpeg/commitdiff
avformat/mov: Only read the mfra size once during sidx parsing
authorDerek Buitenhuis <derek.buitenhuis@gmail.com>
Tue, 1 Sep 2020 14:33:47 +0000 (15:33 +0100)
committerDerek Buitenhuis <derek.buitenhuis@gmail.com>
Thu, 3 Sep 2020 18:04:29 +0000 (19:04 +0100)
On files with more than one sidx box, like live fragmented MP4
files, it was previously re-reading and seeking on every singl
sidx box, leading to extremely poor performance on larger files,
especially over the network.

Only do it on the first one, and stash its result.

Signed-off-by: Derek Buitenhuis <derek.buitenhuis@gmail.com>
libavformat/isom.h
libavformat/mov.c

index 41a9c64c119628569530c03b023513f6e756e399..78495fd3366c5045ec52b07614a285325492cc4a 100644 (file)
@@ -291,6 +291,8 @@ typedef struct MOVContext {
     int decryption_key_len;
     int enable_drefs;
     int32_t movie_display_matrix[3][3]; ///< display matrix from mvhd
+    int have_read_mfra_size;
+    uint32_t mfra_size;
 } MOVContext;
 
 int ff_mp4_read_descr_len(AVIOContext *pb);
index 49c2d05d211203d931a70c1ced4185664d8e43a0..e33031f1582bbb07ec8c69803bfcdfa72d1ca39a 100644 (file)
@@ -5097,14 +5097,16 @@ static int mov_read_sidx(MOVContext *c, AVIOContext *pb, MOVAtom atom)
     if (!is_complete && (pb->seekable & AVIO_SEEKABLE_NORMAL)) {
         int64_t ret;
         int64_t original_pos = avio_tell(pb);
-        int32_t mfra_size;
-        if ((ret = avio_seek(pb, stream_size - 4, SEEK_SET)) < 0)
-            return ret;
-        mfra_size = avio_rb32(pb);
-        if (offset + mfra_size == stream_size)
+        if (!c->have_read_mfra_size) {
+            if ((ret = avio_seek(pb, stream_size - 4, SEEK_SET)) < 0)
+                return ret;
+            c->mfra_size = avio_rb32(pb);
+            c->have_read_mfra_size = 1;
+            if ((ret = avio_seek(pb, original_pos, SEEK_SET)) < 0)
+                return ret;
+        }
+        if (offset + c->mfra_size == stream_size)
             is_complete = 1;
-        if ((ret = avio_seek(pb, original_pos, SEEK_SET)) < 0)
-            return ret;
     }
 
     if (is_complete) {