]> git.sesse.net Git - ffmpeg/blob - libavformat/swf.c
Set FLV_SAMPLESSIZE_16BIT for ADPCM.
[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 AVCodecTag swf_codec_tags[] = {
84     {CODEC_ID_FLV1, 0x02},
85     {CODEC_ID_VP6F, 0x04},
86     {0, 0},
87 };
88
89 static const AVCodecTag swf_audio_codec_tags[] = {
90     {CODEC_ID_PCM_S16LE,  0x00},
91     {CODEC_ID_ADPCM_SWF,  0x01},
92     {CODEC_ID_MP3,        0x02},
93     {CODEC_ID_PCM_S16LE,  0x03},
94   //{CODEC_ID_NELLYMOSER, 0x06},
95     {0, 0},
96 };
97
98 static const int sSampleRates[3][4] = {
99     {44100, 48000, 32000, 0},
100     {22050, 24000, 16000, 0},
101     {11025, 12000,  8000, 0},
102 };
103
104 static const int sBitRates[2][3][15] = {
105     {   {  0, 32, 64, 96,128,160,192,224,256,288,320,352,384,416,448},
106         {  0, 32, 48, 56, 64, 80, 96,112,128,160,192,224,256,320,384},
107         {  0, 32, 40, 48, 56, 64, 80, 96,112,128,160,192,224,256,320}
108     },
109     {   {  0, 32, 48, 56, 64, 80, 96,112,128,144,160,176,192,224,256},
110         {  0,  8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160},
111         {  0,  8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160}
112     },
113 };
114
115 static const int sSamplesPerFrame[3][3] =
116 {
117     {  384,     1152,    1152 },
118     {  384,     1152,     576 },
119     {  384,     1152,     576 }
120 };
121
122 static const int sBitsPerSlot[3] = {
123     32,
124     8,
125     8
126 };
127
128 static int swf_mp3_info(void *data, int *byteSize, int *samplesPerFrame, int *sampleRate, int *isMono )
129 {
130     uint32_t header = AV_RB32(data);
131     int layerID = 3 - ((header >> 17) & 0x03);
132     int bitRateID = ((header >> 12) & 0x0f);
133     int sampleRateID = ((header >> 10) & 0x03);
134     int bitRate = 0;
135     int bitsPerSlot = sBitsPerSlot[layerID];
136     int isPadded = ((header >> 9) & 0x01);
137
138     if ( (( header >> 21 ) & 0x7ff) != 0x7ff ) {
139         return 0;
140     }
141
142     *isMono = ((header >>  6) & 0x03) == 0x03;
143
144     if ( (header >> 19 ) & 0x01 ) {
145         *sampleRate = sSampleRates[0][sampleRateID];
146         bitRate = sBitRates[0][layerID][bitRateID] * 1000;
147         *samplesPerFrame = sSamplesPerFrame[0][layerID];
148     } else {
149         if ( (header >> 20) & 0x01 ) {
150             *sampleRate = sSampleRates[1][sampleRateID];
151             bitRate = sBitRates[1][layerID][bitRateID] * 1000;
152             *samplesPerFrame = sSamplesPerFrame[1][layerID];
153         } else {
154             *sampleRate = sSampleRates[2][sampleRateID];
155             bitRate = sBitRates[1][layerID][bitRateID] * 1000;
156             *samplesPerFrame = sSamplesPerFrame[2][layerID];
157         }
158     }
159
160     *byteSize = ( ( ( ( *samplesPerFrame * (bitRate / bitsPerSlot) ) / *sampleRate ) + isPadded ) );
161
162     return 1;
163 }
164
165 #ifdef CONFIG_MUXERS
166 static void put_swf_tag(AVFormatContext *s, int tag)
167 {
168     SWFContext *swf = s->priv_data;
169     ByteIOContext *pb = &s->pb;
170
171     swf->tag_pos = url_ftell(pb);
172     swf->tag = tag;
173     /* reserve some room for the tag */
174     if (tag & TAG_LONG) {
175         put_le16(pb, 0);
176         put_le32(pb, 0);
177     } else {
178         put_le16(pb, 0);
179     }
180 }
181
182 static void put_swf_end_tag(AVFormatContext *s)
183 {
184     SWFContext *swf = s->priv_data;
185     ByteIOContext *pb = &s->pb;
186     offset_t pos;
187     int tag_len, tag;
188
189     pos = url_ftell(pb);
190     tag_len = pos - swf->tag_pos - 2;
191     tag = swf->tag;
192     url_fseek(pb, swf->tag_pos, SEEK_SET);
193     if (tag & TAG_LONG) {
194         tag &= ~TAG_LONG;
195         put_le16(pb, (tag << 6) | 0x3f);
196         put_le32(pb, tag_len - 4);
197     } else {
198         assert(tag_len < 0x3f);
199         put_le16(pb, (tag << 6) | tag_len);
200     }
201     url_fseek(pb, pos, SEEK_SET);
202 }
203
204 static inline void max_nbits(int *nbits_ptr, int val)
205 {
206     int n;
207
208     if (val == 0)
209         return;
210     val = abs(val);
211     n = 1;
212     while (val != 0) {
213         n++;
214         val >>= 1;
215     }
216     if (n > *nbits_ptr)
217         *nbits_ptr = n;
218 }
219
220 static void put_swf_rect(ByteIOContext *pb,
221                          int xmin, int xmax, int ymin, int ymax)
222 {
223     PutBitContext p;
224     uint8_t buf[256];
225     int nbits, mask;
226
227     init_put_bits(&p, buf, sizeof(buf));
228
229     nbits = 0;
230     max_nbits(&nbits, xmin);
231     max_nbits(&nbits, xmax);
232     max_nbits(&nbits, ymin);
233     max_nbits(&nbits, ymax);
234     mask = (1 << nbits) - 1;
235
236     /* rectangle info */
237     put_bits(&p, 5, nbits);
238     put_bits(&p, nbits, xmin & mask);
239     put_bits(&p, nbits, xmax & mask);
240     put_bits(&p, nbits, ymin & mask);
241     put_bits(&p, nbits, ymax & mask);
242
243     flush_put_bits(&p);
244     put_buffer(pb, buf, pbBufPtr(&p) - p.buf);
245 }
246
247 static void put_swf_line_edge(PutBitContext *pb, int dx, int dy)
248 {
249     int nbits, mask;
250
251     put_bits(pb, 1, 1); /* edge */
252     put_bits(pb, 1, 1); /* line select */
253     nbits = 2;
254     max_nbits(&nbits, dx);
255     max_nbits(&nbits, dy);
256
257     mask = (1 << nbits) - 1;
258     put_bits(pb, 4, nbits - 2); /* 16 bits precision */
259     if (dx == 0) {
260       put_bits(pb, 1, 0);
261       put_bits(pb, 1, 1);
262       put_bits(pb, nbits, dy & mask);
263     } else if (dy == 0) {
264       put_bits(pb, 1, 0);
265       put_bits(pb, 1, 0);
266       put_bits(pb, nbits, dx & mask);
267     } else {
268       put_bits(pb, 1, 1);
269       put_bits(pb, nbits, dx & mask);
270       put_bits(pb, nbits, dy & mask);
271     }
272 }
273
274 #define FRAC_BITS 16
275
276 /* put matrix */
277 static void put_swf_matrix(ByteIOContext *pb,
278                            int a, int b, int c, int d, int tx, int ty)
279 {
280     PutBitContext p;
281     uint8_t buf[256];
282     int nbits;
283
284     init_put_bits(&p, buf, sizeof(buf));
285
286     put_bits(&p, 1, 1); /* a, d present */
287     nbits = 1;
288     max_nbits(&nbits, a);
289     max_nbits(&nbits, d);
290     put_bits(&p, 5, nbits); /* nb bits */
291     put_bits(&p, nbits, a);
292     put_bits(&p, nbits, d);
293
294     put_bits(&p, 1, 1); /* b, c present */
295     nbits = 1;
296     max_nbits(&nbits, c);
297     max_nbits(&nbits, b);
298     put_bits(&p, 5, nbits); /* nb bits */
299     put_bits(&p, nbits, c);
300     put_bits(&p, nbits, b);
301
302     nbits = 1;
303     max_nbits(&nbits, tx);
304     max_nbits(&nbits, ty);
305     put_bits(&p, 5, nbits); /* nb bits */
306     put_bits(&p, nbits, tx);
307     put_bits(&p, nbits, ty);
308
309     flush_put_bits(&p);
310     put_buffer(pb, buf, pbBufPtr(&p) - p.buf);
311 }
312
313 /* */
314 static int swf_write_header(AVFormatContext *s)
315 {
316     SWFContext *swf = s->priv_data;
317     ByteIOContext *pb = &s->pb;
318     AVCodecContext *enc, *audio_enc, *video_enc;
319     PutBitContext p;
320     uint8_t buf1[256];
321     int i, width, height, rate, rate_base;
322
323     swf->audio_in_pos = 0;
324     swf->audio_out_pos = 0;
325     swf->audio_size = 0;
326     swf->audio_fifo = av_malloc(AUDIO_FIFO_SIZE);
327     swf->sound_samples = 0;
328     swf->video_samples = 0;
329     swf->swf_frame_number = 0;
330     swf->video_frame_number = 0;
331
332     video_enc = NULL;
333     audio_enc = NULL;
334     for(i=0;i<s->nb_streams;i++) {
335         enc = s->streams[i]->codec;
336         if (enc->codec_type == CODEC_TYPE_AUDIO)
337             audio_enc = enc;
338         else {
339             if ( enc->codec_id == CODEC_ID_VP6F ||
340                  enc->codec_id == CODEC_ID_FLV1 ||
341                  enc->codec_id == CODEC_ID_MJPEG ) {
342                 video_enc = enc;
343             } else {
344                 av_log(enc, AV_LOG_ERROR, "SWF only supports VP6, FLV1 and MJPEG\n");
345                 return -1;
346             }
347         }
348     }
349
350     if (!video_enc) {
351         /* currenty, cannot work correctly if audio only */
352         swf->video_type = 0;
353         width = 320;
354         height = 200;
355         rate = 10;
356         rate_base= 1;
357     } else {
358         swf->video_type = video_enc->codec_id;
359         width = video_enc->width;
360         height = video_enc->height;
361         rate = video_enc->time_base.den;
362         rate_base = video_enc->time_base.num;
363     }
364
365     if (!audio_enc ) {
366         swf->audio_type = 0;
367         swf->samples_per_frame = ( 44100. * rate_base ) / rate;
368     } else {
369         swf->audio_type = audio_enc->codec_id;
370         swf->samples_per_frame = ( ( audio_enc->sample_rate ) * rate_base ) / rate;
371     }
372
373     put_tag(pb, "FWS");
374     if ( video_enc && video_enc->codec_id == CODEC_ID_VP6F ) {
375         put_byte(pb, 8); /* version (version 8 and above support VP6 codec) */
376     } else if ( video_enc && video_enc->codec_id == CODEC_ID_FLV1 ) {
377         put_byte(pb, 6); /* version (version 6 and above support FLV1 codec) */
378     } else {
379         put_byte(pb, 4); /* version (should use 4 for mpeg audio support) */
380     }
381     put_le32(pb, DUMMY_FILE_SIZE); /* dummy size
382                                       (will be patched if not streamed) */
383
384     put_swf_rect(pb, 0, width * 20, 0, height * 20);
385     put_le16(pb, (rate * 256) / rate_base); /* frame rate */
386     swf->duration_pos = url_ftell(pb);
387     put_le16(pb, (uint16_t)(DUMMY_DURATION * (int64_t)rate / rate_base)); /* frame count */
388
389     /* define a shape with the jpeg inside */
390     if ( video_enc && (video_enc->codec_id == CODEC_ID_VP6F ||
391                        video_enc->codec_id == CODEC_ID_FLV1 )) {
392     } else if ( video_enc && video_enc->codec_id == CODEC_ID_MJPEG ) {
393         put_swf_tag(s, TAG_DEFINESHAPE);
394
395         put_le16(pb, SHAPE_ID); /* ID of shape */
396         /* bounding rectangle */
397         put_swf_rect(pb, 0, width, 0, height);
398         /* style info */
399         put_byte(pb, 1); /* one fill style */
400         put_byte(pb, 0x41); /* clipped bitmap fill */
401         put_le16(pb, BITMAP_ID); /* bitmap ID */
402         /* position of the bitmap */
403         put_swf_matrix(pb, (int)(1.0 * (1 << FRAC_BITS)), 0,
404                         0, (int)(1.0 * (1 << FRAC_BITS)), 0, 0);
405         put_byte(pb, 0); /* no line style */
406
407         /* shape drawing */
408         init_put_bits(&p, buf1, sizeof(buf1));
409         put_bits(&p, 4, 1); /* one fill bit */
410         put_bits(&p, 4, 0); /* zero line bit */
411
412         put_bits(&p, 1, 0); /* not an edge */
413         put_bits(&p, 5, FLAG_MOVETO | FLAG_SETFILL0);
414         put_bits(&p, 5, 1); /* nbits */
415         put_bits(&p, 1, 0); /* X */
416         put_bits(&p, 1, 0); /* Y */
417         put_bits(&p, 1, 1); /* set fill style 1 */
418
419         /* draw the rectangle ! */
420         put_swf_line_edge(&p, width, 0);
421         put_swf_line_edge(&p, 0, height);
422         put_swf_line_edge(&p, -width, 0);
423         put_swf_line_edge(&p, 0, -height);
424
425         /* end of shape */
426         put_bits(&p, 1, 0); /* not an edge */
427         put_bits(&p, 5, 0);
428
429         flush_put_bits(&p);
430         put_buffer(pb, buf1, pbBufPtr(&p) - p.buf);
431
432         put_swf_end_tag(s);
433     }
434
435     if (audio_enc && audio_enc->codec_id == CODEC_ID_MP3 ) {
436         int v;
437
438         /* start sound */
439         put_swf_tag(s, TAG_STREAMHEAD2);
440
441         v = 0;
442         switch(audio_enc->sample_rate) {
443         case 11025:
444             v |= 1 << 2;
445             break;
446         case 22050:
447             v |= 2 << 2;
448             break;
449         case 44100:
450             v |= 3 << 2;
451             break;
452         default:
453             /* not supported */
454             av_log(s, AV_LOG_ERROR, "swf doesnt support that sample rate, choose from (44100, 22050, 11025)\n");
455             av_free(swf->audio_fifo);
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         url_fseek(pb, file_size, SEEK_SET);
703     }
704
705     av_free(swf->audio_fifo);
706
707     return 0;
708 }
709 #endif //CONFIG_MUXERS
710
711 /*********************************************/
712 /* Extract FLV encoded frame and MP3 from swf
713    Note that the detection of the real frame
714    is inaccurate at this point as it can be
715    quite tricky to determine, you almost certainly
716    will get a bad audio/video sync */
717
718 static int get_swf_tag(ByteIOContext *pb, int *len_ptr)
719 {
720     int tag, len;
721
722     if (url_feof(pb))
723         return -1;
724
725     tag = get_le16(pb);
726     len = tag & 0x3f;
727     tag = tag >> 6;
728     if (len == 0x3f) {
729         len = get_le32(pb);
730     }
731 //    av_log(NULL, AV_LOG_DEBUG, "Tag: %d - Len: %d\n", tag, len);
732     *len_ptr = len;
733     return tag;
734 }
735
736
737 static int swf_probe(AVProbeData *p)
738 {
739     /* check file header */
740     if (p->buf_size <= 16)
741         return 0;
742     if ((p->buf[0] == 'F' || p->buf[0] == 'C') && p->buf[1] == 'W' &&
743         p->buf[2] == 'S')
744         return AVPROBE_SCORE_MAX;
745     else
746         return 0;
747 }
748
749 static int swf_read_header(AVFormatContext *s, AVFormatParameters *ap)
750 {
751     SWFContext *swf = s->priv_data;
752     ByteIOContext *pb = &s->pb;
753     int nbits, len, frame_rate, tag, v;
754     offset_t frame_offset = -1;
755     AVStream *ast = 0;
756     AVStream *vst = 0;
757
758     tag = get_be32(pb) & 0xffffff00;
759
760     if (tag == MKBETAG('C', 'W', 'S', 0))
761     {
762         av_log(s, AV_LOG_ERROR, "Compressed SWF format not supported\n");
763         return AVERROR_IO;
764     }
765     if (tag != MKBETAG('F', 'W', 'S', 0))
766         return AVERROR_IO;
767     get_le32(pb);
768     /* skip rectangle size */
769     nbits = get_byte(pb) >> 3;
770     len = (4 * nbits - 3 + 7) / 8;
771     url_fskip(pb, len);
772     frame_rate = get_le16(pb);
773     get_le16(pb); /* frame count */
774
775     /* The Flash Player converts 8.8 frame rates
776        to milliseconds internally. Do the same to get
777        a correct framerate */
778     swf->ms_per_frame = ( 1000 * 256 ) / frame_rate;
779     swf->samples_per_frame = 0;
780
781     for(;;) {
782         offset_t tag_offset = url_ftell(pb);
783         tag = get_swf_tag(pb, &len);
784         if (tag < 0 || tag == TAG_VIDEOFRAME || tag == TAG_STREAMBLOCK) {
785             url_fseek(pb, frame_offset == -1 ? tag_offset : frame_offset, SEEK_SET);
786             break;
787         }
788         if ( tag == TAG_VIDEOSTREAM && !vst) {
789             int ch_id = get_le16(pb);
790             get_le16(pb);
791             get_le16(pb);
792             get_le16(pb);
793             get_byte(pb);
794             /* Check for FLV1 */
795             vst = av_new_stream(s, ch_id);
796             vst->codec->codec_type = CODEC_TYPE_VIDEO;
797             vst->codec->codec_id = codec_get_id(swf_codec_tags, get_byte(pb));
798         } else if ( ( tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2 ) && !ast) {
799             /* streaming found */
800             int sample_rate_code;
801             get_byte(pb);
802             v = get_byte(pb);
803             swf->samples_per_frame = get_le16(pb);
804             ast = av_new_stream(s, -1); /* -1 to avoid clash with video stream ch_id */
805             av_set_pts_info(ast, 24, 1, 1000); /* 24 bit pts in ms */
806             swf->audio_stream_index = ast->index;
807             ast->codec->channels = 1 + (v&1);
808             ast->codec->codec_type = CODEC_TYPE_AUDIO;
809             ast->codec->codec_id = codec_get_id(swf_audio_codec_tags, (v>>4) & 15);
810             ast->need_parsing = 1;
811             sample_rate_code= (v>>2) & 3;
812             if (!sample_rate_code)
813                 return AVERROR_IO;
814             ast->codec->sample_rate = 11025 << (sample_rate_code-1);
815             if (len > 4)
816                 url_fskip(pb,len-4);
817
818         } else if (tag == TAG_JPEG2 && !vst) {
819             vst = av_new_stream(s, -2); /* -2 to avoid clash with video stream and audio stream */
820             vst->codec->codec_type = CODEC_TYPE_VIDEO;
821             vst->codec->codec_id = CODEC_ID_MJPEG;
822             url_fskip(pb, len);
823             frame_offset = tag_offset;
824         } else {
825             url_fskip(pb, len);
826         }
827     }
828     if (vst) {
829         av_set_pts_info(vst, 24, 1, 1000); /* 24 bit pts in ms */
830         if (swf->ms_per_frame) {
831             vst->codec->time_base.den = 1000. / swf->ms_per_frame;
832             vst->codec->time_base.num = 1;
833         }
834     }
835     return 0;
836 }
837
838 static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
839 {
840     SWFContext *swf = s->priv_data;
841     ByteIOContext *pb = &s->pb;
842     AVStream *st = 0;
843     int tag, len, i, frame;
844
845     for(;;) {
846         tag = get_swf_tag(pb, &len);
847         if (tag < 0)
848             return AVERROR_IO;
849         if (tag == TAG_VIDEOFRAME) {
850             int ch_id = get_le16(pb);
851             len -= 2;
852             for( i=0; i<s->nb_streams; i++ ) {
853                 st = s->streams[i];
854                 if (st->codec->codec_type == CODEC_TYPE_VIDEO && st->id == ch_id) {
855                     frame = get_le16(pb);
856                     av_get_packet(pb, pkt, len-2);
857                     pkt->pts = frame * swf->ms_per_frame;
858                     pkt->stream_index = st->index;
859                     return pkt->size;
860                 }
861             }
862         } else if (tag == TAG_STREAMBLOCK) {
863             st = s->streams[swf->audio_stream_index];
864             if (st->codec->codec_id == CODEC_ID_MP3) {
865                 url_fskip(pb, 4);
866                 av_get_packet(pb, pkt, len-4);
867             } else { // ADPCM, PCM
868                 av_get_packet(pb, pkt, len);
869             }
870             pkt->stream_index = st->index;
871             return pkt->size;
872         } else if (tag == TAG_JPEG2) {
873             for (i=0; i<s->nb_streams; i++) {
874                 st = s->streams[i];
875                 if (st->id == -2) {
876                     get_le16(pb); /* BITMAP_ID */
877                     av_new_packet(pkt, len-2);
878                     get_buffer(pb, pkt->data, 4);
879                     if (AV_RB32(pkt->data) == 0xffd8ffd9) {
880                         /* old SWF files containing SOI/EOI as data start */
881                         pkt->size -= 4;
882                         get_buffer(pb, pkt->data, pkt->size);
883                     } else {
884                         get_buffer(pb, pkt->data + 4, pkt->size - 4);
885                     }
886                     pkt->stream_index = st->index;
887                     return pkt->size;
888                 }
889             }
890         }
891         url_fskip(pb, len);
892     }
893     return 0;
894 }
895
896 static int swf_read_close(AVFormatContext *s)
897 {
898      return 0;
899 }
900
901 #ifdef CONFIG_SWF_DEMUXER
902 AVInputFormat swf_demuxer = {
903     "swf",
904     "Flash format",
905     sizeof(SWFContext),
906     swf_probe,
907     swf_read_header,
908     swf_read_packet,
909     swf_read_close,
910 };
911 #endif
912 #ifdef CONFIG_SWF_MUXER
913 AVOutputFormat swf_muxer = {
914     "swf",
915     "Flash format",
916     "application/x-shockwave-flash",
917     "swf",
918     sizeof(SWFContext),
919     CODEC_ID_MP3,
920     CODEC_ID_FLV1,
921     swf_write_header,
922     swf_write_packet,
923     swf_write_trailer,
924 };
925 #endif