comparison swfdec.c @ 3302:171f5664d129 libavformat

split swf de/muxer
author bcoudurier
date Tue, 20 May 2008 23:31:10 +0000
parents swf.c@6f61c3b36632
children 811758d926fd
comparison
equal deleted inserted replaced
3301:11b6da5ffe78 3302:171f5664d129
1 /*
2 * Flash Compatible Streaming Format
3 * Copyright (c) 2000 Fabrice Bellard.
4 * Copyright (c) 2003 Tinic Uro.
5 *
6 * This file is part of FFmpeg.
7 *
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.
12 *
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.
17 *
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
21 */
22
23 #include "swf.h"
24
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 */
31
32 static int get_swf_tag(ByteIOContext *pb, int *len_ptr)
33 {
34 int tag, len;
35
36 if (url_feof(pb))
37 return -1;
38
39 tag = get_le16(pb);
40 len = tag & 0x3f;
41 tag = tag >> 6;
42 if (len == 0x3f) {
43 len = get_le32(pb);
44 }
45 // av_log(NULL, AV_LOG_DEBUG, "Tag: %d - Len: %d\n", tag, len);
46 *len_ptr = len;
47 return tag;
48 }
49
50
51 static int swf_probe(AVProbeData *p)
52 {
53 /* check file header */
54 if ((p->buf[0] == 'F' || p->buf[0] == 'C') && p->buf[1] == 'W' &&
55 p->buf[2] == 'S')
56 return AVPROBE_SCORE_MAX;
57 else
58 return 0;
59 }
60
61 static int swf_read_header(AVFormatContext *s, AVFormatParameters *ap)
62 {
63 SWFContext *swf = s->priv_data;
64 ByteIOContext *pb = s->pb;
65 int nbits, len, tag;
66
67 tag = get_be32(pb) & 0xffffff00;
68
69 if (tag == MKBETAG('C', 'W', 'S', 0)) {
70 av_log(s, AV_LOG_ERROR, "Compressed SWF format not supported\n");
71 return AVERROR(EIO);
72 }
73 if (tag != MKBETAG('F', 'W', 'S', 0))
74 return AVERROR(EIO);
75 get_le32(pb);
76 /* skip rectangle size */
77 nbits = get_byte(pb) >> 3;
78 len = (4 * nbits - 3 + 7) / 8;
79 url_fskip(pb, len);
80 swf->frame_rate = get_le16(pb); /* 8.8 fixed */
81 get_le16(pb); /* frame count */
82
83 swf->samples_per_frame = 0;
84 s->ctx_flags |= AVFMTCTX_NOHEADER;
85 return 0;
86 }
87
88 static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
89 {
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;
94
95 for(;;) {
96 tag = get_swf_tag(pb, &len);
97 if (tag < 0)
98 return AVERROR(EIO);
99 if (tag == TAG_VIDEOSTREAM && !vst) {
100 int ch_id = get_le16(pb);
101 get_le16(pb);
102 get_le16(pb);
103 get_le16(pb);
104 get_byte(pb);
105 /* Check for FLV1 */
106 vst = av_new_stream(s, ch_id);
107 if (!vst)
108 return -1;
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 };
113 len -= 10;
114 } else if ((tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2) && !ast) {
115 /* streaming found */
116 int sample_rate_code;
117 get_byte(pb);
118 v = get_byte(pb);
119 swf->samples_per_frame = get_le16(pb);
120 ast = av_new_stream(s, -1); /* -1 to avoid clash with video stream ch_id */
121 if (!ast)
122 return -1;
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)
130 return AVERROR(EIO);
131 ast->codec->sample_rate = 11025 << (sample_rate_code-1);
132 av_set_pts_info(ast, 64, 1, ast->codec->sample_rate);
133 len -= 4;
134 } else if (tag == TAG_VIDEOFRAME) {
135 int ch_id = get_le16(pb);
136 len -= 2;
137 for(i=0; i<s->nb_streams; i++) {
138 st = s->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);
142 pkt->pts = frame;
143 pkt->stream_index = st->index;
144 return pkt->size;
145 }
146 }
147 } else if (tag == TAG_STREAMBLOCK) {
148 st = s->streams[swf->audio_stream_index];
149 if (st->codec->codec_id == CODEC_ID_MP3) {
150 url_fskip(pb, 4);
151 av_get_packet(pb, pkt, len-4);
152 } else { // ADPCM, PCM
153 av_get_packet(pb, pkt, len);
154 }
155 pkt->stream_index = st->index;
156 return pkt->size;
157 } else if (tag == TAG_JPEG2) {
158 for (i=0; i<s->nb_streams; i++) {
159 st = s->streams[i];
160 if (st->id == -2)
161 break;
162 }
163 if (i == s->nb_streams) {
164 vst = av_new_stream(s, -2); /* -2 to avoid clash with video stream and audio stream */
165 if (!vst)
166 return -1;
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 };
171 st = vst;
172 }
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 */
180 pkt->size -= 4;
181 get_buffer(pb, pkt->data, pkt->size);
182 } else {
183 get_buffer(pb, pkt->data + 4, pkt->size - 4);
184 }
185 pkt->stream_index = st->index;
186 return pkt->size;
187 }
188 url_fskip(pb, len);
189 }
190 return 0;
191 }
192
193 static int swf_read_close(AVFormatContext *s)
194 {
195 return 0;
196 }
197
198 AVInputFormat swf_demuxer = {
199 "swf",
200 "Flash format",
201 sizeof(SWFContext),
202 swf_probe,
203 swf_read_header,
204 swf_read_packet,
205 swf_read_close,
206 };