]> git.sesse.net Git - ffmpeg/blob - libavformat/swf.c
enable mjpeg in swf
[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     }
695
696     av_free(swf->audio_fifo);
697
698     return 0;
699 }
700 #endif //CONFIG_MUXERS
701
702 /*********************************************/
703 /* Extract FLV encoded frame and MP3 from swf
704    Note that the detection of the real frame
705    is inaccurate at this point as it can be
706    quite tricky to determine, you almost certainly
707    will get a bad audio/video sync */
708
709 static int get_swf_tag(ByteIOContext *pb, int *len_ptr)
710 {
711     int tag, len;
712
713     if (url_feof(pb))
714         return -1;
715
716     tag = get_le16(pb);
717     len = tag & 0x3f;
718     tag = tag >> 6;
719     if (len == 0x3f) {
720         len = get_le32(pb);
721     }
722 //    av_log(NULL, AV_LOG_DEBUG, "Tag: %d - Len: %d\n", tag, len);
723     *len_ptr = len;
724     return tag;
725 }
726
727
728 static int swf_probe(AVProbeData *p)
729 {
730     /* check file header */
731     if (p->buf_size <= 16)
732         return 0;
733     if ((p->buf[0] == 'F' || p->buf[0] == 'C') && p->buf[1] == 'W' &&
734         p->buf[2] == 'S')
735         return AVPROBE_SCORE_MAX;
736     else
737         return 0;
738 }
739
740 static int swf_read_header(AVFormatContext *s, AVFormatParameters *ap)
741 {
742     SWFContext *swf = 0;
743     ByteIOContext *pb = &s->pb;
744     int nbits, len, frame_rate, tag, v;
745     offset_t firstTagOff;
746     AVStream *ast = 0;
747     AVStream *vst = 0;
748
749     swf = av_malloc(sizeof(SWFContext));
750     if (!swf)
751         return -1;
752     s->priv_data = swf;
753
754     tag = get_be32(pb) & 0xffffff00;
755
756     if (tag == MKBETAG('C', 'W', 'S', 0))
757     {
758         av_log(s, AV_LOG_ERROR, "Compressed SWF format not supported\n");
759         return AVERROR_IO;
760     }
761     if (tag != MKBETAG('F', 'W', 'S', 0))
762         return AVERROR_IO;
763     get_le32(pb);
764     /* skip rectangle size */
765     nbits = get_byte(pb) >> 3;
766     len = (4 * nbits - 3 + 7) / 8;
767     url_fskip(pb, len);
768     frame_rate = get_le16(pb);
769     get_le16(pb); /* frame count */
770
771     /* The Flash Player converts 8.8 frame rates
772        to milliseconds internally. Do the same to get
773        a correct framerate */
774     swf->ms_per_frame = ( 1000 * 256 ) / frame_rate;
775     swf->samples_per_frame = 0;
776
777     firstTagOff = url_ftell(pb);
778     for(;;) {
779         tag = get_swf_tag(pb, &len);
780         if (tag < 0) {
781             if ( ast || vst ) {
782                 if ( vst && ast ) {
783                     vst->codec->time_base.den = ast->codec->sample_rate / swf->samples_per_frame;
784                     vst->codec->time_base.num = 1;
785                 }
786                 break;
787             }
788             av_log(s, AV_LOG_ERROR, "No media found in SWF\n");
789             return AVERROR_IO;
790         }
791         if ( tag == TAG_VIDEOSTREAM && !vst) {
792             int ch_id = get_le16(pb);
793             get_le16(pb);
794             get_le16(pb);
795             get_le16(pb);
796             get_byte(pb);
797             /* Check for FLV1 */
798             vst = av_new_stream(s, ch_id);
799             av_set_pts_info(vst, 24, 1, 1000); /* 24 bit pts in ms */
800             vst->codec->codec_type = CODEC_TYPE_VIDEO;
801             vst->codec->codec_id = codec_get_id(swf_codec_tags, get_byte(pb));
802             if (swf->samples_per_frame) {
803                 vst->codec->time_base.den = 1000. / swf->ms_per_frame;
804                 vst->codec->time_base.num = 1;
805             }
806         } else if ( ( tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2 ) && !ast) {
807             /* streaming found */
808             get_byte(pb);
809             v = get_byte(pb);
810             swf->samples_per_frame = get_le16(pb);
811             ast = av_new_stream(s, -1); /* -1 to avoid clash with video stream ch_id */
812             av_set_pts_info(ast, 24, 1, 1000); /* 24 bit pts in ms */
813             swf->audio_stream_index = ast->index;
814             ast->codec->channels = 1 + (v&1);
815             ast->codec->codec_type = CODEC_TYPE_AUDIO;
816             if (v & 0x20)
817                 ast->codec->codec_id = CODEC_ID_MP3;
818             ast->need_parsing = 1;
819             switch((v>> 2) & 0x03) {
820             case 1:
821                 ast->codec->sample_rate = 11025;
822                 break;
823             case 2:
824                 ast->codec->sample_rate = 22050;
825                 break;
826             case 3:
827                 ast->codec->sample_rate = 44100;
828                 break;
829             default:
830                 return AVERROR_IO;
831             }
832
833             if (len > 4)
834                 url_fskip(pb,len-4);
835
836         } else if (tag == TAG_JPEG2 && !vst) {
837             vst = av_new_stream(s, -2); /* -2 to avoid clash with video stream and audio stream */
838             av_set_pts_info(vst, 24, 1, 1000); /* 24 bit pts in ms */
839             vst->codec->codec_type = CODEC_TYPE_VIDEO;
840             vst->codec->codec_id = CODEC_ID_MJPEG;
841             if (swf->samples_per_frame) {
842                 vst->codec->time_base.den = 1000. / swf->ms_per_frame;
843                 vst->codec->time_base.num = 1;
844             }
845             url_fskip(pb, len);
846         } else {
847             url_fskip(pb, len);
848         }
849     }
850     url_fseek(pb, firstTagOff, SEEK_SET);
851
852     return 0;
853 }
854
855 static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
856 {
857     SWFContext *swf = s->priv_data;
858     ByteIOContext *pb = &s->pb;
859     AVStream *st = 0;
860     int tag, len, i, frame;
861
862     for(;;) {
863         tag = get_swf_tag(pb, &len);
864         if (tag < 0)
865             return AVERROR_IO;
866         if (tag == TAG_VIDEOFRAME) {
867             int ch_id = get_le16(pb);
868             len -= 2;
869             for( i=0; i<s->nb_streams; i++ ) {
870                 st = s->streams[i];
871                 if (st->codec->codec_type == CODEC_TYPE_VIDEO && st->id == ch_id) {
872                     frame = get_le16(pb);
873                     av_get_packet(pb, pkt, len-2);
874                     pkt->pts = frame * swf->ms_per_frame;
875                     pkt->stream_index = st->index;
876                     return pkt->size;
877                 }
878             }
879         } else if (tag == TAG_STREAMBLOCK) {
880             st = s->streams[swf->audio_stream_index];
881             if (st->codec->codec_id == CODEC_ID_MP3) {
882                 url_fskip(pb, 4);
883                 av_get_packet(pb, pkt, len-4);
884                 pkt->stream_index = st->index;
885                 return pkt->size;
886             }
887         } else if (tag == TAG_JPEG2) {
888             for (i=0; i<s->nb_streams; i++) {
889                 st = s->streams[i];
890                 if (st->id == -2) {
891                     get_le16(pb); /* BITMAP_ID */
892                     av_new_packet(pkt, len-2);
893                     get_buffer(pb, pkt->data, 4);
894                     if (BE_32(pkt->data) == 0xffd8ffd9) {
895                         /* old SWF files containing SOI/EOI as data start */
896                         pkt->size -= 4;
897                         get_buffer(pb, pkt->data, pkt->size);
898                     } else {
899                         get_buffer(pb, pkt->data + 4, pkt->size - 4);
900                     }
901                     pkt->stream_index = st->index;
902                     return pkt->size;
903                 }
904             }
905         }
906         url_fskip(pb, len);
907     }
908     return 0;
909 }
910
911 static int swf_read_close(AVFormatContext *s)
912 {
913      return 0;
914 }
915
916 #ifdef CONFIG_SWF_DEMUXER
917 AVInputFormat swf_demuxer = {
918     "swf",
919     "Flash format",
920     sizeof(SWFContext),
921     swf_probe,
922     swf_read_header,
923     swf_read_packet,
924     swf_read_close,
925 };
926 #endif
927 #ifdef CONFIG_SWF_MUXER
928 AVOutputFormat swf_muxer = {
929     "swf",
930     "Flash format",
931     "application/x-shockwave-flash",
932     "swf",
933     sizeof(SWFContext),
934     CODEC_ID_MP3,
935     CODEC_ID_FLV1,
936     swf_write_header,
937     swf_write_packet,
938     swf_write_trailer,
939 };
940 #endif