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(enc, AV_LOG_ERROR, "SWF 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(enc, AV_LOG_ERROR, "SWF 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");
390 av_free(swf->audio_fifo);
393 v |= 0x02; /* 16 bit playback */
394 if (audio_enc->channels == 2)
395 v |= 0x01; /* stereo playback */
397 v |= 0x20; /* mp3 compressed */
399 put_le16(&s->pb, swf->samples_per_frame); /* avg samples per frame */
405 put_flush_packet(&s->pb);
409 static int swf_write_video(AVFormatContext *s,
410 AVCodecContext *enc, const uint8_t *buf, int size)
412 SWFContext *swf = s->priv_data;
413 ByteIOContext *pb = &s->pb;
415 /* Flash Player limit */
416 if ( swf->swf_frame_number == 16000 ) {
417 av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
420 if ( swf->video_type == CODEC_ID_VP6F ||
421 swf->video_type == CODEC_ID_FLV1 ) {
422 if ( swf->video_frame_number == 0 ) {
423 /* create a new video object */
424 put_swf_tag(s, TAG_VIDEOSTREAM);
425 put_le16(pb, VIDEO_ID);
426 put_le16(pb, 15000 ); /* hard flash player limit */
427 put_le16(pb, enc->width);
428 put_le16(pb, enc->height);
430 put_byte(pb,codec_get_tag(swf_codec_tags,swf->video_type));
433 /* place the video object for the first time */
434 put_swf_tag(s, TAG_PLACEOBJECT2);
437 put_le16(pb, VIDEO_ID);
438 put_swf_matrix(pb, 1 << FRAC_BITS, 0, 0, 1 << FRAC_BITS, 0, 0);
439 put_le16(pb, swf->video_frame_number );
448 /* mark the character for update */
449 put_swf_tag(s, TAG_PLACEOBJECT2);
452 put_le16(pb, swf->video_frame_number );
456 /* set video frame data */
457 put_swf_tag(s, TAG_VIDEOFRAME | TAG_LONG);
458 put_le16(pb, VIDEO_ID);
459 put_le16(pb, swf->video_frame_number++ );
460 put_buffer(pb, buf, size);
462 } else if ( swf->video_type == CODEC_ID_MJPEG ) {
463 if (swf->swf_frame_number > 0) {
464 /* remove the shape */
465 put_swf_tag(s, TAG_REMOVEOBJECT);
466 put_le16(pb, SHAPE_ID); /* shape ID */
467 put_le16(pb, 1); /* depth */
470 /* free the bitmap */
471 put_swf_tag(s, TAG_FREECHARACTER);
472 put_le16(pb, BITMAP_ID);
476 put_swf_tag(s, TAG_JPEG2 | TAG_LONG);
478 put_le16(pb, BITMAP_ID); /* ID of the image */
480 /* a dummy jpeg header seems to be required */
485 /* write the jpeg image */
486 put_buffer(pb, buf, size);
492 put_swf_tag(s, TAG_PLACEOBJECT);
493 put_le16(pb, SHAPE_ID); /* shape ID */
494 put_le16(pb, 1); /* depth */
495 put_swf_matrix(pb, 20 << FRAC_BITS, 0, 0, 20 << FRAC_BITS, 0, 0);
501 swf->swf_frame_number ++;
503 /* streaming sound always should be placed just before showframe tags */
504 if (swf->audio_type && swf->audio_in_pos) {
505 put_swf_tag(s, TAG_STREAMBLOCK | TAG_LONG);
506 put_le16(pb, swf->sound_samples);
507 put_le16(pb, 0); // seek samples
508 put_buffer(pb, swf->audio_fifo, swf->audio_in_pos);
512 swf->sound_samples = 0;
513 swf->audio_in_pos = 0;
516 /* output the frame */
517 put_swf_tag(s, TAG_SHOWFRAME);
520 put_flush_packet(&s->pb);
525 static int swf_write_audio(AVFormatContext *s,
526 AVCodecContext *enc, const uint8_t *buf, int size)
528 SWFContext *swf = s->priv_data;
530 /* Flash Player limit */
531 if ( swf->swf_frame_number == 16000 ) {
532 av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
535 if (swf->audio_in_pos + size >= AUDIO_FIFO_SIZE) {
536 av_log(s, AV_LOG_ERROR, "audio fifo too small to mux audio essence\n");
540 memcpy(swf->audio_fifo + swf->audio_in_pos, buf, size);
541 swf->audio_in_pos += size;
542 swf->sound_samples += enc->frame_size;
544 /* if audio only stream make sure we add swf frames */
545 if ( swf->video_type == 0 ) {
546 swf_write_video(s, enc, 0, 0);
552 static int swf_write_packet(AVFormatContext *s, AVPacket *pkt)
554 AVCodecContext *codec = s->streams[pkt->stream_index]->codec;
555 if (codec->codec_type == CODEC_TYPE_AUDIO)
556 return swf_write_audio(s, codec, pkt->data, pkt->size);
558 return swf_write_video(s, codec, pkt->data, pkt->size);
561 static int swf_write_trailer(AVFormatContext *s)
563 SWFContext *swf = s->priv_data;
564 ByteIOContext *pb = &s->pb;
565 AVCodecContext *enc, *video_enc;
569 for(i=0;i<s->nb_streams;i++) {
570 enc = s->streams[i]->codec;
571 if (enc->codec_type == CODEC_TYPE_VIDEO)
575 put_swf_tag(s, TAG_END);
578 put_flush_packet(&s->pb);
580 /* patch file size and number of frames if not streamed */
581 if (!url_is_streamed(&s->pb) && video_enc) {
582 file_size = url_ftell(pb);
583 url_fseek(pb, 4, SEEK_SET);
584 put_le32(pb, file_size);
585 url_fseek(pb, swf->duration_pos, SEEK_SET);
586 put_le16(pb, video_enc->frame_number);
587 url_fseek(pb, file_size, SEEK_SET);
591 #endif //CONFIG_MUXERS
593 /*********************************************/
594 /* Extract FLV encoded frame and MP3 from swf
595 Note that the detection of the real frame
596 is inaccurate at this point as it can be
597 quite tricky to determine, you almost certainly
598 will get a bad audio/video sync */
600 static int get_swf_tag(ByteIOContext *pb, int *len_ptr)
613 // av_log(NULL, AV_LOG_DEBUG, "Tag: %d - Len: %d\n", tag, len);
619 static int swf_probe(AVProbeData *p)
621 /* check file header */
622 if (p->buf_size <= 16)
624 if ((p->buf[0] == 'F' || p->buf[0] == 'C') && p->buf[1] == 'W' &&
626 return AVPROBE_SCORE_MAX;
631 static int swf_read_header(AVFormatContext *s, AVFormatParameters *ap)
633 SWFContext *swf = s->priv_data;
634 ByteIOContext *pb = &s->pb;
635 int nbits, len, frame_rate, tag, v;
636 offset_t frame_offset = -1;
640 tag = get_be32(pb) & 0xffffff00;
642 if (tag == MKBETAG('C', 'W', 'S', 0))
644 av_log(s, AV_LOG_ERROR, "Compressed SWF format not supported\n");
647 if (tag != MKBETAG('F', 'W', 'S', 0))
650 /* skip rectangle size */
651 nbits = get_byte(pb) >> 3;
652 len = (4 * nbits - 3 + 7) / 8;
654 frame_rate = get_le16(pb);
655 get_le16(pb); /* frame count */
657 /* The Flash Player converts 8.8 frame rates
658 to milliseconds internally. Do the same to get
659 a correct framerate */
660 swf->ms_per_frame = ( 1000 * 256 ) / frame_rate;
661 swf->samples_per_frame = 0;
664 offset_t tag_offset = url_ftell(pb);
665 tag = get_swf_tag(pb, &len);
666 if (tag < 0 || tag == TAG_VIDEOFRAME || tag == TAG_STREAMBLOCK) {
667 url_fseek(pb, frame_offset == -1 ? tag_offset : frame_offset, SEEK_SET);
670 if ( tag == TAG_VIDEOSTREAM && !vst) {
671 int ch_id = get_le16(pb);
677 vst = av_new_stream(s, ch_id);
678 vst->codec->codec_type = CODEC_TYPE_VIDEO;
679 vst->codec->codec_id = codec_get_id(swf_codec_tags, get_byte(pb));
680 } else if ( ( tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2 ) && !ast) {
681 /* streaming found */
682 int sample_rate_code;
685 swf->samples_per_frame = get_le16(pb);
686 ast = av_new_stream(s, -1); /* -1 to avoid clash with video stream ch_id */
687 av_set_pts_info(ast, 24, 1, 1000); /* 24 bit pts in ms */
688 swf->audio_stream_index = ast->index;
689 ast->codec->channels = 1 + (v&1);
690 ast->codec->codec_type = CODEC_TYPE_AUDIO;
691 ast->codec->codec_id = codec_get_id(swf_audio_codec_tags, (v>>4) & 15);
692 ast->need_parsing = 1;
693 sample_rate_code= (v>>2) & 3;
694 if (!sample_rate_code)
696 ast->codec->sample_rate = 11025 << (sample_rate_code-1);
700 } else if (tag == TAG_JPEG2 && !vst) {
701 vst = av_new_stream(s, -2); /* -2 to avoid clash with video stream and audio stream */
702 vst->codec->codec_type = CODEC_TYPE_VIDEO;
703 vst->codec->codec_id = CODEC_ID_MJPEG;
705 frame_offset = tag_offset;
711 av_set_pts_info(vst, 24, 1, 1000); /* 24 bit pts in ms */
712 if (swf->ms_per_frame) {
713 vst->codec->time_base.den = 1000. / swf->ms_per_frame;
714 vst->codec->time_base.num = 1;
720 static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
722 SWFContext *swf = s->priv_data;
723 ByteIOContext *pb = &s->pb;
725 int tag, len, i, frame;
728 tag = get_swf_tag(pb, &len);
731 if (tag == TAG_VIDEOFRAME) {
732 int ch_id = get_le16(pb);
734 for( i=0; i<s->nb_streams; i++ ) {
736 if (st->codec->codec_type == CODEC_TYPE_VIDEO && st->id == ch_id) {
737 frame = get_le16(pb);
738 av_get_packet(pb, pkt, len-2);
739 pkt->pts = frame * swf->ms_per_frame;
740 pkt->stream_index = st->index;
744 } else if (tag == TAG_STREAMBLOCK) {
745 st = s->streams[swf->audio_stream_index];
746 if (st->codec->codec_id == CODEC_ID_MP3) {
748 av_get_packet(pb, pkt, len-4);
749 } else { // ADPCM, PCM
750 av_get_packet(pb, pkt, len);
752 pkt->stream_index = st->index;
754 } else if (tag == TAG_JPEG2) {
755 for (i=0; i<s->nb_streams; i++) {
758 get_le16(pb); /* BITMAP_ID */
759 av_new_packet(pkt, len-2);
760 get_buffer(pb, pkt->data, 4);
761 if (AV_RB32(pkt->data) == 0xffd8ffd9) {
762 /* old SWF files containing SOI/EOI as data start */
764 get_buffer(pb, pkt->data, pkt->size);
766 get_buffer(pb, pkt->data + 4, pkt->size - 4);
768 pkt->stream_index = st->index;
778 static int swf_read_close(AVFormatContext *s)
783 #ifdef CONFIG_SWF_DEMUXER
784 AVInputFormat swf_demuxer = {
794 #ifdef CONFIG_SWF_MUXER
795 AVOutputFormat swf_muxer = {
798 "application/x-shockwave-flash",