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
29 #include "libavutil/avassert.h"
30 #include "libavutil/channel_layout.h"
31 #include "libavutil/imgutils.h"
32 #include "libavutil/internal.h"
33 #include "libavutil/intreadwrite.h"
34 #include "libavutil/mem.h"
35 #include "libavcodec/get_bits.h"
40 typedef struct SWFDecContext
{
41 int samples_per_frame
;
44 #define ZBUF_SIZE 4096
52 static const AVCodecTag swf_audio_codec_tags
[] = {
53 { AV_CODEC_ID_PCM_S16LE
, 0x00 },
54 { AV_CODEC_ID_ADPCM_SWF
, 0x01 },
55 { AV_CODEC_ID_MP3
, 0x02 },
56 { AV_CODEC_ID_PCM_S16LE
, 0x03 },
57 { AV_CODEC_ID_NELLYMOSER
, 0x06 },
58 { AV_CODEC_ID_NONE
, 0 },
61 static int get_swf_tag(AVIOContext
*pb
, int *len_ptr
)
79 static int swf_probe(const AVProbeData
*p
)
82 int len
, xmin
, xmax
, ymin
, ymax
;
87 /* check file header */
88 if ( AV_RB24(p
->buf
) != AV_RB24("CWS")
89 && AV_RB24(p
->buf
) != AV_RB24("FWS"))
92 if ( AV_RB24(p
->buf
) == AV_RB24("CWS")
94 return AVPROBE_SCORE_MAX
/ 4 + 1;
96 if (init_get_bits8(&gb
, p
->buf
+ 8, p
->buf_size
- 8) < 0)
99 len
= get_bits(&gb
, 5);
102 xmin
= get_bits_long(&gb
, len
);
103 xmax
= get_bits_long(&gb
, len
);
104 ymin
= get_bits_long(&gb
, len
);
105 ymax
= get_bits_long(&gb
, len
);
106 if (xmin
|| ymin
|| !xmax
|| !ymax
)
109 if (p
->buf
[3] >= 20 || xmax
< 16 || ymax
< 16)
110 return AVPROBE_SCORE_MAX
/ 4;
112 return AVPROBE_SCORE_EXTENSION
+ 1;
116 static int zlib_refill(void *opaque
, uint8_t *buf
, int buf_size
)
118 AVFormatContext
*s
= opaque
;
119 SWFDecContext
*swf
= s
->priv_data
;
120 z_stream
*z
= &swf
->zstream
;
125 int n
= avio_read(s
->pb
, swf
->zbuf_in
, ZBUF_SIZE
);
128 z
->next_in
= swf
->zbuf_in
;
133 z
->avail_out
= buf_size
;
135 ret
= inflate(z
, Z_NO_FLUSH
);
136 if (ret
== Z_STREAM_END
)
139 return AVERROR(EINVAL
);
141 if (buf_size
- z
->avail_out
== 0)
144 return buf_size
- z
->avail_out
;
147 static av_cold
int swf_read_close(AVFormatContext
*avctx
);
150 static int swf_read_header(AVFormatContext
*s
)
152 SWFDecContext
*swf
= s
->priv_data
;
153 AVIOContext
*pb
= s
->pb
;
156 tag
= avio_rb32(pb
) & 0xffffff00;
159 if (tag
== MKBETAG('C', 'W', 'S', 0)) {
160 av_log(s
, AV_LOG_INFO
, "SWF compressed file detected\n");
162 if (inflateInit(&swf
->zstream
) != Z_OK
) {
163 av_log(s
, AV_LOG_ERROR
, "Unable to init zlib context\n");
164 return AVERROR(EINVAL
);
166 if (!(swf
->zbuf_in
= av_malloc(ZBUF_SIZE
)) ||
167 !(swf
->zbuf_out
= av_malloc(ZBUF_SIZE
)) ||
168 !(swf
->zpb
= avio_alloc_context(swf
->zbuf_out
, ZBUF_SIZE
, 0,
169 s
, zlib_refill
, NULL
, NULL
))) {
171 return AVERROR(ENOMEM
);
173 swf
->zpb
->seekable
= 0;
176 av_log(s
, AV_LOG_ERROR
, "zlib support is required to read SWF compressed files\n");
177 return AVERROR(ENOSYS
);
179 } else if (tag
!= MKBETAG('F', 'W', 'S', 0))
180 return AVERROR_INVALIDDATA
;
181 /* skip rectangle size */
182 nbits
= avio_r8(pb
) >> 3;
183 len
= (4 * nbits
- 3 + 7) / 8;
185 swf
->frame_rate
= avio_rl16(pb
); /* 8.8 fixed */
186 avio_rl16(pb
); /* frame count */
188 swf
->samples_per_frame
= 0;
189 s
->ctx_flags
|= AVFMTCTX_NOHEADER
;
193 static AVStream
*create_new_audio_stream(AVFormatContext
*s
, int id
, int info
)
195 int sample_rate_code
, sample_size_code
;
196 AVStream
*ast
= avformat_new_stream(s
, NULL
);
200 av_channel_layout_default(&ast
->codecpar
->ch_layout
, 1 + (info
& 1));
201 ast
->codecpar
->codec_type
= AVMEDIA_TYPE_AUDIO
;
202 ast
->codecpar
->codec_id
= ff_codec_get_id(swf_audio_codec_tags
, info
>>4 & 15);
203 ffstream(ast
)->need_parsing
= AVSTREAM_PARSE_FULL
;
204 sample_rate_code
= info
>>2 & 3;
205 sample_size_code
= info
>>1 & 1;
206 if (!sample_size_code
&& ast
->codecpar
->codec_id
== AV_CODEC_ID_PCM_S16LE
)
207 ast
->codecpar
->codec_id
= AV_CODEC_ID_PCM_U8
;
208 ast
->codecpar
->sample_rate
= 44100 >> (3 - sample_rate_code
);
209 avpriv_set_pts_info(ast
, 64, 1, ast
->codecpar
->sample_rate
);
213 static int swf_read_packet(AVFormatContext
*s
, AVPacket
*pkt
)
215 SWFDecContext
*swf
= s
->priv_data
;
216 AVIOContext
*pb
= s
->pb
;
217 AVStream
*vst
= NULL
, *ast
= NULL
, *st
= 0;
218 int tag
, len
, i
, frame
, v
, res
;
226 uint64_t pos
= avio_tell(pb
);
227 tag
= get_swf_tag(pb
, &len
);
231 av_log(s
, AV_LOG_ERROR
, "invalid tag length: %d\n", len
);
232 return AVERROR_INVALIDDATA
;
234 if (tag
== TAG_VIDEOSTREAM
) {
235 int ch_id
= avio_rl16(pb
);
238 for (i
=0; i
<s
->nb_streams
; i
++) {
240 if (st
->codecpar
->codec_type
== AVMEDIA_TYPE_VIDEO
&& st
->id
== ch_id
)
249 vst
= avformat_new_stream(s
, NULL
);
251 return AVERROR(ENOMEM
);
253 vst
->codecpar
->codec_type
= AVMEDIA_TYPE_VIDEO
;
254 vst
->codecpar
->codec_id
= ff_codec_get_id(ff_swf_codec_tags
, avio_r8(pb
));
255 avpriv_set_pts_info(vst
, 16, 256, swf
->frame_rate
);
257 } else if (tag
== TAG_STREAMHEAD
|| tag
== TAG_STREAMHEAD2
) {
258 /* streaming found */
260 for (i
=0; i
<s
->nb_streams
; i
++) {
262 if (st
->codecpar
->codec_type
== AVMEDIA_TYPE_AUDIO
&& st
->id
== -1)
268 swf
->samples_per_frame
= avio_rl16(pb
);
269 ast
= create_new_audio_stream(s
, -1, v
); /* -1 to avoid clash with video stream ch_id */
271 return AVERROR(ENOMEM
);
273 } else if (tag
== TAG_DEFINESOUND
) {
275 int ch_id
= avio_rl16(pb
);
277 for (i
=0; i
<s
->nb_streams
; i
++) {
279 if (st
->codecpar
->codec_type
== AVMEDIA_TYPE_AUDIO
&& st
->id
== ch_id
)
283 // FIXME: The entire audio stream is stored in a single chunk/tag. Normally,
284 // these are smaller audio streams in DEFINESOUND tags, but it's technically
285 // possible they could be huge. Break it up into multiple packets if it's big.
287 ast
= create_new_audio_stream(s
, ch_id
, v
);
289 return AVERROR(ENOMEM
);
290 ast
->duration
= avio_rl32(pb
); // number of samples
291 if (((v
>>4) & 15) == 2) { // MP3 sound data record
292 ffstream(ast
)->skip_samples
= avio_rl16(pb
);
296 if ((res
= av_get_packet(pb
, pkt
, len
)) < 0)
299 pkt
->stream_index
= ast
->index
;
301 } else if (tag
== TAG_VIDEOFRAME
) {
302 int ch_id
= avio_rl16(pb
);
304 for(i
=0; i
<s
->nb_streams
; i
++) {
306 if (st
->codecpar
->codec_type
== AVMEDIA_TYPE_VIDEO
&& st
->id
== ch_id
) {
308 frame
= avio_rl16(pb
);
312 if (st
->codecpar
->codec_id
== AV_CODEC_ID_FLASHSV
) {
313 unsigned flags
= avio_r8(pb
);
317 pkt_flags
|= (flags
& FLV_VIDEO_FRAMETYPE_MASK
) == FLV_FRAME_KEY
? AV_PKT_FLAG_KEY
: 0;
319 if ((res
= av_get_packet(pb
, pkt
, len
)) < 0)
323 pkt
->stream_index
= st
->index
;
324 pkt
->flags
|= pkt_flags
;
328 } else if (tag
== TAG_DEFINEBITSLOSSLESS
|| tag
== TAG_DEFINEBITSLOSSLESS2
) {
331 uint8_t *buf
= NULL
, *zbuf
= NULL
, *pal
;
332 uint32_t colormap
[AVPALETTE_COUNT
] = {0};
333 const int alpha_bmp
= tag
== TAG_DEFINEBITSLOSSLESS2
;
334 const int colormapbpp
= 3 + alpha_bmp
;
335 int linesize
, colormapsize
= 0;
337 const int ch_id
= avio_rl16(pb
);
338 const int bmp_fmt
= avio_r8(pb
);
339 const int width
= avio_rl16(pb
);
340 const int height
= avio_rl16(pb
);
348 colormapsize
= avio_r8(pb
) + 1;
352 linesize
= width
* 2;
354 case 5: // RGB24 (0RGB)
355 linesize
= width
* 4;
358 av_log(s
, AV_LOG_ERROR
, "invalid bitmap format %d, skipped\n", bmp_fmt
);
359 goto bitmap_end_skip
;
362 linesize
= FFALIGN(linesize
, 4);
364 if (av_image_check_size(width
, height
, 0, s
) < 0 ||
365 linesize
>= INT_MAX
/ height
||
366 linesize
* height
>= INT_MAX
- colormapsize
* colormapbpp
) {
367 av_log(s
, AV_LOG_ERROR
, "invalid frame size %dx%d\n", width
, height
);
368 goto bitmap_end_skip
;
371 out_len
= colormapsize
* colormapbpp
+ linesize
* height
;
373 ff_dlog(s
, "bitmap: ch=%d fmt=%d %dx%d (linesize=%d) len=%d->%ld pal=%d\n",
374 ch_id
, bmp_fmt
, width
, height
, linesize
, len
, out_len
, colormapsize
);
376 if (len
* 17373LL < out_len
)
377 goto bitmap_end_skip
;
379 zbuf
= av_malloc(len
);
381 res
= AVERROR(ENOMEM
);
385 len
= avio_read(pb
, zbuf
, len
);
387 goto bitmap_end_skip
;
389 buf
= av_malloc(out_len
);
391 res
= AVERROR(ENOMEM
);
394 if ((res
= uncompress(buf
, &out_len
, zbuf
, len
)) != Z_OK
) {
395 av_log(s
, AV_LOG_WARNING
, "Failed to uncompress one bitmap\n");
396 goto bitmap_end_skip
;
399 for (i
= 0; i
< s
->nb_streams
; i
++) {
401 if (st
->codecpar
->codec_id
== AV_CODEC_ID_RAWVIDEO
&& st
->id
== -3)
404 if (i
== s
->nb_streams
) {
405 vst
= avformat_new_stream(s
, NULL
);
407 res
= AVERROR(ENOMEM
);
410 vst
->id
= -3; /* -3 to avoid clash with video stream and audio stream */
411 vst
->codecpar
->codec_type
= AVMEDIA_TYPE_VIDEO
;
412 vst
->codecpar
->codec_id
= AV_CODEC_ID_RAWVIDEO
;
413 avpriv_set_pts_info(vst
, 64, 256, swf
->frame_rate
);
417 if ((res
= av_new_packet(pkt
, out_len
- colormapsize
* colormapbpp
)) < 0)
419 if (!st
->codecpar
->width
&& !st
->codecpar
->height
) {
420 st
->codecpar
->width
= width
;
421 st
->codecpar
->height
= height
;
423 ff_add_param_change(pkt
, 0, 0, 0, width
, height
);
426 pkt
->stream_index
= st
->index
;
428 if (linesize
* height
> pkt
->size
) {
429 res
= AVERROR_INVALIDDATA
;
435 pix_fmt
= AV_PIX_FMT_PAL8
;
436 for (i
= 0; i
< colormapsize
; i
++)
437 if (alpha_bmp
) colormap
[i
] = buf
[3]<<24 | AV_RB24(buf
+ 4*i
);
438 else colormap
[i
] = 0xffU
<<24 | AV_RB24(buf
+ 3*i
);
439 pal
= av_packet_new_side_data(pkt
, AV_PKT_DATA_PALETTE
, AVPALETTE_SIZE
);
441 res
= AVERROR(ENOMEM
);
444 memcpy(pal
, colormap
, AVPALETTE_SIZE
);
447 pix_fmt
= AV_PIX_FMT_RGB555
;
450 pix_fmt
= alpha_bmp
? AV_PIX_FMT_ARGB
: AV_PIX_FMT_0RGB
;
455 if (st
->codecpar
->format
!= AV_PIX_FMT_NONE
&& st
->codecpar
->format
!= pix_fmt
) {
456 av_log(s
, AV_LOG_ERROR
, "pixel format change unsupported\n");
458 st
->codecpar
->format
= pix_fmt
;
460 memcpy(pkt
->data
, buf
+ colormapsize
*colormapbpp
, linesize
* height
);
472 av_log(s
, AV_LOG_ERROR
, "this file requires zlib support compiled in\n");
474 } else if (tag
== TAG_STREAMBLOCK
) {
475 for (i
= 0; i
< s
->nb_streams
; i
++) {
477 if (st
->codecpar
->codec_type
== AVMEDIA_TYPE_AUDIO
&& st
->id
== -1) {
478 if (st
->codecpar
->codec_id
== AV_CODEC_ID_MP3
) {
483 if ((res
= av_get_packet(pb
, pkt
, len
)) < 0)
485 } else { // ADPCM, PCM
488 if ((res
= av_get_packet(pb
, pkt
, len
)) < 0)
492 pkt
->stream_index
= st
->index
;
496 } else if (tag
== TAG_JPEG2
) {
497 for (i
=0; i
<s
->nb_streams
; i
++) {
499 if (st
->codecpar
->codec_id
== AV_CODEC_ID_MJPEG
&& st
->id
== -2)
502 if (i
== s
->nb_streams
) {
503 vst
= avformat_new_stream(s
, NULL
);
505 return AVERROR(ENOMEM
);
506 vst
->id
= -2; /* -2 to avoid clash with video stream and audio stream */
507 vst
->codecpar
->codec_type
= AVMEDIA_TYPE_VIDEO
;
508 vst
->codecpar
->codec_id
= AV_CODEC_ID_MJPEG
;
509 avpriv_set_pts_info(vst
, 64, 256, swf
->frame_rate
);
512 avio_rl16(pb
); /* BITMAP_ID */
516 if ((res
= av_new_packet(pkt
, len
)) < 0)
518 if (avio_read(pb
, pkt
->data
, 4) != 4) {
519 return AVERROR_INVALIDDATA
;
521 if (AV_RB32(pkt
->data
) == 0xffd8ffd9 ||
522 AV_RB32(pkt
->data
) == 0xffd9ffd8) {
523 /* old SWF files containing SOI/EOI as data start */
524 /* files created by swink have reversed tag */
526 memset(pkt
->data
+pkt
->size
, 0, 4);
527 res
= avio_read(pb
, pkt
->data
, pkt
->size
);
529 res
= avio_read(pb
, pkt
->data
+ 4, pkt
->size
- 4);
533 if (res
!= pkt
->size
) {
537 av_shrink_packet(pkt
, res
);
541 pkt
->stream_index
= st
->index
;
544 av_log(s
, AV_LOG_DEBUG
, "Unknown tag: %d\n", tag
);
548 av_log(s
, AV_LOG_WARNING
, "Clipping len %d\n", len
);
555 static av_cold
int swf_read_close(AVFormatContext
*avctx
)
557 SWFDecContext
*s
= avctx
->priv_data
;
558 inflateEnd(&s
->zstream
);
559 av_freep(&s
->zbuf_in
);
560 av_freep(&s
->zbuf_out
);
561 avio_context_free(&s
->zpb
);
566 const FFInputFormat ff_swf_demuxer
= {
568 .p
.long_name
= NULL_IF_CONFIG_SMALL("SWF (ShockWave Flash)"),
569 .priv_data_size
= sizeof(SWFDecContext
),
570 .read_probe
= swf_probe
,
571 .read_header
= swf_read_header
,
572 .read_packet
= swf_read_packet
,
574 .read_close
= swf_read_close
,