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