2 * Flash Compatible Streaming Format
3 * Copyright (c) 2000 Fabrice Bellard.
4 * Copyright (c) 2003 Tinic Uro.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include "bitstream.h"
23 /* should have a generic way to indicate probable size */
24 #define DUMMY_FILE_SIZE (100 * 1024 * 1024)
25 #define DUMMY_DURATION 600 /* in seconds */
28 #define TAG_SHOWFRAME 1
29 #define TAG_DEFINESHAPE 2
30 #define TAG_FREECHARACTER 3
31 #define TAG_PLACEOBJECT 4
32 #define TAG_REMOVEOBJECT 5
33 #define TAG_STREAMHEAD 18
34 #define TAG_STREAMBLOCK 19
36 #define TAG_PLACEOBJECT2 26
37 #define TAG_STREAMHEAD2 45
38 #define TAG_VIDEOSTREAM 60
39 #define TAG_VIDEOFRAME 61
41 #define TAG_LONG 0x100
43 /* flags for shape definition */
44 #define FLAG_MOVETO 0x01
45 #define FLAG_SETFILL0 0x02
46 #define FLAG_SETFILL1 0x04
48 #define SWF_VIDEO_CODEC_FLV1 0x02
50 #define AUDIO_FIFO_SIZE 65536
52 /* character id used */
62 offset_t duration_pos;
65 int samples_per_frame;
69 int video_frame_number;
83 static const int sSampleRates[3][4] = {
84 {44100, 48000, 32000, 0},
85 {22050, 24000, 16000, 0},
86 {11025, 12000, 8000, 0},
89 static const int sBitRates[2][3][15] = {
90 { { 0, 32, 64, 96,128,160,192,224,256,288,320,352,384,416,448},
91 { 0, 32, 48, 56, 64, 80, 96,112,128,160,192,224,256,320,384},
92 { 0, 32, 40, 48, 56, 64, 80, 96,112,128,160,192,224,256,320}
94 { { 0, 32, 48, 56, 64, 80, 96,112,128,144,160,176,192,224,256},
95 { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160},
96 { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160}
100 static const int sSamplesPerFrame[3][3] =
107 static const int sBitsPerSlot[3] = {
113 static int swf_mp3_info(void *data, int *byteSize, int *samplesPerFrame, int *sampleRate, int *isMono )
115 uint8_t *dataTmp = (uint8_t *)data;
116 uint32_t header = ( (uint32_t)dataTmp[0] << 24 ) | ( (uint32_t)dataTmp[1] << 16 ) | ( (uint32_t)dataTmp[2] << 8 ) | (uint32_t)dataTmp[3];
117 int layerID = 3 - ((header >> 17) & 0x03);
118 int bitRateID = ((header >> 12) & 0x0f);
119 int sampleRateID = ((header >> 10) & 0x03);
121 int bitsPerSlot = sBitsPerSlot[layerID];
122 int isPadded = ((header >> 9) & 0x01);
124 if ( (( header >> 21 ) & 0x7ff) != 0x7ff ) {
128 *isMono = ((header >> 6) & 0x03) == 0x03;
130 if ( (header >> 19 ) & 0x01 ) {
131 *sampleRate = sSampleRates[0][sampleRateID];
132 bitRate = sBitRates[0][layerID][bitRateID] * 1000;
133 *samplesPerFrame = sSamplesPerFrame[0][layerID];
135 if ( (header >> 20) & 0x01 ) {
136 *sampleRate = sSampleRates[1][sampleRateID];
137 bitRate = sBitRates[1][layerID][bitRateID] * 1000;
138 *samplesPerFrame = sSamplesPerFrame[1][layerID];
140 *sampleRate = sSampleRates[2][sampleRateID];
141 bitRate = sBitRates[1][layerID][bitRateID] * 1000;
142 *samplesPerFrame = sSamplesPerFrame[2][layerID];
146 *byteSize = ( ( ( ( *samplesPerFrame * (bitRate / bitsPerSlot) ) / *sampleRate ) + isPadded ) );
152 static void put_swf_tag(AVFormatContext *s, int tag)
154 SWFContext *swf = s->priv_data;
155 ByteIOContext *pb = &s->pb;
157 swf->tag_pos = url_ftell(pb);
159 /* reserve some room for the tag */
160 if (tag & TAG_LONG) {
168 static void put_swf_end_tag(AVFormatContext *s)
170 SWFContext *swf = s->priv_data;
171 ByteIOContext *pb = &s->pb;
176 tag_len = pos - swf->tag_pos - 2;
178 url_fseek(pb, swf->tag_pos, SEEK_SET);
179 if (tag & TAG_LONG) {
181 put_le16(pb, (tag << 6) | 0x3f);
182 put_le32(pb, tag_len - 4);
184 assert(tag_len < 0x3f);
185 put_le16(pb, (tag << 6) | tag_len);
187 url_fseek(pb, pos, SEEK_SET);
190 static inline void max_nbits(int *nbits_ptr, int val)
206 static void put_swf_rect(ByteIOContext *pb,
207 int xmin, int xmax, int ymin, int ymax)
213 init_put_bits(&p, buf, sizeof(buf));
216 max_nbits(&nbits, xmin);
217 max_nbits(&nbits, xmax);
218 max_nbits(&nbits, ymin);
219 max_nbits(&nbits, ymax);
220 mask = (1 << nbits) - 1;
223 put_bits(&p, 5, nbits);
224 put_bits(&p, nbits, xmin & mask);
225 put_bits(&p, nbits, xmax & mask);
226 put_bits(&p, nbits, ymin & mask);
227 put_bits(&p, nbits, ymax & mask);
230 put_buffer(pb, buf, pbBufPtr(&p) - p.buf);
233 static void put_swf_line_edge(PutBitContext *pb, int dx, int dy)
237 put_bits(pb, 1, 1); /* edge */
238 put_bits(pb, 1, 1); /* line select */
240 max_nbits(&nbits, dx);
241 max_nbits(&nbits, dy);
243 mask = (1 << nbits) - 1;
244 put_bits(pb, 4, nbits - 2); /* 16 bits precision */
248 put_bits(pb, nbits, dy & mask);
249 } else if (dy == 0) {
252 put_bits(pb, nbits, dx & mask);
255 put_bits(pb, nbits, dx & mask);
256 put_bits(pb, nbits, dy & mask);
263 static void put_swf_matrix(ByteIOContext *pb,
264 int a, int b, int c, int d, int tx, int ty)
270 init_put_bits(&p, buf, sizeof(buf));
272 put_bits(&p, 1, 1); /* a, d present */
274 max_nbits(&nbits, a);
275 max_nbits(&nbits, d);
276 put_bits(&p, 5, nbits); /* nb bits */
277 put_bits(&p, nbits, a);
278 put_bits(&p, nbits, d);
280 put_bits(&p, 1, 1); /* b, c present */
282 max_nbits(&nbits, c);
283 max_nbits(&nbits, b);
284 put_bits(&p, 5, nbits); /* nb bits */
285 put_bits(&p, nbits, c);
286 put_bits(&p, nbits, b);
289 max_nbits(&nbits, tx);
290 max_nbits(&nbits, ty);
291 put_bits(&p, 5, nbits); /* nb bits */
292 put_bits(&p, nbits, tx);
293 put_bits(&p, nbits, ty);
296 put_buffer(pb, buf, pbBufPtr(&p) - p.buf);
300 static int swf_write_header(AVFormatContext *s)
303 ByteIOContext *pb = &s->pb;
304 AVCodecContext *enc, *audio_enc, *video_enc;
307 int i, width, height, rate, rate_base;
309 swf = av_malloc(sizeof(SWFContext));
315 swf->audio_in_pos = 0;
316 swf->audio_out_pos = 0;
318 swf->audio_fifo = av_malloc(AUDIO_FIFO_SIZE);
319 swf->sound_samples = 0;
320 swf->video_samples = 0;
321 swf->swf_frame_number = 0;
322 swf->video_frame_number = 0;
326 for(i=0;i<s->nb_streams;i++) {
327 enc = s->streams[i]->codec;
328 if (enc->codec_type == CODEC_TYPE_AUDIO)
331 if ( enc->codec_id == CODEC_ID_FLV1 || enc->codec_id == CODEC_ID_MJPEG ) {
334 av_log(enc, AV_LOG_ERROR, "SWF only supports FLV1 and MJPEG\n");
341 /* currenty, cannot work correctly if audio only */
348 swf->video_type = video_enc->codec_id;
349 width = video_enc->width;
350 height = video_enc->height;
351 rate = video_enc->time_base.den;
352 rate_base = video_enc->time_base.num;
357 swf->samples_per_frame = ( 44100. * rate_base ) / rate;
359 swf->audio_type = audio_enc->codec_id;
360 swf->samples_per_frame = ( ( audio_enc->sample_rate ) * rate_base ) / rate;
364 if ( video_enc && video_enc->codec_id == CODEC_ID_FLV1 ) {
365 put_byte(pb, 6); /* version (version 6 and above support FLV1 codec) */
367 put_byte(pb, 4); /* version (should use 4 for mpeg audio support) */
369 put_le32(pb, DUMMY_FILE_SIZE); /* dummy size
370 (will be patched if not streamed) */
372 put_swf_rect(pb, 0, width * 20, 0, height * 20);
373 put_le16(pb, (rate * 256) / rate_base); /* frame rate */
374 swf->duration_pos = url_ftell(pb);
375 put_le16(pb, (uint16_t)(DUMMY_DURATION * (int64_t)rate / rate_base)); /* frame count */
377 /* define a shape with the jpeg inside */
378 if ( video_enc && video_enc->codec_id == CODEC_ID_FLV1 ) {
379 } else if ( video_enc && video_enc->codec_id == CODEC_ID_MJPEG ) {
380 put_swf_tag(s, TAG_DEFINESHAPE);
382 put_le16(pb, SHAPE_ID); /* ID of shape */
383 /* bounding rectangle */
384 put_swf_rect(pb, 0, width, 0, height);
386 put_byte(pb, 1); /* one fill style */
387 put_byte(pb, 0x41); /* clipped bitmap fill */
388 put_le16(pb, BITMAP_ID); /* bitmap ID */
389 /* position of the bitmap */
390 put_swf_matrix(pb, (int)(1.0 * (1 << FRAC_BITS)), 0,
391 0, (int)(1.0 * (1 << FRAC_BITS)), 0, 0);
392 put_byte(pb, 0); /* no line style */
395 init_put_bits(&p, buf1, sizeof(buf1));
396 put_bits(&p, 4, 1); /* one fill bit */
397 put_bits(&p, 4, 0); /* zero line bit */
399 put_bits(&p, 1, 0); /* not an edge */
400 put_bits(&p, 5, FLAG_MOVETO | FLAG_SETFILL0);
401 put_bits(&p, 5, 1); /* nbits */
402 put_bits(&p, 1, 0); /* X */
403 put_bits(&p, 1, 0); /* Y */
404 put_bits(&p, 1, 1); /* set fill style 1 */
406 /* draw the rectangle ! */
407 put_swf_line_edge(&p, width, 0);
408 put_swf_line_edge(&p, 0, height);
409 put_swf_line_edge(&p, -width, 0);
410 put_swf_line_edge(&p, 0, -height);
413 put_bits(&p, 1, 0); /* not an edge */
417 put_buffer(pb, buf1, pbBufPtr(&p) - p.buf);
422 if (audio_enc && audio_enc->codec_id == CODEC_ID_MP3 ) {
426 put_swf_tag(s, TAG_STREAMHEAD2);
429 switch(audio_enc->sample_rate) {
441 av_free(swf->audio_fifo);
445 v |= 0x02; /* 16 bit playback */
446 if (audio_enc->channels == 2)
447 v |= 0x01; /* stereo playback */
449 v |= 0x20; /* mp3 compressed */
451 put_le16(&s->pb, swf->samples_per_frame); /* avg samples per frame */
457 put_flush_packet(&s->pb);
461 static int swf_write_video(AVFormatContext *s,
462 AVCodecContext *enc, const uint8_t *buf, int size)
464 SWFContext *swf = s->priv_data;
465 ByteIOContext *pb = &s->pb;
470 /* Flash Player limit */
471 if ( swf->swf_frame_number == 16000 ) {
472 av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
475 if ( swf->audio_type ) {
476 /* Prescan audio data for this swf frame */
477 retry_swf_audio_packet:
478 if ( ( swf->audio_size-outSize ) >= 4 ) {
479 int mp3FrameSize = 0;
480 int mp3SampleRate = 0;
482 int mp3SamplesPerFrame = 0;
484 /* copy out mp3 header from ring buffer */
486 for (c=0; c<4; c++) {
487 header[c] = swf->audio_fifo[(swf->audio_in_pos+outSize+c) % AUDIO_FIFO_SIZE];
490 if ( swf_mp3_info(header,&mp3FrameSize,&mp3SamplesPerFrame,&mp3SampleRate,&mp3IsMono) ) {
491 if ( ( swf->audio_size-outSize ) >= mp3FrameSize ) {
492 outSize += mp3FrameSize;
493 outSamples += mp3SamplesPerFrame;
494 if ( ( swf->sound_samples + outSamples + swf->samples_per_frame ) < swf->video_samples ) {
495 goto retry_swf_audio_packet;
499 /* invalid mp3 data, skip forward
500 we need to do this since the Flash Player
501 does not like custom headers */
502 swf->audio_in_pos ++;
504 swf->audio_in_pos %= AUDIO_FIFO_SIZE;
505 goto retry_swf_audio_packet;
509 /* audio stream is behind video stream, bail */
510 if ( ( swf->sound_samples + outSamples + swf->samples_per_frame ) < swf->video_samples ) {
515 if ( swf->video_type == CODEC_ID_FLV1 ) {
516 if ( swf->video_frame_number == 0 ) {
517 /* create a new video object */
518 put_swf_tag(s, TAG_VIDEOSTREAM);
519 put_le16(pb, VIDEO_ID);
520 put_le16(pb, 15000 ); /* hard flash player limit */
521 put_le16(pb, enc->width);
522 put_le16(pb, enc->height);
524 put_byte(pb, SWF_VIDEO_CODEC_FLV1);
527 /* place the video object for the first time */
528 put_swf_tag(s, TAG_PLACEOBJECT2);
531 put_le16(pb, VIDEO_ID);
532 put_swf_matrix(pb, 1 << FRAC_BITS, 0, 0, 1 << FRAC_BITS, 0, 0);
533 put_le16(pb, swf->video_frame_number );
542 /* mark the character for update */
543 put_swf_tag(s, TAG_PLACEOBJECT2);
546 put_le16(pb, swf->video_frame_number );
550 /* set video frame data */
551 put_swf_tag(s, TAG_VIDEOFRAME | TAG_LONG);
552 put_le16(pb, VIDEO_ID);
553 put_le16(pb, swf->video_frame_number++ );
554 put_buffer(pb, buf, size);
556 } else if ( swf->video_type == CODEC_ID_MJPEG ) {
557 if (swf->swf_frame_number > 0) {
558 /* remove the shape */
559 put_swf_tag(s, TAG_REMOVEOBJECT);
560 put_le16(pb, SHAPE_ID); /* shape ID */
561 put_le16(pb, 1); /* depth */
564 /* free the bitmap */
565 put_swf_tag(s, TAG_FREECHARACTER);
566 put_le16(pb, BITMAP_ID);
570 put_swf_tag(s, TAG_JPEG2 | TAG_LONG);
572 put_le16(pb, BITMAP_ID); /* ID of the image */
574 /* a dummy jpeg header seems to be required */
579 /* write the jpeg image */
580 put_buffer(pb, buf, size);
586 put_swf_tag(s, TAG_PLACEOBJECT);
587 put_le16(pb, SHAPE_ID); /* shape ID */
588 put_le16(pb, 1); /* depth */
589 put_swf_matrix(pb, 20 << FRAC_BITS, 0, 0, 20 << FRAC_BITS, 0, 0);
595 swf->swf_frame_number ++;
597 swf->video_samples += swf->samples_per_frame;
599 /* streaming sound always should be placed just before showframe tags */
601 put_swf_tag(s, TAG_STREAMBLOCK | TAG_LONG);
602 put_le16(pb, outSamples);
604 for (c=0; c<outSize; c++) {
605 put_byte(pb,swf->audio_fifo[(swf->audio_in_pos+c) % AUDIO_FIFO_SIZE]);
610 swf->sound_samples += outSamples;
611 swf->audio_in_pos += outSize;
612 swf->audio_size -= outSize;
613 swf->audio_in_pos %= AUDIO_FIFO_SIZE;
616 /* output the frame */
617 put_swf_tag(s, TAG_SHOWFRAME);
620 put_flush_packet(&s->pb);
625 static int swf_write_audio(AVFormatContext *s,
626 AVCodecContext *enc, const uint8_t *buf, int size)
628 SWFContext *swf = s->priv_data;
631 /* Flash Player limit */
632 if ( swf->swf_frame_number == 16000 ) {
633 av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
636 if (enc->codec_id == CODEC_ID_MP3 ) {
637 for (c=0; c<size; c++) {
638 swf->audio_fifo[(swf->audio_out_pos+c)%AUDIO_FIFO_SIZE] = buf[c];
640 swf->audio_size += size;
641 swf->audio_out_pos += size;
642 swf->audio_out_pos %= AUDIO_FIFO_SIZE;
645 /* if audio only stream make sure we add swf frames */
646 if ( swf->video_type == 0 ) {
647 swf_write_video(s, enc, 0, 0);
653 static int swf_write_packet(AVFormatContext *s, AVPacket *pkt)
655 AVCodecContext *codec = s->streams[pkt->stream_index]->codec;
656 if (codec->codec_type == CODEC_TYPE_AUDIO)
657 return swf_write_audio(s, codec, pkt->data, pkt->size);
659 return swf_write_video(s, codec, pkt->data, pkt->size);
662 static int swf_write_trailer(AVFormatContext *s)
664 SWFContext *swf = s->priv_data;
665 ByteIOContext *pb = &s->pb;
666 AVCodecContext *enc, *video_enc;
670 for(i=0;i<s->nb_streams;i++) {
671 enc = s->streams[i]->codec;
672 if (enc->codec_type == CODEC_TYPE_VIDEO)
676 put_swf_tag(s, TAG_END);
679 put_flush_packet(&s->pb);
681 /* patch file size and number of frames if not streamed */
682 if (!url_is_streamed(&s->pb) && video_enc) {
683 file_size = url_ftell(pb);
684 url_fseek(pb, 4, SEEK_SET);
685 put_le32(pb, file_size);
686 url_fseek(pb, swf->duration_pos, SEEK_SET);
687 put_le16(pb, video_enc->frame_number);
690 av_free(swf->audio_fifo);
694 #endif //CONFIG_MUXERS
696 /*********************************************/
697 /* Extract FLV encoded frame and MP3 from swf
698 Note that the detection of the real frame
699 is inaccurate at this point as it can be
700 quite tricky to determine, you almost certainly
701 will get a bad audio/video sync */
703 static int get_swf_tag(ByteIOContext *pb, int *len_ptr)
716 // av_log(NULL, AV_LOG_DEBUG, "Tag: %d - Len: %d\n", tag, len);
722 static int swf_probe(AVProbeData *p)
724 /* check file header */
725 if (p->buf_size <= 16)
727 if ((p->buf[0] == 'F' || p->buf[0] == 'C') && p->buf[1] == 'W' &&
729 return AVPROBE_SCORE_MAX;
734 static int swf_read_header(AVFormatContext *s, AVFormatParameters *ap)
737 ByteIOContext *pb = &s->pb;
738 int nbits, len, frame_rate, tag, v;
739 offset_t firstTagOff;
743 swf = av_malloc(sizeof(SWFContext));
748 tag = get_be32(pb) & 0xffffff00;
750 if (tag == MKBETAG('C', 'W', 'S', 0))
752 av_log(s, AV_LOG_ERROR, "Compressed SWF format not supported\n");
755 if (tag != MKBETAG('F', 'W', 'S', 0))
758 /* skip rectangle size */
759 nbits = get_byte(pb) >> 3;
760 len = (4 * nbits - 3 + 7) / 8;
762 frame_rate = get_le16(pb);
763 get_le16(pb); /* frame count */
765 /* The Flash Player converts 8.8 frame rates
766 to milliseconds internally. Do the same to get
767 a correct framerate */
768 swf->ms_per_frame = ( 1000 * 256 ) / frame_rate;
769 swf->samples_per_frame = 0;
772 firstTagOff = url_ftell(pb);
774 tag = get_swf_tag(pb, &len);
778 vst->codec->time_base.den = ast->codec->sample_rate / swf->samples_per_frame;
779 vst->codec->time_base.num = 1;
783 av_log(s, AV_LOG_ERROR, "No media found in SWF\n");
786 if ( tag == TAG_VIDEOSTREAM && !vst) {
787 swf->ch_id = get_le16(pb);
793 if ( get_byte(pb) == SWF_VIDEO_CODEC_FLV1 ) {
794 vst = av_new_stream(s, 0);
795 av_set_pts_info(vst, 24, 1, 1000); /* 24 bit pts in ms */
797 vst->codec->codec_type = CODEC_TYPE_VIDEO;
798 vst->codec->codec_id = CODEC_ID_FLV1;
799 if ( swf->samples_per_frame ) {
800 vst->codec->time_base.den = 1000. / swf->ms_per_frame;
801 vst->codec->time_base.num = 1;
804 } else if ( ( tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2 ) && !ast) {
805 /* streaming found */
808 swf->samples_per_frame = get_le16(pb);
811 /* if mp3 streaming found, OK */
812 if ((v & 0x20) != 0) {
813 if ( tag == TAG_STREAMHEAD2 ) {
816 ast = av_new_stream(s, 1);
817 av_set_pts_info(ast, 24, 1, 1000); /* 24 bit pts in ms */
822 ast->codec->channels = 2;
824 ast->codec->channels = 1;
826 switch((v>> 2) & 0x03) {
828 ast->codec->sample_rate = 11025;
831 ast->codec->sample_rate = 22050;
834 ast->codec->sample_rate = 44100;
840 ast->codec->codec_type = CODEC_TYPE_AUDIO;
841 ast->codec->codec_id = CODEC_ID_MP3;
847 url_fseek(pb, firstTagOff, SEEK_SET);
852 static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
854 SWFContext *swf = s->priv_data;
855 ByteIOContext *pb = &s->pb;
857 int tag, len, i, frame;
860 tag = get_swf_tag(pb, &len);
863 if (tag == TAG_VIDEOFRAME) {
864 for( i=0; i<s->nb_streams; i++ ) {
867 if ( get_le16(pb) == swf->ch_id ) {
868 frame = get_le16(pb);
869 av_get_packet(pb, pkt, len-4);
870 pkt->pts = frame * swf->ms_per_frame;
871 pkt->stream_index = st->index;
874 url_fskip(pb, len-2);
880 } else if (tag == TAG_STREAMBLOCK) {
881 for( i=0; i<s->nb_streams; i++ ) {
884 av_get_packet(pb, pkt, len);
885 pkt->stream_index = st->index;
897 static int swf_read_close(AVFormatContext *s)
902 static AVInputFormat swf_iformat = {
913 static AVOutputFormat swf_oformat = {
916 "application/x-shockwave-flash",
925 #endif //CONFIG_MUXERS
929 av_register_input_format(&swf_iformat);
931 av_register_output_format(&swf_oformat);
932 #endif //CONFIG_MUXERS