[FFmpeg-devel] [PATCH 1/2] oggdec: Support chained streams, support replacing streams in multistream files.

Michael Niedermayer michaelni at gmx.at
Wed Jan 16 20:20:21 CET 2013


Signed-off-by: Michael Niedermayer <michaelni at gmx.at>
---
 Changelog            |    1 +
 libavformat/oggdec.c |   37 ++++++++++++++++++++++++++++---------
 2 files changed, 29 insertions(+), 9 deletions(-)

diff --git a/Changelog b/Changelog
index 6a520d2..c51e2d7 100644
--- a/Changelog
+++ b/Changelog
@@ -4,6 +4,7 @@ releases are sorted from youngest to oldest.
 version <next>:
 - VDPAU hardware acceleration through normal hwaccel
 - SRTP support
+- Chained Ogg support
 
 
 version 1.1:
diff --git a/libavformat/oggdec.c b/libavformat/oggdec.c
index 3e3be2f..55604b4 100644
--- a/libavformat/oggdec.c
+++ b/libavformat/oggdec.c
@@ -57,6 +57,7 @@ static const struct ogg_codec * const ogg_codecs[] = {
 };
 
 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts);
+static int ogg_new_stream(AVFormatContext *s, uint32_t serial);
 
 //FIXME We could avoid some structure duplication
 static int ogg_save(AVFormatContext *s)
@@ -169,30 +170,48 @@ static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size)
  * situation where a new audio stream spawn (identified with a new serial) and
  * must replace the previous one (track switch).
  */
-static int ogg_replace_stream(AVFormatContext *s, uint32_t serial)
+static int ogg_replace_stream(AVFormatContext *s, uint32_t serial, int nsegs)
 {
     struct ogg *ogg = s->priv_data;
     struct ogg_stream *os;
     unsigned bufsize;
     uint8_t *buf;
     const struct ogg_codec *codec;
-
-    if (ogg->nstreams != 1) {
+    int i = 0;
+
+    if (s->pb->seekable) {
+        uint8_t magic[8];
+        int64_t pos = avio_tell(s->pb);
+        avio_skip(s->pb, nsegs);
+        avio_read(s->pb, magic, sizeof(magic));
+        avio_seek(s->pb, pos, SEEK_SET);
+        codec = ogg_find_codec(magic, sizeof(magic));
+        if (!codec) {
+            av_log(s, AV_LOG_ERROR, "Cannot identify new stream\n");
+            return AVERROR_INVALIDDATA;
+        }
+        for (i = 0; i < ogg->nstreams; i++) {
+            if (ogg->streams[i].codec == codec)
+                break;
+        }
+        if (i >= ogg->nstreams)
+            return ogg_new_stream(s, serial);
+    } else if (ogg->nstreams != 1) {
         av_log_missing_feature(s, "Changing stream parameters in multistream ogg", 0);
         return AVERROR_PATCHWELCOME;
     }
 
-    os = &ogg->streams[0];
+    os = &ogg->streams[i];
 
     os->serial  = serial;
-    return 0;
+    return i;
 
     buf     = os->buf;
     bufsize = os->bufsize;
     codec   = os->codec;
 
-    if (!ogg->state || ogg->state->streams[0].private != os->private)
-        av_freep(&ogg->streams[0].private);
+    if (!ogg->state || ogg->state->streams[i].private != os->private)
+        av_freep(&ogg->streams[i].private);
 
     /* Set Ogg stream settings similar to what is done in ogg_new_stream(). We
      * also re-use the ogg_stream allocated buffer */
@@ -203,7 +222,7 @@ static int ogg_replace_stream(AVFormatContext *s, uint32_t serial)
     os->header  = -1;
     os->codec   = codec;
 
-    return 0;
+    return i;
 }
 
 static int ogg_new_stream(AVFormatContext *s, uint32_t serial)
@@ -334,7 +353,7 @@ static int ogg_read_page(AVFormatContext *s, int *sid)
     idx = ogg_find_stream(ogg, serial);
     if (idx < 0) {
         if (data_packets_seen(ogg))
-            idx = ogg_replace_stream(s, serial);
+            idx = ogg_replace_stream(s, serial, nsegs);
         else
             idx = ogg_new_stream(s, serial);
 
-- 
1.7.9.5



More information about the ffmpeg-devel mailing list