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;
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},
98 static const int sSampleRates[3][4] = {
99 {44100, 48000, 32000, 0},
100 {22050, 24000, 16000, 0},
101 {11025, 12000, 8000, 0},
104 static const int sBitRates[2][3][15] = {
105 { { 0, 32, 64, 96,128,160,192,224,256,288,320,352,384,416,448},
106 { 0, 32, 48, 56, 64, 80, 96,112,128,160,192,224,256,320,384},
107 { 0, 32, 40, 48, 56, 64, 80, 96,112,128,160,192,224,256,320}
109 { { 0, 32, 48, 56, 64, 80, 96,112,128,144,160,176,192,224,256},
110 { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160},
111 { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160}
115 static const int sSamplesPerFrame[3][3] =
122 static const int sBitsPerSlot[3] = {
128 static int swf_mp3_info(void *data, int *byteSize, int *samplesPerFrame, int *sampleRate, int *isMono )
130 uint32_t header = AV_RB32(data);
131 int layerID = 3 - ((header >> 17) & 0x03);
132 int bitRateID = ((header >> 12) & 0x0f);
133 int sampleRateID = ((header >> 10) & 0x03);
135 int bitsPerSlot = sBitsPerSlot[layerID];
136 int isPadded = ((header >> 9) & 0x01);
138 if ( (( header >> 21 ) & 0x7ff) != 0x7ff ) {
142 *isMono = ((header >> 6) & 0x03) == 0x03;
144 if ( (header >> 19 ) & 0x01 ) {
145 *sampleRate = sSampleRates[0][sampleRateID];
146 bitRate = sBitRates[0][layerID][bitRateID] * 1000;
147 *samplesPerFrame = sSamplesPerFrame[0][layerID];
149 if ( (header >> 20) & 0x01 ) {
150 *sampleRate = sSampleRates[1][sampleRateID];
151 bitRate = sBitRates[1][layerID][bitRateID] * 1000;
152 *samplesPerFrame = sSamplesPerFrame[1][layerID];
154 *sampleRate = sSampleRates[2][sampleRateID];
155 bitRate = sBitRates[1][layerID][bitRateID] * 1000;
156 *samplesPerFrame = sSamplesPerFrame[2][layerID];
160 *byteSize = ( ( ( ( *samplesPerFrame * (bitRate / bitsPerSlot) ) / *sampleRate ) + isPadded ) );
166 static void put_swf_tag(AVFormatContext *s, int tag)
168 SWFContext *swf = s->priv_data;
169 ByteIOContext *pb = &s->pb;
171 swf->tag_pos = url_ftell(pb);
173 /* reserve some room for the tag */
174 if (tag & TAG_LONG) {
182 static void put_swf_end_tag(AVFormatContext *s)
184 SWFContext *swf = s->priv_data;
185 ByteIOContext *pb = &s->pb;
190 tag_len = pos - swf->tag_pos - 2;
192 url_fseek(pb, swf->tag_pos, SEEK_SET);
193 if (tag & TAG_LONG) {
195 put_le16(pb, (tag << 6) | 0x3f);
196 put_le32(pb, tag_len - 4);
198 assert(tag_len < 0x3f);
199 put_le16(pb, (tag << 6) | tag_len);
201 url_fseek(pb, pos, SEEK_SET);
204 static inline void max_nbits(int *nbits_ptr, int val)
220 static void put_swf_rect(ByteIOContext *pb,
221 int xmin, int xmax, int ymin, int ymax)
227 init_put_bits(&p, buf, sizeof(buf));
230 max_nbits(&nbits, xmin);
231 max_nbits(&nbits, xmax);
232 max_nbits(&nbits, ymin);
233 max_nbits(&nbits, ymax);
234 mask = (1 << nbits) - 1;
237 put_bits(&p, 5, nbits);
238 put_bits(&p, nbits, xmin & mask);
239 put_bits(&p, nbits, xmax & mask);
240 put_bits(&p, nbits, ymin & mask);
241 put_bits(&p, nbits, ymax & mask);
244 put_buffer(pb, buf, pbBufPtr(&p) - p.buf);
247 static void put_swf_line_edge(PutBitContext *pb, int dx, int dy)
251 put_bits(pb, 1, 1); /* edge */
252 put_bits(pb, 1, 1); /* line select */
254 max_nbits(&nbits, dx);
255 max_nbits(&nbits, dy);
257 mask = (1 << nbits) - 1;
258 put_bits(pb, 4, nbits - 2); /* 16 bits precision */
262 put_bits(pb, nbits, dy & mask);
263 } else if (dy == 0) {
266 put_bits(pb, nbits, dx & mask);
269 put_bits(pb, nbits, dx & mask);
270 put_bits(pb, nbits, dy & mask);
277 static void put_swf_matrix(ByteIOContext *pb,
278 int a, int b, int c, int d, int tx, int ty)
284 init_put_bits(&p, buf, sizeof(buf));
286 put_bits(&p, 1, 1); /* a, d present */
288 max_nbits(&nbits, a);
289 max_nbits(&nbits, d);
290 put_bits(&p, 5, nbits); /* nb bits */
291 put_bits(&p, nbits, a);
292 put_bits(&p, nbits, d);
294 put_bits(&p, 1, 1); /* b, c present */
296 max_nbits(&nbits, c);
297 max_nbits(&nbits, b);
298 put_bits(&p, 5, nbits); /* nb bits */
299 put_bits(&p, nbits, c);
300 put_bits(&p, nbits, b);
303 max_nbits(&nbits, tx);
304 max_nbits(&nbits, ty);
305 put_bits(&p, 5, nbits); /* nb bits */
306 put_bits(&p, nbits, tx);
307 put_bits(&p, nbits, ty);
310 put_buffer(pb, buf, pbBufPtr(&p) - p.buf);
314 static int swf_write_header(AVFormatContext *s)
316 SWFContext *swf = s->priv_data;
317 ByteIOContext *pb = &s->pb;
318 AVCodecContext *enc, *audio_enc, *video_enc;
321 int i, width, height, rate, rate_base;
323 swf->audio_in_pos = 0;
324 swf->audio_out_pos = 0;
326 swf->audio_fifo = av_malloc(AUDIO_FIFO_SIZE);
327 swf->sound_samples = 0;
328 swf->video_samples = 0;
329 swf->swf_frame_number = 0;
330 swf->video_frame_number = 0;
334 for(i=0;i<s->nb_streams;i++) {
335 enc = s->streams[i]->codec;
336 if (enc->codec_type == CODEC_TYPE_AUDIO)
339 if ( enc->codec_id == CODEC_ID_VP6F ||
340 enc->codec_id == CODEC_ID_FLV1 ||
341 enc->codec_id == CODEC_ID_MJPEG ) {
344 av_log(enc, AV_LOG_ERROR, "SWF only supports VP6, FLV1 and MJPEG\n");
351 /* currenty, cannot work correctly if audio only */
358 swf->video_type = video_enc->codec_id;
359 width = video_enc->width;
360 height = video_enc->height;
361 rate = video_enc->time_base.den;
362 rate_base = video_enc->time_base.num;
367 swf->samples_per_frame = ( 44100. * rate_base ) / rate;
369 swf->audio_type = audio_enc->codec_id;
370 swf->samples_per_frame = ( ( audio_enc->sample_rate ) * rate_base ) / rate;
374 if ( video_enc && video_enc->codec_id == CODEC_ID_VP6F ) {
375 put_byte(pb, 8); /* version (version 8 and above support VP6 codec) */
376 } else if ( video_enc && video_enc->codec_id == CODEC_ID_FLV1 ) {
377 put_byte(pb, 6); /* version (version 6 and above support FLV1 codec) */
379 put_byte(pb, 4); /* version (should use 4 for mpeg audio support) */
381 put_le32(pb, DUMMY_FILE_SIZE); /* dummy size
382 (will be patched if not streamed) */
384 put_swf_rect(pb, 0, width * 20, 0, height * 20);
385 put_le16(pb, (rate * 256) / rate_base); /* frame rate */
386 swf->duration_pos = url_ftell(pb);
387 put_le16(pb, (uint16_t)(DUMMY_DURATION * (int64_t)rate / rate_base)); /* frame count */
389 /* define a shape with the jpeg inside */
390 if ( video_enc && (video_enc->codec_id == CODEC_ID_VP6F ||
391 video_enc->codec_id == CODEC_ID_FLV1 )) {
392 } else if ( video_enc && video_enc->codec_id == CODEC_ID_MJPEG ) {
393 put_swf_tag(s, TAG_DEFINESHAPE);
395 put_le16(pb, SHAPE_ID); /* ID of shape */
396 /* bounding rectangle */
397 put_swf_rect(pb, 0, width, 0, height);
399 put_byte(pb, 1); /* one fill style */
400 put_byte(pb, 0x41); /* clipped bitmap fill */
401 put_le16(pb, BITMAP_ID); /* bitmap ID */
402 /* position of the bitmap */
403 put_swf_matrix(pb, (int)(1.0 * (1 << FRAC_BITS)), 0,
404 0, (int)(1.0 * (1 << FRAC_BITS)), 0, 0);
405 put_byte(pb, 0); /* no line style */
408 init_put_bits(&p, buf1, sizeof(buf1));
409 put_bits(&p, 4, 1); /* one fill bit */
410 put_bits(&p, 4, 0); /* zero line bit */
412 put_bits(&p, 1, 0); /* not an edge */
413 put_bits(&p, 5, FLAG_MOVETO | FLAG_SETFILL0);
414 put_bits(&p, 5, 1); /* nbits */
415 put_bits(&p, 1, 0); /* X */
416 put_bits(&p, 1, 0); /* Y */
417 put_bits(&p, 1, 1); /* set fill style 1 */
419 /* draw the rectangle ! */
420 put_swf_line_edge(&p, width, 0);
421 put_swf_line_edge(&p, 0, height);
422 put_swf_line_edge(&p, -width, 0);
423 put_swf_line_edge(&p, 0, -height);
426 put_bits(&p, 1, 0); /* not an edge */
430 put_buffer(pb, buf1, pbBufPtr(&p) - p.buf);
435 if (audio_enc && audio_enc->codec_id == CODEC_ID_MP3 ) {
439 put_swf_tag(s, TAG_STREAMHEAD2);
442 switch(audio_enc->sample_rate) {
454 av_log(s, AV_LOG_ERROR, "swf doesnt support that sample rate, choose from (44100, 22050, 11025)\n");
455 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);
702 url_fseek(pb, file_size, SEEK_SET);
705 av_free(swf->audio_fifo);
709 #endif //CONFIG_MUXERS
711 /*********************************************/
712 /* Extract FLV encoded frame and MP3 from swf
713 Note that the detection of the real frame
714 is inaccurate at this point as it can be
715 quite tricky to determine, you almost certainly
716 will get a bad audio/video sync */
718 static int get_swf_tag(ByteIOContext *pb, int *len_ptr)
731 // av_log(NULL, AV_LOG_DEBUG, "Tag: %d - Len: %d\n", tag, len);
737 static int swf_probe(AVProbeData *p)
739 /* check file header */
740 if (p->buf_size <= 16)
742 if ((p->buf[0] == 'F' || p->buf[0] == 'C') && p->buf[1] == 'W' &&
744 return AVPROBE_SCORE_MAX;
749 static int swf_read_header(AVFormatContext *s, AVFormatParameters *ap)
751 SWFContext *swf = s->priv_data;
752 ByteIOContext *pb = &s->pb;
753 int nbits, len, frame_rate, tag, v;
754 offset_t frame_offset = -1;
758 tag = get_be32(pb) & 0xffffff00;
760 if (tag == MKBETAG('C', 'W', 'S', 0))
762 av_log(s, AV_LOG_ERROR, "Compressed SWF format not supported\n");
765 if (tag != MKBETAG('F', 'W', 'S', 0))
768 /* skip rectangle size */
769 nbits = get_byte(pb) >> 3;
770 len = (4 * nbits - 3 + 7) / 8;
772 frame_rate = get_le16(pb);
773 get_le16(pb); /* frame count */
775 /* The Flash Player converts 8.8 frame rates
776 to milliseconds internally. Do the same to get
777 a correct framerate */
778 swf->ms_per_frame = ( 1000 * 256 ) / frame_rate;
779 swf->samples_per_frame = 0;
782 offset_t tag_offset = url_ftell(pb);
783 tag = get_swf_tag(pb, &len);
784 if (tag < 0 || tag == TAG_VIDEOFRAME || tag == TAG_STREAMBLOCK) {
785 url_fseek(pb, frame_offset == -1 ? tag_offset : frame_offset, SEEK_SET);
788 if ( tag == TAG_VIDEOSTREAM && !vst) {
789 int ch_id = get_le16(pb);
795 vst = av_new_stream(s, ch_id);
796 vst->codec->codec_type = CODEC_TYPE_VIDEO;
797 vst->codec->codec_id = codec_get_id(swf_codec_tags, get_byte(pb));
798 } else if ( ( tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2 ) && !ast) {
799 /* streaming found */
800 int sample_rate_code;
803 swf->samples_per_frame = get_le16(pb);
804 ast = av_new_stream(s, -1); /* -1 to avoid clash with video stream ch_id */
805 av_set_pts_info(ast, 24, 1, 1000); /* 24 bit pts in ms */
806 swf->audio_stream_index = ast->index;
807 ast->codec->channels = 1 + (v&1);
808 ast->codec->codec_type = CODEC_TYPE_AUDIO;
809 ast->codec->codec_id = codec_get_id(swf_audio_codec_tags, (v>>4) & 15);
810 ast->need_parsing = 1;
811 sample_rate_code= (v>>2) & 3;
812 if (!sample_rate_code)
814 ast->codec->sample_rate = 11025 << (sample_rate_code-1);
818 } else if (tag == TAG_JPEG2 && !vst) {
819 vst = av_new_stream(s, -2); /* -2 to avoid clash with video stream and audio stream */
820 vst->codec->codec_type = CODEC_TYPE_VIDEO;
821 vst->codec->codec_id = CODEC_ID_MJPEG;
823 frame_offset = tag_offset;
829 av_set_pts_info(vst, 24, 1, 1000); /* 24 bit pts in ms */
830 if (swf->ms_per_frame) {
831 vst->codec->time_base.den = 1000. / swf->ms_per_frame;
832 vst->codec->time_base.num = 1;
838 static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
840 SWFContext *swf = s->priv_data;
841 ByteIOContext *pb = &s->pb;
843 int tag, len, i, frame;
846 tag = get_swf_tag(pb, &len);
849 if (tag == TAG_VIDEOFRAME) {
850 int ch_id = get_le16(pb);
852 for( i=0; i<s->nb_streams; i++ ) {
854 if (st->codec->codec_type == CODEC_TYPE_VIDEO && st->id == ch_id) {
855 frame = get_le16(pb);
856 av_get_packet(pb, pkt, len-2);
857 pkt->pts = frame * swf->ms_per_frame;
858 pkt->stream_index = st->index;
862 } else if (tag == TAG_STREAMBLOCK) {
863 st = s->streams[swf->audio_stream_index];
864 if (st->codec->codec_id == CODEC_ID_MP3) {
866 av_get_packet(pb, pkt, len-4);
867 } else { // ADPCM, PCM
868 av_get_packet(pb, pkt, len);
870 pkt->stream_index = st->index;
872 } else if (tag == TAG_JPEG2) {
873 for (i=0; i<s->nb_streams; i++) {
876 get_le16(pb); /* BITMAP_ID */
877 av_new_packet(pkt, len-2);
878 get_buffer(pb, pkt->data, 4);
879 if (AV_RB32(pkt->data) == 0xffd8ffd9) {
880 /* old SWF files containing SOI/EOI as data start */
882 get_buffer(pb, pkt->data, pkt->size);
884 get_buffer(pb, pkt->data + 4, pkt->size - 4);
886 pkt->stream_index = st->index;
896 static int swf_read_close(AVFormatContext *s)
901 #ifdef CONFIG_SWF_DEMUXER
902 AVInputFormat swf_demuxer = {
912 #ifdef CONFIG_SWF_MUXER
913 AVOutputFormat swf_muxer = {
916 "application/x-shockwave-flash",