]> git.sesse.net Git - ffmpeg/blob - libavformat/swf.c
add support for tta in matroska
[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
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_log(s, AV_LOG_ERROR, "swf doesnt support that sample rate, choose from (44100, 22050, 11025)\n");
454             av_free(swf->audio_fifo);
455             av_free(swf);
456             return -1;
457         }
458         v |= 0x02; /* 16 bit playback */
459         if (audio_enc->channels == 2)
460             v |= 0x01; /* stereo playback */
461         put_byte(&s->pb, v);
462         v |= 0x20; /* mp3 compressed */
463         put_byte(&s->pb, v);
464         put_le16(&s->pb, swf->samples_per_frame);  /* avg samples per frame */
465         put_le16(&s->pb, 0);
466
467         put_swf_end_tag(s);
468     }
469
470     put_flush_packet(&s->pb);
471     return 0;
472 }
473
474 static int swf_write_video(AVFormatContext *s,
475                            AVCodecContext *enc, const uint8_t *buf, int size)
476 {
477     SWFContext *swf = s->priv_data;
478     ByteIOContext *pb = &s->pb;
479     int c = 0;
480     int outSize = 0;
481     int outSamples = 0;
482
483     /* Flash Player limit */
484     if ( swf->swf_frame_number == 16000 ) {
485         av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
486     }
487
488     if ( swf->audio_type ) {
489         /* Prescan audio data for this swf frame */
490 retry_swf_audio_packet:
491         if ( ( swf->audio_size-outSize ) >= 4 ) {
492             int mp3FrameSize = 0;
493             int mp3SampleRate = 0;
494             int mp3IsMono = 0;
495             int mp3SamplesPerFrame = 0;
496
497             /* copy out mp3 header from ring buffer */
498             uint8_t header[4];
499             for (c=0; c<4; c++) {
500                 header[c] = swf->audio_fifo[(swf->audio_in_pos+outSize+c) % AUDIO_FIFO_SIZE];
501             }
502
503             if ( swf_mp3_info(header,&mp3FrameSize,&mp3SamplesPerFrame,&mp3SampleRate,&mp3IsMono) ) {
504                 if ( ( swf->audio_size-outSize ) >= mp3FrameSize ) {
505                     outSize += mp3FrameSize;
506                     outSamples += mp3SamplesPerFrame;
507                     if ( ( swf->sound_samples + outSamples + swf->samples_per_frame ) < swf->video_samples ) {
508                         goto retry_swf_audio_packet;
509                     }
510                 }
511             } else {
512                 /* invalid mp3 data, skip forward
513                 we need to do this since the Flash Player
514                 does not like custom headers */
515                 swf->audio_in_pos ++;
516                 swf->audio_size --;
517                 swf->audio_in_pos %= AUDIO_FIFO_SIZE;
518                 goto retry_swf_audio_packet;
519             }
520         }
521
522         /* audio stream is behind video stream, bail */
523         if ( ( swf->sound_samples + outSamples + swf->samples_per_frame ) < swf->video_samples ) {
524             return 0;
525         }
526     }
527
528             if ( swf->video_type == CODEC_ID_VP6F ||
529                  swf->video_type == CODEC_ID_FLV1 ) {
530                 if ( swf->video_frame_number == 0 ) {
531                     /* create a new video object */
532                     put_swf_tag(s, TAG_VIDEOSTREAM);
533                     put_le16(pb, VIDEO_ID);
534                     put_le16(pb, 15000 ); /* hard flash player limit */
535                     put_le16(pb, enc->width);
536                     put_le16(pb, enc->height);
537                     put_byte(pb, 0);
538                     put_byte(pb,codec_get_tag(swf_codec_tags,swf->video_type));
539                     put_swf_end_tag(s);
540
541                     /* place the video object for the first time */
542                     put_swf_tag(s, TAG_PLACEOBJECT2);
543                     put_byte(pb, 0x36);
544                     put_le16(pb, 1);
545                     put_le16(pb, VIDEO_ID);
546                     put_swf_matrix(pb, 1 << FRAC_BITS, 0, 0, 1 << FRAC_BITS, 0, 0);
547                     put_le16(pb, swf->video_frame_number );
548                     put_byte(pb, 'v');
549                     put_byte(pb, 'i');
550                     put_byte(pb, 'd');
551                     put_byte(pb, 'e');
552                     put_byte(pb, 'o');
553                     put_byte(pb, 0x00);
554                     put_swf_end_tag(s);
555                 } else {
556                     /* mark the character for update */
557                     put_swf_tag(s, TAG_PLACEOBJECT2);
558                     put_byte(pb, 0x11);
559                     put_le16(pb, 1);
560                     put_le16(pb, swf->video_frame_number );
561                     put_swf_end_tag(s);
562                 }
563
564                     /* set video frame data */
565                     put_swf_tag(s, TAG_VIDEOFRAME | TAG_LONG);
566                     put_le16(pb, VIDEO_ID);
567                     put_le16(pb, swf->video_frame_number++ );
568                     put_buffer(pb, buf, size);
569                     put_swf_end_tag(s);
570             } else if ( swf->video_type == CODEC_ID_MJPEG ) {
571                 if (swf->swf_frame_number > 0) {
572                     /* remove the shape */
573                     put_swf_tag(s, TAG_REMOVEOBJECT);
574                     put_le16(pb, SHAPE_ID); /* shape ID */
575                     put_le16(pb, 1); /* depth */
576                     put_swf_end_tag(s);
577
578                     /* free the bitmap */
579                     put_swf_tag(s, TAG_FREECHARACTER);
580                     put_le16(pb, BITMAP_ID);
581                     put_swf_end_tag(s);
582                 }
583
584                 put_swf_tag(s, TAG_JPEG2 | TAG_LONG);
585
586                 put_le16(pb, BITMAP_ID); /* ID of the image */
587
588                 /* a dummy jpeg header seems to be required */
589                 put_byte(pb, 0xff);
590                 put_byte(pb, 0xd8);
591                 put_byte(pb, 0xff);
592                 put_byte(pb, 0xd9);
593                 /* write the jpeg image */
594                 put_buffer(pb, buf, size);
595
596                 put_swf_end_tag(s);
597
598                 /* draw the shape */
599
600                 put_swf_tag(s, TAG_PLACEOBJECT);
601                 put_le16(pb, SHAPE_ID); /* shape ID */
602                 put_le16(pb, 1); /* depth */
603                 put_swf_matrix(pb, 20 << FRAC_BITS, 0, 0, 20 << FRAC_BITS, 0, 0);
604                 put_swf_end_tag(s);
605             } else {
606                 /* invalid codec */
607             }
608
609             swf->swf_frame_number ++;
610
611     swf->video_samples += swf->samples_per_frame;
612
613     /* streaming sound always should be placed just before showframe tags */
614     if ( outSize > 0 ) {
615         put_swf_tag(s, TAG_STREAMBLOCK | TAG_LONG);
616         put_le16(pb, outSamples);
617         put_le16(pb, 0);
618         for (c=0; c<outSize; c++) {
619             put_byte(pb,swf->audio_fifo[(swf->audio_in_pos+c) % AUDIO_FIFO_SIZE]);
620         }
621         put_swf_end_tag(s);
622
623         /* update FIFO */
624         swf->sound_samples += outSamples;
625         swf->audio_in_pos += outSize;
626         swf->audio_size -= outSize;
627         swf->audio_in_pos %= AUDIO_FIFO_SIZE;
628     }
629
630     /* output the frame */
631     put_swf_tag(s, TAG_SHOWFRAME);
632     put_swf_end_tag(s);
633
634     put_flush_packet(&s->pb);
635
636     return 0;
637 }
638
639 static int swf_write_audio(AVFormatContext *s,
640                            AVCodecContext *enc, const uint8_t *buf, int size)
641 {
642     SWFContext *swf = s->priv_data;
643     int c = 0;
644
645     /* Flash Player limit */
646     if ( swf->swf_frame_number == 16000 ) {
647         av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
648     }
649
650     if (enc->codec_id == CODEC_ID_MP3 ) {
651         for (c=0; c<size; c++) {
652             swf->audio_fifo[(swf->audio_out_pos+c)%AUDIO_FIFO_SIZE] = buf[c];
653         }
654         swf->audio_size += size;
655         swf->audio_out_pos += size;
656         swf->audio_out_pos %= AUDIO_FIFO_SIZE;
657     }
658
659     /* if audio only stream make sure we add swf frames */
660     if ( swf->video_type == 0 ) {
661         swf_write_video(s, enc, 0, 0);
662     }
663
664     return 0;
665 }
666
667 static int swf_write_packet(AVFormatContext *s, AVPacket *pkt)
668 {
669     AVCodecContext *codec = s->streams[pkt->stream_index]->codec;
670     if (codec->codec_type == CODEC_TYPE_AUDIO)
671         return swf_write_audio(s, codec, pkt->data, pkt->size);
672     else
673         return swf_write_video(s, codec, pkt->data, pkt->size);
674 }
675
676 static int swf_write_trailer(AVFormatContext *s)
677 {
678     SWFContext *swf = s->priv_data;
679     ByteIOContext *pb = &s->pb;
680     AVCodecContext *enc, *video_enc;
681     int file_size, i;
682
683     video_enc = NULL;
684     for(i=0;i<s->nb_streams;i++) {
685         enc = s->streams[i]->codec;
686         if (enc->codec_type == CODEC_TYPE_VIDEO)
687             video_enc = enc;
688     }
689
690     put_swf_tag(s, TAG_END);
691     put_swf_end_tag(s);
692
693     put_flush_packet(&s->pb);
694
695     /* patch file size and number of frames if not streamed */
696     if (!url_is_streamed(&s->pb) && video_enc) {
697         file_size = url_ftell(pb);
698         url_fseek(pb, 4, SEEK_SET);
699         put_le32(pb, file_size);
700         url_fseek(pb, swf->duration_pos, SEEK_SET);
701         put_le16(pb, video_enc->frame_number);
702     }
703
704     av_free(swf->audio_fifo);
705
706     return 0;
707 }
708 #endif //CONFIG_MUXERS
709
710 /*********************************************/
711 /* Extract FLV encoded frame and MP3 from swf
712    Note that the detection of the real frame
713    is inaccurate at this point as it can be
714    quite tricky to determine, you almost certainly
715    will get a bad audio/video sync */
716
717 static int get_swf_tag(ByteIOContext *pb, int *len_ptr)
718 {
719     int tag, len;
720
721     if (url_feof(pb))
722         return -1;
723
724     tag = get_le16(pb);
725     len = tag & 0x3f;
726     tag = tag >> 6;
727     if (len == 0x3f) {
728         len = get_le32(pb);
729     }
730 //    av_log(NULL, AV_LOG_DEBUG, "Tag: %d - Len: %d\n", tag, len);
731     *len_ptr = len;
732     return tag;
733 }
734
735
736 static int swf_probe(AVProbeData *p)
737 {
738     /* check file header */
739     if (p->buf_size <= 16)
740         return 0;
741     if ((p->buf[0] == 'F' || p->buf[0] == 'C') && p->buf[1] == 'W' &&
742         p->buf[2] == 'S')
743         return AVPROBE_SCORE_MAX;
744     else
745         return 0;
746 }
747
748 static int swf_read_header(AVFormatContext *s, AVFormatParameters *ap)
749 {
750     SWFContext *swf = 0;
751     ByteIOContext *pb = &s->pb;
752     int nbits, len, frame_rate, tag, v;
753     offset_t firstTagOff;
754     AVStream *ast = 0;
755     AVStream *vst = 0;
756
757     swf = av_malloc(sizeof(SWFContext));
758     if (!swf)
759         return -1;
760     s->priv_data = swf;
761
762     tag = get_be32(pb) & 0xffffff00;
763
764     if (tag == MKBETAG('C', 'W', 'S', 0))
765     {
766         av_log(s, AV_LOG_ERROR, "Compressed SWF format not supported\n");
767         return AVERROR_IO;
768     }
769     if (tag != MKBETAG('F', 'W', 'S', 0))
770         return AVERROR_IO;
771     get_le32(pb);
772     /* skip rectangle size */
773     nbits = get_byte(pb) >> 3;
774     len = (4 * nbits - 3 + 7) / 8;
775     url_fskip(pb, len);
776     frame_rate = get_le16(pb);
777     get_le16(pb); /* frame count */
778
779     /* The Flash Player converts 8.8 frame rates
780        to milliseconds internally. Do the same to get
781        a correct framerate */
782     swf->ms_per_frame = ( 1000 * 256 ) / frame_rate;
783     swf->samples_per_frame = 0;
784     swf->ch_id = -1;
785
786     firstTagOff = url_ftell(pb);
787     for(;;) {
788         tag = get_swf_tag(pb, &len);
789         if (tag < 0) {
790             if ( ast || vst ) {
791                 if ( vst && ast ) {
792                     vst->codec->time_base.den = ast->codec->sample_rate / swf->samples_per_frame;
793                     vst->codec->time_base.num = 1;
794                 }
795                 break;
796             }
797             av_log(s, AV_LOG_ERROR, "No media found in SWF\n");
798             return AVERROR_IO;
799         }
800         if ( tag == TAG_VIDEOSTREAM && !vst) {
801             int codec_id;
802             swf->ch_id = get_le16(pb);
803             get_le16(pb);
804             get_le16(pb);
805             get_le16(pb);
806             get_byte(pb);
807             /* Check for FLV1 */
808             codec_id = codec_get_id(swf_codec_tags, get_byte(pb));
809             if ( codec_id ) {
810                 vst = av_new_stream(s, 0);
811                 av_set_pts_info(vst, 24, 1, 1000); /* 24 bit pts in ms */
812
813                 vst->codec->codec_type = CODEC_TYPE_VIDEO;
814                 vst->codec->codec_id = codec_id;
815                 if ( swf->samples_per_frame ) {
816                     vst->codec->time_base.den = 1000. / swf->ms_per_frame;
817                     vst->codec->time_base.num = 1;
818                 }
819             }
820         } else if ( ( tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2 ) && !ast) {
821             /* streaming found */
822             get_byte(pb);
823             v = get_byte(pb);
824             swf->samples_per_frame = get_le16(pb);
825             if (len!=4)
826                 url_fskip(pb,len-4);
827             /* if mp3 streaming found, OK */
828             if ((v & 0x20) != 0) {
829                 if ( tag == TAG_STREAMHEAD2 ) {
830                     get_le16(pb);
831                 }
832                 ast = av_new_stream(s, 1);
833                 if (!ast)
834                     return -ENOMEM;
835                 av_set_pts_info(ast, 24, 1, 1000); /* 24 bit pts in ms */
836
837                 if (v & 0x01)
838                     ast->codec->channels = 2;
839                 else
840                     ast->codec->channels = 1;
841
842                 switch((v>> 2) & 0x03) {
843                 case 1:
844                     ast->codec->sample_rate = 11025;
845                     break;
846                 case 2:
847                     ast->codec->sample_rate = 22050;
848                     break;
849                 case 3:
850                     ast->codec->sample_rate = 44100;
851                     break;
852                 default:
853                     av_free(ast);
854                     return AVERROR_IO;
855                 }
856                 ast->codec->codec_type = CODEC_TYPE_AUDIO;
857                 ast->codec->codec_id = CODEC_ID_MP3;
858                 ast->need_parsing = 1;
859             }
860         } else {
861             url_fskip(pb, len);
862         }
863     }
864     url_fseek(pb, firstTagOff, SEEK_SET);
865
866     return 0;
867 }
868
869 static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
870 {
871     SWFContext *swf = s->priv_data;
872     ByteIOContext *pb = &s->pb;
873     AVStream *st = 0;
874     int tag, len, i, frame;
875
876     for(;;) {
877         tag = get_swf_tag(pb, &len);
878         if (tag < 0)
879             return AVERROR_IO;
880         if (tag == TAG_VIDEOFRAME) {
881             for( i=0; i<s->nb_streams; i++ ) {
882                 st = s->streams[i];
883                 if (st->id == 0) {
884                     if ( get_le16(pb) == swf->ch_id ) {
885                         frame = get_le16(pb);
886                         av_get_packet(pb, pkt, len-4);
887                         pkt->pts = frame * swf->ms_per_frame;
888                         pkt->stream_index = st->index;
889                         return pkt->size;
890                     } else {
891                         url_fskip(pb, len-2);
892                         continue;
893                     }
894                 }
895             }
896             url_fskip(pb, len);
897         } else if (tag == TAG_STREAMBLOCK) {
898             for( i=0; i<s->nb_streams; i++ ) {
899                 st = s->streams[i];
900                 if (st->id == 1) {
901                     url_fskip(pb, 4);
902                     av_get_packet(pb, pkt, len-4);
903                     pkt->stream_index = st->index;
904                     return pkt->size;
905                 }
906             }
907             url_fskip(pb, len);
908         } else {
909             url_fskip(pb, len);
910         }
911     }
912     return 0;
913 }
914
915 static int swf_read_close(AVFormatContext *s)
916 {
917      return 0;
918 }
919
920 #ifdef CONFIG_SWF_DEMUXER
921 AVInputFormat swf_demuxer = {
922     "swf",
923     "Flash format",
924     sizeof(SWFContext),
925     swf_probe,
926     swf_read_header,
927     swf_read_packet,
928     swf_read_close,
929 };
930 #endif
931 #ifdef CONFIG_SWF_MUXER
932 AVOutputFormat swf_muxer = {
933     "swf",
934     "Flash format",
935     "application/x-shockwave-flash",
936     "swf",
937     sizeof(SWFContext),
938     CODEC_ID_MP3,
939     CODEC_ID_FLV1,
940     swf_write_header,
941     swf_write_packet,
942     swf_write_trailer,
943 };
944 #endif