]> git.sesse.net Git - ffmpeg/blob - libavformat/swf.c
10l, audio_fifo is a static array
[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(s, AV_LOG_ERROR, "SWF muxer 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(s, AV_LOG_ERROR, "SWF muxer 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             return -1;
391         }
392         v |= 0x02; /* 16 bit playback */
393         if (audio_enc->channels == 2)
394             v |= 0x01; /* stereo playback */
395         put_byte(&s->pb, v);
396         v |= 0x20; /* mp3 compressed */
397         put_byte(&s->pb, v);
398         put_le16(&s->pb, swf->samples_per_frame);  /* avg samples per frame */
399         put_le16(&s->pb, 0);
400
401         put_swf_end_tag(s);
402     }
403
404     put_flush_packet(&s->pb);
405     return 0;
406 }
407
408 static int swf_write_video(AVFormatContext *s,
409                            AVCodecContext *enc, const uint8_t *buf, int size)
410 {
411     SWFContext *swf = s->priv_data;
412     ByteIOContext *pb = &s->pb;
413
414     /* Flash Player limit */
415     if ( swf->swf_frame_number == 16000 ) {
416         av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
417     }
418
419             if ( swf->video_type == CODEC_ID_VP6F ||
420                  swf->video_type == CODEC_ID_FLV1 ) {
421                 if ( swf->video_frame_number == 0 ) {
422                     /* create a new video object */
423                     put_swf_tag(s, TAG_VIDEOSTREAM);
424                     put_le16(pb, VIDEO_ID);
425                     put_le16(pb, 15000 ); /* hard flash player limit */
426                     put_le16(pb, enc->width);
427                     put_le16(pb, enc->height);
428                     put_byte(pb, 0);
429                     put_byte(pb,codec_get_tag(swf_codec_tags,swf->video_type));
430                     put_swf_end_tag(s);
431
432                     /* place the video object for the first time */
433                     put_swf_tag(s, TAG_PLACEOBJECT2);
434                     put_byte(pb, 0x36);
435                     put_le16(pb, 1);
436                     put_le16(pb, VIDEO_ID);
437                     put_swf_matrix(pb, 1 << FRAC_BITS, 0, 0, 1 << FRAC_BITS, 0, 0);
438                     put_le16(pb, swf->video_frame_number );
439                     put_byte(pb, 'v');
440                     put_byte(pb, 'i');
441                     put_byte(pb, 'd');
442                     put_byte(pb, 'e');
443                     put_byte(pb, 'o');
444                     put_byte(pb, 0x00);
445                     put_swf_end_tag(s);
446                 } else {
447                     /* mark the character for update */
448                     put_swf_tag(s, TAG_PLACEOBJECT2);
449                     put_byte(pb, 0x11);
450                     put_le16(pb, 1);
451                     put_le16(pb, swf->video_frame_number );
452                     put_swf_end_tag(s);
453                 }
454
455                     /* set video frame data */
456                     put_swf_tag(s, TAG_VIDEOFRAME | TAG_LONG);
457                     put_le16(pb, VIDEO_ID);
458                     put_le16(pb, swf->video_frame_number++ );
459                     put_buffer(pb, buf, size);
460                     put_swf_end_tag(s);
461             } else if ( swf->video_type == CODEC_ID_MJPEG ) {
462                 if (swf->swf_frame_number > 0) {
463                     /* remove the shape */
464                     put_swf_tag(s, TAG_REMOVEOBJECT);
465                     put_le16(pb, SHAPE_ID); /* shape ID */
466                     put_le16(pb, 1); /* depth */
467                     put_swf_end_tag(s);
468
469                     /* free the bitmap */
470                     put_swf_tag(s, TAG_FREECHARACTER);
471                     put_le16(pb, BITMAP_ID);
472                     put_swf_end_tag(s);
473                 }
474
475                 put_swf_tag(s, TAG_JPEG2 | TAG_LONG);
476
477                 put_le16(pb, BITMAP_ID); /* ID of the image */
478
479                 /* a dummy jpeg header seems to be required */
480                 put_byte(pb, 0xff);
481                 put_byte(pb, 0xd8);
482                 put_byte(pb, 0xff);
483                 put_byte(pb, 0xd9);
484                 /* write the jpeg image */
485                 put_buffer(pb, buf, size);
486
487                 put_swf_end_tag(s);
488
489                 /* draw the shape */
490
491                 put_swf_tag(s, TAG_PLACEOBJECT);
492                 put_le16(pb, SHAPE_ID); /* shape ID */
493                 put_le16(pb, 1); /* depth */
494                 put_swf_matrix(pb, 20 << FRAC_BITS, 0, 0, 20 << FRAC_BITS, 0, 0);
495                 put_swf_end_tag(s);
496             } else {
497                 /* invalid codec */
498             }
499
500             swf->swf_frame_number ++;
501
502     /* streaming sound always should be placed just before showframe tags */
503     if (swf->audio_type && swf->audio_in_pos) {
504         put_swf_tag(s, TAG_STREAMBLOCK | TAG_LONG);
505         put_le16(pb, swf->sound_samples);
506         put_le16(pb, 0); // seek samples
507         put_buffer(pb, swf->audio_fifo, swf->audio_in_pos);
508         put_swf_end_tag(s);
509
510         /* update FIFO */
511         swf->sound_samples = 0;
512         swf->audio_in_pos = 0;
513     }
514
515     /* output the frame */
516     put_swf_tag(s, TAG_SHOWFRAME);
517     put_swf_end_tag(s);
518
519     put_flush_packet(&s->pb);
520
521     return 0;
522 }
523
524 static int swf_write_audio(AVFormatContext *s,
525                            AVCodecContext *enc, const uint8_t *buf, int size)
526 {
527     SWFContext *swf = s->priv_data;
528
529     /* Flash Player limit */
530     if ( swf->swf_frame_number == 16000 ) {
531         av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
532     }
533
534     if (swf->audio_in_pos + size >= AUDIO_FIFO_SIZE) {
535         av_log(s, AV_LOG_ERROR, "audio fifo too small to mux audio essence\n");
536         return -1;
537     }
538
539     memcpy(swf->audio_fifo +  swf->audio_in_pos, buf, size);
540     swf->audio_in_pos += size;
541     swf->sound_samples += enc->frame_size;
542
543     /* if audio only stream make sure we add swf frames */
544     if ( swf->video_type == 0 ) {
545         swf_write_video(s, enc, 0, 0);
546     }
547
548     return 0;
549 }
550
551 static int swf_write_packet(AVFormatContext *s, AVPacket *pkt)
552 {
553     AVCodecContext *codec = s->streams[pkt->stream_index]->codec;
554     if (codec->codec_type == CODEC_TYPE_AUDIO)
555         return swf_write_audio(s, codec, pkt->data, pkt->size);
556     else
557         return swf_write_video(s, codec, pkt->data, pkt->size);
558 }
559
560 static int swf_write_trailer(AVFormatContext *s)
561 {
562     SWFContext *swf = s->priv_data;
563     ByteIOContext *pb = &s->pb;
564     AVCodecContext *enc, *video_enc;
565     int file_size, i;
566
567     video_enc = NULL;
568     for(i=0;i<s->nb_streams;i++) {
569         enc = s->streams[i]->codec;
570         if (enc->codec_type == CODEC_TYPE_VIDEO)
571             video_enc = enc;
572     }
573
574     put_swf_tag(s, TAG_END);
575     put_swf_end_tag(s);
576
577     put_flush_packet(&s->pb);
578
579     /* patch file size and number of frames if not streamed */
580     if (!url_is_streamed(&s->pb) && video_enc) {
581         file_size = url_ftell(pb);
582         url_fseek(pb, 4, SEEK_SET);
583         put_le32(pb, file_size);
584         url_fseek(pb, swf->duration_pos, SEEK_SET);
585         put_le16(pb, video_enc->frame_number);
586         url_fseek(pb, file_size, SEEK_SET);
587     }
588     return 0;
589 }
590 #endif //CONFIG_MUXERS
591
592 /*********************************************/
593 /* Extract FLV encoded frame and MP3 from swf
594    Note that the detection of the real frame
595    is inaccurate at this point as it can be
596    quite tricky to determine, you almost certainly
597    will get a bad audio/video sync */
598
599 static int get_swf_tag(ByteIOContext *pb, int *len_ptr)
600 {
601     int tag, len;
602
603     if (url_feof(pb))
604         return -1;
605
606     tag = get_le16(pb);
607     len = tag & 0x3f;
608     tag = tag >> 6;
609     if (len == 0x3f) {
610         len = get_le32(pb);
611     }
612 //    av_log(NULL, AV_LOG_DEBUG, "Tag: %d - Len: %d\n", tag, len);
613     *len_ptr = len;
614     return tag;
615 }
616
617
618 static int swf_probe(AVProbeData *p)
619 {
620     /* check file header */
621     if (p->buf_size <= 16)
622         return 0;
623     if ((p->buf[0] == 'F' || p->buf[0] == 'C') && p->buf[1] == 'W' &&
624         p->buf[2] == 'S')
625         return AVPROBE_SCORE_MAX;
626     else
627         return 0;
628 }
629
630 static int swf_read_header(AVFormatContext *s, AVFormatParameters *ap)
631 {
632     SWFContext *swf = s->priv_data;
633     ByteIOContext *pb = &s->pb;
634     int nbits, len, frame_rate, tag, v;
635     offset_t frame_offset = -1;
636     AVStream *ast = 0;
637     AVStream *vst = 0;
638
639     tag = get_be32(pb) & 0xffffff00;
640
641     if (tag == MKBETAG('C', 'W', 'S', 0))
642     {
643         av_log(s, AV_LOG_ERROR, "Compressed SWF format not supported\n");
644         return AVERROR_IO;
645     }
646     if (tag != MKBETAG('F', 'W', 'S', 0))
647         return AVERROR_IO;
648     get_le32(pb);
649     /* skip rectangle size */
650     nbits = get_byte(pb) >> 3;
651     len = (4 * nbits - 3 + 7) / 8;
652     url_fskip(pb, len);
653     frame_rate = get_le16(pb);
654     get_le16(pb); /* frame count */
655
656     /* The Flash Player converts 8.8 frame rates
657        to milliseconds internally. Do the same to get
658        a correct framerate */
659     swf->ms_per_frame = ( 1000 * 256 ) / frame_rate;
660     swf->samples_per_frame = 0;
661
662     for(;;) {
663         offset_t tag_offset = url_ftell(pb);
664         tag = get_swf_tag(pb, &len);
665         if (tag < 0 || tag == TAG_VIDEOFRAME || tag == TAG_STREAMBLOCK) {
666             url_fseek(pb, frame_offset == -1 ? tag_offset : frame_offset, SEEK_SET);
667             break;
668         }
669         if ( tag == TAG_VIDEOSTREAM && !vst) {
670             int ch_id = get_le16(pb);
671             get_le16(pb);
672             get_le16(pb);
673             get_le16(pb);
674             get_byte(pb);
675             /* Check for FLV1 */
676             vst = av_new_stream(s, ch_id);
677             vst->codec->codec_type = CODEC_TYPE_VIDEO;
678             vst->codec->codec_id = codec_get_id(swf_codec_tags, get_byte(pb));
679         } else if ( ( tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2 ) && !ast) {
680             /* streaming found */
681             int sample_rate_code;
682             get_byte(pb);
683             v = get_byte(pb);
684             swf->samples_per_frame = get_le16(pb);
685             ast = av_new_stream(s, -1); /* -1 to avoid clash with video stream ch_id */
686             av_set_pts_info(ast, 24, 1, 1000); /* 24 bit pts in ms */
687             swf->audio_stream_index = ast->index;
688             ast->codec->channels = 1 + (v&1);
689             ast->codec->codec_type = CODEC_TYPE_AUDIO;
690             ast->codec->codec_id = codec_get_id(swf_audio_codec_tags, (v>>4) & 15);
691             ast->need_parsing = 1;
692             sample_rate_code= (v>>2) & 3;
693             if (!sample_rate_code)
694                 return AVERROR_IO;
695             ast->codec->sample_rate = 11025 << (sample_rate_code-1);
696             if (len > 4)
697                 url_fskip(pb,len-4);
698
699         } else if (tag == TAG_JPEG2 && !vst) {
700             vst = av_new_stream(s, -2); /* -2 to avoid clash with video stream and audio stream */
701             vst->codec->codec_type = CODEC_TYPE_VIDEO;
702             vst->codec->codec_id = CODEC_ID_MJPEG;
703             url_fskip(pb, len);
704             frame_offset = tag_offset;
705         } else {
706             url_fskip(pb, len);
707         }
708     }
709     if (vst) {
710         av_set_pts_info(vst, 24, 1, 1000); /* 24 bit pts in ms */
711         if (swf->ms_per_frame) {
712             vst->codec->time_base.den = 1000. / swf->ms_per_frame;
713             vst->codec->time_base.num = 1;
714         }
715     }
716     return 0;
717 }
718
719 static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
720 {
721     SWFContext *swf = s->priv_data;
722     ByteIOContext *pb = &s->pb;
723     AVStream *st = 0;
724     int tag, len, i, frame;
725
726     for(;;) {
727         tag = get_swf_tag(pb, &len);
728         if (tag < 0)
729             return AVERROR_IO;
730         if (tag == TAG_VIDEOFRAME) {
731             int ch_id = get_le16(pb);
732             len -= 2;
733             for( i=0; i<s->nb_streams; i++ ) {
734                 st = s->streams[i];
735                 if (st->codec->codec_type == CODEC_TYPE_VIDEO && st->id == ch_id) {
736                     frame = get_le16(pb);
737                     av_get_packet(pb, pkt, len-2);
738                     pkt->pts = frame * swf->ms_per_frame;
739                     pkt->stream_index = st->index;
740                     return pkt->size;
741                 }
742             }
743         } else if (tag == TAG_STREAMBLOCK) {
744             st = s->streams[swf->audio_stream_index];
745             if (st->codec->codec_id == CODEC_ID_MP3) {
746                 url_fskip(pb, 4);
747                 av_get_packet(pb, pkt, len-4);
748             } else { // ADPCM, PCM
749                 av_get_packet(pb, pkt, len);
750             }
751             pkt->stream_index = st->index;
752             return pkt->size;
753         } else if (tag == TAG_JPEG2) {
754             for (i=0; i<s->nb_streams; i++) {
755                 st = s->streams[i];
756                 if (st->id == -2) {
757                     get_le16(pb); /* BITMAP_ID */
758                     av_new_packet(pkt, len-2);
759                     get_buffer(pb, pkt->data, 4);
760                     if (AV_RB32(pkt->data) == 0xffd8ffd9) {
761                         /* old SWF files containing SOI/EOI as data start */
762                         pkt->size -= 4;
763                         get_buffer(pb, pkt->data, pkt->size);
764                     } else {
765                         get_buffer(pb, pkt->data + 4, pkt->size - 4);
766                     }
767                     pkt->stream_index = st->index;
768                     return pkt->size;
769                 }
770             }
771         }
772         url_fskip(pb, len);
773     }
774     return 0;
775 }
776
777 static int swf_read_close(AVFormatContext *s)
778 {
779      return 0;
780 }
781
782 #ifdef CONFIG_SWF_DEMUXER
783 AVInputFormat swf_demuxer = {
784     "swf",
785     "Flash format",
786     sizeof(SWFContext),
787     swf_probe,
788     swf_read_header,
789     swf_read_packet,
790     swf_read_close,
791 };
792 #endif
793 #ifdef CONFIG_SWF_MUXER
794 AVOutputFormat swf_muxer = {
795     "swf",
796     "Flash format",
797     "application/x-shockwave-flash",
798     "swf",
799     sizeof(SWFContext),
800     CODEC_ID_MP3,
801     CODEC_ID_FLV1,
802     swf_write_header,
803     swf_write_packet,
804     swf_write_trailer,
805 };
806 #endif