]> git.sesse.net Git - ffmpeg/blob - libavformat/swf.c
8dba80da75ac1a120f180a876a712835f1a69d09
[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[AUDIO_FIFO_SIZE];
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 #ifdef CONFIG_MUXERS
99 static void put_swf_tag(AVFormatContext *s, int tag)
100 {
101     SWFContext *swf = s->priv_data;
102     ByteIOContext *pb = &s->pb;
103
104     swf->tag_pos = url_ftell(pb);
105     swf->tag = tag;
106     /* reserve some room for the tag */
107     if (tag & TAG_LONG) {
108         put_le16(pb, 0);
109         put_le32(pb, 0);
110     } else {
111         put_le16(pb, 0);
112     }
113 }
114
115 static void put_swf_end_tag(AVFormatContext *s)
116 {
117     SWFContext *swf = s->priv_data;
118     ByteIOContext *pb = &s->pb;
119     offset_t pos;
120     int tag_len, tag;
121
122     pos = url_ftell(pb);
123     tag_len = pos - swf->tag_pos - 2;
124     tag = swf->tag;
125     url_fseek(pb, swf->tag_pos, SEEK_SET);
126     if (tag & TAG_LONG) {
127         tag &= ~TAG_LONG;
128         put_le16(pb, (tag << 6) | 0x3f);
129         put_le32(pb, tag_len - 4);
130     } else {
131         assert(tag_len < 0x3f);
132         put_le16(pb, (tag << 6) | tag_len);
133     }
134     url_fseek(pb, pos, SEEK_SET);
135 }
136
137 static inline void max_nbits(int *nbits_ptr, int val)
138 {
139     int n;
140
141     if (val == 0)
142         return;
143     val = abs(val);
144     n = 1;
145     while (val != 0) {
146         n++;
147         val >>= 1;
148     }
149     if (n > *nbits_ptr)
150         *nbits_ptr = n;
151 }
152
153 static void put_swf_rect(ByteIOContext *pb,
154                          int xmin, int xmax, int ymin, int ymax)
155 {
156     PutBitContext p;
157     uint8_t buf[256];
158     int nbits, mask;
159
160     init_put_bits(&p, buf, sizeof(buf));
161
162     nbits = 0;
163     max_nbits(&nbits, xmin);
164     max_nbits(&nbits, xmax);
165     max_nbits(&nbits, ymin);
166     max_nbits(&nbits, ymax);
167     mask = (1 << nbits) - 1;
168
169     /* rectangle info */
170     put_bits(&p, 5, nbits);
171     put_bits(&p, nbits, xmin & mask);
172     put_bits(&p, nbits, xmax & mask);
173     put_bits(&p, nbits, ymin & mask);
174     put_bits(&p, nbits, ymax & mask);
175
176     flush_put_bits(&p);
177     put_buffer(pb, buf, pbBufPtr(&p) - p.buf);
178 }
179
180 static void put_swf_line_edge(PutBitContext *pb, int dx, int dy)
181 {
182     int nbits, mask;
183
184     put_bits(pb, 1, 1); /* edge */
185     put_bits(pb, 1, 1); /* line select */
186     nbits = 2;
187     max_nbits(&nbits, dx);
188     max_nbits(&nbits, dy);
189
190     mask = (1 << nbits) - 1;
191     put_bits(pb, 4, nbits - 2); /* 16 bits precision */
192     if (dx == 0) {
193       put_bits(pb, 1, 0);
194       put_bits(pb, 1, 1);
195       put_bits(pb, nbits, dy & mask);
196     } else if (dy == 0) {
197       put_bits(pb, 1, 0);
198       put_bits(pb, 1, 0);
199       put_bits(pb, nbits, dx & mask);
200     } else {
201       put_bits(pb, 1, 1);
202       put_bits(pb, nbits, dx & mask);
203       put_bits(pb, nbits, dy & mask);
204     }
205 }
206
207 #define FRAC_BITS 16
208
209 /* put matrix */
210 static void put_swf_matrix(ByteIOContext *pb,
211                            int a, int b, int c, int d, int tx, int ty)
212 {
213     PutBitContext p;
214     uint8_t buf[256];
215     int nbits;
216
217     init_put_bits(&p, buf, sizeof(buf));
218
219     put_bits(&p, 1, 1); /* a, d present */
220     nbits = 1;
221     max_nbits(&nbits, a);
222     max_nbits(&nbits, d);
223     put_bits(&p, 5, nbits); /* nb bits */
224     put_bits(&p, nbits, a);
225     put_bits(&p, nbits, d);
226
227     put_bits(&p, 1, 1); /* b, c present */
228     nbits = 1;
229     max_nbits(&nbits, c);
230     max_nbits(&nbits, b);
231     put_bits(&p, 5, nbits); /* nb bits */
232     put_bits(&p, nbits, c);
233     put_bits(&p, nbits, b);
234
235     nbits = 1;
236     max_nbits(&nbits, tx);
237     max_nbits(&nbits, ty);
238     put_bits(&p, 5, nbits); /* nb bits */
239     put_bits(&p, nbits, tx);
240     put_bits(&p, nbits, ty);
241
242     flush_put_bits(&p);
243     put_buffer(pb, buf, pbBufPtr(&p) - p.buf);
244 }
245
246 /* */
247 static int swf_write_header(AVFormatContext *s)
248 {
249     SWFContext *swf = s->priv_data;
250     ByteIOContext *pb = &s->pb;
251     AVCodecContext *enc, *audio_enc, *video_enc;
252     PutBitContext p;
253     uint8_t buf1[256];
254     int i, width, height, rate, rate_base;
255
256     swf->audio_in_pos = 0;
257     swf->audio_out_pos = 0;
258     swf->audio_size = 0;
259     swf->sound_samples = 0;
260     swf->video_samples = 0;
261     swf->swf_frame_number = 0;
262     swf->video_frame_number = 0;
263
264     video_enc = NULL;
265     audio_enc = NULL;
266     for(i=0;i<s->nb_streams;i++) {
267         enc = s->streams[i]->codec;
268         if (enc->codec_type == CODEC_TYPE_AUDIO) {
269             if (enc->codec_id == CODEC_ID_MP3) {
270                 if (!enc->frame_size) {
271                     av_log(s, AV_LOG_ERROR, "audio frame size not set\n");
272                     return -1;
273                 }
274                 audio_enc = enc;
275             } else {
276                 av_log(enc, AV_LOG_ERROR, "SWF only supports MP3\n");
277                 return -1;
278             }
279         } else {
280             if ( enc->codec_id == CODEC_ID_VP6F ||
281                  enc->codec_id == CODEC_ID_FLV1 ||
282                  enc->codec_id == CODEC_ID_MJPEG ) {
283                 video_enc = enc;
284             } else {
285                 av_log(enc, AV_LOG_ERROR, "SWF only supports VP6, FLV1 and MJPEG\n");
286                 return -1;
287             }
288         }
289     }
290
291     if (!video_enc) {
292         /* currenty, cannot work correctly if audio only */
293         swf->video_type = 0;
294         width = 320;
295         height = 200;
296         rate = 10;
297         rate_base= 1;
298     } else {
299         swf->video_type = video_enc->codec_id;
300         width = video_enc->width;
301         height = video_enc->height;
302         rate = video_enc->time_base.den;
303         rate_base = video_enc->time_base.num;
304     }
305
306     if (!audio_enc ) {
307         swf->audio_type = 0;
308         swf->samples_per_frame = ( 44100. * rate_base ) / rate;
309     } else {
310         swf->audio_type = audio_enc->codec_id;
311         swf->samples_per_frame = ( ( audio_enc->sample_rate ) * rate_base ) / rate;
312     }
313
314     put_tag(pb, "FWS");
315     if ( video_enc && video_enc->codec_id == CODEC_ID_VP6F ) {
316         put_byte(pb, 8); /* version (version 8 and above support VP6 codec) */
317     } else if ( video_enc && video_enc->codec_id == CODEC_ID_FLV1 ) {
318         put_byte(pb, 6); /* version (version 6 and above support FLV1 codec) */
319     } else {
320         put_byte(pb, 4); /* version (should use 4 for mpeg audio support) */
321     }
322     put_le32(pb, DUMMY_FILE_SIZE); /* dummy size
323                                       (will be patched if not streamed) */
324
325     put_swf_rect(pb, 0, width * 20, 0, height * 20);
326     put_le16(pb, (rate * 256) / rate_base); /* frame rate */
327     swf->duration_pos = url_ftell(pb);
328     put_le16(pb, (uint16_t)(DUMMY_DURATION * (int64_t)rate / rate_base)); /* frame count */
329
330     /* define a shape with the jpeg inside */
331     if ( video_enc && (video_enc->codec_id == CODEC_ID_VP6F ||
332                        video_enc->codec_id == CODEC_ID_FLV1 )) {
333     } else if ( video_enc && video_enc->codec_id == CODEC_ID_MJPEG ) {
334         put_swf_tag(s, TAG_DEFINESHAPE);
335
336         put_le16(pb, SHAPE_ID); /* ID of shape */
337         /* bounding rectangle */
338         put_swf_rect(pb, 0, width, 0, height);
339         /* style info */
340         put_byte(pb, 1); /* one fill style */
341         put_byte(pb, 0x41); /* clipped bitmap fill */
342         put_le16(pb, BITMAP_ID); /* bitmap ID */
343         /* position of the bitmap */
344         put_swf_matrix(pb, (int)(1.0 * (1 << FRAC_BITS)), 0,
345                         0, (int)(1.0 * (1 << FRAC_BITS)), 0, 0);
346         put_byte(pb, 0); /* no line style */
347
348         /* shape drawing */
349         init_put_bits(&p, buf1, sizeof(buf1));
350         put_bits(&p, 4, 1); /* one fill bit */
351         put_bits(&p, 4, 0); /* zero line bit */
352
353         put_bits(&p, 1, 0); /* not an edge */
354         put_bits(&p, 5, FLAG_MOVETO | FLAG_SETFILL0);
355         put_bits(&p, 5, 1); /* nbits */
356         put_bits(&p, 1, 0); /* X */
357         put_bits(&p, 1, 0); /* Y */
358         put_bits(&p, 1, 1); /* set fill style 1 */
359
360         /* draw the rectangle ! */
361         put_swf_line_edge(&p, width, 0);
362         put_swf_line_edge(&p, 0, height);
363         put_swf_line_edge(&p, -width, 0);
364         put_swf_line_edge(&p, 0, -height);
365
366         /* end of shape */
367         put_bits(&p, 1, 0); /* not an edge */
368         put_bits(&p, 5, 0);
369
370         flush_put_bits(&p);
371         put_buffer(pb, buf1, pbBufPtr(&p) - p.buf);
372
373         put_swf_end_tag(s);
374     }
375
376     if (audio_enc && audio_enc->codec_id == CODEC_ID_MP3 ) {
377         int v;
378
379         /* start sound */
380         put_swf_tag(s, TAG_STREAMHEAD2);
381
382         v = 0;
383         switch(audio_enc->sample_rate) {
384         case 11025:
385             v |= 1 << 2;
386             break;
387         case 22050:
388             v |= 2 << 2;
389             break;
390         case 44100:
391             v |= 3 << 2;
392             break;
393         default:
394             /* not supported */
395             av_log(s, AV_LOG_ERROR, "swf doesnt support that sample rate, choose from (44100, 22050, 11025)\n");
396             av_free(swf->audio_fifo);
397             return -1;
398         }
399         v |= 0x02; /* 16 bit playback */
400         if (audio_enc->channels == 2)
401             v |= 0x01; /* stereo playback */
402         put_byte(&s->pb, v);
403         v |= 0x20; /* mp3 compressed */
404         put_byte(&s->pb, v);
405         put_le16(&s->pb, swf->samples_per_frame);  /* avg samples per frame */
406         put_le16(&s->pb, 0);
407
408         put_swf_end_tag(s);
409     }
410
411     put_flush_packet(&s->pb);
412     return 0;
413 }
414
415 static int swf_write_video(AVFormatContext *s,
416                            AVCodecContext *enc, const uint8_t *buf, int size)
417 {
418     SWFContext *swf = s->priv_data;
419     ByteIOContext *pb = &s->pb;
420
421     /* Flash Player limit */
422     if ( swf->swf_frame_number == 16000 ) {
423         av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
424     }
425
426             if ( swf->video_type == CODEC_ID_VP6F ||
427                  swf->video_type == CODEC_ID_FLV1 ) {
428                 if ( swf->video_frame_number == 0 ) {
429                     /* create a new video object */
430                     put_swf_tag(s, TAG_VIDEOSTREAM);
431                     put_le16(pb, VIDEO_ID);
432                     put_le16(pb, 15000 ); /* hard flash player limit */
433                     put_le16(pb, enc->width);
434                     put_le16(pb, enc->height);
435                     put_byte(pb, 0);
436                     put_byte(pb,codec_get_tag(swf_codec_tags,swf->video_type));
437                     put_swf_end_tag(s);
438
439                     /* place the video object for the first time */
440                     put_swf_tag(s, TAG_PLACEOBJECT2);
441                     put_byte(pb, 0x36);
442                     put_le16(pb, 1);
443                     put_le16(pb, VIDEO_ID);
444                     put_swf_matrix(pb, 1 << FRAC_BITS, 0, 0, 1 << FRAC_BITS, 0, 0);
445                     put_le16(pb, swf->video_frame_number );
446                     put_byte(pb, 'v');
447                     put_byte(pb, 'i');
448                     put_byte(pb, 'd');
449                     put_byte(pb, 'e');
450                     put_byte(pb, 'o');
451                     put_byte(pb, 0x00);
452                     put_swf_end_tag(s);
453                 } else {
454                     /* mark the character for update */
455                     put_swf_tag(s, TAG_PLACEOBJECT2);
456                     put_byte(pb, 0x11);
457                     put_le16(pb, 1);
458                     put_le16(pb, swf->video_frame_number );
459                     put_swf_end_tag(s);
460                 }
461
462                     /* set video frame data */
463                     put_swf_tag(s, TAG_VIDEOFRAME | TAG_LONG);
464                     put_le16(pb, VIDEO_ID);
465                     put_le16(pb, swf->video_frame_number++ );
466                     put_buffer(pb, buf, size);
467                     put_swf_end_tag(s);
468             } else if ( swf->video_type == CODEC_ID_MJPEG ) {
469                 if (swf->swf_frame_number > 0) {
470                     /* remove the shape */
471                     put_swf_tag(s, TAG_REMOVEOBJECT);
472                     put_le16(pb, SHAPE_ID); /* shape ID */
473                     put_le16(pb, 1); /* depth */
474                     put_swf_end_tag(s);
475
476                     /* free the bitmap */
477                     put_swf_tag(s, TAG_FREECHARACTER);
478                     put_le16(pb, BITMAP_ID);
479                     put_swf_end_tag(s);
480                 }
481
482                 put_swf_tag(s, TAG_JPEG2 | TAG_LONG);
483
484                 put_le16(pb, BITMAP_ID); /* ID of the image */
485
486                 /* a dummy jpeg header seems to be required */
487                 put_byte(pb, 0xff);
488                 put_byte(pb, 0xd8);
489                 put_byte(pb, 0xff);
490                 put_byte(pb, 0xd9);
491                 /* write the jpeg image */
492                 put_buffer(pb, buf, size);
493
494                 put_swf_end_tag(s);
495
496                 /* draw the shape */
497
498                 put_swf_tag(s, TAG_PLACEOBJECT);
499                 put_le16(pb, SHAPE_ID); /* shape ID */
500                 put_le16(pb, 1); /* depth */
501                 put_swf_matrix(pb, 20 << FRAC_BITS, 0, 0, 20 << FRAC_BITS, 0, 0);
502                 put_swf_end_tag(s);
503             } else {
504                 /* invalid codec */
505             }
506
507             swf->swf_frame_number ++;
508
509     swf->video_samples += swf->samples_per_frame;
510
511     /* streaming sound always should be placed just before showframe tags */
512     if (swf->audio_type && swf->audio_in_pos) {
513         put_swf_tag(s, TAG_STREAMBLOCK | TAG_LONG);
514         put_le16(pb, swf->sound_samples);
515         put_le16(pb, 0); // seek samples
516         put_buffer(pb, swf->audio_fifo, swf->audio_in_pos);
517         put_swf_end_tag(s);
518
519         /* update FIFO */
520         swf->sound_samples = 0;
521         swf->audio_in_pos = 0;
522     }
523
524     /* output the frame */
525     put_swf_tag(s, TAG_SHOWFRAME);
526     put_swf_end_tag(s);
527
528     put_flush_packet(&s->pb);
529
530     return 0;
531 }
532
533 static int swf_write_audio(AVFormatContext *s,
534                            AVCodecContext *enc, const uint8_t *buf, int size)
535 {
536     SWFContext *swf = s->priv_data;
537
538     /* Flash Player limit */
539     if ( swf->swf_frame_number == 16000 ) {
540         av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
541     }
542
543     if (swf->audio_in_pos + size >= AUDIO_FIFO_SIZE) {
544         av_log(s, AV_LOG_ERROR, "audio fifo too small to mux audio essence\n");
545         return -1;
546     }
547
548     memcpy(swf->audio_fifo +  swf->audio_in_pos, buf, size);
549     swf->audio_in_pos += size;
550     swf->sound_samples += enc->frame_size;
551
552     /* if audio only stream make sure we add swf frames */
553     if ( swf->video_type == 0 ) {
554         swf_write_video(s, enc, 0, 0);
555     }
556
557     return 0;
558 }
559
560 static int swf_write_packet(AVFormatContext *s, AVPacket *pkt)
561 {
562     AVCodecContext *codec = s->streams[pkt->stream_index]->codec;
563     if (codec->codec_type == CODEC_TYPE_AUDIO)
564         return swf_write_audio(s, codec, pkt->data, pkt->size);
565     else
566         return swf_write_video(s, codec, pkt->data, pkt->size);
567 }
568
569 static int swf_write_trailer(AVFormatContext *s)
570 {
571     SWFContext *swf = s->priv_data;
572     ByteIOContext *pb = &s->pb;
573     AVCodecContext *enc, *video_enc;
574     int file_size, i;
575
576     video_enc = NULL;
577     for(i=0;i<s->nb_streams;i++) {
578         enc = s->streams[i]->codec;
579         if (enc->codec_type == CODEC_TYPE_VIDEO)
580             video_enc = enc;
581     }
582
583     put_swf_tag(s, TAG_END);
584     put_swf_end_tag(s);
585
586     put_flush_packet(&s->pb);
587
588     /* patch file size and number of frames if not streamed */
589     if (!url_is_streamed(&s->pb) && video_enc) {
590         file_size = url_ftell(pb);
591         url_fseek(pb, 4, SEEK_SET);
592         put_le32(pb, file_size);
593         url_fseek(pb, swf->duration_pos, SEEK_SET);
594         put_le16(pb, video_enc->frame_number);
595         url_fseek(pb, file_size, SEEK_SET);
596     }
597     return 0;
598 }
599 #endif //CONFIG_MUXERS
600
601 /*********************************************/
602 /* Extract FLV encoded frame and MP3 from swf
603    Note that the detection of the real frame
604    is inaccurate at this point as it can be
605    quite tricky to determine, you almost certainly
606    will get a bad audio/video sync */
607
608 static int get_swf_tag(ByteIOContext *pb, int *len_ptr)
609 {
610     int tag, len;
611
612     if (url_feof(pb))
613         return -1;
614
615     tag = get_le16(pb);
616     len = tag & 0x3f;
617     tag = tag >> 6;
618     if (len == 0x3f) {
619         len = get_le32(pb);
620     }
621 //    av_log(NULL, AV_LOG_DEBUG, "Tag: %d - Len: %d\n", tag, len);
622     *len_ptr = len;
623     return tag;
624 }
625
626
627 static int swf_probe(AVProbeData *p)
628 {
629     /* check file header */
630     if (p->buf_size <= 16)
631         return 0;
632     if ((p->buf[0] == 'F' || p->buf[0] == 'C') && p->buf[1] == 'W' &&
633         p->buf[2] == 'S')
634         return AVPROBE_SCORE_MAX;
635     else
636         return 0;
637 }
638
639 static int swf_read_header(AVFormatContext *s, AVFormatParameters *ap)
640 {
641     SWFContext *swf = s->priv_data;
642     ByteIOContext *pb = &s->pb;
643     int nbits, len, frame_rate, tag, v;
644     offset_t frame_offset = -1;
645     AVStream *ast = 0;
646     AVStream *vst = 0;
647
648     tag = get_be32(pb) & 0xffffff00;
649
650     if (tag == MKBETAG('C', 'W', 'S', 0))
651     {
652         av_log(s, AV_LOG_ERROR, "Compressed SWF format not supported\n");
653         return AVERROR_IO;
654     }
655     if (tag != MKBETAG('F', 'W', 'S', 0))
656         return AVERROR_IO;
657     get_le32(pb);
658     /* skip rectangle size */
659     nbits = get_byte(pb) >> 3;
660     len = (4 * nbits - 3 + 7) / 8;
661     url_fskip(pb, len);
662     frame_rate = get_le16(pb);
663     get_le16(pb); /* frame count */
664
665     /* The Flash Player converts 8.8 frame rates
666        to milliseconds internally. Do the same to get
667        a correct framerate */
668     swf->ms_per_frame = ( 1000 * 256 ) / frame_rate;
669     swf->samples_per_frame = 0;
670
671     for(;;) {
672         offset_t tag_offset = url_ftell(pb);
673         tag = get_swf_tag(pb, &len);
674         if (tag < 0 || tag == TAG_VIDEOFRAME || tag == TAG_STREAMBLOCK) {
675             url_fseek(pb, frame_offset == -1 ? tag_offset : frame_offset, SEEK_SET);
676             break;
677         }
678         if ( tag == TAG_VIDEOSTREAM && !vst) {
679             int ch_id = get_le16(pb);
680             get_le16(pb);
681             get_le16(pb);
682             get_le16(pb);
683             get_byte(pb);
684             /* Check for FLV1 */
685             vst = av_new_stream(s, ch_id);
686             vst->codec->codec_type = CODEC_TYPE_VIDEO;
687             vst->codec->codec_id = codec_get_id(swf_codec_tags, get_byte(pb));
688         } else if ( ( tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2 ) && !ast) {
689             /* streaming found */
690             int sample_rate_code;
691             get_byte(pb);
692             v = get_byte(pb);
693             swf->samples_per_frame = get_le16(pb);
694             ast = av_new_stream(s, -1); /* -1 to avoid clash with video stream ch_id */
695             av_set_pts_info(ast, 24, 1, 1000); /* 24 bit pts in ms */
696             swf->audio_stream_index = ast->index;
697             ast->codec->channels = 1 + (v&1);
698             ast->codec->codec_type = CODEC_TYPE_AUDIO;
699             ast->codec->codec_id = codec_get_id(swf_audio_codec_tags, (v>>4) & 15);
700             ast->need_parsing = 1;
701             sample_rate_code= (v>>2) & 3;
702             if (!sample_rate_code)
703                 return AVERROR_IO;
704             ast->codec->sample_rate = 11025 << (sample_rate_code-1);
705             if (len > 4)
706                 url_fskip(pb,len-4);
707
708         } else if (tag == TAG_JPEG2 && !vst) {
709             vst = av_new_stream(s, -2); /* -2 to avoid clash with video stream and audio stream */
710             vst->codec->codec_type = CODEC_TYPE_VIDEO;
711             vst->codec->codec_id = CODEC_ID_MJPEG;
712             url_fskip(pb, len);
713             frame_offset = tag_offset;
714         } else {
715             url_fskip(pb, len);
716         }
717     }
718     if (vst) {
719         av_set_pts_info(vst, 24, 1, 1000); /* 24 bit pts in ms */
720         if (swf->ms_per_frame) {
721             vst->codec->time_base.den = 1000. / swf->ms_per_frame;
722             vst->codec->time_base.num = 1;
723         }
724     }
725     return 0;
726 }
727
728 static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
729 {
730     SWFContext *swf = s->priv_data;
731     ByteIOContext *pb = &s->pb;
732     AVStream *st = 0;
733     int tag, len, i, frame;
734
735     for(;;) {
736         tag = get_swf_tag(pb, &len);
737         if (tag < 0)
738             return AVERROR_IO;
739         if (tag == TAG_VIDEOFRAME) {
740             int ch_id = get_le16(pb);
741             len -= 2;
742             for( i=0; i<s->nb_streams; i++ ) {
743                 st = s->streams[i];
744                 if (st->codec->codec_type == CODEC_TYPE_VIDEO && st->id == ch_id) {
745                     frame = get_le16(pb);
746                     av_get_packet(pb, pkt, len-2);
747                     pkt->pts = frame * swf->ms_per_frame;
748                     pkt->stream_index = st->index;
749                     return pkt->size;
750                 }
751             }
752         } else if (tag == TAG_STREAMBLOCK) {
753             st = s->streams[swf->audio_stream_index];
754             if (st->codec->codec_id == CODEC_ID_MP3) {
755                 url_fskip(pb, 4);
756                 av_get_packet(pb, pkt, len-4);
757             } else { // ADPCM, PCM
758                 av_get_packet(pb, pkt, len);
759             }
760             pkt->stream_index = st->index;
761             return pkt->size;
762         } else if (tag == TAG_JPEG2) {
763             for (i=0; i<s->nb_streams; i++) {
764                 st = s->streams[i];
765                 if (st->id == -2) {
766                     get_le16(pb); /* BITMAP_ID */
767                     av_new_packet(pkt, len-2);
768                     get_buffer(pb, pkt->data, 4);
769                     if (AV_RB32(pkt->data) == 0xffd8ffd9) {
770                         /* old SWF files containing SOI/EOI as data start */
771                         pkt->size -= 4;
772                         get_buffer(pb, pkt->data, pkt->size);
773                     } else {
774                         get_buffer(pb, pkt->data + 4, pkt->size - 4);
775                     }
776                     pkt->stream_index = st->index;
777                     return pkt->size;
778                 }
779             }
780         }
781         url_fskip(pb, len);
782     }
783     return 0;
784 }
785
786 static int swf_read_close(AVFormatContext *s)
787 {
788      return 0;
789 }
790
791 #ifdef CONFIG_SWF_DEMUXER
792 AVInputFormat swf_demuxer = {
793     "swf",
794     "Flash format",
795     sizeof(SWFContext),
796     swf_probe,
797     swf_read_header,
798     swf_read_packet,
799     swf_read_close,
800 };
801 #endif
802 #ifdef CONFIG_SWF_MUXER
803 AVOutputFormat swf_muxer = {
804     "swf",
805     "Flash format",
806     "application/x-shockwave-flash",
807     "swf",
808     sizeof(SWFContext),
809     CODEC_ID_MP3,
810     CODEC_ID_FLV1,
811     swf_write_header,
812     swf_write_packet,
813     swf_write_trailer,
814 };
815 #endif