2 * Flash Compatible Streaming Format muxer
3 * Copyright (c) 2000 Fabrice Bellard
4 * Copyright (c) 2003 Tinic Uro
6 * This file is part of FFmpeg.
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.
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.
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
23 #include "config_components.h"
25 #include "libavcodec/put_bits.h"
26 #include "libavutil/avassert.h"
27 #include "libavutil/fifo.h"
33 #define AUDIO_FIFO_SIZE 65536
35 typedef struct SWFEncContext
{
39 int samples_per_frame
;
42 int video_frame_number
;
45 AVCodecParameters
*audio_par
, *video_par
;
49 static void put_swf_tag(AVFormatContext
*s
, int tag
)
51 SWFEncContext
*swf
= s
->priv_data
;
52 AVIOContext
*pb
= s
->pb
;
54 swf
->tag_pos
= avio_tell(pb
);
56 /* reserve some room for the tag */
65 static void put_swf_end_tag(AVFormatContext
*s
)
67 SWFEncContext
*swf
= s
->priv_data
;
68 AVIOContext
*pb
= s
->pb
;
73 tag_len
= pos
- swf
->tag_pos
- 2;
75 avio_seek(pb
, swf
->tag_pos
, SEEK_SET
);
78 avio_wl16(pb
, (tag
<< 6) | 0x3f);
79 avio_wl32(pb
, tag_len
- 4);
81 av_assert0(tag_len
< 0x3f);
82 avio_wl16(pb
, (tag
<< 6) | tag_len
);
84 avio_seek(pb
, pos
, SEEK_SET
);
87 static inline void max_nbits(int *nbits_ptr
, int val
)
103 static void put_swf_rect(AVIOContext
*pb
,
104 int xmin
, int xmax
, int ymin
, int ymax
)
110 init_put_bits(&p
, buf
, sizeof(buf
));
113 max_nbits(&nbits
, xmin
);
114 max_nbits(&nbits
, xmax
);
115 max_nbits(&nbits
, ymin
);
116 max_nbits(&nbits
, ymax
);
117 mask
= (1 << nbits
) - 1;
120 put_bits(&p
, 5, nbits
);
121 put_bits(&p
, nbits
, xmin
& mask
);
122 put_bits(&p
, nbits
, xmax
& mask
);
123 put_bits(&p
, nbits
, ymin
& mask
);
124 put_bits(&p
, nbits
, ymax
& mask
);
127 avio_write(pb
, buf
, put_bits_ptr(&p
) - p
.buf
);
130 static void put_swf_line_edge(PutBitContext
*pb
, int dx
, int dy
)
134 put_bits(pb
, 1, 1); /* edge */
135 put_bits(pb
, 1, 1); /* line select */
137 max_nbits(&nbits
, dx
);
138 max_nbits(&nbits
, dy
);
140 mask
= (1 << nbits
) - 1;
141 put_bits(pb
, 4, nbits
- 2); /* 16 bits precision */
145 put_bits(pb
, nbits
, dy
& mask
);
146 } else if (dy
== 0) {
149 put_bits(pb
, nbits
, dx
& mask
);
152 put_bits(pb
, nbits
, dx
& mask
);
153 put_bits(pb
, nbits
, dy
& mask
);
159 static void put_swf_matrix(AVIOContext
*pb
,
160 int a
, int b
, int c
, int d
, int tx
, int ty
)
166 init_put_bits(&p
, buf
, sizeof(buf
));
168 put_bits(&p
, 1, 1); /* a, d present */
170 max_nbits(&nbits
, a
);
171 max_nbits(&nbits
, d
);
172 put_bits(&p
, 5, nbits
); /* nb bits */
173 put_bits(&p
, nbits
, a
);
174 put_bits(&p
, nbits
, d
);
176 put_bits(&p
, 1, 1); /* b, c present */
178 max_nbits(&nbits
, c
);
179 max_nbits(&nbits
, b
);
180 put_bits(&p
, 5, nbits
); /* nb bits */
181 put_bits(&p
, nbits
, c
);
182 put_bits(&p
, nbits
, b
);
185 max_nbits(&nbits
, tx
);
186 max_nbits(&nbits
, ty
);
187 put_bits(&p
, 5, nbits
); /* nb bits */
188 put_bits(&p
, nbits
, tx
);
189 put_bits(&p
, nbits
, ty
);
192 avio_write(pb
, buf
, put_bits_ptr(&p
) - p
.buf
);
195 static int swf_write_header(AVFormatContext
*s
)
197 SWFEncContext
*swf
= s
->priv_data
;
198 AVIOContext
*pb
= s
->pb
;
201 int i
, width
, height
, rate
, rate_base
;
204 swf
->sound_samples
= 0;
205 swf
->swf_frame_number
= 0;
206 swf
->video_frame_number
= 0;
208 for(i
=0;i
<s
->nb_streams
;i
++) {
209 AVCodecParameters
*par
= s
->streams
[i
]->codecpar
;
210 if (par
->codec_type
== AVMEDIA_TYPE_AUDIO
) {
211 if (par
->codec_id
== AV_CODEC_ID_MP3
) {
212 swf
->audio_par
= par
;
213 swf
->audio_fifo
= av_fifo_alloc2(AUDIO_FIFO_SIZE
, 1, 0);
214 if (!swf
->audio_fifo
)
215 return AVERROR(ENOMEM
);
217 av_log(s
, AV_LOG_ERROR
, "SWF muxer only supports MP3\n");
221 if (ff_codec_get_tag(ff_swf_codec_tags
, par
->codec_id
) ||
222 par
->codec_id
== AV_CODEC_ID_PNG
||
223 par
->codec_id
== AV_CODEC_ID_MJPEG
) {
224 swf
->video_st
= s
->streams
[i
];
225 swf
->video_par
= par
;
227 av_log(s
, AV_LOG_ERROR
, "SWF muxer only supports VP6, FLV, Flash Screen Video, PNG and MJPEG\n");
233 if (!swf
->video_par
) {
234 /* currently, cannot work correctly if audio only */
240 width
= swf
->video_par
->width
;
241 height
= swf
->video_par
->height
;
242 // TODO: should be avg_frame_rate
243 rate
= swf
->video_st
->time_base
.den
;
244 rate_base
= swf
->video_st
->time_base
.num
;
248 swf
->samples_per_frame
= (44100LL * rate_base
) / rate
;
250 swf
->samples_per_frame
= (swf
->audio_par
->sample_rate
* rate_base
) / rate
;
252 avio_write(pb
, "FWS", 3);
254 if (!strcmp("avm2", s
->oformat
->name
))
256 else if (swf
->video_par
&& (swf
->video_par
->codec_id
== AV_CODEC_ID_VP6A
||
257 swf
->video_par
->codec_id
== AV_CODEC_ID_VP6F
||
258 swf
->video_par
->codec_id
== AV_CODEC_ID_PNG
))
259 version
= 8; /* version 8 and above support VP6 and PNG codec */
260 else if (swf
->video_par
&& swf
->video_par
->codec_id
== AV_CODEC_ID_FLASHSV
)
261 version
= 7; /* version 7 and above support Flash Screen Video codec */
262 else if (swf
->video_par
&& swf
->video_par
->codec_id
== AV_CODEC_ID_FLV1
)
263 version
= 6; /* version 6 and above support FLV1 codec */
265 version
= 4; /* version 4 for mpeg audio support */
266 avio_w8(pb
, version
);
268 avio_wl32(pb
, DUMMY_FILE_SIZE
); /* dummy size
269 (will be patched if not streamed) */
271 put_swf_rect(pb
, 0, width
* 20, 0, height
* 20);
272 if ((rate
* 256LL) / rate_base
>= (1<<16)) {
273 av_log(s
, AV_LOG_ERROR
, "Invalid (too large) frame rate %d/%d\n", rate
, rate_base
);
274 return AVERROR(EINVAL
);
276 avio_wl16(pb
, (rate
* 256LL) / rate_base
); /* frame rate */
277 swf
->duration_pos
= avio_tell(pb
);
278 avio_wl16(pb
, (uint16_t)(DUMMY_DURATION
* (int64_t)rate
/ rate_base
)); /* frame count */
280 /* swf v8 and later files require a file attribute tag */
282 put_swf_tag(s
, TAG_FILEATTRIBUTES
);
283 avio_wl32(pb
, (version
>= 9) << 3); /* set ActionScript v3/AVM2 flag */
287 /* define a shape with the jpeg inside */
288 if (swf
->video_par
&& (swf
->video_par
->codec_id
== AV_CODEC_ID_MJPEG
|| swf
->video_par
->codec_id
== AV_CODEC_ID_PNG
)) {
289 put_swf_tag(s
, TAG_DEFINESHAPE
);
291 avio_wl16(pb
, SHAPE_ID
); /* ID of shape */
292 /* bounding rectangle */
293 put_swf_rect(pb
, 0, width
, 0, height
);
295 avio_w8(pb
, 1); /* one fill style */
296 avio_w8(pb
, 0x41); /* clipped bitmap fill */
297 avio_wl16(pb
, BITMAP_ID
); /* bitmap ID */
298 /* position of the bitmap */
299 put_swf_matrix(pb
, 1 << FRAC_BITS
, 0,
300 0, 1 << FRAC_BITS
, 0, 0);
301 avio_w8(pb
, 0); /* no line style */
304 init_put_bits(&p
, buf1
, sizeof(buf1
));
305 put_bits(&p
, 4, 1); /* one fill bit */
306 put_bits(&p
, 4, 0); /* zero line bit */
308 put_bits(&p
, 1, 0); /* not an edge */
309 put_bits(&p
, 5, FLAG_MOVETO
| FLAG_SETFILL0
);
310 put_bits(&p
, 5, 1); /* nbits */
311 put_bits(&p
, 1, 0); /* X */
312 put_bits(&p
, 1, 0); /* Y */
313 put_bits(&p
, 1, 1); /* set fill style 1 */
315 /* draw the rectangle ! */
316 put_swf_line_edge(&p
, width
, 0);
317 put_swf_line_edge(&p
, 0, height
);
318 put_swf_line_edge(&p
, -width
, 0);
319 put_swf_line_edge(&p
, 0, -height
);
322 put_bits(&p
, 1, 0); /* not an edge */
326 avio_write(pb
, buf1
, put_bits_ptr(&p
) - p
.buf
);
331 if (swf
->audio_par
&& swf
->audio_par
->codec_id
== AV_CODEC_ID_MP3
) {
335 put_swf_tag(s
, TAG_STREAMHEAD2
);
336 switch(swf
->audio_par
->sample_rate
) {
337 case 11025: v
|= 1 << 2; break;
338 case 22050: v
|= 2 << 2; break;
339 case 44100: v
|= 3 << 2; break;
342 av_log(s
, AV_LOG_ERROR
, "swf does not support that sample rate, choose from (44100, 22050, 11025).\n");
345 v
|= 0x02; /* 16 bit playback */
346 if (swf
->audio_par
->ch_layout
.nb_channels
== 2)
347 v
|= 0x01; /* stereo playback */
349 v
|= 0x20; /* mp3 compressed */
351 avio_wl16(s
->pb
, swf
->samples_per_frame
); /* avg samples per frame */
360 static int fifo_avio_wrapper(void *opaque
, void *buf
, size_t *nb_elems
)
362 avio_write(opaque
, buf
, *nb_elems
);
366 static int swf_write_video(AVFormatContext
*s
,
367 AVCodecParameters
*par
, const uint8_t *buf
, int size
, unsigned pkt_flags
)
369 SWFEncContext
*swf
= s
->priv_data
;
370 AVIOContext
*pb
= s
->pb
;
371 unsigned codec_tag
= ff_codec_get_tag(ff_swf_codec_tags
, par
->codec_id
);
373 /* Flash Player limit */
374 if (swf
->swf_frame_number
== 16000)
375 av_log(s
, AV_LOG_INFO
, "warning: Flash Player limit of 16000 frames reached\n");
378 if (swf
->video_frame_number
== 0) {
379 /* create a new video object */
380 put_swf_tag(s
, TAG_VIDEOSTREAM
);
381 avio_wl16(pb
, VIDEO_ID
);
382 swf
->vframes_pos
= avio_tell(pb
);
383 avio_wl16(pb
, 15000); /* hard flash player limit */
384 avio_wl16(pb
, par
->width
);
385 avio_wl16(pb
, par
->height
);
387 avio_w8(pb
, codec_tag
);
390 /* place the video object for the first time */
391 put_swf_tag(s
, TAG_PLACEOBJECT2
);
394 avio_wl16(pb
, VIDEO_ID
);
395 put_swf_matrix(pb
, 1 << FRAC_BITS
, 0, 0, 1 << FRAC_BITS
, 0, 0);
396 avio_wl16(pb
, swf
->video_frame_number
);
397 avio_write(pb
, "video", 5);
401 /* mark the character for update */
402 put_swf_tag(s
, TAG_PLACEOBJECT2
);
405 avio_wl16(pb
, swf
->video_frame_number
);
409 /* set video frame data */
410 put_swf_tag(s
, TAG_VIDEOFRAME
| TAG_LONG
);
411 avio_wl16(pb
, VIDEO_ID
);
412 avio_wl16(pb
, swf
->video_frame_number
++);
413 if (par
->codec_id
== AV_CODEC_ID_FLASHSV
) {
414 /* FrameType and CodecId is needed here even if it is not documented correctly in the SWF specs */
415 int flags
= codec_tag
| (pkt_flags
& AV_PKT_FLAG_KEY
? FLV_FRAME_KEY
: FLV_FRAME_INTER
);
418 avio_write(pb
, buf
, size
);
420 } else if (par
->codec_id
== AV_CODEC_ID_MJPEG
|| par
->codec_id
== AV_CODEC_ID_PNG
) {
421 if (swf
->swf_frame_number
> 0) {
422 /* remove the shape */
423 put_swf_tag(s
, TAG_REMOVEOBJECT
);
424 avio_wl16(pb
, SHAPE_ID
); /* shape ID */
425 avio_wl16(pb
, 1); /* depth */
428 /* free the bitmap */
429 put_swf_tag(s
, TAG_FREECHARACTER
);
430 avio_wl16(pb
, BITMAP_ID
);
434 put_swf_tag(s
, TAG_JPEG2
| TAG_LONG
);
436 avio_wl16(pb
, BITMAP_ID
); /* ID of the image */
438 /* a dummy jpeg header seems to be required */
439 if (par
->codec_id
== AV_CODEC_ID_MJPEG
)
440 avio_wb32(pb
, 0xffd8ffd9);
441 /* write the jpeg/png image */
442 avio_write(pb
, buf
, size
);
448 put_swf_tag(s
, TAG_PLACEOBJECT
);
449 avio_wl16(pb
, SHAPE_ID
); /* shape ID */
450 avio_wl16(pb
, 1); /* depth */
451 put_swf_matrix(pb
, 20 << FRAC_BITS
, 0, 0, 20 << FRAC_BITS
, 0, 0);
455 swf
->swf_frame_number
++;
457 /* streaming sound always should be placed just before showframe tags */
458 if (swf
->audio_par
&& av_fifo_can_read(swf
->audio_fifo
)) {
459 size_t frame_size
= av_fifo_can_read(swf
->audio_fifo
);
460 put_swf_tag(s
, TAG_STREAMBLOCK
| TAG_LONG
);
461 avio_wl16(pb
, swf
->sound_samples
);
462 avio_wl16(pb
, 0); // seek samples
463 av_fifo_read_to_cb(swf
->audio_fifo
, fifo_avio_wrapper
, pb
, &frame_size
);
467 swf
->sound_samples
= 0;
470 /* output the frame */
471 put_swf_tag(s
, TAG_SHOWFRAME
);
477 static int swf_write_audio(AVFormatContext
*s
, AVCodecParameters
*par
,
478 const uint8_t *buf
, int size
)
480 SWFEncContext
*swf
= s
->priv_data
;
482 /* Flash Player limit */
483 if (swf
->swf_frame_number
== 16000)
484 av_log(s
, AV_LOG_INFO
, "warning: Flash Player limit of 16000 frames reached\n");
486 if (av_fifo_can_write(swf
->audio_fifo
) < size
) {
487 av_log(s
, AV_LOG_ERROR
, "audio fifo too small to mux audio essence\n");
491 av_fifo_write(swf
->audio_fifo
, buf
, size
);
492 swf
->sound_samples
+= av_get_audio_frame_duration2(par
, size
);
494 /* if audio only stream make sure we add swf frames */
496 swf_write_video(s
, par
, 0, 0, 0);
501 static int swf_write_packet(AVFormatContext
*s
, AVPacket
*pkt
)
503 AVCodecParameters
*par
= s
->streams
[pkt
->stream_index
]->codecpar
;
504 if (par
->codec_type
== AVMEDIA_TYPE_AUDIO
)
505 return swf_write_audio(s
, par
, pkt
->data
, pkt
->size
);
507 return swf_write_video(s
, par
, pkt
->data
, pkt
->size
, pkt
->flags
);
510 static int swf_write_trailer(AVFormatContext
*s
)
512 SWFEncContext
*swf
= s
->priv_data
;
513 AVIOContext
*pb
= s
->pb
;
516 put_swf_tag(s
, TAG_END
);
519 /* patch file size and number of frames if not streamed */
520 if ((s
->pb
->seekable
& AVIO_SEEKABLE_NORMAL
) && swf
->video_par
) {
521 file_size
= avio_tell(pb
);
522 avio_seek(pb
, 4, SEEK_SET
);
523 avio_wl32(pb
, file_size
);
524 avio_seek(pb
, swf
->duration_pos
, SEEK_SET
);
525 avio_wl16(pb
, swf
->video_frame_number
);
526 if (swf
->vframes_pos
) {
527 avio_seek(pb
, swf
->vframes_pos
, SEEK_SET
);
528 avio_wl16(pb
, swf
->video_frame_number
);
530 avio_seek(pb
, file_size
, SEEK_SET
);
535 static void swf_deinit(AVFormatContext
*s
)
537 SWFEncContext
*swf
= s
->priv_data
;
539 av_fifo_freep2(&swf
->audio_fifo
);
543 const FFOutputFormat ff_swf_muxer
= {
545 .p
.long_name
= NULL_IF_CONFIG_SMALL("SWF (ShockWave Flash)"),
546 .p
.mime_type
= "application/x-shockwave-flash",
547 .p
.extensions
= "swf",
548 .priv_data_size
= sizeof(SWFEncContext
),
549 .p
.audio_codec
= AV_CODEC_ID_MP3
,
550 .p
.video_codec
= AV_CODEC_ID_FLV1
,
551 .p
.subtitle_codec
= AV_CODEC_ID_NONE
,
552 .write_header
= swf_write_header
,
553 .write_packet
= swf_write_packet
,
554 .write_trailer
= swf_write_trailer
,
555 .deinit
= swf_deinit
,
556 .p
.flags
= AVFMT_TS_NONSTRICT
,
557 .flags_internal
= FF_OFMT_FLAG_MAX_ONE_OF_EACH
,
560 #if CONFIG_AVM2_MUXER
561 const FFOutputFormat ff_avm2_muxer
= {
563 .p
.long_name
= NULL_IF_CONFIG_SMALL("SWF (ShockWave Flash) (AVM2)"),
564 .p
.mime_type
= "application/x-shockwave-flash",
565 .priv_data_size
= sizeof(SWFEncContext
),
566 .p
.audio_codec
= AV_CODEC_ID_MP3
,
567 .p
.video_codec
= AV_CODEC_ID_FLV1
,
568 .p
.subtitle_codec
= AV_CODEC_ID_NONE
,
569 .write_header
= swf_write_header
,
570 .write_packet
= swf_write_packet
,
571 .write_trailer
= swf_write_trailer
,
572 .deinit
= swf_deinit
,
573 .p
.flags
= AVFMT_TS_NONSTRICT
,
574 .flags_internal
= FF_OFMT_FLAG_MAX_ONE_OF_EACH
,