• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Flash Compatible Streaming Format muxer
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 
23 #include "config_components.h"
24 
25 #include "libavcodec/put_bits.h"
26 #include "libavutil/avassert.h"
27 #include "libavutil/fifo.h"
28 #include "avformat.h"
29 #include "flv.h"
30 #include "swf.h"
31 
32 #define AUDIO_FIFO_SIZE 65536
33 
34 typedef struct SWFEncContext {
35     int64_t duration_pos;
36     int64_t tag_pos;
37     int64_t vframes_pos;
38     int samples_per_frame;
39     int sound_samples;
40     int swf_frame_number;
41     int video_frame_number;
42     int tag;
43     AVFifo *audio_fifo;
44     AVCodecParameters *audio_par, *video_par;
45     AVStream *video_st;
46 } SWFEncContext;
47 
put_swf_tag(AVFormatContext * s,int tag)48 static void put_swf_tag(AVFormatContext *s, int tag)
49 {
50     SWFEncContext *swf = s->priv_data;
51     AVIOContext *pb = s->pb;
52 
53     swf->tag_pos = avio_tell(pb);
54     swf->tag = tag;
55     /* reserve some room for the tag */
56     if (tag & TAG_LONG) {
57         avio_wl16(pb, 0);
58         avio_wl32(pb, 0);
59     } else {
60         avio_wl16(pb, 0);
61     }
62 }
63 
put_swf_end_tag(AVFormatContext * s)64 static void put_swf_end_tag(AVFormatContext *s)
65 {
66     SWFEncContext *swf = s->priv_data;
67     AVIOContext *pb = s->pb;
68     int64_t pos;
69     int tag_len, tag;
70 
71     pos = avio_tell(pb);
72     tag_len = pos - swf->tag_pos - 2;
73     tag = swf->tag;
74     avio_seek(pb, swf->tag_pos, SEEK_SET);
75     if (tag & TAG_LONG) {
76         tag &= ~TAG_LONG;
77         avio_wl16(pb, (tag << 6) | 0x3f);
78         avio_wl32(pb, tag_len - 4);
79     } else {
80         av_assert0(tag_len < 0x3f);
81         avio_wl16(pb, (tag << 6) | tag_len);
82     }
83     avio_seek(pb, pos, SEEK_SET);
84 }
85 
max_nbits(int * nbits_ptr,int val)86 static inline void max_nbits(int *nbits_ptr, int val)
87 {
88     int n;
89 
90     if (val == 0)
91         return;
92     val = FFABS(val);
93     n = 1;
94     while (val != 0) {
95         n++;
96         val >>= 1;
97     }
98     if (n > *nbits_ptr)
99         *nbits_ptr = n;
100 }
101 
put_swf_rect(AVIOContext * pb,int xmin,int xmax,int ymin,int ymax)102 static void put_swf_rect(AVIOContext *pb,
103                          int xmin, int xmax, int ymin, int ymax)
104 {
105     PutBitContext p;
106     uint8_t buf[256];
107     int nbits, mask;
108 
109     init_put_bits(&p, buf, sizeof(buf));
110 
111     nbits = 0;
112     max_nbits(&nbits, xmin);
113     max_nbits(&nbits, xmax);
114     max_nbits(&nbits, ymin);
115     max_nbits(&nbits, ymax);
116     mask = (1 << nbits) - 1;
117 
118     /* rectangle info */
119     put_bits(&p, 5, nbits);
120     put_bits(&p, nbits, xmin & mask);
121     put_bits(&p, nbits, xmax & mask);
122     put_bits(&p, nbits, ymin & mask);
123     put_bits(&p, nbits, ymax & mask);
124 
125     flush_put_bits(&p);
126     avio_write(pb, buf, put_bits_ptr(&p) - p.buf);
127 }
128 
put_swf_line_edge(PutBitContext * pb,int dx,int dy)129 static void put_swf_line_edge(PutBitContext *pb, int dx, int dy)
130 {
131     int nbits, mask;
132 
133     put_bits(pb, 1, 1); /* edge */
134     put_bits(pb, 1, 1); /* line select */
135     nbits = 2;
136     max_nbits(&nbits, dx);
137     max_nbits(&nbits, dy);
138 
139     mask = (1 << nbits) - 1;
140     put_bits(pb, 4, nbits - 2); /* 16 bits precision */
141     if (dx == 0) {
142         put_bits(pb, 1, 0);
143         put_bits(pb, 1, 1);
144         put_bits(pb, nbits, dy & mask);
145     } else if (dy == 0) {
146         put_bits(pb, 1, 0);
147         put_bits(pb, 1, 0);
148         put_bits(pb, nbits, dx & mask);
149     } else {
150         put_bits(pb, 1, 1);
151         put_bits(pb, nbits, dx & mask);
152         put_bits(pb, nbits, dy & mask);
153     }
154 }
155 
156 #define FRAC_BITS 16
157 
put_swf_matrix(AVIOContext * pb,int a,int b,int c,int d,int tx,int ty)158 static void put_swf_matrix(AVIOContext *pb,
159                            int a, int b, int c, int d, int tx, int ty)
160 {
161     PutBitContext p;
162     uint8_t buf[256];
163     int nbits;
164 
165     init_put_bits(&p, buf, sizeof(buf));
166 
167     put_bits(&p, 1, 1); /* a, d present */
168     nbits = 1;
169     max_nbits(&nbits, a);
170     max_nbits(&nbits, d);
171     put_bits(&p, 5, nbits); /* nb bits */
172     put_bits(&p, nbits, a);
173     put_bits(&p, nbits, d);
174 
175     put_bits(&p, 1, 1); /* b, c present */
176     nbits = 1;
177     max_nbits(&nbits, c);
178     max_nbits(&nbits, b);
179     put_bits(&p, 5, nbits); /* nb bits */
180     put_bits(&p, nbits, c);
181     put_bits(&p, nbits, b);
182 
183     nbits = 1;
184     max_nbits(&nbits, tx);
185     max_nbits(&nbits, ty);
186     put_bits(&p, 5, nbits); /* nb bits */
187     put_bits(&p, nbits, tx);
188     put_bits(&p, nbits, ty);
189 
190     flush_put_bits(&p);
191     avio_write(pb, buf, put_bits_ptr(&p) - p.buf);
192 }
193 
swf_write_header(AVFormatContext * s)194 static int swf_write_header(AVFormatContext *s)
195 {
196     SWFEncContext *swf = s->priv_data;
197     AVIOContext *pb = s->pb;
198     PutBitContext p;
199     uint8_t buf1[256];
200     int i, width, height, rate, rate_base;
201     int version;
202 
203     swf->sound_samples = 0;
204     swf->swf_frame_number = 0;
205     swf->video_frame_number = 0;
206 
207     for(i=0;i<s->nb_streams;i++) {
208         AVCodecParameters *par = s->streams[i]->codecpar;
209         if (par->codec_type == AVMEDIA_TYPE_AUDIO) {
210             if (swf->audio_par) {
211                 av_log(s, AV_LOG_ERROR, "SWF muxer only supports 1 audio stream\n");
212                 return AVERROR_INVALIDDATA;
213             }
214             if (par->codec_id == AV_CODEC_ID_MP3) {
215                 swf->audio_par = par;
216                 swf->audio_fifo = av_fifo_alloc2(AUDIO_FIFO_SIZE, 1, 0);
217                 if (!swf->audio_fifo)
218                     return AVERROR(ENOMEM);
219             } else {
220                 av_log(s, AV_LOG_ERROR, "SWF muxer only supports MP3\n");
221                 return -1;
222             }
223         } else {
224             if (swf->video_par) {
225                 av_log(s, AV_LOG_ERROR, "SWF muxer only supports 1 video stream\n");
226                 return AVERROR_INVALIDDATA;
227             }
228             if (ff_codec_get_tag(ff_swf_codec_tags, par->codec_id) ||
229                 par->codec_id == AV_CODEC_ID_PNG ||
230                 par->codec_id == AV_CODEC_ID_MJPEG) {
231                 swf->video_st  = s->streams[i];
232                 swf->video_par = par;
233             } else {
234                 av_log(s, AV_LOG_ERROR, "SWF muxer only supports VP6, FLV, Flash Screen Video, PNG and MJPEG\n");
235                 return -1;
236             }
237         }
238     }
239 
240     if (!swf->video_par) {
241         /* currently, cannot work correctly if audio only */
242         width = 320;
243         height = 200;
244         rate = 10;
245         rate_base= 1;
246     } else {
247         width = swf->video_par->width;
248         height = swf->video_par->height;
249         // TODO: should be avg_frame_rate
250         rate = swf->video_st->time_base.den;
251         rate_base = swf->video_st->time_base.num;
252     }
253 
254     if (!swf->audio_par)
255         swf->samples_per_frame = (44100LL * rate_base) / rate;
256     else
257         swf->samples_per_frame = (swf->audio_par->sample_rate * rate_base) / rate;
258 
259     avio_write(pb, "FWS", 3);
260 
261     if (!strcmp("avm2", s->oformat->name))
262         version = 9;
263     else if (swf->video_par && (swf->video_par->codec_id == AV_CODEC_ID_VP6A ||
264                                 swf->video_par->codec_id == AV_CODEC_ID_VP6F ||
265                                 swf->video_par->codec_id == AV_CODEC_ID_PNG))
266         version = 8; /* version 8 and above support VP6 and PNG codec */
267     else if (swf->video_par && swf->video_par->codec_id == AV_CODEC_ID_FLASHSV)
268         version = 7; /* version 7 and above support Flash Screen Video codec */
269     else if (swf->video_par && swf->video_par->codec_id == AV_CODEC_ID_FLV1)
270         version = 6; /* version 6 and above support FLV1 codec */
271     else
272         version = 4; /* version 4 for mpeg audio support */
273     avio_w8(pb, version);
274 
275     avio_wl32(pb, DUMMY_FILE_SIZE); /* dummy size
276                                       (will be patched if not streamed) */
277 
278     put_swf_rect(pb, 0, width * 20, 0, height * 20);
279     if ((rate * 256LL) / rate_base >= (1<<16)) {
280         av_log(s, AV_LOG_ERROR, "Invalid (too large) frame rate %d/%d\n", rate, rate_base);
281         return AVERROR(EINVAL);
282     }
283     avio_wl16(pb, (rate * 256LL) / rate_base); /* frame rate */
284     swf->duration_pos = avio_tell(pb);
285     avio_wl16(pb, (uint16_t)(DUMMY_DURATION * (int64_t)rate / rate_base)); /* frame count */
286 
287     /* swf v8 and later files require a file attribute tag */
288     if (version >= 8) {
289         put_swf_tag(s, TAG_FILEATTRIBUTES);
290         avio_wl32(pb, (version >= 9) << 3); /* set ActionScript v3/AVM2 flag */
291         put_swf_end_tag(s);
292     }
293 
294     /* define a shape with the jpeg inside */
295     if (swf->video_par && (swf->video_par->codec_id == AV_CODEC_ID_MJPEG || swf->video_par->codec_id == AV_CODEC_ID_PNG)) {
296         put_swf_tag(s, TAG_DEFINESHAPE);
297 
298         avio_wl16(pb, SHAPE_ID); /* ID of shape */
299         /* bounding rectangle */
300         put_swf_rect(pb, 0, width, 0, height);
301         /* style info */
302         avio_w8(pb, 1); /* one fill style */
303         avio_w8(pb, 0x41); /* clipped bitmap fill */
304         avio_wl16(pb, BITMAP_ID); /* bitmap ID */
305         /* position of the bitmap */
306         put_swf_matrix(pb, 1 << FRAC_BITS, 0,
307                        0,  1 << FRAC_BITS, 0, 0);
308         avio_w8(pb, 0); /* no line style */
309 
310         /* shape drawing */
311         init_put_bits(&p, buf1, sizeof(buf1));
312         put_bits(&p, 4, 1); /* one fill bit */
313         put_bits(&p, 4, 0); /* zero line bit */
314 
315         put_bits(&p, 1, 0); /* not an edge */
316         put_bits(&p, 5, FLAG_MOVETO | FLAG_SETFILL0);
317         put_bits(&p, 5, 1); /* nbits */
318         put_bits(&p, 1, 0); /* X */
319         put_bits(&p, 1, 0); /* Y */
320         put_bits(&p, 1, 1); /* set fill style 1 */
321 
322         /* draw the rectangle ! */
323         put_swf_line_edge(&p, width, 0);
324         put_swf_line_edge(&p, 0, height);
325         put_swf_line_edge(&p, -width, 0);
326         put_swf_line_edge(&p, 0, -height);
327 
328         /* end of shape */
329         put_bits(&p, 1, 0); /* not an edge */
330         put_bits(&p, 5, 0);
331 
332         flush_put_bits(&p);
333         avio_write(pb, buf1, put_bits_ptr(&p) - p.buf);
334 
335         put_swf_end_tag(s);
336     }
337 
338     if (swf->audio_par && swf->audio_par->codec_id == AV_CODEC_ID_MP3) {
339         int v = 0;
340 
341         /* start sound */
342         put_swf_tag(s, TAG_STREAMHEAD2);
343         switch(swf->audio_par->sample_rate) {
344         case 11025: v |= 1 << 2; break;
345         case 22050: v |= 2 << 2; break;
346         case 44100: v |= 3 << 2; break;
347         default:
348             /* not supported */
349             av_log(s, AV_LOG_ERROR, "swf does not support that sample rate, choose from (44100, 22050, 11025).\n");
350             return -1;
351         }
352         v |= 0x02; /* 16 bit playback */
353         if (swf->audio_par->ch_layout.nb_channels == 2)
354             v |= 0x01; /* stereo playback */
355         avio_w8(s->pb, v);
356         v |= 0x20; /* mp3 compressed */
357         avio_w8(s->pb, v);
358         avio_wl16(s->pb, swf->samples_per_frame);  /* avg samples per frame */
359         avio_wl16(s->pb, 0);
360 
361         put_swf_end_tag(s);
362     }
363 
364     return 0;
365 }
366 
fifo_avio_wrapper(void * opaque,void * buf,size_t * nb_elems)367 static int fifo_avio_wrapper(void *opaque, void *buf, size_t *nb_elems)
368 {
369     avio_write(opaque, buf, *nb_elems);
370     return 0;
371 }
372 
swf_write_video(AVFormatContext * s,AVCodecParameters * par,const uint8_t * buf,int size,unsigned pkt_flags)373 static int swf_write_video(AVFormatContext *s,
374                            AVCodecParameters *par, const uint8_t *buf, int size, unsigned pkt_flags)
375 {
376     SWFEncContext *swf = s->priv_data;
377     AVIOContext *pb = s->pb;
378     unsigned codec_tag = ff_codec_get_tag(ff_swf_codec_tags, par->codec_id);
379 
380     /* Flash Player limit */
381     if (swf->swf_frame_number == 16000)
382         av_log(s, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
383 
384     if (codec_tag) {
385         if (swf->video_frame_number == 0) {
386             /* create a new video object */
387             put_swf_tag(s, TAG_VIDEOSTREAM);
388             avio_wl16(pb, VIDEO_ID);
389             swf->vframes_pos = avio_tell(pb);
390             avio_wl16(pb, 15000); /* hard flash player limit */
391             avio_wl16(pb, par->width);
392             avio_wl16(pb, par->height);
393             avio_w8(pb, 0);
394             avio_w8(pb, codec_tag);
395             put_swf_end_tag(s);
396 
397             /* place the video object for the first time */
398             put_swf_tag(s, TAG_PLACEOBJECT2);
399             avio_w8(pb, 0x36);
400             avio_wl16(pb, 1);
401             avio_wl16(pb, VIDEO_ID);
402             put_swf_matrix(pb, 1 << FRAC_BITS, 0, 0, 1 << FRAC_BITS, 0, 0);
403             avio_wl16(pb, swf->video_frame_number);
404             avio_write(pb, "video", 5);
405             avio_w8(pb, 0x00);
406             put_swf_end_tag(s);
407         } else {
408             /* mark the character for update */
409             put_swf_tag(s, TAG_PLACEOBJECT2);
410             avio_w8(pb, 0x11);
411             avio_wl16(pb, 1);
412             avio_wl16(pb, swf->video_frame_number);
413             put_swf_end_tag(s);
414         }
415 
416         /* set video frame data */
417         put_swf_tag(s, TAG_VIDEOFRAME | TAG_LONG);
418         avio_wl16(pb, VIDEO_ID);
419         avio_wl16(pb, swf->video_frame_number++);
420         if (par->codec_id == AV_CODEC_ID_FLASHSV) {
421             /* FrameType and CodecId is needed here even if it is not documented correctly in the SWF specs */
422             int flags = codec_tag | (pkt_flags & AV_PKT_FLAG_KEY ? FLV_FRAME_KEY : FLV_FRAME_INTER);
423             avio_w8(pb, flags);
424         }
425         avio_write(pb, buf, size);
426         put_swf_end_tag(s);
427     } else if (par->codec_id == AV_CODEC_ID_MJPEG || par->codec_id == AV_CODEC_ID_PNG) {
428         if (swf->swf_frame_number > 0) {
429             /* remove the shape */
430             put_swf_tag(s, TAG_REMOVEOBJECT);
431             avio_wl16(pb, SHAPE_ID); /* shape ID */
432             avio_wl16(pb, 1); /* depth */
433             put_swf_end_tag(s);
434 
435             /* free the bitmap */
436             put_swf_tag(s, TAG_FREECHARACTER);
437             avio_wl16(pb, BITMAP_ID);
438             put_swf_end_tag(s);
439         }
440 
441         put_swf_tag(s, TAG_JPEG2 | TAG_LONG);
442 
443         avio_wl16(pb, BITMAP_ID); /* ID of the image */
444 
445         /* a dummy jpeg header seems to be required */
446         if (par->codec_id == AV_CODEC_ID_MJPEG)
447             avio_wb32(pb, 0xffd8ffd9);
448         /* write the jpeg/png image */
449         avio_write(pb, buf, size);
450 
451         put_swf_end_tag(s);
452 
453         /* draw the shape */
454 
455         put_swf_tag(s, TAG_PLACEOBJECT);
456         avio_wl16(pb, SHAPE_ID); /* shape ID */
457         avio_wl16(pb, 1); /* depth */
458         put_swf_matrix(pb, 20 << FRAC_BITS, 0, 0, 20 << FRAC_BITS, 0, 0);
459         put_swf_end_tag(s);
460     }
461 
462     swf->swf_frame_number++;
463 
464     /* streaming sound always should be placed just before showframe tags */
465     if (swf->audio_par && av_fifo_can_read(swf->audio_fifo)) {
466         size_t frame_size = av_fifo_can_read(swf->audio_fifo);
467         put_swf_tag(s, TAG_STREAMBLOCK | TAG_LONG);
468         avio_wl16(pb, swf->sound_samples);
469         avio_wl16(pb, 0); // seek samples
470         av_fifo_read_to_cb(swf->audio_fifo, fifo_avio_wrapper, pb, &frame_size);
471         put_swf_end_tag(s);
472 
473         /* update FIFO */
474         swf->sound_samples = 0;
475     }
476 
477     /* output the frame */
478     put_swf_tag(s, TAG_SHOWFRAME);
479     put_swf_end_tag(s);
480 
481     return 0;
482 }
483 
swf_write_audio(AVFormatContext * s,AVCodecParameters * par,const uint8_t * buf,int size)484 static int swf_write_audio(AVFormatContext *s, AVCodecParameters *par,
485                            const uint8_t *buf, int size)
486 {
487     SWFEncContext *swf = s->priv_data;
488 
489     /* Flash Player limit */
490     if (swf->swf_frame_number == 16000)
491         av_log(s, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
492 
493     if (av_fifo_can_write(swf->audio_fifo) < size) {
494         av_log(s, AV_LOG_ERROR, "audio fifo too small to mux audio essence\n");
495         return -1;
496     }
497 
498     av_fifo_write(swf->audio_fifo, buf, size);
499     swf->sound_samples += av_get_audio_frame_duration2(par, size);
500 
501     /* if audio only stream make sure we add swf frames */
502     if (!swf->video_par)
503         swf_write_video(s, par, 0, 0, 0);
504 
505     return 0;
506 }
507 
swf_write_packet(AVFormatContext * s,AVPacket * pkt)508 static int swf_write_packet(AVFormatContext *s, AVPacket *pkt)
509 {
510     AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar;
511     if (par->codec_type == AVMEDIA_TYPE_AUDIO)
512         return swf_write_audio(s, par, pkt->data, pkt->size);
513     else
514         return swf_write_video(s, par, pkt->data, pkt->size, pkt->flags);
515 }
516 
swf_write_trailer(AVFormatContext * s)517 static int swf_write_trailer(AVFormatContext *s)
518 {
519     SWFEncContext *swf = s->priv_data;
520     AVIOContext *pb = s->pb;
521     int file_size;
522 
523     put_swf_tag(s, TAG_END);
524     put_swf_end_tag(s);
525 
526     /* patch file size and number of frames if not streamed */
527     if ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) && swf->video_par) {
528         file_size = avio_tell(pb);
529         avio_seek(pb, 4, SEEK_SET);
530         avio_wl32(pb, file_size);
531         avio_seek(pb, swf->duration_pos, SEEK_SET);
532         avio_wl16(pb, swf->video_frame_number);
533         if (swf->vframes_pos) {
534         avio_seek(pb, swf->vframes_pos, SEEK_SET);
535         avio_wl16(pb, swf->video_frame_number);
536         }
537         avio_seek(pb, file_size, SEEK_SET);
538     }
539     return 0;
540 }
541 
swf_deinit(AVFormatContext * s)542 static void swf_deinit(AVFormatContext *s)
543 {
544     SWFEncContext *swf = s->priv_data;
545 
546     av_fifo_freep2(&swf->audio_fifo);
547 }
548 
549 #if CONFIG_SWF_MUXER
550 const AVOutputFormat ff_swf_muxer = {
551     .name              = "swf",
552     .long_name         = NULL_IF_CONFIG_SMALL("SWF (ShockWave Flash)"),
553     .mime_type         = "application/x-shockwave-flash",
554     .extensions        = "swf",
555     .priv_data_size    = sizeof(SWFEncContext),
556     .audio_codec       = AV_CODEC_ID_MP3,
557     .video_codec       = AV_CODEC_ID_FLV1,
558     .write_header      = swf_write_header,
559     .write_packet      = swf_write_packet,
560     .write_trailer     = swf_write_trailer,
561     .deinit            = swf_deinit,
562     .flags             = AVFMT_TS_NONSTRICT,
563 };
564 #endif
565 #if CONFIG_AVM2_MUXER
566 const AVOutputFormat ff_avm2_muxer = {
567     .name              = "avm2",
568     .long_name         = NULL_IF_CONFIG_SMALL("SWF (ShockWave Flash) (AVM2)"),
569     .mime_type         = "application/x-shockwave-flash",
570     .priv_data_size    = sizeof(SWFEncContext),
571     .audio_codec       = AV_CODEC_ID_MP3,
572     .video_codec       = AV_CODEC_ID_FLV1,
573     .write_header      = swf_write_header,
574     .write_packet      = swf_write_packet,
575     .write_trailer     = swf_write_trailer,
576     .deinit            = swf_deinit,
577     .flags             = AVFMT_TS_NONSTRICT,
578 };
579 #endif
580