00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "libavutil/intreadwrite.h"
00024 #include "swf.h"
00025
00026 static const AVCodecTag swf_audio_codec_tags[] = {
00027 { AV_CODEC_ID_PCM_S16LE, 0x00 },
00028 { AV_CODEC_ID_ADPCM_SWF, 0x01 },
00029 { AV_CODEC_ID_MP3, 0x02 },
00030 { AV_CODEC_ID_PCM_S16LE, 0x03 },
00031
00032 { AV_CODEC_ID_NONE, 0 },
00033 };
00034
00035 static int get_swf_tag(AVIOContext *pb, int *len_ptr)
00036 {
00037 int tag, len;
00038
00039 if (url_feof(pb))
00040 return AVERROR_EOF;
00041
00042 tag = avio_rl16(pb);
00043 len = tag & 0x3f;
00044 tag = tag >> 6;
00045 if (len == 0x3f) {
00046 len = avio_rl32(pb);
00047 }
00048
00049 *len_ptr = len;
00050 return tag;
00051 }
00052
00053
00054 static int swf_probe(AVProbeData *p)
00055 {
00056
00057 if ((p->buf[0] == 'F' || p->buf[0] == 'C') && p->buf[1] == 'W' &&
00058 p->buf[2] == 'S')
00059 return AVPROBE_SCORE_MAX;
00060 else
00061 return 0;
00062 }
00063
00064 #if CONFIG_ZLIB
00065 static int zlib_refill(void *opaque, uint8_t *buf, int buf_size)
00066 {
00067 AVFormatContext *s = opaque;
00068 SWFContext *swf = s->priv_data;
00069 z_stream *z = &swf->zstream;
00070 int ret;
00071
00072 retry:
00073 if (!z->avail_in) {
00074 int n = avio_read(s->pb, swf->zbuf_in, ZBUF_SIZE);
00075 if (n <= 0)
00076 return n;
00077 z->next_in = swf->zbuf_in;
00078 z->avail_in = n;
00079 }
00080
00081 z->next_out = buf;
00082 z->avail_out = buf_size;
00083
00084 ret = inflate(z, Z_NO_FLUSH);
00085 if (ret < 0)
00086 return AVERROR(EINVAL);
00087 if (ret == Z_STREAM_END)
00088 return AVERROR_EOF;
00089
00090 if (buf_size - z->avail_out == 0)
00091 goto retry;
00092
00093 return buf_size - z->avail_out;
00094 }
00095 #endif
00096
00097 static int swf_read_header(AVFormatContext *s)
00098 {
00099 SWFContext *swf = s->priv_data;
00100 AVIOContext *pb = s->pb;
00101 int nbits, len, tag;
00102
00103 tag = avio_rb32(pb) & 0xffffff00;
00104 avio_rl32(pb);
00105
00106 if (tag == MKBETAG('C', 'W', 'S', 0)) {
00107 av_log(s, AV_LOG_INFO, "SWF compressed file detected\n");
00108 #if CONFIG_ZLIB
00109 swf->zbuf_in = av_malloc(ZBUF_SIZE);
00110 swf->zbuf_out = av_malloc(ZBUF_SIZE);
00111 swf->zpb = avio_alloc_context(swf->zbuf_out, ZBUF_SIZE, 0, s,
00112 zlib_refill, NULL, NULL);
00113 if (!swf->zbuf_in || !swf->zbuf_out || !swf->zpb)
00114 return AVERROR(ENOMEM);
00115 swf->zpb->seekable = 0;
00116 if (inflateInit(&swf->zstream) != Z_OK) {
00117 av_log(s, AV_LOG_ERROR, "Unable to init zlib context\n");
00118 return AVERROR(EINVAL);
00119 }
00120 pb = swf->zpb;
00121 #else
00122 av_log(s, AV_LOG_ERROR, "zlib support is required to read SWF compressed files\n");
00123 return AVERROR(EIO);
00124 #endif
00125 } else if (tag != MKBETAG('F', 'W', 'S', 0))
00126 return AVERROR(EIO);
00127
00128 nbits = avio_r8(pb) >> 3;
00129 len = (4 * nbits - 3 + 7) / 8;
00130 avio_skip(pb, len);
00131 swf->frame_rate = avio_rl16(pb);
00132 avio_rl16(pb);
00133
00134 swf->samples_per_frame = 0;
00135 s->ctx_flags |= AVFMTCTX_NOHEADER;
00136 return 0;
00137 }
00138
00139 static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
00140 {
00141 SWFContext *swf = s->priv_data;
00142 AVIOContext *pb = s->pb;
00143 AVStream *vst = NULL, *ast = NULL, *st = 0;
00144 int tag, len, i, frame, v, res;
00145
00146 #if CONFIG_ZLIB
00147 if (swf->zpb)
00148 pb = swf->zpb;
00149 #endif
00150
00151 for(;;) {
00152 uint64_t pos = avio_tell(pb);
00153 tag = get_swf_tag(pb, &len);
00154 if (tag < 0)
00155 return tag;
00156 if (tag == TAG_VIDEOSTREAM) {
00157 int ch_id = avio_rl16(pb);
00158 len -= 2;
00159
00160 for (i=0; i<s->nb_streams; i++) {
00161 st = s->streams[i];
00162 if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && st->id == ch_id)
00163 goto skip;
00164 }
00165
00166 avio_rl16(pb);
00167 avio_rl16(pb);
00168 avio_rl16(pb);
00169 avio_r8(pb);
00170
00171 vst = avformat_new_stream(s, NULL);
00172 if (!vst)
00173 return -1;
00174 vst->id = ch_id;
00175 vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00176 vst->codec->codec_id = ff_codec_get_id(ff_swf_codec_tags, avio_r8(pb));
00177 avpriv_set_pts_info(vst, 16, 256, swf->frame_rate);
00178 len -= 8;
00179 } else if (tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2) {
00180
00181 int sample_rate_code;
00182
00183 for (i=0; i<s->nb_streams; i++) {
00184 st = s->streams[i];
00185 if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && st->id == -1)
00186 goto skip;
00187 }
00188
00189 avio_r8(pb);
00190 v = avio_r8(pb);
00191 swf->samples_per_frame = avio_rl16(pb);
00192 ast = avformat_new_stream(s, NULL);
00193 if (!ast)
00194 return -1;
00195 ast->id = -1;
00196 ast->codec->channels = 1 + (v&1);
00197 ast->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00198 ast->codec->codec_id = ff_codec_get_id(swf_audio_codec_tags, (v>>4) & 15);
00199 ast->need_parsing = AVSTREAM_PARSE_FULL;
00200 sample_rate_code= (v>>2) & 3;
00201 ast->codec->sample_rate = 44100 >> (3 - sample_rate_code);
00202 avpriv_set_pts_info(ast, 64, 1, ast->codec->sample_rate);
00203 len -= 4;
00204 } else if (tag == TAG_VIDEOFRAME) {
00205 int ch_id = avio_rl16(pb);
00206 len -= 2;
00207 for(i=0; i<s->nb_streams; i++) {
00208 st = s->streams[i];
00209 if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && st->id == ch_id) {
00210 frame = avio_rl16(pb);
00211 if ((res = av_get_packet(pb, pkt, len-2)) < 0)
00212 return res;
00213 pkt->pos = pos;
00214 pkt->pts = frame;
00215 pkt->stream_index = st->index;
00216 return pkt->size;
00217 }
00218 }
00219 } else if (tag == TAG_STREAMBLOCK) {
00220 for (i = 0; i < s->nb_streams; i++) {
00221 st = s->streams[i];
00222 if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && st->id == -1) {
00223 if (st->codec->codec_id == AV_CODEC_ID_MP3) {
00224 avio_skip(pb, 4);
00225 if ((res = av_get_packet(pb, pkt, len-4)) < 0)
00226 return res;
00227 } else {
00228 if ((res = av_get_packet(pb, pkt, len)) < 0)
00229 return res;
00230 }
00231 pkt->pos = pos;
00232 pkt->stream_index = st->index;
00233 return pkt->size;
00234 }
00235 }
00236 } else if (tag == TAG_JPEG2) {
00237 for (i=0; i<s->nb_streams; i++) {
00238 st = s->streams[i];
00239 if (st->codec->codec_id == AV_CODEC_ID_MJPEG && st->id == -2)
00240 break;
00241 }
00242 if (i == s->nb_streams) {
00243 vst = avformat_new_stream(s, NULL);
00244 if (!vst)
00245 return -1;
00246 vst->id = -2;
00247 vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00248 vst->codec->codec_id = AV_CODEC_ID_MJPEG;
00249 avpriv_set_pts_info(vst, 64, 256, swf->frame_rate);
00250 st = vst;
00251 }
00252 avio_rl16(pb);
00253 if ((res = av_new_packet(pkt, len-2)) < 0)
00254 return res;
00255 avio_read(pb, pkt->data, 4);
00256 if (AV_RB32(pkt->data) == 0xffd8ffd9 ||
00257 AV_RB32(pkt->data) == 0xffd9ffd8) {
00258
00259
00260 pkt->size -= 4;
00261 avio_read(pb, pkt->data, pkt->size);
00262 } else {
00263 avio_read(pb, pkt->data + 4, pkt->size - 4);
00264 }
00265 pkt->pos = pos;
00266 pkt->stream_index = st->index;
00267 return pkt->size;
00268 }
00269 skip:
00270 avio_skip(pb, len);
00271 }
00272 }
00273
00274 #if CONFIG_ZLIB
00275 static av_cold int swf_read_close(AVFormatContext *avctx)
00276 {
00277 SWFContext *s = avctx->priv_data;
00278 inflateEnd(&s->zstream);
00279 av_freep(&s->zbuf_in);
00280 av_freep(&s->zbuf_out);
00281 av_freep(&s->zpb);
00282 return 0;
00283 }
00284 #endif
00285
00286 AVInputFormat ff_swf_demuxer = {
00287 .name = "swf",
00288 .long_name = NULL_IF_CONFIG_SMALL("SWF (ShockWave Flash)"),
00289 .priv_data_size = sizeof(SWFContext),
00290 .read_probe = swf_probe,
00291 .read_header = swf_read_header,
00292 .read_packet = swf_read_packet,
00293 #if CONFIG_ZLIB
00294 .read_close = swf_read_close,
00295 #endif
00296 };