00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "movenc.h"
00025 #include "avformat.h"
00026 #include "avio_internal.h"
00027 #include "riff.h"
00028 #include "avio.h"
00029 #include "isom.h"
00030 #include "avc.h"
00031 #include "libavcodec/get_bits.h"
00032 #include "libavcodec/put_bits.h"
00033 #include "libavcodec/vc1.h"
00034 #include "internal.h"
00035 #include "libavutil/avstring.h"
00036 #include "libavutil/intfloat.h"
00037 #include "libavutil/mathematics.h"
00038 #include "libavutil/opt.h"
00039 #include "libavutil/dict.h"
00040 #include "rtpenc.h"
00041 #include "mov_chan.h"
00042
00043 #undef NDEBUG
00044 #include <assert.h>
00045
00046 static const AVOption options[] = {
00047 { "movflags", "MOV muxer flags", offsetof(MOVMuxContext, flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
00048 { "rtphint", "Add RTP hint tracks", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_RTP_HINT}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
00049 { "moov_size", "maximum moov size so it can be placed at the begin", offsetof(MOVMuxContext, reserved_moov_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, 0 },
00050 { "empty_moov", "Make the initial moov atom empty (not supported by QuickTime)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_EMPTY_MOOV}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
00051 { "frag_keyframe", "Fragment at video keyframes", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_FRAG_KEYFRAME}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
00052 { "separate_moof", "Write separate moof/mdat atoms for each track", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_SEPARATE_MOOF}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
00053 { "frag_custom", "Flush fragments on caller requests", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_FRAG_CUSTOM}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
00054 { "isml", "Create a live smooth streaming feed (for pushing to a publishing point)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_ISML}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
00055 { "faststart", "Run a second pass to put the moov at the beginning of the file", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_FASTSTART}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
00056 FF_RTP_FLAG_OPTS(MOVMuxContext, rtp_flags),
00057 { "skip_iods", "Skip writing iods atom.", offsetof(MOVMuxContext, iods_skip), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
00058 { "iods_audio_profile", "iods audio profile atom.", offsetof(MOVMuxContext, iods_audio_profile), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 255, AV_OPT_FLAG_ENCODING_PARAM},
00059 { "iods_video_profile", "iods video profile atom.", offsetof(MOVMuxContext, iods_video_profile), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 255, AV_OPT_FLAG_ENCODING_PARAM},
00060 { "frag_duration", "Maximum fragment duration", offsetof(MOVMuxContext, max_fragment_duration), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
00061 { "min_frag_duration", "Minimum fragment duration", offsetof(MOVMuxContext, min_fragment_duration), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
00062 { "frag_size", "Maximum fragment size", offsetof(MOVMuxContext, max_fragment_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
00063 { "ism_lookahead", "Number of lookahead entries for ISM files", offsetof(MOVMuxContext, ism_lookahead), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
00064 { "use_editlist", "use edit list", offsetof(MOVMuxContext, use_editlist), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM},
00065 { NULL },
00066 };
00067
00068 #define MOV_CLASS(flavor)\
00069 static const AVClass flavor ## _muxer_class = {\
00070 .class_name = #flavor " muxer",\
00071 .item_name = av_default_item_name,\
00072 .option = options,\
00073 .version = LIBAVUTIL_VERSION_INT,\
00074 };
00075
00076
00077 static int64_t update_size(AVIOContext *pb, int64_t pos)
00078 {
00079 int64_t curpos = avio_tell(pb);
00080 avio_seek(pb, pos, SEEK_SET);
00081 avio_wb32(pb, curpos - pos);
00082 avio_seek(pb, curpos, SEEK_SET);
00083
00084 return curpos - pos;
00085 }
00086
00087 static int supports_edts(MOVMuxContext *mov)
00088 {
00089
00090 return (mov->use_editlist<0 && !(mov->flags & FF_MOV_FLAG_FRAGMENT)) || mov->use_editlist>0;
00091 }
00092
00093 static int is_co64_required(const MOVTrack *track)
00094 {
00095 int i;
00096
00097 for (i = 0; i < track->entry; i++) {
00098 if (!track->cluster[i].chunkNum)
00099 continue;
00100 if (track->cluster[i].pos + track->data_offset > UINT32_MAX)
00101 return 1;
00102 }
00103 return 0;
00104 }
00105
00106
00107 static int mov_write_stco_tag(AVIOContext *pb, MOVTrack *track)
00108 {
00109 int i;
00110 int mode64 = is_co64_required(track);
00111 int64_t pos = avio_tell(pb);
00112 avio_wb32(pb, 0);
00113 if (mode64)
00114 ffio_wfourcc(pb, "co64");
00115 else
00116 ffio_wfourcc(pb, "stco");
00117 avio_wb32(pb, 0);
00118 avio_wb32(pb, track->chunkCount);
00119 for (i=0; i<track->entry; i++) {
00120 if(!track->cluster[i].chunkNum)
00121 continue;
00122 if(mode64 == 1)
00123 avio_wb64(pb, track->cluster[i].pos + track->data_offset);
00124 else
00125 avio_wb32(pb, track->cluster[i].pos + track->data_offset);
00126 }
00127 return update_size(pb, pos);
00128 }
00129
00130
00131 static int mov_write_stsz_tag(AVIOContext *pb, MOVTrack *track)
00132 {
00133 int equalChunks = 1;
00134 int i, j, entries = 0, tst = -1, oldtst = -1;
00135
00136 int64_t pos = avio_tell(pb);
00137 avio_wb32(pb, 0);
00138 ffio_wfourcc(pb, "stsz");
00139 avio_wb32(pb, 0);
00140
00141 for (i=0; i<track->entry; i++) {
00142 tst = track->cluster[i].size/track->cluster[i].entries;
00143 if(oldtst != -1 && tst != oldtst) {
00144 equalChunks = 0;
00145 }
00146 oldtst = tst;
00147 entries += track->cluster[i].entries;
00148 }
00149 if (equalChunks && track->entry) {
00150 int sSize = track->entry ? track->cluster[0].size/track->cluster[0].entries : 0;
00151 sSize = FFMAX(1, sSize);
00152 avio_wb32(pb, sSize);
00153 avio_wb32(pb, entries);
00154 }
00155 else {
00156 avio_wb32(pb, 0);
00157 avio_wb32(pb, entries);
00158 for (i=0; i<track->entry; i++) {
00159 for (j=0; j<track->cluster[i].entries; j++) {
00160 avio_wb32(pb, track->cluster[i].size /
00161 track->cluster[i].entries);
00162 }
00163 }
00164 }
00165 return update_size(pb, pos);
00166 }
00167
00168
00169 static int mov_write_stsc_tag(AVIOContext *pb, MOVTrack *track)
00170 {
00171 int index = 0, oldval = -1, i;
00172 int64_t entryPos, curpos;
00173
00174 int64_t pos = avio_tell(pb);
00175 avio_wb32(pb, 0);
00176 ffio_wfourcc(pb, "stsc");
00177 avio_wb32(pb, 0);
00178 entryPos = avio_tell(pb);
00179 avio_wb32(pb, track->chunkCount);
00180 for (i=0; i<track->entry; i++) {
00181 if (oldval != track->cluster[i].samples_in_chunk && track->cluster[i].chunkNum)
00182 {
00183 avio_wb32(pb, track->cluster[i].chunkNum);
00184 avio_wb32(pb, track->cluster[i].samples_in_chunk);
00185 avio_wb32(pb, 0x1);
00186 oldval = track->cluster[i].samples_in_chunk;
00187 index++;
00188 }
00189 }
00190 curpos = avio_tell(pb);
00191 avio_seek(pb, entryPos, SEEK_SET);
00192 avio_wb32(pb, index);
00193 avio_seek(pb, curpos, SEEK_SET);
00194
00195 return update_size(pb, pos);
00196 }
00197
00198
00199 static int mov_write_stss_tag(AVIOContext *pb, MOVTrack *track, uint32_t flag)
00200 {
00201 int64_t curpos, entryPos;
00202 int i, index = 0;
00203 int64_t pos = avio_tell(pb);
00204 avio_wb32(pb, 0);
00205 ffio_wfourcc(pb, flag == MOV_SYNC_SAMPLE ? "stss" : "stps");
00206 avio_wb32(pb, 0);
00207 entryPos = avio_tell(pb);
00208 avio_wb32(pb, track->entry);
00209 for (i=0; i<track->entry; i++) {
00210 if (track->cluster[i].flags & flag) {
00211 avio_wb32(pb, i+1);
00212 index++;
00213 }
00214 }
00215 curpos = avio_tell(pb);
00216 avio_seek(pb, entryPos, SEEK_SET);
00217 avio_wb32(pb, index);
00218 avio_seek(pb, curpos, SEEK_SET);
00219 return update_size(pb, pos);
00220 }
00221
00222 static int mov_write_amr_tag(AVIOContext *pb, MOVTrack *track)
00223 {
00224 avio_wb32(pb, 0x11);
00225 if (track->mode == MODE_MOV) ffio_wfourcc(pb, "samr");
00226 else ffio_wfourcc(pb, "damr");
00227 ffio_wfourcc(pb, "FFMP");
00228 avio_w8(pb, 0);
00229
00230 avio_wb16(pb, 0x81FF);
00231 avio_w8(pb, 0x00);
00232 avio_w8(pb, 0x01);
00233 return 0x11;
00234 }
00235
00236 static int mov_write_ac3_tag(AVIOContext *pb, MOVTrack *track)
00237 {
00238 GetBitContext gbc;
00239 PutBitContext pbc;
00240 uint8_t buf[3];
00241 int fscod, bsid, bsmod, acmod, lfeon, frmsizecod;
00242
00243 if (track->vos_len < 7)
00244 return -1;
00245
00246 avio_wb32(pb, 11);
00247 ffio_wfourcc(pb, "dac3");
00248
00249 init_get_bits(&gbc, track->vos_data + 4, (track->vos_len - 4) * 8);
00250 fscod = get_bits(&gbc, 2);
00251 frmsizecod = get_bits(&gbc, 6);
00252 bsid = get_bits(&gbc, 5);
00253 bsmod = get_bits(&gbc, 3);
00254 acmod = get_bits(&gbc, 3);
00255 if (acmod == 2) {
00256 skip_bits(&gbc, 2);
00257 } else {
00258 if ((acmod & 1) && acmod != 1)
00259 skip_bits(&gbc, 2);
00260 if (acmod & 4)
00261 skip_bits(&gbc, 2);
00262 }
00263 lfeon = get_bits1(&gbc);
00264
00265 init_put_bits(&pbc, buf, sizeof(buf));
00266 put_bits(&pbc, 2, fscod);
00267 put_bits(&pbc, 5, bsid);
00268 put_bits(&pbc, 3, bsmod);
00269 put_bits(&pbc, 3, acmod);
00270 put_bits(&pbc, 1, lfeon);
00271 put_bits(&pbc, 5, frmsizecod>>1);
00272 put_bits(&pbc, 5, 0);
00273
00274 flush_put_bits(&pbc);
00275 avio_write(pb, buf, sizeof(buf));
00276
00277 return 11;
00278 }
00279
00284 static int mov_write_extradata_tag(AVIOContext *pb, MOVTrack *track)
00285 {
00286 avio_write(pb, track->enc->extradata, track->enc->extradata_size);
00287 return track->enc->extradata_size;
00288 }
00289
00290 static int mov_write_enda_tag(AVIOContext *pb)
00291 {
00292 avio_wb32(pb, 10);
00293 ffio_wfourcc(pb, "enda");
00294 avio_wb16(pb, 1);
00295 return 10;
00296 }
00297
00298 static int mov_write_enda_tag_be(AVIOContext *pb)
00299 {
00300 avio_wb32(pb, 10);
00301 ffio_wfourcc(pb, "enda");
00302 avio_wb16(pb, 0);
00303 return 10;
00304 }
00305
00306 static void put_descr(AVIOContext *pb, int tag, unsigned int size)
00307 {
00308 int i = 3;
00309 avio_w8(pb, tag);
00310 for(; i>0; i--)
00311 avio_w8(pb, (size>>(7*i)) | 0x80);
00312 avio_w8(pb, size & 0x7F);
00313 }
00314
00315 static unsigned compute_avg_bitrate(MOVTrack *track)
00316 {
00317 uint64_t size = 0;
00318 int i;
00319 if (!track->track_duration)
00320 return 0;
00321 for (i = 0; i < track->entry; i++)
00322 size += track->cluster[i].size;
00323 return size * 8 * track->timescale / track->track_duration;
00324 }
00325
00326 static int mov_write_esds_tag(AVIOContext *pb, MOVTrack *track)
00327 {
00328 int64_t pos = avio_tell(pb);
00329 int decoder_specific_info_len = track->vos_len ? 5 + track->vos_len : 0;
00330 unsigned avg_bitrate;
00331
00332 avio_wb32(pb, 0);
00333 ffio_wfourcc(pb, "esds");
00334 avio_wb32(pb, 0);
00335
00336
00337 put_descr(pb, 0x03, 3 + 5+13 + decoder_specific_info_len + 5+1);
00338 avio_wb16(pb, track->track_id);
00339 avio_w8(pb, 0x00);
00340
00341
00342 put_descr(pb, 0x04, 13 + decoder_specific_info_len);
00343
00344
00345 if ((track->enc->codec_id == AV_CODEC_ID_MP2 ||
00346 track->enc->codec_id == AV_CODEC_ID_MP3) &&
00347 track->enc->sample_rate > 24000)
00348 avio_w8(pb, 0x6B);
00349 else
00350 avio_w8(pb, ff_codec_get_tag(ff_mp4_obj_type, track->enc->codec_id));
00351
00352
00353
00354 if(track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
00355 avio_w8(pb, 0x15);
00356 else
00357 avio_w8(pb, 0x11);
00358
00359 avio_w8(pb, track->enc->rc_buffer_size>>(3+16));
00360 avio_wb16(pb, (track->enc->rc_buffer_size>>3)&0xFFFF);
00361
00362 avg_bitrate = compute_avg_bitrate(track);
00363
00364 avio_wb32(pb, FFMAX3(track->enc->bit_rate, track->enc->rc_max_rate, avg_bitrate));
00365 avio_wb32(pb, avg_bitrate);
00366
00367 if (track->vos_len) {
00368
00369 put_descr(pb, 0x05, track->vos_len);
00370 avio_write(pb, track->vos_data, track->vos_len);
00371 }
00372
00373
00374 put_descr(pb, 0x06, 1);
00375 avio_w8(pb, 0x02);
00376 return update_size(pb, pos);
00377 }
00378
00379 static int mov_pcm_le_gt16(enum AVCodecID codec_id)
00380 {
00381 return codec_id == AV_CODEC_ID_PCM_S24LE ||
00382 codec_id == AV_CODEC_ID_PCM_S32LE ||
00383 codec_id == AV_CODEC_ID_PCM_F32LE ||
00384 codec_id == AV_CODEC_ID_PCM_F64LE;
00385 }
00386
00387 static int mov_pcm_be_gt16(enum AVCodecID codec_id)
00388 {
00389 return codec_id == AV_CODEC_ID_PCM_S24BE ||
00390 codec_id == AV_CODEC_ID_PCM_S32BE ||
00391 codec_id == AV_CODEC_ID_PCM_F32BE ||
00392 codec_id == AV_CODEC_ID_PCM_F64BE;
00393 }
00394
00395 static int mov_write_ms_tag(AVIOContext *pb, MOVTrack *track)
00396 {
00397 int64_t pos = avio_tell(pb);
00398 avio_wb32(pb, 0);
00399 avio_wl32(pb, track->tag);
00400 track->enc->codec_tag = av_bswap16(track->tag >> 16);
00401 ff_put_wav_header(pb, track->enc);
00402 return update_size(pb, pos);
00403 }
00404
00405 static int mov_write_wfex_tag(AVIOContext *pb, MOVTrack *track)
00406 {
00407 int64_t pos = avio_tell(pb);
00408 avio_wb32(pb, 0);
00409 ffio_wfourcc(pb, "wfex");
00410 ff_put_wav_header(pb, track->enc);
00411 return update_size(pb, pos);
00412 }
00413
00414 static int mov_write_chan_tag(AVIOContext *pb, MOVTrack *track)
00415 {
00416 uint32_t layout_tag, bitmap;
00417 int64_t pos = avio_tell(pb);
00418
00419 layout_tag = ff_mov_get_channel_layout_tag(track->enc->codec_id,
00420 track->enc->channel_layout,
00421 &bitmap);
00422 if (!layout_tag) {
00423 av_log(track->enc, AV_LOG_WARNING, "not writing 'chan' tag due to "
00424 "lack of channel information\n");
00425 return 0;
00426 }
00427
00428 avio_wb32(pb, 0);
00429 ffio_wfourcc(pb, "chan");
00430 avio_w8(pb, 0);
00431 avio_wb24(pb, 0);
00432 avio_wb32(pb, layout_tag);
00433 avio_wb32(pb, bitmap);
00434 avio_wb32(pb, 0);
00435
00436 return update_size(pb, pos);
00437 }
00438
00439 static int mov_write_wave_tag(AVIOContext *pb, MOVTrack *track)
00440 {
00441 int64_t pos = avio_tell(pb);
00442
00443 avio_wb32(pb, 0);
00444 ffio_wfourcc(pb, "wave");
00445
00446 if (track->enc->codec_id != AV_CODEC_ID_QDM2) {
00447 avio_wb32(pb, 12);
00448 ffio_wfourcc(pb, "frma");
00449 avio_wl32(pb, track->tag);
00450 }
00451
00452 if (track->enc->codec_id == AV_CODEC_ID_AAC) {
00453
00454 avio_wb32(pb, 12);
00455 ffio_wfourcc(pb, "mp4a");
00456 avio_wb32(pb, 0);
00457 mov_write_esds_tag(pb, track);
00458 } else if (mov_pcm_le_gt16(track->enc->codec_id)) {
00459 mov_write_enda_tag(pb);
00460 } else if (mov_pcm_be_gt16(track->enc->codec_id)) {
00461 mov_write_enda_tag_be(pb);
00462 } else if (track->enc->codec_id == AV_CODEC_ID_AMR_NB) {
00463 mov_write_amr_tag(pb, track);
00464 } else if (track->enc->codec_id == AV_CODEC_ID_AC3) {
00465 mov_write_ac3_tag(pb, track);
00466 } else if (track->enc->codec_id == AV_CODEC_ID_ALAC ||
00467 track->enc->codec_id == AV_CODEC_ID_QDM2) {
00468 mov_write_extradata_tag(pb, track);
00469 } else if (track->enc->codec_id == AV_CODEC_ID_ADPCM_MS ||
00470 track->enc->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) {
00471 mov_write_ms_tag(pb, track);
00472 }
00473
00474 avio_wb32(pb, 8);
00475 avio_wb32(pb, 0);
00476
00477 return update_size(pb, pos);
00478 }
00479
00480 static int mov_write_dvc1_structs(MOVTrack *track, uint8_t *buf)
00481 {
00482 uint8_t *unescaped;
00483 const uint8_t *start, *next, *end = track->vos_data + track->vos_len;
00484 int unescaped_size, seq_found = 0;
00485 int level = 0, interlace = 0;
00486 int packet_seq = track->vc1_info.packet_seq;
00487 int packet_entry = track->vc1_info.packet_entry;
00488 int slices = track->vc1_info.slices;
00489 PutBitContext pbc;
00490
00491 if (track->start_dts == AV_NOPTS_VALUE) {
00492
00493
00494
00495 packet_seq = packet_entry = 1;
00496 }
00497
00498 unescaped = av_mallocz(track->vos_len + FF_INPUT_BUFFER_PADDING_SIZE);
00499 if (!unescaped)
00500 return AVERROR(ENOMEM);
00501 start = find_next_marker(track->vos_data, end);
00502 for (next = start; next < end; start = next) {
00503 GetBitContext gb;
00504 int size;
00505 next = find_next_marker(start + 4, end);
00506 size = next - start - 4;
00507 if (size <= 0)
00508 continue;
00509 unescaped_size = vc1_unescape_buffer(start + 4, size, unescaped);
00510 init_get_bits(&gb, unescaped, 8 * unescaped_size);
00511 if (AV_RB32(start) == VC1_CODE_SEQHDR) {
00512 int profile = get_bits(&gb, 2);
00513 if (profile != PROFILE_ADVANCED) {
00514 av_free(unescaped);
00515 return AVERROR(ENOSYS);
00516 }
00517 seq_found = 1;
00518 level = get_bits(&gb, 3);
00519
00520
00521 skip_bits_long(&gb, 2 + 3 + 5 + 1 + 2*12);
00522 skip_bits(&gb, 1);
00523 interlace = get_bits1(&gb);
00524 skip_bits(&gb, 4);
00525 }
00526 }
00527 if (!seq_found) {
00528 av_free(unescaped);
00529 return AVERROR(ENOSYS);
00530 }
00531
00532 init_put_bits(&pbc, buf, 7);
00533
00534 put_bits(&pbc, 4, 12);
00535 put_bits(&pbc, 3, level);
00536 put_bits(&pbc, 1, 0);
00537
00538 put_bits(&pbc, 3, level);
00539 put_bits(&pbc, 1, 0);
00540 put_bits(&pbc, 6, 0);
00541 put_bits(&pbc, 1, !interlace);
00542 put_bits(&pbc, 1, !packet_seq);
00543 put_bits(&pbc, 1, !packet_entry);
00544 put_bits(&pbc, 1, !slices);
00545 put_bits(&pbc, 1, 0);
00546 put_bits(&pbc, 1, 0);
00547 put_bits32(&pbc, track->enc->time_base.den);
00548 flush_put_bits(&pbc);
00549
00550 av_free(unescaped);
00551
00552 return 0;
00553 }
00554
00555 static int mov_write_dvc1_tag(AVIOContext *pb, MOVTrack *track)
00556 {
00557 uint8_t buf[7] = { 0 };
00558 int ret;
00559
00560 if ((ret = mov_write_dvc1_structs(track, buf)) < 0)
00561 return ret;
00562
00563 avio_wb32(pb, track->vos_len + 8 + sizeof(buf));
00564 ffio_wfourcc(pb, "dvc1");
00565 track->vc1_info.struct_offset = avio_tell(pb);
00566 avio_write(pb, buf, sizeof(buf));
00567 avio_write(pb, track->vos_data, track->vos_len);
00568
00569 return 0;
00570 }
00571
00572 static int mov_write_glbl_tag(AVIOContext *pb, MOVTrack *track)
00573 {
00574 avio_wb32(pb, track->vos_len + 8);
00575 ffio_wfourcc(pb, "glbl");
00576 avio_write(pb, track->vos_data, track->vos_len);
00577 return 8 + track->vos_len;
00578 }
00579
00584 static int mov_get_lpcm_flags(enum AVCodecID codec_id)
00585 {
00586 switch (codec_id) {
00587 case AV_CODEC_ID_PCM_F32BE:
00588 case AV_CODEC_ID_PCM_F64BE:
00589 return 11;
00590 case AV_CODEC_ID_PCM_F32LE:
00591 case AV_CODEC_ID_PCM_F64LE:
00592 return 9;
00593 case AV_CODEC_ID_PCM_U8:
00594 return 10;
00595 case AV_CODEC_ID_PCM_S16BE:
00596 case AV_CODEC_ID_PCM_S24BE:
00597 case AV_CODEC_ID_PCM_S32BE:
00598 return 14;
00599 case AV_CODEC_ID_PCM_S8:
00600 case AV_CODEC_ID_PCM_S16LE:
00601 case AV_CODEC_ID_PCM_S24LE:
00602 case AV_CODEC_ID_PCM_S32LE:
00603 return 12;
00604 default:
00605 return 0;
00606 }
00607 }
00608
00609 static int get_cluster_duration(MOVTrack *track, int cluster_idx)
00610 {
00611 int64_t next_dts;
00612
00613 if (cluster_idx >= track->entry)
00614 return 0;
00615
00616 if (cluster_idx + 1 == track->entry)
00617 next_dts = track->track_duration + track->start_dts;
00618 else
00619 next_dts = track->cluster[cluster_idx + 1].dts;
00620
00621 return next_dts - track->cluster[cluster_idx].dts;
00622 }
00623
00624 static int get_samples_per_packet(MOVTrack *track)
00625 {
00626 int i, first_duration;
00627
00628
00629
00630
00631 if (!track->audio_vbr)
00632 return 1;
00633
00634
00635 if (!track->entry)
00636 return 0;
00637 first_duration = get_cluster_duration(track, 0);
00638 for (i = 1; i < track->entry; i++) {
00639 if (get_cluster_duration(track, i) != first_duration)
00640 return 0;
00641 }
00642 return first_duration;
00643 }
00644
00645 static int mov_write_audio_tag(AVIOContext *pb, MOVTrack *track)
00646 {
00647 int64_t pos = avio_tell(pb);
00648 int version = 0;
00649 uint32_t tag = track->tag;
00650
00651 if (track->mode == MODE_MOV) {
00652 if (track->timescale > UINT16_MAX) {
00653 if (mov_get_lpcm_flags(track->enc->codec_id))
00654 tag = AV_RL32("lpcm");
00655 version = 2;
00656 } else if (track->audio_vbr || mov_pcm_le_gt16(track->enc->codec_id) ||
00657 mov_pcm_be_gt16(track->enc->codec_id) ||
00658 track->enc->codec_id == AV_CODEC_ID_ADPCM_MS ||
00659 track->enc->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV ||
00660 track->enc->codec_id == AV_CODEC_ID_QDM2) {
00661 version = 1;
00662 }
00663 }
00664
00665 avio_wb32(pb, 0);
00666 avio_wl32(pb, tag);
00667 avio_wb32(pb, 0);
00668 avio_wb16(pb, 0);
00669 avio_wb16(pb, 1);
00670
00671
00672 avio_wb16(pb, version);
00673 avio_wb16(pb, 0);
00674 avio_wb32(pb, 0);
00675
00676 if (version == 2) {
00677 avio_wb16(pb, 3);
00678 avio_wb16(pb, 16);
00679 avio_wb16(pb, 0xfffe);
00680 avio_wb16(pb, 0);
00681 avio_wb32(pb, 0x00010000);
00682 avio_wb32(pb, 72);
00683 avio_wb64(pb, av_double2int(track->enc->sample_rate));
00684 avio_wb32(pb, track->enc->channels);
00685 avio_wb32(pb, 0x7F000000);
00686 avio_wb32(pb, av_get_bits_per_sample(track->enc->codec_id));
00687 avio_wb32(pb, mov_get_lpcm_flags(track->enc->codec_id));
00688 avio_wb32(pb, track->sample_size);
00689 avio_wb32(pb, get_samples_per_packet(track));
00690 } else {
00691 if (track->mode == MODE_MOV) {
00692 avio_wb16(pb, track->enc->channels);
00693 if (track->enc->codec_id == AV_CODEC_ID_PCM_U8 ||
00694 track->enc->codec_id == AV_CODEC_ID_PCM_S8)
00695 avio_wb16(pb, 8);
00696 else
00697 avio_wb16(pb, 16);
00698 avio_wb16(pb, track->audio_vbr ? -2 : 0);
00699 } else {
00700 avio_wb16(pb, 2);
00701 avio_wb16(pb, 16);
00702 avio_wb16(pb, 0);
00703 }
00704
00705 avio_wb16(pb, 0);
00706 avio_wb16(pb, track->enc->sample_rate <= UINT16_MAX ?
00707 track->enc->sample_rate : 0);
00708 avio_wb16(pb, 0);
00709 }
00710
00711 if(version == 1) {
00712 if (mov_pcm_le_gt16(track->enc->codec_id) ||
00713 mov_pcm_be_gt16(track->enc->codec_id))
00714 avio_wb32(pb, 1);
00715 else
00716 avio_wb32(pb, track->enc->frame_size);
00717 avio_wb32(pb, track->sample_size / track->enc->channels);
00718 avio_wb32(pb, track->sample_size);
00719 avio_wb32(pb, 2);
00720 }
00721
00722 if(track->mode == MODE_MOV &&
00723 (track->enc->codec_id == AV_CODEC_ID_AAC ||
00724 track->enc->codec_id == AV_CODEC_ID_AC3 ||
00725 track->enc->codec_id == AV_CODEC_ID_AMR_NB ||
00726 track->enc->codec_id == AV_CODEC_ID_ALAC ||
00727 track->enc->codec_id == AV_CODEC_ID_ADPCM_MS ||
00728 track->enc->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV ||
00729 track->enc->codec_id == AV_CODEC_ID_QDM2 ||
00730 (mov_pcm_le_gt16(track->enc->codec_id) && version==1) ||
00731 (mov_pcm_be_gt16(track->enc->codec_id) && version==1)))
00732 mov_write_wave_tag(pb, track);
00733 else if(track->tag == MKTAG('m','p','4','a'))
00734 mov_write_esds_tag(pb, track);
00735 else if(track->enc->codec_id == AV_CODEC_ID_AMR_NB)
00736 mov_write_amr_tag(pb, track);
00737 else if(track->enc->codec_id == AV_CODEC_ID_AC3)
00738 mov_write_ac3_tag(pb, track);
00739 else if(track->enc->codec_id == AV_CODEC_ID_ALAC)
00740 mov_write_extradata_tag(pb, track);
00741 else if (track->enc->codec_id == AV_CODEC_ID_WMAPRO)
00742 mov_write_wfex_tag(pb, track);
00743 else if (track->vos_len > 0)
00744 mov_write_glbl_tag(pb, track);
00745
00746 if (track->mode == MODE_MOV && track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
00747 mov_write_chan_tag(pb, track);
00748
00749 return update_size(pb, pos);
00750 }
00751
00752 static int mov_write_d263_tag(AVIOContext *pb)
00753 {
00754 avio_wb32(pb, 0xf);
00755 ffio_wfourcc(pb, "d263");
00756 ffio_wfourcc(pb, "FFMP");
00757 avio_w8(pb, 0);
00758
00759 avio_w8(pb, 0xa);
00760 avio_w8(pb, 0);
00761 return 0xf;
00762 }
00763
00764 static int mov_write_avcc_tag(AVIOContext *pb, MOVTrack *track)
00765 {
00766 int64_t pos = avio_tell(pb);
00767
00768 avio_wb32(pb, 0);
00769 ffio_wfourcc(pb, "avcC");
00770 ff_isom_write_avcc(pb, track->vos_data, track->vos_len);
00771 return update_size(pb, pos);
00772 }
00773
00774
00775 static int mov_write_avid_tag(AVIOContext *pb, MOVTrack *track)
00776 {
00777 int i;
00778 avio_wb32(pb, 24);
00779 ffio_wfourcc(pb, "ACLR");
00780 ffio_wfourcc(pb, "ACLR");
00781 ffio_wfourcc(pb, "0001");
00782 avio_wb32(pb, 2);
00783 avio_wb32(pb, 0);
00784
00785 avio_wb32(pb, 24);
00786 ffio_wfourcc(pb, "APRG");
00787 ffio_wfourcc(pb, "APRG");
00788 ffio_wfourcc(pb, "0001");
00789 avio_wb32(pb, 1);
00790 avio_wb32(pb, 0);
00791
00792 avio_wb32(pb, 120);
00793 ffio_wfourcc(pb, "ARES");
00794 ffio_wfourcc(pb, "ARES");
00795 ffio_wfourcc(pb, "0001");
00796 avio_wb32(pb, AV_RB32(track->vos_data + 0x28));
00797 avio_wb32(pb, track->enc->width);
00798
00799 if (track->vos_data[5] & 2) {
00800 avio_wb32(pb, track->enc->height/2);
00801 avio_wb32(pb, 2);
00802 avio_wb32(pb, 0);
00803 avio_wb32(pb, 4);
00804 } else {
00805 avio_wb32(pb, track->enc->height);
00806 avio_wb32(pb, 1);
00807 avio_wb32(pb, 0);
00808 if (track->enc->height == 1080)
00809 avio_wb32(pb, 5);
00810 else
00811 avio_wb32(pb, 6);
00812 }
00813
00814 for (i = 0; i < 10; i++)
00815 avio_wb64(pb, 0);
00816
00817
00818 avio_wb32(pb, 0);
00819 return 0;
00820 }
00821
00822 static int mp4_get_codec_tag(AVFormatContext *s, MOVTrack *track)
00823 {
00824 int tag = track->enc->codec_tag;
00825
00826 if (!ff_codec_get_tag(ff_mp4_obj_type, track->enc->codec_id))
00827 return 0;
00828
00829 if (track->enc->codec_id == AV_CODEC_ID_H264) tag = MKTAG('a','v','c','1');
00830 else if (track->enc->codec_id == AV_CODEC_ID_AC3) tag = MKTAG('a','c','-','3');
00831 else if (track->enc->codec_id == AV_CODEC_ID_DIRAC) tag = MKTAG('d','r','a','c');
00832 else if (track->enc->codec_id == AV_CODEC_ID_MOV_TEXT) tag = MKTAG('t','x','3','g');
00833 else if (track->enc->codec_id == AV_CODEC_ID_VC1) tag = MKTAG('v','c','-','1');
00834 else if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) tag = MKTAG('m','p','4','v');
00835 else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) tag = MKTAG('m','p','4','a');
00836
00837 return tag;
00838 }
00839
00840 static const AVCodecTag codec_ipod_tags[] = {
00841 { AV_CODEC_ID_H264, MKTAG('a','v','c','1') },
00842 { AV_CODEC_ID_MPEG4, MKTAG('m','p','4','v') },
00843 { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') },
00844 { AV_CODEC_ID_ALAC, MKTAG('a','l','a','c') },
00845 { AV_CODEC_ID_AC3, MKTAG('a','c','-','3') },
00846 { AV_CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') },
00847 { AV_CODEC_ID_MOV_TEXT, MKTAG('t','e','x','t') },
00848 { AV_CODEC_ID_NONE, 0 },
00849 };
00850
00851 static int ipod_get_codec_tag(AVFormatContext *s, MOVTrack *track)
00852 {
00853 int tag = track->enc->codec_tag;
00854
00855
00856 if (!(track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE &&
00857 (tag == MKTAG('t','x','3','g') ||
00858 tag == MKTAG('t','e','x','t'))))
00859 tag = ff_codec_get_tag(codec_ipod_tags, track->enc->codec_id);
00860
00861 if (!av_match_ext(s->filename, "m4a") && !av_match_ext(s->filename, "m4v"))
00862 av_log(s, AV_LOG_WARNING, "Warning, extension is not .m4a nor .m4v "
00863 "Quicktime/Ipod might not play the file\n");
00864
00865 return tag;
00866 }
00867
00868 static int mov_get_dv_codec_tag(AVFormatContext *s, MOVTrack *track)
00869 {
00870 int tag;
00871
00872 if (track->enc->width == 720) {
00873 if (track->enc->height == 480) {
00874 if (track->enc->pix_fmt == AV_PIX_FMT_YUV422P) tag = MKTAG('d','v','5','n');
00875 else tag = MKTAG('d','v','c',' ');
00876 }else if (track->enc->pix_fmt == AV_PIX_FMT_YUV422P) tag = MKTAG('d','v','5','p');
00877 else if (track->enc->pix_fmt == AV_PIX_FMT_YUV420P) tag = MKTAG('d','v','c','p');
00878 else tag = MKTAG('d','v','p','p');
00879 } else if (track->enc->height == 720) {
00880 if (track->enc->time_base.den == 50) tag = MKTAG('d','v','h','q');
00881 else tag = MKTAG('d','v','h','p');
00882 } else if (track->enc->height == 1080) {
00883 if (track->enc->time_base.den == 25) tag = MKTAG('d','v','h','5');
00884 else tag = MKTAG('d','v','h','6');
00885 } else {
00886 av_log(s, AV_LOG_ERROR, "unsupported height for dv codec\n");
00887 return 0;
00888 }
00889
00890 return tag;
00891 }
00892
00893 static const struct {
00894 enum AVPixelFormat pix_fmt;
00895 uint32_t tag;
00896 unsigned bps;
00897 } mov_pix_fmt_tags[] = {
00898 { AV_PIX_FMT_YUYV422, MKTAG('y','u','v','2'), 0 },
00899 { AV_PIX_FMT_YUYV422, MKTAG('y','u','v','s'), 0 },
00900 { AV_PIX_FMT_UYVY422, MKTAG('2','v','u','y'), 0 },
00901 { AV_PIX_FMT_RGB555BE,MKTAG('r','a','w',' '), 16 },
00902 { AV_PIX_FMT_RGB555LE,MKTAG('L','5','5','5'), 16 },
00903 { AV_PIX_FMT_RGB565LE,MKTAG('L','5','6','5'), 16 },
00904 { AV_PIX_FMT_RGB565BE,MKTAG('B','5','6','5'), 16 },
00905 { AV_PIX_FMT_GRAY16BE,MKTAG('b','1','6','g'), 16 },
00906 { AV_PIX_FMT_RGB24, MKTAG('r','a','w',' '), 24 },
00907 { AV_PIX_FMT_BGR24, MKTAG('2','4','B','G'), 24 },
00908 { AV_PIX_FMT_ARGB, MKTAG('r','a','w',' '), 32 },
00909 { AV_PIX_FMT_BGRA, MKTAG('B','G','R','A'), 32 },
00910 { AV_PIX_FMT_RGBA, MKTAG('R','G','B','A'), 32 },
00911 { AV_PIX_FMT_ABGR, MKTAG('A','B','G','R'), 32 },
00912 { AV_PIX_FMT_RGB48BE, MKTAG('b','4','8','r'), 48 },
00913 };
00914
00915 static int mov_get_rawvideo_codec_tag(AVFormatContext *s, MOVTrack *track)
00916 {
00917 int tag = track->enc->codec_tag;
00918 int i;
00919
00920 for (i = 0; i < FF_ARRAY_ELEMS(mov_pix_fmt_tags); i++) {
00921 if (track->enc->pix_fmt == mov_pix_fmt_tags[i].pix_fmt) {
00922 tag = mov_pix_fmt_tags[i].tag;
00923 track->enc->bits_per_coded_sample = mov_pix_fmt_tags[i].bps;
00924 if (track->enc->codec_tag == mov_pix_fmt_tags[i].tag)
00925 break;
00926 }
00927 }
00928
00929 return tag;
00930 }
00931
00932 static int mov_get_codec_tag(AVFormatContext *s, MOVTrack *track)
00933 {
00934 int tag = track->enc->codec_tag;
00935
00936 if (!tag || (track->enc->strict_std_compliance >= FF_COMPLIANCE_NORMAL &&
00937 (track->enc->codec_id == AV_CODEC_ID_DVVIDEO ||
00938 track->enc->codec_id == AV_CODEC_ID_RAWVIDEO ||
00939 track->enc->codec_id == AV_CODEC_ID_H263 ||
00940 av_get_bits_per_sample(track->enc->codec_id)))) {
00941 if (track->enc->codec_id == AV_CODEC_ID_DVVIDEO)
00942 tag = mov_get_dv_codec_tag(s, track);
00943 else if (track->enc->codec_id == AV_CODEC_ID_RAWVIDEO)
00944 tag = mov_get_rawvideo_codec_tag(s, track);
00945 else if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) {
00946 tag = ff_codec_get_tag(ff_codec_movvideo_tags, track->enc->codec_id);
00947 if (!tag) {
00948 tag = ff_codec_get_tag(ff_codec_bmp_tags, track->enc->codec_id);
00949 if (tag)
00950 av_log(s, AV_LOG_WARNING, "Using MS style video codec tag, "
00951 "the file may be unplayable!\n");
00952 }
00953 } else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) {
00954 tag = ff_codec_get_tag(ff_codec_movaudio_tags, track->enc->codec_id);
00955 if (!tag) {
00956 int ms_tag = ff_codec_get_tag(ff_codec_wav_tags, track->enc->codec_id);
00957 if (ms_tag) {
00958 tag = MKTAG('m', 's', ((ms_tag >> 8) & 0xff), (ms_tag & 0xff));
00959 av_log(s, AV_LOG_WARNING, "Using MS style audio codec tag, "
00960 "the file may be unplayable!\n");
00961 }
00962 }
00963 } else if (track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE)
00964 tag = ff_codec_get_tag(ff_codec_movsubtitle_tags, track->enc->codec_id);
00965 }
00966
00967 return tag;
00968 }
00969
00970 static const AVCodecTag codec_3gp_tags[] = {
00971 { AV_CODEC_ID_H263, MKTAG('s','2','6','3') },
00972 { AV_CODEC_ID_H264, MKTAG('a','v','c','1') },
00973 { AV_CODEC_ID_MPEG4, MKTAG('m','p','4','v') },
00974 { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') },
00975 { AV_CODEC_ID_AMR_NB, MKTAG('s','a','m','r') },
00976 { AV_CODEC_ID_AMR_WB, MKTAG('s','a','w','b') },
00977 { AV_CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') },
00978 { AV_CODEC_ID_NONE, 0 },
00979 };
00980
00981 static const AVCodecTag codec_f4v_tags[] = {
00982 { AV_CODEC_ID_MP3, MKTAG('.','m','p','3') },
00983 { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') },
00984 { AV_CODEC_ID_H264, MKTAG('a','v','c','1') },
00985 { AV_CODEC_ID_VP6F, MKTAG('V','P','6','F') },
00986 { AV_CODEC_ID_NONE, 0 },
00987 };
00988
00989 static int mov_find_codec_tag(AVFormatContext *s, MOVTrack *track)
00990 {
00991 int tag;
00992
00993 if (track->mode == MODE_MP4 || track->mode == MODE_PSP)
00994 tag = mp4_get_codec_tag(s, track);
00995 else if (track->mode == MODE_ISM) {
00996 tag = mp4_get_codec_tag(s, track);
00997 if (!tag && track->enc->codec_id == AV_CODEC_ID_WMAPRO)
00998 tag = MKTAG('w', 'm', 'a', ' ');
00999 } else if (track->mode == MODE_IPOD)
01000 tag = ipod_get_codec_tag(s, track);
01001 else if (track->mode & MODE_3GP)
01002 tag = ff_codec_get_tag(codec_3gp_tags, track->enc->codec_id);
01003 else if (track->mode & MODE_F4V)
01004 tag = ff_codec_get_tag(codec_f4v_tags, track->enc->codec_id);
01005 else
01006 tag = mov_get_codec_tag(s, track);
01007
01008 return tag;
01009 }
01010
01015 static int mov_write_uuid_tag_ipod(AVIOContext *pb)
01016 {
01017 avio_wb32(pb, 28);
01018 ffio_wfourcc(pb, "uuid");
01019 avio_wb32(pb, 0x6b6840f2);
01020 avio_wb32(pb, 0x5f244fc5);
01021 avio_wb32(pb, 0xba39a51b);
01022 avio_wb32(pb, 0xcf0323f3);
01023 avio_wb32(pb, 0x0);
01024 return 28;
01025 }
01026
01027 static const uint16_t fiel_data[] = {
01028 0x0000, 0x0100, 0x0201, 0x0206, 0x0209, 0x020e
01029 };
01030
01031 static int mov_write_fiel_tag(AVIOContext *pb, MOVTrack *track)
01032 {
01033 unsigned mov_field_order = 0;
01034 if (track->enc->field_order < FF_ARRAY_ELEMS(fiel_data))
01035 mov_field_order = fiel_data[track->enc->field_order];
01036 else
01037 return 0;
01038 avio_wb32(pb, 10);
01039 ffio_wfourcc(pb, "fiel");
01040 avio_wb16(pb, mov_field_order);
01041 return 10;
01042 }
01043
01044 static int mov_write_subtitle_tag(AVIOContext *pb, MOVTrack *track)
01045 {
01046 int64_t pos = avio_tell(pb);
01047 avio_wb32(pb, 0);
01048 avio_wl32(pb, track->tag);
01049 avio_wb32(pb, 0);
01050 avio_wb16(pb, 0);
01051 avio_wb16(pb, 1);
01052
01053 if (track->enc->extradata_size)
01054 avio_write(pb, track->enc->extradata, track->enc->extradata_size);
01055
01056 return update_size(pb, pos);
01057 }
01058
01059 static int mov_write_pasp_tag(AVIOContext *pb, MOVTrack *track)
01060 {
01061 AVRational sar;
01062 av_reduce(&sar.num, &sar.den, track->enc->sample_aspect_ratio.num,
01063 track->enc->sample_aspect_ratio.den, INT_MAX);
01064
01065 avio_wb32(pb, 16);
01066 ffio_wfourcc(pb, "pasp");
01067 avio_wb32(pb, sar.num);
01068 avio_wb32(pb, sar.den);
01069 return 16;
01070 }
01071
01072 static int mov_write_video_tag(AVIOContext *pb, MOVTrack *track)
01073 {
01074 int64_t pos = avio_tell(pb);
01075 char compressor_name[32] = { 0 };
01076
01077 avio_wb32(pb, 0);
01078 avio_wl32(pb, track->tag);
01079 avio_wb32(pb, 0);
01080 avio_wb16(pb, 0);
01081 avio_wb16(pb, 1);
01082
01083 avio_wb16(pb, 0);
01084 avio_wb16(pb, 0);
01085 if (track->mode == MODE_MOV) {
01086 ffio_wfourcc(pb, "FFMP");
01087 if(track->enc->codec_id == AV_CODEC_ID_RAWVIDEO) {
01088 avio_wb32(pb, 0);
01089 avio_wb32(pb, 0x400);
01090 } else {
01091 avio_wb32(pb, 0x200);
01092 avio_wb32(pb, 0x200);
01093 }
01094 } else {
01095 avio_wb32(pb, 0);
01096 avio_wb32(pb, 0);
01097 avio_wb32(pb, 0);
01098 }
01099 avio_wb16(pb, track->enc->width);
01100 avio_wb16(pb, track->height);
01101 avio_wb32(pb, 0x00480000);
01102 avio_wb32(pb, 0x00480000);
01103 avio_wb32(pb, 0);
01104 avio_wb16(pb, 1);
01105
01106
01107 if (track->mode == MODE_MOV && track->enc->codec && track->enc->codec->name)
01108 av_strlcpy(compressor_name,track->enc->codec->name,32);
01109 avio_w8(pb, strlen(compressor_name));
01110 avio_write(pb, compressor_name, 31);
01111
01112 if (track->mode == MODE_MOV && track->enc->bits_per_coded_sample)
01113 avio_wb16(pb, track->enc->bits_per_coded_sample);
01114 else
01115 avio_wb16(pb, 0x18);
01116 avio_wb16(pb, 0xffff);
01117 if(track->tag == MKTAG('m','p','4','v'))
01118 mov_write_esds_tag(pb, track);
01119 else if(track->enc->codec_id == AV_CODEC_ID_H263)
01120 mov_write_d263_tag(pb);
01121 else if(track->enc->codec_id == AV_CODEC_ID_AVUI ||
01122 track->enc->codec_id == AV_CODEC_ID_SVQ3) {
01123 mov_write_extradata_tag(pb, track);
01124 avio_wb32(pb, 0);
01125 } else if(track->enc->codec_id == AV_CODEC_ID_DNXHD)
01126 mov_write_avid_tag(pb, track);
01127 else if(track->enc->codec_id == AV_CODEC_ID_H264) {
01128 mov_write_avcc_tag(pb, track);
01129 if(track->mode == MODE_IPOD)
01130 mov_write_uuid_tag_ipod(pb);
01131 } else if (track->enc->field_order != AV_FIELD_UNKNOWN)
01132 mov_write_fiel_tag(pb, track);
01133 else if (track->enc->codec_id == AV_CODEC_ID_VC1 && track->vos_len > 0)
01134 mov_write_dvc1_tag(pb, track);
01135 else if (track->vos_len > 0)
01136 mov_write_glbl_tag(pb, track);
01137
01138 if (track->enc->sample_aspect_ratio.den && track->enc->sample_aspect_ratio.num &&
01139 track->enc->sample_aspect_ratio.den != track->enc->sample_aspect_ratio.num) {
01140 mov_write_pasp_tag(pb, track);
01141 }
01142
01143 return update_size(pb, pos);
01144 }
01145
01146 static int mov_write_tmcd_tag(AVIOContext *pb, MOVTrack *track)
01147 {
01148 int64_t pos = avio_tell(pb);
01149 int frame_duration = av_rescale(track->timescale, track->enc->time_base.num, track->enc->time_base.den);
01150 int nb_frames = (track->timescale + frame_duration/2) / frame_duration;
01151
01152 avio_wb32(pb, 0);
01153 ffio_wfourcc(pb, "tmcd");
01154 avio_wb32(pb, 0);
01155 avio_wb32(pb, 1);
01156 avio_wb32(pb, 0);
01157 avio_wb32(pb, track->timecode_flags);
01158 avio_wb32(pb, track->timescale);
01159 avio_wb32(pb, frame_duration);
01160 avio_w8(pb, nb_frames);
01161 avio_wb24(pb, 0);
01162
01163 return update_size(pb, pos);
01164 }
01165
01166 static int mov_write_rtp_tag(AVIOContext *pb, MOVTrack *track)
01167 {
01168 int64_t pos = avio_tell(pb);
01169 avio_wb32(pb, 0);
01170 ffio_wfourcc(pb, "rtp ");
01171 avio_wb32(pb, 0);
01172 avio_wb16(pb, 0);
01173 avio_wb16(pb, 1);
01174
01175 avio_wb16(pb, 1);
01176 avio_wb16(pb, 1);
01177 avio_wb32(pb, track->max_packet_size);
01178
01179 avio_wb32(pb, 12);
01180 ffio_wfourcc(pb, "tims");
01181 avio_wb32(pb, track->timescale);
01182
01183 return update_size(pb, pos);
01184 }
01185
01186 static int mov_write_stsd_tag(AVIOContext *pb, MOVTrack *track)
01187 {
01188 int64_t pos = avio_tell(pb);
01189 avio_wb32(pb, 0);
01190 ffio_wfourcc(pb, "stsd");
01191 avio_wb32(pb, 0);
01192 avio_wb32(pb, 1);
01193 if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO)
01194 mov_write_video_tag(pb, track);
01195 else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
01196 mov_write_audio_tag(pb, track);
01197 else if (track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE)
01198 mov_write_subtitle_tag(pb, track);
01199 else if (track->enc->codec_tag == MKTAG('r','t','p',' '))
01200 mov_write_rtp_tag(pb, track);
01201 else if (track->enc->codec_tag == MKTAG('t','m','c','d'))
01202 mov_write_tmcd_tag(pb, track);
01203 return update_size(pb, pos);
01204 }
01205
01206 static int mov_write_ctts_tag(AVIOContext *pb, MOVTrack *track)
01207 {
01208 MOVStts *ctts_entries;
01209 uint32_t entries = 0;
01210 uint32_t atom_size;
01211 int i;
01212
01213 ctts_entries = av_malloc((track->entry + 1) * sizeof(*ctts_entries));
01214 ctts_entries[0].count = 1;
01215 ctts_entries[0].duration = track->cluster[0].cts;
01216 for (i=1; i<track->entry; i++) {
01217 if (track->cluster[i].cts == ctts_entries[entries].duration) {
01218 ctts_entries[entries].count++;
01219 } else {
01220 entries++;
01221 ctts_entries[entries].duration = track->cluster[i].cts;
01222 ctts_entries[entries].count = 1;
01223 }
01224 }
01225 entries++;
01226 atom_size = 16 + (entries * 8);
01227 avio_wb32(pb, atom_size);
01228 ffio_wfourcc(pb, "ctts");
01229 avio_wb32(pb, 0);
01230 avio_wb32(pb, entries);
01231 for (i=0; i<entries; i++) {
01232 avio_wb32(pb, ctts_entries[i].count);
01233 avio_wb32(pb, ctts_entries[i].duration);
01234 }
01235 av_free(ctts_entries);
01236 return atom_size;
01237 }
01238
01239
01240 static int mov_write_stts_tag(AVIOContext *pb, MOVTrack *track)
01241 {
01242 MOVStts *stts_entries;
01243 uint32_t entries = -1;
01244 uint32_t atom_size;
01245 int i;
01246
01247 if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO && !track->audio_vbr) {
01248 stts_entries = av_malloc(sizeof(*stts_entries));
01249 stts_entries[0].count = track->sample_count;
01250 stts_entries[0].duration = 1;
01251 entries = 1;
01252 } else {
01253 stts_entries = track->entry ?
01254 av_malloc(track->entry * sizeof(*stts_entries)) :
01255 NULL;
01256 for (i=0; i<track->entry; i++) {
01257 int duration = get_cluster_duration(track, i);
01258 if (i && duration == stts_entries[entries].duration) {
01259 stts_entries[entries].count++;
01260 } else {
01261 entries++;
01262 stts_entries[entries].duration = duration;
01263 stts_entries[entries].count = 1;
01264 }
01265 }
01266 entries++;
01267 }
01268 atom_size = 16 + (entries * 8);
01269 avio_wb32(pb, atom_size);
01270 ffio_wfourcc(pb, "stts");
01271 avio_wb32(pb, 0);
01272 avio_wb32(pb, entries);
01273 for (i=0; i<entries; i++) {
01274 avio_wb32(pb, stts_entries[i].count);
01275 avio_wb32(pb, stts_entries[i].duration);
01276 }
01277 av_free(stts_entries);
01278 return atom_size;
01279 }
01280
01281 static int mov_write_dref_tag(AVIOContext *pb)
01282 {
01283 avio_wb32(pb, 28);
01284 ffio_wfourcc(pb, "dref");
01285 avio_wb32(pb, 0);
01286 avio_wb32(pb, 1);
01287
01288 avio_wb32(pb, 0xc);
01289
01290 ffio_wfourcc(pb, "url ");
01291 avio_wb32(pb, 1);
01292
01293 return 28;
01294 }
01295
01296 static int mov_write_stbl_tag(AVIOContext *pb, MOVTrack *track)
01297 {
01298 int64_t pos = avio_tell(pb);
01299 avio_wb32(pb, 0);
01300 ffio_wfourcc(pb, "stbl");
01301 mov_write_stsd_tag(pb, track);
01302 mov_write_stts_tag(pb, track);
01303 if ((track->enc->codec_type == AVMEDIA_TYPE_VIDEO ||
01304 track->enc->codec_tag == MKTAG('r','t','p',' ')) &&
01305 track->has_keyframes && track->has_keyframes < track->entry)
01306 mov_write_stss_tag(pb, track, MOV_SYNC_SAMPLE);
01307 if (track->mode == MODE_MOV && track->flags & MOV_TRACK_STPS)
01308 mov_write_stss_tag(pb, track, MOV_PARTIAL_SYNC_SAMPLE);
01309 if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO &&
01310 track->flags & MOV_TRACK_CTTS)
01311 mov_write_ctts_tag(pb, track);
01312 mov_write_stsc_tag(pb, track);
01313 mov_write_stsz_tag(pb, track);
01314 mov_write_stco_tag(pb, track);
01315 return update_size(pb, pos);
01316 }
01317
01318 static int mov_write_dinf_tag(AVIOContext *pb)
01319 {
01320 int64_t pos = avio_tell(pb);
01321 avio_wb32(pb, 0);
01322 ffio_wfourcc(pb, "dinf");
01323 mov_write_dref_tag(pb);
01324 return update_size(pb, pos);
01325 }
01326
01327 static int mov_write_nmhd_tag(AVIOContext *pb)
01328 {
01329 avio_wb32(pb, 12);
01330 ffio_wfourcc(pb, "nmhd");
01331 avio_wb32(pb, 0);
01332 return 12;
01333 }
01334
01335 static int mov_write_tcmi_tag(AVIOContext *pb, MOVTrack *track)
01336 {
01337 int64_t pos = avio_tell(pb);
01338 const char *font = "Lucida Grande";
01339 avio_wb32(pb, 0);
01340 ffio_wfourcc(pb, "tcmi");
01341 avio_wb32(pb, 0);
01342 avio_wb16(pb, 0);
01343 avio_wb16(pb, 0);
01344 avio_wb16(pb, 12);
01345 avio_wb16(pb, 0);
01346 avio_wb16(pb, 0x0000);
01347 avio_wb16(pb, 0x0000);
01348 avio_wb16(pb, 0x0000);
01349 avio_wb16(pb, 0xffff);
01350 avio_wb16(pb, 0xffff);
01351 avio_wb16(pb, 0xffff);
01352 avio_w8(pb, strlen(font));
01353 avio_write(pb, font, strlen(font));
01354 return update_size(pb, pos);
01355 }
01356
01357 static int mov_write_gmhd_tag(AVIOContext *pb, MOVTrack *track)
01358 {
01359 int64_t pos = avio_tell(pb);
01360 avio_wb32(pb, 0);
01361 ffio_wfourcc(pb, "gmhd");
01362 avio_wb32(pb, 0x18);
01363 ffio_wfourcc(pb, "gmin");
01364 avio_wb32(pb, 0);
01365 avio_wb16(pb, 0x40);
01366 avio_wb16(pb, 0x8000);
01367 avio_wb16(pb, 0x8000);
01368 avio_wb16(pb, 0x8000);
01369 avio_wb16(pb, 0);
01370 avio_wb16(pb, 0);
01371
01372
01373
01374
01375
01376
01377
01378 if (track->tag != MKTAG('c','6','0','8')) {
01379 avio_wb32(pb, 0x2C);
01380 ffio_wfourcc(pb, "text");
01381 avio_wb16(pb, 0x01);
01382 avio_wb32(pb, 0x00);
01383 avio_wb32(pb, 0x00);
01384 avio_wb32(pb, 0x00);
01385 avio_wb32(pb, 0x01);
01386 avio_wb32(pb, 0x00);
01387 avio_wb32(pb, 0x00);
01388 avio_wb32(pb, 0x00);
01389 avio_wb32(pb, 0x00004000);
01390 avio_wb16(pb, 0x0000);
01391 }
01392
01393 if (track->enc->codec_tag == MKTAG('t','m','c','d')) {
01394 int64_t tmcd_pos = avio_tell(pb);
01395 avio_wb32(pb, 0);
01396 ffio_wfourcc(pb, "tmcd");
01397 mov_write_tcmi_tag(pb, track);
01398 update_size(pb, tmcd_pos);
01399 }
01400 return update_size(pb, pos);
01401 }
01402
01403 static int mov_write_smhd_tag(AVIOContext *pb)
01404 {
01405 avio_wb32(pb, 16);
01406 ffio_wfourcc(pb, "smhd");
01407 avio_wb32(pb, 0);
01408 avio_wb16(pb, 0);
01409 avio_wb16(pb, 0);
01410 return 16;
01411 }
01412
01413 static int mov_write_vmhd_tag(AVIOContext *pb)
01414 {
01415 avio_wb32(pb, 0x14);
01416 ffio_wfourcc(pb, "vmhd");
01417 avio_wb32(pb, 0x01);
01418 avio_wb64(pb, 0);
01419 return 0x14;
01420 }
01421
01422 static int mov_write_hdlr_tag(AVIOContext *pb, MOVTrack *track)
01423 {
01424 const char *hdlr, *descr = NULL, *hdlr_type = NULL;
01425 int64_t pos = avio_tell(pb);
01426
01427 if (!track) {
01428 hdlr = "dhlr";
01429 hdlr_type = "url ";
01430 descr = "DataHandler";
01431 } else {
01432 hdlr = (track->mode == MODE_MOV) ? "mhlr" : "\0\0\0\0";
01433 if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) {
01434 hdlr_type = "vide";
01435 descr = "VideoHandler";
01436 } else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) {
01437 hdlr_type = "soun";
01438 descr = "SoundHandler";
01439 } else if (track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE) {
01440 if (track->tag == MKTAG('c','6','0','8')) {
01441 hdlr_type = "clcp";
01442 descr = "ClosedCaptionHandler";
01443 } else {
01444 if (track->tag == MKTAG('t','x','3','g')) hdlr_type = "sbtl";
01445 else hdlr_type = "text";
01446 descr = "SubtitleHandler";
01447 }
01448 } else if (track->enc->codec_tag == MKTAG('t','m','c','d')) {
01449 hdlr_type = "tmcd";
01450 descr = "TimeCodeHandler";
01451 } else if (track->enc->codec_tag == MKTAG('r','t','p',' ')) {
01452 hdlr_type = "hint";
01453 descr = "HintHandler";
01454 } else {
01455 hdlr = "dhlr";
01456 hdlr_type = "url ";
01457 descr = "DataHandler";
01458 }
01459 }
01460
01461 avio_wb32(pb, 0);
01462 ffio_wfourcc(pb, "hdlr");
01463 avio_wb32(pb, 0);
01464 avio_write(pb, hdlr, 4);
01465 ffio_wfourcc(pb, hdlr_type);
01466 avio_wb32(pb ,0);
01467 avio_wb32(pb ,0);
01468 avio_wb32(pb ,0);
01469 if (!track || track->mode == MODE_MOV)
01470 avio_w8(pb, strlen(descr));
01471 avio_write(pb, descr, strlen(descr));
01472 if (track && track->mode != MODE_MOV)
01473 avio_w8(pb, 0);
01474 return update_size(pb, pos);
01475 }
01476
01477 static int mov_write_hmhd_tag(AVIOContext *pb)
01478 {
01479
01480
01481 avio_wb32(pb, 28);
01482 ffio_wfourcc(pb, "hmhd");
01483 avio_wb32(pb, 0);
01484 avio_wb16(pb, 0);
01485 avio_wb16(pb, 0);
01486 avio_wb32(pb, 0);
01487 avio_wb32(pb, 0);
01488 avio_wb32(pb, 0);
01489 return 28;
01490 }
01491
01492 static int mov_write_minf_tag(AVIOContext *pb, MOVTrack *track)
01493 {
01494 int64_t pos = avio_tell(pb);
01495 avio_wb32(pb, 0);
01496 ffio_wfourcc(pb, "minf");
01497 if(track->enc->codec_type == AVMEDIA_TYPE_VIDEO)
01498 mov_write_vmhd_tag(pb);
01499 else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
01500 mov_write_smhd_tag(pb);
01501 else if (track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE) {
01502 if (track->tag == MKTAG('t','e','x','t') || track->tag == MKTAG('c','6','0','8')) {
01503 mov_write_gmhd_tag(pb, track);
01504 } else {
01505 mov_write_nmhd_tag(pb);
01506 }
01507 } else if (track->tag == MKTAG('t','m','c','d')) {
01508 mov_write_gmhd_tag(pb, track);
01509 } else if (track->tag == MKTAG('r','t','p',' ')) {
01510 mov_write_hmhd_tag(pb);
01511 }
01512 if (track->mode == MODE_MOV)
01513 mov_write_hdlr_tag(pb, NULL);
01514 mov_write_dinf_tag(pb);
01515 mov_write_stbl_tag(pb, track);
01516 return update_size(pb, pos);
01517 }
01518
01519 static int mov_write_mdhd_tag(AVIOContext *pb, MOVTrack *track)
01520 {
01521 int version = track->track_duration < INT32_MAX ? 0 : 1;
01522
01523 if (track->mode == MODE_ISM)
01524 version = 1;
01525
01526 (version == 1) ? avio_wb32(pb, 44) : avio_wb32(pb, 32);
01527 ffio_wfourcc(pb, "mdhd");
01528 avio_w8(pb, version);
01529 avio_wb24(pb, 0);
01530 if (version == 1) {
01531 avio_wb64(pb, track->time);
01532 avio_wb64(pb, track->time);
01533 } else {
01534 avio_wb32(pb, track->time);
01535 avio_wb32(pb, track->time);
01536 }
01537 avio_wb32(pb, track->timescale);
01538 if (!track->entry)
01539 (version == 1) ? avio_wb64(pb, UINT64_C(0xffffffffffffffff)) : avio_wb32(pb, 0xffffffff);
01540 else
01541 (version == 1) ? avio_wb64(pb, track->track_duration) : avio_wb32(pb, track->track_duration);
01542 avio_wb16(pb, track->language);
01543 avio_wb16(pb, 0);
01544
01545 if(version!=0 && track->mode == MODE_MOV){
01546 av_log(NULL, AV_LOG_ERROR,
01547 "FATAL error, file duration too long for timebase, this file will not be\n"
01548 "playable with quicktime. Choose a different timebase or a different\n"
01549 "container format\n");
01550 }
01551
01552 return 32;
01553 }
01554
01555 static int mov_write_mdia_tag(AVIOContext *pb, MOVTrack *track)
01556 {
01557 int64_t pos = avio_tell(pb);
01558 avio_wb32(pb, 0);
01559 ffio_wfourcc(pb, "mdia");
01560 mov_write_mdhd_tag(pb, track);
01561 mov_write_hdlr_tag(pb, track);
01562 mov_write_minf_tag(pb, track);
01563 return update_size(pb, pos);
01564 }
01565
01566
01567
01568
01569
01570 static void write_matrix(AVIOContext *pb, int16_t a, int16_t b, int16_t c,
01571 int16_t d, int16_t tx, int16_t ty)
01572 {
01573 avio_wb32(pb, a << 16);
01574 avio_wb32(pb, b << 16);
01575 avio_wb32(pb, 0);
01576 avio_wb32(pb, c << 16);
01577 avio_wb32(pb, d << 16);
01578 avio_wb32(pb, 0);
01579 avio_wb32(pb, tx << 16);
01580 avio_wb32(pb, ty << 16);
01581 avio_wb32(pb, 1 << 30);
01582 }
01583
01584 static int mov_write_tkhd_tag(AVIOContext *pb, MOVTrack *track, AVStream *st)
01585 {
01586 int64_t duration = av_rescale_rnd(track->track_duration, MOV_TIMESCALE,
01587 track->timescale, AV_ROUND_UP);
01588 int version = duration < INT32_MAX ? 0 : 1;
01589 int rotation = 0;
01590
01591 if (track->mode == MODE_ISM)
01592 version = 1;
01593
01594 (version == 1) ? avio_wb32(pb, 104) : avio_wb32(pb, 92);
01595 ffio_wfourcc(pb, "tkhd");
01596 avio_w8(pb, version);
01597 avio_wb24(pb, 0xf);
01598 if (version == 1) {
01599 avio_wb64(pb, track->time);
01600 avio_wb64(pb, track->time);
01601 } else {
01602 avio_wb32(pb, track->time);
01603 avio_wb32(pb, track->time);
01604 }
01605 avio_wb32(pb, track->track_id);
01606 avio_wb32(pb, 0);
01607 if (!track->entry)
01608 (version == 1) ? avio_wb64(pb, UINT64_C(0xffffffffffffffff)) : avio_wb32(pb, 0xffffffff);
01609 else
01610 (version == 1) ? avio_wb64(pb, duration) : avio_wb32(pb, duration);
01611
01612 avio_wb32(pb, 0);
01613 avio_wb32(pb, 0);
01614 avio_wb16(pb, 0);
01615 avio_wb16(pb, st ? st->codec->codec_type : 0);
01616
01617 if(track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
01618 avio_wb16(pb, 0x0100);
01619 else
01620 avio_wb16(pb, 0);
01621 avio_wb16(pb, 0);
01622
01623
01624 if (st && st->metadata) {
01625 AVDictionaryEntry *rot = av_dict_get(st->metadata, "rotate", NULL, 0);
01626 rotation = (rot && rot->value) ? atoi(rot->value) : 0;
01627 }
01628 if (rotation == 90) {
01629 write_matrix(pb, 0, 1, -1, 0, track->enc->height, 0);
01630 } else if (rotation == 180) {
01631 write_matrix(pb, -1, 0, 0, -1, track->enc->width, track->enc->height);
01632 } else if (rotation == 270) {
01633 write_matrix(pb, 0, -1, 1, 0, 0, track->enc->width);
01634 } else {
01635 write_matrix(pb, 1, 0, 0, 1, 0, 0);
01636 }
01637
01638 if(st && (track->enc->codec_type == AVMEDIA_TYPE_VIDEO ||
01639 track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE)) {
01640 if(track->mode == MODE_MOV) {
01641 avio_wb32(pb, track->enc->width << 16);
01642 avio_wb32(pb, track->height << 16);
01643 } else {
01644 double sample_aspect_ratio = av_q2d(st->sample_aspect_ratio);
01645 if(!sample_aspect_ratio || track->height != track->enc->height)
01646 sample_aspect_ratio = 1;
01647 avio_wb32(pb, sample_aspect_ratio * track->enc->width*0x10000);
01648 avio_wb32(pb, track->height*0x10000);
01649 }
01650 }
01651 else {
01652 avio_wb32(pb, 0);
01653 avio_wb32(pb, 0);
01654 }
01655 return 0x5c;
01656 }
01657
01658 static int mov_write_tapt_tag(AVIOContext *pb, MOVTrack *track)
01659 {
01660 int32_t width = av_rescale(track->enc->sample_aspect_ratio.num, track->enc->width,
01661 track->enc->sample_aspect_ratio.den);
01662
01663 int64_t pos = avio_tell(pb);
01664
01665 avio_wb32(pb, 0);
01666 ffio_wfourcc(pb, "tapt");
01667
01668 avio_wb32(pb, 20);
01669 ffio_wfourcc(pb, "clef");
01670 avio_wb32(pb, 0);
01671 avio_wb32(pb, width << 16);
01672 avio_wb32(pb, track->enc->height << 16);
01673
01674 avio_wb32(pb, 20);
01675 ffio_wfourcc(pb, "prof");
01676 avio_wb32(pb, 0);
01677 avio_wb32(pb, width << 16);
01678 avio_wb32(pb, track->enc->height << 16);
01679
01680 avio_wb32(pb, 20);
01681 ffio_wfourcc(pb, "enof");
01682 avio_wb32(pb, 0);
01683 avio_wb32(pb, track->enc->width << 16);
01684 avio_wb32(pb, track->enc->height << 16);
01685
01686 return update_size(pb, pos);
01687 }
01688
01689
01690 static int mov_write_edts_tag(AVIOContext *pb, MOVTrack *track)
01691 {
01692 int64_t duration = av_rescale_rnd(track->track_duration, MOV_TIMESCALE,
01693 track->timescale, AV_ROUND_UP);
01694 int version = duration < INT32_MAX ? 0 : 1;
01695 int entry_size, entry_count, size;
01696 int64_t delay, start_ct = track->cluster[0].cts;
01697 delay = av_rescale_rnd(track->cluster[0].dts + start_ct, MOV_TIMESCALE,
01698 track->timescale, AV_ROUND_DOWN);
01699 version |= delay < INT32_MAX ? 0 : 1;
01700
01701 entry_size = (version == 1) ? 20 : 12;
01702 entry_count = 1 + (delay > 0);
01703 size = 24 + entry_count * entry_size;
01704
01705
01706 avio_wb32(pb, size);
01707 ffio_wfourcc(pb, "edts");
01708 avio_wb32(pb, size - 8);
01709 ffio_wfourcc(pb, "elst");
01710 avio_w8(pb, version);
01711 avio_wb24(pb, 0);
01712
01713 avio_wb32(pb, entry_count);
01714 if (delay > 0) {
01715 if (version == 1) {
01716 avio_wb64(pb, delay);
01717 avio_wb64(pb, -1);
01718 } else {
01719 avio_wb32(pb, delay);
01720 avio_wb32(pb, -1);
01721 }
01722 avio_wb32(pb, 0x00010000);
01723 } else {
01724 av_assert0(av_rescale_rnd(track->cluster[0].dts, MOV_TIMESCALE, track->timescale, AV_ROUND_DOWN) <= 0);
01725 start_ct = -FFMIN(track->cluster[0].dts, 0);
01726 duration += delay;
01727 }
01728
01729
01730 if (version == 1) {
01731 avio_wb64(pb, duration);
01732 avio_wb64(pb, start_ct);
01733 } else {
01734 avio_wb32(pb, duration);
01735 avio_wb32(pb, start_ct);
01736 }
01737 avio_wb32(pb, 0x00010000);
01738 return size;
01739 }
01740
01741 static int mov_write_tref_tag(AVIOContext *pb, MOVTrack *track)
01742 {
01743 avio_wb32(pb, 20);
01744 ffio_wfourcc(pb, "tref");
01745 avio_wb32(pb, 12);
01746 avio_wl32(pb, track->tref_tag);
01747 avio_wb32(pb, track->tref_id);
01748 return 20;
01749 }
01750
01751
01752 static int mov_write_uuid_tag_psp(AVIOContext *pb, MOVTrack *mov)
01753 {
01754 avio_wb32(pb, 0x34);
01755 ffio_wfourcc(pb, "uuid");
01756 ffio_wfourcc(pb, "USMT");
01757 avio_wb32(pb, 0x21d24fce);
01758 avio_wb32(pb, 0xbb88695c);
01759 avio_wb32(pb, 0xfac9c740);
01760 avio_wb32(pb, 0x1c);
01761 ffio_wfourcc(pb, "MTDT");
01762 avio_wb32(pb, 0x00010012);
01763 avio_wb32(pb, 0x0a);
01764 avio_wb32(pb, 0x55c40000);
01765 avio_wb32(pb, 0x1);
01766 avio_wb32(pb, 0x0);
01767 return 0x34;
01768 }
01769
01770 static int mov_write_udta_sdp(AVIOContext *pb, MOVTrack *track)
01771 {
01772
01773 AVFormatContext *ctx = track->rtp_ctx;
01774 char buf[1000] = "";
01775 int len;
01776
01777 ff_sdp_write_media(buf, sizeof(buf), ctx->streams[0], track->src_track,
01778 NULL, NULL, 0, 0, ctx);
01779 av_strlcatf(buf, sizeof(buf), "a=control:streamid=%d\r\n", track->track_id);
01780 len = strlen(buf);
01781
01782 avio_wb32(pb, len + 24);
01783 ffio_wfourcc(pb, "udta");
01784 avio_wb32(pb, len + 16);
01785 ffio_wfourcc(pb, "hnti");
01786 avio_wb32(pb, len + 8);
01787 ffio_wfourcc(pb, "sdp ");
01788 avio_write(pb, buf, len);
01789 return len + 24;
01790 }
01791
01792 static int mov_write_trak_tag(AVIOContext *pb, MOVMuxContext *mov,
01793 MOVTrack *track, AVStream *st)
01794 {
01795 int64_t pos = avio_tell(pb);
01796 avio_wb32(pb, 0);
01797 ffio_wfourcc(pb, "trak");
01798 mov_write_tkhd_tag(pb, track, st);
01799 if (supports_edts(mov))
01800 mov_write_edts_tag(pb, track);
01801 if (track->tref_tag)
01802 mov_write_tref_tag(pb, track);
01803 mov_write_mdia_tag(pb, track);
01804 if (track->mode == MODE_PSP)
01805 mov_write_uuid_tag_psp(pb,track);
01806 if (track->tag == MKTAG('r','t','p',' '))
01807 mov_write_udta_sdp(pb, track);
01808 if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO && track->mode == MODE_MOV) {
01809 double sample_aspect_ratio = av_q2d(st->sample_aspect_ratio);
01810 if (st->sample_aspect_ratio.num && 1.0 != sample_aspect_ratio)
01811 mov_write_tapt_tag(pb, track);
01812 };
01813 return update_size(pb, pos);
01814 }
01815
01816 static int mov_write_iods_tag(AVIOContext *pb, MOVMuxContext *mov)
01817 {
01818 int i, has_audio = 0, has_video = 0;
01819 int64_t pos = avio_tell(pb);
01820 int audio_profile = mov->iods_audio_profile;
01821 int video_profile = mov->iods_video_profile;
01822 for (i = 0; i < mov->nb_streams; i++) {
01823 if(mov->tracks[i].entry > 0) {
01824 has_audio |= mov->tracks[i].enc->codec_type == AVMEDIA_TYPE_AUDIO;
01825 has_video |= mov->tracks[i].enc->codec_type == AVMEDIA_TYPE_VIDEO;
01826 }
01827 }
01828 if (audio_profile < 0)
01829 audio_profile = 0xFF - has_audio;
01830 if (video_profile < 0)
01831 video_profile = 0xFF - has_video;
01832 avio_wb32(pb, 0x0);
01833 ffio_wfourcc(pb, "iods");
01834 avio_wb32(pb, 0);
01835 put_descr(pb, 0x10, 7);
01836 avio_wb16(pb, 0x004f);
01837 avio_w8(pb, 0xff);
01838 avio_w8(pb, 0xff);
01839 avio_w8(pb, audio_profile);
01840 avio_w8(pb, video_profile);
01841 avio_w8(pb, 0xff);
01842 return update_size(pb, pos);
01843 }
01844
01845 static int mov_write_trex_tag(AVIOContext *pb, MOVTrack *track)
01846 {
01847 avio_wb32(pb, 0x20);
01848 ffio_wfourcc(pb, "trex");
01849 avio_wb32(pb, 0);
01850 avio_wb32(pb, track->track_id);
01851 avio_wb32(pb, 1);
01852 avio_wb32(pb, 0);
01853 avio_wb32(pb, 0);
01854 avio_wb32(pb, 0);
01855 return 0;
01856 }
01857
01858 static int mov_write_mvex_tag(AVIOContext *pb, MOVMuxContext *mov)
01859 {
01860 int64_t pos = avio_tell(pb);
01861 int i;
01862 avio_wb32(pb, 0x0);
01863 ffio_wfourcc(pb, "mvex");
01864 for (i = 0; i < mov->nb_streams; i++)
01865 mov_write_trex_tag(pb, &mov->tracks[i]);
01866 return update_size(pb, pos);
01867 }
01868
01869 static int mov_write_mvhd_tag(AVIOContext *pb, MOVMuxContext *mov)
01870 {
01871 int max_track_id = 1, i;
01872 int64_t max_track_len_temp, max_track_len = 0;
01873 int version;
01874
01875 for (i=0; i<mov->nb_streams; i++) {
01876 if(mov->tracks[i].entry > 0) {
01877 max_track_len_temp = av_rescale_rnd(mov->tracks[i].track_duration,
01878 MOV_TIMESCALE,
01879 mov->tracks[i].timescale,
01880 AV_ROUND_UP);
01881 if (max_track_len < max_track_len_temp)
01882 max_track_len = max_track_len_temp;
01883 if (max_track_id < mov->tracks[i].track_id)
01884 max_track_id = mov->tracks[i].track_id;
01885 }
01886 }
01887
01888 version = max_track_len < UINT32_MAX ? 0 : 1;
01889 (version == 1) ? avio_wb32(pb, 120) : avio_wb32(pb, 108);
01890 ffio_wfourcc(pb, "mvhd");
01891 avio_w8(pb, version);
01892 avio_wb24(pb, 0);
01893 if (version == 1) {
01894 avio_wb64(pb, mov->time);
01895 avio_wb64(pb, mov->time);
01896 } else {
01897 avio_wb32(pb, mov->time);
01898 avio_wb32(pb, mov->time);
01899 }
01900 avio_wb32(pb, MOV_TIMESCALE);
01901 (version == 1) ? avio_wb64(pb, max_track_len) : avio_wb32(pb, max_track_len);
01902
01903 avio_wb32(pb, 0x00010000);
01904 avio_wb16(pb, 0x0100);
01905 avio_wb16(pb, 0);
01906 avio_wb32(pb, 0);
01907 avio_wb32(pb, 0);
01908
01909
01910 write_matrix(pb, 1, 0, 0, 1, 0, 0);
01911
01912 avio_wb32(pb, 0);
01913 avio_wb32(pb, 0);
01914 avio_wb32(pb, 0);
01915 avio_wb32(pb, 0);
01916 avio_wb32(pb, 0);
01917 avio_wb32(pb, 0);
01918 avio_wb32(pb, max_track_id + 1);
01919 return 0x6c;
01920 }
01921
01922 static int mov_write_itunes_hdlr_tag(AVIOContext *pb, MOVMuxContext *mov,
01923 AVFormatContext *s)
01924 {
01925 avio_wb32(pb, 33);
01926 ffio_wfourcc(pb, "hdlr");
01927 avio_wb32(pb, 0);
01928 avio_wb32(pb, 0);
01929 ffio_wfourcc(pb, "mdir");
01930 ffio_wfourcc(pb, "appl");
01931 avio_wb32(pb, 0);
01932 avio_wb32(pb, 0);
01933 avio_w8(pb, 0);
01934 return 33;
01935 }
01936
01937
01938 static int mov_write_string_data_tag(AVIOContext *pb, const char *data, int lang, int long_style)
01939 {
01940 if(long_style){
01941 int size = 16 + strlen(data);
01942 avio_wb32(pb, size);
01943 ffio_wfourcc(pb, "data");
01944 avio_wb32(pb, 1);
01945 avio_wb32(pb, 0);
01946 avio_write(pb, data, strlen(data));
01947 return size;
01948 }else{
01949 if (!lang)
01950 lang = ff_mov_iso639_to_lang("und", 1);
01951 avio_wb16(pb, strlen(data));
01952 avio_wb16(pb, lang);
01953 avio_write(pb, data, strlen(data));
01954 return strlen(data) + 4;
01955 }
01956 }
01957
01958 static int mov_write_string_tag(AVIOContext *pb, const char *name, const char *value, int lang, int long_style){
01959 int size = 0;
01960 if (value && value[0]) {
01961 int64_t pos = avio_tell(pb);
01962 avio_wb32(pb, 0);
01963 ffio_wfourcc(pb, name);
01964 mov_write_string_data_tag(pb, value, lang, long_style);
01965 size = update_size(pb, pos);
01966 }
01967 return size;
01968 }
01969
01970 static int mov_write_string_metadata(AVFormatContext *s, AVIOContext *pb,
01971 const char *name, const char *tag,
01972 int long_style)
01973 {
01974 int l, lang = 0, len, len2;
01975 AVDictionaryEntry *t, *t2 = NULL;
01976 char tag2[16];
01977
01978 if (!(t = av_dict_get(s->metadata, tag, NULL, 0)))
01979 return 0;
01980
01981 len = strlen(t->key);
01982 snprintf(tag2, sizeof(tag2), "%s-", tag);
01983 while ((t2 = av_dict_get(s->metadata, tag2, t2, AV_DICT_IGNORE_SUFFIX))) {
01984 len2 = strlen(t2->key);
01985 if (len2 == len+4 && !strcmp(t->value, t2->value)
01986 && (l=ff_mov_iso639_to_lang(&t2->key[len2-3], 1)) >= 0) {
01987 lang = l;
01988 break;
01989 }
01990 }
01991 return mov_write_string_tag(pb, name, t->value, lang, long_style);
01992 }
01993
01994
01995 static int mov_write_tmpo_tag(AVIOContext *pb, AVFormatContext *s)
01996 {
01997 AVDictionaryEntry *t = av_dict_get(s->metadata, "tmpo", NULL, 0);
01998 int size = 0, tmpo = t ? atoi(t->value) : 0;
01999 if (tmpo) {
02000 size = 26;
02001 avio_wb32(pb, size);
02002 ffio_wfourcc(pb, "tmpo");
02003 avio_wb32(pb, size-8);
02004 ffio_wfourcc(pb, "data");
02005 avio_wb32(pb, 0x15);
02006 avio_wb32(pb, 0);
02007 avio_wb16(pb, tmpo);
02008 }
02009 return size;
02010 }
02011
02012
02013 static int mov_write_trkn_tag(AVIOContext *pb, MOVMuxContext *mov,
02014 AVFormatContext *s)
02015 {
02016 AVDictionaryEntry *t = av_dict_get(s->metadata, "track", NULL, 0);
02017 int size = 0, track = t ? atoi(t->value) : 0;
02018 if (track) {
02019 avio_wb32(pb, 32);
02020 ffio_wfourcc(pb, "trkn");
02021 avio_wb32(pb, 24);
02022 ffio_wfourcc(pb, "data");
02023 avio_wb32(pb, 0);
02024 avio_wb32(pb, 0);
02025 avio_wb16(pb, 0);
02026 avio_wb16(pb, track);
02027 avio_wb16(pb, 0);
02028 avio_wb16(pb, 0);
02029 size = 32;
02030 }
02031 return size;
02032 }
02033
02034 static int mov_write_int8_metadata(AVFormatContext *s, AVIOContext *pb,
02035 const char *name, const char *tag,
02036 int len)
02037 {
02038 AVDictionaryEntry *t = NULL;
02039 uint8_t num;
02040
02041 if (!(t = av_dict_get(s->metadata, tag, NULL, 0)))
02042 return 0;
02043 num = atoi(t->value);
02044
02045 avio_wb32(pb, len+8);
02046 ffio_wfourcc(pb, name);
02047 if (len==4) avio_wb32(pb, num);
02048 else avio_w8 (pb, num);
02049 return len+8;
02050 }
02051
02052
02053 static int mov_write_ilst_tag(AVIOContext *pb, MOVMuxContext *mov,
02054 AVFormatContext *s)
02055 {
02056 int64_t pos = avio_tell(pb);
02057 avio_wb32(pb, 0);
02058 ffio_wfourcc(pb, "ilst");
02059 mov_write_string_metadata(s, pb, "\251nam", "title" , 1);
02060 mov_write_string_metadata(s, pb, "\251ART", "artist" , 1);
02061 mov_write_string_metadata(s, pb, "aART", "album_artist", 1);
02062 mov_write_string_metadata(s, pb, "\251wrt", "composer" , 1);
02063 mov_write_string_metadata(s, pb, "\251alb", "album" , 1);
02064 mov_write_string_metadata(s, pb, "\251day", "date" , 1);
02065 mov_write_string_tag(pb, "\251too", LIBAVFORMAT_IDENT, 0, 1);
02066 mov_write_string_metadata(s, pb, "\251cmt", "comment" , 1);
02067 mov_write_string_metadata(s, pb, "\251gen", "genre" , 1);
02068 mov_write_string_metadata(s, pb, "\251cpy", "copyright", 1);
02069 mov_write_string_metadata(s, pb, "\251grp", "grouping" , 1);
02070 mov_write_string_metadata(s, pb, "\251lyr", "lyrics" , 1);
02071 mov_write_string_metadata(s, pb, "desc", "description",1);
02072 mov_write_string_metadata(s, pb, "ldes", "synopsis" , 1);
02073 mov_write_string_metadata(s, pb, "tvsh", "show" , 1);
02074 mov_write_string_metadata(s, pb, "tven", "episode_id",1);
02075 mov_write_string_metadata(s, pb, "tvnn", "network" , 1);
02076 mov_write_int8_metadata (s, pb, "tves", "episode_sort",4);
02077 mov_write_int8_metadata (s, pb, "tvsn", "season_number",4);
02078 mov_write_int8_metadata (s, pb, "stik", "media_type",1);
02079 mov_write_int8_metadata (s, pb, "hdvd", "hd_video", 1);
02080 mov_write_int8_metadata (s, pb, "pgap", "gapless_playback",1);
02081 mov_write_trkn_tag(pb, mov, s);
02082 mov_write_tmpo_tag(pb, s);
02083 return update_size(pb, pos);
02084 }
02085
02086
02087 static int mov_write_meta_tag(AVIOContext *pb, MOVMuxContext *mov,
02088 AVFormatContext *s)
02089 {
02090 int size = 0;
02091 int64_t pos = avio_tell(pb);
02092 avio_wb32(pb, 0);
02093 ffio_wfourcc(pb, "meta");
02094 avio_wb32(pb, 0);
02095 mov_write_itunes_hdlr_tag(pb, mov, s);
02096 mov_write_ilst_tag(pb, mov, s);
02097 size = update_size(pb, pos);
02098 return size;
02099 }
02100
02101 static int utf8len(const uint8_t *b)
02102 {
02103 int len=0;
02104 int val;
02105 while(*b){
02106 GET_UTF8(val, *b++, return -1;)
02107 len++;
02108 }
02109 return len;
02110 }
02111
02112 static int ascii_to_wc(AVIOContext *pb, const uint8_t *b)
02113 {
02114 int val;
02115 while(*b){
02116 GET_UTF8(val, *b++, return -1;)
02117 avio_wb16(pb, val);
02118 }
02119 avio_wb16(pb, 0x00);
02120 return 0;
02121 }
02122
02123 static uint16_t language_code(const char *str)
02124 {
02125 return (((str[0]-0x60) & 0x1F) << 10) + (((str[1]-0x60) & 0x1F) << 5) + ((str[2]-0x60) & 0x1F);
02126 }
02127
02128 static int mov_write_3gp_udta_tag(AVIOContext *pb, AVFormatContext *s,
02129 const char *tag, const char *str)
02130 {
02131 int64_t pos = avio_tell(pb);
02132 AVDictionaryEntry *t = av_dict_get(s->metadata, str, NULL, 0);
02133 if (!t || !utf8len(t->value))
02134 return 0;
02135 avio_wb32(pb, 0);
02136 ffio_wfourcc(pb, tag);
02137 avio_wb32(pb, 0);
02138 if (!strcmp(tag, "yrrc"))
02139 avio_wb16(pb, atoi(t->value));
02140 else {
02141 avio_wb16(pb, language_code("eng"));
02142 avio_write(pb, t->value, strlen(t->value)+1);
02143 if (!strcmp(tag, "albm") &&
02144 (t = av_dict_get(s->metadata, "track", NULL, 0)))
02145 avio_w8(pb, atoi(t->value));
02146 }
02147 return update_size(pb, pos);
02148 }
02149
02150 static int mov_write_chpl_tag(AVIOContext *pb, AVFormatContext *s)
02151 {
02152 int64_t pos = avio_tell(pb);
02153 int i, nb_chapters = FFMIN(s->nb_chapters, 255);
02154
02155 avio_wb32(pb, 0);
02156 ffio_wfourcc(pb, "chpl");
02157 avio_wb32(pb, 0x01000000);
02158 avio_wb32(pb, 0);
02159 avio_w8(pb, nb_chapters);
02160
02161 for (i = 0; i < nb_chapters; i++) {
02162 AVChapter *c = s->chapters[i];
02163 AVDictionaryEntry *t;
02164 avio_wb64(pb, av_rescale_q(c->start, c->time_base, (AVRational){1,10000000}));
02165
02166 if ((t = av_dict_get(c->metadata, "title", NULL, 0))) {
02167 int len = FFMIN(strlen(t->value), 255);
02168 avio_w8(pb, len);
02169 avio_write(pb, t->value, len);
02170 } else
02171 avio_w8(pb, 0);
02172 }
02173 return update_size(pb, pos);
02174 }
02175
02176 static int mov_write_udta_tag(AVIOContext *pb, MOVMuxContext *mov,
02177 AVFormatContext *s)
02178 {
02179 AVIOContext *pb_buf;
02180 int i, ret, size;
02181 uint8_t *buf;
02182
02183 for (i = 0; i < s->nb_streams; i++)
02184 if (mov->tracks[i].enc->flags & CODEC_FLAG_BITEXACT) {
02185 return 0;
02186 }
02187
02188 ret = avio_open_dyn_buf(&pb_buf);
02189 if(ret < 0)
02190 return ret;
02191
02192 if (mov->mode & MODE_3GP) {
02193 mov_write_3gp_udta_tag(pb_buf, s, "perf", "artist");
02194 mov_write_3gp_udta_tag(pb_buf, s, "titl", "title");
02195 mov_write_3gp_udta_tag(pb_buf, s, "auth", "author");
02196 mov_write_3gp_udta_tag(pb_buf, s, "gnre", "genre");
02197 mov_write_3gp_udta_tag(pb_buf, s, "dscp", "comment");
02198 mov_write_3gp_udta_tag(pb_buf, s, "albm", "album");
02199 mov_write_3gp_udta_tag(pb_buf, s, "cprt", "copyright");
02200 mov_write_3gp_udta_tag(pb_buf, s, "yrrc", "date");
02201 } else if (mov->mode == MODE_MOV) {
02202 mov_write_string_metadata(s, pb_buf, "\251ART", "artist" , 0);
02203 mov_write_string_metadata(s, pb_buf, "\251nam", "title" , 0);
02204 mov_write_string_metadata(s, pb_buf, "\251aut", "author" , 0);
02205 mov_write_string_metadata(s, pb_buf, "\251alb", "album" , 0);
02206 mov_write_string_metadata(s, pb_buf, "\251day", "date" , 0);
02207 mov_write_string_metadata(s, pb_buf, "\251swr", "encoder" , 0);
02208
02209 mov_write_string_metadata(s, pb_buf, "\251des", "comment" , 0);
02210
02211 mov_write_string_metadata(s, pb_buf, "\251cmt", "comment" , 0);
02212 mov_write_string_metadata(s, pb_buf, "\251gen", "genre" , 0);
02213 mov_write_string_metadata(s, pb_buf, "\251cpy", "copyright" , 0);
02214 } else {
02215
02216 mov_write_meta_tag(pb_buf, mov, s);
02217 }
02218
02219 if (s->nb_chapters)
02220 mov_write_chpl_tag(pb_buf, s);
02221
02222 if ((size = avio_close_dyn_buf(pb_buf, &buf)) > 0) {
02223 avio_wb32(pb, size+8);
02224 ffio_wfourcc(pb, "udta");
02225 avio_write(pb, buf, size);
02226 }
02227 av_free(buf);
02228
02229 return 0;
02230 }
02231
02232 static void mov_write_psp_udta_tag(AVIOContext *pb,
02233 const char *str, const char *lang, int type)
02234 {
02235 int len = utf8len(str)+1;
02236 if(len<=0)
02237 return;
02238 avio_wb16(pb, len*2+10);
02239 avio_wb32(pb, type);
02240 avio_wb16(pb, language_code(lang));
02241 avio_wb16(pb, 0x01);
02242 ascii_to_wc(pb, str);
02243 }
02244
02245 static int mov_write_uuidusmt_tag(AVIOContext *pb, AVFormatContext *s)
02246 {
02247 AVDictionaryEntry *title = av_dict_get(s->metadata, "title", NULL, 0);
02248 int64_t pos, pos2;
02249
02250 if (title) {
02251 pos = avio_tell(pb);
02252 avio_wb32(pb, 0);
02253 ffio_wfourcc(pb, "uuid");
02254 ffio_wfourcc(pb, "USMT");
02255 avio_wb32(pb, 0x21d24fce);
02256 avio_wb32(pb, 0xbb88695c);
02257 avio_wb32(pb, 0xfac9c740);
02258
02259 pos2 = avio_tell(pb);
02260 avio_wb32(pb, 0);
02261 ffio_wfourcc(pb, "MTDT");
02262 avio_wb16(pb, 4);
02263
02264
02265 avio_wb16(pb, 0x0C);
02266 avio_wb32(pb, 0x0B);
02267 avio_wb16(pb, language_code("und"));
02268 avio_wb16(pb, 0x0);
02269 avio_wb16(pb, 0x021C);
02270
02271 mov_write_psp_udta_tag(pb, LIBAVCODEC_IDENT, "eng", 0x04);
02272 mov_write_psp_udta_tag(pb, title->value, "eng", 0x01);
02273 mov_write_psp_udta_tag(pb, "2006/04/01 11:11:11", "und", 0x03);
02274
02275 update_size(pb, pos2);
02276 return update_size(pb, pos);
02277 }
02278
02279 return 0;
02280 }
02281
02282 static void build_chunks(MOVTrack *trk)
02283 {
02284 int i;
02285 MOVIentry *chunk= &trk->cluster[0];
02286 uint64_t chunkSize = chunk->size;
02287 chunk->chunkNum= 1;
02288 if (trk->chunkCount)
02289 return;
02290 trk->chunkCount= 1;
02291 for(i=1; i<trk->entry; i++){
02292 if(chunk->pos + chunkSize == trk->cluster[i].pos &&
02293 chunkSize + trk->cluster[i].size < (1<<20)){
02294 chunkSize += trk->cluster[i].size;
02295 chunk->samples_in_chunk += trk->cluster[i].entries;
02296 }else{
02297 trk->cluster[i].chunkNum = chunk->chunkNum+1;
02298 chunk=&trk->cluster[i];
02299 chunkSize = chunk->size;
02300 trk->chunkCount++;
02301 }
02302 }
02303 }
02304
02305 static int mov_write_moov_tag(AVIOContext *pb, MOVMuxContext *mov,
02306 AVFormatContext *s)
02307 {
02308 int i;
02309 int64_t pos = avio_tell(pb);
02310 avio_wb32(pb, 0);
02311 ffio_wfourcc(pb, "moov");
02312
02313 for (i=0; i<mov->nb_streams; i++) {
02314 if (mov->tracks[i].entry <= 0 && !(mov->flags & FF_MOV_FLAG_FRAGMENT))
02315 continue;
02316
02317 mov->tracks[i].time = mov->time;
02318 mov->tracks[i].track_id = i+1;
02319
02320 if (mov->tracks[i].entry)
02321 build_chunks(&mov->tracks[i]);
02322 }
02323
02324 if (mov->chapter_track)
02325 for (i=0; i<s->nb_streams; i++) {
02326 mov->tracks[i].tref_tag = MKTAG('c','h','a','p');
02327 mov->tracks[i].tref_id = mov->tracks[mov->chapter_track].track_id;
02328 }
02329 for (i = 0; i < mov->nb_streams; i++) {
02330 if (mov->tracks[i].tag == MKTAG('r','t','p',' ')) {
02331 mov->tracks[i].tref_tag = MKTAG('h','i','n','t');
02332 mov->tracks[i].tref_id =
02333 mov->tracks[mov->tracks[i].src_track].track_id;
02334 }
02335 }
02336 for (i = 0; i < mov->nb_streams; i++) {
02337 if (mov->tracks[i].tag == MKTAG('t','m','c','d')) {
02338 int src_trk = mov->tracks[i].src_track;
02339 mov->tracks[src_trk].tref_tag = mov->tracks[i].tag;
02340 mov->tracks[src_trk].tref_id = mov->tracks[i].track_id;
02341 mov->tracks[i].track_duration = mov->tracks[src_trk].track_duration;
02342 }
02343 }
02344
02345 mov_write_mvhd_tag(pb, mov);
02346 if (mov->mode != MODE_MOV && !mov->iods_skip)
02347 mov_write_iods_tag(pb, mov);
02348 for (i=0; i<mov->nb_streams; i++) {
02349 if (mov->tracks[i].entry > 0 || mov->flags & FF_MOV_FLAG_FRAGMENT) {
02350 mov_write_trak_tag(pb, mov, &(mov->tracks[i]), i < s->nb_streams ? s->streams[i] : NULL);
02351 }
02352 }
02353 if (mov->flags & FF_MOV_FLAG_FRAGMENT)
02354 mov_write_mvex_tag(pb, mov);
02355
02356 if (mov->mode == MODE_PSP)
02357 mov_write_uuidusmt_tag(pb, s);
02358 else
02359 mov_write_udta_tag(pb, mov, s);
02360
02361 return update_size(pb, pos);
02362 }
02363
02364 static void param_write_int(AVIOContext *pb, const char *name, int value)
02365 {
02366 avio_printf(pb, "<param name=\"%s\" value=\"%d\" valuetype=\"data\"/>\n", name, value);
02367 }
02368
02369 static void param_write_string(AVIOContext *pb, const char *name, const char *value)
02370 {
02371 avio_printf(pb, "<param name=\"%s\" value=\"%s\" valuetype=\"data\"/>\n", name, value);
02372 }
02373
02374 static void param_write_hex(AVIOContext *pb, const char *name, const uint8_t *value, int len)
02375 {
02376 char buf[150];
02377 len = FFMIN(sizeof(buf)/2 - 1, len);
02378 ff_data_to_hex(buf, value, len, 0);
02379 buf[2*len] = '\0';
02380 avio_printf(pb, "<param name=\"%s\" value=\"%s\" valuetype=\"data\"/>\n", name, buf);
02381 }
02382
02383 static int mov_write_isml_manifest(AVIOContext *pb, MOVMuxContext *mov)
02384 {
02385 int64_t pos = avio_tell(pb);
02386 int i;
02387 const uint8_t uuid[] = {
02388 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
02389 0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
02390 };
02391
02392 avio_wb32(pb, 0);
02393 ffio_wfourcc(pb, "uuid");
02394 avio_write(pb, uuid, sizeof(uuid));
02395 avio_wb32(pb, 0);
02396
02397 avio_printf(pb, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
02398 avio_printf(pb, "<smil xmlns=\"http://www.w3.org/2001/SMIL20/Language\">\n");
02399 avio_printf(pb, "<head>\n");
02400 avio_printf(pb, "<meta name=\"creator\" content=\"%s\" />\n",
02401 LIBAVFORMAT_IDENT);
02402 avio_printf(pb, "</head>\n");
02403 avio_printf(pb, "<body>\n");
02404 avio_printf(pb, "<switch>\n");
02405 for (i = 0; i < mov->nb_streams; i++) {
02406 MOVTrack *track = &mov->tracks[i];
02407 const char *type;
02408
02409
02410 int track_id = i + 1;
02411
02412 if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) {
02413 type = "video";
02414 } else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) {
02415 type = "audio";
02416 } else {
02417 continue;
02418 }
02419 avio_printf(pb, "<%s systemBitrate=\"%d\">\n", type,
02420 track->enc->bit_rate);
02421 param_write_int(pb, "systemBitrate", track->enc->bit_rate);
02422 param_write_int(pb, "trackID", track_id);
02423 if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) {
02424 if (track->enc->codec_id == AV_CODEC_ID_H264) {
02425 uint8_t *ptr;
02426 int size = track->enc->extradata_size;
02427 if (!ff_avc_write_annexb_extradata(track->enc->extradata, &ptr,
02428 &size)) {
02429 param_write_hex(pb, "CodecPrivateData",
02430 ptr ? ptr : track->enc->extradata,
02431 size);
02432 av_free(ptr);
02433 }
02434 param_write_string(pb, "FourCC", "H264");
02435 } else if (track->enc->codec_id == AV_CODEC_ID_VC1) {
02436 param_write_string(pb, "FourCC", "WVC1");
02437 param_write_hex(pb, "CodecPrivateData", track->enc->extradata,
02438 track->enc->extradata_size);
02439 }
02440 param_write_int(pb, "MaxWidth", track->enc->width);
02441 param_write_int(pb, "MaxHeight", track->enc->height);
02442 param_write_int(pb, "DisplayWidth", track->enc->width);
02443 param_write_int(pb, "DisplayHeight", track->enc->height);
02444 } else {
02445 if (track->enc->codec_id == AV_CODEC_ID_AAC) {
02446 param_write_string(pb, "FourCC", "AACL");
02447 } else if (track->enc->codec_id == AV_CODEC_ID_WMAPRO) {
02448 param_write_string(pb, "FourCC", "WMAP");
02449 }
02450 param_write_hex(pb, "CodecPrivateData", track->enc->extradata,
02451 track->enc->extradata_size);
02452 param_write_int(pb, "AudioTag", ff_codec_get_tag(ff_codec_wav_tags,
02453 track->enc->codec_id));
02454 param_write_int(pb, "Channels", track->enc->channels);
02455 param_write_int(pb, "SamplingRate", track->enc->sample_rate);
02456 param_write_int(pb, "BitsPerSample", 16);
02457 param_write_int(pb, "PacketSize", track->enc->block_align ?
02458 track->enc->block_align : 4);
02459 }
02460 avio_printf(pb, "</%s>\n", type);
02461 }
02462 avio_printf(pb, "</switch>\n");
02463 avio_printf(pb, "</body>\n");
02464 avio_printf(pb, "</smil>\n");
02465
02466 return update_size(pb, pos);
02467 }
02468
02469 static int mov_write_mfhd_tag(AVIOContext *pb, MOVMuxContext *mov)
02470 {
02471 avio_wb32(pb, 16);
02472 ffio_wfourcc(pb, "mfhd");
02473 avio_wb32(pb, 0);
02474 avio_wb32(pb, mov->fragments);
02475 return 0;
02476 }
02477
02478 static int mov_write_tfhd_tag(AVIOContext *pb, MOVTrack *track,
02479 int64_t moof_offset)
02480 {
02481 int64_t pos = avio_tell(pb);
02482 uint32_t flags = MOV_TFHD_DEFAULT_SIZE | MOV_TFHD_DEFAULT_DURATION |
02483 MOV_TFHD_BASE_DATA_OFFSET;
02484 if (!track->entry) {
02485 flags |= MOV_TFHD_DURATION_IS_EMPTY;
02486 } else {
02487 flags |= MOV_TFHD_DEFAULT_FLAGS;
02488 }
02489
02490
02491
02492
02493 if (track->mode == MODE_ISM)
02494 flags &= ~(MOV_TFHD_DEFAULT_SIZE | MOV_TFHD_DEFAULT_DURATION);
02495
02496 avio_wb32(pb, 0);
02497 ffio_wfourcc(pb, "tfhd");
02498 avio_w8(pb, 0);
02499 avio_wb24(pb, flags);
02500
02501 avio_wb32(pb, track->track_id);
02502 if (flags & MOV_TFHD_BASE_DATA_OFFSET)
02503 avio_wb64(pb, moof_offset);
02504 if (flags & MOV_TFHD_DEFAULT_DURATION) {
02505 track->default_duration = get_cluster_duration(track, 0);
02506 avio_wb32(pb, track->default_duration);
02507 }
02508 if (flags & MOV_TFHD_DEFAULT_SIZE) {
02509 track->default_size = track->entry ? track->cluster[0].size : 1;
02510 avio_wb32(pb, track->default_size);
02511 } else
02512 track->default_size = -1;
02513
02514 if (flags & MOV_TFHD_DEFAULT_FLAGS) {
02515 track->default_sample_flags =
02516 track->enc->codec_type == AVMEDIA_TYPE_VIDEO ?
02517 (MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES | MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC) :
02518 MOV_FRAG_SAMPLE_FLAG_DEPENDS_NO;
02519 avio_wb32(pb, track->default_sample_flags);
02520 }
02521
02522 return update_size(pb, pos);
02523 }
02524
02525 static uint32_t get_sample_flags(MOVTrack *track, MOVIentry *entry)
02526 {
02527 return entry->flags & MOV_SYNC_SAMPLE ? MOV_FRAG_SAMPLE_FLAG_DEPENDS_NO :
02528 (MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES | MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC);
02529 }
02530
02531 static int mov_write_trun_tag(AVIOContext *pb, MOVTrack *track)
02532 {
02533 int64_t pos = avio_tell(pb);
02534 uint32_t flags = MOV_TRUN_DATA_OFFSET;
02535 int i;
02536
02537 for (i = 0; i < track->entry; i++) {
02538 if (get_cluster_duration(track, i) != track->default_duration)
02539 flags |= MOV_TRUN_SAMPLE_DURATION;
02540 if (track->cluster[i].size != track->default_size)
02541 flags |= MOV_TRUN_SAMPLE_SIZE;
02542 if (i > 0 && get_sample_flags(track, &track->cluster[i]) != track->default_sample_flags)
02543 flags |= MOV_TRUN_SAMPLE_FLAGS;
02544 }
02545 if (!(flags & MOV_TRUN_SAMPLE_FLAGS))
02546 flags |= MOV_TRUN_FIRST_SAMPLE_FLAGS;
02547 if (track->flags & MOV_TRACK_CTTS)
02548 flags |= MOV_TRUN_SAMPLE_CTS;
02549
02550 avio_wb32(pb, 0);
02551 ffio_wfourcc(pb, "trun");
02552 avio_w8(pb, 0);
02553 avio_wb24(pb, flags);
02554
02555 avio_wb32(pb, track->entry);
02556 track->moof_size_offset = avio_tell(pb);
02557 avio_wb32(pb, 0);
02558 if (flags & MOV_TRUN_FIRST_SAMPLE_FLAGS)
02559 avio_wb32(pb, get_sample_flags(track, &track->cluster[0]));
02560
02561 for (i = 0; i < track->entry; i++) {
02562 if (flags & MOV_TRUN_SAMPLE_DURATION)
02563 avio_wb32(pb, get_cluster_duration(track, i));
02564 if (flags & MOV_TRUN_SAMPLE_SIZE)
02565 avio_wb32(pb, track->cluster[i].size);
02566 if (flags & MOV_TRUN_SAMPLE_FLAGS)
02567 avio_wb32(pb, get_sample_flags(track, &track->cluster[i]));
02568 if (flags & MOV_TRUN_SAMPLE_CTS)
02569 avio_wb32(pb, track->cluster[i].cts);
02570 }
02571
02572 return update_size(pb, pos);
02573 }
02574
02575 static int mov_write_tfxd_tag(AVIOContext *pb, MOVTrack *track)
02576 {
02577 int64_t pos = avio_tell(pb);
02578 const uint8_t uuid[] = {
02579 0x6d, 0x1d, 0x9b, 0x05, 0x42, 0xd5, 0x44, 0xe6,
02580 0x80, 0xe2, 0x14, 0x1d, 0xaf, 0xf7, 0x57, 0xb2
02581 };
02582
02583 avio_wb32(pb, 0);
02584 ffio_wfourcc(pb, "uuid");
02585 avio_write(pb, uuid, sizeof(uuid));
02586 avio_w8(pb, 1);
02587 avio_wb24(pb, 0);
02588 avio_wb64(pb, track->frag_start);
02589 avio_wb64(pb, track->start_dts + track->track_duration -
02590 track->cluster[0].dts);
02591
02592 return update_size(pb, pos);
02593 }
02594
02595 static int mov_write_tfrf_tag(AVIOContext *pb, MOVMuxContext *mov,
02596 MOVTrack *track, int entry)
02597 {
02598 int n = track->nb_frag_info - 1 - entry, i;
02599 int size = 8 + 16 + 4 + 1 + 16*n;
02600 const uint8_t uuid[] = {
02601 0xd4, 0x80, 0x7e, 0xf2, 0xca, 0x39, 0x46, 0x95,
02602 0x8e, 0x54, 0x26, 0xcb, 0x9e, 0x46, 0xa7, 0x9f
02603 };
02604
02605 if (entry < 0)
02606 return 0;
02607
02608 avio_seek(pb, track->frag_info[entry].tfrf_offset, SEEK_SET);
02609 avio_wb32(pb, size);
02610 ffio_wfourcc(pb, "uuid");
02611 avio_write(pb, uuid, sizeof(uuid));
02612 avio_w8(pb, 1);
02613 avio_wb24(pb, 0);
02614 avio_w8(pb, n);
02615 for (i = 0; i < n; i++) {
02616 int index = entry + 1 + i;
02617 avio_wb64(pb, track->frag_info[index].time);
02618 avio_wb64(pb, track->frag_info[index].duration);
02619 }
02620 if (n < mov->ism_lookahead) {
02621 int free_size = 16*(mov->ism_lookahead - n);
02622 avio_wb32(pb, free_size);
02623 ffio_wfourcc(pb, "free");
02624 for (i = 0; i < free_size - 8; i++)
02625 avio_w8(pb, 0);
02626 }
02627
02628 return 0;
02629 }
02630
02631 static int mov_write_tfrf_tags(AVIOContext *pb, MOVMuxContext *mov,
02632 MOVTrack *track)
02633 {
02634 int64_t pos = avio_tell(pb);
02635 int i;
02636 for (i = 0; i < mov->ism_lookahead; i++) {
02637
02638
02639 mov_write_tfrf_tag(pb, mov, track, track->nb_frag_info - 2 - i);
02640 }
02641 avio_seek(pb, pos, SEEK_SET);
02642 return 0;
02643 }
02644
02645 static int mov_write_traf_tag(AVIOContext *pb, MOVMuxContext *mov,
02646 MOVTrack *track, int64_t moof_offset)
02647 {
02648 int64_t pos = avio_tell(pb);
02649 avio_wb32(pb, 0);
02650 ffio_wfourcc(pb, "traf");
02651
02652 mov_write_tfhd_tag(pb, track, moof_offset);
02653 mov_write_trun_tag(pb, track);
02654 if (mov->mode == MODE_ISM) {
02655 mov_write_tfxd_tag(pb, track);
02656
02657 if (mov->ism_lookahead) {
02658 int i, size = 16 + 4 + 1 + 16*mov->ism_lookahead;
02659
02660 track->tfrf_offset = avio_tell(pb);
02661 avio_wb32(pb, 8 + size);
02662 ffio_wfourcc(pb, "free");
02663 for (i = 0; i < size; i++)
02664 avio_w8(pb, 0);
02665 }
02666 }
02667
02668 return update_size(pb, pos);
02669 }
02670
02671 static int mov_write_moof_tag(AVIOContext *pb, MOVMuxContext *mov, int tracks)
02672 {
02673 int64_t pos = avio_tell(pb), end;
02674 int i, moof_size;
02675
02676 avio_wb32(pb, 0);
02677 ffio_wfourcc(pb, "moof");
02678
02679 mov_write_mfhd_tag(pb, mov);
02680 for (i = 0; i < mov->nb_streams; i++) {
02681 MOVTrack *track = &mov->tracks[i];
02682 if (tracks >= 0 && i != tracks)
02683 continue;
02684 if (!track->entry)
02685 continue;
02686 mov_write_traf_tag(pb, mov, track, pos);
02687 }
02688
02689 end = avio_tell(pb);
02690 moof_size = end - pos;
02691 for (i = 0; i < mov->nb_streams; i++) {
02692 MOVTrack *track = &mov->tracks[i];
02693 if (tracks >= 0 && i != tracks)
02694 continue;
02695 if (!track->entry)
02696 continue;
02697 avio_seek(pb, mov->tracks[i].moof_size_offset, SEEK_SET);
02698 avio_wb32(pb, moof_size + 8 + mov->tracks[i].data_offset);
02699 }
02700 avio_seek(pb, end, SEEK_SET);
02701
02702 return update_size(pb, pos);
02703 }
02704
02705 static int mov_write_tfra_tag(AVIOContext *pb, MOVTrack *track)
02706 {
02707 int64_t pos = avio_tell(pb);
02708 int i;
02709
02710 avio_wb32(pb, 0);
02711 ffio_wfourcc(pb, "tfra");
02712 avio_w8(pb, 1);
02713 avio_wb24(pb, 0);
02714
02715 avio_wb32(pb, track->track_id);
02716 avio_wb32(pb, 0);
02717 avio_wb32(pb, track->nb_frag_info);
02718 for (i = 0; i < track->nb_frag_info; i++) {
02719 avio_wb64(pb, track->frag_info[i].time);
02720 avio_wb64(pb, track->frag_info[i].offset);
02721 avio_w8(pb, 1);
02722 avio_w8(pb, 1);
02723 avio_w8(pb, 1);
02724 }
02725
02726 return update_size(pb, pos);
02727 }
02728
02729 static int mov_write_mfra_tag(AVIOContext *pb, MOVMuxContext *mov)
02730 {
02731 int64_t pos = avio_tell(pb);
02732 int i;
02733
02734 avio_wb32(pb, 0);
02735 ffio_wfourcc(pb, "mfra");
02736
02737
02738 if (mov->flags & FF_MOV_FLAG_ISML)
02739 return update_size(pb, pos);
02740
02741 for (i = 0; i < mov->nb_streams; i++) {
02742 MOVTrack *track = &mov->tracks[i];
02743 if (track->nb_frag_info)
02744 mov_write_tfra_tag(pb, track);
02745 }
02746
02747 avio_wb32(pb, 16);
02748 ffio_wfourcc(pb, "mfro");
02749 avio_wb32(pb, 0);
02750 avio_wb32(pb, avio_tell(pb) + 4 - pos);
02751
02752 return update_size(pb, pos);
02753 }
02754
02755 static int mov_write_mdat_tag(AVIOContext *pb, MOVMuxContext *mov)
02756 {
02757 avio_wb32(pb, 8);
02758 ffio_wfourcc(pb, mov->mode == MODE_MOV ? "wide" : "free");
02759
02760 mov->mdat_pos = avio_tell(pb);
02761 avio_wb32(pb, 0);
02762 ffio_wfourcc(pb, "mdat");
02763 return 0;
02764 }
02765
02766
02767 static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s)
02768 {
02769 MOVMuxContext *mov = s->priv_data;
02770 int64_t pos = avio_tell(pb);
02771 int has_h264 = 0, has_video = 0;
02772 int minor = 0x200;
02773 int i;
02774
02775 for (i = 0; i < s->nb_streams; i++) {
02776 AVStream *st = s->streams[i];
02777 if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
02778 has_video = 1;
02779 if (st->codec->codec_id == AV_CODEC_ID_H264)
02780 has_h264 = 1;
02781 }
02782
02783 avio_wb32(pb, 0);
02784 ffio_wfourcc(pb, "ftyp");
02785
02786 if (mov->mode == MODE_3GP) {
02787 ffio_wfourcc(pb, has_h264 ? "3gp6" : "3gp4");
02788 minor = has_h264 ? 0x100 : 0x200;
02789 } else if (mov->mode & MODE_3G2) {
02790 ffio_wfourcc(pb, has_h264 ? "3g2b" : "3g2a");
02791 minor = has_h264 ? 0x20000 : 0x10000;
02792 }else if (mov->mode == MODE_PSP)
02793 ffio_wfourcc(pb, "MSNV");
02794 else if (mov->mode == MODE_MP4)
02795 ffio_wfourcc(pb, "isom");
02796 else if (mov->mode == MODE_IPOD)
02797 ffio_wfourcc(pb, has_video ? "M4V ":"M4A ");
02798 else if (mov->mode == MODE_ISM)
02799 ffio_wfourcc(pb, "isml");
02800 else if (mov->mode == MODE_F4V)
02801 ffio_wfourcc(pb, "f4v ");
02802 else
02803 ffio_wfourcc(pb, "qt ");
02804
02805 avio_wb32(pb, minor);
02806
02807 if(mov->mode == MODE_MOV)
02808 ffio_wfourcc(pb, "qt ");
02809 else if (mov->mode == MODE_ISM) {
02810 ffio_wfourcc(pb, "piff");
02811 ffio_wfourcc(pb, "iso2");
02812 } else {
02813 ffio_wfourcc(pb, "isom");
02814 ffio_wfourcc(pb, "iso2");
02815 if(has_h264)
02816 ffio_wfourcc(pb, "avc1");
02817 }
02818
02819 if (mov->mode == MODE_3GP)
02820 ffio_wfourcc(pb, has_h264 ? "3gp6":"3gp4");
02821 else if (mov->mode & MODE_3G2)
02822 ffio_wfourcc(pb, has_h264 ? "3g2b":"3g2a");
02823 else if (mov->mode == MODE_PSP)
02824 ffio_wfourcc(pb, "MSNV");
02825 else if (mov->mode == MODE_MP4)
02826 ffio_wfourcc(pb, "mp41");
02827 return update_size(pb, pos);
02828 }
02829
02830 static void mov_write_uuidprof_tag(AVIOContext *pb, AVFormatContext *s)
02831 {
02832 AVCodecContext *video_codec = s->streams[0]->codec;
02833 AVCodecContext *audio_codec = s->streams[1]->codec;
02834 int audio_rate = audio_codec->sample_rate;
02835 int frame_rate = ((video_codec->time_base.den) * (0x10000))/ (video_codec->time_base.num);
02836 int audio_kbitrate = audio_codec->bit_rate / 1000;
02837 int video_kbitrate = FFMIN(video_codec->bit_rate / 1000, 800 - audio_kbitrate);
02838
02839 avio_wb32(pb, 0x94);
02840 ffio_wfourcc(pb, "uuid");
02841 ffio_wfourcc(pb, "PROF");
02842
02843 avio_wb32(pb, 0x21d24fce);
02844 avio_wb32(pb, 0xbb88695c);
02845 avio_wb32(pb, 0xfac9c740);
02846
02847 avio_wb32(pb, 0x0);
02848 avio_wb32(pb, 0x3);
02849
02850 avio_wb32(pb, 0x14);
02851 ffio_wfourcc(pb, "FPRF");
02852 avio_wb32(pb, 0x0);
02853 avio_wb32(pb, 0x0);
02854 avio_wb32(pb, 0x0);
02855
02856 avio_wb32(pb, 0x2c);
02857 ffio_wfourcc(pb, "APRF");
02858 avio_wb32(pb, 0x0);
02859 avio_wb32(pb, 0x2);
02860 ffio_wfourcc(pb, "mp4a");
02861 avio_wb32(pb, 0x20f);
02862 avio_wb32(pb, 0x0);
02863 avio_wb32(pb, audio_kbitrate);
02864 avio_wb32(pb, audio_kbitrate);
02865 avio_wb32(pb, audio_rate);
02866 avio_wb32(pb, audio_codec->channels);
02867
02868 avio_wb32(pb, 0x34);
02869 ffio_wfourcc(pb, "VPRF");
02870 avio_wb32(pb, 0x0);
02871 avio_wb32(pb, 0x1);
02872 if (video_codec->codec_id == AV_CODEC_ID_H264) {
02873 ffio_wfourcc(pb, "avc1");
02874 avio_wb16(pb, 0x014D);
02875 avio_wb16(pb, 0x0015);
02876 } else {
02877 ffio_wfourcc(pb, "mp4v");
02878 avio_wb16(pb, 0x0000);
02879 avio_wb16(pb, 0x0103);
02880 }
02881 avio_wb32(pb, 0x0);
02882 avio_wb32(pb, video_kbitrate);
02883 avio_wb32(pb, video_kbitrate);
02884 avio_wb32(pb, frame_rate);
02885 avio_wb32(pb, frame_rate);
02886 avio_wb16(pb, video_codec->width);
02887 avio_wb16(pb, video_codec->height);
02888 avio_wb32(pb, 0x010001);
02889 }
02890
02891 static int mov_parse_mpeg2_frame(AVPacket *pkt, uint32_t *flags)
02892 {
02893 uint32_t c = -1;
02894 int i, closed_gop = 0;
02895
02896 for (i = 0; i < pkt->size - 4; i++) {
02897 c = (c<<8) + pkt->data[i];
02898 if (c == 0x1b8) {
02899 closed_gop = pkt->data[i+4]>>6 & 0x01;
02900 } else if (c == 0x100) {
02901 int temp_ref = (pkt->data[i+1]<<2) | (pkt->data[i+2]>>6);
02902 if (!temp_ref || closed_gop)
02903 *flags = MOV_SYNC_SAMPLE;
02904 else
02905 *flags = MOV_PARTIAL_SYNC_SAMPLE;
02906 break;
02907 }
02908 }
02909 return 0;
02910 }
02911
02912 static void mov_parse_vc1_frame(AVPacket *pkt, MOVTrack *trk, int fragment)
02913 {
02914 const uint8_t *start, *next, *end = pkt->data + pkt->size;
02915 int seq = 0, entry = 0;
02916 int key = pkt->flags & AV_PKT_FLAG_KEY;
02917 start = find_next_marker(pkt->data, end);
02918 for (next = start; next < end; start = next) {
02919 next = find_next_marker(start + 4, end);
02920 switch (AV_RB32(start)) {
02921 case VC1_CODE_SEQHDR:
02922 seq = 1;
02923 break;
02924 case VC1_CODE_ENTRYPOINT:
02925 entry = 1;
02926 break;
02927 case VC1_CODE_SLICE:
02928 trk->vc1_info.slices = 1;
02929 break;
02930 }
02931 }
02932 if (!trk->entry && !fragment) {
02933
02934 trk->vc1_info.first_packet_seq = seq;
02935 trk->vc1_info.first_packet_entry = entry;
02936 } else if ((seq && !trk->vc1_info.packet_seq) ||
02937 (entry && !trk->vc1_info.packet_entry)) {
02938 int i;
02939 for (i = 0; i < trk->entry; i++)
02940 trk->cluster[i].flags &= ~MOV_SYNC_SAMPLE;
02941 trk->has_keyframes = 0;
02942 if (seq)
02943 trk->vc1_info.packet_seq = 1;
02944 if (entry)
02945 trk->vc1_info.packet_entry = 1;
02946 if (!fragment) {
02947
02948 if ((!seq || trk->vc1_info.first_packet_seq) &&
02949 (!entry || trk->vc1_info.first_packet_entry)) {
02950
02951
02952 trk->cluster[0].flags |= MOV_SYNC_SAMPLE;
02953 trk->has_keyframes = 1;
02954 }
02955 }
02956 }
02957 if (trk->vc1_info.packet_seq && trk->vc1_info.packet_entry)
02958 key = seq && entry;
02959 else if (trk->vc1_info.packet_seq)
02960 key = seq;
02961 else if (trk->vc1_info.packet_entry)
02962 key = entry;
02963 if (key) {
02964 trk->cluster[trk->entry].flags |= MOV_SYNC_SAMPLE;
02965 trk->has_keyframes++;
02966 }
02967 }
02968
02969 static int get_moov_size(AVFormatContext *s)
02970 {
02971 int ret;
02972 uint8_t *buf;
02973 AVIOContext *moov_buf;
02974 MOVMuxContext *mov = s->priv_data;
02975
02976 if ((ret = avio_open_dyn_buf(&moov_buf)) < 0)
02977 return ret;
02978 mov_write_moov_tag(moov_buf, mov, s);
02979 ret = avio_close_dyn_buf(moov_buf, &buf);
02980 av_free(buf);
02981 return ret;
02982 }
02983
02984 static int mov_flush_fragment(AVFormatContext *s)
02985 {
02986 MOVMuxContext *mov = s->priv_data;
02987 int i, first_track = -1;
02988 int64_t mdat_size = 0;
02989
02990 if (!(mov->flags & FF_MOV_FLAG_FRAGMENT))
02991 return 0;
02992
02993 if (!(mov->flags & FF_MOV_FLAG_EMPTY_MOOV) && mov->fragments == 0) {
02994 int64_t pos = avio_tell(s->pb);
02995 uint8_t *buf;
02996 int buf_size, moov_size;
02997
02998 for (i = 0; i < mov->nb_streams; i++)
02999 if (!mov->tracks[i].entry)
03000 break;
03001
03002 if (i < mov->nb_streams)
03003 return 0;
03004
03005 moov_size = get_moov_size(s);
03006 for (i = 0; i < mov->nb_streams; i++)
03007 mov->tracks[i].data_offset = pos + moov_size + 8;
03008
03009 mov_write_moov_tag(s->pb, mov, s);
03010
03011 buf_size = avio_close_dyn_buf(mov->mdat_buf, &buf);
03012 mov->mdat_buf = NULL;
03013 avio_wb32(s->pb, buf_size + 8);
03014 ffio_wfourcc(s->pb, "mdat");
03015 avio_write(s->pb, buf, buf_size);
03016 av_free(buf);
03017
03018 mov->fragments++;
03019 mov->mdat_size = 0;
03020 for (i = 0; i < mov->nb_streams; i++) {
03021 if (mov->tracks[i].entry)
03022 mov->tracks[i].frag_start += mov->tracks[i].start_dts +
03023 mov->tracks[i].track_duration -
03024 mov->tracks[i].cluster[0].dts;
03025 mov->tracks[i].entry = 0;
03026 }
03027 avio_flush(s->pb);
03028 return 0;
03029 }
03030
03031 for (i = 0; i < mov->nb_streams; i++) {
03032 MOVTrack *track = &mov->tracks[i];
03033 if (mov->flags & FF_MOV_FLAG_SEPARATE_MOOF)
03034 track->data_offset = 0;
03035 else
03036 track->data_offset = mdat_size;
03037 if (!track->mdat_buf)
03038 continue;
03039 mdat_size += avio_tell(track->mdat_buf);
03040 if (first_track < 0)
03041 first_track = i;
03042 }
03043
03044 if (!mdat_size)
03045 return 0;
03046
03047 for (i = 0; i < mov->nb_streams; i++) {
03048 MOVTrack *track = &mov->tracks[i];
03049 int buf_size, write_moof = 1, moof_tracks = -1;
03050 uint8_t *buf;
03051 int64_t duration = 0;
03052
03053 if (track->entry)
03054 duration = track->start_dts + track->track_duration -
03055 track->cluster[0].dts;
03056 if (mov->flags & FF_MOV_FLAG_SEPARATE_MOOF) {
03057 if (!track->mdat_buf)
03058 continue;
03059 mdat_size = avio_tell(track->mdat_buf);
03060 moof_tracks = i;
03061 } else {
03062 write_moof = i == first_track;
03063 }
03064
03065 if (write_moof) {
03066 MOVFragmentInfo *info;
03067 avio_flush(s->pb);
03068 track->nb_frag_info++;
03069 track->frag_info = av_realloc(track->frag_info,
03070 sizeof(*track->frag_info) *
03071 track->nb_frag_info);
03072 info = &track->frag_info[track->nb_frag_info - 1];
03073 info->offset = avio_tell(s->pb);
03074 info->time = mov->tracks[i].frag_start;
03075 info->duration = duration;
03076 mov_write_tfrf_tags(s->pb, mov, track);
03077
03078 mov_write_moof_tag(s->pb, mov, moof_tracks);
03079 info->tfrf_offset = track->tfrf_offset;
03080 mov->fragments++;
03081
03082 avio_wb32(s->pb, mdat_size + 8);
03083 ffio_wfourcc(s->pb, "mdat");
03084 }
03085
03086 if (track->entry)
03087 track->frag_start += duration;
03088 track->entry = 0;
03089 if (!track->mdat_buf)
03090 continue;
03091 buf_size = avio_close_dyn_buf(track->mdat_buf, &buf);
03092 track->mdat_buf = NULL;
03093
03094 avio_write(s->pb, buf, buf_size);
03095 av_free(buf);
03096 }
03097
03098 mov->mdat_size = 0;
03099
03100 avio_flush(s->pb);
03101 return 0;
03102 }
03103
03104 int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
03105 {
03106 MOVMuxContext *mov = s->priv_data;
03107 AVIOContext *pb = s->pb;
03108 MOVTrack *trk = &mov->tracks[pkt->stream_index];
03109 AVCodecContext *enc = trk->enc;
03110 unsigned int samples_in_chunk = 0;
03111 int size= pkt->size;
03112 uint8_t *reformatted_data = NULL;
03113
03114 if (mov->flags & FF_MOV_FLAG_FRAGMENT) {
03115 int ret;
03116 if (mov->fragments > 0) {
03117 if (!trk->mdat_buf) {
03118 if ((ret = avio_open_dyn_buf(&trk->mdat_buf)) < 0)
03119 return ret;
03120 }
03121 pb = trk->mdat_buf;
03122 } else {
03123 if (!mov->mdat_buf) {
03124 if ((ret = avio_open_dyn_buf(&mov->mdat_buf)) < 0)
03125 return ret;
03126 }
03127 pb = mov->mdat_buf;
03128 }
03129 }
03130
03131 if (enc->codec_id == AV_CODEC_ID_AMR_NB) {
03132
03133 static uint16_t packed_size[16] =
03134 {13, 14, 16, 18, 20, 21, 27, 32, 6, 0, 0, 0, 0, 0, 0, 1};
03135 int len = 0;
03136
03137 while (len < size && samples_in_chunk < 100) {
03138 len += packed_size[(pkt->data[len] >> 3) & 0x0F];
03139 samples_in_chunk++;
03140 }
03141 if (samples_in_chunk > 1) {
03142 av_log(s, AV_LOG_ERROR, "fatal error, input is not a single packet, implement a AVParser for it\n");
03143 return -1;
03144 }
03145 } else if (enc->codec_id == AV_CODEC_ID_ADPCM_MS ||
03146 enc->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) {
03147 samples_in_chunk = enc->frame_size;
03148 } else if (trk->sample_size)
03149 samples_in_chunk = size / trk->sample_size;
03150 else
03151 samples_in_chunk = 1;
03152
03153
03154 if (trk->vos_len == 0 && enc->extradata_size > 0) {
03155 trk->vos_len = enc->extradata_size;
03156 trk->vos_data = av_malloc(trk->vos_len);
03157 memcpy(trk->vos_data, enc->extradata, trk->vos_len);
03158 }
03159
03160 if (enc->codec_id == AV_CODEC_ID_H264 && trk->vos_len > 0 && *(uint8_t *)trk->vos_data != 1) {
03161
03162
03163 if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams) {
03164 ff_avc_parse_nal_units_buf(pkt->data, &reformatted_data,
03165 &size);
03166 avio_write(pb, reformatted_data, size);
03167 } else {
03168 size = ff_avc_parse_nal_units(pb, pkt->data, pkt->size);
03169 }
03170 } else if (enc->codec_id == AV_CODEC_ID_AAC && pkt->size > 2 &&
03171 (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) {
03172 av_log(s, AV_LOG_ERROR, "malformated aac bitstream, use -absf aac_adtstoasc\n");
03173 return -1;
03174 } else {
03175 avio_write(pb, pkt->data, size);
03176 }
03177
03178 if ((enc->codec_id == AV_CODEC_ID_DNXHD ||
03179 enc->codec_id == AV_CODEC_ID_AC3) && !trk->vos_len) {
03180
03181 trk->vos_len = size;
03182 trk->vos_data = av_malloc(size);
03183 if (!trk->vos_data)
03184 return AVERROR(ENOMEM);
03185 memcpy(trk->vos_data, pkt->data, size);
03186 }
03187
03188 if (!(trk->entry % MOV_INDEX_CLUSTER_SIZE)) {
03189 trk->cluster = av_realloc_f(trk->cluster, sizeof(*trk->cluster), (trk->entry + MOV_INDEX_CLUSTER_SIZE));
03190 if (!trk->cluster)
03191 return -1;
03192 }
03193
03194 trk->cluster[trk->entry].pos = avio_tell(pb) - size;
03195 trk->cluster[trk->entry].samples_in_chunk = samples_in_chunk;
03196 trk->cluster[trk->entry].chunkNum = 0;
03197 trk->cluster[trk->entry].size = size;
03198 trk->cluster[trk->entry].entries = samples_in_chunk;
03199 trk->cluster[trk->entry].dts = pkt->dts;
03200 if (!trk->entry && trk->start_dts != AV_NOPTS_VALUE) {
03201
03202
03203
03204
03205 trk->cluster[trk->entry].dts = trk->start_dts + trk->track_duration;
03206 }
03207 if (!trk->entry && trk->start_dts == AV_NOPTS_VALUE && !supports_edts(mov)) {
03208 trk->cluster[trk->entry].dts = trk->start_dts = 0;
03209 }
03210 if (trk->start_dts == AV_NOPTS_VALUE)
03211 trk->start_dts = pkt->dts;
03212 trk->track_duration = pkt->dts - trk->start_dts + pkt->duration;
03213 trk->last_sample_is_subtitle_end = 0;
03214
03215 if (pkt->pts == AV_NOPTS_VALUE) {
03216 av_log(s, AV_LOG_WARNING, "pts has no value\n");
03217 pkt->pts = pkt->dts;
03218 }
03219 if (pkt->dts != pkt->pts)
03220 trk->flags |= MOV_TRACK_CTTS;
03221 trk->cluster[trk->entry].cts = pkt->pts - pkt->dts;
03222 trk->cluster[trk->entry].flags = 0;
03223 if (enc->codec_id == AV_CODEC_ID_VC1) {
03224 mov_parse_vc1_frame(pkt, trk, mov->fragments);
03225 } else if (pkt->flags & AV_PKT_FLAG_KEY) {
03226 if (mov->mode == MODE_MOV && enc->codec_id == AV_CODEC_ID_MPEG2VIDEO &&
03227 trk->entry > 0) {
03228 mov_parse_mpeg2_frame(pkt, &trk->cluster[trk->entry].flags);
03229 if (trk->cluster[trk->entry].flags & MOV_PARTIAL_SYNC_SAMPLE)
03230 trk->flags |= MOV_TRACK_STPS;
03231 } else {
03232 trk->cluster[trk->entry].flags = MOV_SYNC_SAMPLE;
03233 }
03234 if (trk->cluster[trk->entry].flags & MOV_SYNC_SAMPLE)
03235 trk->has_keyframes++;
03236 }
03237 trk->entry++;
03238 trk->sample_count += samples_in_chunk;
03239 mov->mdat_size += size;
03240
03241 avio_flush(pb);
03242
03243 if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams)
03244 ff_mov_add_hinted_packet(s, pkt, trk->hint_track, trk->entry,
03245 reformatted_data, size);
03246 av_free(reformatted_data);
03247 return 0;
03248 }
03249
03250 static int mov_write_single_packet(AVFormatContext *s, AVPacket *pkt)
03251 {
03252 MOVMuxContext *mov = s->priv_data;
03253 MOVTrack *trk = &mov->tracks[pkt->stream_index];
03254 AVCodecContext *enc = trk->enc;
03255 int64_t frag_duration = 0;
03256 int size = pkt->size;
03257
03258 if (!pkt->size) return 0;
03259
03260 if (trk->entry && pkt->stream_index < s->nb_streams)
03261 frag_duration = av_rescale_q(pkt->dts - trk->cluster[0].dts,
03262 s->streams[pkt->stream_index]->time_base,
03263 AV_TIME_BASE_Q);
03264 if ((mov->max_fragment_duration &&
03265 frag_duration >= mov->max_fragment_duration) ||
03266 (mov->max_fragment_size && mov->mdat_size + size >= mov->max_fragment_size) ||
03267 (mov->flags & FF_MOV_FLAG_FRAG_KEYFRAME &&
03268 enc->codec_type == AVMEDIA_TYPE_VIDEO &&
03269 trk->entry && pkt->flags & AV_PKT_FLAG_KEY)) {
03270 if (frag_duration >= mov->min_fragment_duration)
03271 mov_flush_fragment(s);
03272 }
03273
03274 return ff_mov_write_packet(s, pkt);
03275 }
03276
03277 static int mov_write_subtitle_end_packet(AVFormatContext *s,
03278 int stream_index,
03279 int64_t dts) {
03280 AVPacket end;
03281 uint8_t data[2] = {0};
03282 int ret;
03283
03284 av_init_packet(&end);
03285 end.size = sizeof(data);
03286 end.data = data;
03287 end.pts = dts;
03288 end.dts = dts;
03289 end.duration = 0;
03290 end.stream_index = stream_index;
03291
03292 ret = mov_write_single_packet(s, &end);
03293 av_free_packet(&end);
03294
03295 return ret;
03296 }
03297
03298 static int mov_write_packet(AVFormatContext *s, AVPacket *pkt)
03299 {
03300 if (!pkt) {
03301 mov_flush_fragment(s);
03302 return 1;
03303 } else {
03304 int i;
03305 MOVMuxContext *mov = s->priv_data;
03306
03307 if (!pkt->size) return 0;
03308
03309
03310
03311
03312
03313
03314
03315
03316
03317
03318
03319
03320
03321
03322
03323
03324
03325
03326
03327
03328 for (i = 0; i < mov->nb_streams; i++) {
03329 MOVTrack *trk = &mov->tracks[i];
03330 int ret;
03331
03332 if (trk->enc->codec_id == AV_CODEC_ID_MOV_TEXT &&
03333 trk->track_duration < pkt->dts &&
03334 (trk->entry == 0 || !trk->last_sample_is_subtitle_end)) {
03335 ret = mov_write_subtitle_end_packet(s, i, trk->track_duration);
03336 if (ret < 0) return ret;
03337 trk->last_sample_is_subtitle_end = 1;
03338 }
03339 }
03340
03341 return mov_write_single_packet(s, pkt);
03342 }
03343 }
03344
03345
03346
03347 static void mov_create_chapter_track(AVFormatContext *s, int tracknum)
03348 {
03349 AVIOContext *pb;
03350
03351 MOVMuxContext *mov = s->priv_data;
03352 MOVTrack *track = &mov->tracks[tracknum];
03353 AVPacket pkt = { .stream_index = tracknum, .flags = AV_PKT_FLAG_KEY };
03354 int i, len;
03355
03356 track->mode = mov->mode;
03357 track->tag = MKTAG('t','e','x','t');
03358 track->timescale = MOV_TIMESCALE;
03359 track->enc = avcodec_alloc_context3(NULL);
03360 track->enc->codec_type = AVMEDIA_TYPE_SUBTITLE;
03361
03362 if (avio_open_dyn_buf(&pb) >= 0) {
03363 int size;
03364 uint8_t *buf;
03365
03366
03367
03368 avio_wb32(pb, 0x01);
03369 avio_w8(pb, 0x00);
03370 avio_w8(pb, 0x00);
03371 avio_w8(pb, 0x00);
03372 avio_w8(pb, 0x00);
03373 avio_w8(pb, 0x00);
03374 avio_w8(pb, 0x00);
03375
03376 avio_wb16(pb, 0x00);
03377 avio_wb16(pb, 0x00);
03378 avio_wb16(pb, 0x00);
03379 avio_wb16(pb, 0x00);
03380
03381 avio_wb16(pb, 0x00);
03382 avio_wb16(pb, 0x00);
03383 avio_wb16(pb, 0x01);
03384 avio_w8(pb, 0x00);
03385 avio_w8(pb, 0x00);
03386 avio_w8(pb, 0x00);
03387 avio_w8(pb, 0x00);
03388 avio_w8(pb, 0x00);
03389 avio_w8(pb, 0x00);
03390
03391 avio_wb32(pb, 0x0D);
03392 ffio_wfourcc(pb, "ftab");
03393 avio_wb16(pb, 0x01);
03394
03395 avio_wb16(pb, 0x01);
03396 avio_w8(pb, 0x00);
03397
03398 if ((size = avio_close_dyn_buf(pb, &buf)) > 0) {
03399 track->enc->extradata = buf;
03400 track->enc->extradata_size = size;
03401 } else {
03402 av_free(&buf);
03403 }
03404 }
03405
03406 for (i = 0; i < s->nb_chapters; i++) {
03407 AVChapter *c = s->chapters[i];
03408 AVDictionaryEntry *t;
03409
03410 int64_t end = av_rescale_q(c->end, c->time_base, (AVRational){1,MOV_TIMESCALE});
03411 pkt.pts = pkt.dts = av_rescale_q(c->start, c->time_base, (AVRational){1,MOV_TIMESCALE});
03412 pkt.duration = end - pkt.dts;
03413
03414 if ((t = av_dict_get(c->metadata, "title", NULL, 0))) {
03415 len = strlen(t->value);
03416 pkt.size = len+2;
03417 pkt.data = av_malloc(pkt.size);
03418 AV_WB16(pkt.data, len);
03419 memcpy(pkt.data+2, t->value, len);
03420 ff_mov_write_packet(s, &pkt);
03421 av_freep(&pkt.data);
03422 }
03423 }
03424 }
03425
03426 static int mov_create_timecode_track(AVFormatContext *s, int index, int src_index, const char *tcstr)
03427 {
03428 int ret;
03429 MOVMuxContext *mov = s->priv_data;
03430 MOVTrack *track = &mov->tracks[index];
03431 AVStream *src_st = s->streams[src_index];
03432 AVTimecode tc;
03433 AVPacket pkt = {.stream_index = index, .flags = AV_PKT_FLAG_KEY, .size = 4};
03434 AVRational rate = {src_st->codec->time_base.den, src_st->codec->time_base.num};
03435
03436
03437 if (av_timecode_check_frame_rate(rate) < 0) {
03438 av_log(s, AV_LOG_DEBUG, "timecode: tbc=%d/%d invalid, fallback on %d/%d\n",
03439 rate.num, rate.den, src_st->avg_frame_rate.num, src_st->avg_frame_rate.den);
03440 rate = src_st->avg_frame_rate;
03441 }
03442
03443
03444 ret = av_timecode_init_from_string(&tc, rate, tcstr, s);
03445 if (ret < 0)
03446 return ret;
03447
03448
03449 track->mode = mov->mode;
03450 track->tag = MKTAG('t','m','c','d');
03451 track->src_track = src_index;
03452 track->timescale = mov->tracks[src_index].timescale;
03453 if (tc.flags & AV_TIMECODE_FLAG_DROPFRAME)
03454 track->timecode_flags |= MOV_TIMECODE_FLAG_DROPFRAME;
03455
03456
03457 track->enc = avcodec_alloc_context3(NULL);
03458 track->enc->codec_type = AVMEDIA_TYPE_DATA;
03459 track->enc->codec_tag = track->tag;
03460 track->enc->time_base = src_st->codec->time_base;
03461
03462
03463 pkt.data = av_malloc(pkt.size);
03464 AV_WB32(pkt.data, tc.start);
03465 ret = ff_mov_write_packet(s, &pkt);
03466 av_free(pkt.data);
03467 return ret;
03468 }
03469
03470 static int mov_write_header(AVFormatContext *s)
03471 {
03472 AVIOContext *pb = s->pb;
03473 MOVMuxContext *mov = s->priv_data;
03474 AVDictionaryEntry *t, *global_tcr = av_dict_get(s->metadata, "timecode", NULL, 0);
03475 int i, hint_track = 0, tmcd_track = 0;
03476
03477
03478
03479 if (mov->max_fragment_duration || mov->max_fragment_size ||
03480 mov->flags & (FF_MOV_FLAG_EMPTY_MOOV |
03481 FF_MOV_FLAG_FRAG_KEYFRAME |
03482 FF_MOV_FLAG_FRAG_CUSTOM))
03483 mov->flags |= FF_MOV_FLAG_FRAGMENT;
03484
03485
03486 if (mov->flags & FF_MOV_FLAG_FASTSTART) {
03487 if (mov->flags & FF_MOV_FLAG_FRAGMENT)
03488 mov->flags &= ~FF_MOV_FLAG_FASTSTART;
03489 else
03490 mov->reserved_moov_size = -1;
03491 }
03492
03493 if (!supports_edts(mov) && s->avoid_negative_ts < 0) {
03494 s->avoid_negative_ts = 1;
03495 }
03496
03497
03498
03499 if (!s->pb->seekable &&
03500 ((!(mov->flags & FF_MOV_FLAG_FRAGMENT) &&
03501 !(s->oformat && !strcmp(s->oformat->name, "ismv")))
03502 || mov->ism_lookahead)) {
03503 av_log(s, AV_LOG_ERROR, "muxer does not support non seekable output\n");
03504 return -1;
03505 }
03506
03507
03508 mov->mode = MODE_MP4;
03509
03510 if (s->oformat != NULL) {
03511 if (!strcmp("3gp", s->oformat->name)) mov->mode = MODE_3GP;
03512 else if (!strcmp("3g2", s->oformat->name)) mov->mode = MODE_3GP|MODE_3G2;
03513 else if (!strcmp("mov", s->oformat->name)) mov->mode = MODE_MOV;
03514 else if (!strcmp("psp", s->oformat->name)) mov->mode = MODE_PSP;
03515 else if (!strcmp("ipod",s->oformat->name)) mov->mode = MODE_IPOD;
03516 else if (!strcmp("ismv",s->oformat->name)) mov->mode = MODE_ISM;
03517 else if (!strcmp("f4v", s->oformat->name)) mov->mode = MODE_F4V;
03518
03519 mov_write_ftyp_tag(pb,s);
03520 if (mov->mode == MODE_PSP) {
03521 if (s->nb_streams != 2) {
03522 av_log(s, AV_LOG_ERROR, "PSP mode need one video and one audio stream\n");
03523 return -1;
03524 }
03525 mov_write_uuidprof_tag(pb,s);
03526 }
03527 }
03528
03529 mov->nb_streams = s->nb_streams;
03530 if (mov->mode & (MODE_MOV|MODE_IPOD) && s->nb_chapters)
03531 mov->chapter_track = mov->nb_streams++;
03532
03533 if (mov->flags & FF_MOV_FLAG_RTP_HINT) {
03534
03535 hint_track = mov->nb_streams;
03536 for (i = 0; i < s->nb_streams; i++) {
03537 AVStream *st = s->streams[i];
03538 if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO ||
03539 st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
03540 mov->nb_streams++;
03541 }
03542 }
03543 }
03544
03545 if (mov->mode == MODE_MOV) {
03546 tmcd_track = mov->nb_streams;
03547
03548
03549 for (i = 0; i < s->nb_streams; i++) {
03550 AVStream *st = s->streams[i];
03551 if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
03552 (global_tcr || av_dict_get(st->metadata, "timecode", NULL, 0)))
03553 mov->nb_meta_tmcd++;
03554 }
03555
03556
03557 if (mov->nb_meta_tmcd) {
03558 for (i = 0; i < s->nb_streams; i++) {
03559 AVStream *st = s->streams[i];
03560 if (st->codec->codec_tag == MKTAG('t','m','c','d')) {
03561 av_log(s, AV_LOG_WARNING, "You requested a copy of the original timecode track "
03562 "so timecode metadata are now ignored\n");
03563 mov->nb_meta_tmcd = 0;
03564 }
03565 }
03566 }
03567
03568 mov->nb_streams += mov->nb_meta_tmcd;
03569 }
03570
03571 mov->tracks = av_mallocz(mov->nb_streams*sizeof(*mov->tracks));
03572 if (!mov->tracks)
03573 return AVERROR(ENOMEM);
03574
03575 for(i=0; i<s->nb_streams; i++){
03576 AVStream *st= s->streams[i];
03577 MOVTrack *track= &mov->tracks[i];
03578 AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL,0);
03579
03580 track->enc = st->codec;
03581 track->language = ff_mov_iso639_to_lang(lang?lang->value:"und", mov->mode!=MODE_MOV);
03582 if (track->language < 0)
03583 track->language = 0;
03584 track->mode = mov->mode;
03585 track->tag = mov_find_codec_tag(s, track);
03586 if (!track->tag) {
03587 av_log(s, AV_LOG_ERROR, "track %d: could not find tag, "
03588 "codec not currently supported in container\n", i);
03589 goto error;
03590 }
03591
03592
03593 track->hint_track = -1;
03594 track->start_dts = AV_NOPTS_VALUE;
03595 if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO){
03596 if (track->tag == MKTAG('m','x','3','p') || track->tag == MKTAG('m','x','3','n') ||
03597 track->tag == MKTAG('m','x','4','p') || track->tag == MKTAG('m','x','4','n') ||
03598 track->tag == MKTAG('m','x','5','p') || track->tag == MKTAG('m','x','5','n')) {
03599 if (st->codec->width != 720 || (st->codec->height != 608 && st->codec->height != 512)) {
03600 av_log(s, AV_LOG_ERROR, "D-10/IMX must use 720x608 or 720x512 video resolution\n");
03601 goto error;
03602 }
03603 track->height = track->tag>>24 == 'n' ? 486 : 576;
03604 }
03605 track->timescale = st->codec->time_base.den;
03606 while(track->timescale < 10000)
03607 track->timescale *= 2;
03608 if (track->mode == MODE_MOV && track->timescale > 100000)
03609 av_log(s, AV_LOG_WARNING,
03610 "WARNING codec timebase is very high. If duration is too long,\n"
03611 "file may not be playable by quicktime. Specify a shorter timebase\n"
03612 "or choose different container.\n");
03613 }else if(st->codec->codec_type == AVMEDIA_TYPE_AUDIO){
03614 track->timescale = st->codec->sample_rate;
03615 if(!st->codec->frame_size && !av_get_bits_per_sample(st->codec->codec_id)) {
03616 av_log(s, AV_LOG_WARNING, "track %d: codec frame size is not set\n", i);
03617 track->audio_vbr = 1;
03618 }else if(st->codec->codec_id == AV_CODEC_ID_ADPCM_MS ||
03619 st->codec->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV ||
03620 st->codec->codec_id == AV_CODEC_ID_ILBC){
03621 if (!st->codec->block_align) {
03622 av_log(s, AV_LOG_ERROR, "track %d: codec block align is not set for adpcm\n", i);
03623 goto error;
03624 }
03625 track->sample_size = st->codec->block_align;
03626 }else if(st->codec->frame_size > 1){
03627 track->audio_vbr = 1;
03628 }else{
03629 track->sample_size = (av_get_bits_per_sample(st->codec->codec_id) >> 3) * st->codec->channels;
03630 }
03631 if (track->mode != MODE_MOV &&
03632 track->enc->codec_id == AV_CODEC_ID_MP3 && track->timescale < 16000) {
03633 av_log(s, AV_LOG_ERROR, "track %d: muxing mp3 at %dhz is not supported\n",
03634 i, track->enc->sample_rate);
03635 goto error;
03636 }
03637 }else if(st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE){
03638 track->timescale = st->codec->time_base.den;
03639 }else{
03640 track->timescale = MOV_TIMESCALE;
03641 }
03642 if (!track->height)
03643 track->height = st->codec->height;
03644
03645
03646 if (mov->mode == MODE_ISM)
03647 track->timescale = 10000000;
03648
03649 avpriv_set_pts_info(st, 64, 1, track->timescale);
03650
03651
03652 if (st->codec->extradata_size) {
03653 track->vos_len = st->codec->extradata_size;
03654 track->vos_data = av_malloc(track->vos_len);
03655 memcpy(track->vos_data, st->codec->extradata, track->vos_len);
03656 }
03657 }
03658
03659 if (mov->mode == MODE_ISM) {
03660
03661 if (!(mov->flags & (FF_MOV_FLAG_FRAG_KEYFRAME |
03662 FF_MOV_FLAG_FRAG_CUSTOM)) &&
03663 !mov->max_fragment_duration && !mov->max_fragment_size)
03664 mov->max_fragment_duration = 5000000;
03665 mov->flags |= FF_MOV_FLAG_EMPTY_MOOV | FF_MOV_FLAG_SEPARATE_MOOF |
03666 FF_MOV_FLAG_FRAGMENT;
03667 }
03668
03669 if(mov->reserved_moov_size){
03670 mov->reserved_moov_pos= avio_tell(pb);
03671 if (mov->reserved_moov_size > 0)
03672 avio_skip(pb, mov->reserved_moov_size);
03673 }
03674
03675 if (!(mov->flags & FF_MOV_FLAG_FRAGMENT))
03676 mov_write_mdat_tag(pb, mov);
03677
03678 if (t = av_dict_get(s->metadata, "creation_time", NULL, 0))
03679 mov->time = ff_iso8601_to_unix_time(t->value);
03680 if (mov->time)
03681 mov->time += 0x7C25B080;
03682
03683 if (mov->chapter_track)
03684 mov_create_chapter_track(s, mov->chapter_track);
03685
03686 if (mov->flags & FF_MOV_FLAG_RTP_HINT) {
03687
03688 for (i = 0; i < s->nb_streams; i++) {
03689 AVStream *st = s->streams[i];
03690 if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO ||
03691 st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
03692 ff_mov_init_hinting(s, hint_track, i);
03693 hint_track++;
03694 }
03695 }
03696 }
03697
03698 if (mov->nb_meta_tmcd) {
03699
03700 for (i = 0; i < s->nb_streams; i++) {
03701 AVStream *st = s->streams[i];
03702 t = global_tcr;
03703
03704 if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
03705 if (!t)
03706 t = av_dict_get(st->metadata, "timecode", NULL, 0);
03707 if (!t)
03708 continue;
03709 if (mov_create_timecode_track(s, tmcd_track, i, t->value) < 0)
03710 goto error;
03711 tmcd_track++;
03712 }
03713 }
03714 }
03715
03716 avio_flush(pb);
03717
03718 if (mov->flags & FF_MOV_FLAG_ISML)
03719 mov_write_isml_manifest(pb, mov);
03720
03721 if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV) {
03722 mov_write_moov_tag(pb, mov, s);
03723 mov->fragments++;
03724 }
03725
03726 return 0;
03727 error:
03728 av_freep(&mov->tracks);
03729 return -1;
03730 }
03731
03738 static int compute_moov_size(AVFormatContext *s)
03739 {
03740 int i, moov_size, moov_size2;
03741 MOVMuxContext *mov = s->priv_data;
03742
03743 moov_size = get_moov_size(s);
03744 if (moov_size < 0)
03745 return moov_size;
03746
03747 for (i = 0; i < mov->nb_streams; i++)
03748 mov->tracks[i].data_offset += moov_size;
03749
03750 moov_size2 = get_moov_size(s);
03751 if (moov_size2 < 0)
03752 return moov_size2;
03753
03754
03755
03756 if (moov_size2 != moov_size)
03757 for (i = 0; i < mov->nb_streams; i++)
03758 mov->tracks[i].data_offset += moov_size2 - moov_size;
03759
03760 return moov_size2;
03761 }
03762
03763 static int shift_data(AVFormatContext *s)
03764 {
03765 int ret = 0, moov_size;
03766 MOVMuxContext *mov = s->priv_data;
03767 int64_t pos, pos_end = avio_tell(s->pb);
03768 uint8_t *buf, *read_buf[2];
03769 int read_buf_id = 0;
03770 int read_size[2];
03771 AVIOContext *read_pb;
03772
03773 moov_size = compute_moov_size(s);
03774 if (moov_size < 0)
03775 return moov_size;
03776
03777 buf = av_malloc(moov_size * 2);
03778 if (!buf)
03779 return AVERROR(ENOMEM);
03780 read_buf[0] = buf;
03781 read_buf[1] = buf + moov_size;
03782
03783
03784
03785
03786 avio_flush(s->pb);
03787 ret = avio_open(&read_pb, s->filename, AVIO_FLAG_READ);
03788 if (ret < 0) {
03789 av_log(s, AV_LOG_ERROR, "Unable to re-open %s output file for "
03790 "the second pass (faststart)\n", s->filename);
03791 goto end;
03792 }
03793
03794
03795
03796 pos_end = avio_tell(s->pb);
03797 avio_seek(s->pb, mov->reserved_moov_pos + moov_size, SEEK_SET);
03798
03799
03800 avio_seek(read_pb, mov->reserved_moov_pos, SEEK_SET);
03801 pos = avio_tell(read_pb);
03802
03803 #define READ_BLOCK do { \
03804 read_size[read_buf_id] = avio_read(read_pb, read_buf[read_buf_id], moov_size); \
03805 read_buf_id ^= 1; \
03806 } while (0)
03807
03808
03809 READ_BLOCK;
03810 do {
03811 int n;
03812 READ_BLOCK;
03813 n = read_size[read_buf_id];
03814 if (n <= 0)
03815 break;
03816 avio_write(s->pb, read_buf[read_buf_id], n);
03817 pos += n;
03818 } while (pos < pos_end);
03819 avio_close(read_pb);
03820
03821 end:
03822 av_free(buf);
03823 return ret;
03824 }
03825
03826 static int mov_write_trailer(AVFormatContext *s)
03827 {
03828 MOVMuxContext *mov = s->priv_data;
03829 AVIOContext *pb = s->pb;
03830 int64_t moov_pos;
03831 int res = 0;
03832 int i;
03833
03834
03835
03836
03837
03838 for (i = 0; i < mov->nb_streams; i++) {
03839 MOVTrack *trk = &mov->tracks[i];
03840 if (trk->enc->codec_id == AV_CODEC_ID_MOV_TEXT &&
03841 !trk->last_sample_is_subtitle_end) {
03842 mov_write_subtitle_end_packet(s, i, trk->track_duration);
03843 trk->last_sample_is_subtitle_end = 1;
03844 }
03845 }
03846
03847 moov_pos = avio_tell(pb);
03848
03849 if (!(mov->flags & FF_MOV_FLAG_FRAGMENT)) {
03850
03851 if (mov->mdat_size + 8 <= UINT32_MAX) {
03852 avio_seek(pb, mov->mdat_pos, SEEK_SET);
03853 avio_wb32(pb, mov->mdat_size + 8);
03854 } else {
03855
03856 avio_seek(pb, mov->mdat_pos - 8, SEEK_SET);
03857
03858
03859 avio_wb32(pb, 1);
03860 ffio_wfourcc(pb, "mdat");
03861 avio_wb64(pb, mov->mdat_size + 16);
03862 }
03863 avio_seek(pb, mov->reserved_moov_size > 0 ? mov->reserved_moov_pos : moov_pos, SEEK_SET);
03864
03865 if (mov->reserved_moov_size == -1) {
03866 av_log(s, AV_LOG_INFO, "Starting second pass: moving header on top of the file\n");
03867 res = shift_data(s);
03868 if (res == 0) {
03869 avio_seek(s->pb, mov->reserved_moov_pos, SEEK_SET);
03870 mov_write_moov_tag(pb, mov, s);
03871 }
03872 } else if (mov->reserved_moov_size > 0) {
03873 int64_t size;
03874 mov_write_moov_tag(pb, mov, s);
03875 size = mov->reserved_moov_size - (avio_tell(pb) - mov->reserved_moov_pos);
03876 if(size < 8){
03877 av_log(s, AV_LOG_ERROR, "reserved_moov_size is too small, needed %"PRId64" additional\n", 8-size);
03878 return -1;
03879 }
03880 avio_wb32(pb, size);
03881 ffio_wfourcc(pb, "free");
03882 for(i=0; i<size; i++)
03883 avio_w8(pb, 0);
03884 avio_seek(pb, moov_pos, SEEK_SET);
03885 } else {
03886 mov_write_moov_tag(pb, mov, s);
03887 }
03888 } else {
03889 mov_flush_fragment(s);
03890 mov_write_mfra_tag(pb, mov);
03891 }
03892
03893 if (mov->chapter_track)
03894 av_freep(&mov->tracks[mov->chapter_track].enc);
03895
03896 for (i=0; i<mov->nb_streams; i++) {
03897 if (mov->tracks[i].tag == MKTAG('r','t','p',' '))
03898 ff_mov_close_hinting(&mov->tracks[i]);
03899 else if (mov->tracks[i].tag == MKTAG('t','m','c','d') && mov->nb_meta_tmcd)
03900 av_freep(&mov->tracks[i].enc);
03901 if (mov->flags & FF_MOV_FLAG_FRAGMENT &&
03902 mov->tracks[i].vc1_info.struct_offset && s->pb->seekable) {
03903 int64_t off = avio_tell(pb);
03904 uint8_t buf[7];
03905 if (mov_write_dvc1_structs(&mov->tracks[i], buf) >= 0) {
03906 avio_seek(pb, mov->tracks[i].vc1_info.struct_offset, SEEK_SET);
03907 avio_write(pb, buf, 7);
03908 avio_seek(pb, off, SEEK_SET);
03909 }
03910 }
03911 av_freep(&mov->tracks[i].cluster);
03912 av_freep(&mov->tracks[i].frag_info);
03913
03914 if (mov->tracks[i].vos_len)
03915 av_free(mov->tracks[i].vos_data);
03916
03917 }
03918
03919 av_freep(&mov->tracks);
03920
03921 return res;
03922 }
03923
03924 #if CONFIG_MOV_MUXER
03925 MOV_CLASS(mov)
03926 AVOutputFormat ff_mov_muxer = {
03927 .name = "mov",
03928 .long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
03929 .extensions = "mov",
03930 .priv_data_size = sizeof(MOVMuxContext),
03931 .audio_codec = AV_CODEC_ID_AAC,
03932 .video_codec = CONFIG_LIBX264_ENCODER ?
03933 AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4,
03934 .write_header = mov_write_header,
03935 .write_packet = mov_write_packet,
03936 .write_trailer = mov_write_trailer,
03937 .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH,
03938 .codec_tag = (const AVCodecTag* const []){
03939 ff_codec_movvideo_tags, ff_codec_movaudio_tags, 0
03940 },
03941 .priv_class = &mov_muxer_class,
03942 };
03943 #endif
03944 #if CONFIG_TGP_MUXER
03945 MOV_CLASS(tgp)
03946 AVOutputFormat ff_tgp_muxer = {
03947 .name = "3gp",
03948 .long_name = NULL_IF_CONFIG_SMALL("3GP (3GPP file format)"),
03949 .extensions = "3gp",
03950 .priv_data_size = sizeof(MOVMuxContext),
03951 .audio_codec = AV_CODEC_ID_AMR_NB,
03952 .video_codec = AV_CODEC_ID_H263,
03953 .write_header = mov_write_header,
03954 .write_packet = mov_write_packet,
03955 .write_trailer = mov_write_trailer,
03956 .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH,
03957 .codec_tag = (const AVCodecTag* const []){ codec_3gp_tags, 0 },
03958 .priv_class = &tgp_muxer_class,
03959 };
03960 #endif
03961 #if CONFIG_MP4_MUXER
03962 MOV_CLASS(mp4)
03963 AVOutputFormat ff_mp4_muxer = {
03964 .name = "mp4",
03965 .long_name = NULL_IF_CONFIG_SMALL("MP4 (MPEG-4 Part 14)"),
03966 .mime_type = "application/mp4",
03967 .extensions = "mp4",
03968 .priv_data_size = sizeof(MOVMuxContext),
03969 .audio_codec = AV_CODEC_ID_AAC,
03970 .video_codec = CONFIG_LIBX264_ENCODER ?
03971 AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4,
03972 .write_header = mov_write_header,
03973 .write_packet = mov_write_packet,
03974 .write_trailer = mov_write_trailer,
03975 .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH,
03976 .codec_tag = (const AVCodecTag* const []){ ff_mp4_obj_type, 0 },
03977 .priv_class = &mp4_muxer_class,
03978 };
03979 #endif
03980 #if CONFIG_PSP_MUXER
03981 MOV_CLASS(psp)
03982 AVOutputFormat ff_psp_muxer = {
03983 .name = "psp",
03984 .long_name = NULL_IF_CONFIG_SMALL("PSP MP4 (MPEG-4 Part 14)"),
03985 .extensions = "mp4,psp",
03986 .priv_data_size = sizeof(MOVMuxContext),
03987 .audio_codec = AV_CODEC_ID_AAC,
03988 .video_codec = CONFIG_LIBX264_ENCODER ?
03989 AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4,
03990 .write_header = mov_write_header,
03991 .write_packet = mov_write_packet,
03992 .write_trailer = mov_write_trailer,
03993 .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH,
03994 .codec_tag = (const AVCodecTag* const []){ ff_mp4_obj_type, 0 },
03995 .priv_class = &psp_muxer_class,
03996 };
03997 #endif
03998 #if CONFIG_TG2_MUXER
03999 MOV_CLASS(tg2)
04000 AVOutputFormat ff_tg2_muxer = {
04001 .name = "3g2",
04002 .long_name = NULL_IF_CONFIG_SMALL("3GP2 (3GPP2 file format)"),
04003 .extensions = "3g2",
04004 .priv_data_size = sizeof(MOVMuxContext),
04005 .audio_codec = AV_CODEC_ID_AMR_NB,
04006 .video_codec = AV_CODEC_ID_H263,
04007 .write_header = mov_write_header,
04008 .write_packet = mov_write_packet,
04009 .write_trailer = mov_write_trailer,
04010 .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH,
04011 .codec_tag = (const AVCodecTag* const []){ codec_3gp_tags, 0 },
04012 .priv_class = &tg2_muxer_class,
04013 };
04014 #endif
04015 #if CONFIG_IPOD_MUXER
04016 MOV_CLASS(ipod)
04017 AVOutputFormat ff_ipod_muxer = {
04018 .name = "ipod",
04019 .long_name = NULL_IF_CONFIG_SMALL("iPod H.264 MP4 (MPEG-4 Part 14)"),
04020 .mime_type = "application/mp4",
04021 .extensions = "m4v,m4a",
04022 .priv_data_size = sizeof(MOVMuxContext),
04023 .audio_codec = AV_CODEC_ID_AAC,
04024 .video_codec = AV_CODEC_ID_H264,
04025 .write_header = mov_write_header,
04026 .write_packet = mov_write_packet,
04027 .write_trailer = mov_write_trailer,
04028 .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH,
04029 .codec_tag = (const AVCodecTag* const []){ codec_ipod_tags, 0 },
04030 .priv_class = &ipod_muxer_class,
04031 };
04032 #endif
04033 #if CONFIG_ISMV_MUXER
04034 MOV_CLASS(ismv)
04035 AVOutputFormat ff_ismv_muxer = {
04036 .name = "ismv",
04037 .long_name = NULL_IF_CONFIG_SMALL("ISMV/ISMA (Smooth Streaming)"),
04038 .mime_type = "application/mp4",
04039 .extensions = "ismv,isma",
04040 .priv_data_size = sizeof(MOVMuxContext),
04041 .audio_codec = AV_CODEC_ID_AAC,
04042 .video_codec = AV_CODEC_ID_H264,
04043 .write_header = mov_write_header,
04044 .write_packet = mov_write_packet,
04045 .write_trailer = mov_write_trailer,
04046 .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH,
04047 .codec_tag = (const AVCodecTag* const []){ ff_mp4_obj_type, 0 },
04048 .priv_class = &ismv_muxer_class,
04049 };
04050 #endif
04051 #if CONFIG_F4V_MUXER
04052 MOV_CLASS(f4v)
04053 AVOutputFormat ff_f4v_muxer = {
04054 .name = "f4v",
04055 .long_name = NULL_IF_CONFIG_SMALL("F4V Adobe Flash Video"),
04056 .mime_type = "application/f4v",
04057 .extensions = "f4v",
04058 .priv_data_size = sizeof(MOVMuxContext),
04059 .audio_codec = AV_CODEC_ID_AAC,
04060 .video_codec = AV_CODEC_ID_H264,
04061 .write_header = mov_write_header,
04062 .write_packet = mov_write_packet,
04063 .write_trailer = mov_write_trailer,
04064 .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH,
04065 .codec_tag = (const AVCodecTag* const []){ codec_f4v_tags, 0 },
04066 .priv_class = &f4v_muxer_class,
04067 };
04068 #endif