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
44 #define TAG_LONG 0x100
46 /* flags for shape definition */
47 #define FLAG_MOVETO 0x01
48 #define FLAG_SETFILL0 0x02
49 #define FLAG_SETFILL1 0x04
51 #define AUDIO_FIFO_SIZE 65536
53 /* character id used */
62 int audio_stream_index;
63 offset_t duration_pos;
66 int samples_per_frame;
69 int video_frame_number;
73 uint8_t audio_fifo[AUDIO_FIFO_SIZE];
80 static const AVCodecTag swf_codec_tags[] = {
81 {CODEC_ID_FLV1, 0x02},
82 {CODEC_ID_VP6F, 0x04},
86 static const AVCodecTag swf_audio_codec_tags[] = {
87 {CODEC_ID_PCM_S16LE, 0x00},
88 {CODEC_ID_ADPCM_SWF, 0x01},
90 {CODEC_ID_PCM_S16LE, 0x03},
91 //{CODEC_ID_NELLYMOSER, 0x06},
96 static void put_swf_tag(AVFormatContext *s, int tag)
98 SWFContext *swf = s->priv_data;
99 ByteIOContext *pb = &s->pb;
101 swf->tag_pos = url_ftell(pb);
103 /* reserve some room for the tag */
104 if (tag & TAG_LONG) {
112 static void put_swf_end_tag(AVFormatContext *s)
114 SWFContext *swf = s->priv_data;
115 ByteIOContext *pb = &s->pb;
120 tag_len = pos - swf->tag_pos - 2;
122 url_fseek(pb, swf->tag_pos, SEEK_SET);
123 if (tag & TAG_LONG) {
125 put_le16(pb, (tag << 6) | 0x3f);
126 put_le32(pb, tag_len - 4);
128 assert(tag_len < 0x3f);
129 put_le16(pb, (tag << 6) | tag_len);
131 url_fseek(pb, pos, SEEK_SET);
134 static inline void max_nbits(int *nbits_ptr, int val)
150 static void put_swf_rect(ByteIOContext *pb,
151 int xmin, int xmax, int ymin, int ymax)
157 init_put_bits(&p, buf, sizeof(buf));
160 max_nbits(&nbits, xmin);
161 max_nbits(&nbits, xmax);
162 max_nbits(&nbits, ymin);
163 max_nbits(&nbits, ymax);
164 mask = (1 << nbits) - 1;
167 put_bits(&p, 5, nbits);
168 put_bits(&p, nbits, xmin & mask);
169 put_bits(&p, nbits, xmax & mask);
170 put_bits(&p, nbits, ymin & mask);
171 put_bits(&p, nbits, ymax & mask);
174 put_buffer(pb, buf, pbBufPtr(&p) - p.buf);
177 static void put_swf_line_edge(PutBitContext *pb, int dx, int dy)
181 put_bits(pb, 1, 1); /* edge */
182 put_bits(pb, 1, 1); /* line select */
184 max_nbits(&nbits, dx);
185 max_nbits(&nbits, dy);
187 mask = (1 << nbits) - 1;
188 put_bits(pb, 4, nbits - 2); /* 16 bits precision */
192 put_bits(pb, nbits, dy & mask);
193 } else if (dy == 0) {
196 put_bits(pb, nbits, dx & mask);
199 put_bits(pb, nbits, dx & mask);
200 put_bits(pb, nbits, dy & mask);
207 static void put_swf_matrix(ByteIOContext *pb,
208 int a, int b, int c, int d, int tx, int ty)
214 init_put_bits(&p, buf, sizeof(buf));
216 put_bits(&p, 1, 1); /* a, d present */
218 max_nbits(&nbits, a);
219 max_nbits(&nbits, d);
220 put_bits(&p, 5, nbits); /* nb bits */
221 put_bits(&p, nbits, a);
222 put_bits(&p, nbits, d);
224 put_bits(&p, 1, 1); /* b, c present */
226 max_nbits(&nbits, c);
227 max_nbits(&nbits, b);
228 put_bits(&p, 5, nbits); /* nb bits */
229 put_bits(&p, nbits, c);
230 put_bits(&p, nbits, b);
233 max_nbits(&nbits, tx);
234 max_nbits(&nbits, ty);
235 put_bits(&p, 5, nbits); /* nb bits */
236 put_bits(&p, nbits, tx);
237 put_bits(&p, nbits, ty);
240 put_buffer(pb, buf, pbBufPtr(&p) - p.buf);
244 static int swf_write_header(AVFormatContext *s)
246 SWFContext *swf = s->priv_data;
247 ByteIOContext *pb = &s->pb;
248 AVCodecContext *enc, *audio_enc, *video_enc;
251 int i, width, height, rate, rate_base;
253 swf->audio_in_pos = 0;
254 swf->sound_samples = 0;
255 swf->swf_frame_number = 0;
256 swf->video_frame_number = 0;
260 for(i=0;i<s->nb_streams;i++) {
261 enc = s->streams[i]->codec;
262 if (enc->codec_type == CODEC_TYPE_AUDIO) {
263 if (enc->codec_id == CODEC_ID_MP3) {
264 if (!enc->frame_size) {
265 av_log(s, AV_LOG_ERROR, "audio frame size not set\n");
270 av_log(s, AV_LOG_ERROR, "SWF muxer only supports MP3\n");
274 if ( enc->codec_id == CODEC_ID_VP6F ||
275 enc->codec_id == CODEC_ID_FLV1 ||
276 enc->codec_id == CODEC_ID_MJPEG ) {
279 av_log(s, AV_LOG_ERROR, "SWF muxer only supports VP6, FLV1 and MJPEG\n");
286 /* currenty, cannot work correctly if audio only */
293 swf->video_type = video_enc->codec_id;
294 width = video_enc->width;
295 height = video_enc->height;
296 rate = video_enc->time_base.den;
297 rate_base = video_enc->time_base.num;
302 swf->samples_per_frame = ( 44100. * rate_base ) / rate;
304 swf->audio_type = audio_enc->codec_id;
305 swf->samples_per_frame = ( ( audio_enc->sample_rate ) * rate_base ) / rate;
309 if ( video_enc && video_enc->codec_id == CODEC_ID_VP6F ) {
310 put_byte(pb, 8); /* version (version 8 and above support VP6 codec) */
311 } else if ( video_enc && video_enc->codec_id == CODEC_ID_FLV1 ) {
312 put_byte(pb, 6); /* version (version 6 and above support FLV1 codec) */
314 put_byte(pb, 4); /* version (should use 4 for mpeg audio support) */
316 put_le32(pb, DUMMY_FILE_SIZE); /* dummy size
317 (will be patched if not streamed) */
319 put_swf_rect(pb, 0, width * 20, 0, height * 20);
320 put_le16(pb, (rate * 256) / rate_base); /* frame rate */
321 swf->duration_pos = url_ftell(pb);
322 put_le16(pb, (uint16_t)(DUMMY_DURATION * (int64_t)rate / rate_base)); /* frame count */
324 /* define a shape with the jpeg inside */
325 if ( video_enc && (video_enc->codec_id == CODEC_ID_VP6F ||
326 video_enc->codec_id == CODEC_ID_FLV1 )) {
327 } else if ( video_enc && video_enc->codec_id == CODEC_ID_MJPEG ) {
328 put_swf_tag(s, TAG_DEFINESHAPE);
330 put_le16(pb, SHAPE_ID); /* ID of shape */
331 /* bounding rectangle */
332 put_swf_rect(pb, 0, width, 0, height);
334 put_byte(pb, 1); /* one fill style */
335 put_byte(pb, 0x41); /* clipped bitmap fill */
336 put_le16(pb, BITMAP_ID); /* bitmap ID */
337 /* position of the bitmap */
338 put_swf_matrix(pb, (int)(1.0 * (1 << FRAC_BITS)), 0,
339 0, (int)(1.0 * (1 << FRAC_BITS)), 0, 0);
340 put_byte(pb, 0); /* no line style */
343 init_put_bits(&p, buf1, sizeof(buf1));
344 put_bits(&p, 4, 1); /* one fill bit */
345 put_bits(&p, 4, 0); /* zero line bit */
347 put_bits(&p, 1, 0); /* not an edge */
348 put_bits(&p, 5, FLAG_MOVETO | FLAG_SETFILL0);
349 put_bits(&p, 5, 1); /* nbits */
350 put_bits(&p, 1, 0); /* X */
351 put_bits(&p, 1, 0); /* Y */
352 put_bits(&p, 1, 1); /* set fill style 1 */
354 /* draw the rectangle ! */
355 put_swf_line_edge(&p, width, 0);
356 put_swf_line_edge(&p, 0, height);
357 put_swf_line_edge(&p, -width, 0);
358 put_swf_line_edge(&p, 0, -height);
361 put_bits(&p, 1, 0); /* not an edge */
365 put_buffer(pb, buf1, pbBufPtr(&p) - p.buf);
370 if (audio_enc && audio_enc->codec_id == CODEC_ID_MP3 ) {
374 put_swf_tag(s, TAG_STREAMHEAD2);
377 switch(audio_enc->sample_rate) {
389 av_log(s, AV_LOG_ERROR, "swf doesnt support that sample rate, choose from (44100, 22050, 11025)\n");
392 v |= 0x02; /* 16 bit playback */
393 if (audio_enc->channels == 2)
394 v |= 0x01; /* stereo playback */
396 v |= 0x20; /* mp3 compressed */
398 put_le16(&s->pb, swf->samples_per_frame); /* avg samples per frame */
404 put_flush_packet(&s->pb);
408 static int swf_write_video(AVFormatContext *s,
409 AVCodecContext *enc, const uint8_t *buf, int size)
411 SWFContext *swf = s->priv_data;
412 ByteIOContext *pb = &s->pb;
414 /* Flash Player limit */
415 if ( swf->swf_frame_number == 16000 ) {
416 av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
419 if ( swf->video_type == CODEC_ID_VP6F ||
420 swf->video_type == CODEC_ID_FLV1 ) {
421 if ( swf->video_frame_number == 0 ) {
422 /* create a new video object */
423 put_swf_tag(s, TAG_VIDEOSTREAM);
424 put_le16(pb, VIDEO_ID);
425 put_le16(pb, 15000 ); /* hard flash player limit */
426 put_le16(pb, enc->width);
427 put_le16(pb, enc->height);
429 put_byte(pb,codec_get_tag(swf_codec_tags,swf->video_type));
432 /* place the video object for the first time */
433 put_swf_tag(s, TAG_PLACEOBJECT2);
436 put_le16(pb, VIDEO_ID);
437 put_swf_matrix(pb, 1 << FRAC_BITS, 0, 0, 1 << FRAC_BITS, 0, 0);
438 put_le16(pb, swf->video_frame_number );
447 /* mark the character for update */
448 put_swf_tag(s, TAG_PLACEOBJECT2);
451 put_le16(pb, swf->video_frame_number );
455 /* set video frame data */
456 put_swf_tag(s, TAG_VIDEOFRAME | TAG_LONG);
457 put_le16(pb, VIDEO_ID);
458 put_le16(pb, swf->video_frame_number++ );
459 put_buffer(pb, buf, size);
461 } else if ( swf->video_type == CODEC_ID_MJPEG ) {
462 if (swf->swf_frame_number > 0) {
463 /* remove the shape */
464 put_swf_tag(s, TAG_REMOVEOBJECT);
465 put_le16(pb, SHAPE_ID); /* shape ID */
466 put_le16(pb, 1); /* depth */
469 /* free the bitmap */
470 put_swf_tag(s, TAG_FREECHARACTER);
471 put_le16(pb, BITMAP_ID);
475 put_swf_tag(s, TAG_JPEG2 | TAG_LONG);
477 put_le16(pb, BITMAP_ID); /* ID of the image */
479 /* a dummy jpeg header seems to be required */
484 /* write the jpeg image */
485 put_buffer(pb, buf, size);
491 put_swf_tag(s, TAG_PLACEOBJECT);
492 put_le16(pb, SHAPE_ID); /* shape ID */
493 put_le16(pb, 1); /* depth */
494 put_swf_matrix(pb, 20 << FRAC_BITS, 0, 0, 20 << FRAC_BITS, 0, 0);
500 swf->swf_frame_number ++;
502 /* streaming sound always should be placed just before showframe tags */
503 if (swf->audio_type && swf->audio_in_pos) {
504 put_swf_tag(s, TAG_STREAMBLOCK | TAG_LONG);
505 put_le16(pb, swf->sound_samples);
506 put_le16(pb, 0); // seek samples
507 put_buffer(pb, swf->audio_fifo, swf->audio_in_pos);
511 swf->sound_samples = 0;
512 swf->audio_in_pos = 0;
515 /* output the frame */
516 put_swf_tag(s, TAG_SHOWFRAME);
519 put_flush_packet(&s->pb);
524 static int swf_write_audio(AVFormatContext *s,
525 AVCodecContext *enc, const uint8_t *buf, int size)
527 SWFContext *swf = s->priv_data;
529 /* Flash Player limit */
530 if ( swf->swf_frame_number == 16000 ) {
531 av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
534 if (swf->audio_in_pos + size >= AUDIO_FIFO_SIZE) {
535 av_log(s, AV_LOG_ERROR, "audio fifo too small to mux audio essence\n");
539 memcpy(swf->audio_fifo + swf->audio_in_pos, buf, size);
540 swf->audio_in_pos += size;
541 swf->sound_samples += enc->frame_size;
543 /* if audio only stream make sure we add swf frames */
544 if ( swf->video_type == 0 ) {
545 swf_write_video(s, enc, 0, 0);
551 static int swf_write_packet(AVFormatContext *s, AVPacket *pkt)
553 AVCodecContext *codec = s->streams[pkt->stream_index]->codec;
554 if (codec->codec_type == CODEC_TYPE_AUDIO)
555 return swf_write_audio(s, codec, pkt->data, pkt->size);
557 return swf_write_video(s, codec, pkt->data, pkt->size);
560 static int swf_write_trailer(AVFormatContext *s)
562 SWFContext *swf = s->priv_data;
563 ByteIOContext *pb = &s->pb;
564 AVCodecContext *enc, *video_enc;
568 for(i=0;i<s->nb_streams;i++) {
569 enc = s->streams[i]->codec;
570 if (enc->codec_type == CODEC_TYPE_VIDEO)
574 put_swf_tag(s, TAG_END);
577 put_flush_packet(&s->pb);
579 /* patch file size and number of frames if not streamed */
580 if (!url_is_streamed(&s->pb) && video_enc) {
581 file_size = url_ftell(pb);
582 url_fseek(pb, 4, SEEK_SET);
583 put_le32(pb, file_size);
584 url_fseek(pb, swf->duration_pos, SEEK_SET);
585 put_le16(pb, video_enc->frame_number);
586 url_fseek(pb, file_size, SEEK_SET);
590 #endif //CONFIG_MUXERS
592 /*********************************************/
593 /* Extract FLV encoded frame and MP3 from swf
594 Note that the detection of the real frame
595 is inaccurate at this point as it can be
596 quite tricky to determine, you almost certainly
597 will get a bad audio/video sync */
599 static int get_swf_tag(ByteIOContext *pb, int *len_ptr)
612 // av_log(NULL, AV_LOG_DEBUG, "Tag: %d - Len: %d\n", tag, len);
618 static int swf_probe(AVProbeData *p)
620 /* check file header */
621 if ((p->buf[0] == 'F' || p->buf[0] == 'C') && p->buf[1] == 'W' &&
623 return AVPROBE_SCORE_MAX;
628 static int swf_read_header(AVFormatContext *s, AVFormatParameters *ap)
630 SWFContext *swf = s->priv_data;
631 ByteIOContext *pb = &s->pb;
632 int nbits, len, tag, v;
633 offset_t frame_offset = -1;
637 tag = get_be32(pb) & 0xffffff00;
639 if (tag == MKBETAG('C', 'W', 'S', 0))
641 av_log(s, AV_LOG_ERROR, "Compressed SWF format not supported\n");
644 if (tag != MKBETAG('F', 'W', 'S', 0))
647 /* skip rectangle size */
648 nbits = get_byte(pb) >> 3;
649 len = (4 * nbits - 3 + 7) / 8;
651 swf->frame_rate = get_le16(pb); /* 8.8 fixed */
652 get_le16(pb); /* frame count */
654 swf->samples_per_frame = 0;
657 offset_t tag_offset = url_ftell(pb);
658 tag = get_swf_tag(pb, &len);
659 if (tag < 0 || tag == TAG_VIDEOFRAME || tag == TAG_STREAMBLOCK) {
660 url_fseek(pb, frame_offset == -1 ? tag_offset : frame_offset, SEEK_SET);
663 if ( tag == TAG_VIDEOSTREAM && !vst) {
664 int ch_id = get_le16(pb);
670 vst = av_new_stream(s, ch_id);
671 vst->codec->codec_type = CODEC_TYPE_VIDEO;
672 vst->codec->codec_id = codec_get_id(swf_codec_tags, get_byte(pb));
673 } else if ( ( tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2 ) && !ast) {
674 /* streaming found */
675 int sample_rate_code;
678 swf->samples_per_frame = get_le16(pb);
679 ast = av_new_stream(s, -1); /* -1 to avoid clash with video stream ch_id */
680 swf->audio_stream_index = ast->index;
681 ast->codec->channels = 1 + (v&1);
682 ast->codec->codec_type = CODEC_TYPE_AUDIO;
683 ast->codec->codec_id = codec_get_id(swf_audio_codec_tags, (v>>4) & 15);
684 ast->need_parsing = AVSTREAM_PARSE_FULL;
685 sample_rate_code= (v>>2) & 3;
686 if (!sample_rate_code)
688 ast->codec->sample_rate = 11025 << (sample_rate_code-1);
689 av_set_pts_info(ast, 64, 1, ast->codec->sample_rate);
693 } else if (tag == TAG_JPEG2 && !vst) {
694 vst = av_new_stream(s, -2); /* -2 to avoid clash with video stream and audio stream */
695 vst->codec->codec_type = CODEC_TYPE_VIDEO;
696 vst->codec->codec_id = CODEC_ID_MJPEG;
698 frame_offset = tag_offset;
704 av_set_pts_info(vst, 64, 256, swf->frame_rate);
708 static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
710 SWFContext *swf = s->priv_data;
711 ByteIOContext *pb = &s->pb;
713 int tag, len, i, frame;
716 tag = get_swf_tag(pb, &len);
719 if (tag == TAG_VIDEOFRAME) {
720 int ch_id = get_le16(pb);
722 for( i=0; i<s->nb_streams; i++ ) {
724 if (st->codec->codec_type == CODEC_TYPE_VIDEO && st->id == ch_id) {
725 frame = get_le16(pb);
726 av_get_packet(pb, pkt, len-2);
728 pkt->stream_index = st->index;
732 } else if (tag == TAG_STREAMBLOCK) {
733 st = s->streams[swf->audio_stream_index];
734 if (st->codec->codec_id == CODEC_ID_MP3) {
736 av_get_packet(pb, pkt, len-4);
737 } else { // ADPCM, PCM
738 av_get_packet(pb, pkt, len);
740 pkt->stream_index = st->index;
742 } else if (tag == TAG_JPEG2) {
743 for (i=0; i<s->nb_streams; i++) {
746 get_le16(pb); /* BITMAP_ID */
747 av_new_packet(pkt, len-2);
748 get_buffer(pb, pkt->data, 4);
749 if (AV_RB32(pkt->data) == 0xffd8ffd9) {
750 /* old SWF files containing SOI/EOI as data start */
752 get_buffer(pb, pkt->data, pkt->size);
754 get_buffer(pb, pkt->data + 4, pkt->size - 4);
756 pkt->stream_index = st->index;
766 static int swf_read_close(AVFormatContext *s)
771 #ifdef CONFIG_SWF_DEMUXER
772 AVInputFormat swf_demuxer = {
782 #ifdef CONFIG_SWF_MUXER
783 AVOutputFormat swf_muxer = {
786 "application/x-shockwave-flash",