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