[FFmpeg-devel] [PATCH] make stream-switching work with MOV demuxer

Reimar Döffinger Reimar.Doeffinger
Tue Jun 23 20:09:05 CEST 2009


Hello,
currently the MOV demuxer does not even keep track of the "current"
position of streams set to AVDISCARD_ALL.
This means that when removing AVDISCARD_ALL, that stream will start
playing from the beginning.
Now, the current behaviour may be valid, but it is at least inconsistent
with most other demuxers, and at least with the current seeking API I
can not see how else it should be possible to seamlessly switch between
e.g. different audio streams.
Since it duplicates code, attached patch is hardly acceptable, but it
fixes the issue...
-------------- next part --------------
Index: libavformat/mov.c
===================================================================
--- libavformat/mov.c	(revision 19256)
+++ libavformat/mov.c	(working copy)
@@ -1981,14 +1981,16 @@
 {
     MOVContext *mov = s->priv_data;
     MOVStreamContext *sc = 0;
-    AVIndexEntry *sample = 0;
+    AVIndexEntry *sample;
     int64_t best_dts = INT64_MAX;
+    int discard = 0;
     int i, ret;
  retry:
+    sample = NULL;
     for (i = 0; i < s->nb_streams; i++) {
         AVStream *st = s->streams[i];
         MOVStreamContext *msc = st->priv_data;
-        if (st->discard != AVDISCARD_ALL && msc->pb && msc->current_sample < st->nb_index_entries) {
+        if (msc->pb && msc->current_sample < st->nb_index_entries) {
             AVIndexEntry *current_sample = &st->index_entries[msc->current_sample];
             int64_t dts = av_rescale(current_sample->timestamp, AV_TIME_BASE, msc->time_scale);
             dprintf(s, "stream %d, sample %d, dts %"PRId64"\n", i, msc->current_sample, dts);
@@ -2000,6 +2002,7 @@
                 sample = current_sample;
                 best_dts = dts;
                 sc = msc;
+                discard = st->discard == AVDISCARD_ALL;
             }
         }
     }
@@ -2014,6 +2017,18 @@
     }
     /* must be done just before reading, to avoid infinite loop on sample */
     sc->current_sample++;
+    if (discard) {
+        if (sc->ctts_data) {
+            /* update ctts context */
+            sc->ctts_sample++;
+            if (sc->ctts_index < sc->ctts_count &&
+                sc->ctts_data[sc->ctts_index].count == sc->ctts_sample) {
+                sc->ctts_index++;
+                sc->ctts_sample = 0;
+            }
+        }
+        goto retry;
+    }
     if (url_fseek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
         av_log(mov->fc, AV_LOG_ERROR, "stream %d, offset 0x%"PRIx64": partial file\n",
                sc->ffindex, sample->pos);
@@ -2108,7 +2123,7 @@
 
     for (i = 0; i < s->nb_streams; i++) {
         st = s->streams[i];
-        if (stream_index == i || st->discard == AVDISCARD_ALL)
+        if (stream_index == i)
             continue;
 
         timestamp = av_rescale_q(seek_timestamp, s->streams[stream_index]->time_base, st->time_base);



More information about the ffmpeg-devel mailing list