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 */
63 offset_t duration_pos;
66 int samples_per_frame;
70 int video_frame_number;
84 static const CodecTag swf_codec_tags[] = {
85 {CODEC_ID_FLV1, 0x02},
86 {CODEC_ID_VP6F, 0x04},
90 static const int sSampleRates[3][4] = {
91 {44100, 48000, 32000, 0},
92 {22050, 24000, 16000, 0},
93 {11025, 12000, 8000, 0},
96 static const int sBitRates[2][3][15] = {
97 { { 0, 32, 64, 96,128,160,192,224,256,288,320,352,384,416,448},
98 { 0, 32, 48, 56, 64, 80, 96,112,128,160,192,224,256,320,384},
99 { 0, 32, 40, 48, 56, 64, 80, 96,112,128,160,192,224,256,320}
101 { { 0, 32, 48, 56, 64, 80, 96,112,128,144,160,176,192,224,256},
102 { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160},
103 { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160}
107 static const int sSamplesPerFrame[3][3] =
114 static const int sBitsPerSlot[3] = {
120 static int swf_mp3_info(void *data, int *byteSize, int *samplesPerFrame, int *sampleRate, int *isMono )
122 uint8_t *dataTmp = (uint8_t *)data;
123 uint32_t header = ( (uint32_t)dataTmp[0] << 24 ) | ( (uint32_t)dataTmp[1] << 16 ) | ( (uint32_t)dataTmp[2] << 8 ) | (uint32_t)dataTmp[3];
124 int layerID = 3 - ((header >> 17) & 0x03);
125 int bitRateID = ((header >> 12) & 0x0f);
126 int sampleRateID = ((header >> 10) & 0x03);
128 int bitsPerSlot = sBitsPerSlot[layerID];
129 int isPadded = ((header >> 9) & 0x01);
131 if ( (( header >> 21 ) & 0x7ff) != 0x7ff ) {
135 *isMono = ((header >> 6) & 0x03) == 0x03;
137 if ( (header >> 19 ) & 0x01 ) {
138 *sampleRate = sSampleRates[0][sampleRateID];
139 bitRate = sBitRates[0][layerID][bitRateID] * 1000;
140 *samplesPerFrame = sSamplesPerFrame[0][layerID];
142 if ( (header >> 20) & 0x01 ) {
143 *sampleRate = sSampleRates[1][sampleRateID];
144 bitRate = sBitRates[1][layerID][bitRateID] * 1000;
145 *samplesPerFrame = sSamplesPerFrame[1][layerID];
147 *sampleRate = sSampleRates[2][sampleRateID];
148 bitRate = sBitRates[1][layerID][bitRateID] * 1000;
149 *samplesPerFrame = sSamplesPerFrame[2][layerID];
153 *byteSize = ( ( ( ( *samplesPerFrame * (bitRate / bitsPerSlot) ) / *sampleRate ) + isPadded ) );
159 static void put_swf_tag(AVFormatContext *s, int tag)
161 SWFContext *swf = s->priv_data;
162 ByteIOContext *pb = &s->pb;
164 swf->tag_pos = url_ftell(pb);
166 /* reserve some room for the tag */
167 if (tag & TAG_LONG) {
175 static void put_swf_end_tag(AVFormatContext *s)
177 SWFContext *swf = s->priv_data;
178 ByteIOContext *pb = &s->pb;
183 tag_len = pos - swf->tag_pos - 2;
185 url_fseek(pb, swf->tag_pos, SEEK_SET);
186 if (tag & TAG_LONG) {
188 put_le16(pb, (tag << 6) | 0x3f);
189 put_le32(pb, tag_len - 4);
191 assert(tag_len < 0x3f);
192 put_le16(pb, (tag << 6) | tag_len);
194 url_fseek(pb, pos, SEEK_SET);
197 static inline void max_nbits(int *nbits_ptr, int val)
213 static void put_swf_rect(ByteIOContext *pb,
214 int xmin, int xmax, int ymin, int ymax)
220 init_put_bits(&p, buf, sizeof(buf));
223 max_nbits(&nbits, xmin);
224 max_nbits(&nbits, xmax);
225 max_nbits(&nbits, ymin);
226 max_nbits(&nbits, ymax);
227 mask = (1 << nbits) - 1;
230 put_bits(&p, 5, nbits);
231 put_bits(&p, nbits, xmin & mask);
232 put_bits(&p, nbits, xmax & mask);
233 put_bits(&p, nbits, ymin & mask);
234 put_bits(&p, nbits, ymax & mask);
237 put_buffer(pb, buf, pbBufPtr(&p) - p.buf);
240 static void put_swf_line_edge(PutBitContext *pb, int dx, int dy)
244 put_bits(pb, 1, 1); /* edge */
245 put_bits(pb, 1, 1); /* line select */
247 max_nbits(&nbits, dx);
248 max_nbits(&nbits, dy);
250 mask = (1 << nbits) - 1;
251 put_bits(pb, 4, nbits - 2); /* 16 bits precision */
255 put_bits(pb, nbits, dy & mask);
256 } else if (dy == 0) {
259 put_bits(pb, nbits, dx & mask);
262 put_bits(pb, nbits, dx & mask);
263 put_bits(pb, nbits, dy & mask);
270 static void put_swf_matrix(ByteIOContext *pb,
271 int a, int b, int c, int d, int tx, int ty)
277 init_put_bits(&p, buf, sizeof(buf));
279 put_bits(&p, 1, 1); /* a, d present */
281 max_nbits(&nbits, a);
282 max_nbits(&nbits, d);
283 put_bits(&p, 5, nbits); /* nb bits */
284 put_bits(&p, nbits, a);
285 put_bits(&p, nbits, d);
287 put_bits(&p, 1, 1); /* b, c present */
289 max_nbits(&nbits, c);
290 max_nbits(&nbits, b);
291 put_bits(&p, 5, nbits); /* nb bits */
292 put_bits(&p, nbits, c);
293 put_bits(&p, nbits, b);
296 max_nbits(&nbits, tx);
297 max_nbits(&nbits, ty);
298 put_bits(&p, 5, nbits); /* nb bits */
299 put_bits(&p, nbits, tx);
300 put_bits(&p, nbits, ty);
303 put_buffer(pb, buf, pbBufPtr(&p) - p.buf);
307 static int swf_write_header(AVFormatContext *s)
310 ByteIOContext *pb = &s->pb;
311 AVCodecContext *enc, *audio_enc, *video_enc;
314 int i, width, height, rate, rate_base;
316 swf = av_malloc(sizeof(SWFContext));
322 swf->audio_in_pos = 0;
323 swf->audio_out_pos = 0;
325 swf->audio_fifo = av_malloc(AUDIO_FIFO_SIZE);
326 swf->sound_samples = 0;
327 swf->video_samples = 0;
328 swf->swf_frame_number = 0;
329 swf->video_frame_number = 0;
333 for(i=0;i<s->nb_streams;i++) {
334 enc = s->streams[i]->codec;
335 if (enc->codec_type == CODEC_TYPE_AUDIO)
338 if ( enc->codec_id == CODEC_ID_VP6F ||
339 enc->codec_id == CODEC_ID_FLV1 ||
340 enc->codec_id == CODEC_ID_MJPEG ) {
343 av_log(enc, AV_LOG_ERROR, "SWF only supports VP6, FLV1 and MJPEG\n");
350 /* currenty, cannot work correctly if audio only */
357 swf->video_type = video_enc->codec_id;
358 width = video_enc->width;
359 height = video_enc->height;
360 rate = video_enc->time_base.den;
361 rate_base = video_enc->time_base.num;
366 swf->samples_per_frame = ( 44100. * rate_base ) / rate;
368 swf->audio_type = audio_enc->codec_id;
369 swf->samples_per_frame = ( ( audio_enc->sample_rate ) * rate_base ) / rate;
373 if ( video_enc && video_enc->codec_id == CODEC_ID_VP6F ) {
374 put_byte(pb, 8); /* version (version 8 and above support VP6 codec) */
375 } else if ( video_enc && video_enc->codec_id == CODEC_ID_FLV1 ) {
376 put_byte(pb, 6); /* version (version 6 and above support FLV1 codec) */
378 put_byte(pb, 4); /* version (should use 4 for mpeg audio support) */
380 put_le32(pb, DUMMY_FILE_SIZE); /* dummy size
381 (will be patched if not streamed) */
383 put_swf_rect(pb, 0, width * 20, 0, height * 20);
384 put_le16(pb, (rate * 256) / rate_base); /* frame rate */
385 swf->duration_pos = url_ftell(pb);
386 put_le16(pb, (uint16_t)(DUMMY_DURATION * (int64_t)rate / rate_base)); /* frame count */
388 /* define a shape with the jpeg inside */
389 if ( video_enc && (video_enc->codec_id == CODEC_ID_VP6F ||
390 video_enc->codec_id == CODEC_ID_FLV1 )) {
391 } else if ( video_enc && video_enc->codec_id == CODEC_ID_MJPEG ) {
392 put_swf_tag(s, TAG_DEFINESHAPE);
394 put_le16(pb, SHAPE_ID); /* ID of shape */
395 /* bounding rectangle */
396 put_swf_rect(pb, 0, width, 0, height);
398 put_byte(pb, 1); /* one fill style */
399 put_byte(pb, 0x41); /* clipped bitmap fill */
400 put_le16(pb, BITMAP_ID); /* bitmap ID */
401 /* position of the bitmap */
402 put_swf_matrix(pb, (int)(1.0 * (1 << FRAC_BITS)), 0,
403 0, (int)(1.0 * (1 << FRAC_BITS)), 0, 0);
404 put_byte(pb, 0); /* no line style */
407 init_put_bits(&p, buf1, sizeof(buf1));
408 put_bits(&p, 4, 1); /* one fill bit */
409 put_bits(&p, 4, 0); /* zero line bit */
411 put_bits(&p, 1, 0); /* not an edge */
412 put_bits(&p, 5, FLAG_MOVETO | FLAG_SETFILL0);
413 put_bits(&p, 5, 1); /* nbits */
414 put_bits(&p, 1, 0); /* X */
415 put_bits(&p, 1, 0); /* Y */
416 put_bits(&p, 1, 1); /* set fill style 1 */
418 /* draw the rectangle ! */
419 put_swf_line_edge(&p, width, 0);
420 put_swf_line_edge(&p, 0, height);
421 put_swf_line_edge(&p, -width, 0);
422 put_swf_line_edge(&p, 0, -height);
425 put_bits(&p, 1, 0); /* not an edge */
429 put_buffer(pb, buf1, pbBufPtr(&p) - p.buf);
434 if (audio_enc && audio_enc->codec_id == CODEC_ID_MP3 ) {
438 put_swf_tag(s, TAG_STREAMHEAD2);
441 switch(audio_enc->sample_rate) {
453 av_log(s, AV_LOG_ERROR, "swf doesnt support that sample rate, choose from (44100, 22050, 11025)\n");
454 av_free(swf->audio_fifo);
458 v |= 0x02; /* 16 bit playback */
459 if (audio_enc->channels == 2)
460 v |= 0x01; /* stereo playback */
462 v |= 0x20; /* mp3 compressed */
464 put_le16(&s->pb, swf->samples_per_frame); /* avg samples per frame */
470 put_flush_packet(&s->pb);
474 static int swf_write_video(AVFormatContext *s,
475 AVCodecContext *enc, const uint8_t *buf, int size)
477 SWFContext *swf = s->priv_data;
478 ByteIOContext *pb = &s->pb;
483 /* Flash Player limit */
484 if ( swf->swf_frame_number == 16000 ) {
485 av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
488 if ( swf->audio_type ) {
489 /* Prescan audio data for this swf frame */
490 retry_swf_audio_packet:
491 if ( ( swf->audio_size-outSize ) >= 4 ) {
492 int mp3FrameSize = 0;
493 int mp3SampleRate = 0;
495 int mp3SamplesPerFrame = 0;
497 /* copy out mp3 header from ring buffer */
499 for (c=0; c<4; c++) {
500 header[c] = swf->audio_fifo[(swf->audio_in_pos+outSize+c) % AUDIO_FIFO_SIZE];
503 if ( swf_mp3_info(header,&mp3FrameSize,&mp3SamplesPerFrame,&mp3SampleRate,&mp3IsMono) ) {
504 if ( ( swf->audio_size-outSize ) >= mp3FrameSize ) {
505 outSize += mp3FrameSize;
506 outSamples += mp3SamplesPerFrame;
507 if ( ( swf->sound_samples + outSamples + swf->samples_per_frame ) < swf->video_samples ) {
508 goto retry_swf_audio_packet;
512 /* invalid mp3 data, skip forward
513 we need to do this since the Flash Player
514 does not like custom headers */
515 swf->audio_in_pos ++;
517 swf->audio_in_pos %= AUDIO_FIFO_SIZE;
518 goto retry_swf_audio_packet;
522 /* audio stream is behind video stream, bail */
523 if ( ( swf->sound_samples + outSamples + swf->samples_per_frame ) < swf->video_samples ) {
528 if ( swf->video_type == CODEC_ID_VP6F ||
529 swf->video_type == CODEC_ID_FLV1 ) {
530 if ( swf->video_frame_number == 0 ) {
531 /* create a new video object */
532 put_swf_tag(s, TAG_VIDEOSTREAM);
533 put_le16(pb, VIDEO_ID);
534 put_le16(pb, 15000 ); /* hard flash player limit */
535 put_le16(pb, enc->width);
536 put_le16(pb, enc->height);
538 put_byte(pb,codec_get_tag(swf_codec_tags,swf->video_type));
541 /* place the video object for the first time */
542 put_swf_tag(s, TAG_PLACEOBJECT2);
545 put_le16(pb, VIDEO_ID);
546 put_swf_matrix(pb, 1 << FRAC_BITS, 0, 0, 1 << FRAC_BITS, 0, 0);
547 put_le16(pb, swf->video_frame_number );
556 /* mark the character for update */
557 put_swf_tag(s, TAG_PLACEOBJECT2);
560 put_le16(pb, swf->video_frame_number );
564 /* set video frame data */
565 put_swf_tag(s, TAG_VIDEOFRAME | TAG_LONG);
566 put_le16(pb, VIDEO_ID);
567 put_le16(pb, swf->video_frame_number++ );
568 put_buffer(pb, buf, size);
570 } else if ( swf->video_type == CODEC_ID_MJPEG ) {
571 if (swf->swf_frame_number > 0) {
572 /* remove the shape */
573 put_swf_tag(s, TAG_REMOVEOBJECT);
574 put_le16(pb, SHAPE_ID); /* shape ID */
575 put_le16(pb, 1); /* depth */
578 /* free the bitmap */
579 put_swf_tag(s, TAG_FREECHARACTER);
580 put_le16(pb, BITMAP_ID);
584 put_swf_tag(s, TAG_JPEG2 | TAG_LONG);
586 put_le16(pb, BITMAP_ID); /* ID of the image */
588 /* a dummy jpeg header seems to be required */
593 /* write the jpeg image */
594 put_buffer(pb, buf, size);
600 put_swf_tag(s, TAG_PLACEOBJECT);
601 put_le16(pb, SHAPE_ID); /* shape ID */
602 put_le16(pb, 1); /* depth */
603 put_swf_matrix(pb, 20 << FRAC_BITS, 0, 0, 20 << FRAC_BITS, 0, 0);
609 swf->swf_frame_number ++;
611 swf->video_samples += swf->samples_per_frame;
613 /* streaming sound always should be placed just before showframe tags */
615 put_swf_tag(s, TAG_STREAMBLOCK | TAG_LONG);
616 put_le16(pb, outSamples);
618 for (c=0; c<outSize; c++) {
619 put_byte(pb,swf->audio_fifo[(swf->audio_in_pos+c) % AUDIO_FIFO_SIZE]);
624 swf->sound_samples += outSamples;
625 swf->audio_in_pos += outSize;
626 swf->audio_size -= outSize;
627 swf->audio_in_pos %= AUDIO_FIFO_SIZE;
630 /* output the frame */
631 put_swf_tag(s, TAG_SHOWFRAME);
634 put_flush_packet(&s->pb);
639 static int swf_write_audio(AVFormatContext *s,
640 AVCodecContext *enc, const uint8_t *buf, int size)
642 SWFContext *swf = s->priv_data;
645 /* Flash Player limit */
646 if ( swf->swf_frame_number == 16000 ) {
647 av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
650 if (enc->codec_id == CODEC_ID_MP3 ) {
651 for (c=0; c<size; c++) {
652 swf->audio_fifo[(swf->audio_out_pos+c)%AUDIO_FIFO_SIZE] = buf[c];
654 swf->audio_size += size;
655 swf->audio_out_pos += size;
656 swf->audio_out_pos %= AUDIO_FIFO_SIZE;
659 /* if audio only stream make sure we add swf frames */
660 if ( swf->video_type == 0 ) {
661 swf_write_video(s, enc, 0, 0);
667 static int swf_write_packet(AVFormatContext *s, AVPacket *pkt)
669 AVCodecContext *codec = s->streams[pkt->stream_index]->codec;
670 if (codec->codec_type == CODEC_TYPE_AUDIO)
671 return swf_write_audio(s, codec, pkt->data, pkt->size);
673 return swf_write_video(s, codec, pkt->data, pkt->size);
676 static int swf_write_trailer(AVFormatContext *s)
678 SWFContext *swf = s->priv_data;
679 ByteIOContext *pb = &s->pb;
680 AVCodecContext *enc, *video_enc;
684 for(i=0;i<s->nb_streams;i++) {
685 enc = s->streams[i]->codec;
686 if (enc->codec_type == CODEC_TYPE_VIDEO)
690 put_swf_tag(s, TAG_END);
693 put_flush_packet(&s->pb);
695 /* patch file size and number of frames if not streamed */
696 if (!url_is_streamed(&s->pb) && video_enc) {
697 file_size = url_ftell(pb);
698 url_fseek(pb, 4, SEEK_SET);
699 put_le32(pb, file_size);
700 url_fseek(pb, swf->duration_pos, SEEK_SET);
701 put_le16(pb, video_enc->frame_number);
704 av_free(swf->audio_fifo);
708 #endif //CONFIG_MUXERS
710 /*********************************************/
711 /* Extract FLV encoded frame and MP3 from swf
712 Note that the detection of the real frame
713 is inaccurate at this point as it can be
714 quite tricky to determine, you almost certainly
715 will get a bad audio/video sync */
717 static int get_swf_tag(ByteIOContext *pb, int *len_ptr)
730 // av_log(NULL, AV_LOG_DEBUG, "Tag: %d - Len: %d\n", tag, len);
736 static int swf_probe(AVProbeData *p)
738 /* check file header */
739 if (p->buf_size <= 16)
741 if ((p->buf[0] == 'F' || p->buf[0] == 'C') && p->buf[1] == 'W' &&
743 return AVPROBE_SCORE_MAX;
748 static int swf_read_header(AVFormatContext *s, AVFormatParameters *ap)
751 ByteIOContext *pb = &s->pb;
752 int nbits, len, frame_rate, tag, v;
753 offset_t firstTagOff;
757 swf = av_malloc(sizeof(SWFContext));
762 tag = get_be32(pb) & 0xffffff00;
764 if (tag == MKBETAG('C', 'W', 'S', 0))
766 av_log(s, AV_LOG_ERROR, "Compressed SWF format not supported\n");
769 if (tag != MKBETAG('F', 'W', 'S', 0))
772 /* skip rectangle size */
773 nbits = get_byte(pb) >> 3;
774 len = (4 * nbits - 3 + 7) / 8;
776 frame_rate = get_le16(pb);
777 get_le16(pb); /* frame count */
779 /* The Flash Player converts 8.8 frame rates
780 to milliseconds internally. Do the same to get
781 a correct framerate */
782 swf->ms_per_frame = ( 1000 * 256 ) / frame_rate;
783 swf->samples_per_frame = 0;
786 firstTagOff = url_ftell(pb);
788 tag = get_swf_tag(pb, &len);
792 vst->codec->time_base.den = ast->codec->sample_rate / swf->samples_per_frame;
793 vst->codec->time_base.num = 1;
797 av_log(s, AV_LOG_ERROR, "No media found in SWF\n");
800 if ( tag == TAG_VIDEOSTREAM && !vst) {
802 swf->ch_id = get_le16(pb);
808 codec_id = codec_get_id(swf_codec_tags, get_byte(pb));
810 vst = av_new_stream(s, 0);
811 av_set_pts_info(vst, 24, 1, 1000); /* 24 bit pts in ms */
813 vst->codec->codec_type = CODEC_TYPE_VIDEO;
814 vst->codec->codec_id = codec_id;
815 if ( swf->samples_per_frame ) {
816 vst->codec->time_base.den = 1000. / swf->ms_per_frame;
817 vst->codec->time_base.num = 1;
820 } else if ( ( tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2 ) && !ast) {
821 /* streaming found */
824 swf->samples_per_frame = get_le16(pb);
827 /* if mp3 streaming found, OK */
828 if ((v & 0x20) != 0) {
829 if ( tag == TAG_STREAMHEAD2 ) {
832 ast = av_new_stream(s, 1);
835 av_set_pts_info(ast, 24, 1, 1000); /* 24 bit pts in ms */
838 ast->codec->channels = 2;
840 ast->codec->channels = 1;
842 switch((v>> 2) & 0x03) {
844 ast->codec->sample_rate = 11025;
847 ast->codec->sample_rate = 22050;
850 ast->codec->sample_rate = 44100;
856 ast->codec->codec_type = CODEC_TYPE_AUDIO;
857 ast->codec->codec_id = CODEC_ID_MP3;
858 ast->need_parsing = 1;
864 url_fseek(pb, firstTagOff, SEEK_SET);
869 static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
871 SWFContext *swf = s->priv_data;
872 ByteIOContext *pb = &s->pb;
874 int tag, len, i, frame;
877 tag = get_swf_tag(pb, &len);
880 if (tag == TAG_VIDEOFRAME) {
881 for( i=0; i<s->nb_streams; i++ ) {
884 if ( get_le16(pb) == swf->ch_id ) {
885 frame = get_le16(pb);
886 av_get_packet(pb, pkt, len-4);
887 pkt->pts = frame * swf->ms_per_frame;
888 pkt->stream_index = st->index;
891 url_fskip(pb, len-2);
897 } else if (tag == TAG_STREAMBLOCK) {
898 for( i=0; i<s->nb_streams; i++ ) {
902 av_get_packet(pb, pkt, len-4);
903 pkt->stream_index = st->index;
915 static int swf_read_close(AVFormatContext *s)
920 #ifdef CONFIG_SWF_DEMUXER
921 AVInputFormat swf_demuxer = {
931 #ifdef CONFIG_SWF_MUXER
932 AVOutputFormat swf_muxer = {
935 "application/x-shockwave-flash",