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