00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "avformat.h"
00023 #include "riff.h"
00024 #include "avio.h"
00025 #include "isom.h"
00026
00027 #undef NDEBUG
00028 #include <assert.h>
00029
00030 #define MOV_INDEX_CLUSTER_SIZE 16384
00031 #define globalTimescale 1000
00032
00033 #define MODE_MP4 0
00034 #define MODE_MOV 1
00035 #define MODE_3GP 2
00036 #define MODE_PSP 3 // example working PSP command line:
00037
00038 #define MODE_3G2 4
00039
00040 typedef struct MOVIentry {
00041 unsigned int flags, size;
00042 uint64_t pos;
00043 unsigned int samplesInChunk;
00044 char key_frame;
00045 unsigned int entries;
00046 int64_t cts;
00047 int64_t dts;
00048 } MOVIentry;
00049
00050 typedef struct MOVIndex {
00051 int mode;
00052 int entry;
00053 long timescale;
00054 long time;
00055 int64_t trackDuration;
00056 long sampleCount;
00057 long sampleSize;
00058 int hasKeyframes;
00059 int hasBframes;
00060 int language;
00061 int trackID;
00062 int tag;
00063 AVCodecContext *enc;
00064
00065 int vosLen;
00066 uint8_t *vosData;
00067 MOVIentry *cluster;
00068 int audio_vbr;
00069 } MOVTrack;
00070
00071 typedef struct MOVContext {
00072 int mode;
00073 int64_t time;
00074 int nb_streams;
00075 offset_t mdat_pos;
00076 uint64_t mdat_size;
00077 long timescale;
00078 MOVTrack tracks[MAX_STREAMS];
00079 } MOVContext;
00080
00081
00082 static offset_t updateSize (ByteIOContext *pb, offset_t pos)
00083 {
00084 offset_t curpos = url_ftell(pb);
00085 url_fseek(pb, pos, SEEK_SET);
00086 put_be32(pb, curpos - pos);
00087 url_fseek(pb, curpos, SEEK_SET);
00088
00089 return curpos - pos;
00090 }
00091
00092
00093 static int mov_write_stco_tag(ByteIOContext *pb, MOVTrack* track)
00094 {
00095 int i;
00096 int mode64 = 0;
00097 offset_t pos = url_ftell(pb);
00098 put_be32(pb, 0);
00099 if (pos > UINT32_MAX) {
00100 mode64 = 1;
00101 put_tag(pb, "co64");
00102 } else
00103 put_tag(pb, "stco");
00104 put_be32(pb, 0);
00105 put_be32(pb, track->entry);
00106 for (i=0; i<track->entry; i++) {
00107 if(mode64 == 1)
00108 put_be64(pb, track->cluster[i].pos);
00109 else
00110 put_be32(pb, track->cluster[i].pos);
00111 }
00112 return updateSize (pb, pos);
00113 }
00114
00115
00116 static int mov_write_stsz_tag(ByteIOContext *pb, MOVTrack* track)
00117 {
00118 int equalChunks = 1;
00119 int i, j, entries = 0, tst = -1, oldtst = -1;
00120
00121 offset_t pos = url_ftell(pb);
00122 put_be32(pb, 0);
00123 put_tag(pb, "stsz");
00124 put_be32(pb, 0);
00125
00126 for (i=0; i<track->entry; i++) {
00127 tst = track->cluster[i].size/track->cluster[i].entries;
00128 if(oldtst != -1 && tst != oldtst) {
00129 equalChunks = 0;
00130 }
00131 oldtst = tst;
00132 entries += track->cluster[i].entries;
00133 }
00134 if (equalChunks) {
00135 int sSize = track->cluster[0].size/track->cluster[0].entries;
00136 put_be32(pb, sSize);
00137 put_be32(pb, entries);
00138 }
00139 else {
00140 put_be32(pb, 0);
00141 put_be32(pb, entries);
00142 for (i=0; i<track->entry; i++) {
00143 for ( j=0; j<track->cluster[i].entries; j++) {
00144 put_be32(pb, track->cluster[i].size /
00145 track->cluster[i].entries);
00146 }
00147 }
00148 }
00149 return updateSize (pb, pos);
00150 }
00151
00152
00153 static int mov_write_stsc_tag(ByteIOContext *pb, MOVTrack* track)
00154 {
00155 int index = 0, oldval = -1, i;
00156 offset_t entryPos, curpos;
00157
00158 offset_t pos = url_ftell(pb);
00159 put_be32(pb, 0);
00160 put_tag(pb, "stsc");
00161 put_be32(pb, 0);
00162 entryPos = url_ftell(pb);
00163 put_be32(pb, track->entry);
00164 for (i=0; i<track->entry; i++) {
00165 if(oldval != track->cluster[i].samplesInChunk)
00166 {
00167 put_be32(pb, i+1);
00168 put_be32(pb, track->cluster[i].samplesInChunk);
00169 put_be32(pb, 0x1);
00170 oldval = track->cluster[i].samplesInChunk;
00171 index++;
00172 }
00173 }
00174 curpos = url_ftell(pb);
00175 url_fseek(pb, entryPos, SEEK_SET);
00176 put_be32(pb, index);
00177 url_fseek(pb, curpos, SEEK_SET);
00178
00179 return updateSize (pb, pos);
00180 }
00181
00182
00183 static int mov_write_stss_tag(ByteIOContext *pb, MOVTrack* track)
00184 {
00185 offset_t curpos, entryPos;
00186 int i, index = 0;
00187 offset_t pos = url_ftell(pb);
00188 put_be32(pb, 0);
00189 put_tag(pb, "stss");
00190 put_be32(pb, 0);
00191 entryPos = url_ftell(pb);
00192 put_be32(pb, track->entry);
00193 for (i=0; i<track->entry; i++) {
00194 if(track->cluster[i].key_frame == 1) {
00195 put_be32(pb, i+1);
00196 index++;
00197 }
00198 }
00199 curpos = url_ftell(pb);
00200 url_fseek(pb, entryPos, SEEK_SET);
00201 put_be32(pb, index);
00202 url_fseek(pb, curpos, SEEK_SET);
00203 return updateSize (pb, pos);
00204 }
00205
00206 static int mov_write_amr_tag(ByteIOContext *pb, MOVTrack *track)
00207 {
00208 put_be32(pb, 0x11);
00209 if (track->mode == MODE_MOV) put_tag(pb, "samr");
00210 else put_tag(pb, "damr");
00211 put_tag(pb, "FFMP");
00212 put_byte(pb, 0);
00213
00214 put_be16(pb, 0x81FF);
00215 put_byte(pb, 0x00);
00216 put_byte(pb, 0x01);
00217 return 0x11;
00218 }
00219
00220 static int mov_write_enda_tag(ByteIOContext *pb)
00221 {
00222 put_be32(pb, 10);
00223 put_tag(pb, "enda");
00224 put_be16(pb, 1);
00225 return 10;
00226 }
00227
00228 static unsigned int descrLength(unsigned int len)
00229 {
00230 int i;
00231 for(i=1; len>>(7*i); i++);
00232 return len + 1 + i;
00233 }
00234
00235 static void putDescr(ByteIOContext *pb, int tag, unsigned int size)
00236 {
00237 int i= descrLength(size) - size - 2;
00238 put_byte(pb, tag);
00239 for(; i>0; i--)
00240 put_byte(pb, (size>>(7*i)) | 0x80);
00241 put_byte(pb, size & 0x7F);
00242 }
00243
00244 static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack* track)
00245 {
00246 offset_t pos = url_ftell(pb);
00247 int decoderSpecificInfoLen = track->vosLen ? descrLength(track->vosLen):0;
00248
00249 put_be32(pb, 0);
00250 put_tag(pb, "esds");
00251 put_be32(pb, 0);
00252
00253
00254 putDescr(pb, 0x03, 3 + descrLength(13 + decoderSpecificInfoLen) +
00255 descrLength(1));
00256 put_be16(pb, track->trackID);
00257 put_byte(pb, 0x00);
00258
00259
00260 putDescr(pb, 0x04, 13 + decoderSpecificInfoLen);
00261
00262
00263 put_byte(pb, codec_get_tag(ff_mp4_obj_type, track->enc->codec_id));
00264
00265
00266
00267 if(track->enc->codec_type == CODEC_TYPE_AUDIO)
00268 put_byte(pb, 0x15);
00269 else
00270 put_byte(pb, 0x11);
00271
00272 put_byte(pb, track->enc->rc_buffer_size>>(3+16));
00273 put_be16(pb, (track->enc->rc_buffer_size>>3)&0xFFFF);
00274
00275 put_be32(pb, FFMAX(track->enc->bit_rate, track->enc->rc_max_rate));
00276 if(track->enc->rc_max_rate != track->enc->rc_min_rate || track->enc->rc_min_rate==0)
00277 put_be32(pb, 0);
00278 else
00279 put_be32(pb, track->enc->rc_max_rate);
00280
00281 if (track->vosLen)
00282 {
00283
00284 putDescr(pb, 0x05, track->vosLen);
00285 put_buffer(pb, track->vosData, track->vosLen);
00286 }
00287
00288
00289
00290 putDescr(pb, 0x06, 1);
00291 put_byte(pb, 0x02);
00292 return updateSize (pb, pos);
00293 }
00294
00295 static int mov_write_wave_tag(ByteIOContext *pb, MOVTrack* track)
00296 {
00297 offset_t pos = url_ftell(pb);
00298
00299 put_be32(pb, 0);
00300 put_tag(pb, "wave");
00301
00302 put_be32(pb, 12);
00303 put_tag(pb, "frma");
00304 put_le32(pb, track->tag);
00305
00306 if (track->enc->codec_id == CODEC_ID_AAC) {
00307
00308 put_be32(pb, 12);
00309 put_tag(pb, "mp4a");
00310 put_be32(pb, 0);
00311 mov_write_esds_tag(pb, track);
00312 } else if (track->enc->codec_id == CODEC_ID_PCM_S24LE ||
00313 track->enc->codec_id == CODEC_ID_PCM_S32LE) {
00314 mov_write_enda_tag(pb);
00315 } else if (track->enc->codec_id == CODEC_ID_AMR_NB) {
00316 mov_write_amr_tag(pb, track);
00317 }
00318
00319 put_be32(pb, 8);
00320 put_be32(pb, 0);
00321
00322 return updateSize (pb, pos);
00323 }
00324
00325 static int mov_write_audio_tag(ByteIOContext *pb, MOVTrack* track)
00326 {
00327 offset_t pos = url_ftell(pb);
00328 int version = track->mode == MODE_MOV &&
00329 (track->audio_vbr ||
00330 track->enc->codec_id == CODEC_ID_PCM_S32LE ||
00331 track->enc->codec_id == CODEC_ID_PCM_S24LE);
00332
00333 put_be32(pb, 0);
00334 put_le32(pb, track->tag);
00335 put_be32(pb, 0);
00336 put_be16(pb, 0);
00337 put_be16(pb, 1);
00338
00339
00340 put_be16(pb, version);
00341 put_be16(pb, 0);
00342 put_be32(pb, 0);
00343
00344 if (track->mode == MODE_MOV) {
00345 put_be16(pb, track->enc->channels);
00346 if (track->enc->codec_id == CODEC_ID_PCM_U8 ||
00347 track->enc->codec_id == CODEC_ID_PCM_S8)
00348 put_be16(pb, 8);
00349 else
00350 put_be16(pb, 16);
00351 put_be16(pb, track->audio_vbr ? -2 : 0);
00352 } else {
00353 put_be16(pb, 2);
00354 put_be16(pb, 16);
00355 put_be16(pb, 0);
00356 }
00357
00358 put_be16(pb, 0);
00359 put_be16(pb, track->timescale);
00360 put_be16(pb, 0);
00361
00362 if(version == 1) {
00363 put_be32(pb, track->enc->frame_size);
00364 put_be32(pb, track->sampleSize / track->enc->channels);
00365 put_be32(pb, track->sampleSize);
00366 put_be32(pb, 2);
00367 }
00368
00369 if(track->mode == MODE_MOV &&
00370 (track->enc->codec_id == CODEC_ID_AAC ||
00371 track->enc->codec_id == CODEC_ID_AMR_NB ||
00372 track->enc->codec_id == CODEC_ID_PCM_S24LE ||
00373 track->enc->codec_id == CODEC_ID_PCM_S32LE))
00374 mov_write_wave_tag(pb, track);
00375 else if(track->enc->codec_id == CODEC_ID_AAC)
00376 mov_write_esds_tag(pb, track);
00377 else if(track->enc->codec_id == CODEC_ID_AMR_NB)
00378 mov_write_amr_tag(pb, track);
00379
00380 return updateSize (pb, pos);
00381 }
00382
00383 static int mov_write_d263_tag(ByteIOContext *pb)
00384 {
00385 put_be32(pb, 0xf);
00386 put_tag(pb, "d263");
00387 put_tag(pb, "FFMP");
00388 put_byte(pb, 0);
00389
00390 put_byte(pb, 0xa);
00391 put_byte(pb, 0);
00392 return 0xf;
00393 }
00394
00395
00396 static int mov_write_svq3_tag(ByteIOContext *pb)
00397 {
00398 put_be32(pb, 0x15);
00399 put_tag(pb, "SMI ");
00400 put_tag(pb, "SEQH");
00401 put_be32(pb, 0x5);
00402 put_be32(pb, 0xe2c0211d);
00403 put_be32(pb, 0xc0000000);
00404 put_byte(pb, 0);
00405 return 0x15;
00406 }
00407
00408 static uint8_t *avc_find_startcode( uint8_t *p, uint8_t *end )
00409 {
00410 uint8_t *a = p + 4 - ((long)p & 3);
00411
00412 for( end -= 3; p < a && p < end; p++ ) {
00413 if( p[0] == 0 && p[1] == 0 && p[2] == 1 )
00414 return p;
00415 }
00416
00417 for( end -= 3; p < end; p += 4 ) {
00418 uint32_t x = *(uint32_t*)p;
00419
00420
00421 if( (x - 0x01010101) & (~x) & 0x80808080 ) {
00422 if( p[1] == 0 ) {
00423 if( p[0] == 0 && p[2] == 1 )
00424 return p-1;
00425 if( p[2] == 0 && p[3] == 1 )
00426 return p;
00427 }
00428 if( p[3] == 0 ) {
00429 if( p[2] == 0 && p[4] == 1 )
00430 return p+1;
00431 if( p[4] == 0 && p[5] == 1 )
00432 return p+2;
00433 }
00434 }
00435 }
00436
00437 for( end += 3; p < end; p++ ) {
00438 if( p[0] == 0 && p[1] == 0 && p[2] == 1 )
00439 return p;
00440 }
00441
00442 return end + 3;
00443 }
00444
00445 static void avc_parse_nal_units(uint8_t **buf, int *size)
00446 {
00447 ByteIOContext pb;
00448 uint8_t *p = *buf;
00449 uint8_t *end = p + *size;
00450 uint8_t *nal_start, *nal_end;
00451
00452 url_open_dyn_buf(&pb);
00453 nal_start = avc_find_startcode(p, end);
00454 while (nal_start < end) {
00455 while(!*(nal_start++));
00456 nal_end = avc_find_startcode(nal_start, end);
00457 put_be32(&pb, nal_end - nal_start);
00458 put_buffer(&pb, nal_start, nal_end - nal_start);
00459 nal_start = nal_end;
00460 }
00461 av_freep(buf);
00462 *size = url_close_dyn_buf(&pb, buf);
00463 }
00464
00465 static int mov_write_avcc_tag(ByteIOContext *pb, MOVTrack *track)
00466 {
00467 offset_t pos = url_ftell(pb);
00468
00469 put_be32(pb, 0);
00470 put_tag(pb, "avcC");
00471 if (track->vosLen > 6) {
00472
00473 if (AV_RB32(track->vosData) == 0x00000001) {
00474 uint8_t *buf, *end;
00475 uint32_t sps_size=0, pps_size=0;
00476 uint8_t *sps=0, *pps=0;
00477
00478 avc_parse_nal_units(&track->vosData, &track->vosLen);
00479 buf = track->vosData;
00480 end = track->vosData + track->vosLen;
00481
00482
00483 while (buf < end) {
00484 unsigned int size;
00485 uint8_t nal_type;
00486 size = AV_RB32(buf);
00487 nal_type = buf[4] & 0x1f;
00488 if (nal_type == 7) {
00489 sps = buf + 4;
00490 sps_size = size;
00491 } else if (nal_type == 8) {
00492 pps = buf + 4;
00493 pps_size = size;
00494 }
00495 buf += size + 4;
00496 }
00497 assert(sps);
00498 assert(pps);
00499
00500 put_byte(pb, 1);
00501 put_byte(pb, sps[1]);
00502 put_byte(pb, sps[2]);
00503 put_byte(pb, sps[3]);
00504 put_byte(pb, 0xff);
00505 put_byte(pb, 0xe1);
00506
00507 put_be16(pb, sps_size);
00508 put_buffer(pb, sps, sps_size);
00509 put_byte(pb, 1);
00510 put_be16(pb, pps_size);
00511 put_buffer(pb, pps, pps_size);
00512 } else {
00513 put_buffer(pb, track->vosData, track->vosLen);
00514 }
00515 }
00516 return updateSize(pb, pos);
00517 }
00518
00519
00520 static int mov_write_avid_tag(ByteIOContext *pb, MOVTrack *track)
00521 {
00522 int i;
00523 put_be32(pb, 24);
00524 put_tag(pb, "ACLR");
00525 put_tag(pb, "ACLR");
00526 put_tag(pb, "0001");
00527 put_be32(pb, 1);
00528 put_be32(pb, 0);
00529
00530 put_be32(pb, 24);
00531 put_tag(pb, "APRG");
00532 put_tag(pb, "APRG");
00533 put_tag(pb, "0001");
00534 put_be32(pb, 1);
00535 put_be32(pb, 0);
00536
00537 put_be32(pb, 120);
00538 put_tag(pb, "ARES");
00539 put_tag(pb, "ARES");
00540 put_tag(pb, "0001");
00541 put_be32(pb, AV_RB32(track->vosData + 0x28));
00542 put_be32(pb, track->enc->width);
00543
00544 if (track->vosData[5] & 2) {
00545 put_be32(pb, track->enc->height/2);
00546 put_be32(pb, 2);
00547 put_be32(pb, 0);
00548 put_be32(pb, 4);
00549 } else {
00550 put_be32(pb, track->enc->height);
00551 put_be32(pb, 1);
00552 put_be32(pb, 0);
00553 put_be32(pb, 5);
00554 }
00555
00556 for (i = 0; i < 10; i++)
00557 put_be64(pb, 0);
00558
00559
00560 put_be32(pb, 0);
00561 return 0;
00562 }
00563
00564 static int mov_find_video_codec_tag(AVFormatContext *s, MOVTrack *track)
00565 {
00566 int tag = track->enc->codec_tag;
00567 if (!tag) {
00568 if (track->enc->codec_id == CODEC_ID_DVVIDEO) {
00569 if (track->enc->height == 480) {
00570 if (track->enc->pix_fmt == PIX_FMT_YUV422P)
00571 tag = MKTAG('d', 'v', '5', 'n');
00572 else
00573 tag = MKTAG('d', 'v', 'c', ' ');
00574 } else {
00575 if (track->enc->pix_fmt == PIX_FMT_YUV422P)
00576 tag = MKTAG('d', 'v', '5', 'p');
00577 else if (track->enc->pix_fmt == PIX_FMT_YUV420P)
00578 tag = MKTAG('d', 'v', 'c', 'p');
00579 else
00580 tag = MKTAG('d', 'v', 'p', 'p');
00581 }
00582 } else if (track->enc->codec_id == CODEC_ID_H263) {
00583 if (track->mode == MODE_MOV)
00584 tag = MKTAG('h', '2', '6', '3');
00585 else
00586 tag = MKTAG('s', '2', '6', '3');
00587 } else {
00588 tag = codec_get_tag(codec_movvideo_tags, track->enc->codec_id);
00589 }
00590 }
00591
00592 if (!tag) {
00593 tag = codec_get_tag(codec_bmp_tags, track->enc->codec_id);
00594 if (tag) {
00595 av_log(s, AV_LOG_INFO, "Warning, using MS style video codec tag, the file may be unplayable!\n");
00596 }
00597 }
00598 assert(tag);
00599 return tag;
00600 }
00601
00602 static int mov_find_audio_codec_tag(AVFormatContext *s, MOVTrack *track)
00603 {
00604 int tag = track->enc->codec_tag;
00605 if (!tag) {
00606 tag = codec_get_tag(codec_movaudio_tags, track->enc->codec_id);
00607 }
00608
00609 if (!tag) {
00610 int ms_tag = codec_get_tag(codec_wav_tags, track->enc->codec_id);
00611 if (ms_tag) {
00612 tag = MKTAG('m', 's', ((ms_tag >> 8) & 0xff), (ms_tag & 0xff));
00613 av_log(s, AV_LOG_INFO, "Warning, using MS style audio codec tag, the file may be unplayable!\n");
00614 }
00615 }
00616 assert(tag);
00617 return tag;
00618 }
00619
00620 static int mov_write_video_tag(ByteIOContext *pb, MOVTrack* track)
00621 {
00622 offset_t pos = url_ftell(pb);
00623 char compressor_name[32];
00624
00625 put_be32(pb, 0);
00626 put_le32(pb, track->tag);
00627 put_be32(pb, 0);
00628 put_be16(pb, 0);
00629 put_be16(pb, 1);
00630
00631 put_be16(pb, 0);
00632 put_be16(pb, 0);
00633 if (track->mode == MODE_MOV) {
00634 put_tag(pb, "FFMP");
00635 if(track->enc->codec_id == CODEC_ID_RAWVIDEO) {
00636 put_be32(pb, 0);
00637 put_be32(pb, 0x400);
00638 } else {
00639 put_be32(pb, 0x200);
00640 put_be32(pb, 0x200);
00641 }
00642 } else {
00643 put_be32(pb, 0);
00644 put_be32(pb, 0);
00645 put_be32(pb, 0);
00646 }
00647 put_be16(pb, track->enc->width);
00648 put_be16(pb, track->enc->height);
00649 put_be32(pb, 0x00480000);
00650 put_be32(pb, 0x00480000);
00651 put_be32(pb, 0);
00652 put_be16(pb, 1);
00653
00654 memset(compressor_name,0,32);
00655
00656 if (track->mode == MODE_MOV && track->enc->codec && track->enc->codec->name)
00657 strncpy(compressor_name,track->enc->codec->name,31);
00658 put_byte(pb, strlen(compressor_name));
00659 put_buffer(pb, compressor_name, 31);
00660
00661 put_be16(pb, 0x18);
00662 put_be16(pb, 0xffff);
00663 if(track->enc->codec_id == CODEC_ID_MPEG4)
00664 mov_write_esds_tag(pb, track);
00665 else if(track->enc->codec_id == CODEC_ID_H263)
00666 mov_write_d263_tag(pb);
00667 else if(track->enc->codec_id == CODEC_ID_SVQ3)
00668 mov_write_svq3_tag(pb);
00669 else if(track->enc->codec_id == CODEC_ID_H264)
00670 mov_write_avcc_tag(pb, track);
00671 else if(track->enc->codec_id == CODEC_ID_DNXHD)
00672 mov_write_avid_tag(pb, track);
00673
00674 return updateSize (pb, pos);
00675 }
00676
00677 static int mov_write_stsd_tag(ByteIOContext *pb, MOVTrack* track)
00678 {
00679 offset_t pos = url_ftell(pb);
00680 put_be32(pb, 0);
00681 put_tag(pb, "stsd");
00682 put_be32(pb, 0);
00683 put_be32(pb, 1);
00684 if (track->enc->codec_type == CODEC_TYPE_VIDEO)
00685 mov_write_video_tag(pb, track);
00686 else if (track->enc->codec_type == CODEC_TYPE_AUDIO)
00687 mov_write_audio_tag(pb, track);
00688 return updateSize(pb, pos);
00689 }
00690
00691 static int mov_write_ctts_tag(ByteIOContext *pb, MOVTrack* track)
00692 {
00693 MOV_stts_t *ctts_entries;
00694 uint32_t entries = 0;
00695 uint32_t atom_size;
00696 int i;
00697
00698 ctts_entries = av_malloc((track->entry + 1) * sizeof(*ctts_entries));
00699 ctts_entries[0].count = 1;
00700 ctts_entries[0].duration = track->cluster[0].cts;
00701 for (i=1; i<track->entry; i++) {
00702 if (track->cluster[i].cts == ctts_entries[entries].duration) {
00703 ctts_entries[entries].count++;
00704 } else {
00705 entries++;
00706 ctts_entries[entries].duration = track->cluster[i].cts;
00707 ctts_entries[entries].count = 1;
00708 }
00709 }
00710 entries++;
00711 atom_size = 16 + (entries * 8);
00712 put_be32(pb, atom_size);
00713 put_tag(pb, "ctts");
00714 put_be32(pb, 0);
00715 put_be32(pb, entries);
00716 for (i=0; i<entries; i++) {
00717 put_be32(pb, ctts_entries[i].count);
00718 put_be32(pb, ctts_entries[i].duration);
00719 }
00720 av_free(ctts_entries);
00721 return atom_size;
00722 }
00723
00724
00725 static int mov_write_stts_tag(ByteIOContext *pb, MOVTrack* track)
00726 {
00727 MOV_stts_t *stts_entries;
00728 uint32_t entries = -1;
00729 uint32_t atom_size;
00730 int i;
00731
00732 if (track->enc->codec_type == CODEC_TYPE_AUDIO && !track->audio_vbr) {
00733 stts_entries = av_malloc(sizeof(*stts_entries));
00734 stts_entries[0].count = track->sampleCount;
00735 stts_entries[0].duration = 1;
00736 entries = 1;
00737 } else {
00738 stts_entries = av_malloc(track->entry * sizeof(*stts_entries));
00739 for (i=0; i<track->entry; i++) {
00740 int64_t duration = i + 1 == track->entry ?
00741 track->trackDuration - track->cluster[i].dts + track->cluster[0].dts :
00742 track->cluster[i+1].dts - track->cluster[i].dts;
00743 if (i && duration == stts_entries[entries].duration) {
00744 stts_entries[entries].count++;
00745 } else {
00746 entries++;
00747 stts_entries[entries].duration = duration;
00748 stts_entries[entries].count = 1;
00749 }
00750 }
00751 entries++;
00752 }
00753 atom_size = 16 + (entries * 8);
00754 put_be32(pb, atom_size);
00755 put_tag(pb, "stts");
00756 put_be32(pb, 0);
00757 put_be32(pb, entries);
00758 for (i=0; i<entries; i++) {
00759 put_be32(pb, stts_entries[i].count);
00760 put_be32(pb, stts_entries[i].duration);
00761 }
00762 av_free(stts_entries);
00763 return atom_size;
00764 }
00765
00766 static int mov_write_dref_tag(ByteIOContext *pb)
00767 {
00768 put_be32(pb, 28);
00769 put_tag(pb, "dref");
00770 put_be32(pb, 0);
00771 put_be32(pb, 1);
00772
00773 put_be32(pb, 0xc);
00774 put_tag(pb, "url ");
00775 put_be32(pb, 1);
00776
00777 return 28;
00778 }
00779
00780 static int mov_write_stbl_tag(ByteIOContext *pb, MOVTrack* track)
00781 {
00782 offset_t pos = url_ftell(pb);
00783 put_be32(pb, 0);
00784 put_tag(pb, "stbl");
00785 mov_write_stsd_tag(pb, track);
00786 mov_write_stts_tag(pb, track);
00787 if (track->enc->codec_type == CODEC_TYPE_VIDEO &&
00788 track->hasKeyframes < track->entry)
00789 mov_write_stss_tag(pb, track);
00790 if (track->enc->codec_type == CODEC_TYPE_VIDEO &&
00791 track->hasBframes)
00792 mov_write_ctts_tag(pb, track);
00793 mov_write_stsc_tag(pb, track);
00794 mov_write_stsz_tag(pb, track);
00795 mov_write_stco_tag(pb, track);
00796 return updateSize(pb, pos);
00797 }
00798
00799 static int mov_write_dinf_tag(ByteIOContext *pb)
00800 {
00801 offset_t pos = url_ftell(pb);
00802 put_be32(pb, 0);
00803 put_tag(pb, "dinf");
00804 mov_write_dref_tag(pb);
00805 return updateSize(pb, pos);
00806 }
00807
00808 static int mov_write_smhd_tag(ByteIOContext *pb)
00809 {
00810 put_be32(pb, 16);
00811 put_tag(pb, "smhd");
00812 put_be32(pb, 0);
00813 put_be16(pb, 0);
00814 put_be16(pb, 0);
00815 return 16;
00816 }
00817
00818 static int mov_write_vmhd_tag(ByteIOContext *pb)
00819 {
00820 put_be32(pb, 0x14);
00821 put_tag(pb, "vmhd");
00822 put_be32(pb, 0x01);
00823 put_be64(pb, 0);
00824 return 0x14;
00825 }
00826
00827 static int mov_write_hdlr_tag(ByteIOContext *pb, MOVTrack* track)
00828 {
00829 const char *descr, *hdlr, *hdlr_type;
00830 offset_t pos = url_ftell(pb);
00831
00832 if (!track) {
00833 hdlr = "dhlr";
00834 hdlr_type = "url ";
00835 descr = "DataHandler";
00836 } else {
00837 hdlr = (track->mode == MODE_MOV) ? "mhlr" : "\0\0\0\0";
00838 if (track->enc->codec_type == CODEC_TYPE_VIDEO) {
00839 hdlr_type = "vide";
00840 descr = "VideoHandler";
00841 } else {
00842 hdlr_type = "soun";
00843 descr = "SoundHandler";
00844 }
00845 }
00846
00847 put_be32(pb, 0);
00848 put_tag(pb, "hdlr");
00849 put_be32(pb, 0);
00850 put_buffer(pb, hdlr, 4);
00851 put_tag(pb, hdlr_type);
00852 put_be32(pb ,0);
00853 put_be32(pb ,0);
00854 put_be32(pb ,0);
00855 put_byte(pb, strlen(descr));
00856 put_buffer(pb, descr, strlen(descr));
00857 return updateSize(pb, pos);
00858 }
00859
00860 static int mov_write_minf_tag(ByteIOContext *pb, MOVTrack* track)
00861 {
00862 offset_t pos = url_ftell(pb);
00863 put_be32(pb, 0);
00864 put_tag(pb, "minf");
00865 if(track->enc->codec_type == CODEC_TYPE_VIDEO)
00866 mov_write_vmhd_tag(pb);
00867 else
00868 mov_write_smhd_tag(pb);
00869 if (track->mode == MODE_MOV)
00870 mov_write_hdlr_tag(pb, NULL);
00871 mov_write_dinf_tag(pb);
00872 mov_write_stbl_tag(pb, track);
00873 return updateSize(pb, pos);
00874 }
00875
00876 static int mov_write_mdhd_tag(ByteIOContext *pb, MOVTrack* track)
00877 {
00878 int version = track->trackDuration < INT32_MAX ? 0 : 1;
00879
00880 (version == 1) ? put_be32(pb, 44) : put_be32(pb, 32);
00881 put_tag(pb, "mdhd");
00882 put_byte(pb, version);
00883 put_be24(pb, 0);
00884 if (version == 1) {
00885 put_be64(pb, track->time);
00886 put_be64(pb, track->time);
00887 } else {
00888 put_be32(pb, track->time);
00889 put_be32(pb, track->time);
00890 }
00891 put_be32(pb, track->timescale);
00892 (version == 1) ? put_be64(pb, track->trackDuration) : put_be32(pb, track->trackDuration);
00893 put_be16(pb, track->language);
00894 put_be16(pb, 0);
00895
00896 if(version!=0 && track->mode == MODE_MOV){
00897 av_log(NULL, AV_LOG_ERROR,
00898 "FATAL error, file duration too long for timebase, this file will not be\n"
00899 "playable with quicktime. Choose a different timebase or a different\n"
00900 "container format\n");
00901 }
00902
00903 return 32;
00904 }
00905
00906 static int mov_write_mdia_tag(ByteIOContext *pb, MOVTrack* track)
00907 {
00908 offset_t pos = url_ftell(pb);
00909 put_be32(pb, 0);
00910 put_tag(pb, "mdia");
00911 mov_write_mdhd_tag(pb, track);
00912 mov_write_hdlr_tag(pb, track);
00913 mov_write_minf_tag(pb, track);
00914 return updateSize(pb, pos);
00915 }
00916
00917 static int mov_write_tkhd_tag(ByteIOContext *pb, MOVTrack* track)
00918 {
00919 int64_t duration = av_rescale_rnd(track->trackDuration, globalTimescale, track->timescale, AV_ROUND_UP);
00920 int version = duration < INT32_MAX ? 0 : 1;
00921
00922 (version == 1) ? put_be32(pb, 104) : put_be32(pb, 92);
00923 put_tag(pb, "tkhd");
00924 put_byte(pb, version);
00925 put_be24(pb, 0xf);
00926 if (version == 1) {
00927 put_be64(pb, track->time);
00928 put_be64(pb, track->time);
00929 } else {
00930 put_be32(pb, track->time);
00931 put_be32(pb, track->time);
00932 }
00933 put_be32(pb, track->trackID);
00934 put_be32(pb, 0);
00935 (version == 1) ? put_be64(pb, duration) : put_be32(pb, duration);
00936
00937 put_be32(pb, 0);
00938 put_be32(pb, 0);
00939 put_be32(pb, 0x0);
00940
00941 if(track->enc->codec_type == CODEC_TYPE_AUDIO)
00942 put_be16(pb, 0x0100);
00943 else
00944 put_be16(pb, 0);
00945 put_be16(pb, 0);
00946
00947
00948 put_be32(pb, 0x00010000);
00949 put_be32(pb, 0x0);
00950 put_be32(pb, 0x0);
00951 put_be32(pb, 0x0);
00952 put_be32(pb, 0x00010000);
00953 put_be32(pb, 0x0);
00954 put_be32(pb, 0x0);
00955 put_be32(pb, 0x0);
00956 put_be32(pb, 0x40000000);
00957
00958
00959 if(track->enc->codec_type == CODEC_TYPE_VIDEO) {
00960 double sample_aspect_ratio = av_q2d(track->enc->sample_aspect_ratio);
00961 if( !sample_aspect_ratio ) sample_aspect_ratio = 1;
00962 put_be32(pb, sample_aspect_ratio * track->enc->width*0x10000);
00963 put_be32(pb, track->enc->height*0x10000);
00964 }
00965 else {
00966 put_be32(pb, 0);
00967 put_be32(pb, 0);
00968 }
00969 return 0x5c;
00970 }
00971
00972
00973 static int mov_write_edts_tag(ByteIOContext *pb, MOVTrack *track)
00974 {
00975 put_be32(pb, 0x24);
00976 put_tag(pb, "edts");
00977 put_be32(pb, 0x1c);
00978 put_tag(pb, "elst");
00979 put_be32(pb, 0x0);
00980 put_be32(pb, 0x1);
00981
00982 put_be32(pb, av_rescale_rnd(track->trackDuration, globalTimescale, track->timescale, AV_ROUND_UP));
00983
00984 put_be32(pb, track->cluster[0].cts);
00985 put_be32(pb, 0x00010000);
00986 return 0x24;
00987 }
00988
00989
00990 static int mov_write_uuid_tag_psp(ByteIOContext *pb, MOVTrack *mov)
00991 {
00992 put_be32(pb, 0x34);
00993 put_tag(pb, "uuid");
00994 put_tag(pb, "USMT");
00995 put_be32(pb, 0x21d24fce);
00996 put_be32(pb, 0xbb88695c);
00997 put_be32(pb, 0xfac9c740);
00998 put_be32(pb, 0x1c);
00999 put_tag(pb, "MTDT");
01000 put_be32(pb, 0x00010012);
01001 put_be32(pb, 0x0a);
01002 put_be32(pb, 0x55c40000);
01003 put_be32(pb, 0x1);
01004 put_be32(pb, 0x0);
01005 return 0x34;
01006 }
01007
01008 static int mov_write_trak_tag(ByteIOContext *pb, MOVTrack* track)
01009 {
01010 offset_t pos = url_ftell(pb);
01011 put_be32(pb, 0);
01012 put_tag(pb, "trak");
01013 mov_write_tkhd_tag(pb, track);
01014 if (track->mode == MODE_PSP || track->hasBframes)
01015 mov_write_edts_tag(pb, track);
01016 mov_write_mdia_tag(pb, track);
01017 if (track->mode == MODE_PSP)
01018 mov_write_uuid_tag_psp(pb,track);
01019 return updateSize(pb, pos);
01020 }
01021
01022 #if 0
01023
01024 static int mov_write_iods_tag(ByteIOContext *pb, MOVContext *mov)
01025 {
01026 put_be32(pb, 0x15);
01027 put_tag(pb, "iods");
01028 put_be32(pb, 0);
01029 put_be16(pb, 0x1007);
01030 put_byte(pb, 0);
01031 put_be16(pb, 0x4fff);
01032 put_be16(pb, 0xfffe);
01033 put_be16(pb, 0x01ff);
01034 return 0x15;
01035 }
01036 #endif
01037
01038 static int mov_write_mvhd_tag(ByteIOContext *pb, MOVContext *mov)
01039 {
01040 int maxTrackID = 1, i;
01041 int64_t maxTrackLenTemp, maxTrackLen = 0;
01042 int version;
01043
01044 for (i=0; i<mov->nb_streams; i++) {
01045 if(mov->tracks[i].entry > 0) {
01046 maxTrackLenTemp = av_rescale_rnd(mov->tracks[i].trackDuration, globalTimescale, mov->tracks[i].timescale, AV_ROUND_UP);
01047 if(maxTrackLen < maxTrackLenTemp)
01048 maxTrackLen = maxTrackLenTemp;
01049 if(maxTrackID < mov->tracks[i].trackID)
01050 maxTrackID = mov->tracks[i].trackID;
01051 }
01052 }
01053
01054 version = maxTrackLen < UINT32_MAX ? 0 : 1;
01055 (version == 1) ? put_be32(pb, 120) : put_be32(pb, 108);
01056 put_tag(pb, "mvhd");
01057 put_byte(pb, version);
01058 put_be24(pb, 0);
01059 if (version == 1) {
01060 put_be64(pb, mov->time);
01061 put_be64(pb, mov->time);
01062 } else {
01063 put_be32(pb, mov->time);
01064 put_be32(pb, mov->time);
01065 }
01066 put_be32(pb, mov->timescale);
01067 (version == 1) ? put_be64(pb, maxTrackLen) : put_be32(pb, maxTrackLen);
01068
01069 put_be32(pb, 0x00010000);
01070 put_be16(pb, 0x0100);
01071 put_be16(pb, 0);
01072 put_be32(pb, 0);
01073 put_be32(pb, 0);
01074
01075
01076 put_be32(pb, 0x00010000);
01077 put_be32(pb, 0x0);
01078 put_be32(pb, 0x0);
01079 put_be32(pb, 0x0);
01080 put_be32(pb, 0x00010000);
01081 put_be32(pb, 0x0);
01082 put_be32(pb, 0x0);
01083 put_be32(pb, 0x0);
01084 put_be32(pb, 0x40000000);
01085
01086 put_be32(pb, 0);
01087 put_be32(pb, 0);
01088 put_be32(pb, 0);
01089 put_be32(pb, 0);
01090 put_be32(pb, 0);
01091 put_be32(pb, 0);
01092 put_be32(pb, maxTrackID+1);
01093 return 0x6c;
01094 }
01095
01096 static int mov_write_itunes_hdlr_tag(ByteIOContext *pb, MOVContext* mov,
01097 AVFormatContext *s)
01098 {
01099 offset_t pos = url_ftell(pb);
01100 put_be32(pb, 0);
01101 put_tag(pb, "hdlr");
01102 put_be32(pb, 0);
01103 put_be32(pb, 0);
01104 put_tag(pb, "mdir");
01105 put_tag(pb, "appl");
01106 put_be32(pb, 0);
01107 put_be32(pb, 0);
01108 put_be16(pb, 0);
01109 return updateSize(pb, pos);
01110 }
01111
01112
01113 static int mov_write_string_data_tag(ByteIOContext *pb, const char *data, int long_style)
01114 {
01115 if(long_style){
01116 offset_t pos = url_ftell(pb);
01117 put_be32(pb, 0);
01118 put_tag(pb, "data");
01119 put_be32(pb, 1);
01120 put_be32(pb, 0);
01121 put_buffer(pb, data, strlen(data));
01122 return updateSize(pb, pos);
01123 }else{
01124 put_be16(pb, strlen(data));
01125 put_be16(pb, 0);
01126 put_buffer(pb, data, strlen(data));
01127 return strlen(data) + 4;
01128 }
01129 }
01130
01131 static int mov_write_string_tag(ByteIOContext *pb, const char *name, const char *value, int long_style){
01132 int size = 0;
01133 if ( value && value[0] ) {
01134 offset_t pos = url_ftell(pb);
01135 put_be32(pb, 0);
01136 put_tag(pb, name);
01137 mov_write_string_data_tag(pb, value, long_style);
01138 size= updateSize(pb, pos);
01139 }
01140 return size;
01141 }
01142
01143
01144 static int mov_write_day_tag(ByteIOContext *pb, int year, int long_style)
01145 {
01146 if(year){
01147 char year_str[5];
01148 snprintf(year_str, sizeof(year_str), "%04d", year);
01149 return mov_write_string_tag(pb, "\251day", year_str, long_style);
01150 }else
01151 return 0;
01152 }
01153
01154
01155 static int mov_write_trkn_tag(ByteIOContext *pb, MOVContext* mov,
01156 AVFormatContext *s)
01157 {
01158 int size = 0;
01159 if ( s->track ) {
01160 offset_t pos = url_ftell(pb);
01161 put_be32(pb, 0);
01162 put_tag(pb, "trkn");
01163 {
01164 offset_t pos = url_ftell(pb);
01165 put_be32(pb, 0);
01166 put_tag(pb, "data");
01167 put_be32(pb, 0);
01168 put_be32(pb, 0);
01169 put_be16(pb, 0);
01170 put_be16(pb, s->track);
01171 put_be16(pb, 0);
01172 put_be16(pb, 0);
01173 updateSize(pb, pos);
01174 }
01175 size = updateSize(pb, pos);
01176 }
01177 return size;
01178 }
01179
01180
01181 static int mov_write_ilst_tag(ByteIOContext *pb, MOVContext* mov,
01182 AVFormatContext *s)
01183 {
01184 offset_t pos = url_ftell(pb);
01185 put_be32(pb, 0);
01186 put_tag(pb, "ilst");
01187 mov_write_string_tag(pb, "\251nam", s->title , 1);
01188 mov_write_string_tag(pb, "\251ART", s->author , 1);
01189 mov_write_string_tag(pb, "\251wrt", s->author , 1);
01190 mov_write_string_tag(pb, "\251alb", s->album , 1);
01191 mov_write_day_tag(pb, s->year ,1);
01192 if(mov->tracks[0].enc && !(mov->tracks[0].enc->flags & CODEC_FLAG_BITEXACT))
01193 mov_write_string_tag(pb, "\251too", LIBAVFORMAT_IDENT, 1);
01194 mov_write_string_tag(pb, "\251cmt", s->comment , 1);
01195 mov_write_string_tag(pb, "\251gen", s->genre , 1);
01196 mov_write_trkn_tag(pb, mov, s);
01197 return updateSize(pb, pos);
01198 }
01199
01200
01201 static int mov_write_meta_tag(ByteIOContext *pb, MOVContext* mov,
01202 AVFormatContext *s)
01203 {
01204 int size = 0;
01205
01206
01207 if ( s->title[0] || s->author[0] || s->album[0] || s->year ||
01208 s->comment[0] || s->genre[0] || s->track ) {
01209 offset_t pos = url_ftell(pb);
01210 put_be32(pb, 0);
01211 put_tag(pb, "meta");
01212 put_be32(pb, 0);
01213 mov_write_itunes_hdlr_tag(pb, mov, s);
01214 mov_write_ilst_tag(pb, mov, s);
01215 size = updateSize(pb, pos);
01216 }
01217 return size;
01218 }
01219
01220 static int mov_write_udta_tag(ByteIOContext *pb, MOVContext* mov,
01221 AVFormatContext *s)
01222 {
01223 int i, req = 0;
01224
01225
01226 for (i=0; i<mov->nb_streams; i++) {
01227 if(mov->tracks[i].entry <= 0) continue;
01228 if (mov->tracks[i].enc->codec_id == CODEC_ID_AAC ||
01229 mov->tracks[i].enc->codec_id == CODEC_ID_MPEG4) {
01230 req = 1;
01231 break;
01232 }
01233 }
01234
01235 if (s->title[0] || s->author[0] || s->album[0] || s->year ||
01236 s->comment[0] || s->genre[0] || s->track ||
01237 (mov->mode == MODE_MOV &&
01238 ((mov->tracks[0].enc && !mov->tracks[0].enc->flags & CODEC_FLAG_BITEXACT) || req))) {
01239 offset_t pos = url_ftell(pb);
01240
01241 put_be32(pb, 0);
01242 put_tag(pb, "udta");
01243
01244
01245 mov_write_meta_tag(pb, mov, s);
01246
01247 if(mov->mode == MODE_MOV){
01248
01249 if (req)
01250 mov_write_string_tag(pb, "\251req", "QuickTime 6.0 or greater", 0);
01251
01252 mov_write_string_tag(pb, "\251nam", s->title , 0);
01253 mov_write_string_tag(pb, "\251aut", s->author , 0);
01254 mov_write_string_tag(pb, "\251alb", s->album , 0);
01255 mov_write_day_tag(pb, s->year, 0);
01256 if(mov->tracks[0].enc && !(mov->tracks[0].enc->flags & CODEC_FLAG_BITEXACT))
01257 mov_write_string_tag(pb, "\251enc", LIBAVFORMAT_IDENT, 0);
01258 mov_write_string_tag(pb, "\251des", s->comment , 0);
01259 mov_write_string_tag(pb, "\251gen", s->genre , 0);
01260 }
01261
01262 return updateSize(pb, pos);
01263 }
01264
01265 return 0;
01266 }
01267
01268 static int utf8len(uint8_t *b){
01269 int len=0;
01270 int val;
01271 while(*b){
01272 GET_UTF8(val, *b++, return -1;)
01273 len++;
01274 }
01275 return len;
01276 }
01277
01278 static int ascii_to_wc (ByteIOContext *pb, uint8_t *b)
01279 {
01280 int val;
01281 while(*b){
01282 GET_UTF8(val, *b++, return -1;)
01283 put_be16(pb, val);
01284 }
01285 put_be16(pb, 0x00);
01286 return 0;
01287 }
01288
01289 static uint16_t language_code (const char *str)
01290 {
01291 return ((((str[0]-0x60) & 0x1F)<<10) + (((str[1]-0x60) & 0x1F)<<5) + ((str[2]-0x60) & 0x1F));
01292 }
01293
01294 static int mov_write_uuidusmt_tag (ByteIOContext *pb, AVFormatContext *s)
01295 {
01296 size_t len, size;
01297 offset_t pos, curpos;
01298
01299 size = 0;
01300 if (s->title[0]) {
01301 pos = url_ftell(pb);
01302 put_be32(pb, 0);
01303 put_tag(pb, "uuid");
01304 put_tag(pb, "USMT");
01305 put_be32(pb, 0x21d24fce );
01306 put_be32(pb, 0xbb88695c );
01307 put_be32(pb, 0xfac9c740 );
01308 size += 24;
01309
01310 put_be32(pb, 0);
01311 put_tag(pb, "MTDT");
01312 put_be16(pb, 4);
01313 size += 10;
01314
01315
01316 put_be16(pb, 0x0C);
01317 put_be32(pb, 0x0B);
01318 put_be16(pb, language_code("und"));
01319 put_be16(pb, 0x0);
01320 put_be16(pb, 0x021C);
01321 size += 12;
01322
01323
01324 len = utf8len(LIBAVCODEC_IDENT)+1;
01325 if(len<=0)
01326 goto not_utf8;
01327 put_be16(pb, len*2+10);
01328 put_be32(pb, 0x04);
01329 put_be16(pb, language_code("eng"));
01330 put_be16(pb, 0x01);
01331 ascii_to_wc(pb, LIBAVCODEC_IDENT);
01332 size += len*2+10;
01333
01334
01335 len = utf8len(s->title)+1;
01336 if(len<=0)
01337 goto not_utf8;
01338 put_be16(pb, len*2+10);
01339 put_be32(pb, 0x01);
01340 put_be16(pb, language_code("eng"));
01341 put_be16(pb, 0x01);
01342 ascii_to_wc (pb, s->title);
01343 size += len*2+10;
01344
01345
01346
01347 len = utf8len("2006/04/01 11:11:11")+1;
01348 if(len<=0)
01349 goto not_utf8;
01350 put_be16(pb, len*2+10);
01351 put_be32(pb, 0x03);
01352 put_be16(pb, language_code("und"));
01353 put_be16(pb, 0x01);
01354 ascii_to_wc (pb, "2006/04/01 11:11:11");
01355 size += len*2+10;
01356
01357
01358 curpos = url_ftell(pb);
01359 url_fseek(pb, pos, SEEK_SET);
01360 put_be32(pb, size);
01361 url_fseek(pb, pos+24, SEEK_SET);
01362 put_be32(pb, size-24);
01363 url_fseek(pb, curpos, SEEK_SET);
01364 }
01365
01366 return size;
01367 not_utf8:
01368 av_log(s, AV_LOG_ERROR, "not utf8\n");
01369 return -1;
01370 }
01371
01372 static int mov_write_moov_tag(ByteIOContext *pb, MOVContext *mov,
01373 AVFormatContext *s)
01374 {
01375 int i;
01376 offset_t pos = url_ftell(pb);
01377 put_be32(pb, 0);
01378 put_tag(pb, "moov");
01379 mov->timescale = globalTimescale;
01380
01381 for (i=0; i<mov->nb_streams; i++) {
01382 if(mov->tracks[i].entry <= 0) continue;
01383
01384 mov->tracks[i].time = mov->time;
01385 mov->tracks[i].trackID = i+1;
01386 }
01387
01388 mov_write_mvhd_tag(pb, mov);
01389
01390 for (i=0; i<mov->nb_streams; i++) {
01391 if(mov->tracks[i].entry > 0) {
01392 mov_write_trak_tag(pb, &(mov->tracks[i]));
01393 }
01394 }
01395
01396 if (mov->mode == MODE_PSP)
01397 mov_write_uuidusmt_tag(pb, s);
01398 else if (mov->mode != MODE_3GP && mov->mode != MODE_3G2)
01399 mov_write_udta_tag(pb, mov, s);
01400
01401 return updateSize(pb, pos);
01402 }
01403
01404 static int mov_write_mdat_tag(ByteIOContext *pb, MOVContext* mov)
01405 {
01406 put_be32(pb, 8);
01407 put_tag(pb, mov->mode == MODE_MOV ? "wide" : "free");
01408
01409 mov->mdat_pos = url_ftell(pb);
01410 put_be32(pb, 0);
01411 put_tag(pb, "mdat");
01412 return 0;
01413 }
01414
01415
01416 static void mov_write_ftyp_tag (ByteIOContext *pb, AVFormatContext *s)
01417 {
01418 MOVContext *mov = s->priv_data;
01419
01420 put_be32(pb, 0x14 );
01421 put_tag(pb, "ftyp");
01422
01423 if ( mov->mode == MODE_3GP )
01424 put_tag(pb, "3gp4");
01425 else if ( mov->mode == MODE_3G2 )
01426 put_tag(pb, "3g2a");
01427 else if ( mov->mode == MODE_PSP )
01428 put_tag(pb, "MSNV");
01429 else if ( mov->mode == MODE_MP4 )
01430 put_tag(pb, "isom");
01431 else
01432 put_tag(pb, "qt ");
01433
01434 put_be32(pb, 0x200 );
01435
01436 if ( mov->mode == MODE_3GP )
01437 put_tag(pb, "3gp4");
01438 else if ( mov->mode == MODE_3G2 )
01439 put_tag(pb, "3g2a");
01440 else if ( mov->mode == MODE_PSP )
01441 put_tag(pb, "MSNV");
01442 else if ( mov->mode == MODE_MP4 )
01443 put_tag(pb, "mp41");
01444 else
01445 put_tag(pb, "qt ");
01446 }
01447
01448 static void mov_write_uuidprof_tag(ByteIOContext *pb, AVFormatContext *s)
01449 {
01450 AVCodecContext *VideoCodec = s->streams[0]->codec;
01451 AVCodecContext *AudioCodec = s->streams[1]->codec;
01452 int AudioRate = AudioCodec->sample_rate;
01453 int FrameRate = ((VideoCodec->time_base.den) * (0x10000))/ (VideoCodec->time_base.num);
01454 int audio_kbitrate= AudioCodec->bit_rate / 1000;
01455 int video_kbitrate= FFMIN(VideoCodec->bit_rate / 1000, 800 - audio_kbitrate);
01456
01457 put_be32(pb, 0x94 );
01458 put_tag(pb, "uuid");
01459 put_tag(pb, "PROF");
01460
01461 put_be32(pb, 0x21d24fce );
01462 put_be32(pb, 0xbb88695c );
01463 put_be32(pb, 0xfac9c740 );
01464
01465 put_be32(pb, 0x0 );
01466 put_be32(pb, 0x3 );
01467
01468 put_be32(pb, 0x14 );
01469 put_tag(pb, "FPRF");
01470 put_be32(pb, 0x0 );
01471 put_be32(pb, 0x0 );
01472 put_be32(pb, 0x0 );
01473
01474 put_be32(pb, 0x2c );
01475 put_tag(pb, "APRF");
01476 put_be32(pb, 0x0 );
01477 put_be32(pb, 0x2 );
01478 put_tag(pb, "mp4a");
01479 put_be32(pb, 0x20f );
01480 put_be32(pb, 0x0 );
01481 put_be32(pb, audio_kbitrate);
01482 put_be32(pb, audio_kbitrate);
01483 put_be32(pb, AudioRate );
01484 put_be32(pb, AudioCodec->channels );
01485
01486 put_be32(pb, 0x34 );
01487 put_tag(pb, "VPRF");
01488 put_be32(pb, 0x0 );
01489 put_be32(pb, 0x1 );
01490 if (VideoCodec->codec_id == CODEC_ID_H264) {
01491 put_tag(pb, "avc1");
01492 put_be16(pb, 0x014D );
01493 put_be16(pb, 0x0015 );
01494 } else {
01495 put_tag(pb, "mp4v");
01496 put_be16(pb, 0x0000 );
01497 put_be16(pb, 0x0103 );
01498 }
01499 put_be32(pb, 0x0 );
01500 put_be32(pb, video_kbitrate);
01501 put_be32(pb, video_kbitrate);
01502 put_be32(pb, FrameRate);
01503 put_be32(pb, FrameRate);
01504 put_be16(pb, VideoCodec->width);
01505 put_be16(pb, VideoCodec->height);
01506 put_be32(pb, 0x010001);
01507 }
01508
01509 static int mov_write_header(AVFormatContext *s)
01510 {
01511 ByteIOContext *pb = &s->pb;
01512 MOVContext *mov = s->priv_data;
01513 int i;
01514
01515 if (url_is_streamed(&s->pb)) {
01516 av_log(s, AV_LOG_ERROR, "muxer does not support non seekable output\n");
01517 return -1;
01518 }
01519
01520
01521 mov->mode = MODE_MP4;
01522
01523 if (s->oformat != NULL) {
01524 if (!strcmp("3gp", s->oformat->name)) mov->mode = MODE_3GP;
01525 else if (!strcmp("3g2", s->oformat->name)) mov->mode = MODE_3G2;
01526 else if (!strcmp("mov", s->oformat->name)) mov->mode = MODE_MOV;
01527 else if (!strcmp("psp", s->oformat->name)) mov->mode = MODE_PSP;
01528
01529 mov_write_ftyp_tag(pb,s);
01530 if ( mov->mode == MODE_PSP ) {
01531 if ( s->nb_streams != 2 ) {
01532 av_log(s, AV_LOG_ERROR, "PSP mode need one video and one audio stream\n");
01533 return -1;
01534 }
01535 mov_write_uuidprof_tag(pb,s);
01536 }
01537 }
01538
01539 for(i=0; i<s->nb_streams; i++){
01540 AVStream *st= s->streams[i];
01541 MOVTrack *track= &mov->tracks[i];
01542
01543 track->enc = st->codec;
01544 track->language = ff_mov_iso639_to_lang(st->language, mov->mode != MODE_MOV);
01545 track->mode = mov->mode;
01546 if(st->codec->codec_type == CODEC_TYPE_VIDEO){
01547 track->tag = mov_find_video_codec_tag(s, track);
01548 track->timescale = st->codec->time_base.den;
01549 av_set_pts_info(st, 64, 1, st->codec->time_base.den);
01550 if (track->timescale > 100000)
01551 av_log(NULL, AV_LOG_WARNING,
01552 "WARNING codec timebase is very high. If duration is too long,\n"
01553 "file may not be playable by quicktime. Specify a shorter timebase\n"
01554 "or choose different container.\n");
01555 }else if(st->codec->codec_type == CODEC_TYPE_AUDIO){
01556 track->tag = mov_find_audio_codec_tag(s, track);
01557 track->timescale = st->codec->sample_rate;
01558 av_set_pts_info(st, 64, 1, st->codec->sample_rate);
01559 if(!st->codec->frame_size){
01560 av_log(s, AV_LOG_ERROR, "track %d: codec frame size is not set\n", i);
01561 return -1;
01562 }else if(st->codec->frame_size > 1){
01563 track->audio_vbr = 1;
01564 }else{
01565 track->sampleSize = (av_get_bits_per_sample(st->codec->codec_id) >> 3) * st->codec->channels;
01566 }
01567 }
01568 }
01569
01570 mov_write_mdat_tag(pb, mov);
01571 mov->time = s->timestamp + 0x7C25B080;
01572 mov->nb_streams = s->nb_streams;
01573
01574 put_flush_packet(pb);
01575
01576 return 0;
01577 }
01578
01579 static int mov_write_packet(AVFormatContext *s, AVPacket *pkt)
01580 {
01581 MOVContext *mov = s->priv_data;
01582 ByteIOContext *pb = &s->pb;
01583 MOVTrack *trk = &mov->tracks[pkt->stream_index];
01584 AVCodecContext *enc = trk->enc;
01585 unsigned int samplesInChunk = 0;
01586 int size= pkt->size;
01587
01588 if (url_is_streamed(&s->pb)) return 0;
01589 if (!size) return 0;
01590
01591 if (enc->codec_id == CODEC_ID_AMR_NB) {
01592
01593 static uint16_t packed_size[16] =
01594 {13, 14, 16, 18, 20, 21, 27, 32, 6, 0, 0, 0, 0, 0, 0, 0};
01595 int len = 0;
01596
01597 while (len < size && samplesInChunk < 100) {
01598 len += packed_size[(pkt->data[len] >> 3) & 0x0F];
01599 samplesInChunk++;
01600 }
01601 if(samplesInChunk > 1){
01602 av_log(s, AV_LOG_ERROR, "fatal error, input is not a single packet, implement a AVParser for it\n");
01603 return -1;
01604 }
01605 } else if (trk->sampleSize)
01606 samplesInChunk = size/trk->sampleSize;
01607 else
01608 samplesInChunk = 1;
01609
01610
01611 if (trk->vosLen == 0 && enc->extradata_size > 0) {
01612 trk->vosLen = enc->extradata_size;
01613 trk->vosData = av_malloc(trk->vosLen);
01614 memcpy(trk->vosData, enc->extradata, trk->vosLen);
01615 }
01616
01617 if (enc->codec_id == CODEC_ID_H264 && trk->vosLen > 0 && *(uint8_t *)trk->vosData != 1) {
01618
01619
01620 avc_parse_nal_units(&pkt->data, &pkt->size);
01621 assert(pkt->size);
01622 size = pkt->size;
01623 } else if (enc->codec_id == CODEC_ID_DNXHD && !trk->vosLen) {
01624
01625 if (size < 640)
01626 return -1;
01627 trk->vosLen = 640;
01628 trk->vosData = av_malloc(trk->vosLen);
01629 memcpy(trk->vosData, pkt->data, 640);
01630 }
01631
01632 if (!(trk->entry % MOV_INDEX_CLUSTER_SIZE)) {
01633 trk->cluster = av_realloc(trk->cluster, (trk->entry + MOV_INDEX_CLUSTER_SIZE) * sizeof(*trk->cluster));
01634 if (!trk->cluster)
01635 return -1;
01636 }
01637
01638 trk->cluster[trk->entry].pos = url_ftell(pb);
01639 trk->cluster[trk->entry].samplesInChunk = samplesInChunk;
01640 trk->cluster[trk->entry].size = size;
01641 trk->cluster[trk->entry].entries = samplesInChunk;
01642 trk->cluster[trk->entry].dts = pkt->dts;
01643 trk->trackDuration = pkt->dts - trk->cluster[0].dts + pkt->duration;
01644
01645 if(enc->codec_type == CODEC_TYPE_VIDEO) {
01646 if (pkt->dts != pkt->pts)
01647 trk->hasBframes = 1;
01648 trk->cluster[trk->entry].cts = pkt->pts - pkt->dts;
01649 trk->cluster[trk->entry].key_frame = !!(pkt->flags & PKT_FLAG_KEY);
01650 if(trk->cluster[trk->entry].key_frame)
01651 trk->hasKeyframes++;
01652 }
01653 trk->entry++;
01654 trk->sampleCount += samplesInChunk;
01655 mov->mdat_size += size;
01656
01657 put_buffer(pb, pkt->data, size);
01658
01659 put_flush_packet(pb);
01660 return 0;
01661 }
01662
01663 static int mov_write_trailer(AVFormatContext *s)
01664 {
01665 MOVContext *mov = s->priv_data;
01666 ByteIOContext *pb = &s->pb;
01667 int res = 0;
01668 int i;
01669
01670 offset_t moov_pos = url_ftell(pb);
01671
01672
01673 if (mov->mdat_size+8 <= UINT32_MAX) {
01674 url_fseek(pb, mov->mdat_pos, SEEK_SET);
01675 put_be32(pb, mov->mdat_size+8);
01676 } else {
01677
01678 url_fseek(pb, mov->mdat_pos - 8, SEEK_SET);
01679 put_be32(pb, 1);
01680 put_tag(pb, "mdat");
01681 put_be64(pb, mov->mdat_size+16);
01682 }
01683 url_fseek(pb, moov_pos, SEEK_SET);
01684
01685 mov_write_moov_tag(pb, mov, s);
01686
01687 for (i=0; i<mov->nb_streams; i++) {
01688 av_freep(&mov->tracks[i].cluster);
01689
01690 if( mov->tracks[i].vosLen ) av_free( mov->tracks[i].vosData );
01691
01692 }
01693
01694 put_flush_packet(pb);
01695
01696 return res;
01697 }
01698
01699 #ifdef CONFIG_MOV_MUXER
01700 AVOutputFormat mov_muxer = {
01701 "mov",
01702 "mov format",
01703 NULL,
01704 "mov",
01705 sizeof(MOVContext),
01706 CODEC_ID_AAC,
01707 CODEC_ID_MPEG4,
01708 mov_write_header,
01709 mov_write_packet,
01710 mov_write_trailer,
01711 .flags = AVFMT_GLOBALHEADER,
01712 };
01713 #endif
01714 #ifdef CONFIG_TGP_MUXER
01715 AVOutputFormat tgp_muxer = {
01716 "3gp",
01717 "3gp format",
01718 NULL,
01719 "3gp",
01720 sizeof(MOVContext),
01721 CODEC_ID_AMR_NB,
01722 CODEC_ID_H263,
01723 mov_write_header,
01724 mov_write_packet,
01725 mov_write_trailer,
01726 .flags = AVFMT_GLOBALHEADER,
01727 };
01728 #endif
01729 #ifdef CONFIG_MP4_MUXER
01730 AVOutputFormat mp4_muxer = {
01731 "mp4",
01732 "mp4 format",
01733 "application/mp4",
01734 "mp4,m4a",
01735 sizeof(MOVContext),
01736 CODEC_ID_AAC,
01737 CODEC_ID_MPEG4,
01738 mov_write_header,
01739 mov_write_packet,
01740 mov_write_trailer,
01741 .flags = AVFMT_GLOBALHEADER,
01742 };
01743 #endif
01744 #ifdef CONFIG_PSP_MUXER
01745 AVOutputFormat psp_muxer = {
01746 "psp",
01747 "psp mp4 format",
01748 NULL,
01749 "mp4,psp",
01750 sizeof(MOVContext),
01751 CODEC_ID_AAC,
01752 CODEC_ID_MPEG4,
01753 mov_write_header,
01754 mov_write_packet,
01755 mov_write_trailer,
01756 .flags = AVFMT_GLOBALHEADER,
01757 };
01758 #endif
01759 #ifdef CONFIG_TG2_MUXER
01760 AVOutputFormat tg2_muxer = {
01761 "3g2",
01762 "3gp2 format",
01763 NULL,
01764 "3g2",
01765 sizeof(MOVContext),
01766 CODEC_ID_AMR_NB,
01767 CODEC_ID_H263,
01768 mov_write_header,
01769 mov_write_packet,
01770 mov_write_trailer,
01771 .flags = AVFMT_GLOBALHEADER,
01772 };
01773 #endif