[FFmpeg-cvslog] flvdec: initial stream switch support

Luca Barbato git at videolan.org
Wed Jul 4 00:36:32 CEST 2012


ffmpeg | branch: master | Luca Barbato <lu_zero at gentoo.org> | Sun Jul  1 23:01:00 2012 +0200| [09a445ce3426081da1254af62cb185180099e74e] | committer: Luca Barbato

flvdec: initial stream switch support

Codec change midstream gets mapped to a separate stream.

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=09a445ce3426081da1254af62cb185180099e74e
---

 libavformat/flvdec.c |   95 +++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 91 insertions(+), 4 deletions(-)

diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c
index 078c2a2..093cd0a 100644
--- a/libavformat/flvdec.c
+++ b/libavformat/flvdec.c
@@ -76,6 +76,59 @@ static AVStream *create_stream(AVFormatContext *s, int tag, int codec_type)
     avpriv_set_pts_info(st, 32, 1, 1000); /* 32 bit pts in ms */
     return st;
 }
+static int flv_same_audio_codec(AVCodecContext *acodec, int flags)
+{
+    int bits_per_coded_sample = (flags & FLV_AUDIO_SAMPLESIZE_MASK) ? 16 : 8;
+    int flv_codecid = flags & FLV_AUDIO_CODECID_MASK;
+    int codec_id;
+
+    if (!acodec->codec_id && !acodec->codec_tag)
+        return 1;
+
+    if (acodec->bits_per_coded_sample != bits_per_coded_sample)
+        return 0;
+
+    switch(flv_codecid) {
+        //no distinction between S16 and S8 PCM codec flags
+    case FLV_CODECID_PCM:
+        codec_id = bits_per_coded_sample == 8 ? CODEC_ID_PCM_U8 :
+#if HAVE_BIGENDIAN
+                            CODEC_ID_PCM_S16BE;
+#else
+                            CODEC_ID_PCM_S16LE;
+#endif
+        return codec_id == acodec->codec_id;
+    case FLV_CODECID_PCM_LE:
+        codec_id = bits_per_coded_sample == 8 ? CODEC_ID_PCM_U8 : CODEC_ID_PCM_S16LE;
+        return codec_id == acodec->codec_id;
+    case FLV_CODECID_AAC:
+        return acodec->codec_id == CODEC_ID_AAC;
+    case FLV_CODECID_ADPCM:
+        return acodec->codec_id == CODEC_ID_ADPCM_SWF;
+    case FLV_CODECID_SPEEX:
+        return acodec->codec_id == CODEC_ID_SPEEX;
+    case FLV_CODECID_MP3:
+        return acodec->codec_id == CODEC_ID_MP3;
+    case FLV_CODECID_NELLYMOSER_8KHZ_MONO:
+        return acodec->sample_rate == 8000 &&
+               acodec->codec_id == CODEC_ID_NELLYMOSER;
+    case FLV_CODECID_NELLYMOSER_16KHZ_MONO:
+        return acodec->sample_rate == 16000 &&
+               acodec->codec_id == CODEC_ID_NELLYMOSER;
+    case FLV_CODECID_NELLYMOSER:
+        return acodec->codec_id == CODEC_ID_NELLYMOSER;
+    case FLV_CODECID_PCM_MULAW:
+        return acodec->sample_rate == 8000 &&
+               acodec->codec_id == CODEC_ID_PCM_MULAW;
+    case FLV_CODECID_PCM_ALAW:
+        return acodec->sample_rate = 8000 &&
+               acodec->codec_id == CODEC_ID_PCM_ALAW;
+    default:
+        return acodec->codec_tag == (flv_codecid >> FLV_AUDIO_CODECID_OFFSET);
+    }
+
+    return 0;
+}
 
 static void flv_set_audio_codec(AVFormatContext *s, AVStream *astream, AVCodecContext *acodec, int flv_codecid) {
     switch(flv_codecid) {
@@ -122,6 +175,33 @@ static void flv_set_audio_codec(AVFormatContext *s, AVStream *astream, AVCodecCo
     }
 }
 
+static int flv_same_video_codec(AVCodecContext *vcodec, int flags)
+{
+    int flv_codecid = flags & FLV_VIDEO_CODECID_MASK;
+
+    if (!vcodec->codec_id && !vcodec->codec_tag)
+        return 1;
+
+    switch (flv_codecid) {
+        case FLV_CODECID_H263:
+            return vcodec->codec_id == CODEC_ID_FLV1;
+        case FLV_CODECID_SCREEN:
+            return vcodec->codec_id == CODEC_ID_FLASHSV;
+        case FLV_CODECID_SCREEN2:
+            return vcodec->codec_id == CODEC_ID_FLASHSV2;
+        case FLV_CODECID_VP6:
+            return vcodec->codec_id == CODEC_ID_VP6F;
+        case FLV_CODECID_VP6A:
+            return vcodec->codec_id == CODEC_ID_VP6A;
+        case FLV_CODECID_H264:
+            return vcodec->codec_id == CODEC_ID_H264;
+        default:
+            return vcodec->codec_tag == flv_codecid;
+    }
+
+    return 0;
+}
+
 static int flv_set_video_codec(AVFormatContext *s, AVStream *vstream, int flv_codecid) {
     AVCodecContext *vcodec = vstream->codec;
     switch(flv_codecid) {
@@ -511,7 +591,7 @@ static int flv_data_packet(AVFormatContext *s, AVPacket *pkt,
 
     for (i = 0; i < s->nb_streams; i++) {
         st = s->streams[i];
-        if (st->id == 2)
+        if (st->codec->codec_type == AVMEDIA_TYPE_DATA)
             break;
     }
 
@@ -605,11 +685,18 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
     /* now find stream */
     for(i=0;i<s->nb_streams;i++) {
         st = s->streams[i];
-        if (st->id == is_audio)
-            break;
+        if (is_audio && st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
+            if (flv_same_audio_codec(st->codec, flags)) {
+                break;
+            }
+        } else
+        if (!is_audio && st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+            if (flv_same_video_codec(st->codec, flags)) {
+                break;
+            }
+        }
     }
     if(i == s->nb_streams){
-        av_log(s, AV_LOG_ERROR, "invalid stream\n");
         st = create_stream(s, is_audio,
              is_audio ? AVMEDIA_TYPE_AUDIO : AVMEDIA_TYPE_VIDEO);
         s->ctx_flags &= ~AVFMTCTX_NOHEADER;



More information about the ffmpeg-cvslog mailing list