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 swf->audio_enc = enc;
00191 swf->audio_fifo= av_fifo_alloc(AUDIO_FIFO_SIZE);
00192 if (!swf->audio_fifo)
00193 return AVERROR(ENOMEM);
00194 } else {
00195 av_log(s, AV_LOG_ERROR, "SWF muxer only supports MP3\n");
00196 return -1;
00197 }
00198 } else {
00199 if (enc->codec_id == CODEC_ID_VP6F ||
00200 enc->codec_id == CODEC_ID_FLV1 ||
00201 enc->codec_id == CODEC_ID_MJPEG) {
00202 swf->video_enc = enc;
00203 } else {
00204 av_log(s, AV_LOG_ERROR, "SWF muxer only supports VP6, FLV1 and MJPEG\n");
00205 return -1;
00206 }
00207 }
00208 }
00209
00210 if (!swf->video_enc) {
00211
00212 width = 320;
00213 height = 200;
00214 rate = 10;
00215 rate_base= 1;
00216 } else {
00217 width = swf->video_enc->width;
00218 height = swf->video_enc->height;
00219 rate = swf->video_enc->time_base.den;
00220 rate_base = swf->video_enc->time_base.num;
00221 }
00222
00223 if (!swf->audio_enc)
00224 swf->samples_per_frame = (44100. * rate_base) / rate;
00225 else
00226 swf->samples_per_frame = (swf->audio_enc->sample_rate * rate_base) / rate;
00227
00228 avio_write(pb, "FWS", 3);
00229
00230 if (!strcmp("avm2", s->oformat->name))
00231 version = 9;
00232 else if (swf->video_enc && swf->video_enc->codec_id == CODEC_ID_VP6F)
00233 version = 8;
00234 else if (swf->video_enc && swf->video_enc->codec_id == CODEC_ID_FLV1)
00235 version = 6;
00236 else
00237 version = 4;
00238 avio_w8(pb, version);
00239
00240 avio_wl32(pb, DUMMY_FILE_SIZE);
00241
00242
00243 put_swf_rect(pb, 0, width * 20, 0, height * 20);
00244 avio_wl16(pb, (rate * 256) / rate_base);
00245 swf->duration_pos = avio_tell(pb);
00246 avio_wl16(pb, (uint16_t)(DUMMY_DURATION * (int64_t)rate / rate_base));
00247
00248
00249 if (version == 9) {
00250 put_swf_tag(s, TAG_FILEATTRIBUTES);
00251 avio_wl32(pb, 1<<3);
00252 put_swf_end_tag(s);
00253 }
00254
00255
00256 if (swf->video_enc && swf->video_enc->codec_id == CODEC_ID_MJPEG) {
00257 put_swf_tag(s, TAG_DEFINESHAPE);
00258
00259 avio_wl16(pb, SHAPE_ID);
00260
00261 put_swf_rect(pb, 0, width, 0, height);
00262
00263 avio_w8(pb, 1);
00264 avio_w8(pb, 0x41);
00265 avio_wl16(pb, BITMAP_ID);
00266
00267 put_swf_matrix(pb, (int)(1.0 * (1 << FRAC_BITS)), 0,
00268 0, (int)(1.0 * (1 << FRAC_BITS)), 0, 0);
00269 avio_w8(pb, 0);
00270
00271
00272 init_put_bits(&p, buf1, sizeof(buf1));
00273 put_bits(&p, 4, 1);
00274 put_bits(&p, 4, 0);
00275
00276 put_bits(&p, 1, 0);
00277 put_bits(&p, 5, FLAG_MOVETO | FLAG_SETFILL0);
00278 put_bits(&p, 5, 1);
00279 put_bits(&p, 1, 0);
00280 put_bits(&p, 1, 0);
00281 put_bits(&p, 1, 1);
00282
00283
00284 put_swf_line_edge(&p, width, 0);
00285 put_swf_line_edge(&p, 0, height);
00286 put_swf_line_edge(&p, -width, 0);
00287 put_swf_line_edge(&p, 0, -height);
00288
00289
00290 put_bits(&p, 1, 0);
00291 put_bits(&p, 5, 0);
00292
00293 flush_put_bits(&p);
00294 avio_write(pb, buf1, put_bits_ptr(&p) - p.buf);
00295
00296 put_swf_end_tag(s);
00297 }
00298
00299 if (swf->audio_enc && swf->audio_enc->codec_id == CODEC_ID_MP3) {
00300 int v = 0;
00301
00302
00303 put_swf_tag(s, TAG_STREAMHEAD2);
00304 switch(swf->audio_enc->sample_rate) {
00305 case 11025: v |= 1 << 2; break;
00306 case 22050: v |= 2 << 2; break;
00307 case 44100: v |= 3 << 2; break;
00308 default:
00309
00310 av_log(s, AV_LOG_ERROR, "swf does not support that sample rate, choose from (44100, 22050, 11025).\n");
00311 return -1;
00312 }
00313 v |= 0x02;
00314 if (swf->audio_enc->channels == 2)
00315 v |= 0x01;
00316 avio_w8(s->pb, v);
00317 v |= 0x20;
00318 avio_w8(s->pb, v);
00319 avio_wl16(s->pb, swf->samples_per_frame);
00320 avio_wl16(s->pb, 0);
00321
00322 put_swf_end_tag(s);
00323 }
00324
00325 avio_flush(s->pb);
00326 return 0;
00327 }
00328
00329 static int swf_write_video(AVFormatContext *s,
00330 AVCodecContext *enc, const uint8_t *buf, int size)
00331 {
00332 SWFContext *swf = s->priv_data;
00333 AVIOContext *pb = s->pb;
00334
00335
00336 if (swf->swf_frame_number == 16000)
00337 av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
00338
00339 if (enc->codec_id == CODEC_ID_VP6F ||
00340 enc->codec_id == CODEC_ID_FLV1) {
00341 if (swf->video_frame_number == 0) {
00342
00343 put_swf_tag(s, TAG_VIDEOSTREAM);
00344 avio_wl16(pb, VIDEO_ID);
00345 swf->vframes_pos = avio_tell(pb);
00346 avio_wl16(pb, 15000);
00347 avio_wl16(pb, enc->width);
00348 avio_wl16(pb, enc->height);
00349 avio_w8(pb, 0);
00350 avio_w8(pb,ff_codec_get_tag(swf_codec_tags,enc->codec_id));
00351 put_swf_end_tag(s);
00352
00353
00354 put_swf_tag(s, TAG_PLACEOBJECT2);
00355 avio_w8(pb, 0x36);
00356 avio_wl16(pb, 1);
00357 avio_wl16(pb, VIDEO_ID);
00358 put_swf_matrix(pb, 1 << FRAC_BITS, 0, 0, 1 << FRAC_BITS, 0, 0);
00359 avio_wl16(pb, swf->video_frame_number);
00360 avio_write(pb, "video", 5);
00361 avio_w8(pb, 0x00);
00362 put_swf_end_tag(s);
00363 } else {
00364
00365 put_swf_tag(s, TAG_PLACEOBJECT2);
00366 avio_w8(pb, 0x11);
00367 avio_wl16(pb, 1);
00368 avio_wl16(pb, swf->video_frame_number);
00369 put_swf_end_tag(s);
00370 }
00371
00372
00373 put_swf_tag(s, TAG_VIDEOFRAME | TAG_LONG);
00374 avio_wl16(pb, VIDEO_ID);
00375 avio_wl16(pb, swf->video_frame_number++);
00376 avio_write(pb, buf, size);
00377 put_swf_end_tag(s);
00378 } else if (enc->codec_id == CODEC_ID_MJPEG) {
00379 if (swf->swf_frame_number > 0) {
00380
00381 put_swf_tag(s, TAG_REMOVEOBJECT);
00382 avio_wl16(pb, SHAPE_ID);
00383 avio_wl16(pb, 1);
00384 put_swf_end_tag(s);
00385
00386
00387 put_swf_tag(s, TAG_FREECHARACTER);
00388 avio_wl16(pb, BITMAP_ID);
00389 put_swf_end_tag(s);
00390 }
00391
00392 put_swf_tag(s, TAG_JPEG2 | TAG_LONG);
00393
00394 avio_wl16(pb, BITMAP_ID);
00395
00396
00397 avio_wb32(pb, 0xffd8ffd9);
00398
00399 avio_write(pb, buf, size);
00400
00401 put_swf_end_tag(s);
00402
00403
00404
00405 put_swf_tag(s, TAG_PLACEOBJECT);
00406 avio_wl16(pb, SHAPE_ID);
00407 avio_wl16(pb, 1);
00408 put_swf_matrix(pb, 20 << FRAC_BITS, 0, 0, 20 << FRAC_BITS, 0, 0);
00409 put_swf_end_tag(s);
00410 }
00411
00412 swf->swf_frame_number++;
00413
00414
00415 if (swf->audio_enc && av_fifo_size(swf->audio_fifo)) {
00416 int frame_size = av_fifo_size(swf->audio_fifo);
00417 put_swf_tag(s, TAG_STREAMBLOCK | TAG_LONG);
00418 avio_wl16(pb, swf->sound_samples);
00419 avio_wl16(pb, 0);
00420 av_fifo_generic_read(swf->audio_fifo, pb, frame_size, (void*)avio_write);
00421 put_swf_end_tag(s);
00422
00423
00424 swf->sound_samples = 0;
00425 }
00426
00427
00428 put_swf_tag(s, TAG_SHOWFRAME);
00429 put_swf_end_tag(s);
00430
00431 avio_flush(s->pb);
00432
00433 return 0;
00434 }
00435
00436 static int swf_write_audio(AVFormatContext *s,
00437 AVCodecContext *enc, uint8_t *buf, int size)
00438 {
00439 SWFContext *swf = s->priv_data;
00440
00441
00442 if (swf->swf_frame_number == 16000)
00443 av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
00444
00445 if (av_fifo_size(swf->audio_fifo) + size > AUDIO_FIFO_SIZE) {
00446 av_log(s, AV_LOG_ERROR, "audio fifo too small to mux audio essence\n");
00447 return -1;
00448 }
00449
00450 av_fifo_generic_write(swf->audio_fifo, buf, size, NULL);
00451 swf->sound_samples += av_get_audio_frame_duration(enc, size);
00452
00453
00454 if (!swf->video_enc)
00455 swf_write_video(s, enc, 0, 0);
00456
00457 return 0;
00458 }
00459
00460 static int swf_write_packet(AVFormatContext *s, AVPacket *pkt)
00461 {
00462 AVCodecContext *codec = s->streams[pkt->stream_index]->codec;
00463 if (codec->codec_type == AVMEDIA_TYPE_AUDIO)
00464 return swf_write_audio(s, codec, pkt->data, pkt->size);
00465 else
00466 return swf_write_video(s, codec, pkt->data, pkt->size);
00467 }
00468
00469 static int swf_write_trailer(AVFormatContext *s)
00470 {
00471 SWFContext *swf = s->priv_data;
00472 AVIOContext *pb = s->pb;
00473 AVCodecContext *enc, *video_enc;
00474 int file_size, i;
00475
00476 video_enc = NULL;
00477 for(i=0;i<s->nb_streams;i++) {
00478 enc = s->streams[i]->codec;
00479 if (enc->codec_type == AVMEDIA_TYPE_VIDEO)
00480 video_enc = enc;
00481 else
00482 av_fifo_free(swf->audio_fifo);
00483 }
00484
00485 put_swf_tag(s, TAG_END);
00486 put_swf_end_tag(s);
00487
00488 avio_flush(s->pb);
00489
00490
00491 if (s->pb->seekable && video_enc) {
00492 file_size = avio_tell(pb);
00493 avio_seek(pb, 4, SEEK_SET);
00494 avio_wl32(pb, file_size);
00495 avio_seek(pb, swf->duration_pos, SEEK_SET);
00496 avio_wl16(pb, swf->video_frame_number);
00497 if (swf->vframes_pos) {
00498 avio_seek(pb, swf->vframes_pos, SEEK_SET);
00499 avio_wl16(pb, swf->video_frame_number);
00500 }
00501 avio_seek(pb, file_size, SEEK_SET);
00502 }
00503 return 0;
00504 }
00505
00506 #if CONFIG_SWF_MUXER
00507 AVOutputFormat ff_swf_muxer = {
00508 .name = "swf",
00509 .long_name = NULL_IF_CONFIG_SMALL("Flash format"),
00510 .mime_type = "application/x-shockwave-flash",
00511 .extensions = "swf",
00512 .priv_data_size = sizeof(SWFContext),
00513 .audio_codec = CODEC_ID_MP3,
00514 .video_codec = CODEC_ID_FLV1,
00515 .write_header = swf_write_header,
00516 .write_packet = swf_write_packet,
00517 .write_trailer = swf_write_trailer,
00518 .flags = AVFMT_TS_NONSTRICT,
00519 };
00520 #endif
00521 #if CONFIG_AVM2_MUXER
00522 AVOutputFormat ff_avm2_muxer = {
00523 .name = "avm2",
00524 .long_name = NULL_IF_CONFIG_SMALL("Flash 9 (AVM2) format"),
00525 .mime_type = "application/x-shockwave-flash",
00526 .priv_data_size = sizeof(SWFContext),
00527 .audio_codec = CODEC_ID_MP3,
00528 .video_codec = CODEC_ID_FLV1,
00529 .write_header = swf_write_header,
00530 .write_packet = swf_write_packet,
00531 .write_trailer = swf_write_trailer,
00532 .flags = AVFMT_TS_NONSTRICT,
00533 };
00534 #endif