]> git.sesse.net Git - ffmpeg/blob - libavformat/swf.c
bring back h264 build
[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 frame_rate;
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 does not 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[0] == 'F' || p->buf[0] == 'C') && p->buf[1] == 'W' &&
622         p->buf[2] == 'S')
623         return AVPROBE_SCORE_MAX;
624     else
625         return 0;
626 }
627
628 static int swf_read_header(AVFormatContext *s, AVFormatParameters *ap)
629 {
630     SWFContext *swf = s->priv_data;
631     ByteIOContext *pb = &s->pb;
632     int nbits, len, tag, v;
633     offset_t frame_offset = -1;
634     AVStream *ast = 0;
635     AVStream *vst = 0;
636
637     tag = get_be32(pb) & 0xffffff00;
638
639     if (tag == MKBETAG('C', 'W', 'S', 0))
640     {
641         av_log(s, AV_LOG_ERROR, "Compressed SWF format not supported\n");
642         return AVERROR_IO;
643     }
644     if (tag != MKBETAG('F', 'W', 'S', 0))
645         return AVERROR_IO;
646     get_le32(pb);
647     /* skip rectangle size */
648     nbits = get_byte(pb) >> 3;
649     len = (4 * nbits - 3 + 7) / 8;
650     url_fskip(pb, len);
651     swf->frame_rate = get_le16(pb); /* 8.8 fixed */
652     get_le16(pb); /* frame count */
653
654     swf->samples_per_frame = 0;
655
656     for(;;) {
657         offset_t tag_offset = url_ftell(pb);
658         tag = get_swf_tag(pb, &len);
659         if (tag < 0 || tag == TAG_VIDEOFRAME || tag == TAG_STREAMBLOCK) {
660             url_fseek(pb, frame_offset == -1 ? tag_offset : frame_offset, SEEK_SET);
661             break;
662         }
663         if ( tag == TAG_VIDEOSTREAM && !vst) {
664             int ch_id = get_le16(pb);
665             get_le16(pb);
666             get_le16(pb);
667             get_le16(pb);
668             get_byte(pb);
669             /* Check for FLV1 */
670             vst = av_new_stream(s, ch_id);
671             vst->codec->codec_type = CODEC_TYPE_VIDEO;
672             vst->codec->codec_id = codec_get_id(swf_codec_tags, get_byte(pb));
673         } else if ( ( tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2 ) && !ast) {
674             /* streaming found */
675             int sample_rate_code;
676             get_byte(pb);
677             v = get_byte(pb);
678             swf->samples_per_frame = get_le16(pb);
679             ast = av_new_stream(s, -1); /* -1 to avoid clash with video stream ch_id */
680             swf->audio_stream_index = ast->index;
681             ast->codec->channels = 1 + (v&1);
682             ast->codec->codec_type = CODEC_TYPE_AUDIO;
683             ast->codec->codec_id = codec_get_id(swf_audio_codec_tags, (v>>4) & 15);
684             ast->need_parsing = AVSTREAM_PARSE_FULL;
685             sample_rate_code= (v>>2) & 3;
686             if (!sample_rate_code)
687                 return AVERROR_IO;
688             ast->codec->sample_rate = 11025 << (sample_rate_code-1);
689             av_set_pts_info(ast, 64, 1, ast->codec->sample_rate);
690             if (len > 4)
691                 url_fskip(pb,len-4);
692
693         } else if (tag == TAG_JPEG2 && !vst) {
694             vst = av_new_stream(s, -2); /* -2 to avoid clash with video stream and audio stream */
695             vst->codec->codec_type = CODEC_TYPE_VIDEO;
696             vst->codec->codec_id = CODEC_ID_MJPEG;
697             url_fskip(pb, len);
698             frame_offset = tag_offset;
699         } else {
700             url_fskip(pb, len);
701         }
702     }
703     if (vst)
704         av_set_pts_info(vst, 64, 256, swf->frame_rate);
705     return 0;
706 }
707
708 static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
709 {
710     SWFContext *swf = s->priv_data;
711     ByteIOContext *pb = &s->pb;
712     AVStream *st = 0;
713     int tag, len, i, frame;
714
715     for(;;) {
716         tag = get_swf_tag(pb, &len);
717         if (tag < 0)
718             return AVERROR_IO;
719         if (tag == TAG_VIDEOFRAME) {
720             int ch_id = get_le16(pb);
721             len -= 2;
722             for( i=0; i<s->nb_streams; i++ ) {
723                 st = s->streams[i];
724                 if (st->codec->codec_type == CODEC_TYPE_VIDEO && st->id == ch_id) {
725                     frame = get_le16(pb);
726                     av_get_packet(pb, pkt, len-2);
727                     pkt->pts = frame;
728                     pkt->stream_index = st->index;
729                     return pkt->size;
730                 }
731             }
732         } else if (tag == TAG_STREAMBLOCK) {
733             st = s->streams[swf->audio_stream_index];
734             if (st->codec->codec_id == CODEC_ID_MP3) {
735                 url_fskip(pb, 4);
736                 av_get_packet(pb, pkt, len-4);
737             } else { // ADPCM, PCM
738                 av_get_packet(pb, pkt, len);
739             }
740             pkt->stream_index = st->index;
741             return pkt->size;
742         } else if (tag == TAG_JPEG2) {
743             for (i=0; i<s->nb_streams; i++) {
744                 st = s->streams[i];
745                 if (st->id == -2) {
746                     get_le16(pb); /* BITMAP_ID */
747                     av_new_packet(pkt, len-2);
748                     get_buffer(pb, pkt->data, 4);
749                     if (AV_RB32(pkt->data) == 0xffd8ffd9) {
750                         /* old SWF files containing SOI/EOI as data start */
751                         pkt->size -= 4;
752                         get_buffer(pb, pkt->data, pkt->size);
753                     } else {
754                         get_buffer(pb, pkt->data + 4, pkt->size - 4);
755                     }
756                     pkt->stream_index = st->index;
757                     return pkt->size;
758                 }
759             }
760         }
761         url_fskip(pb, len);
762     }
763     return 0;
764 }
765
766 static int swf_read_close(AVFormatContext *s)
767 {
768      return 0;
769 }
770
771 #ifdef CONFIG_SWF_DEMUXER
772 AVInputFormat swf_demuxer = {
773     "swf",
774     "Flash format",
775     sizeof(SWFContext),
776     swf_probe,
777     swf_read_header,
778     swf_read_packet,
779     swf_read_close,
780 };
781 #endif
782 #ifdef CONFIG_SWF_MUXER
783 AVOutputFormat swf_muxer = {
784     "swf",
785     "Flash format",
786     "application/x-shockwave-flash",
787     "swf",
788     sizeof(SWFContext),
789     CODEC_ID_MP3,
790     CODEC_ID_FLV1,
791     swf_write_header,
792     swf_write_packet,
793     swf_write_trailer,
794 };
795 #endif