From a41c824c539cc1fe79b3afd9393a91d22a8065da Mon Sep 17 00:00:00 2001 From: Michael Bradshaw Date: Thu, 11 Oct 2012 19:48:44 -0600 Subject: [PATCH] Parse DEFINESOUND tags in swf (fix ticket 1638) Signed-off-by: Michael Bradshaw Signed-off-by: Michael Niedermayer --- libavformat/swf.h | 1 + libavformat/swfdec.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/libavformat/swf.h b/libavformat/swf.h index 5f0d486233..4e8f877b67 100644 --- a/libavformat/swf.h +++ b/libavformat/swf.h @@ -44,6 +44,7 @@ #define TAG_FREECHARACTER 3 #define TAG_PLACEOBJECT 4 #define TAG_REMOVEOBJECT 5 +#define TAG_DEFINESOUND 14 #define TAG_STREAMHEAD 18 #define TAG_STREAMBLOCK 19 #define TAG_JPEG2 21 diff --git a/libavformat/swfdec.c b/libavformat/swfdec.c index 3967d82ef3..8a57a34d04 100644 --- a/libavformat/swfdec.c +++ b/libavformat/swfdec.c @@ -200,6 +200,44 @@ static int swf_read_packet(AVFormatContext *s, AVPacket *pkt) ast->codec->sample_rate = 44100 >> (3 - sample_rate_code); avpriv_set_pts_info(ast, 64, 1, ast->codec->sample_rate); len -= 4; + } else if (tag == TAG_DEFINESOUND) { + /* audio stream */ + int sample_rate_code; + int ch_id = avio_rl16(pb); + + for (i=0; inb_streams; i++) { + st = s->streams[i]; + if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && st->id == ch_id) + goto skip; + } + + // FIXME: 8-bit uncompressed PCM audio will be interpreted as 16-bit + // FIXME: The entire audio stream is stored in a single chunk/tag. Normally, + // these are smaller audio streams in DEFINESOUND tags, but it's technically + // possible they could be huge. Break it up into multiple packets if it's big. + v = avio_r8(pb); + ast = avformat_new_stream(s, NULL); + if (!ast) + return -1; + ast->id = ch_id; + ast->codec->channels = 1 + (v&1); + ast->codec->codec_type = AVMEDIA_TYPE_AUDIO; + ast->codec->codec_id = ff_codec_get_id(swf_audio_codec_tags, (v>>4) & 15); + ast->need_parsing = AVSTREAM_PARSE_FULL; + sample_rate_code= (v>>2) & 3; + ast->codec->sample_rate = 44100 >> (3 - sample_rate_code); + avpriv_set_pts_info(ast, 64, 1, ast->codec->sample_rate); + ast->duration = avio_rl32(pb); // number of samples + if (((v>>4) & 15) == 2) { // MP3 sound data record + ast->skip_samples = avio_rl16(pb); + len -= 2; + } + len -= 7; + if ((res = av_get_packet(pb, pkt, len)) < 0) + return res; + pkt->pos = pos; + pkt->stream_index = ast->index; + return pkt->size; } else if (tag == TAG_VIDEOFRAME) { int ch_id = avio_rl16(pb); len -= 2;