diff mbox series

[FFmpeg-devel,2/2] avformat mov fix to detect if stream position has been reset

Message ID 20200424152042.29383-3-hello.vectronic@gmail.com
State New
Headers show
Series fix for seeking in HLS with TS/FMP4 media
Related show

Checks

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

Commit Message

vectronic April 24, 2020, 3:20 p.m. UTC
if pos has been reset, clear fragments and indexes and search for next root

Signed-off-by: vectronic <hello.vectronic@gmail.com>
---
 libavformat/mov.c | 36 +++++++++++++++++++++++++++++++++---
 1 file changed, 33 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/libavformat/mov.c b/libavformat/mov.c
index 3d6fef685d..8f051fb9b1 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -7796,15 +7796,15 @@  static int mov_switch_root(AVFormatContext *s, int64_t target, int index)
 
     if (index >= 0 && index < mov->frag_index.nb_items)
         target = mov->frag_index.item[index].moof_offset;
-    if (avio_seek(s->pb, target, SEEK_SET) != target) {
+    if (target >= 0 && avio_seek(s->pb, target, SEEK_SET) != target) {
         av_log(mov->fc, AV_LOG_ERROR, "root atom offset 0x%"PRIx64": partial file\n", target);
         return AVERROR_INVALIDDATA;
     }
 
     mov->next_root_atom = 0;
-    if (index < 0 || index >= mov->frag_index.nb_items)
+    if ((index < 0 && target >= 0) || index >= mov->frag_index.nb_items)
         index = search_frag_moof_offset(&mov->frag_index, target);
-    if (index < mov->frag_index.nb_items &&
+    if (index >= 0 && index < mov->frag_index.nb_items &&
         mov->frag_index.item[index].moof_offset == target) {
         if (index + 1 < mov->frag_index.nb_items)
             mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
@@ -7856,8 +7856,38 @@  static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
     AVStream *st = NULL;
     int64_t current_index;
     int ret;
+    int i;
     mov->fc = s;
  retry:
+    if (s->pb->pos == 0) {
+
+        // Discard current fragment index
+        if (mov->frag_index.allocated_size > 0) {
+            av_freep(&mov->frag_index.item);
+            mov->frag_index.nb_items = 0;
+            mov->frag_index.allocated_size = 0;
+            mov->frag_index.current = -1;
+            mov->frag_index.complete = 0;
+        }
+
+        for (i = 0; i < s->nb_streams; i++) {
+            AVStream *avst = s->streams[i];
+            MOVStreamContext *msc = avst->priv_data;
+
+            // Clear current sample
+            mov_current_sample_set(msc, 0);
+
+            // Discard current index entries
+            if (avst->index_entries_allocated_size > 0) {
+                av_freep(&avst->index_entries);
+                avst->index_entries_allocated_size = 0;
+                avst->nb_index_entries = 0;
+            }
+        }
+
+        if ((ret = mov_switch_root(s, -1, -1)) < 0)
+            return ret;
+    }
     sample = mov_find_next_sample(s, &st);
     if (!sample || (mov->next_root_atom && sample->pos > mov->next_root_atom)) {
         if (!mov->next_root_atom)