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;
70 int video_frame_number;
74 uint8_t audio_fifo[AUDIO_FIFO_SIZE];
83 static const AVCodecTag swf_codec_tags[] = {
84 {CODEC_ID_FLV1, 0x02},
85 {CODEC_ID_VP6F, 0x04},
89 static const AVCodecTag swf_audio_codec_tags[] = {
90 {CODEC_ID_PCM_S16LE, 0x00},
91 {CODEC_ID_ADPCM_SWF, 0x01},
93 {CODEC_ID_PCM_S16LE, 0x03},
94 //{CODEC_ID_NELLYMOSER, 0x06},
99 static void put_swf_tag(AVFormatContext *s, int tag)
101 SWFContext *swf = s->priv_data;
102 ByteIOContext *pb = &s->pb;
104 swf->tag_pos = url_ftell(pb);
106 /* reserve some room for the tag */
107 if (tag & TAG_LONG) {
115 static void put_swf_end_tag(AVFormatContext *s)
117 SWFContext *swf = s->priv_data;
118 ByteIOContext *pb = &s->pb;
123 tag_len = pos - swf->tag_pos - 2;
125 url_fseek(pb, swf->tag_pos, SEEK_SET);
126 if (tag & TAG_LONG) {
128 put_le16(pb, (tag << 6) | 0x3f);
129 put_le32(pb, tag_len - 4);
131 assert(tag_len < 0x3f);
132 put_le16(pb, (tag << 6) | tag_len);
134 url_fseek(pb, pos, SEEK_SET);
137 static inline void max_nbits(int *nbits_ptr, int val)
153 static void put_swf_rect(ByteIOContext *pb,
154 int xmin, int xmax, int ymin, int ymax)
160 init_put_bits(&p, buf, sizeof(buf));
163 max_nbits(&nbits, xmin);
164 max_nbits(&nbits, xmax);
165 max_nbits(&nbits, ymin);
166 max_nbits(&nbits, ymax);
167 mask = (1 << nbits) - 1;
170 put_bits(&p, 5, nbits);
171 put_bits(&p, nbits, xmin & mask);
172 put_bits(&p, nbits, xmax & mask);
173 put_bits(&p, nbits, ymin & mask);
174 put_bits(&p, nbits, ymax & mask);
177 put_buffer(pb, buf, pbBufPtr(&p) - p.buf);
180 static void put_swf_line_edge(PutBitContext *pb, int dx, int dy)
184 put_bits(pb, 1, 1); /* edge */
185 put_bits(pb, 1, 1); /* line select */
187 max_nbits(&nbits, dx);
188 max_nbits(&nbits, dy);
190 mask = (1 << nbits) - 1;
191 put_bits(pb, 4, nbits - 2); /* 16 bits precision */
195 put_bits(pb, nbits, dy & mask);
196 } else if (dy == 0) {
199 put_bits(pb, nbits, dx & mask);
202 put_bits(pb, nbits, dx & mask);
203 put_bits(pb, nbits, dy & mask);
210 static void put_swf_matrix(ByteIOContext *pb,
211 int a, int b, int c, int d, int tx, int ty)
217 init_put_bits(&p, buf, sizeof(buf));
219 put_bits(&p, 1, 1); /* a, d present */
221 max_nbits(&nbits, a);
222 max_nbits(&nbits, d);
223 put_bits(&p, 5, nbits); /* nb bits */
224 put_bits(&p, nbits, a);
225 put_bits(&p, nbits, d);
227 put_bits(&p, 1, 1); /* b, c present */
229 max_nbits(&nbits, c);
230 max_nbits(&nbits, b);
231 put_bits(&p, 5, nbits); /* nb bits */
232 put_bits(&p, nbits, c);
233 put_bits(&p, nbits, b);
236 max_nbits(&nbits, tx);
237 max_nbits(&nbits, ty);
238 put_bits(&p, 5, nbits); /* nb bits */
239 put_bits(&p, nbits, tx);
240 put_bits(&p, nbits, ty);
243 put_buffer(pb, buf, pbBufPtr(&p) - p.buf);
247 static int swf_write_header(AVFormatContext *s)
249 SWFContext *swf = s->priv_data;
250 ByteIOContext *pb = &s->pb;
251 AVCodecContext *enc, *audio_enc, *video_enc;
254 int i, width, height, rate, rate_base;
256 swf->audio_in_pos = 0;
257 swf->audio_out_pos = 0;
259 swf->sound_samples = 0;
260 swf->video_samples = 0;
261 swf->swf_frame_number = 0;
262 swf->video_frame_number = 0;
266 for(i=0;i<s->nb_streams;i++) {
267 enc = s->streams[i]->codec;
268 if (enc->codec_type == CODEC_TYPE_AUDIO) {
269 if (enc->codec_id == CODEC_ID_MP3) {
270 if (!enc->frame_size) {
271 av_log(s, AV_LOG_ERROR, "audio frame size not set\n");
276 av_log(enc, AV_LOG_ERROR, "SWF only supports MP3\n");
280 if ( enc->codec_id == CODEC_ID_VP6F ||
281 enc->codec_id == CODEC_ID_FLV1 ||
282 enc->codec_id == CODEC_ID_MJPEG ) {
285 av_log(enc, AV_LOG_ERROR, "SWF only supports VP6, FLV1 and MJPEG\n");
292 /* currenty, cannot work correctly if audio only */
299 swf->video_type = video_enc->codec_id;
300 width = video_enc->width;
301 height = video_enc->height;
302 rate = video_enc->time_base.den;
303 rate_base = video_enc->time_base.num;
308 swf->samples_per_frame = ( 44100. * rate_base ) / rate;
310 swf->audio_type = audio_enc->codec_id;
311 swf->samples_per_frame = ( ( audio_enc->sample_rate ) * rate_base ) / rate;
315 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 /* define a shape with the jpeg inside */
331 if ( video_enc && (video_enc->codec_id == CODEC_ID_VP6F ||
332 video_enc->codec_id == CODEC_ID_FLV1 )) {
333 } else if ( video_enc && video_enc->codec_id == CODEC_ID_MJPEG ) {
334 put_swf_tag(s, TAG_DEFINESHAPE);
336 put_le16(pb, SHAPE_ID); /* ID of shape */
337 /* bounding rectangle */
338 put_swf_rect(pb, 0, width, 0, height);
340 put_byte(pb, 1); /* one fill style */
341 put_byte(pb, 0x41); /* clipped bitmap fill */
342 put_le16(pb, BITMAP_ID); /* bitmap ID */
343 /* position of the bitmap */
344 put_swf_matrix(pb, (int)(1.0 * (1 << FRAC_BITS)), 0,
345 0, (int)(1.0 * (1 << FRAC_BITS)), 0, 0);
346 put_byte(pb, 0); /* no line style */
349 init_put_bits(&p, buf1, sizeof(buf1));
350 put_bits(&p, 4, 1); /* one fill bit */
351 put_bits(&p, 4, 0); /* zero line bit */
353 put_bits(&p, 1, 0); /* not an edge */
354 put_bits(&p, 5, FLAG_MOVETO | FLAG_SETFILL0);
355 put_bits(&p, 5, 1); /* nbits */
356 put_bits(&p, 1, 0); /* X */
357 put_bits(&p, 1, 0); /* Y */
358 put_bits(&p, 1, 1); /* set fill style 1 */
360 /* draw the rectangle ! */
361 put_swf_line_edge(&p, width, 0);
362 put_swf_line_edge(&p, 0, height);
363 put_swf_line_edge(&p, -width, 0);
364 put_swf_line_edge(&p, 0, -height);
367 put_bits(&p, 1, 0); /* not an edge */
371 put_buffer(pb, buf1, pbBufPtr(&p) - p.buf);
376 if (audio_enc && audio_enc->codec_id == CODEC_ID_MP3 ) {
380 put_swf_tag(s, TAG_STREAMHEAD2);
383 switch(audio_enc->sample_rate) {
395 av_log(s, AV_LOG_ERROR, "swf doesnt support that sample rate, choose from (44100, 22050, 11025)\n");
396 av_free(swf->audio_fifo);
399 v |= 0x02; /* 16 bit playback */
400 if (audio_enc->channels == 2)
401 v |= 0x01; /* stereo playback */
403 v |= 0x20; /* mp3 compressed */
405 put_le16(&s->pb, swf->samples_per_frame); /* avg samples per frame */
411 put_flush_packet(&s->pb);
415 static int swf_write_video(AVFormatContext *s,
416 AVCodecContext *enc, const uint8_t *buf, int size)
418 SWFContext *swf = s->priv_data;
419 ByteIOContext *pb = &s->pb;
421 /* Flash Player limit */
422 if ( swf->swf_frame_number == 16000 ) {
423 av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
426 if ( swf->video_type == CODEC_ID_VP6F ||
427 swf->video_type == CODEC_ID_FLV1 ) {
428 if ( swf->video_frame_number == 0 ) {
429 /* create a new video object */
430 put_swf_tag(s, TAG_VIDEOSTREAM);
431 put_le16(pb, VIDEO_ID);
432 put_le16(pb, 15000 ); /* hard flash player limit */
433 put_le16(pb, enc->width);
434 put_le16(pb, enc->height);
436 put_byte(pb,codec_get_tag(swf_codec_tags,swf->video_type));
439 /* place the video object for the first time */
440 put_swf_tag(s, TAG_PLACEOBJECT2);
443 put_le16(pb, VIDEO_ID);
444 put_swf_matrix(pb, 1 << FRAC_BITS, 0, 0, 1 << FRAC_BITS, 0, 0);
445 put_le16(pb, swf->video_frame_number );
454 /* mark the character for update */
455 put_swf_tag(s, TAG_PLACEOBJECT2);
458 put_le16(pb, swf->video_frame_number );
462 /* set video frame data */
463 put_swf_tag(s, TAG_VIDEOFRAME | TAG_LONG);
464 put_le16(pb, VIDEO_ID);
465 put_le16(pb, swf->video_frame_number++ );
466 put_buffer(pb, buf, size);
468 } else if ( swf->video_type == CODEC_ID_MJPEG ) {
469 if (swf->swf_frame_number > 0) {
470 /* remove the shape */
471 put_swf_tag(s, TAG_REMOVEOBJECT);
472 put_le16(pb, SHAPE_ID); /* shape ID */
473 put_le16(pb, 1); /* depth */
476 /* free the bitmap */
477 put_swf_tag(s, TAG_FREECHARACTER);
478 put_le16(pb, BITMAP_ID);
482 put_swf_tag(s, TAG_JPEG2 | TAG_LONG);
484 put_le16(pb, BITMAP_ID); /* ID of the image */
486 /* a dummy jpeg header seems to be required */
491 /* write the jpeg image */
492 put_buffer(pb, buf, size);
498 put_swf_tag(s, TAG_PLACEOBJECT);
499 put_le16(pb, SHAPE_ID); /* shape ID */
500 put_le16(pb, 1); /* depth */
501 put_swf_matrix(pb, 20 << FRAC_BITS, 0, 0, 20 << FRAC_BITS, 0, 0);
507 swf->swf_frame_number ++;
509 swf->video_samples += swf->samples_per_frame;
511 /* streaming sound always should be placed just before showframe tags */
512 if (swf->audio_type && swf->audio_in_pos) {
513 put_swf_tag(s, TAG_STREAMBLOCK | TAG_LONG);
514 put_le16(pb, swf->sound_samples);
515 put_le16(pb, 0); // seek samples
516 put_buffer(pb, swf->audio_fifo, swf->audio_in_pos);
520 swf->sound_samples = 0;
521 swf->audio_in_pos = 0;
524 /* output the frame */
525 put_swf_tag(s, TAG_SHOWFRAME);
528 put_flush_packet(&s->pb);
533 static int swf_write_audio(AVFormatContext *s,
534 AVCodecContext *enc, const uint8_t *buf, int size)
536 SWFContext *swf = s->priv_data;
538 /* Flash Player limit */
539 if ( swf->swf_frame_number == 16000 ) {
540 av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
543 if (swf->audio_in_pos + size >= AUDIO_FIFO_SIZE) {
544 av_log(s, AV_LOG_ERROR, "audio fifo too small to mux audio essence\n");
548 memcpy(swf->audio_fifo + swf->audio_in_pos, buf, size);
549 swf->audio_in_pos += size;
550 swf->sound_samples += enc->frame_size;
552 /* if audio only stream make sure we add swf frames */
553 if ( swf->video_type == 0 ) {
554 swf_write_video(s, enc, 0, 0);
560 static int swf_write_packet(AVFormatContext *s, AVPacket *pkt)
562 AVCodecContext *codec = s->streams[pkt->stream_index]->codec;
563 if (codec->codec_type == CODEC_TYPE_AUDIO)
564 return swf_write_audio(s, codec, pkt->data, pkt->size);
566 return swf_write_video(s, codec, pkt->data, pkt->size);
569 static int swf_write_trailer(AVFormatContext *s)
571 SWFContext *swf = s->priv_data;
572 ByteIOContext *pb = &s->pb;
573 AVCodecContext *enc, *video_enc;
577 for(i=0;i<s->nb_streams;i++) {
578 enc = s->streams[i]->codec;
579 if (enc->codec_type == CODEC_TYPE_VIDEO)
583 put_swf_tag(s, TAG_END);
586 put_flush_packet(&s->pb);
588 /* patch file size and number of frames if not streamed */
589 if (!url_is_streamed(&s->pb) && video_enc) {
590 file_size = url_ftell(pb);
591 url_fseek(pb, 4, SEEK_SET);
592 put_le32(pb, file_size);
593 url_fseek(pb, swf->duration_pos, SEEK_SET);
594 put_le16(pb, video_enc->frame_number);
595 url_fseek(pb, file_size, SEEK_SET);
599 #endif //CONFIG_MUXERS
601 /*********************************************/
602 /* Extract FLV encoded frame and MP3 from swf
603 Note that the detection of the real frame
604 is inaccurate at this point as it can be
605 quite tricky to determine, you almost certainly
606 will get a bad audio/video sync */
608 static int get_swf_tag(ByteIOContext *pb, int *len_ptr)
621 // av_log(NULL, AV_LOG_DEBUG, "Tag: %d - Len: %d\n", tag, len);
627 static int swf_probe(AVProbeData *p)
629 /* check file header */
630 if (p->buf_size <= 16)
632 if ((p->buf[0] == 'F' || p->buf[0] == 'C') && p->buf[1] == 'W' &&
634 return AVPROBE_SCORE_MAX;
639 static int swf_read_header(AVFormatContext *s, AVFormatParameters *ap)
641 SWFContext *swf = s->priv_data;
642 ByteIOContext *pb = &s->pb;
643 int nbits, len, frame_rate, tag, v;
644 offset_t frame_offset = -1;
648 tag = get_be32(pb) & 0xffffff00;
650 if (tag == MKBETAG('C', 'W', 'S', 0))
652 av_log(s, AV_LOG_ERROR, "Compressed SWF format not supported\n");
655 if (tag != MKBETAG('F', 'W', 'S', 0))
658 /* skip rectangle size */
659 nbits = get_byte(pb) >> 3;
660 len = (4 * nbits - 3 + 7) / 8;
662 frame_rate = get_le16(pb);
663 get_le16(pb); /* frame count */
665 /* The Flash Player converts 8.8 frame rates
666 to milliseconds internally. Do the same to get
667 a correct framerate */
668 swf->ms_per_frame = ( 1000 * 256 ) / frame_rate;
669 swf->samples_per_frame = 0;
672 offset_t tag_offset = url_ftell(pb);
673 tag = get_swf_tag(pb, &len);
674 if (tag < 0 || tag == TAG_VIDEOFRAME || tag == TAG_STREAMBLOCK) {
675 url_fseek(pb, frame_offset == -1 ? tag_offset : frame_offset, SEEK_SET);
678 if ( tag == TAG_VIDEOSTREAM && !vst) {
679 int ch_id = get_le16(pb);
685 vst = av_new_stream(s, ch_id);
686 vst->codec->codec_type = CODEC_TYPE_VIDEO;
687 vst->codec->codec_id = codec_get_id(swf_codec_tags, get_byte(pb));
688 } else if ( ( tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2 ) && !ast) {
689 /* streaming found */
690 int sample_rate_code;
693 swf->samples_per_frame = get_le16(pb);
694 ast = av_new_stream(s, -1); /* -1 to avoid clash with video stream ch_id */
695 av_set_pts_info(ast, 24, 1, 1000); /* 24 bit pts in ms */
696 swf->audio_stream_index = ast->index;
697 ast->codec->channels = 1 + (v&1);
698 ast->codec->codec_type = CODEC_TYPE_AUDIO;
699 ast->codec->codec_id = codec_get_id(swf_audio_codec_tags, (v>>4) & 15);
700 ast->need_parsing = 1;
701 sample_rate_code= (v>>2) & 3;
702 if (!sample_rate_code)
704 ast->codec->sample_rate = 11025 << (sample_rate_code-1);
708 } else if (tag == TAG_JPEG2 && !vst) {
709 vst = av_new_stream(s, -2); /* -2 to avoid clash with video stream and audio stream */
710 vst->codec->codec_type = CODEC_TYPE_VIDEO;
711 vst->codec->codec_id = CODEC_ID_MJPEG;
713 frame_offset = tag_offset;
719 av_set_pts_info(vst, 24, 1, 1000); /* 24 bit pts in ms */
720 if (swf->ms_per_frame) {
721 vst->codec->time_base.den = 1000. / swf->ms_per_frame;
722 vst->codec->time_base.num = 1;
728 static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
730 SWFContext *swf = s->priv_data;
731 ByteIOContext *pb = &s->pb;
733 int tag, len, i, frame;
736 tag = get_swf_tag(pb, &len);
739 if (tag == TAG_VIDEOFRAME) {
740 int ch_id = get_le16(pb);
742 for( i=0; i<s->nb_streams; i++ ) {
744 if (st->codec->codec_type == CODEC_TYPE_VIDEO && st->id == ch_id) {
745 frame = get_le16(pb);
746 av_get_packet(pb, pkt, len-2);
747 pkt->pts = frame * swf->ms_per_frame;
748 pkt->stream_index = st->index;
752 } else if (tag == TAG_STREAMBLOCK) {
753 st = s->streams[swf->audio_stream_index];
754 if (st->codec->codec_id == CODEC_ID_MP3) {
756 av_get_packet(pb, pkt, len-4);
757 } else { // ADPCM, PCM
758 av_get_packet(pb, pkt, len);
760 pkt->stream_index = st->index;
762 } else if (tag == TAG_JPEG2) {
763 for (i=0; i<s->nb_streams; i++) {
766 get_le16(pb); /* BITMAP_ID */
767 av_new_packet(pkt, len-2);
768 get_buffer(pb, pkt->data, 4);
769 if (AV_RB32(pkt->data) == 0xffd8ffd9) {
770 /* old SWF files containing SOI/EOI as data start */
772 get_buffer(pb, pkt->data, pkt->size);
774 get_buffer(pb, pkt->data + 4, pkt->size - 4);
776 pkt->stream_index = st->index;
786 static int swf_read_close(AVFormatContext *s)
791 #ifdef CONFIG_SWF_DEMUXER
792 AVInputFormat swf_demuxer = {
802 #ifdef CONFIG_SWF_MUXER
803 AVOutputFormat swf_muxer = {
806 "application/x-shockwave-flash",