]> git.sesse.net Git - ffmpeg/blob - libavformat/swf.c
seek back at the end of file after updating header
[ffmpeg] / libavformat / swf.c
1 /*
2  * Flash Compatible Streaming Format
3  * Copyright (c) 2000 Fabrice Bellard.
4  * Copyright (c) 2003 Tinic Uro.
5  *
6  * This file is part of FFmpeg.
7  *
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.
12  *
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.
17  *
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
21  */
22 #include "avformat.h"
23 #include "bitstream.h"
24 #include "riff.h"    /* for CodecTag */
25
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 */
29
30 #define TAG_END           0
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
38 #define TAG_JPEG2         21
39 #define TAG_PLACEOBJECT2  26
40 #define TAG_STREAMHEAD2   45
41 #define TAG_VIDEOSTREAM   60
42 #define TAG_VIDEOFRAME    61
43
44 #define TAG_LONG         0x100
45
46 /* flags for shape definition */
47 #define FLAG_MOVETO      0x01
48 #define FLAG_SETFILL0    0x02
49 #define FLAG_SETFILL1    0x04
50
51 #define AUDIO_FIFO_SIZE 65536
52
53 /* character id used */
54 #define BITMAP_ID 0
55 #define VIDEO_ID 0
56 #define SHAPE_ID  1
57
58 #undef NDEBUG
59 #include <assert.h>
60
61 typedef struct {
62     int audio_stream_index;
63     offset_t duration_pos;
64     offset_t tag_pos;
65
66     int samples_per_frame;
67     int sound_samples;
68     int video_samples;
69     int swf_frame_number;
70     int video_frame_number;
71     int ms_per_frame;
72     int tag;
73
74     uint8_t *audio_fifo;
75     int audio_in_pos;
76     int audio_out_pos;
77     int audio_size;
78
79     int video_type;
80     int audio_type;
81 } SWFContext;
82
83 static const CodecTag swf_codec_tags[] = {
84     {CODEC_ID_FLV1, 0x02},
85     {CODEC_ID_VP6F, 0x04},
86     {0, 0},
87 };
88
89 static const int sSampleRates[3][4] = {
90     {44100, 48000, 32000, 0},
91     {22050, 24000, 16000, 0},
92     {11025, 12000,  8000, 0},
93 };
94
95 static const int sBitRates[2][3][15] = {
96     {   {  0, 32, 64, 96,128,160,192,224,256,288,320,352,384,416,448},
97         {  0, 32, 48, 56, 64, 80, 96,112,128,160,192,224,256,320,384},
98         {  0, 32, 40, 48, 56, 64, 80, 96,112,128,160,192,224,256,320}
99     },
100     {   {  0, 32, 48, 56, 64, 80, 96,112,128,144,160,176,192,224,256},
101         {  0,  8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160},
102         {  0,  8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160}
103     },
104 };
105
106 static const int sSamplesPerFrame[3][3] =
107 {
108     {  384,     1152,    1152 },
109     {  384,     1152,     576 },
110     {  384,     1152,     576 }
111 };
112
113 static const int sBitsPerSlot[3] = {
114     32,
115     8,
116     8
117 };
118
119 static int swf_mp3_info(void *data, int *byteSize, int *samplesPerFrame, int *sampleRate, int *isMono )
120 {
121     uint8_t *dataTmp = (uint8_t *)data;
122     uint32_t header = ( (uint32_t)dataTmp[0] << 24 ) | ( (uint32_t)dataTmp[1] << 16 ) | ( (uint32_t)dataTmp[2] << 8 ) | (uint32_t)dataTmp[3];
123     int layerID = 3 - ((header >> 17) & 0x03);
124     int bitRateID = ((header >> 12) & 0x0f);
125     int sampleRateID = ((header >> 10) & 0x03);
126     int bitRate = 0;
127     int bitsPerSlot = sBitsPerSlot[layerID];
128     int isPadded = ((header >> 9) & 0x01);
129
130     if ( (( header >> 21 ) & 0x7ff) != 0x7ff ) {
131         return 0;
132     }
133
134     *isMono = ((header >>  6) & 0x03) == 0x03;
135
136     if ( (header >> 19 ) & 0x01 ) {
137         *sampleRate = sSampleRates[0][sampleRateID];
138         bitRate = sBitRates[0][layerID][bitRateID] * 1000;
139         *samplesPerFrame = sSamplesPerFrame[0][layerID];
140     } else {
141         if ( (header >> 20) & 0x01 ) {
142             *sampleRate = sSampleRates[1][sampleRateID];
143             bitRate = sBitRates[1][layerID][bitRateID] * 1000;
144             *samplesPerFrame = sSamplesPerFrame[1][layerID];
145         } else {
146             *sampleRate = sSampleRates[2][sampleRateID];
147             bitRate = sBitRates[1][layerID][bitRateID] * 1000;
148             *samplesPerFrame = sSamplesPerFrame[2][layerID];
149         }
150     }
151
152     *byteSize = ( ( ( ( *samplesPerFrame * (bitRate / bitsPerSlot) ) / *sampleRate ) + isPadded ) );
153
154     return 1;
155 }
156
157 #ifdef CONFIG_MUXERS
158 static void put_swf_tag(AVFormatContext *s, int tag)
159 {
160     SWFContext *swf = s->priv_data;
161     ByteIOContext *pb = &s->pb;
162
163     swf->tag_pos = url_ftell(pb);
164     swf->tag = tag;
165     /* reserve some room for the tag */
166     if (tag & TAG_LONG) {
167         put_le16(pb, 0);
168         put_le32(pb, 0);
169     } else {
170         put_le16(pb, 0);
171     }
172 }
173
174 static void put_swf_end_tag(AVFormatContext *s)
175 {
176     SWFContext *swf = s->priv_data;
177     ByteIOContext *pb = &s->pb;
178     offset_t pos;
179     int tag_len, tag;
180
181     pos = url_ftell(pb);
182     tag_len = pos - swf->tag_pos - 2;
183     tag = swf->tag;
184     url_fseek(pb, swf->tag_pos, SEEK_SET);
185     if (tag & TAG_LONG) {
186         tag &= ~TAG_LONG;
187         put_le16(pb, (tag << 6) | 0x3f);
188         put_le32(pb, tag_len - 4);
189     } else {
190         assert(tag_len < 0x3f);
191         put_le16(pb, (tag << 6) | tag_len);
192     }
193     url_fseek(pb, pos, SEEK_SET);
194 }
195
196 static inline void max_nbits(int *nbits_ptr, int val)
197 {
198     int n;
199
200     if (val == 0)
201         return;
202     val = abs(val);
203     n = 1;
204     while (val != 0) {
205         n++;
206         val >>= 1;
207     }
208     if (n > *nbits_ptr)
209         *nbits_ptr = n;
210 }
211
212 static void put_swf_rect(ByteIOContext *pb,
213                          int xmin, int xmax, int ymin, int ymax)
214 {
215     PutBitContext p;
216     uint8_t buf[256];
217     int nbits, mask;
218
219     init_put_bits(&p, buf, sizeof(buf));
220
221     nbits = 0;
222     max_nbits(&nbits, xmin);
223     max_nbits(&nbits, xmax);
224     max_nbits(&nbits, ymin);
225     max_nbits(&nbits, ymax);
226     mask = (1 << nbits) - 1;
227
228     /* rectangle info */
229     put_bits(&p, 5, nbits);
230     put_bits(&p, nbits, xmin & mask);
231     put_bits(&p, nbits, xmax & mask);
232     put_bits(&p, nbits, ymin & mask);
233     put_bits(&p, nbits, ymax & mask);
234
235     flush_put_bits(&p);
236     put_buffer(pb, buf, pbBufPtr(&p) - p.buf);
237 }
238
239 static void put_swf_line_edge(PutBitContext *pb, int dx, int dy)
240 {
241     int nbits, mask;
242
243     put_bits(pb, 1, 1); /* edge */
244     put_bits(pb, 1, 1); /* line select */
245     nbits = 2;
246     max_nbits(&nbits, dx);
247     max_nbits(&nbits, dy);
248
249     mask = (1 << nbits) - 1;
250     put_bits(pb, 4, nbits - 2); /* 16 bits precision */
251     if (dx == 0) {
252       put_bits(pb, 1, 0);
253       put_bits(pb, 1, 1);
254       put_bits(pb, nbits, dy & mask);
255     } else if (dy == 0) {
256       put_bits(pb, 1, 0);
257       put_bits(pb, 1, 0);
258       put_bits(pb, nbits, dx & mask);
259     } else {
260       put_bits(pb, 1, 1);
261       put_bits(pb, nbits, dx & mask);
262       put_bits(pb, nbits, dy & mask);
263     }
264 }
265
266 #define FRAC_BITS 16
267
268 /* put matrix */
269 static void put_swf_matrix(ByteIOContext *pb,
270                            int a, int b, int c, int d, int tx, int ty)
271 {
272     PutBitContext p;
273     uint8_t buf[256];
274     int nbits;
275
276     init_put_bits(&p, buf, sizeof(buf));
277
278     put_bits(&p, 1, 1); /* a, d present */
279     nbits = 1;
280     max_nbits(&nbits, a);
281     max_nbits(&nbits, d);
282     put_bits(&p, 5, nbits); /* nb bits */
283     put_bits(&p, nbits, a);
284     put_bits(&p, nbits, d);
285
286     put_bits(&p, 1, 1); /* b, c present */
287     nbits = 1;
288     max_nbits(&nbits, c);
289     max_nbits(&nbits, b);
290     put_bits(&p, 5, nbits); /* nb bits */
291     put_bits(&p, nbits, c);
292     put_bits(&p, nbits, b);
293
294     nbits = 1;
295     max_nbits(&nbits, tx);
296     max_nbits(&nbits, ty);
297     put_bits(&p, 5, nbits); /* nb bits */
298     put_bits(&p, nbits, tx);
299     put_bits(&p, nbits, ty);
300
301     flush_put_bits(&p);
302     put_buffer(pb, buf, pbBufPtr(&p) - p.buf);
303 }
304
305 /* */
306 static int swf_write_header(AVFormatContext *s)
307 {
308     SWFContext *swf = s->priv_data;
309     ByteIOContext *pb = &s->pb;
310     AVCodecContext *enc, *audio_enc, *video_enc;
311     PutBitContext p;
312     uint8_t buf1[256];
313     int i, width, height, rate, rate_base;
314
315     swf->audio_in_pos = 0;
316     swf->audio_out_pos = 0;
317     swf->audio_size = 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;
323
324     video_enc = NULL;
325     audio_enc = NULL;
326     for(i=0;i<s->nb_streams;i++) {
327         enc = s->streams[i]->codec;
328         if (enc->codec_type == CODEC_TYPE_AUDIO)
329             audio_enc = enc;
330         else {
331             if ( enc->codec_id == CODEC_ID_VP6F ||
332                  enc->codec_id == CODEC_ID_FLV1 ||
333                  enc->codec_id == CODEC_ID_MJPEG ) {
334                 video_enc = enc;
335             } else {
336                 av_log(enc, AV_LOG_ERROR, "SWF only supports VP6, FLV1 and MJPEG\n");
337                 return -1;
338             }
339         }
340     }
341
342     if (!video_enc) {
343         /* currenty, cannot work correctly if audio only */
344         swf->video_type = 0;
345         width = 320;
346         height = 200;
347         rate = 10;
348         rate_base= 1;
349     } else {
350         swf->video_type = video_enc->codec_id;
351         width = video_enc->width;
352         height = video_enc->height;
353         rate = video_enc->time_base.den;
354         rate_base = video_enc->time_base.num;
355     }
356
357     if (!audio_enc ) {
358         swf->audio_type = 0;
359         swf->samples_per_frame = ( 44100. * rate_base ) / rate;
360     } else {
361         swf->audio_type = audio_enc->codec_id;
362         swf->samples_per_frame = ( ( audio_enc->sample_rate ) * rate_base ) / rate;
363     }
364
365     put_tag(pb, "FWS");
366     if ( video_enc && video_enc->codec_id == CODEC_ID_VP6F ) {
367         put_byte(pb, 8); /* version (version 8 and above support VP6 codec) */
368     } else if ( video_enc && video_enc->codec_id == CODEC_ID_FLV1 ) {
369         put_byte(pb, 6); /* version (version 6 and above support FLV1 codec) */
370     } else {
371         put_byte(pb, 4); /* version (should use 4 for mpeg audio support) */
372     }
373     put_le32(pb, DUMMY_FILE_SIZE); /* dummy size
374                                       (will be patched if not streamed) */
375
376     put_swf_rect(pb, 0, width * 20, 0, height * 20);
377     put_le16(pb, (rate * 256) / rate_base); /* frame rate */
378     swf->duration_pos = url_ftell(pb);
379     put_le16(pb, (uint16_t)(DUMMY_DURATION * (int64_t)rate / rate_base)); /* frame count */
380
381     /* define a shape with the jpeg inside */
382     if ( video_enc && (video_enc->codec_id == CODEC_ID_VP6F ||
383                        video_enc->codec_id == CODEC_ID_FLV1 )) {
384     } else if ( video_enc && video_enc->codec_id == CODEC_ID_MJPEG ) {
385         put_swf_tag(s, TAG_DEFINESHAPE);
386
387         put_le16(pb, SHAPE_ID); /* ID of shape */
388         /* bounding rectangle */
389         put_swf_rect(pb, 0, width, 0, height);
390         /* style info */
391         put_byte(pb, 1); /* one fill style */
392         put_byte(pb, 0x41); /* clipped bitmap fill */
393         put_le16(pb, BITMAP_ID); /* bitmap ID */
394         /* position of the bitmap */
395         put_swf_matrix(pb, (int)(1.0 * (1 << FRAC_BITS)), 0,
396                         0, (int)(1.0 * (1 << FRAC_BITS)), 0, 0);
397         put_byte(pb, 0); /* no line style */
398
399         /* shape drawing */
400         init_put_bits(&p, buf1, sizeof(buf1));
401         put_bits(&p, 4, 1); /* one fill bit */
402         put_bits(&p, 4, 0); /* zero line bit */
403
404         put_bits(&p, 1, 0); /* not an edge */
405         put_bits(&p, 5, FLAG_MOVETO | FLAG_SETFILL0);
406         put_bits(&p, 5, 1); /* nbits */
407         put_bits(&p, 1, 0); /* X */
408         put_bits(&p, 1, 0); /* Y */
409         put_bits(&p, 1, 1); /* set fill style 1 */
410
411         /* draw the rectangle ! */
412         put_swf_line_edge(&p, width, 0);
413         put_swf_line_edge(&p, 0, height);
414         put_swf_line_edge(&p, -width, 0);
415         put_swf_line_edge(&p, 0, -height);
416
417         /* end of shape */
418         put_bits(&p, 1, 0); /* not an edge */
419         put_bits(&p, 5, 0);
420
421         flush_put_bits(&p);
422         put_buffer(pb, buf1, pbBufPtr(&p) - p.buf);
423
424         put_swf_end_tag(s);
425     }
426
427     if (audio_enc && audio_enc->codec_id == CODEC_ID_MP3 ) {
428         int v;
429
430         /* start sound */
431         put_swf_tag(s, TAG_STREAMHEAD2);
432
433         v = 0;
434         switch(audio_enc->sample_rate) {
435         case 11025:
436             v |= 1 << 2;
437             break;
438         case 22050:
439             v |= 2 << 2;
440             break;
441         case 44100:
442             v |= 3 << 2;
443             break;
444         default:
445             /* not supported */
446             av_log(s, AV_LOG_ERROR, "swf doesnt support that sample rate, choose from (44100, 22050, 11025)\n");
447             av_free(swf->audio_fifo);
448             return -1;
449         }
450         v |= 0x02; /* 16 bit playback */
451         if (audio_enc->channels == 2)
452             v |= 0x01; /* stereo playback */
453         put_byte(&s->pb, v);
454         v |= 0x20; /* mp3 compressed */
455         put_byte(&s->pb, v);
456         put_le16(&s->pb, swf->samples_per_frame);  /* avg samples per frame */
457         put_le16(&s->pb, 0);
458
459         put_swf_end_tag(s);
460     }
461
462     put_flush_packet(&s->pb);
463     return 0;
464 }
465
466 static int swf_write_video(AVFormatContext *s,
467                            AVCodecContext *enc, const uint8_t *buf, int size)
468 {
469     SWFContext *swf = s->priv_data;
470     ByteIOContext *pb = &s->pb;
471     int c = 0;
472     int outSize = 0;
473     int outSamples = 0;
474
475     /* Flash Player limit */
476     if ( swf->swf_frame_number == 16000 ) {
477         av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
478     }
479
480     if ( swf->audio_type ) {
481         /* Prescan audio data for this swf frame */
482 retry_swf_audio_packet:
483         if ( ( swf->audio_size-outSize ) >= 4 ) {
484             int mp3FrameSize = 0;
485             int mp3SampleRate = 0;
486             int mp3IsMono = 0;
487             int mp3SamplesPerFrame = 0;
488
489             /* copy out mp3 header from ring buffer */
490             uint8_t header[4];
491             for (c=0; c<4; c++) {
492                 header[c] = swf->audio_fifo[(swf->audio_in_pos+outSize+c) % AUDIO_FIFO_SIZE];
493             }
494
495             if ( swf_mp3_info(header,&mp3FrameSize,&mp3SamplesPerFrame,&mp3SampleRate,&mp3IsMono) ) {
496                 if ( ( swf->audio_size-outSize ) >= mp3FrameSize ) {
497                     outSize += mp3FrameSize;
498                     outSamples += mp3SamplesPerFrame;
499                     if ( ( swf->sound_samples + outSamples + swf->samples_per_frame ) < swf->video_samples ) {
500                         goto retry_swf_audio_packet;
501                     }
502                 }
503             } else {
504                 /* invalid mp3 data, skip forward
505                 we need to do this since the Flash Player
506                 does not like custom headers */
507                 swf->audio_in_pos ++;
508                 swf->audio_size --;
509                 swf->audio_in_pos %= AUDIO_FIFO_SIZE;
510                 goto retry_swf_audio_packet;
511             }
512         }
513
514         /* audio stream is behind video stream, bail */
515         if ( ( swf->sound_samples + outSamples + swf->samples_per_frame ) < swf->video_samples ) {
516             return 0;
517         }
518     }
519
520             if ( swf->video_type == CODEC_ID_VP6F ||
521                  swf->video_type == CODEC_ID_FLV1 ) {
522                 if ( swf->video_frame_number == 0 ) {
523                     /* create a new video object */
524                     put_swf_tag(s, TAG_VIDEOSTREAM);
525                     put_le16(pb, VIDEO_ID);
526                     put_le16(pb, 15000 ); /* hard flash player limit */
527                     put_le16(pb, enc->width);
528                     put_le16(pb, enc->height);
529                     put_byte(pb, 0);
530                     put_byte(pb,codec_get_tag(swf_codec_tags,swf->video_type));
531                     put_swf_end_tag(s);
532
533                     /* place the video object for the first time */
534                     put_swf_tag(s, TAG_PLACEOBJECT2);
535                     put_byte(pb, 0x36);
536                     put_le16(pb, 1);
537                     put_le16(pb, VIDEO_ID);
538                     put_swf_matrix(pb, 1 << FRAC_BITS, 0, 0, 1 << FRAC_BITS, 0, 0);
539                     put_le16(pb, swf->video_frame_number );
540                     put_byte(pb, 'v');
541                     put_byte(pb, 'i');
542                     put_byte(pb, 'd');
543                     put_byte(pb, 'e');
544                     put_byte(pb, 'o');
545                     put_byte(pb, 0x00);
546                     put_swf_end_tag(s);
547                 } else {
548                     /* mark the character for update */
549                     put_swf_tag(s, TAG_PLACEOBJECT2);
550                     put_byte(pb, 0x11);
551                     put_le16(pb, 1);
552                     put_le16(pb, swf->video_frame_number );
553                     put_swf_end_tag(s);
554                 }
555
556                     /* set video frame data */
557                     put_swf_tag(s, TAG_VIDEOFRAME | TAG_LONG);
558                     put_le16(pb, VIDEO_ID);
559                     put_le16(pb, swf->video_frame_number++ );
560                     put_buffer(pb, buf, size);
561                     put_swf_end_tag(s);
562             } else if ( swf->video_type == CODEC_ID_MJPEG ) {
563                 if (swf->swf_frame_number > 0) {
564                     /* remove the shape */
565                     put_swf_tag(s, TAG_REMOVEOBJECT);
566                     put_le16(pb, SHAPE_ID); /* shape ID */
567                     put_le16(pb, 1); /* depth */
568                     put_swf_end_tag(s);
569
570                     /* free the bitmap */
571                     put_swf_tag(s, TAG_FREECHARACTER);
572                     put_le16(pb, BITMAP_ID);
573                     put_swf_end_tag(s);
574                 }
575
576                 put_swf_tag(s, TAG_JPEG2 | TAG_LONG);
577
578                 put_le16(pb, BITMAP_ID); /* ID of the image */
579
580                 /* a dummy jpeg header seems to be required */
581                 put_byte(pb, 0xff);
582                 put_byte(pb, 0xd8);
583                 put_byte(pb, 0xff);
584                 put_byte(pb, 0xd9);
585                 /* write the jpeg image */
586                 put_buffer(pb, buf, size);
587
588                 put_swf_end_tag(s);
589
590                 /* draw the shape */
591
592                 put_swf_tag(s, TAG_PLACEOBJECT);
593                 put_le16(pb, SHAPE_ID); /* shape ID */
594                 put_le16(pb, 1); /* depth */
595                 put_swf_matrix(pb, 20 << FRAC_BITS, 0, 0, 20 << FRAC_BITS, 0, 0);
596                 put_swf_end_tag(s);
597             } else {
598                 /* invalid codec */
599             }
600
601             swf->swf_frame_number ++;
602
603     swf->video_samples += swf->samples_per_frame;
604
605     /* streaming sound always should be placed just before showframe tags */
606     if ( outSize > 0 ) {
607         put_swf_tag(s, TAG_STREAMBLOCK | TAG_LONG);
608         put_le16(pb, outSamples);
609         put_le16(pb, 0);
610         for (c=0; c<outSize; c++) {
611             put_byte(pb,swf->audio_fifo[(swf->audio_in_pos+c) % AUDIO_FIFO_SIZE]);
612         }
613         put_swf_end_tag(s);
614
615         /* update FIFO */
616         swf->sound_samples += outSamples;
617         swf->audio_in_pos += outSize;
618         swf->audio_size -= outSize;
619         swf->audio_in_pos %= AUDIO_FIFO_SIZE;
620     }
621
622     /* output the frame */
623     put_swf_tag(s, TAG_SHOWFRAME);
624     put_swf_end_tag(s);
625
626     put_flush_packet(&s->pb);
627
628     return 0;
629 }
630
631 static int swf_write_audio(AVFormatContext *s,
632                            AVCodecContext *enc, const uint8_t *buf, int size)
633 {
634     SWFContext *swf = s->priv_data;
635     int c = 0;
636
637     /* Flash Player limit */
638     if ( swf->swf_frame_number == 16000 ) {
639         av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
640     }
641
642     if (enc->codec_id == CODEC_ID_MP3 ) {
643         for (c=0; c<size; c++) {
644             swf->audio_fifo[(swf->audio_out_pos+c)%AUDIO_FIFO_SIZE] = buf[c];
645         }
646         swf->audio_size += size;
647         swf->audio_out_pos += size;
648         swf->audio_out_pos %= AUDIO_FIFO_SIZE;
649     }
650
651     /* if audio only stream make sure we add swf frames */
652     if ( swf->video_type == 0 ) {
653         swf_write_video(s, enc, 0, 0);
654     }
655
656     return 0;
657 }
658
659 static int swf_write_packet(AVFormatContext *s, AVPacket *pkt)
660 {
661     AVCodecContext *codec = s->streams[pkt->stream_index]->codec;
662     if (codec->codec_type == CODEC_TYPE_AUDIO)
663         return swf_write_audio(s, codec, pkt->data, pkt->size);
664     else
665         return swf_write_video(s, codec, pkt->data, pkt->size);
666 }
667
668 static int swf_write_trailer(AVFormatContext *s)
669 {
670     SWFContext *swf = s->priv_data;
671     ByteIOContext *pb = &s->pb;
672     AVCodecContext *enc, *video_enc;
673     int file_size, i;
674
675     video_enc = NULL;
676     for(i=0;i<s->nb_streams;i++) {
677         enc = s->streams[i]->codec;
678         if (enc->codec_type == CODEC_TYPE_VIDEO)
679             video_enc = enc;
680     }
681
682     put_swf_tag(s, TAG_END);
683     put_swf_end_tag(s);
684
685     put_flush_packet(&s->pb);
686
687     /* patch file size and number of frames if not streamed */
688     if (!url_is_streamed(&s->pb) && video_enc) {
689         file_size = url_ftell(pb);
690         url_fseek(pb, 4, SEEK_SET);
691         put_le32(pb, file_size);
692         url_fseek(pb, swf->duration_pos, SEEK_SET);
693         put_le16(pb, video_enc->frame_number);
694         url_fseek(pb, file_size, SEEK_SET);
695     }
696
697     av_free(swf->audio_fifo);
698
699     return 0;
700 }
701 #endif //CONFIG_MUXERS
702
703 /*********************************************/
704 /* Extract FLV encoded frame and MP3 from swf
705    Note that the detection of the real frame
706    is inaccurate at this point as it can be
707    quite tricky to determine, you almost certainly
708    will get a bad audio/video sync */
709
710 static int get_swf_tag(ByteIOContext *pb, int *len_ptr)
711 {
712     int tag, len;
713
714     if (url_feof(pb))
715         return -1;
716
717     tag = get_le16(pb);
718     len = tag & 0x3f;
719     tag = tag >> 6;
720     if (len == 0x3f) {
721         len = get_le32(pb);
722     }
723 //    av_log(NULL, AV_LOG_DEBUG, "Tag: %d - Len: %d\n", tag, len);
724     *len_ptr = len;
725     return tag;
726 }
727
728
729 static int swf_probe(AVProbeData *p)
730 {
731     /* check file header */
732     if (p->buf_size <= 16)
733         return 0;
734     if ((p->buf[0] == 'F' || p->buf[0] == 'C') && p->buf[1] == 'W' &&
735         p->buf[2] == 'S')
736         return AVPROBE_SCORE_MAX;
737     else
738         return 0;
739 }
740
741 static int swf_read_header(AVFormatContext *s, AVFormatParameters *ap)
742 {
743     SWFContext *swf = s->priv_data;
744     ByteIOContext *pb = &s->pb;
745     int nbits, len, frame_rate, tag, v;
746     offset_t firstTagOff;
747     AVStream *ast = 0;
748     AVStream *vst = 0;
749
750     tag = get_be32(pb) & 0xffffff00;
751
752     if (tag == MKBETAG('C', 'W', 'S', 0))
753     {
754         av_log(s, AV_LOG_ERROR, "Compressed SWF format not supported\n");
755         return AVERROR_IO;
756     }
757     if (tag != MKBETAG('F', 'W', 'S', 0))
758         return AVERROR_IO;
759     get_le32(pb);
760     /* skip rectangle size */
761     nbits = get_byte(pb) >> 3;
762     len = (4 * nbits - 3 + 7) / 8;
763     url_fskip(pb, len);
764     frame_rate = get_le16(pb);
765     get_le16(pb); /* frame count */
766
767     /* The Flash Player converts 8.8 frame rates
768        to milliseconds internally. Do the same to get
769        a correct framerate */
770     swf->ms_per_frame = ( 1000 * 256 ) / frame_rate;
771     swf->samples_per_frame = 0;
772
773     firstTagOff = url_ftell(pb);
774     for(;;) {
775         tag = get_swf_tag(pb, &len);
776         if (tag < 0) {
777             if ( ast || vst ) {
778                 if ( vst && ast ) {
779                     vst->codec->time_base.den = ast->codec->sample_rate / swf->samples_per_frame;
780                     vst->codec->time_base.num = 1;
781                 }
782                 break;
783             }
784             av_log(s, AV_LOG_ERROR, "No media found in SWF\n");
785             return AVERROR_IO;
786         }
787         if ( tag == TAG_VIDEOSTREAM && !vst) {
788             int ch_id = get_le16(pb);
789             get_le16(pb);
790             get_le16(pb);
791             get_le16(pb);
792             get_byte(pb);
793             /* Check for FLV1 */
794             vst = av_new_stream(s, ch_id);
795             av_set_pts_info(vst, 24, 1, 1000); /* 24 bit pts in ms */
796             vst->codec->codec_type = CODEC_TYPE_VIDEO;
797             vst->codec->codec_id = codec_get_id(swf_codec_tags, get_byte(pb));
798             if (swf->samples_per_frame) {
799                 vst->codec->time_base.den = 1000. / swf->ms_per_frame;
800                 vst->codec->time_base.num = 1;
801             }
802         } else if ( ( tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2 ) && !ast) {
803             /* streaming found */
804             int sample_rate_code;
805             get_byte(pb);
806             v = get_byte(pb);
807             swf->samples_per_frame = get_le16(pb);
808             ast = av_new_stream(s, -1); /* -1 to avoid clash with video stream ch_id */
809             av_set_pts_info(ast, 24, 1, 1000); /* 24 bit pts in ms */
810             swf->audio_stream_index = ast->index;
811             ast->codec->channels = 1 + (v&1);
812             ast->codec->codec_type = CODEC_TYPE_AUDIO;
813             if (v & 0x20)
814                 ast->codec->codec_id = CODEC_ID_MP3;
815             ast->need_parsing = 1;
816             sample_rate_code= (v>>2) & 3;
817             if (!sample_rate_code)
818                 return AVERROR_IO;
819             ast->codec->sample_rate = 11025 << (sample_rate_code-1);
820             if (len > 4)
821                 url_fskip(pb,len-4);
822
823         } else if (tag == TAG_JPEG2 && !vst) {
824             vst = av_new_stream(s, -2); /* -2 to avoid clash with video stream and audio stream */
825             av_set_pts_info(vst, 24, 1, 1000); /* 24 bit pts in ms */
826             vst->codec->codec_type = CODEC_TYPE_VIDEO;
827             vst->codec->codec_id = CODEC_ID_MJPEG;
828             if (swf->samples_per_frame) {
829                 vst->codec->time_base.den = 1000. / swf->ms_per_frame;
830                 vst->codec->time_base.num = 1;
831             }
832             url_fskip(pb, len);
833         } else {
834             url_fskip(pb, len);
835         }
836     }
837     url_fseek(pb, firstTagOff, SEEK_SET);
838
839     return 0;
840 }
841
842 static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
843 {
844     SWFContext *swf = s->priv_data;
845     ByteIOContext *pb = &s->pb;
846     AVStream *st = 0;
847     int tag, len, i, frame;
848
849     for(;;) {
850         tag = get_swf_tag(pb, &len);
851         if (tag < 0)
852             return AVERROR_IO;
853         if (tag == TAG_VIDEOFRAME) {
854             int ch_id = get_le16(pb);
855             len -= 2;
856             for( i=0; i<s->nb_streams; i++ ) {
857                 st = s->streams[i];
858                 if (st->codec->codec_type == CODEC_TYPE_VIDEO && st->id == ch_id) {
859                     frame = get_le16(pb);
860                     av_get_packet(pb, pkt, len-2);
861                     pkt->pts = frame * swf->ms_per_frame;
862                     pkt->stream_index = st->index;
863                     return pkt->size;
864                 }
865             }
866         } else if (tag == TAG_STREAMBLOCK) {
867             st = s->streams[swf->audio_stream_index];
868             if (st->codec->codec_id == CODEC_ID_MP3) {
869                 url_fskip(pb, 4);
870                 av_get_packet(pb, pkt, len-4);
871                 pkt->stream_index = st->index;
872                 return pkt->size;
873             }
874         } else if (tag == TAG_JPEG2) {
875             for (i=0; i<s->nb_streams; i++) {
876                 st = s->streams[i];
877                 if (st->id == -2) {
878                     get_le16(pb); /* BITMAP_ID */
879                     av_new_packet(pkt, len-2);
880                     get_buffer(pb, pkt->data, 4);
881                     if (BE_32(pkt->data) == 0xffd8ffd9) {
882                         /* old SWF files containing SOI/EOI as data start */
883                         pkt->size -= 4;
884                         get_buffer(pb, pkt->data, pkt->size);
885                     } else {
886                         get_buffer(pb, pkt->data + 4, pkt->size - 4);
887                     }
888                     pkt->stream_index = st->index;
889                     return pkt->size;
890                 }
891             }
892         }
893         url_fskip(pb, len);
894     }
895     return 0;
896 }
897
898 static int swf_read_close(AVFormatContext *s)
899 {
900      return 0;
901 }
902
903 #ifdef CONFIG_SWF_DEMUXER
904 AVInputFormat swf_demuxer = {
905     "swf",
906     "Flash format",
907     sizeof(SWFContext),
908     swf_probe,
909     swf_read_header,
910     swf_read_packet,
911     swf_read_close,
912 };
913 #endif
914 #ifdef CONFIG_SWF_MUXER
915 AVOutputFormat swf_muxer = {
916     "swf",
917     "Flash format",
918     "application/x-shockwave-flash",
919     "swf",
920     sizeof(SWFContext),
921     CODEC_ID_MP3,
922     CODEC_ID_FLV1,
923     swf_write_header,
924     swf_write_packet,
925     swf_write_trailer,
926 };
927 #endif