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