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