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