diff mbox

[FFmpeg-devel] libavformat/mov: Speed up fragmented mp4 parsing (Take 2)

Message ID 5c2b3be1-1345-1196-dd7a-bea83e804746@gmail.com
State New
Headers show

Commit Message

Aaron Boushley Nov. 5, 2018, 11:48 p.m. UTC
Sorry for the second thread, first one was corrupted with a newline 
because I attempted an inline patch. Hopefully the mime-type will be set 
correctly on this one.
---
When parsing a fragmented MP4 with the use_mfra_for option set so that
the mfra box is parsed we currently continue to parse all the top level
boxes in the mp4. We also avoid using the index in mov_seek_fragment
unless the fragment index is marked as complete, which the mfra parsing
code never does.

This updates the mfra parsing code to mark the fragment index as
complete, similar to the way the sidx parsing code does.

With this change in place mov_read_default stops parsing top level boxes
in a fragmented mp4 and uses the mfra data for mov_seek_fragment calls
(assuming a use_mfra_for option is passed). When loading the file over a
network this results in significantly better performance since
avformat_open_input doesn't require a scan of the entire file.

Aaron
From 61412c5990037484e13c7daa60d83b8ba548b8a6 Mon Sep 17 00:00:00 2001
From: Aaron Boushley <aboushley@axon.com>
Date: Mon, 5 Nov 2018 11:02:00 -0800
Subject: [PATCH] libavformat/mov: Speed up fragmented mp4 parsing

When parsing a fragmented MP4 with the use_mfra_for option set so that
the mfra box is parsed we currently continue to parse all the top level
boxes in the mp4. We also avoid using the index in mov_seek_fragment
unless the fragment index is marked as complete, which the mfra parsing
code never does.

This updates the mfra parsing code to mark the fragment index as
complete, similar to the way the sidx parsing code does.

With this change in place mov_read_default stops parsing top level boxes
in a fragmented mp4 and uses the mfra data for mov_seek_fragment calls
(assuming a use_mfra_for option is passed). When loading the file over a
network this results in significantly better performance since
avformat_open_input doesn't require a scan of the entire file.

Signed-off-by: Aaron Boushley <boushley@gmail.com>
---
 libavformat/mov.c | 1 +
 1 file changed, 1 insertion(+)

Comments

Aaron Boushley Nov. 13, 2018, 11:34 p.m. UTC | #1
On Mon, Nov 5, 2018 at 3:48 PM Aaron Boushley <boushley@gmail.com> wrote:
>
> Sorry for the second thread, first one was corrupted with a newline
> because I attempted an inline patch. Hopefully the mime-type will be set
> correctly on this one.
> ---
> When parsing a fragmented MP4 with the use_mfra_for option set so that
> the mfra box is parsed we currently continue to parse all the top level
> boxes in the mp4. We also avoid using the index in mov_seek_fragment
> unless the fragment index is marked as complete, which the mfra parsing
> code never does.
>
> This updates the mfra parsing code to mark the fragment index as
> complete, similar to the way the sidx parsing code does.
>
> With this change in place mov_read_default stops parsing top level boxes
> in a fragmented mp4 and uses the mfra data for mov_seek_fragment calls
> (assuming a use_mfra_for option is passed). When loading the file over a
> network this results in significantly better performance since
> avformat_open_input doesn't require a scan of the entire file.
>
> Aaron

After further investigation this patch can result in the
AVFormatContext duration field being set incorrectly.

Because the mfra box doesn't contain the duration for the fragment we
have no way of knowing the duration from just reading the mfra. I will
investigate a patch where after reading all of the tfra boxes inside
the mfra we then read the moof for the last fragment. This should
allow us to get the duration without needing to scan every moof.

Aaron
diff mbox

Patch

diff --git a/libavformat/mov.c b/libavformat/mov.c
index ec57a05803..34ba7ffe61 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -7344,6 +7344,7 @@  static int mov_read_mfra(MOVContext *c, AVIOContext *f)
         if (ret < 0)
             goto fail;
     } while (!ret);
+    c->frag_index.complete = 1;
     ret = 0;
 fail:
     seek_ret = avio_seek(f, original_pos, SEEK_SET);