2 * Flash Compatible Streaming Format
3 * Copyright (c) 2000 Fabrice Bellard.
4 * Copyright (c) 2003 Tinic Uro.
6 * This file is part of FFmpeg.
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 /*********************************************/
26 /* Extract FLV encoded frame and MP3 from swf
27 Note that the detection of the real frame
28 is inaccurate at this point as it can be
29 quite tricky to determine, you almost certainly
30 will get a bad audio/video sync */
32 static int get_swf_tag(ByteIOContext *pb, int *len_ptr)
45 // av_log(NULL, AV_LOG_DEBUG, "Tag: %d - Len: %d\n", tag, len);
51 static int swf_probe(AVProbeData *p)
53 /* check file header */
54 if ((p->buf[0] == 'F' || p->buf[0] == 'C') && p->buf[1] == 'W' &&
56 return AVPROBE_SCORE_MAX;
61 static int swf_read_header(AVFormatContext *s, AVFormatParameters *ap)
63 SWFContext *swf = s->priv_data;
64 ByteIOContext *pb = s->pb;
67 tag = get_be32(pb) & 0xffffff00;
69 if (tag == MKBETAG('C', 'W', 'S', 0)) {
70 av_log(s, AV_LOG_ERROR, "Compressed SWF format not supported\n");
73 if (tag != MKBETAG('F', 'W', 'S', 0))
76 /* skip rectangle size */
77 nbits = get_byte(pb) >> 3;
78 len = (4 * nbits - 3 + 7) / 8;
80 swf->frame_rate = get_le16(pb); /* 8.8 fixed */
81 get_le16(pb); /* frame count */
83 swf->samples_per_frame = 0;
84 s->ctx_flags |= AVFMTCTX_NOHEADER;
88 static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
90 SWFContext *swf = s->priv_data;
91 ByteIOContext *pb = s->pb;
92 AVStream *vst = NULL, *ast = NULL, *st = 0;
93 int tag, len, i, frame, v;
96 tag = get_swf_tag(pb, &len);
99 if (tag == TAG_VIDEOSTREAM && !vst) {
100 int ch_id = get_le16(pb);
106 vst = av_new_stream(s, ch_id);
109 vst->codec->codec_type = CODEC_TYPE_VIDEO;
110 vst->codec->codec_id = codec_get_id(swf_codec_tags, get_byte(pb));
111 av_set_pts_info(vst, 64, 256, swf->frame_rate);
112 vst->codec->time_base = (AVRational){ 256, swf->frame_rate };
114 } else if ((tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2) && !ast) {
115 /* streaming found */
116 int sample_rate_code;
119 swf->samples_per_frame = get_le16(pb);
120 ast = av_new_stream(s, -1); /* -1 to avoid clash with video stream ch_id */
123 swf->audio_stream_index = ast->index;
124 ast->codec->channels = 1 + (v&1);
125 ast->codec->codec_type = CODEC_TYPE_AUDIO;
126 ast->codec->codec_id = codec_get_id(swf_audio_codec_tags, (v>>4) & 15);
127 ast->need_parsing = AVSTREAM_PARSE_FULL;
128 sample_rate_code= (v>>2) & 3;
129 if (!sample_rate_code)
131 ast->codec->sample_rate = 11025 << (sample_rate_code-1);
132 av_set_pts_info(ast, 64, 1, ast->codec->sample_rate);
134 } else if (tag == TAG_VIDEOFRAME) {
135 int ch_id = get_le16(pb);
137 for(i=0; i<s->nb_streams; i++) {
139 if (st->codec->codec_type == CODEC_TYPE_VIDEO && st->id == ch_id) {
140 frame = get_le16(pb);
141 av_get_packet(pb, pkt, len-2);
143 pkt->stream_index = st->index;
147 } else if (tag == TAG_STREAMBLOCK) {
148 st = s->streams[swf->audio_stream_index];
149 if (st->codec->codec_id == CODEC_ID_MP3) {
151 av_get_packet(pb, pkt, len-4);
152 } else { // ADPCM, PCM
153 av_get_packet(pb, pkt, len);
155 pkt->stream_index = st->index;
157 } else if (tag == TAG_JPEG2) {
158 for (i=0; i<s->nb_streams; i++) {
163 if (i == s->nb_streams) {
164 vst = av_new_stream(s, -2); /* -2 to avoid clash with video stream and audio stream */
167 vst->codec->codec_type = CODEC_TYPE_VIDEO;
168 vst->codec->codec_id = CODEC_ID_MJPEG;
169 av_set_pts_info(vst, 64, 256, swf->frame_rate);
170 vst->codec->time_base = (AVRational){ 256, swf->frame_rate };
173 get_le16(pb); /* BITMAP_ID */
174 av_new_packet(pkt, len-2);
175 get_buffer(pb, pkt->data, 4);
176 if (AV_RB32(pkt->data) == 0xffd8ffd9 ||
177 AV_RB32(pkt->data) == 0xffd9ffd8) {
178 /* old SWF files containing SOI/EOI as data start */
179 /* files created by swink have reversed tag */
181 get_buffer(pb, pkt->data, pkt->size);
183 get_buffer(pb, pkt->data + 4, pkt->size - 4);
185 pkt->stream_index = st->index;
193 AVInputFormat swf_demuxer = {