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