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