f105c141c60e036181db4ede608794bb940e2dcc
[ffmpeg.git] / libavformat / swfdec.c
1 /*
2  * Flash Compatible Streaming Format demuxer
3  * Copyright (c) 2000 Fabrice Bellard
4  * Copyright (c) 2003 Tinic Uro
5  *
6  * This file is part of Libav.
7  *
8  * Libav 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.
12  *
13  * Libav 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.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with Libav; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22
23 #include "libavutil/channel_layout.h"
24 #include "libavutil/intreadwrite.h"
25 #include "swf.h"
26
27 static const AVCodecTag swf_audio_codec_tags[] = {
28     { AV_CODEC_ID_PCM_S16LE,  0x00 },
29     { AV_CODEC_ID_ADPCM_SWF,  0x01 },
30     { AV_CODEC_ID_MP3,        0x02 },
31     { AV_CODEC_ID_PCM_S16LE,  0x03 },
32 //  { AV_CODEC_ID_NELLYMOSER, 0x06 },
33     { AV_CODEC_ID_NONE,          0 },
34 };
35
36 static int get_swf_tag(AVIOContext *pb, int *len_ptr)
37 {
38     int tag, len;
39
40     if (pb->eof_reached)
41         return -1;
42
43     tag = avio_rl16(pb);
44     len = tag & 0x3f;
45     tag = tag >> 6;
46     if (len == 0x3f) {
47         len = avio_rl32(pb);
48     }
49     *len_ptr = len;
50     return tag;
51 }
52
53
54 static int swf_probe(AVProbeData *p)
55 {
56     /* check file header */
57     if ((p->buf[0] == 'F' || p->buf[0] == 'C') && p->buf[1] == 'W' &&
58         p->buf[2] == 'S')
59         return AVPROBE_SCORE_MAX;
60     else
61         return 0;
62 }
63
64 static int swf_read_header(AVFormatContext *s)
65 {
66     SWFContext *swf = s->priv_data;
67     AVIOContext *pb = s->pb;
68     int nbits, len, tag;
69
70     tag = avio_rb32(pb) & 0xffffff00;
71
72     if (tag == MKBETAG('C', 'W', 'S', 0)) {
73         av_log(s, AV_LOG_ERROR, "Compressed SWF format not supported\n");
74         return AVERROR(EIO);
75     }
76     if (tag != MKBETAG('F', 'W', 'S', 0))
77         return AVERROR(EIO);
78     avio_rl32(pb);
79     /* skip rectangle size */
80     nbits = avio_r8(pb) >> 3;
81     len = (4 * nbits - 3 + 7) / 8;
82     avio_skip(pb, len);
83     swf->frame_rate = avio_rl16(pb); /* 8.8 fixed */
84     avio_rl16(pb); /* frame count */
85
86     swf->samples_per_frame = 0;
87     s->ctx_flags |= AVFMTCTX_NOHEADER;
88     return 0;
89 }
90
91 static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
92 {
93     SWFContext *swf = s->priv_data;
94     AVIOContext *pb = s->pb;
95     AVStream *vst = NULL, *ast = NULL, *st = 0;
96     int tag, len, i, frame, v, res;
97
98     for(;;) {
99         uint64_t pos = avio_tell(pb);
100         tag = get_swf_tag(pb, &len);
101         if (tag < 0)
102             return AVERROR(EIO);
103         if (tag == TAG_VIDEOSTREAM) {
104             int ch_id = avio_rl16(pb);
105             len -= 2;
106
107             for (i=0; i<s->nb_streams; i++) {
108                 st = s->streams[i];
109                 if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && st->id == ch_id)
110                     goto skip;
111             }
112
113             avio_rl16(pb);
114             avio_rl16(pb);
115             avio_rl16(pb);
116             avio_r8(pb);
117             /* Check for FLV1 */
118             vst = avformat_new_stream(s, NULL);
119             if (!vst)
120                 return -1;
121             vst->id = ch_id;
122             vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
123             vst->codec->codec_id = ff_codec_get_id(ff_swf_codec_tags, avio_r8(pb));
124             avpriv_set_pts_info(vst, 16, 256, swf->frame_rate);
125             len -= 8;
126         } else if (tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2) {
127             /* streaming found */
128             int sample_rate_code;
129
130             for (i=0; i<s->nb_streams; i++) {
131                 st = s->streams[i];
132                 if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && st->id == -1)
133                     goto skip;
134             }
135
136             avio_r8(pb);
137             v = avio_r8(pb);
138             swf->samples_per_frame = avio_rl16(pb);
139             ast = avformat_new_stream(s, NULL);
140             if (!ast)
141                 return -1;
142             ast->id = -1; /* -1 to avoid clash with video stream ch_id */
143             if (v & 1) {
144                 ast->codec->channels       = 2;
145                 ast->codec->channel_layout = AV_CH_LAYOUT_STEREO;
146             } else {
147                 ast->codec->channels       = 1;
148                 ast->codec->channel_layout = AV_CH_LAYOUT_MONO;
149             }
150             ast->codec->codec_type = AVMEDIA_TYPE_AUDIO;
151             ast->codec->codec_id = ff_codec_get_id(swf_audio_codec_tags, (v>>4) & 15);
152             ast->need_parsing = AVSTREAM_PARSE_FULL;
153             sample_rate_code= (v>>2) & 3;
154             ast->codec->sample_rate = 44100 >> (3 - sample_rate_code);
155             avpriv_set_pts_info(ast, 64, 1, ast->codec->sample_rate);
156             len -= 4;
157         } else if (tag == TAG_VIDEOFRAME) {
158             int ch_id = avio_rl16(pb);
159             len -= 2;
160             for(i=0; i<s->nb_streams; i++) {
161                 st = s->streams[i];
162                 if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && st->id == ch_id) {
163                     frame = avio_rl16(pb);
164                     if ((res = av_get_packet(pb, pkt, len-2)) < 0)
165                         return res;
166                     pkt->pos = pos;
167                     pkt->pts = frame;
168                     pkt->stream_index = st->index;
169                     return pkt->size;
170                 }
171             }
172         } else if (tag == TAG_STREAMBLOCK) {
173             for (i = 0; i < s->nb_streams; i++) {
174                 st = s->streams[i];
175                 if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && st->id == -1) {
176             if (st->codec->codec_id == AV_CODEC_ID_MP3) {
177                 avio_skip(pb, 4);
178                 if ((res = av_get_packet(pb, pkt, len-4)) < 0)
179                     return res;
180             } else { // ADPCM, PCM
181                 if ((res = av_get_packet(pb, pkt, len)) < 0)
182                     return res;
183             }
184             pkt->pos = pos;
185             pkt->stream_index = st->index;
186             return pkt->size;
187                 }
188             }
189         } else if (tag == TAG_JPEG2) {
190             for (i=0; i<s->nb_streams; i++) {
191                 st = s->streams[i];
192                 if (st->codec->codec_id == AV_CODEC_ID_MJPEG && st->id == -2)
193                     break;
194             }
195             if (i == s->nb_streams) {
196                 vst = avformat_new_stream(s, NULL);
197                 if (!vst)
198                     return -1;
199                 vst->id = -2; /* -2 to avoid clash with video stream and audio stream */
200                 vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
201                 vst->codec->codec_id = AV_CODEC_ID_MJPEG;
202                 avpriv_set_pts_info(vst, 64, 256, swf->frame_rate);
203                 st = vst;
204             }
205             avio_rl16(pb); /* BITMAP_ID */
206             if ((res = av_new_packet(pkt, len-2)) < 0)
207                 return res;
208             avio_read(pb, pkt->data, 4);
209             if (AV_RB32(pkt->data) == 0xffd8ffd9 ||
210                 AV_RB32(pkt->data) == 0xffd9ffd8) {
211                 /* old SWF files containing SOI/EOI as data start */
212                 /* files created by swink have reversed tag */
213                 pkt->size -= 4;
214                 avio_read(pb, pkt->data, pkt->size);
215             } else {
216                 avio_read(pb, pkt->data + 4, pkt->size - 4);
217             }
218             pkt->pos = pos;
219             pkt->stream_index = st->index;
220             return pkt->size;
221         }
222     skip:
223         avio_skip(pb, len);
224     }
225 }
226
227 AVInputFormat ff_swf_demuxer = {
228     .name           = "swf",
229     .long_name      = NULL_IF_CONFIG_SMALL("SWF (ShockWave Flash)"),
230     .priv_data_size = sizeof(SWFContext),
231     .read_probe     = swf_probe,
232     .read_header    = swf_read_header,
233     .read_packet    = swf_read_packet,
234 };