[FFmpeg-devel] [PATCH] avformat/mov: fix sidx loading issues in fragmented files.

agrecascino123 at gmail.com agrecascino123 at gmail.com
Sun Feb 10 06:44:52 EET 2019


From: mptcultist  <agrecascino123 at gmail.com>

fixed issue where if sidx was after another sidx and happened to point to the same media, it wouldn't be read.
this is done by counting the sidx atoms before they're read. for #7572
---
 libavformat/isom.h |  2 ++
 libavformat/mov.c  | 45 +++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 45 insertions(+), 2 deletions(-)

diff --git a/libavformat/isom.h b/libavformat/isom.h
index 69452cae8e..cc3067d2c0 100644
--- a/libavformat/isom.h
+++ b/libavformat/isom.h
@@ -288,6 +288,8 @@ typedef struct MOVContext {
     int decryption_key_len;
     int enable_drefs;
     int32_t movie_display_matrix[3][3]; ///< display matrix from mvhd
+    int sidx_count;
+    int cur_sidx;
 } MOVContext;
 
 int ff_mp4_read_descr_len(AVIOContext *pb);
diff --git a/libavformat/mov.c b/libavformat/mov.c
index cc91beb7f9..a59c893274 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -4961,6 +4961,8 @@ static int mov_read_sidx(MOVContext *c, AVIOContext *pb, MOVAtom atom)
     MOVStreamContext *sc, *ref_sc = NULL;
     AVRational timescale;
 
+    c->cur_sidx++;
+
     version = avio_r8(pb);
     if (version > 1) {
         avpriv_request_sample(c->fc, "sidx version %u", version);
@@ -5027,7 +5029,8 @@ static int mov_read_sidx(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 
     sc->has_sidx = 1;
 
-    if (offset == avio_size(pb)) {
+    if ((!(pb->seekable & AVIO_SEEKABLE_NORMAL) && (offset == avio_size(pb))) ||
+         ((pb->seekable & AVIO_SEEKABLE_NORMAL) && (c->sidx_count == c->cur_sidx))  ) {
         // Find first entry in fragment index that came from an sidx.
         // This will pretty much always be the first entry.
         for (i = 0; i < c->frag_index.nb_items; i++) {
@@ -6779,6 +6782,43 @@ static const MOVParseTableEntry mov_default_parse_table[] = {
 { 0, NULL }
 };
 
+static int mov_count_sidx(MOVContext *c, AVIOContext *pb, MOVAtom atom)
+{
+    int64_t total_size = 0;
+    MOVAtom a;
+    int si = 0;
+
+    if (atom.size < 0)
+        atom.size = INT64_MAX;
+    while (total_size <= atom.size - 8 && !avio_feof(pb)) {
+        a.size = atom.size;
+        a.type=0;
+        if (atom.size >= 8) {
+            a.size = avio_rb32(pb);
+            a.type = avio_rl32(pb);
+            if (a.type == MKTAG('s','i','d','x')) {
+                si++;
+            }
+            total_size += 8;
+            if (a.size == 1 && total_size + 8 <= atom.size) { /* 64 bit extended size */
+                a.size = avio_rb64(pb) - 8;
+                total_size += 8;
+            }
+        }
+        if (a.size == 0) {
+            a.size = atom.size - total_size + 8;
+        }
+        a.size -= 8;
+        if (a.size < 0)
+            break;
+        a.size = FFMIN(a.size, atom.size - total_size);
+        avio_skip(pb, a.size);
+        total_size += a.size;
+    }
+    avio_seek(pb, 0, SEEK_SET);
+    return si;
+}
+
 static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 {
     int64_t total_size = 0;
@@ -7401,7 +7441,8 @@ static int mov_read_header(AVFormatContext *s)
         atom.size = avio_size(pb);
     else
         atom.size = INT64_MAX;
-
+    if (pb->seekable & AVIO_SEEKABLE_NORMAL)
+        mov->sidx_count = mov_count_sidx(mov, pb, atom);
     /* check MOV header */
     do {
         if (mov->moov_retry)
-- 
2.20.1



More information about the ffmpeg-devel mailing list