00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "libavcodec/put_bits.h"
00024 #include "avformat.h"
00025 #include "swf.h"
00026
00027 static void put_swf_tag(AVFormatContext *s, int tag)
00028 {
00029 SWFContext *swf = s->priv_data;
00030 AVIOContext *pb = s->pb;
00031
00032 swf->tag_pos = avio_tell(pb);
00033 swf->tag = tag;
00034
00035 if (tag & TAG_LONG) {
00036 avio_wl16(pb, 0);
00037 avio_wl32(pb, 0);
00038 } else {
00039 avio_wl16(pb, 0);
00040 }
00041 }
00042
00043 static void put_swf_end_tag(AVFormatContext *s)
00044 {
00045 SWFContext *swf = s->priv_data;
00046 AVIOContext *pb = s->pb;
00047 int64_t pos;
00048 int tag_len, tag;
00049
00050 pos = avio_tell(pb);
00051 tag_len = pos - swf->tag_pos - 2;
00052 tag = swf->tag;
00053 avio_seek(pb, swf->tag_pos, SEEK_SET);
00054 if (tag & TAG_LONG) {
00055 tag &= ~TAG_LONG;
00056 avio_wl16(pb, (tag << 6) | 0x3f);
00057 avio_wl32(pb, tag_len - 4);
00058 } else {
00059 assert(tag_len < 0x3f);
00060 avio_wl16(pb, (tag << 6) | tag_len);
00061 }
00062 avio_seek(pb, pos, SEEK_SET);
00063 }
00064
00065 static inline void max_nbits(int *nbits_ptr, int val)
00066 {
00067 int n;
00068
00069 if (val == 0)
00070 return;
00071 val = abs(val);
00072 n = 1;
00073 while (val != 0) {
00074 n++;
00075 val >>= 1;
00076 }
00077 if (n > *nbits_ptr)
00078 *nbits_ptr = n;
00079 }
00080
00081 static void put_swf_rect(AVIOContext *pb,
00082 int xmin, int xmax, int ymin, int ymax)
00083 {
00084 PutBitContext p;
00085 uint8_t buf[256];
00086 int nbits, mask;
00087
00088 init_put_bits(&p, buf, sizeof(buf));
00089
00090 nbits = 0;
00091 max_nbits(&nbits, xmin);
00092 max_nbits(&nbits, xmax);
00093 max_nbits(&nbits, ymin);
00094 max_nbits(&nbits, ymax);
00095 mask = (1 << nbits) - 1;
00096
00097
00098 put_bits(&p, 5, nbits);
00099 put_bits(&p, nbits, xmin & mask);
00100 put_bits(&p, nbits, xmax & mask);
00101 put_bits(&p, nbits, ymin & mask);
00102 put_bits(&p, nbits, ymax & mask);
00103
00104 flush_put_bits(&p);
00105 avio_write(pb, buf, put_bits_ptr(&p) - p.buf);
00106 }
00107
00108 static void put_swf_line_edge(PutBitContext *pb, int dx, int dy)
00109 {
00110 int nbits, mask;
00111
00112 put_bits(pb, 1, 1);
00113 put_bits(pb, 1, 1);
00114 nbits = 2;
00115 max_nbits(&nbits, dx);
00116 max_nbits(&nbits, dy);
00117
00118 mask = (1 << nbits) - 1;
00119 put_bits(pb, 4, nbits - 2);
00120 if (dx == 0) {
00121 put_bits(pb, 1, 0);
00122 put_bits(pb, 1, 1);
00123 put_bits(pb, nbits, dy & mask);
00124 } else if (dy == 0) {
00125 put_bits(pb, 1, 0);
00126 put_bits(pb, 1, 0);
00127 put_bits(pb, nbits, dx & mask);
00128 } else {
00129 put_bits(pb, 1, 1);
00130 put_bits(pb, nbits, dx & mask);
00131 put_bits(pb, nbits, dy & mask);
00132 }
00133 }
00134
00135 #define FRAC_BITS 16
00136
00137 static void put_swf_matrix(AVIOContext *pb,
00138 int a, int b, int c, int d, int tx, int ty)
00139 {
00140 PutBitContext p;
00141 uint8_t buf[256];
00142 int nbits;
00143
00144 init_put_bits(&p, buf, sizeof(buf));
00145
00146 put_bits(&p, 1, 1);
00147 nbits = 1;
00148 max_nbits(&nbits, a);
00149 max_nbits(&nbits, d);
00150 put_bits(&p, 5, nbits);
00151 put_bits(&p, nbits, a);
00152 put_bits(&p, nbits, d);
00153
00154 put_bits(&p, 1, 1);
00155 nbits = 1;
00156 max_nbits(&nbits, c);
00157 max_nbits(&nbits, b);
00158 put_bits(&p, 5, nbits);
00159 put_bits(&p, nbits, c);
00160 put_bits(&p, nbits, b);
00161
00162 nbits = 1;
00163 max_nbits(&nbits, tx);
00164 max_nbits(&nbits, ty);
00165 put_bits(&p, 5, nbits);
00166 put_bits(&p, nbits, tx);
00167 put_bits(&p, nbits, ty);
00168
00169 flush_put_bits(&p);
00170 avio_write(pb, buf, put_bits_ptr(&p) - p.buf);
00171 }
00172
00173 static int swf_write_header(AVFormatContext *s)
00174 {
00175 SWFContext *swf = s->priv_data;
00176 AVIOContext *pb = s->pb;
00177 PutBitContext p;
00178 uint8_t buf1[256];
00179 int i, width, height, rate, rate_base;
00180 int version;
00181
00182 swf->sound_samples = 0;
00183 swf->swf_frame_number = 0;
00184 swf->video_frame_number = 0;
00185
00186 for(i=0;i<s->nb_streams;i++) {
00187 AVCodecContext *enc = s->streams[i]->codec;
00188 if (enc->codec_type == AVMEDIA_TYPE_AUDIO) {
00189 if (enc->codec_id == CODEC_ID_MP3) {
00190 if (!enc->frame_size) {
00191 av_log(s, AV_LOG_ERROR, "audio frame size not set\n");
00192 return -1;
00193 }
00194 swf->audio_enc = enc;
00195 swf->audio_fifo= av_fifo_alloc(AUDIO_FIFO_SIZE);
00196 if (!swf->audio_fifo)
00197 return AVERROR(ENOMEM);
00198 } else {
00199 av_log(s, AV_LOG_ERROR, "SWF muxer only supports MP3\n");
00200 return -1;
00201 }
00202 } else {
00203 if (enc->codec_id == CODEC_ID_VP6F ||
00204 enc->codec_id == CODEC_ID_FLV1 ||
00205 enc->codec_id == CODEC_ID_MJPEG) {
00206 swf->video_enc = enc;
00207 } else {
00208 av_log(s, AV_LOG_ERROR, "SWF muxer only supports VP6, FLV1 and MJPEG\n");
00209 return -1;
00210 }
00211 }
00212 }
00213
00214 if (!swf->video_enc) {
00215
00216 width = 320;
00217 height = 200;
00218 rate = 10;
00219 rate_base= 1;
00220 } else {
00221 width = swf->video_enc->width;
00222 height = swf->video_enc->height;
00223 rate = swf->video_enc->time_base.den;
00224 rate_base = swf->video_enc->time_base.num;
00225 }
00226
00227 if (!swf->audio_enc)
00228 swf->samples_per_frame = (44100. * rate_base) / rate;
00229 else
00230 swf->samples_per_frame = (swf->audio_enc->sample_rate * rate_base) / rate;
00231
00232 avio_write(pb, "FWS", 3);
00233
00234 if (!strcmp("avm2", s->oformat->name))
00235 version = 9;
00236 else if (swf->video_enc && swf->video_enc->codec_id == CODEC_ID_VP6F)
00237 version = 8;
00238 else if (swf->video_enc && swf->video_enc->codec_id == CODEC_ID_FLV1)
00239 version = 6;
00240 else
00241 version = 4;
00242 avio_w8(pb, version);
00243
00244 avio_wl32(pb, DUMMY_FILE_SIZE);
00245
00246
00247 put_swf_rect(pb, 0, width * 20, 0, height * 20);
00248 avio_wl16(pb, (rate * 256) / rate_base);
00249 swf->duration_pos = avio_tell(pb);
00250 avio_wl16(pb, (uint16_t)(DUMMY_DURATION * (int64_t)rate / rate_base));
00251
00252
00253 if (version == 9) {
00254 put_swf_tag(s, TAG_FILEATTRIBUTES);
00255 avio_wl32(pb, 1<<3);
00256 put_swf_end_tag(s);
00257 }
00258
00259
00260 if (swf->video_enc && swf->video_enc->codec_id == CODEC_ID_MJPEG) {
00261 put_swf_tag(s, TAG_DEFINESHAPE);
00262
00263 avio_wl16(pb, SHAPE_ID);
00264
00265 put_swf_rect(pb, 0, width, 0, height);
00266
00267 avio_w8(pb, 1);
00268 avio_w8(pb, 0x41);
00269 avio_wl16(pb, BITMAP_ID);
00270
00271 put_swf_matrix(pb, (int)(1.0 * (1 << FRAC_BITS)), 0,
00272 0, (int)(1.0 * (1 << FRAC_BITS)), 0, 0);
00273 avio_w8(pb, 0);
00274
00275
00276 init_put_bits(&p, buf1, sizeof(buf1));
00277 put_bits(&p, 4, 1);
00278 put_bits(&p, 4, 0);
00279
00280 put_bits(&p, 1, 0);
00281 put_bits(&p, 5, FLAG_MOVETO | FLAG_SETFILL0);
00282 put_bits(&p, 5, 1);
00283 put_bits(&p, 1, 0);
00284 put_bits(&p, 1, 0);
00285 put_bits(&p, 1, 1);
00286
00287
00288 put_swf_line_edge(&p, width, 0);
00289 put_swf_line_edge(&p, 0, height);
00290 put_swf_line_edge(&p, -width, 0);
00291 put_swf_line_edge(&p, 0, -height);
00292
00293
00294 put_bits(&p, 1, 0);
00295 put_bits(&p, 5, 0);
00296
00297 flush_put_bits(&p);
00298 avio_write(pb, buf1, put_bits_ptr(&p) - p.buf);
00299
00300 put_swf_end_tag(s);
00301 }
00302
00303 if (swf->audio_enc && swf->audio_enc->codec_id == CODEC_ID_MP3) {
00304 int v = 0;
00305
00306
00307 put_swf_tag(s, TAG_STREAMHEAD2);
00308 switch(swf->audio_enc->sample_rate) {
00309 case 11025: v |= 1 << 2; break;
00310 case 22050: v |= 2 << 2; break;
00311 case 44100: v |= 3 << 2; break;
00312 default:
00313
00314 av_log(s, AV_LOG_ERROR, "swf does not support that sample rate, choose from (44100, 22050, 11025).\n");
00315 return -1;
00316 }
00317 v |= 0x02;
00318 if (swf->audio_enc->channels == 2)
00319 v |= 0x01;
00320 avio_w8(s->pb, v);
00321 v |= 0x20;
00322 avio_w8(s->pb, v);
00323 avio_wl16(s->pb, swf->samples_per_frame);
00324 avio_wl16(s->pb, 0);
00325
00326 put_swf_end_tag(s);
00327 }
00328
00329 avio_flush(s->pb);
00330 return 0;
00331 }
00332
00333 static int swf_write_video(AVFormatContext *s,
00334 AVCodecContext *enc, const uint8_t *buf, int size)
00335 {
00336 SWFContext *swf = s->priv_data;
00337 AVIOContext *pb = s->pb;
00338
00339
00340 if (swf->swf_frame_number == 16000)
00341 av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
00342
00343 if (enc->codec_id == CODEC_ID_VP6F ||
00344 enc->codec_id == CODEC_ID_FLV1) {
00345 if (swf->video_frame_number == 0) {
00346
00347 put_swf_tag(s, TAG_VIDEOSTREAM);
00348 avio_wl16(pb, VIDEO_ID);
00349 swf->vframes_pos = avio_tell(pb);
00350 avio_wl16(pb, 15000);
00351 avio_wl16(pb, enc->width);
00352 avio_wl16(pb, enc->height);
00353 avio_w8(pb, 0);
00354 avio_w8(pb,ff_codec_get_tag(swf_codec_tags,enc->codec_id));
00355 put_swf_end_tag(s);
00356
00357
00358 put_swf_tag(s, TAG_PLACEOBJECT2);
00359 avio_w8(pb, 0x36);
00360 avio_wl16(pb, 1);
00361 avio_wl16(pb, VIDEO_ID);
00362 put_swf_matrix(pb, 1 << FRAC_BITS, 0, 0, 1 << FRAC_BITS, 0, 0);
00363 avio_wl16(pb, swf->video_frame_number);
00364 avio_write(pb, "video", 5);
00365 avio_w8(pb, 0x00);
00366 put_swf_end_tag(s);
00367 } else {
00368
00369 put_swf_tag(s, TAG_PLACEOBJECT2);
00370 avio_w8(pb, 0x11);
00371 avio_wl16(pb, 1);
00372 avio_wl16(pb, swf->video_frame_number);
00373 put_swf_end_tag(s);
00374 }
00375
00376
00377 put_swf_tag(s, TAG_VIDEOFRAME | TAG_LONG);
00378 avio_wl16(pb, VIDEO_ID);
00379 avio_wl16(pb, swf->video_frame_number++);
00380 avio_write(pb, buf, size);
00381 put_swf_end_tag(s);
00382 } else if (enc->codec_id == CODEC_ID_MJPEG) {
00383 if (swf->swf_frame_number > 0) {
00384
00385 put_swf_tag(s, TAG_REMOVEOBJECT);
00386 avio_wl16(pb, SHAPE_ID);
00387 avio_wl16(pb, 1);
00388 put_swf_end_tag(s);
00389
00390
00391 put_swf_tag(s, TAG_FREECHARACTER);
00392 avio_wl16(pb, BITMAP_ID);
00393 put_swf_end_tag(s);
00394 }
00395
00396 put_swf_tag(s, TAG_JPEG2 | TAG_LONG);
00397
00398 avio_wl16(pb, BITMAP_ID);
00399
00400
00401 avio_wb32(pb, 0xffd8ffd9);
00402
00403 avio_write(pb, buf, size);
00404
00405 put_swf_end_tag(s);
00406
00407
00408
00409 put_swf_tag(s, TAG_PLACEOBJECT);
00410 avio_wl16(pb, SHAPE_ID);
00411 avio_wl16(pb, 1);
00412 put_swf_matrix(pb, 20 << FRAC_BITS, 0, 0, 20 << FRAC_BITS, 0, 0);
00413 put_swf_end_tag(s);
00414 }
00415
00416 swf->swf_frame_number++;
00417
00418
00419 if (swf->audio_enc && av_fifo_size(swf->audio_fifo)) {
00420 int frame_size = av_fifo_size(swf->audio_fifo);
00421 put_swf_tag(s, TAG_STREAMBLOCK | TAG_LONG);
00422 avio_wl16(pb, swf->sound_samples);
00423 avio_wl16(pb, 0);
00424 av_fifo_generic_read(swf->audio_fifo, pb, frame_size, (void*)avio_write);
00425 put_swf_end_tag(s);
00426
00427
00428 swf->sound_samples = 0;
00429 }
00430
00431
00432 put_swf_tag(s, TAG_SHOWFRAME);
00433 put_swf_end_tag(s);
00434
00435 avio_flush(s->pb);
00436
00437 return 0;
00438 }
00439
00440 static int swf_write_audio(AVFormatContext *s,
00441 AVCodecContext *enc, uint8_t *buf, int size)
00442 {
00443 SWFContext *swf = s->priv_data;
00444
00445
00446 if (swf->swf_frame_number == 16000)
00447 av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
00448
00449 if (av_fifo_size(swf->audio_fifo) + size > AUDIO_FIFO_SIZE) {
00450 av_log(s, AV_LOG_ERROR, "audio fifo too small to mux audio essence\n");
00451 return -1;
00452 }
00453
00454 av_fifo_generic_write(swf->audio_fifo, buf, size, NULL);
00455 swf->sound_samples += enc->frame_size;
00456
00457
00458 if (!swf->video_enc)
00459 swf_write_video(s, enc, 0, 0);
00460
00461 return 0;
00462 }
00463
00464 static int swf_write_packet(AVFormatContext *s, AVPacket *pkt)
00465 {
00466 AVCodecContext *codec = s->streams[pkt->stream_index]->codec;
00467 if (codec->codec_type == AVMEDIA_TYPE_AUDIO)
00468 return swf_write_audio(s, codec, pkt->data, pkt->size);
00469 else
00470 return swf_write_video(s, codec, pkt->data, pkt->size);
00471 }
00472
00473 static int swf_write_trailer(AVFormatContext *s)
00474 {
00475 SWFContext *swf = s->priv_data;
00476 AVIOContext *pb = s->pb;
00477 AVCodecContext *enc, *video_enc;
00478 int file_size, i;
00479
00480 video_enc = NULL;
00481 for(i=0;i<s->nb_streams;i++) {
00482 enc = s->streams[i]->codec;
00483 if (enc->codec_type == AVMEDIA_TYPE_VIDEO)
00484 video_enc = enc;
00485 else
00486 av_fifo_free(swf->audio_fifo);
00487 }
00488
00489 put_swf_tag(s, TAG_END);
00490 put_swf_end_tag(s);
00491
00492 avio_flush(s->pb);
00493
00494
00495 if (s->pb->seekable && video_enc) {
00496 file_size = avio_tell(pb);
00497 avio_seek(pb, 4, SEEK_SET);
00498 avio_wl32(pb, file_size);
00499 avio_seek(pb, swf->duration_pos, SEEK_SET);
00500 avio_wl16(pb, swf->video_frame_number);
00501 if (swf->vframes_pos) {
00502 avio_seek(pb, swf->vframes_pos, SEEK_SET);
00503 avio_wl16(pb, swf->video_frame_number);
00504 }
00505 avio_seek(pb, file_size, SEEK_SET);
00506 }
00507 return 0;
00508 }
00509
00510 #if CONFIG_SWF_MUXER
00511 AVOutputFormat ff_swf_muxer = {
00512 "swf",
00513 NULL_IF_CONFIG_SMALL("Flash format"),
00514 "application/x-shockwave-flash",
00515 "swf",
00516 sizeof(SWFContext),
00517 CODEC_ID_MP3,
00518 CODEC_ID_FLV1,
00519 swf_write_header,
00520 swf_write_packet,
00521 swf_write_trailer,
00522 };
00523 #endif
00524 #if CONFIG_AVM2_MUXER
00525 AVOutputFormat ff_avm2_muxer = {
00526 "avm2",
00527 NULL_IF_CONFIG_SMALL("Flash 9 (AVM2) format"),
00528 "application/x-shockwave-flash",
00529 NULL,
00530 sizeof(SWFContext),
00531 CODEC_ID_MP3,
00532 CODEC_ID_FLV1,
00533 swf_write_header,
00534 swf_write_packet,
00535 swf_write_trailer,
00536 };
00537 #endif