[FFmpeg-devel] [PATCH 8/9] lavf/oggdec: make stream replacement less convoluted.

Clément Bœsch ubitux at gmail.com
Sat Sep 15 01:20:47 CEST 2012


Also re-use the allocated buffer instead of re-allocating a new one.
---
 libavformat/oggdec.c | 58 ++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 40 insertions(+), 18 deletions(-)

diff --git a/libavformat/oggdec.c b/libavformat/oggdec.c
index aed49a5..5b3b789 100644
--- a/libavformat/oggdec.c
+++ b/libavformat/oggdec.c
@@ -161,9 +161,44 @@ static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size)
     return NULL;
 }
 
-static int ogg_new_stream(AVFormatContext *s, uint32_t serial, int new_avstream)
+/**
+ * Reset the current stream with a new one. This is a typical webradio
+ * 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)
 {
+    struct ogg *ogg = s->priv_data;
+    struct ogg_stream *os;
+    unsigned bufsize;
+    uint8_t *buf;
+
+    if (ogg->nstreams != 1) {
+        av_log_missing_feature(s, "Changing stream parameters in multistream ogg is", 0);
+        return AVERROR_PATCHWELCOME;
+    }
 
+    os = &ogg->streams[0];
+
+    buf = os->buf;
+    bufsize = os->bufsize;
+
+    if (!ogg->state || ogg->state->streams[0].private != os->private)
+        av_freep(&ogg->streams[0].private);
+
+    /* Set Ogg stream settings similar to what is done in ogg_new_stream(). We
+     * also re-use the ogg_stream allocated buffer */
+    memset(os, 0, sizeof(*os));
+    os->serial = serial;
+    os->bufsize = bufsize;
+    os->buf = buf;
+    os->header = -1;
+
+    return 0;
+}
+
+static int ogg_new_stream(AVFormatContext *s, uint32_t serial)
+{
     struct ogg *ogg = s->priv_data;
     int idx = ogg->nstreams++;
     AVStream *st;
@@ -182,14 +217,12 @@ static int ogg_new_stream(AVFormatContext *s, uint32_t serial, int new_avstream)
     if (!os->buf)
         return AVERROR(ENOMEM);
 
-    if (new_avstream) {
         st = avformat_new_stream(s, NULL);
         if (!st)
             return AVERROR(ENOMEM);
 
         st->id = idx;
         avpriv_set_pts_info(st, 64, 1, 1000000);
-    }
 
     return idx;
 }
@@ -259,22 +292,11 @@ static int ogg_read_page(AVFormatContext *s, int *sid)
 
     idx = ogg_find_stream (ogg, serial);
     if (idx < 0){
-        if (ogg->headers) {
+        if (ogg->headers)
+            idx = ogg_replace_stream(s, serial);
+        else
+            idx = ogg_new_stream(s, serial);
 
-            if (ogg->nstreams != 1) {
-                av_log_missing_feature(s, "Changing stream parameters in multistream ogg is", 0);
-                return idx;
-            }
-
-            av_freep(&ogg->streams[0].buf);
-            if (!ogg->state || ogg->state->streams[0].private != ogg->streams[0].private)
-                av_freep(&ogg->streams[0].private);
-            ogg->curidx   = -1;
-            ogg->nstreams = 0;
-            idx = ogg_new_stream(s, serial, 0);
-        } else {
-            idx = ogg_new_stream(s, serial, 1);
-        }
         if (idx < 0)
             return idx;
     }
-- 
1.7.12



More information about the ffmpeg-devel mailing list