2 * Flash Compatible Streaming Format demuxer
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
23 #include "libavutil/avassert.h"
24 #include "libavutil/channel_layout.h"
25 #include "libavutil/imgutils.h"
26 #include "libavutil/intreadwrite.h"
29 static const AVCodecTag swf_audio_codec_tags
[] = {
30 { AV_CODEC_ID_PCM_S16LE
, 0x00 },
31 { AV_CODEC_ID_ADPCM_SWF
, 0x01 },
32 { AV_CODEC_ID_MP3
, 0x02 },
33 { AV_CODEC_ID_PCM_S16LE
, 0x03 },
34 // { AV_CODEC_ID_NELLYMOSER, 0x06 },
35 { AV_CODEC_ID_NONE
, 0 },
38 static int get_swf_tag(AVIOContext
*pb
, int *len_ptr
)
56 static int swf_probe(AVProbeData
*p
)
61 /* check file header */
62 if ( AV_RB24(p
->buf
) != AV_RB24("CWS")
63 && AV_RB24(p
->buf
) != AV_RB24("FWS"))
67 return AVPROBE_SCORE_MAX
/ 4;
69 return AVPROBE_SCORE_MAX
;
73 static int zlib_refill(void *opaque
, uint8_t *buf
, int buf_size
)
75 AVFormatContext
*s
= opaque
;
76 SWFContext
*swf
= s
->priv_data
;
77 z_stream
*z
= &swf
->zstream
;
82 int n
= avio_read(s
->pb
, swf
->zbuf_in
, ZBUF_SIZE
);
85 z
->next_in
= swf
->zbuf_in
;
90 z
->avail_out
= buf_size
;
92 ret
= inflate(z
, Z_NO_FLUSH
);
94 return AVERROR(EINVAL
);
95 if (ret
== Z_STREAM_END
)
98 if (buf_size
- z
->avail_out
== 0)
101 return buf_size
- z
->avail_out
;
105 static int swf_read_header(AVFormatContext
*s
)
107 SWFContext
*swf
= s
->priv_data
;
108 AVIOContext
*pb
= s
->pb
;
111 tag
= avio_rb32(pb
) & 0xffffff00;
114 if (tag
== MKBETAG('C', 'W', 'S', 0)) {
115 av_log(s
, AV_LOG_INFO
, "SWF compressed file detected\n");
117 swf
->zbuf_in
= av_malloc(ZBUF_SIZE
);
118 swf
->zbuf_out
= av_malloc(ZBUF_SIZE
);
119 swf
->zpb
= avio_alloc_context(swf
->zbuf_out
, ZBUF_SIZE
, 0, s
,
120 zlib_refill
, NULL
, NULL
);
121 if (!swf
->zbuf_in
|| !swf
->zbuf_out
|| !swf
->zpb
)
122 return AVERROR(ENOMEM
);
123 swf
->zpb
->seekable
= 0;
124 if (inflateInit(&swf
->zstream
) != Z_OK
) {
125 av_log(s
, AV_LOG_ERROR
, "Unable to init zlib context\n");
126 return AVERROR(EINVAL
);
130 av_log(s
, AV_LOG_ERROR
, "zlib support is required to read SWF compressed files\n");
133 } else if (tag
!= MKBETAG('F', 'W', 'S', 0))
135 /* skip rectangle size */
136 nbits
= avio_r8(pb
) >> 3;
137 len
= (4 * nbits
- 3 + 7) / 8;
139 swf
->frame_rate
= avio_rl16(pb
); /* 8.8 fixed */
140 avio_rl16(pb
); /* frame count */
142 swf
->samples_per_frame
= 0;
143 s
->ctx_flags
|= AVFMTCTX_NOHEADER
;
147 static AVStream
*create_new_audio_stream(AVFormatContext
*s
, int id
, int info
)
149 int sample_rate_code
, sample_size_code
;
150 AVStream
*ast
= avformat_new_stream(s
, NULL
);
155 ast
->codec
->channels
= 2;
156 ast
->codec
->channel_layout
= AV_CH_LAYOUT_STEREO
;
158 ast
->codec
->channels
= 1;
159 ast
->codec
->channel_layout
= AV_CH_LAYOUT_MONO
;
161 ast
->codec
->codec_type
= AVMEDIA_TYPE_AUDIO
;
162 ast
->codec
->codec_id
= ff_codec_get_id(swf_audio_codec_tags
, info
>>4 & 15);
163 ast
->need_parsing
= AVSTREAM_PARSE_FULL
;
164 sample_rate_code
= info
>>2 & 3;
165 sample_size_code
= info
>>1 & 1;
166 if (!sample_size_code
&& ast
->codec
->codec_id
== AV_CODEC_ID_PCM_S16LE
)
167 ast
->codec
->codec_id
= AV_CODEC_ID_PCM_U8
;
168 ast
->codec
->sample_rate
= 44100 >> (3 - sample_rate_code
);
169 avpriv_set_pts_info(ast
, 64, 1, ast
->codec
->sample_rate
);
173 static int swf_read_packet(AVFormatContext
*s
, AVPacket
*pkt
)
175 SWFContext
*swf
= s
->priv_data
;
176 AVIOContext
*pb
= s
->pb
;
177 AVStream
*vst
= NULL
, *ast
= NULL
, *st
= 0;
178 int tag
, len
, i
, frame
, v
, res
;
186 uint64_t pos
= avio_tell(pb
);
187 tag
= get_swf_tag(pb
, &len
);
191 av_log(s
, AV_LOG_ERROR
, "invalid tag length: %d\n", len
);
192 return AVERROR_INVALIDDATA
;
194 if (tag
== TAG_VIDEOSTREAM
) {
195 int ch_id
= avio_rl16(pb
);
198 for (i
=0; i
<s
->nb_streams
; i
++) {
200 if (st
->codec
->codec_type
== AVMEDIA_TYPE_VIDEO
&& st
->id
== ch_id
)
209 vst
= avformat_new_stream(s
, NULL
);
211 return AVERROR(ENOMEM
);
213 vst
->codec
->codec_type
= AVMEDIA_TYPE_VIDEO
;
214 vst
->codec
->codec_id
= ff_codec_get_id(ff_swf_codec_tags
, avio_r8(pb
));
215 avpriv_set_pts_info(vst
, 16, 256, swf
->frame_rate
);
217 } else if (tag
== TAG_STREAMHEAD
|| tag
== TAG_STREAMHEAD2
) {
218 /* streaming found */
220 for (i
=0; i
<s
->nb_streams
; i
++) {
222 if (st
->codec
->codec_type
== AVMEDIA_TYPE_AUDIO
&& st
->id
== -1)
228 swf
->samples_per_frame
= avio_rl16(pb
);
229 ast
= create_new_audio_stream(s
, -1, v
); /* -1 to avoid clash with video stream ch_id */
231 return AVERROR(ENOMEM
);
233 } else if (tag
== TAG_DEFINESOUND
) {
235 int ch_id
= avio_rl16(pb
);
237 for (i
=0; i
<s
->nb_streams
; i
++) {
239 if (st
->codec
->codec_type
== AVMEDIA_TYPE_AUDIO
&& st
->id
== ch_id
)
243 // FIXME: The entire audio stream is stored in a single chunk/tag. Normally,
244 // these are smaller audio streams in DEFINESOUND tags, but it's technically
245 // possible they could be huge. Break it up into multiple packets if it's big.
247 ast
= create_new_audio_stream(s
, ch_id
, v
);
249 return AVERROR(ENOMEM
);
250 ast
->duration
= avio_rl32(pb
); // number of samples
251 if (((v
>>4) & 15) == 2) { // MP3 sound data record
252 ast
->skip_samples
= avio_rl16(pb
);
256 if ((res
= av_get_packet(pb
, pkt
, len
)) < 0)
259 pkt
->stream_index
= ast
->index
;
261 } else if (tag
== TAG_VIDEOFRAME
) {
262 int ch_id
= avio_rl16(pb
);
264 for(i
=0; i
<s
->nb_streams
; i
++) {
266 if (st
->codec
->codec_type
== AVMEDIA_TYPE_VIDEO
&& st
->id
== ch_id
) {
267 frame
= avio_rl16(pb
);
271 if ((res
= av_get_packet(pb
, pkt
, len
)) < 0)
275 pkt
->stream_index
= st
->index
;
279 } else if (tag
== TAG_DEFINEBITSLOSSLESS
|| tag
== TAG_DEFINEBITSLOSSLESS2
) {
282 uint8_t *buf
= NULL
, *zbuf
= NULL
, *pal
;
283 uint32_t colormap
[AVPALETTE_COUNT
] = {0};
284 const int alpha_bmp
= tag
== TAG_DEFINEBITSLOSSLESS2
;
285 const int colormapbpp
= 3 + alpha_bmp
;
286 int linesize
, colormapsize
= 0;
288 const int ch_id
= avio_rl16(pb
);
289 const int bmp_fmt
= avio_r8(pb
);
290 const int width
= avio_rl16(pb
);
291 const int height
= avio_rl16(pb
);
299 colormapsize
= avio_r8(pb
) + 1;
303 linesize
= width
* 2;
305 case 5: // RGB24 (0RGB)
306 linesize
= width
* 4;
309 av_log(s
, AV_LOG_ERROR
, "invalid bitmap format %d, skipped\n", bmp_fmt
);
310 goto bitmap_end_skip
;
313 linesize
= FFALIGN(linesize
, 4);
315 if (av_image_check_size(width
, height
, 0, s
) < 0 ||
316 linesize
>= INT_MAX
/ height
||
317 linesize
* height
>= INT_MAX
- colormapsize
* colormapbpp
) {
318 av_log(s
, AV_LOG_ERROR
, "invalid frame size %dx%d\n", width
, height
);
319 goto bitmap_end_skip
;
322 out_len
= colormapsize
* colormapbpp
+ linesize
* height
;
324 av_dlog(s
, "bitmap: ch=%d fmt=%d %dx%d (linesize=%d) len=%d->%ld pal=%d\n",
325 ch_id
, bmp_fmt
, width
, height
, linesize
, len
, out_len
, colormapsize
);
327 zbuf
= av_malloc(len
);
328 buf
= av_malloc(out_len
);
330 res
= AVERROR(ENOMEM
);
334 len
= avio_read(pb
, zbuf
, len
);
335 if (len
< 0 || (res
= uncompress(buf
, &out_len
, zbuf
, len
)) != Z_OK
) {
336 av_log(s
, AV_LOG_WARNING
, "Failed to uncompress one bitmap\n");
337 goto bitmap_end_skip
;
340 for (i
= 0; i
< s
->nb_streams
; i
++) {
342 if (st
->codec
->codec_id
== AV_CODEC_ID_RAWVIDEO
&& st
->id
== -3)
345 if (i
== s
->nb_streams
) {
346 vst
= avformat_new_stream(s
, NULL
);
348 res
= AVERROR(ENOMEM
);
351 vst
->id
= -3; /* -3 to avoid clash with video stream and audio stream */
352 vst
->codec
->codec_type
= AVMEDIA_TYPE_VIDEO
;
353 vst
->codec
->codec_id
= AV_CODEC_ID_RAWVIDEO
;
354 avpriv_set_pts_info(vst
, 64, 256, swf
->frame_rate
);
358 if ((res
= av_new_packet(pkt
, out_len
- colormapsize
* colormapbpp
)) < 0)
360 if (!st
->codec
->width
&& !st
->codec
->height
) {
361 st
->codec
->width
= width
;
362 st
->codec
->height
= height
;
364 ff_add_param_change(pkt
, 0, 0, 0, width
, height
);
367 pkt
->stream_index
= st
->index
;
371 pix_fmt
= AV_PIX_FMT_PAL8
;
372 for (i
= 0; i
< colormapsize
; i
++)
373 if (alpha_bmp
) colormap
[i
] = buf
[3]<<24 | AV_RB24(buf
+ 4*i
);
374 else colormap
[i
] = 0xffU
<<24 | AV_RB24(buf
+ 3*i
);
375 pal
= av_packet_new_side_data(pkt
, AV_PKT_DATA_PALETTE
, AVPALETTE_SIZE
);
377 res
= AVERROR(ENOMEM
);
380 memcpy(pal
, colormap
, AVPALETTE_SIZE
);
383 pix_fmt
= AV_PIX_FMT_RGB555
;
386 pix_fmt
= alpha_bmp
? AV_PIX_FMT_ARGB
: AV_PIX_FMT_0RGB
;
391 if (st
->codec
->pix_fmt
!= AV_PIX_FMT_NONE
&& st
->codec
->pix_fmt
!= pix_fmt
) {
392 av_log(s
, AV_LOG_ERROR
, "pixel format change unsupported\n");
393 res
= AVERROR_PATCHWELCOME
;
396 st
->codec
->pix_fmt
= pix_fmt
;
398 if (linesize
* height
> pkt
->size
) {
399 res
= AVERROR_INVALIDDATA
;
402 memcpy(pkt
->data
, buf
+ colormapsize
*colormapbpp
, linesize
* height
);
414 av_log(s
, AV_LOG_ERROR
, "this file requires zlib support compiled in\n");
416 } else if (tag
== TAG_STREAMBLOCK
) {
417 for (i
= 0; i
< s
->nb_streams
; i
++) {
419 if (st
->codec
->codec_type
== AVMEDIA_TYPE_AUDIO
&& st
->id
== -1) {
420 if (st
->codec
->codec_id
== AV_CODEC_ID_MP3
) {
425 if ((res
= av_get_packet(pb
, pkt
, len
)) < 0)
427 } else { // ADPCM, PCM
430 if ((res
= av_get_packet(pb
, pkt
, len
)) < 0)
434 pkt
->stream_index
= st
->index
;
438 } else if (tag
== TAG_JPEG2
) {
439 for (i
=0; i
<s
->nb_streams
; i
++) {
441 if (st
->codec
->codec_id
== AV_CODEC_ID_MJPEG
&& st
->id
== -2)
444 if (i
== s
->nb_streams
) {
445 vst
= avformat_new_stream(s
, NULL
);
447 return AVERROR(ENOMEM
);
448 vst
->id
= -2; /* -2 to avoid clash with video stream and audio stream */
449 vst
->codec
->codec_type
= AVMEDIA_TYPE_VIDEO
;
450 vst
->codec
->codec_id
= AV_CODEC_ID_MJPEG
;
451 avpriv_set_pts_info(vst
, 64, 256, swf
->frame_rate
);
454 avio_rl16(pb
); /* BITMAP_ID */
458 if ((res
= av_new_packet(pkt
, len
)) < 0)
460 if (avio_read(pb
, pkt
->data
, 4) != 4) {
462 return AVERROR_INVALIDDATA
;
464 if (AV_RB32(pkt
->data
) == 0xffd8ffd9 ||
465 AV_RB32(pkt
->data
) == 0xffd9ffd8) {
466 /* old SWF files containing SOI/EOI as data start */
467 /* files created by swink have reversed tag */
469 memset(pkt
->data
+pkt
->size
, 0, 4);
470 res
= avio_read(pb
, pkt
->data
, pkt
->size
);
472 res
= avio_read(pb
, pkt
->data
+ 4, pkt
->size
- 4);
476 if (res
!= pkt
->size
) {
481 av_shrink_packet(pkt
, res
);
485 pkt
->stream_index
= st
->index
;
488 av_log(s
, AV_LOG_DEBUG
, "Unknown tag: %d\n", tag
);
492 av_log(s
, AV_LOG_WARNING
, "Cliping len %d\n", len
);
499 static av_cold
int swf_read_close(AVFormatContext
*avctx
)
501 SWFContext
*s
= avctx
->priv_data
;
502 inflateEnd(&s
->zstream
);
503 av_freep(&s
->zbuf_in
);
504 av_freep(&s
->zbuf_out
);
510 AVInputFormat ff_swf_demuxer
= {
512 .long_name
= NULL_IF_CONFIG_SMALL("SWF (ShockWave Flash)"),
513 .priv_data_size
= sizeof(SWFContext
),
514 .read_probe
= swf_probe
,
515 .read_header
= swf_read_header
,
516 .read_packet
= swf_read_packet
,
518 .read_close
= swf_read_close
,