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/avassert.h"
00024 #include "libavutil/channel_layout.h"
00025 #include "libavutil/imgutils.h"
00026 #include "libavutil/intreadwrite.h"
00027 #include "swf.h"
00028
00029 static const AVCodecTag swf_audio_codec_tags[] = {
00030 { AV_CODEC_ID_PCM_S16LE, 0x00 },
00031 { AV_CODEC_ID_ADPCM_SWF, 0x01 },
00032 { AV_CODEC_ID_MP3, 0x02 },
00033 { AV_CODEC_ID_PCM_S16LE, 0x03 },
00034
00035 { AV_CODEC_ID_NONE, 0 },
00036 };
00037
00038 static int get_swf_tag(AVIOContext *pb, int *len_ptr)
00039 {
00040 int tag, len;
00041
00042 if (url_feof(pb))
00043 return AVERROR_EOF;
00044
00045 tag = avio_rl16(pb);
00046 len = tag & 0x3f;
00047 tag = tag >> 6;
00048 if (len == 0x3f) {
00049 len = avio_rl32(pb);
00050 }
00051 *len_ptr = len;
00052 return tag;
00053 }
00054
00055
00056 static int swf_probe(AVProbeData *p)
00057 {
00058
00059 if ((p->buf[0] == 'F' || p->buf[0] == 'C') && p->buf[1] == 'W' &&
00060 p->buf[2] == 'S')
00061 return AVPROBE_SCORE_MAX;
00062 else
00063 return 0;
00064 }
00065
00066 #if CONFIG_ZLIB
00067 static int zlib_refill(void *opaque, uint8_t *buf, int buf_size)
00068 {
00069 AVFormatContext *s = opaque;
00070 SWFContext *swf = s->priv_data;
00071 z_stream *z = &swf->zstream;
00072 int ret;
00073
00074 retry:
00075 if (!z->avail_in) {
00076 int n = avio_read(s->pb, swf->zbuf_in, ZBUF_SIZE);
00077 if (n < 0)
00078 return n;
00079 z->next_in = swf->zbuf_in;
00080 z->avail_in = n;
00081 }
00082
00083 z->next_out = buf;
00084 z->avail_out = buf_size;
00085
00086 ret = inflate(z, Z_NO_FLUSH);
00087 if (ret < 0)
00088 return AVERROR(EINVAL);
00089 if (ret == Z_STREAM_END)
00090 return AVERROR_EOF;
00091
00092 if (buf_size - z->avail_out == 0)
00093 goto retry;
00094
00095 return buf_size - z->avail_out;
00096 }
00097 #endif
00098
00099 static int swf_read_header(AVFormatContext *s)
00100 {
00101 SWFContext *swf = s->priv_data;
00102 AVIOContext *pb = s->pb;
00103 int nbits, len, tag;
00104
00105 tag = avio_rb32(pb) & 0xffffff00;
00106 avio_rl32(pb);
00107
00108 if (tag == MKBETAG('C', 'W', 'S', 0)) {
00109 av_log(s, AV_LOG_INFO, "SWF compressed file detected\n");
00110 #if CONFIG_ZLIB
00111 swf->zbuf_in = av_malloc(ZBUF_SIZE);
00112 swf->zbuf_out = av_malloc(ZBUF_SIZE);
00113 swf->zpb = avio_alloc_context(swf->zbuf_out, ZBUF_SIZE, 0, s,
00114 zlib_refill, NULL, NULL);
00115 if (!swf->zbuf_in || !swf->zbuf_out || !swf->zpb)
00116 return AVERROR(ENOMEM);
00117 swf->zpb->seekable = 0;
00118 if (inflateInit(&swf->zstream) != Z_OK) {
00119 av_log(s, AV_LOG_ERROR, "Unable to init zlib context\n");
00120 return AVERROR(EINVAL);
00121 }
00122 pb = swf->zpb;
00123 #else
00124 av_log(s, AV_LOG_ERROR, "zlib support is required to read SWF compressed files\n");
00125 return AVERROR(EIO);
00126 #endif
00127 } else if (tag != MKBETAG('F', 'W', 'S', 0))
00128 return AVERROR(EIO);
00129
00130 nbits = avio_r8(pb) >> 3;
00131 len = (4 * nbits - 3 + 7) / 8;
00132 avio_skip(pb, len);
00133 swf->frame_rate = avio_rl16(pb);
00134 avio_rl16(pb);
00135
00136 swf->samples_per_frame = 0;
00137 s->ctx_flags |= AVFMTCTX_NOHEADER;
00138 return 0;
00139 }
00140
00141 static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
00142 {
00143 SWFContext *swf = s->priv_data;
00144 AVIOContext *pb = s->pb;
00145 AVStream *vst = NULL, *ast = NULL, *st = 0;
00146 int tag, len, i, frame, v, res;
00147
00148 #if CONFIG_ZLIB
00149 if (swf->zpb)
00150 pb = swf->zpb;
00151 #endif
00152
00153 for(;;) {
00154 uint64_t pos = avio_tell(pb);
00155 tag = get_swf_tag(pb, &len);
00156 if (tag < 0)
00157 return tag;
00158 if (len < 0) {
00159 av_log(s, AV_LOG_ERROR, "invalid tag length: %d\n", len);
00160 return AVERROR_INVALIDDATA;
00161 }
00162 if (tag == TAG_VIDEOSTREAM) {
00163 int ch_id = avio_rl16(pb);
00164 len -= 2;
00165
00166 for (i=0; i<s->nb_streams; i++) {
00167 st = s->streams[i];
00168 if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && st->id == ch_id)
00169 goto skip;
00170 }
00171
00172 avio_rl16(pb);
00173 avio_rl16(pb);
00174 avio_rl16(pb);
00175 avio_r8(pb);
00176
00177 vst = avformat_new_stream(s, NULL);
00178 if (!vst)
00179 return AVERROR(ENOMEM);
00180 vst->id = ch_id;
00181 vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00182 vst->codec->codec_id = ff_codec_get_id(ff_swf_codec_tags, avio_r8(pb));
00183 avpriv_set_pts_info(vst, 16, 256, swf->frame_rate);
00184 len -= 8;
00185 } else if (tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2) {
00186
00187 int sample_rate_code;
00188
00189 for (i=0; i<s->nb_streams; i++) {
00190 st = s->streams[i];
00191 if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && st->id == -1)
00192 goto skip;
00193 }
00194
00195 avio_r8(pb);
00196 v = avio_r8(pb);
00197 swf->samples_per_frame = avio_rl16(pb);
00198 ast = avformat_new_stream(s, NULL);
00199 if (!ast)
00200 return AVERROR(ENOMEM);
00201 ast->id = -1;
00202 if (v & 1) {
00203 ast->codec->channels = 2;
00204 ast->codec->channel_layout = AV_CH_LAYOUT_STEREO;
00205 } else {
00206 ast->codec->channels = 1;
00207 ast->codec->channel_layout = AV_CH_LAYOUT_MONO;
00208 }
00209 ast->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00210 ast->codec->codec_id = ff_codec_get_id(swf_audio_codec_tags, (v>>4) & 15);
00211 ast->need_parsing = AVSTREAM_PARSE_FULL;
00212 sample_rate_code= (v>>2) & 3;
00213 ast->codec->sample_rate = 44100 >> (3 - sample_rate_code);
00214 avpriv_set_pts_info(ast, 64, 1, ast->codec->sample_rate);
00215 len -= 4;
00216 } else if (tag == TAG_DEFINESOUND) {
00217
00218 int sample_rate_code;
00219 int ch_id = avio_rl16(pb);
00220
00221 for (i=0; i<s->nb_streams; i++) {
00222 st = s->streams[i];
00223 if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && st->id == ch_id)
00224 goto skip;
00225 }
00226
00227
00228
00229
00230
00231 v = avio_r8(pb);
00232 ast = avformat_new_stream(s, NULL);
00233 if (!ast)
00234 return AVERROR(ENOMEM);
00235 ast->id = ch_id;
00236 ast->codec->channels = 1 + (v&1);
00237 ast->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00238 ast->codec->codec_id = ff_codec_get_id(swf_audio_codec_tags, (v>>4) & 15);
00239 ast->need_parsing = AVSTREAM_PARSE_FULL;
00240 sample_rate_code= (v>>2) & 3;
00241 ast->codec->sample_rate = 44100 >> (3 - sample_rate_code);
00242 avpriv_set_pts_info(ast, 64, 1, ast->codec->sample_rate);
00243 ast->duration = avio_rl32(pb);
00244 if (((v>>4) & 15) == 2) {
00245 ast->skip_samples = avio_rl16(pb);
00246 len -= 2;
00247 }
00248 len -= 7;
00249 if ((res = av_get_packet(pb, pkt, len)) < 0)
00250 return res;
00251 pkt->pos = pos;
00252 pkt->stream_index = ast->index;
00253 return pkt->size;
00254 } else if (tag == TAG_VIDEOFRAME) {
00255 int ch_id = avio_rl16(pb);
00256 len -= 2;
00257 for(i=0; i<s->nb_streams; i++) {
00258 st = s->streams[i];
00259 if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && st->id == ch_id) {
00260 frame = avio_rl16(pb);
00261 len -= 2;
00262 if (len <= 0)
00263 goto skip;
00264 if ((res = av_get_packet(pb, pkt, len)) < 0)
00265 return res;
00266 pkt->pos = pos;
00267 pkt->pts = frame;
00268 pkt->stream_index = st->index;
00269 return pkt->size;
00270 }
00271 }
00272 } else if (tag == TAG_DEFINEBITSLOSSLESS || tag == TAG_DEFINEBITSLOSSLESS2) {
00273 #if CONFIG_ZLIB
00274 long out_len;
00275 uint8_t *buf = NULL, *zbuf = NULL, *pal;
00276 uint32_t colormap[AVPALETTE_COUNT] = {0};
00277 const int alpha_bmp = tag == TAG_DEFINEBITSLOSSLESS2;
00278 const int colormapbpp = 3 + alpha_bmp;
00279 int linesize, colormapsize = 0;
00280
00281 const int ch_id = avio_rl16(pb);
00282 const int bmp_fmt = avio_r8(pb);
00283 const int width = avio_rl16(pb);
00284 const int height = avio_rl16(pb);
00285
00286 len -= 2+1+2+2;
00287
00288 switch (bmp_fmt) {
00289 case 3:
00290 linesize = width;
00291 colormapsize = avio_r8(pb) + 1;
00292 len--;
00293 break;
00294 case 4:
00295 linesize = width * 2;
00296 break;
00297 case 5:
00298 linesize = width * 4;
00299 break;
00300 default:
00301 av_log(s, AV_LOG_ERROR, "invalid bitmap format %d, skipped\n", bmp_fmt);
00302 goto bitmap_end_skip;
00303 }
00304
00305 linesize = FFALIGN(linesize, 4);
00306
00307 if (av_image_check_size(width, height, 0, s) < 0 ||
00308 linesize >= INT_MAX / height ||
00309 linesize * height >= INT_MAX - colormapsize * colormapbpp) {
00310 av_log(s, AV_LOG_ERROR, "invalid frame size %dx%d\n", width, height);
00311 goto bitmap_end_skip;
00312 }
00313
00314 out_len = colormapsize * colormapbpp + linesize * height;
00315
00316 av_dlog(s, "bitmap: ch=%d fmt=%d %dx%d (linesize=%d) len=%d->%ld pal=%d\n",
00317 ch_id, bmp_fmt, width, height, linesize, len, out_len, colormapsize);
00318
00319 zbuf = av_malloc(len);
00320 buf = av_malloc(out_len);
00321 if (!zbuf || !buf) {
00322 res = AVERROR(ENOMEM);
00323 goto bitmap_end;
00324 }
00325
00326 len = avio_read(pb, zbuf, len);
00327 if (len < 0 || (res = uncompress(buf, &out_len, zbuf, len)) != Z_OK) {
00328 av_log(s, AV_LOG_WARNING, "Failed to uncompress one bitmap\n");
00329 goto bitmap_end_skip;
00330 }
00331
00332 for (i = 0; i < s->nb_streams; i++) {
00333 st = s->streams[i];
00334 if (st->codec->codec_id == AV_CODEC_ID_RAWVIDEO && st->id == -3)
00335 break;
00336 }
00337 if (i == s->nb_streams) {
00338 vst = avformat_new_stream(s, NULL);
00339 if (!vst) {
00340 res = AVERROR(ENOMEM);
00341 goto bitmap_end;
00342 }
00343 vst->id = -3;
00344 vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00345 vst->codec->codec_id = AV_CODEC_ID_RAWVIDEO;
00346 avpriv_set_pts_info(vst, 64, 256, swf->frame_rate);
00347 st = vst;
00348 }
00349 st->codec->width = width;
00350 st->codec->height = height;
00351
00352 if ((res = av_new_packet(pkt, out_len - colormapsize * colormapbpp)) < 0)
00353 goto bitmap_end;
00354 pkt->pos = pos;
00355 pkt->stream_index = st->index;
00356
00357 switch (bmp_fmt) {
00358 case 3:
00359 st->codec->pix_fmt = AV_PIX_FMT_PAL8;
00360 for (i = 0; i < colormapsize; i++)
00361 if (alpha_bmp) colormap[i] = buf[3]<<24 | AV_RB24(buf + 4*i);
00362 else colormap[i] = 0xffU <<24 | AV_RB24(buf + 3*i);
00363 pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
00364 if (!pal) {
00365 res = AVERROR(ENOMEM);
00366 goto bitmap_end;
00367 }
00368 memcpy(pal, colormap, AVPALETTE_SIZE);
00369 break;
00370 case 4:
00371 st->codec->pix_fmt = AV_PIX_FMT_RGB555;
00372 break;
00373 case 5:
00374 st->codec->pix_fmt = alpha_bmp ? AV_PIX_FMT_ARGB : AV_PIX_FMT_0RGB;
00375 break;
00376 default:
00377 av_assert0(0);
00378 }
00379
00380 if (linesize * height > pkt->size) {
00381 res = AVERROR_INVALIDDATA;
00382 goto bitmap_end;
00383 }
00384 memcpy(pkt->data, buf + colormapsize*colormapbpp, linesize * height);
00385
00386 res = pkt->size;
00387
00388 bitmap_end:
00389 av_freep(&zbuf);
00390 av_freep(&buf);
00391 return res;
00392 bitmap_end_skip:
00393 av_freep(&zbuf);
00394 av_freep(&buf);
00395 #else
00396 av_log(s, AV_LOG_ERROR, "this file requires zlib support compiled in\n");
00397 #endif
00398 } else if (tag == TAG_STREAMBLOCK) {
00399 for (i = 0; i < s->nb_streams; i++) {
00400 st = s->streams[i];
00401 if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && st->id == -1) {
00402 if (st->codec->codec_id == AV_CODEC_ID_MP3) {
00403 avio_skip(pb, 4);
00404 len -= 4;
00405 if (len <= 0)
00406 goto skip;
00407 if ((res = av_get_packet(pb, pkt, len)) < 0)
00408 return res;
00409 } else {
00410 if (len <= 0)
00411 goto skip;
00412 if ((res = av_get_packet(pb, pkt, len)) < 0)
00413 return res;
00414 }
00415 pkt->pos = pos;
00416 pkt->stream_index = st->index;
00417 return pkt->size;
00418 }
00419 }
00420 } else if (tag == TAG_JPEG2) {
00421 for (i=0; i<s->nb_streams; i++) {
00422 st = s->streams[i];
00423 if (st->codec->codec_id == AV_CODEC_ID_MJPEG && st->id == -2)
00424 break;
00425 }
00426 if (i == s->nb_streams) {
00427 vst = avformat_new_stream(s, NULL);
00428 if (!vst)
00429 return AVERROR(ENOMEM);
00430 vst->id = -2;
00431 vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00432 vst->codec->codec_id = AV_CODEC_ID_MJPEG;
00433 avpriv_set_pts_info(vst, 64, 256, swf->frame_rate);
00434 st = vst;
00435 }
00436 avio_rl16(pb);
00437 len -= 2;
00438 if (len < 4)
00439 goto skip;
00440 if ((res = av_new_packet(pkt, len)) < 0)
00441 return res;
00442 avio_read(pb, pkt->data, 4);
00443 if (AV_RB32(pkt->data) == 0xffd8ffd9 ||
00444 AV_RB32(pkt->data) == 0xffd9ffd8) {
00445
00446
00447 pkt->size -= 4;
00448 avio_read(pb, pkt->data, pkt->size);
00449 } else {
00450 avio_read(pb, pkt->data + 4, pkt->size - 4);
00451 }
00452 pkt->pos = pos;
00453 pkt->stream_index = st->index;
00454 return pkt->size;
00455 } else {
00456 av_log(s, AV_LOG_DEBUG, "Unknown tag: %d\n", tag);
00457 }
00458 skip:
00459 if(len<0)
00460 av_log(s, AV_LOG_WARNING, "Cliping len %d\n", len);
00461 len = FFMAX(0, len);
00462 avio_skip(pb, len);
00463 }
00464 }
00465
00466 #if CONFIG_ZLIB
00467 static av_cold int swf_read_close(AVFormatContext *avctx)
00468 {
00469 SWFContext *s = avctx->priv_data;
00470 inflateEnd(&s->zstream);
00471 av_freep(&s->zbuf_in);
00472 av_freep(&s->zbuf_out);
00473 av_freep(&s->zpb);
00474 return 0;
00475 }
00476 #endif
00477
00478 AVInputFormat ff_swf_demuxer = {
00479 .name = "swf",
00480 .long_name = NULL_IF_CONFIG_SMALL("SWF (ShockWave Flash)"),
00481 .priv_data_size = sizeof(SWFContext),
00482 .read_probe = swf_probe,
00483 .read_header = swf_read_header,
00484 .read_packet = swf_read_packet,
00485 #if CONFIG_ZLIB
00486 .read_close = swf_read_close,
00487 #endif
00488 };