2 * Flash Compatible Streaming Format
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 "bitstream.h"
24 #include "riff.h" /* for CodecTag */
26 /* should have a generic way to indicate probable size */
27 #define DUMMY_FILE_SIZE (100 * 1024 * 1024)
28 #define DUMMY_DURATION 600 /* in seconds */
31 #define TAG_SHOWFRAME 1
32 #define TAG_DEFINESHAPE 2
33 #define TAG_FREECHARACTER 3
34 #define TAG_PLACEOBJECT 4
35 #define TAG_REMOVEOBJECT 5
36 #define TAG_STREAMHEAD 18
37 #define TAG_STREAMBLOCK 19
39 #define TAG_PLACEOBJECT2 26
40 #define TAG_STREAMHEAD2 45
41 #define TAG_VIDEOSTREAM 60
42 #define TAG_VIDEOFRAME 61
43 #define TAG_FILEATTRIBUTES 69
45 #define TAG_LONG 0x100
47 /* flags for shape definition */
48 #define FLAG_MOVETO 0x01
49 #define FLAG_SETFILL0 0x02
50 #define FLAG_SETFILL1 0x04
52 #define AUDIO_FIFO_SIZE 65536
54 /* character id used */
63 int audio_stream_index
;
64 offset_t duration_pos
;
67 int samples_per_frame
;
70 int video_frame_number
;
74 uint8_t audio_fifo
[AUDIO_FIFO_SIZE
];
81 static const AVCodecTag swf_codec_tags
[] = {
82 {CODEC_ID_FLV1
, 0x02},
83 {CODEC_ID_VP6F
, 0x04},
87 static const AVCodecTag swf_audio_codec_tags
[] = {
88 {CODEC_ID_PCM_S16LE
, 0x00},
89 {CODEC_ID_ADPCM_SWF
, 0x01},
91 {CODEC_ID_PCM_S16LE
, 0x03},
92 //{CODEC_ID_NELLYMOSER, 0x06},
97 static void put_swf_tag(AVFormatContext
*s
, int tag
)
99 SWFContext
*swf
= s
->priv_data
;
100 ByteIOContext
*pb
= s
->pb
;
102 swf
->tag_pos
= url_ftell(pb
);
104 /* reserve some room for the tag */
105 if (tag
& TAG_LONG
) {
113 static void put_swf_end_tag(AVFormatContext
*s
)
115 SWFContext
*swf
= s
->priv_data
;
116 ByteIOContext
*pb
= s
->pb
;
121 tag_len
= pos
- swf
->tag_pos
- 2;
123 url_fseek(pb
, swf
->tag_pos
, SEEK_SET
);
124 if (tag
& TAG_LONG
) {
126 put_le16(pb
, (tag
<< 6) | 0x3f);
127 put_le32(pb
, tag_len
- 4);
129 assert(tag_len
< 0x3f);
130 put_le16(pb
, (tag
<< 6) | tag_len
);
132 url_fseek(pb
, pos
, SEEK_SET
);
135 static inline void max_nbits(int *nbits_ptr
, int val
)
151 static void put_swf_rect(ByteIOContext
*pb
,
152 int xmin
, int xmax
, int ymin
, int ymax
)
158 init_put_bits(&p
, buf
, sizeof(buf
));
161 max_nbits(&nbits
, xmin
);
162 max_nbits(&nbits
, xmax
);
163 max_nbits(&nbits
, ymin
);
164 max_nbits(&nbits
, ymax
);
165 mask
= (1 << nbits
) - 1;
168 put_bits(&p
, 5, nbits
);
169 put_bits(&p
, nbits
, xmin
& mask
);
170 put_bits(&p
, nbits
, xmax
& mask
);
171 put_bits(&p
, nbits
, ymin
& mask
);
172 put_bits(&p
, nbits
, ymax
& mask
);
175 put_buffer(pb
, buf
, pbBufPtr(&p
) - p
.buf
);
178 static void put_swf_line_edge(PutBitContext
*pb
, int dx
, int dy
)
182 put_bits(pb
, 1, 1); /* edge */
183 put_bits(pb
, 1, 1); /* line select */
185 max_nbits(&nbits
, dx
);
186 max_nbits(&nbits
, dy
);
188 mask
= (1 << nbits
) - 1;
189 put_bits(pb
, 4, nbits
- 2); /* 16 bits precision */
193 put_bits(pb
, nbits
, dy
& mask
);
194 } else if (dy
== 0) {
197 put_bits(pb
, nbits
, dx
& mask
);
200 put_bits(pb
, nbits
, dx
& mask
);
201 put_bits(pb
, nbits
, dy
& mask
);
208 static void put_swf_matrix(ByteIOContext
*pb
,
209 int a
, int b
, int c
, int d
, int tx
, int ty
)
215 init_put_bits(&p
, buf
, sizeof(buf
));
217 put_bits(&p
, 1, 1); /* a, d present */
219 max_nbits(&nbits
, a
);
220 max_nbits(&nbits
, d
);
221 put_bits(&p
, 5, nbits
); /* nb bits */
222 put_bits(&p
, nbits
, a
);
223 put_bits(&p
, nbits
, d
);
225 put_bits(&p
, 1, 1); /* b, c present */
227 max_nbits(&nbits
, c
);
228 max_nbits(&nbits
, b
);
229 put_bits(&p
, 5, nbits
); /* nb bits */
230 put_bits(&p
, nbits
, c
);
231 put_bits(&p
, nbits
, b
);
234 max_nbits(&nbits
, tx
);
235 max_nbits(&nbits
, ty
);
236 put_bits(&p
, 5, nbits
); /* nb bits */
237 put_bits(&p
, nbits
, tx
);
238 put_bits(&p
, nbits
, ty
);
241 put_buffer(pb
, buf
, pbBufPtr(&p
) - p
.buf
);
245 static int swf_write_header(AVFormatContext
*s
)
247 SWFContext
*swf
= s
->priv_data
;
248 ByteIOContext
*pb
= s
->pb
;
249 AVCodecContext
*enc
, *audio_enc
, *video_enc
;
252 int i
, width
, height
, rate
, rate_base
;
255 swf
->audio_in_pos
= 0;
256 swf
->sound_samples
= 0;
257 swf
->swf_frame_number
= 0;
258 swf
->video_frame_number
= 0;
262 for(i
=0;i
<s
->nb_streams
;i
++) {
263 enc
= s
->streams
[i
]->codec
;
264 if (enc
->codec_type
== CODEC_TYPE_AUDIO
) {
265 if (enc
->codec_id
== CODEC_ID_MP3
) {
266 if (!enc
->frame_size
) {
267 av_log(s
, AV_LOG_ERROR
, "audio frame size not set\n");
272 av_log(s
, AV_LOG_ERROR
, "SWF muxer only supports MP3\n");
276 if (enc
->codec_id
== CODEC_ID_VP6F
||
277 enc
->codec_id
== CODEC_ID_FLV1
||
278 enc
->codec_id
== CODEC_ID_MJPEG
) {
281 av_log(s
, AV_LOG_ERROR
, "SWF muxer only supports VP6, FLV1 and MJPEG\n");
288 /* currently, cannot work correctly if audio only */
295 swf
->video_type
= video_enc
->codec_id
;
296 width
= video_enc
->width
;
297 height
= video_enc
->height
;
298 rate
= video_enc
->time_base
.den
;
299 rate_base
= video_enc
->time_base
.num
;
304 swf
->samples_per_frame
= (44100. * rate_base
) / rate
;
306 swf
->audio_type
= audio_enc
->codec_id
;
307 swf
->samples_per_frame
= (audio_enc
->sample_rate
* rate_base
) / rate
;
310 is_avm2
= !strcmp("avm2", s
->oformat
->name
);
315 } else if (video_enc
&& video_enc
->codec_id
== CODEC_ID_VP6F
) {
316 put_byte(pb
, 8); /* version (version 8 and above support VP6 codec) */
317 } else if (video_enc
&& video_enc
->codec_id
== CODEC_ID_FLV1
) {
318 put_byte(pb
, 6); /* version (version 6 and above support FLV1 codec) */
320 put_byte(pb
, 4); /* version (should use 4 for mpeg audio support) */
322 put_le32(pb
, DUMMY_FILE_SIZE
); /* dummy size
323 (will be patched if not streamed) */
325 put_swf_rect(pb
, 0, width
* 20, 0, height
* 20);
326 put_le16(pb
, (rate
* 256) / rate_base
); /* frame rate */
327 swf
->duration_pos
= url_ftell(pb
);
328 put_le16(pb
, (uint16_t)(DUMMY_DURATION
* (int64_t)rate
/ rate_base
)); /* frame count */
330 /* avm2/swf v9 (also v8?) files require a file attribute tag */
332 put_swf_tag(s
, TAG_FILEATTRIBUTES
);
333 put_le32(pb
, 1<<3); /* set ActionScript v3/AVM2 flag */
337 /* define a shape with the jpeg inside */
338 if (video_enc
&& (video_enc
->codec_id
== CODEC_ID_VP6F
||
339 video_enc
->codec_id
== CODEC_ID_FLV1
)) {
340 } else if (video_enc
&& video_enc
->codec_id
== CODEC_ID_MJPEG
) {
341 put_swf_tag(s
, TAG_DEFINESHAPE
);
343 put_le16(pb
, SHAPE_ID
); /* ID of shape */
344 /* bounding rectangle */
345 put_swf_rect(pb
, 0, width
, 0, height
);
347 put_byte(pb
, 1); /* one fill style */
348 put_byte(pb
, 0x41); /* clipped bitmap fill */
349 put_le16(pb
, BITMAP_ID
); /* bitmap ID */
350 /* position of the bitmap */
351 put_swf_matrix(pb
, (int)(1.0 * (1 << FRAC_BITS
)), 0,
352 0, (int)(1.0 * (1 << FRAC_BITS
)), 0, 0);
353 put_byte(pb
, 0); /* no line style */
356 init_put_bits(&p
, buf1
, sizeof(buf1
));
357 put_bits(&p
, 4, 1); /* one fill bit */
358 put_bits(&p
, 4, 0); /* zero line bit */
360 put_bits(&p
, 1, 0); /* not an edge */
361 put_bits(&p
, 5, FLAG_MOVETO
| FLAG_SETFILL0
);
362 put_bits(&p
, 5, 1); /* nbits */
363 put_bits(&p
, 1, 0); /* X */
364 put_bits(&p
, 1, 0); /* Y */
365 put_bits(&p
, 1, 1); /* set fill style 1 */
367 /* draw the rectangle ! */
368 put_swf_line_edge(&p
, width
, 0);
369 put_swf_line_edge(&p
, 0, height
);
370 put_swf_line_edge(&p
, -width
, 0);
371 put_swf_line_edge(&p
, 0, -height
);
374 put_bits(&p
, 1, 0); /* not an edge */
378 put_buffer(pb
, buf1
, pbBufPtr(&p
) - p
.buf
);
383 if (audio_enc
&& audio_enc
->codec_id
== CODEC_ID_MP3
) {
387 put_swf_tag(s
, TAG_STREAMHEAD2
);
390 switch(audio_enc
->sample_rate
) {
402 av_log(s
, AV_LOG_ERROR
, "swf does not support that sample rate, choose from (44100, 22050, 11025).\n");
405 v
|= 0x02; /* 16 bit playback */
406 if (audio_enc
->channels
== 2)
407 v
|= 0x01; /* stereo playback */
409 v
|= 0x20; /* mp3 compressed */
411 put_le16(s
->pb
, swf
->samples_per_frame
); /* avg samples per frame */
417 put_flush_packet(s
->pb
);
421 static int swf_write_video(AVFormatContext
*s
,
422 AVCodecContext
*enc
, const uint8_t *buf
, int size
)
424 SWFContext
*swf
= s
->priv_data
;
425 ByteIOContext
*pb
= s
->pb
;
427 /* Flash Player limit */
428 if (swf
->swf_frame_number
== 16000) {
429 av_log(enc
, AV_LOG_INFO
, "warning: Flash Player limit of 16000 frames reached\n");
432 if (swf
->video_type
== CODEC_ID_VP6F
||
433 swf
->video_type
== CODEC_ID_FLV1
) {
434 if (swf
->video_frame_number
== 0) {
435 /* create a new video object */
436 put_swf_tag(s
, TAG_VIDEOSTREAM
);
437 put_le16(pb
, VIDEO_ID
);
438 put_le16(pb
, 15000); /* hard flash player limit */
439 put_le16(pb
, enc
->width
);
440 put_le16(pb
, enc
->height
);
442 put_byte(pb
,codec_get_tag(swf_codec_tags
,swf
->video_type
));
445 /* place the video object for the first time */
446 put_swf_tag(s
, TAG_PLACEOBJECT2
);
449 put_le16(pb
, VIDEO_ID
);
450 put_swf_matrix(pb
, 1 << FRAC_BITS
, 0, 0, 1 << FRAC_BITS
, 0, 0);
451 put_le16(pb
, swf
->video_frame_number
);
460 /* mark the character for update */
461 put_swf_tag(s
, TAG_PLACEOBJECT2
);
464 put_le16(pb
, swf
->video_frame_number
);
468 /* set video frame data */
469 put_swf_tag(s
, TAG_VIDEOFRAME
| TAG_LONG
);
470 put_le16(pb
, VIDEO_ID
);
471 put_le16(pb
, swf
->video_frame_number
++);
472 put_buffer(pb
, buf
, size
);
474 } else if (swf
->video_type
== CODEC_ID_MJPEG
) {
475 if (swf
->swf_frame_number
> 0) {
476 /* remove the shape */
477 put_swf_tag(s
, TAG_REMOVEOBJECT
);
478 put_le16(pb
, SHAPE_ID
); /* shape ID */
479 put_le16(pb
, 1); /* depth */
482 /* free the bitmap */
483 put_swf_tag(s
, TAG_FREECHARACTER
);
484 put_le16(pb
, BITMAP_ID
);
488 put_swf_tag(s
, TAG_JPEG2
| TAG_LONG
);
490 put_le16(pb
, BITMAP_ID
); /* ID of the image */
492 /* a dummy jpeg header seems to be required */
497 /* write the jpeg image */
498 put_buffer(pb
, buf
, size
);
504 put_swf_tag(s
, TAG_PLACEOBJECT
);
505 put_le16(pb
, SHAPE_ID
); /* shape ID */
506 put_le16(pb
, 1); /* depth */
507 put_swf_matrix(pb
, 20 << FRAC_BITS
, 0, 0, 20 << FRAC_BITS
, 0, 0);
513 swf
->swf_frame_number
++;
515 /* streaming sound always should be placed just before showframe tags */
516 if (swf
->audio_type
&& swf
->audio_in_pos
) {
517 put_swf_tag(s
, TAG_STREAMBLOCK
| TAG_LONG
);
518 put_le16(pb
, swf
->sound_samples
);
519 put_le16(pb
, 0); // seek samples
520 put_buffer(pb
, swf
->audio_fifo
, swf
->audio_in_pos
);
524 swf
->sound_samples
= 0;
525 swf
->audio_in_pos
= 0;
528 /* output the frame */
529 put_swf_tag(s
, TAG_SHOWFRAME
);
532 put_flush_packet(s
->pb
);
537 static int swf_write_audio(AVFormatContext
*s
,
538 AVCodecContext
*enc
, const uint8_t *buf
, int size
)
540 SWFContext
*swf
= s
->priv_data
;
542 /* Flash Player limit */
543 if (swf
->swf_frame_number
== 16000) {
544 av_log(enc
, AV_LOG_INFO
, "warning: Flash Player limit of 16000 frames reached\n");
547 if (swf
->audio_in_pos
+ size
>= AUDIO_FIFO_SIZE
) {
548 av_log(s
, AV_LOG_ERROR
, "audio fifo too small to mux audio essence\n");
552 memcpy(swf
->audio_fifo
+ swf
->audio_in_pos
, buf
, size
);
553 swf
->audio_in_pos
+= size
;
554 swf
->sound_samples
+= enc
->frame_size
;
556 /* if audio only stream make sure we add swf frames */
557 if (swf
->video_type
== 0) {
558 swf_write_video(s
, enc
, 0, 0);
564 static int swf_write_packet(AVFormatContext
*s
, AVPacket
*pkt
)
566 AVCodecContext
*codec
= s
->streams
[pkt
->stream_index
]->codec
;
567 if (codec
->codec_type
== CODEC_TYPE_AUDIO
)
568 return swf_write_audio(s
, codec
, pkt
->data
, pkt
->size
);
570 return swf_write_video(s
, codec
, pkt
->data
, pkt
->size
);
573 static int swf_write_trailer(AVFormatContext
*s
)
575 SWFContext
*swf
= s
->priv_data
;
576 ByteIOContext
*pb
= s
->pb
;
577 AVCodecContext
*enc
, *video_enc
;
581 for(i
=0;i
<s
->nb_streams
;i
++) {
582 enc
= s
->streams
[i
]->codec
;
583 if (enc
->codec_type
== CODEC_TYPE_VIDEO
)
587 put_swf_tag(s
, TAG_END
);
590 put_flush_packet(s
->pb
);
592 /* patch file size and number of frames if not streamed */
593 if (!url_is_streamed(s
->pb
) && video_enc
) {
594 file_size
= url_ftell(pb
);
595 url_fseek(pb
, 4, SEEK_SET
);
596 put_le32(pb
, file_size
);
597 url_fseek(pb
, swf
->duration_pos
, SEEK_SET
);
598 put_le16(pb
, video_enc
->frame_number
);
599 url_fseek(pb
, file_size
, SEEK_SET
);
603 #endif //CONFIG_MUXERS
605 /*********************************************/
606 /* Extract FLV encoded frame and MP3 from swf
607 Note that the detection of the real frame
608 is inaccurate at this point as it can be
609 quite tricky to determine, you almost certainly
610 will get a bad audio/video sync */
612 static int get_swf_tag(ByteIOContext
*pb
, int *len_ptr
)
625 // av_log(NULL, AV_LOG_DEBUG, "Tag: %d - Len: %d\n", tag, len);
631 static int swf_probe(AVProbeData
*p
)
633 /* check file header */
634 if ((p
->buf
[0] == 'F' || p
->buf
[0] == 'C') && p
->buf
[1] == 'W' &&
636 return AVPROBE_SCORE_MAX
;
641 static int swf_read_header(AVFormatContext
*s
, AVFormatParameters
*ap
)
643 SWFContext
*swf
= s
->priv_data
;
644 ByteIOContext
*pb
= s
->pb
;
647 tag
= get_be32(pb
) & 0xffffff00;
649 if (tag
== MKBETAG('C', 'W', 'S', 0)) {
650 av_log(s
, AV_LOG_ERROR
, "Compressed SWF format not supported\n");
653 if (tag
!= MKBETAG('F', 'W', 'S', 0))
656 /* skip rectangle size */
657 nbits
= get_byte(pb
) >> 3;
658 len
= (4 * nbits
- 3 + 7) / 8;
660 swf
->frame_rate
= get_le16(pb
); /* 8.8 fixed */
661 get_le16(pb
); /* frame count */
663 swf
->samples_per_frame
= 0;
664 s
->ctx_flags
|= AVFMTCTX_NOHEADER
;
668 static int swf_read_packet(AVFormatContext
*s
, AVPacket
*pkt
)
670 SWFContext
*swf
= s
->priv_data
;
671 ByteIOContext
*pb
= s
->pb
;
672 AVStream
*vst
= NULL
, *ast
= NULL
, *st
= 0;
673 int tag
, len
, i
, frame
, v
;
676 tag
= get_swf_tag(pb
, &len
);
679 if (tag
== TAG_VIDEOSTREAM
&& !vst
) {
680 int ch_id
= get_le16(pb
);
686 vst
= av_new_stream(s
, ch_id
);
689 vst
->codec
->codec_type
= CODEC_TYPE_VIDEO
;
690 vst
->codec
->codec_id
= codec_get_id(swf_codec_tags
, get_byte(pb
));
691 av_set_pts_info(vst
, 64, 256, swf
->frame_rate
);
692 vst
->codec
->time_base
= (AVRational
){ 256, swf
->frame_rate
};
694 } else if ((tag
== TAG_STREAMHEAD
|| tag
== TAG_STREAMHEAD2
) && !ast
) {
695 /* streaming found */
696 int sample_rate_code
;
699 swf
->samples_per_frame
= get_le16(pb
);
700 ast
= av_new_stream(s
, -1); /* -1 to avoid clash with video stream ch_id */
703 swf
->audio_stream_index
= ast
->index
;
704 ast
->codec
->channels
= 1 + (v
&1);
705 ast
->codec
->codec_type
= CODEC_TYPE_AUDIO
;
706 ast
->codec
->codec_id
= codec_get_id(swf_audio_codec_tags
, (v
>>4) & 15);
707 ast
->need_parsing
= AVSTREAM_PARSE_FULL
;
708 sample_rate_code
= (v
>>2) & 3;
709 if (!sample_rate_code
)
711 ast
->codec
->sample_rate
= 11025 << (sample_rate_code
-1);
712 av_set_pts_info(ast
, 64, 1, ast
->codec
->sample_rate
);
714 } else if (tag
== TAG_VIDEOFRAME
) {
715 int ch_id
= get_le16(pb
);
717 for(i
=0; i
<s
->nb_streams
; i
++) {
719 if (st
->codec
->codec_type
== CODEC_TYPE_VIDEO
&& st
->id
== ch_id
) {
720 frame
= get_le16(pb
);
721 av_get_packet(pb
, pkt
, len
-2);
723 pkt
->stream_index
= st
->index
;
727 } else if (tag
== TAG_STREAMBLOCK
) {
728 st
= s
->streams
[swf
->audio_stream_index
];
729 if (st
->codec
->codec_id
== CODEC_ID_MP3
) {
731 av_get_packet(pb
, pkt
, len
-4);
732 } else { // ADPCM, PCM
733 av_get_packet(pb
, pkt
, len
);
735 pkt
->stream_index
= st
->index
;
737 } else if (tag
== TAG_JPEG2
) {
738 for (i
=0; i
<s
->nb_streams
; i
++) {
743 if (i
== s
->nb_streams
) {
744 vst
= av_new_stream(s
, -2); /* -2 to avoid clash with video stream and audio stream */
747 vst
->codec
->codec_type
= CODEC_TYPE_VIDEO
;
748 vst
->codec
->codec_id
= CODEC_ID_MJPEG
;
749 av_set_pts_info(vst
, 64, 256, swf
->frame_rate
);
750 vst
->codec
->time_base
= (AVRational
){ 256, swf
->frame_rate
};
753 get_le16(pb
); /* BITMAP_ID */
754 av_new_packet(pkt
, len
-2);
755 get_buffer(pb
, pkt
->data
, 4);
756 if (AV_RB32(pkt
->data
) == 0xffd8ffd9 ||
757 AV_RB32(pkt
->data
) == 0xffd9ffd8) {
758 /* old SWF files containing SOI/EOI as data start */
759 /* files created by swink have reversed tag */
761 get_buffer(pb
, pkt
->data
, pkt
->size
);
763 get_buffer(pb
, pkt
->data
+ 4, pkt
->size
- 4);
765 pkt
->stream_index
= st
->index
;
773 static int swf_read_close(AVFormatContext
*s
)
778 #ifdef CONFIG_SWF_DEMUXER
779 AVInputFormat swf_demuxer
= {
789 #ifdef CONFIG_SWF_MUXER
790 AVOutputFormat swf_muxer
= {
793 "application/x-shockwave-flash",
803 #ifdef CONFIG_AVM2_MUXER
804 AVOutputFormat avm2_muxer
= {
806 "Flash 9 (AVM2) format",
807 "application/x-shockwave-flash",