diff mbox series

[FFmpeg-devel,3/4] avformat/mov: Only read the mfra size once during sidx parsing

Message ID 20200901150335.103855-3-derek.buitenhuis@gmail.com
State Accepted
Commit 97fa669a6f8f3ecee458a51d38f14429e2d67024
Headers show
Series [FFmpeg-devel,1/4] avformat/mov: Fix return type used for av_seek in mfra code | expand

Checks

Context Check Description
andriy/default pending
andriy/make success Make finished
andriy/make_fate success Make fate finished

Commit Message

Derek Buitenhuis Sept. 1, 2020, 3:03 p.m. UTC
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 |  2 ++
 libavformat/mov.c  | 16 +++++++++-------
 2 files changed, 11 insertions(+), 7 deletions(-)
diff mbox series

Patch

diff --git a/libavformat/isom.h b/libavformat/isom.h
index 41a9c64c11..78495fd336 100644
--- a/libavformat/isom.h
+++ b/libavformat/isom.h
@@ -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);
diff --git a/libavformat/mov.c b/libavformat/mov.c
index 49c2d05d21..e33031f158 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -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) {