• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavformat/movenc.c

Go to the documentation of this file.
00001 /*
00002  * MOV, 3GP, MP4 muxer
00003  * Copyright (c) 2003 Thomas Raivio
00004  * Copyright (c) 2004 Gildas Bazin <gbazin at videolan dot org>
00005  *
00006  * This file is part of FFmpeg.
00007  *
00008  * FFmpeg is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Lesser General Public
00010  * License as published by the Free Software Foundation; either
00011  * version 2.1 of the License, or (at your option) any later version.
00012  *
00013  * FFmpeg is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * Lesser General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public
00019  * License along with FFmpeg; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00021  */
00022 #include "avformat.h"
00023 #include "riff.h"
00024 #include "avio.h"
00025 #include "isom.h"
00026 #include "avc.h"
00027 #include "libavcodec/bitstream.h"
00028 
00029 #undef NDEBUG
00030 #include <assert.h>
00031 
00032 #define MOV_INDEX_CLUSTER_SIZE 16384
00033 #define globalTimescale 1000
00034 
00035 #define MODE_MP4  0x01
00036 #define MODE_MOV  0x02
00037 #define MODE_3GP  0x04
00038 #define MODE_PSP  0x08 // example working PSP command line:
00039 // ffmpeg -i testinput.avi  -f psp -r 14.985 -s 320x240 -b 768 -ar 24000 -ab 32 M4V00001.MP4
00040 #define MODE_3G2  0x10
00041 #define MODE_IPOD 0x20
00042 
00043 typedef struct MOVIentry {
00044     unsigned int flags, size;
00045     uint64_t     pos;
00046     unsigned int samplesInChunk;
00047     char         key_frame;
00048     unsigned int entries;
00049     int64_t      cts;
00050     int64_t      dts;
00051 } MOVIentry;
00052 
00053 typedef struct MOVIndex {
00054     int         mode;
00055     int         entry;
00056     long        timescale;
00057     long        time;
00058     int64_t     trackDuration;
00059     long        sampleCount;
00060     long        sampleSize;
00061     int         hasKeyframes;
00062     int         hasBframes;
00063     int         language;
00064     int         trackID;
00065     int         tag; 
00066     AVCodecContext *enc;
00067 
00068     int         vosLen;
00069     uint8_t     *vosData;
00070     MOVIentry   *cluster;
00071     int         audio_vbr;
00072     int         height; 
00073 } MOVTrack;
00074 
00075 typedef struct MOVMuxContext {
00076     int     mode;
00077     int64_t time;
00078     int     nb_streams;
00079     int64_t mdat_pos;
00080     uint64_t mdat_size;
00081     long    timescale;
00082     MOVTrack tracks[MAX_STREAMS];
00083 } MOVMuxContext;
00084 
00085 //FIXME support 64 bit variant with wide placeholders
00086 static int64_t updateSize(ByteIOContext *pb, int64_t pos)
00087 {
00088     int64_t curpos = url_ftell(pb);
00089     url_fseek(pb, pos, SEEK_SET);
00090     put_be32(pb, curpos - pos); /* rewrite size */
00091     url_fseek(pb, curpos, SEEK_SET);
00092 
00093     return curpos - pos;
00094 }
00095 
00096 /* Chunk offset atom */
00097 static int mov_write_stco_tag(ByteIOContext *pb, MOVTrack *track)
00098 {
00099     int i;
00100     int mode64 = 0; //   use 32 bit size variant if possible
00101     int64_t pos = url_ftell(pb);
00102     put_be32(pb, 0); /* size */
00103     if (pos > UINT32_MAX) {
00104         mode64 = 1;
00105         put_tag(pb, "co64");
00106     } else
00107         put_tag(pb, "stco");
00108     put_be32(pb, 0); /* version & flags */
00109     put_be32(pb, track->entry); /* entry count */
00110     for (i=0; i<track->entry; i++) {
00111         if(mode64 == 1)
00112             put_be64(pb, track->cluster[i].pos);
00113         else
00114             put_be32(pb, track->cluster[i].pos);
00115     }
00116     return updateSize(pb, pos);
00117 }
00118 
00119 /* Sample size atom */
00120 static int mov_write_stsz_tag(ByteIOContext *pb, MOVTrack *track)
00121 {
00122     int equalChunks = 1;
00123     int i, j, entries = 0, tst = -1, oldtst = -1;
00124 
00125     int64_t pos = url_ftell(pb);
00126     put_be32(pb, 0); /* size */
00127     put_tag(pb, "stsz");
00128     put_be32(pb, 0); /* version & flags */
00129 
00130     for (i=0; i<track->entry; i++) {
00131         tst = track->cluster[i].size/track->cluster[i].entries;
00132         if(oldtst != -1 && tst != oldtst) {
00133             equalChunks = 0;
00134         }
00135         oldtst = tst;
00136         entries += track->cluster[i].entries;
00137     }
00138     if (equalChunks) {
00139         int sSize = track->cluster[0].size/track->cluster[0].entries;
00140         put_be32(pb, sSize); // sample size
00141         put_be32(pb, entries); // sample count
00142     }
00143     else {
00144         put_be32(pb, 0); // sample size
00145         put_be32(pb, entries); // sample count
00146         for (i=0; i<track->entry; i++) {
00147             for (j=0; j<track->cluster[i].entries; j++) {
00148                 put_be32(pb, track->cluster[i].size /
00149                          track->cluster[i].entries);
00150             }
00151         }
00152     }
00153     return updateSize(pb, pos);
00154 }
00155 
00156 /* Sample to chunk atom */
00157 static int mov_write_stsc_tag(ByteIOContext *pb, MOVTrack *track)
00158 {
00159     int index = 0, oldval = -1, i;
00160     int64_t entryPos, curpos;
00161 
00162     int64_t pos = url_ftell(pb);
00163     put_be32(pb, 0); /* size */
00164     put_tag(pb, "stsc");
00165     put_be32(pb, 0); // version & flags
00166     entryPos = url_ftell(pb);
00167     put_be32(pb, track->entry); // entry count
00168     for (i=0; i<track->entry; i++) {
00169         if(oldval != track->cluster[i].samplesInChunk)
00170         {
00171             put_be32(pb, i+1); // first chunk
00172             put_be32(pb, track->cluster[i].samplesInChunk); // samples per chunk
00173             put_be32(pb, 0x1); // sample description index
00174             oldval = track->cluster[i].samplesInChunk;
00175             index++;
00176         }
00177     }
00178     curpos = url_ftell(pb);
00179     url_fseek(pb, entryPos, SEEK_SET);
00180     put_be32(pb, index); // rewrite size
00181     url_fseek(pb, curpos, SEEK_SET);
00182 
00183     return updateSize(pb, pos);
00184 }
00185 
00186 /* Sync sample atom */
00187 static int mov_write_stss_tag(ByteIOContext *pb, MOVTrack *track)
00188 {
00189     int64_t curpos, entryPos;
00190     int i, index = 0;
00191     int64_t pos = url_ftell(pb);
00192     put_be32(pb, 0); // size
00193     put_tag(pb, "stss");
00194     put_be32(pb, 0); // version & flags
00195     entryPos = url_ftell(pb);
00196     put_be32(pb, track->entry); // entry count
00197     for (i=0; i<track->entry; i++) {
00198         if(track->cluster[i].key_frame == 1) {
00199             put_be32(pb, i+1);
00200             index++;
00201         }
00202     }
00203     curpos = url_ftell(pb);
00204     url_fseek(pb, entryPos, SEEK_SET);
00205     put_be32(pb, index); // rewrite size
00206     url_fseek(pb, curpos, SEEK_SET);
00207     return updateSize(pb, pos);
00208 }
00209 
00210 static int mov_write_amr_tag(ByteIOContext *pb, MOVTrack *track)
00211 {
00212     put_be32(pb, 0x11); /* size */
00213     if (track->mode == MODE_MOV) put_tag(pb, "samr");
00214     else                         put_tag(pb, "damr");
00215     put_tag(pb, "FFMP");
00216     put_byte(pb, 0); /* decoder version */
00217 
00218     put_be16(pb, 0x81FF); /* Mode set (all modes for AMR_NB) */
00219     put_byte(pb, 0x00); /* Mode change period (no restriction) */
00220     put_byte(pb, 0x01); /* Frames per sample */
00221     return 0x11;
00222 }
00223 
00224 static int mov_write_ac3_tag(ByteIOContext *pb, MOVTrack *track)
00225 {
00226     GetBitContext gbc;
00227     PutBitContext pbc;
00228     uint8_t buf[3];
00229     int fscod, bsid, bsmod, acmod, lfeon, frmsizecod;
00230 
00231     if (track->vosLen < 7)
00232         return -1;
00233 
00234     put_be32(pb, 11);
00235     put_tag(pb, "dac3");
00236 
00237     init_get_bits(&gbc, track->vosData+4, track->vosLen-4);
00238     fscod      = get_bits(&gbc, 2);
00239     frmsizecod = get_bits(&gbc, 6);
00240     bsid       = get_bits(&gbc, 5);
00241     bsmod      = get_bits(&gbc, 3);
00242     acmod      = get_bits(&gbc, 3);
00243     if (acmod == 2) {
00244         skip_bits(&gbc, 2); // dsurmod
00245     } else {
00246         if ((acmod & 1) && acmod != 1)
00247             skip_bits(&gbc, 2); // cmixlev
00248         if (acmod & 4)
00249             skip_bits(&gbc, 2); // surmixlev
00250     }
00251     lfeon = get_bits1(&gbc);
00252 
00253     init_put_bits(&pbc, buf, sizeof(buf));
00254     put_bits(&pbc, 2, fscod);
00255     put_bits(&pbc, 5, bsid);
00256     put_bits(&pbc, 3, bsmod);
00257     put_bits(&pbc, 3, acmod);
00258     put_bits(&pbc, 1, lfeon);
00259     put_bits(&pbc, 5, frmsizecod>>1); // bit_rate_code
00260     put_bits(&pbc, 5, 0); // reserved
00261 
00262     flush_put_bits(&pbc);
00263     put_buffer(pb, buf, sizeof(buf));
00264 
00265     return 11;
00266 }
00267 
00272 static int mov_write_extradata_tag(ByteIOContext *pb, MOVTrack *track)
00273 {
00274     put_buffer(pb, track->enc->extradata, track->enc->extradata_size);
00275     return track->enc->extradata_size;
00276 }
00277 
00278 static int mov_write_enda_tag(ByteIOContext *pb)
00279 {
00280     put_be32(pb, 10);
00281     put_tag(pb, "enda");
00282     put_be16(pb, 1); /* little endian */
00283     return 10;
00284 }
00285 
00286 static unsigned int descrLength(unsigned int len)
00287 {
00288     int i;
00289     for(i=1; len>>(7*i); i++);
00290     return len + 1 + i;
00291 }
00292 
00293 static void putDescr(ByteIOContext *pb, int tag, unsigned int size)
00294 {
00295     int i= descrLength(size) - size - 2;
00296     put_byte(pb, tag);
00297     for(; i>0; i--)
00298         put_byte(pb, (size>>(7*i)) | 0x80);
00299     put_byte(pb, size & 0x7F);
00300 }
00301 
00302 static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack *track) // Basic
00303 {
00304     int64_t pos = url_ftell(pb);
00305     int decoderSpecificInfoLen = track->vosLen ? descrLength(track->vosLen):0;
00306 
00307     put_be32(pb, 0); // size
00308     put_tag(pb, "esds");
00309     put_be32(pb, 0); // Version
00310 
00311     // ES descriptor
00312     putDescr(pb, 0x03, 3 + descrLength(13 + decoderSpecificInfoLen) +
00313              descrLength(1));
00314     put_be16(pb, track->trackID);
00315     put_byte(pb, 0x00); // flags (= no flags)
00316 
00317     // DecoderConfig descriptor
00318     putDescr(pb, 0x04, 13 + decoderSpecificInfoLen);
00319 
00320     // Object type indication
00321     if ((track->enc->codec_id == CODEC_ID_MP2 ||
00322          track->enc->codec_id == CODEC_ID_MP3) &&
00323         track->enc->sample_rate > 24000)
00324         put_byte(pb, 0x6B); // 11172-3
00325     else
00326         put_byte(pb, codec_get_tag(ff_mp4_obj_type, track->enc->codec_id));
00327 
00328     // the following fields is made of 6 bits to identify the streamtype (4 for video, 5 for audio)
00329     // plus 1 bit to indicate upstream and 1 bit set to 1 (reserved)
00330     if(track->enc->codec_type == CODEC_TYPE_AUDIO)
00331         put_byte(pb, 0x15); // flags (= Audiostream)
00332     else
00333         put_byte(pb, 0x11); // flags (= Visualstream)
00334 
00335     put_byte(pb,  track->enc->rc_buffer_size>>(3+16));    // Buffersize DB (24 bits)
00336     put_be16(pb, (track->enc->rc_buffer_size>>3)&0xFFFF); // Buffersize DB
00337 
00338     put_be32(pb, FFMAX(track->enc->bit_rate, track->enc->rc_max_rate)); // maxbitrate (FIXME should be max rate in any 1 sec window)
00339     if(track->enc->rc_max_rate != track->enc->rc_min_rate || track->enc->rc_min_rate==0)
00340         put_be32(pb, 0); // vbr
00341     else
00342         put_be32(pb, track->enc->rc_max_rate); // avg bitrate
00343 
00344     if (track->vosLen) {
00345         // DecoderSpecific info descriptor
00346         putDescr(pb, 0x05, track->vosLen);
00347         put_buffer(pb, track->vosData, track->vosLen);
00348     }
00349 
00350     // SL descriptor
00351     putDescr(pb, 0x06, 1);
00352     put_byte(pb, 0x02);
00353     return updateSize(pb, pos);
00354 }
00355 
00356 static int mov_write_wave_tag(ByteIOContext *pb, MOVTrack *track)
00357 {
00358     int64_t pos = url_ftell(pb);
00359 
00360     put_be32(pb, 0);     /* size */
00361     put_tag(pb, "wave");
00362 
00363     put_be32(pb, 12);    /* size */
00364     put_tag(pb, "frma");
00365     put_le32(pb, track->tag);
00366 
00367     if (track->enc->codec_id == CODEC_ID_AAC) {
00368         /* useless atom needed by mplayer, ipod, not needed by quicktime */
00369         put_be32(pb, 12); /* size */
00370         put_tag(pb, "mp4a");
00371         put_be32(pb, 0);
00372         mov_write_esds_tag(pb, track);
00373     } else if (track->enc->codec_id == CODEC_ID_PCM_S24LE ||
00374                track->enc->codec_id == CODEC_ID_PCM_S32LE) {
00375         mov_write_enda_tag(pb);
00376     } else if (track->enc->codec_id == CODEC_ID_AMR_NB) {
00377         mov_write_amr_tag(pb, track);
00378     } else if (track->enc->codec_id == CODEC_ID_AC3) {
00379         mov_write_ac3_tag(pb, track);
00380     } else if (track->enc->codec_id == CODEC_ID_ALAC) {
00381         mov_write_extradata_tag(pb, track);
00382     }
00383 
00384     put_be32(pb, 8);     /* size */
00385     put_be32(pb, 0);     /* null tag */
00386 
00387     return updateSize(pb, pos);
00388 }
00389 
00390 static int mov_write_glbl_tag(ByteIOContext *pb, MOVTrack *track)
00391 {
00392     put_be32(pb, track->vosLen+8);
00393     put_tag(pb, "glbl");
00394     put_buffer(pb, track->vosData, track->vosLen);
00395     return 8+track->vosLen;
00396 }
00397 
00398 static int mov_write_audio_tag(ByteIOContext *pb, MOVTrack *track)
00399 {
00400     int64_t pos = url_ftell(pb);
00401     int version = track->mode == MODE_MOV &&
00402         (track->audio_vbr ||
00403          track->enc->codec_id == CODEC_ID_PCM_S32LE ||
00404          track->enc->codec_id == CODEC_ID_PCM_S24LE);
00405 
00406     put_be32(pb, 0); /* size */
00407     put_le32(pb, track->tag); // store it byteswapped
00408     put_be32(pb, 0); /* Reserved */
00409     put_be16(pb, 0); /* Reserved */
00410     put_be16(pb, 1); /* Data-reference index, XXX  == 1 */
00411 
00412     /* SoundDescription */
00413     put_be16(pb, version); /* Version */
00414     put_be16(pb, 0); /* Revision level */
00415     put_be32(pb, 0); /* Reserved */
00416 
00417     if (track->mode == MODE_MOV) {
00418         put_be16(pb, track->enc->channels);
00419         if (track->enc->codec_id == CODEC_ID_PCM_U8 ||
00420             track->enc->codec_id == CODEC_ID_PCM_S8)
00421             put_be16(pb, 8); /* bits per sample */
00422         else
00423             put_be16(pb, 16);
00424         put_be16(pb, track->audio_vbr ? -2 : 0); /* compression ID */
00425     } else { /* reserved for mp4/3gp */
00426         put_be16(pb, 2);
00427         put_be16(pb, 16);
00428         put_be16(pb, 0);
00429     }
00430 
00431     put_be16(pb, 0); /* packet size (= 0) */
00432     put_be16(pb, track->timescale); /* Time scale */
00433     put_be16(pb, 0); /* Reserved */
00434 
00435     if(version == 1) { /* SoundDescription V1 extended info */
00436         put_be32(pb, track->enc->frame_size); /* Samples per packet */
00437         put_be32(pb, track->sampleSize / track->enc->channels); /* Bytes per packet */
00438         put_be32(pb, track->sampleSize); /* Bytes per frame */
00439         put_be32(pb, 2); /* Bytes per sample */
00440     }
00441 
00442     if(track->mode == MODE_MOV &&
00443        (track->enc->codec_id == CODEC_ID_AAC ||
00444         track->enc->codec_id == CODEC_ID_AC3 ||
00445         track->enc->codec_id == CODEC_ID_AMR_NB ||
00446         track->enc->codec_id == CODEC_ID_PCM_S24LE ||
00447         track->enc->codec_id == CODEC_ID_PCM_S32LE ||
00448         track->enc->codec_id == CODEC_ID_ALAC))
00449         mov_write_wave_tag(pb, track);
00450     else if(track->tag == MKTAG('m','p','4','a'))
00451         mov_write_esds_tag(pb, track);
00452     else if(track->enc->codec_id == CODEC_ID_AMR_NB)
00453         mov_write_amr_tag(pb, track);
00454     else if(track->enc->codec_id == CODEC_ID_AC3)
00455         mov_write_ac3_tag(pb, track);
00456     else if(track->enc->codec_id == CODEC_ID_ALAC)
00457         mov_write_extradata_tag(pb, track);
00458     else if(track->vosLen > 0)
00459         mov_write_glbl_tag(pb, track);
00460 
00461     return updateSize(pb, pos);
00462 }
00463 
00464 static int mov_write_d263_tag(ByteIOContext *pb)
00465 {
00466     put_be32(pb, 0xf); /* size */
00467     put_tag(pb, "d263");
00468     put_tag(pb, "FFMP");
00469     put_byte(pb, 0); /* decoder version */
00470     /* FIXME use AVCodecContext level/profile, when encoder will set values */
00471     put_byte(pb, 0xa); /* level */
00472     put_byte(pb, 0); /* profile */
00473     return 0xf;
00474 }
00475 
00476 /* TODO: No idea about these values */
00477 static int mov_write_svq3_tag(ByteIOContext *pb)
00478 {
00479     put_be32(pb, 0x15);
00480     put_tag(pb, "SMI ");
00481     put_tag(pb, "SEQH");
00482     put_be32(pb, 0x5);
00483     put_be32(pb, 0xe2c0211d);
00484     put_be32(pb, 0xc0000000);
00485     put_byte(pb, 0);
00486     return 0x15;
00487 }
00488 
00489 static int mov_write_avcc_tag(ByteIOContext *pb, MOVTrack *track)
00490 {
00491     int64_t pos = url_ftell(pb);
00492 
00493     put_be32(pb, 0);
00494     put_tag(pb, "avcC");
00495     ff_isom_write_avcc(pb, track->vosData, track->vosLen);
00496     return updateSize(pb, pos);
00497 }
00498 
00499 /* also used by all avid codecs (dv, imx, meridien) and their variants */
00500 static int mov_write_avid_tag(ByteIOContext *pb, MOVTrack *track)
00501 {
00502     int i;
00503     put_be32(pb, 24); /* size */
00504     put_tag(pb, "ACLR");
00505     put_tag(pb, "ACLR");
00506     put_tag(pb, "0001");
00507     put_be32(pb, 1); /* yuv 1 / rgb 2 ? */
00508     put_be32(pb, 0); /* unknown */
00509 
00510     put_be32(pb, 24); /* size */
00511     put_tag(pb, "APRG");
00512     put_tag(pb, "APRG");
00513     put_tag(pb, "0001");
00514     put_be32(pb, 1); /* unknown */
00515     put_be32(pb, 0); /* unknown */
00516 
00517     put_be32(pb, 120); /* size */
00518     put_tag(pb, "ARES");
00519     put_tag(pb, "ARES");
00520     put_tag(pb, "0001");
00521     put_be32(pb, AV_RB32(track->vosData + 0x28)); /* dnxhd cid, some id ? */
00522     put_be32(pb, track->enc->width);
00523     /* values below are based on samples created with quicktime and avid codecs */
00524     if (track->vosData[5] & 2) { // interlaced
00525         put_be32(pb, track->enc->height/2);
00526         put_be32(pb, 2); /* unknown */
00527         put_be32(pb, 0); /* unknown */
00528         put_be32(pb, 4); /* unknown */
00529     } else {
00530         put_be32(pb, track->enc->height);
00531         put_be32(pb, 1); /* unknown */
00532         put_be32(pb, 0); /* unknown */
00533         if (track->enc->height == 1080)
00534             put_be32(pb, 5); /* unknown */
00535         else
00536             put_be32(pb, 6); /* unknown */
00537     }
00538     /* padding */
00539     for (i = 0; i < 10; i++)
00540         put_be64(pb, 0);
00541 
00542     /* extra padding for stsd needed */
00543     put_be32(pb, 0);
00544     return 0;
00545 }
00546 
00547 static const AVCodecTag codec_3gp_tags[] = {
00548     { CODEC_ID_H263,   MKTAG('s','2','6','3') },
00549     { CODEC_ID_H264,   MKTAG('a','v','c','1') },
00550     { CODEC_ID_MPEG4,  MKTAG('m','p','4','v') },
00551     { CODEC_ID_AAC,    MKTAG('m','p','4','a') },
00552     { CODEC_ID_AMR_NB, MKTAG('s','a','m','r') },
00553     { CODEC_ID_AMR_WB, MKTAG('s','a','w','b') },
00554     { CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') },
00555     { CODEC_ID_NONE, 0 },
00556 };
00557 
00558 static const AVCodecTag mov_pix_fmt_tags[] = {
00559     { PIX_FMT_YUYV422, MKTAG('y','u','v','s') },
00560     { PIX_FMT_UYVY422, MKTAG('2','v','u','y') },
00561     { PIX_FMT_BGR555,  MKTAG('r','a','w',' ') },
00562     { PIX_FMT_RGB24,   MKTAG('r','a','w',' ') },
00563     { PIX_FMT_BGR32_1, MKTAG('r','a','w',' ') },
00564 };
00565 
00566 static const AVCodecTag codec_ipod_tags[] = {
00567     { CODEC_ID_H264,   MKTAG('a','v','c','1') },
00568     { CODEC_ID_MPEG4,  MKTAG('m','p','4','v') },
00569     { CODEC_ID_AAC,    MKTAG('m','p','4','a') },
00570     { CODEC_ID_ALAC,   MKTAG('a','l','a','c') },
00571     { CODEC_ID_AC3,    MKTAG('a','c','-','3') },
00572     { CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') },
00573     { CODEC_ID_NONE, 0 },
00574 };
00575 
00576 static int mov_find_codec_tag(AVFormatContext *s, MOVTrack *track)
00577 {
00578     int tag = track->enc->codec_tag;
00579     if (track->mode == MODE_MP4 || track->mode == MODE_PSP) {
00580         if (!codec_get_tag(ff_mp4_obj_type, track->enc->codec_id))
00581             return 0;
00582         if      (track->enc->codec_id == CODEC_ID_H264)      tag = MKTAG('a','v','c','1');
00583         else if (track->enc->codec_id == CODEC_ID_AC3)       tag = MKTAG('a','c','-','3');
00584         else if (track->enc->codec_id == CODEC_ID_DIRAC)     tag = MKTAG('d','r','a','c');
00585         else if (track->enc->codec_id == CODEC_ID_MOV_TEXT)  tag = MKTAG('t','x','3','g');
00586         else if (track->enc->codec_type == CODEC_TYPE_VIDEO) tag = MKTAG('m','p','4','v');
00587         else if (track->enc->codec_type == CODEC_TYPE_AUDIO) tag = MKTAG('m','p','4','a');
00588     } else if (track->mode == MODE_IPOD) {
00589         tag = codec_get_tag(codec_ipod_tags, track->enc->codec_id);
00590         if (!match_ext(s->filename, "m4a") && !match_ext(s->filename, "m4v"))
00591             av_log(s, AV_LOG_WARNING, "Warning, extension is not .m4a nor .m4v "
00592                    "Quicktime/Ipod might not play the file\n");
00593     } else if (track->mode & MODE_3GP) {
00594         tag = codec_get_tag(codec_3gp_tags, track->enc->codec_id);
00595     } else if (!tag || (track->enc->strict_std_compliance >= FF_COMPLIANCE_NORMAL &&
00596                         (tag == MKTAG('d','v','c','p') ||
00597                          track->enc->codec_id == CODEC_ID_RAWVIDEO))) {
00598         if (track->enc->codec_id == CODEC_ID_DVVIDEO) {
00599             if (track->enc->height == 480) /* NTSC */
00600                 if  (track->enc->pix_fmt == PIX_FMT_YUV422P) tag = MKTAG('d','v','5','n');
00601                 else                                         tag = MKTAG('d','v','c',' ');
00602             else if (track->enc->pix_fmt == PIX_FMT_YUV422P) tag = MKTAG('d','v','5','p');
00603             else if (track->enc->pix_fmt == PIX_FMT_YUV420P) tag = MKTAG('d','v','c','p');
00604             else                                             tag = MKTAG('d','v','p','p');
00605         } else if (track->enc->codec_id == CODEC_ID_RAWVIDEO) {
00606             tag = codec_get_tag(mov_pix_fmt_tags, track->enc->pix_fmt);
00607             if (!tag) // restore tag
00608                 tag = track->enc->codec_tag;
00609         } else {
00610             if (track->enc->codec_type == CODEC_TYPE_VIDEO) {
00611                 tag = codec_get_tag(codec_movvideo_tags, track->enc->codec_id);
00612                 if (!tag) { // if no mac fcc found, try with Microsoft tags
00613                     tag = codec_get_tag(codec_bmp_tags, track->enc->codec_id);
00614                     if (tag)
00615                         av_log(s, AV_LOG_INFO, "Warning, using MS style video codec tag, "
00616                                "the file may be unplayable!\n");
00617                 }
00618             } else if (track->enc->codec_type == CODEC_TYPE_AUDIO) {
00619                 tag = codec_get_tag(codec_movaudio_tags, track->enc->codec_id);
00620                 if (!tag) { // if no mac fcc found, try with Microsoft tags
00621                     int ms_tag = codec_get_tag(codec_wav_tags, track->enc->codec_id);
00622                     if (ms_tag) {
00623                         tag = MKTAG('m', 's', ((ms_tag >> 8) & 0xff), (ms_tag & 0xff));
00624                         av_log(s, AV_LOG_INFO, "Warning, using MS style audio codec tag, "
00625                                "the file may be unplayable!\n");
00626                     }
00627                 }
00628             } else if (track->enc->codec_type == CODEC_TYPE_SUBTITLE) {
00629                 tag = codec_get_tag(ff_codec_movsubtitle_tags, track->enc->codec_id);
00630             }
00631         }
00632     }
00633     return tag;
00634 }
00635 
00640 static int mov_write_uuid_tag_ipod(ByteIOContext *pb)
00641 {
00642     put_be32(pb, 28);
00643     put_tag(pb, "uuid");
00644     put_be32(pb, 0x6b6840f2);
00645     put_be32(pb, 0x5f244fc5);
00646     put_be32(pb, 0xba39a51b);
00647     put_be32(pb, 0xcf0323f3);
00648     put_be32(pb, 0x0);
00649     return 28;
00650 }
00651 
00652 static int mov_write_subtitle_tag(ByteIOContext *pb, MOVTrack *track)
00653 {
00654     int64_t pos = url_ftell(pb);
00655     put_be32(pb, 0);    /* size */
00656     put_le32(pb, track->tag); // store it byteswapped
00657     put_be32(pb, 0);    /* Reserved */
00658     put_be16(pb, 0);    /* Reserved */
00659     put_be16(pb, 1);    /* Data-reference index */
00660 
00661     if (track->enc->extradata_size)
00662         put_buffer(pb, track->enc->extradata, track->enc->extradata_size);
00663 
00664     return updateSize(pb, pos);
00665 }
00666 
00667 static int mov_write_video_tag(ByteIOContext *pb, MOVTrack *track)
00668 {
00669     int64_t pos = url_ftell(pb);
00670     char compressor_name[32];
00671 
00672     put_be32(pb, 0); /* size */
00673     put_le32(pb, track->tag); // store it byteswapped
00674     put_be32(pb, 0); /* Reserved */
00675     put_be16(pb, 0); /* Reserved */
00676     put_be16(pb, 1); /* Data-reference index */
00677 
00678     put_be16(pb, 0); /* Codec stream version */
00679     put_be16(pb, 0); /* Codec stream revision (=0) */
00680     if (track->mode == MODE_MOV) {
00681         put_tag(pb, "FFMP"); /* Vendor */
00682         if(track->enc->codec_id == CODEC_ID_RAWVIDEO) {
00683             put_be32(pb, 0); /* Temporal Quality */
00684             put_be32(pb, 0x400); /* Spatial Quality = lossless*/
00685         } else {
00686             put_be32(pb, 0x200); /* Temporal Quality = normal */
00687             put_be32(pb, 0x200); /* Spatial Quality = normal */
00688         }
00689     } else {
00690         put_be32(pb, 0); /* Reserved */
00691         put_be32(pb, 0); /* Reserved */
00692         put_be32(pb, 0); /* Reserved */
00693     }
00694     put_be16(pb, track->enc->width); /* Video width */
00695     put_be16(pb, track->height); /* Video height */
00696     put_be32(pb, 0x00480000); /* Horizontal resolution 72dpi */
00697     put_be32(pb, 0x00480000); /* Vertical resolution 72dpi */
00698     put_be32(pb, 0); /* Data size (= 0) */
00699     put_be16(pb, 1); /* Frame count (= 1) */
00700 
00701     memset(compressor_name,0,32);
00702     /* FIXME not sure, ISO 14496-1 draft where it shall be set to 0 */
00703     if (track->mode == MODE_MOV && track->enc->codec && track->enc->codec->name)
00704         strncpy(compressor_name,track->enc->codec->name,31);
00705     put_byte(pb, strlen(compressor_name));
00706     put_buffer(pb, compressor_name, 31);
00707 
00708     if (track->mode == MODE_MOV && track->enc->bits_per_coded_sample)
00709         put_be16(pb, track->enc->bits_per_coded_sample);
00710     else
00711         put_be16(pb, 0x18); /* Reserved */
00712     put_be16(pb, 0xffff); /* Reserved */
00713     if(track->tag == MKTAG('m','p','4','v'))
00714         mov_write_esds_tag(pb, track);
00715     else if(track->enc->codec_id == CODEC_ID_H263)
00716         mov_write_d263_tag(pb);
00717     else if(track->enc->codec_id == CODEC_ID_SVQ3)
00718         mov_write_svq3_tag(pb);
00719     else if(track->enc->codec_id == CODEC_ID_DNXHD)
00720         mov_write_avid_tag(pb, track);
00721     else if(track->enc->codec_id == CODEC_ID_H264) {
00722         mov_write_avcc_tag(pb, track);
00723         if(track->mode == MODE_IPOD)
00724             mov_write_uuid_tag_ipod(pb);
00725     } else if(track->vosLen > 0)
00726         mov_write_glbl_tag(pb, track);
00727 
00728     return updateSize(pb, pos);
00729 }
00730 
00731 static int mov_write_stsd_tag(ByteIOContext *pb, MOVTrack *track)
00732 {
00733     int64_t pos = url_ftell(pb);
00734     put_be32(pb, 0); /* size */
00735     put_tag(pb, "stsd");
00736     put_be32(pb, 0); /* version & flags */
00737     put_be32(pb, 1); /* entry count */
00738     if (track->enc->codec_type == CODEC_TYPE_VIDEO)
00739         mov_write_video_tag(pb, track);
00740     else if (track->enc->codec_type == CODEC_TYPE_AUDIO)
00741         mov_write_audio_tag(pb, track);
00742     else if (track->enc->codec_type == CODEC_TYPE_SUBTITLE)
00743         mov_write_subtitle_tag(pb, track);
00744     return updateSize(pb, pos);
00745 }
00746 
00747 static int mov_write_ctts_tag(ByteIOContext *pb, MOVTrack *track)
00748 {
00749     MOVStts *ctts_entries;
00750     uint32_t entries = 0;
00751     uint32_t atom_size;
00752     int i;
00753 
00754     ctts_entries = av_malloc((track->entry + 1) * sizeof(*ctts_entries)); /* worst case */
00755     ctts_entries[0].count = 1;
00756     ctts_entries[0].duration = track->cluster[0].cts;
00757     for (i=1; i<track->entry; i++) {
00758         if (track->cluster[i].cts == ctts_entries[entries].duration) {
00759             ctts_entries[entries].count++; /* compress */
00760         } else {
00761             entries++;
00762             ctts_entries[entries].duration = track->cluster[i].cts;
00763             ctts_entries[entries].count = 1;
00764         }
00765     }
00766     entries++; /* last one */
00767     atom_size = 16 + (entries * 8);
00768     put_be32(pb, atom_size); /* size */
00769     put_tag(pb, "ctts");
00770     put_be32(pb, 0); /* version & flags */
00771     put_be32(pb, entries); /* entry count */
00772     for (i=0; i<entries; i++) {
00773         put_be32(pb, ctts_entries[i].count);
00774         put_be32(pb, ctts_entries[i].duration);
00775     }
00776     av_free(ctts_entries);
00777     return atom_size;
00778 }
00779 
00780 /* Time to sample atom */
00781 static int mov_write_stts_tag(ByteIOContext *pb, MOVTrack *track)
00782 {
00783     MOVStts *stts_entries;
00784     uint32_t entries = -1;
00785     uint32_t atom_size;
00786     int i;
00787 
00788     if (track->enc->codec_type == CODEC_TYPE_AUDIO && !track->audio_vbr) {
00789         stts_entries = av_malloc(sizeof(*stts_entries)); /* one entry */
00790         stts_entries[0].count = track->sampleCount;
00791         stts_entries[0].duration = 1;
00792         entries = 1;
00793     } else {
00794         stts_entries = av_malloc(track->entry * sizeof(*stts_entries)); /* worst case */
00795         for (i=0; i<track->entry; i++) {
00796             int64_t duration = i + 1 == track->entry ?
00797                 track->trackDuration - track->cluster[i].dts + track->cluster[0].dts : /* readjusting */
00798                 track->cluster[i+1].dts - track->cluster[i].dts;
00799             if (i && duration == stts_entries[entries].duration) {
00800                 stts_entries[entries].count++; /* compress */
00801             } else {
00802                 entries++;
00803                 stts_entries[entries].duration = duration;
00804                 stts_entries[entries].count = 1;
00805             }
00806         }
00807         entries++; /* last one */
00808     }
00809     atom_size = 16 + (entries * 8);
00810     put_be32(pb, atom_size); /* size */
00811     put_tag(pb, "stts");
00812     put_be32(pb, 0); /* version & flags */
00813     put_be32(pb, entries); /* entry count */
00814     for (i=0; i<entries; i++) {
00815         put_be32(pb, stts_entries[i].count);
00816         put_be32(pb, stts_entries[i].duration);
00817     }
00818     av_free(stts_entries);
00819     return atom_size;
00820 }
00821 
00822 static int mov_write_dref_tag(ByteIOContext *pb)
00823 {
00824     put_be32(pb, 28); /* size */
00825     put_tag(pb, "dref");
00826     put_be32(pb, 0); /* version & flags */
00827     put_be32(pb, 1); /* entry count */
00828 
00829     put_be32(pb, 0xc); /* size */
00830     put_tag(pb, "url ");
00831     put_be32(pb, 1); /* version & flags */
00832 
00833     return 28;
00834 }
00835 
00836 static int mov_write_stbl_tag(ByteIOContext *pb, MOVTrack *track)
00837 {
00838     int64_t pos = url_ftell(pb);
00839     put_be32(pb, 0); /* size */
00840     put_tag(pb, "stbl");
00841     mov_write_stsd_tag(pb, track);
00842     mov_write_stts_tag(pb, track);
00843     if (track->enc->codec_type == CODEC_TYPE_VIDEO &&
00844         track->hasKeyframes && track->hasKeyframes < track->entry)
00845         mov_write_stss_tag(pb, track);
00846     if (track->enc->codec_type == CODEC_TYPE_VIDEO &&
00847         track->hasBframes)
00848         mov_write_ctts_tag(pb, track);
00849     mov_write_stsc_tag(pb, track);
00850     mov_write_stsz_tag(pb, track);
00851     mov_write_stco_tag(pb, track);
00852     return updateSize(pb, pos);
00853 }
00854 
00855 static int mov_write_dinf_tag(ByteIOContext *pb)
00856 {
00857     int64_t pos = url_ftell(pb);
00858     put_be32(pb, 0); /* size */
00859     put_tag(pb, "dinf");
00860     mov_write_dref_tag(pb);
00861     return updateSize(pb, pos);
00862 }
00863 
00864 static int mov_write_nmhd_tag(ByteIOContext *pb)
00865 {
00866     put_be32(pb, 12);
00867     put_tag(pb, "nmhd");
00868     put_be32(pb, 0);
00869     return 12;
00870 }
00871 
00872 static int mov_write_gmhd_tag(ByteIOContext *pb)
00873 {
00874     put_be32(pb, 0x20);   /* size */
00875     put_tag(pb, "gmhd");
00876     put_be32(pb, 0x18);   /* gmin size */
00877     put_tag(pb, "gmin");  /* generic media info */
00878     put_be32(pb, 0);      /* version & flags */
00879     put_be16(pb, 0x40);   /* graphics mode = */
00880     put_be16(pb, 0x8000); /* opColor (r?) */
00881     put_be16(pb, 0x8000); /* opColor (g?) */
00882     put_be16(pb, 0x8000); /* opColor (b?) */
00883     put_be16(pb, 0);      /* balance */
00884     put_be16(pb, 0);      /* reserved */
00885     return 0x20;
00886 }
00887 
00888 static int mov_write_smhd_tag(ByteIOContext *pb)
00889 {
00890     put_be32(pb, 16); /* size */
00891     put_tag(pb, "smhd");
00892     put_be32(pb, 0); /* version & flags */
00893     put_be16(pb, 0); /* reserved (balance, normally = 0) */
00894     put_be16(pb, 0); /* reserved */
00895     return 16;
00896 }
00897 
00898 static int mov_write_vmhd_tag(ByteIOContext *pb)
00899 {
00900     put_be32(pb, 0x14); /* size (always 0x14) */
00901     put_tag(pb, "vmhd");
00902     put_be32(pb, 0x01); /* version & flags */
00903     put_be64(pb, 0); /* reserved (graphics mode = copy) */
00904     return 0x14;
00905 }
00906 
00907 static int mov_write_hdlr_tag(ByteIOContext *pb, MOVTrack *track)
00908 {
00909     const char *hdlr, *descr = NULL, *hdlr_type = NULL;
00910     int64_t pos = url_ftell(pb);
00911 
00912     if (!track) { /* no media --> data handler */
00913         hdlr = "dhlr";
00914         hdlr_type = "url ";
00915         descr = "DataHandler";
00916     } else {
00917         hdlr = (track->mode == MODE_MOV) ? "mhlr" : "\0\0\0\0";
00918         if (track->enc->codec_type == CODEC_TYPE_VIDEO) {
00919             hdlr_type = "vide";
00920             descr = "VideoHandler";
00921         } else if (track->enc->codec_type == CODEC_TYPE_AUDIO) {
00922             hdlr_type = "soun";
00923             descr = "SoundHandler";
00924         } else if (track->enc->codec_type == CODEC_TYPE_SUBTITLE) {
00925             if (track->mode == MODE_IPOD) hdlr_type = "sbtl";
00926             else                          hdlr_type = "text";
00927             descr = "SubtitleHandler";
00928         }
00929     }
00930 
00931     put_be32(pb, 0); /* size */
00932     put_tag(pb, "hdlr");
00933     put_be32(pb, 0); /* Version & flags */
00934     put_buffer(pb, hdlr, 4); /* handler */
00935     put_tag(pb, hdlr_type); /* handler type */
00936     put_be32(pb ,0); /* reserved */
00937     put_be32(pb ,0); /* reserved */
00938     put_be32(pb ,0); /* reserved */
00939     put_byte(pb, strlen(descr)); /* string counter */
00940     put_buffer(pb, descr, strlen(descr)); /* handler description */
00941     return updateSize(pb, pos);
00942 }
00943 
00944 static int mov_write_minf_tag(ByteIOContext *pb, MOVTrack *track)
00945 {
00946     int64_t pos = url_ftell(pb);
00947     put_be32(pb, 0); /* size */
00948     put_tag(pb, "minf");
00949     if(track->enc->codec_type == CODEC_TYPE_VIDEO)
00950         mov_write_vmhd_tag(pb);
00951     else if (track->enc->codec_type == CODEC_TYPE_AUDIO)
00952         mov_write_smhd_tag(pb);
00953     else if (track->enc->codec_type == CODEC_TYPE_SUBTITLE) {
00954         if (track->mode == MODE_MOV) mov_write_gmhd_tag(pb);
00955         else                         mov_write_nmhd_tag(pb);
00956     }
00957     if (track->mode == MODE_MOV) /* FIXME: Why do it for MODE_MOV only ? */
00958         mov_write_hdlr_tag(pb, NULL);
00959     mov_write_dinf_tag(pb);
00960     mov_write_stbl_tag(pb, track);
00961     return updateSize(pb, pos);
00962 }
00963 
00964 static int mov_write_mdhd_tag(ByteIOContext *pb, MOVTrack *track)
00965 {
00966     int version = track->trackDuration < INT32_MAX ? 0 : 1;
00967 
00968     (version == 1) ? put_be32(pb, 44) : put_be32(pb, 32); /* size */
00969     put_tag(pb, "mdhd");
00970     put_byte(pb, version);
00971     put_be24(pb, 0); /* flags */
00972     if (version == 1) {
00973         put_be64(pb, track->time);
00974         put_be64(pb, track->time);
00975     } else {
00976         put_be32(pb, track->time); /* creation time */
00977         put_be32(pb, track->time); /* modification time */
00978     }
00979     put_be32(pb, track->timescale); /* time scale (sample rate for audio) */
00980     (version == 1) ? put_be64(pb, track->trackDuration) : put_be32(pb, track->trackDuration); /* duration */
00981     put_be16(pb, track->language); /* language */
00982     put_be16(pb, 0); /* reserved (quality) */
00983 
00984     if(version!=0 && track->mode == MODE_MOV){
00985         av_log(NULL, AV_LOG_ERROR,
00986             "FATAL error, file duration too long for timebase, this file will not be\n"
00987             "playable with quicktime. Choose a different timebase or a different\n"
00988             "container format\n");
00989     }
00990 
00991     return 32;
00992 }
00993 
00994 static int mov_write_mdia_tag(ByteIOContext *pb, MOVTrack *track)
00995 {
00996     int64_t pos = url_ftell(pb);
00997     put_be32(pb, 0); /* size */
00998     put_tag(pb, "mdia");
00999     mov_write_mdhd_tag(pb, track);
01000     mov_write_hdlr_tag(pb, track);
01001     mov_write_minf_tag(pb, track);
01002     return updateSize(pb, pos);
01003 }
01004 
01005 static int mov_write_tkhd_tag(ByteIOContext *pb, MOVTrack *track, AVStream *st)
01006 {
01007     int64_t duration = av_rescale_rnd(track->trackDuration, globalTimescale, track->timescale, AV_ROUND_UP);
01008     int version = duration < INT32_MAX ? 0 : 1;
01009 
01010     (version == 1) ? put_be32(pb, 104) : put_be32(pb, 92); /* size */
01011     put_tag(pb, "tkhd");
01012     put_byte(pb, version);
01013     put_be24(pb, 0xf); /* flags (track enabled) */
01014     if (version == 1) {
01015         put_be64(pb, track->time);
01016         put_be64(pb, track->time);
01017     } else {
01018         put_be32(pb, track->time); /* creation time */
01019         put_be32(pb, track->time); /* modification time */
01020     }
01021     put_be32(pb, track->trackID); /* track-id */
01022     put_be32(pb, 0); /* reserved */
01023     (version == 1) ? put_be64(pb, duration) : put_be32(pb, duration);
01024 
01025     put_be32(pb, 0); /* reserved */
01026     put_be32(pb, 0); /* reserved */
01027     put_be32(pb, 0x0); /* reserved (Layer & Alternate group) */
01028     /* Volume, only for audio */
01029     if(track->enc->codec_type == CODEC_TYPE_AUDIO)
01030         put_be16(pb, 0x0100);
01031     else
01032         put_be16(pb, 0);
01033     put_be16(pb, 0); /* reserved */
01034 
01035     /* Matrix structure */
01036     put_be32(pb, 0x00010000); /* reserved */
01037     put_be32(pb, 0x0); /* reserved */
01038     put_be32(pb, 0x0); /* reserved */
01039     put_be32(pb, 0x0); /* reserved */
01040     put_be32(pb, 0x00010000); /* reserved */
01041     put_be32(pb, 0x0); /* reserved */
01042     put_be32(pb, 0x0); /* reserved */
01043     put_be32(pb, 0x0); /* reserved */
01044     put_be32(pb, 0x40000000); /* reserved */
01045 
01046     /* Track width and height, for visual only */
01047     if(track->enc->codec_type == CODEC_TYPE_VIDEO ||
01048        track->enc->codec_type == CODEC_TYPE_SUBTITLE) {
01049         double sample_aspect_ratio = av_q2d(st->sample_aspect_ratio);
01050         if(!sample_aspect_ratio || track->height != track->enc->height)
01051             sample_aspect_ratio = 1;
01052         put_be32(pb, sample_aspect_ratio * track->enc->width*0x10000);
01053         put_be32(pb, track->height*0x10000);
01054     }
01055     else {
01056         put_be32(pb, 0);
01057         put_be32(pb, 0);
01058     }
01059     return 0x5c;
01060 }
01061 
01062 // This box seems important for the psp playback ... without it the movie seems to hang
01063 static int mov_write_edts_tag(ByteIOContext *pb, MOVTrack *track)
01064 {
01065     put_be32(pb, 0x24); /* size  */
01066     put_tag(pb, "edts");
01067     put_be32(pb, 0x1c); /* size  */
01068     put_tag(pb, "elst");
01069     put_be32(pb, 0x0);
01070     put_be32(pb, 0x1);
01071 
01072     put_be32(pb, av_rescale_rnd(track->trackDuration, globalTimescale, track->timescale, AV_ROUND_UP)); /* duration   ... doesn't seem to effect psp */
01073 
01074     put_be32(pb, track->cluster[0].cts); /* first pts is cts since dts is 0 */
01075     put_be32(pb, 0x00010000);
01076     return 0x24;
01077 }
01078 
01079 // goes at the end of each track!  ... Critical for PSP playback ("Incompatible data" without it)
01080 static int mov_write_uuid_tag_psp(ByteIOContext *pb, MOVTrack *mov)
01081 {
01082     put_be32(pb, 0x34); /* size ... reports as 28 in mp4box! */
01083     put_tag(pb, "uuid");
01084     put_tag(pb, "USMT");
01085     put_be32(pb, 0x21d24fce);
01086     put_be32(pb, 0xbb88695c);
01087     put_be32(pb, 0xfac9c740);
01088     put_be32(pb, 0x1c);     // another size here!
01089     put_tag(pb, "MTDT");
01090     put_be32(pb, 0x00010012);
01091     put_be32(pb, 0x0a);
01092     put_be32(pb, 0x55c40000);
01093     put_be32(pb, 0x1);
01094     put_be32(pb, 0x0);
01095     return 0x34;
01096 }
01097 
01098 static int mov_write_trak_tag(ByteIOContext *pb, MOVTrack *track, AVStream *st)
01099 {
01100     int64_t pos = url_ftell(pb);
01101     put_be32(pb, 0); /* size */
01102     put_tag(pb, "trak");
01103     mov_write_tkhd_tag(pb, track, st);
01104     if (track->mode == MODE_PSP || track->hasBframes)
01105         mov_write_edts_tag(pb, track);  // PSP Movies require edts box
01106     mov_write_mdia_tag(pb, track);
01107     if (track->mode == MODE_PSP)
01108         mov_write_uuid_tag_psp(pb,track);  // PSP Movies require this uuid box
01109     return updateSize(pb, pos);
01110 }
01111 
01112 #if 0
01113 /* TODO: Not sorted out, but not necessary either */
01114 static int mov_write_iods_tag(ByteIOContext *pb, MOVMuxContext *mov)
01115 {
01116     put_be32(pb, 0x15); /* size */
01117     put_tag(pb, "iods");
01118     put_be32(pb, 0);    /* version & flags */
01119     put_be16(pb, 0x1007);
01120     put_byte(pb, 0);
01121     put_be16(pb, 0x4fff);
01122     put_be16(pb, 0xfffe);
01123     put_be16(pb, 0x01ff);
01124     return 0x15;
01125 }
01126 #endif
01127 
01128 static int mov_write_mvhd_tag(ByteIOContext *pb, MOVMuxContext *mov)
01129 {
01130     int maxTrackID = 1, i;
01131     int64_t maxTrackLenTemp, maxTrackLen = 0;
01132     int version;
01133 
01134     for (i=0; i<mov->nb_streams; i++) {
01135         if(mov->tracks[i].entry > 0) {
01136             maxTrackLenTemp = av_rescale_rnd(mov->tracks[i].trackDuration, globalTimescale, mov->tracks[i].timescale, AV_ROUND_UP);
01137             if(maxTrackLen < maxTrackLenTemp)
01138                 maxTrackLen = maxTrackLenTemp;
01139             if(maxTrackID < mov->tracks[i].trackID)
01140                 maxTrackID = mov->tracks[i].trackID;
01141         }
01142     }
01143 
01144     version = maxTrackLen < UINT32_MAX ? 0 : 1;
01145     (version == 1) ? put_be32(pb, 120) : put_be32(pb, 108); /* size */
01146     put_tag(pb, "mvhd");
01147     put_byte(pb, version);
01148     put_be24(pb, 0); /* flags */
01149     if (version == 1) {
01150         put_be64(pb, mov->time);
01151         put_be64(pb, mov->time);
01152     } else {
01153         put_be32(pb, mov->time); /* creation time */
01154         put_be32(pb, mov->time); /* modification time */
01155     }
01156     put_be32(pb, mov->timescale); /* timescale */
01157     (version == 1) ? put_be64(pb, maxTrackLen) : put_be32(pb, maxTrackLen); /* duration of longest track */
01158 
01159     put_be32(pb, 0x00010000); /* reserved (preferred rate) 1.0 = normal */
01160     put_be16(pb, 0x0100); /* reserved (preferred volume) 1.0 = normal */
01161     put_be16(pb, 0); /* reserved */
01162     put_be32(pb, 0); /* reserved */
01163     put_be32(pb, 0); /* reserved */
01164 
01165     /* Matrix structure */
01166     put_be32(pb, 0x00010000); /* reserved */
01167     put_be32(pb, 0x0); /* reserved */
01168     put_be32(pb, 0x0); /* reserved */
01169     put_be32(pb, 0x0); /* reserved */
01170     put_be32(pb, 0x00010000); /* reserved */
01171     put_be32(pb, 0x0); /* reserved */
01172     put_be32(pb, 0x0); /* reserved */
01173     put_be32(pb, 0x0); /* reserved */
01174     put_be32(pb, 0x40000000); /* reserved */
01175 
01176     put_be32(pb, 0); /* reserved (preview time) */
01177     put_be32(pb, 0); /* reserved (preview duration) */
01178     put_be32(pb, 0); /* reserved (poster time) */
01179     put_be32(pb, 0); /* reserved (selection time) */
01180     put_be32(pb, 0); /* reserved (selection duration) */
01181     put_be32(pb, 0); /* reserved (current time) */
01182     put_be32(pb, maxTrackID+1); /* Next track id */
01183     return 0x6c;
01184 }
01185 
01186 static int mov_write_itunes_hdlr_tag(ByteIOContext *pb, MOVMuxContext *mov,
01187                                      AVFormatContext *s)
01188 {
01189     int64_t pos = url_ftell(pb);
01190     put_be32(pb, 0); /* size */
01191     put_tag(pb, "hdlr");
01192     put_be32(pb, 0);
01193     put_be32(pb, 0);
01194     put_tag(pb, "mdir");
01195     put_tag(pb, "appl");
01196     put_be32(pb, 0);
01197     put_be32(pb, 0);
01198     put_be16(pb, 0);
01199     return updateSize(pb, pos);
01200 }
01201 
01202 /* helper function to write a data tag with the specified string as data */
01203 static int mov_write_string_data_tag(ByteIOContext *pb, const char *data, int lang, int long_style)
01204 {
01205     if(long_style){
01206         int64_t pos = url_ftell(pb);
01207         put_be32(pb, 0); /* size */
01208         put_tag(pb, "data");
01209         put_be32(pb, 1);
01210         put_be32(pb, 0);
01211         put_buffer(pb, data, strlen(data));
01212         return updateSize(pb, pos);
01213     }else{
01214         put_be16(pb, strlen(data)); /* string length */
01215         put_be16(pb, lang);
01216         put_buffer(pb, data, strlen(data));
01217         return strlen(data) + 4;
01218     }
01219 }
01220 
01221 static int mov_write_string_tag(ByteIOContext *pb, const char *name, const char *value, int lang, int long_style){
01222     int size = 0;
01223     if (value && value[0]) {
01224         int64_t pos = url_ftell(pb);
01225         put_be32(pb, 0); /* size */
01226         put_tag(pb, name);
01227         mov_write_string_data_tag(pb, value, lang, long_style);
01228         size= updateSize(pb, pos);
01229     }
01230     return size;
01231 }
01232 
01233 static int mov_write_string_metadata(AVFormatContext *s, ByteIOContext *pb,
01234                                      const char *name, const char *tag,
01235                                      int long_style)
01236 {
01237     int l, lang = 0, len, len2;
01238     AVMetadataTag *t, *t2 = NULL;
01239     char tag2[16];
01240 
01241     if (!(t = av_metadata_get(s->metadata, tag, NULL, 0)))
01242         return 0;
01243 
01244     len = strlen(t->key);
01245     snprintf(tag2, sizeof(tag2), "%s-", tag);
01246     while ((t2 = av_metadata_get(s->metadata, tag2, t2, AV_METADATA_IGNORE_SUFFIX))) {
01247         len2 = strlen(t2->key);
01248         if (len2 == len+4 && !strcmp(t->value, t2->value)
01249             && (l=ff_mov_iso639_to_lang(&t2->key[len2-3], 0)) >= 0) {
01250             lang = l;
01251             break;
01252         }
01253     }
01254     return mov_write_string_tag(pb, name, t->value, lang, long_style);
01255 }
01256 
01257 /* iTunes track number */
01258 static int mov_write_trkn_tag(ByteIOContext *pb, MOVMuxContext *mov,
01259                               AVFormatContext *s)
01260 {
01261     AVMetadataTag *t = av_metadata_get(s->metadata, "track", NULL, 0);
01262     int size = 0, track = t ? atoi(t->value) : 0;
01263     if (track) {
01264         int64_t pos = url_ftell(pb);
01265         put_be32(pb, 0); /* size */
01266         put_tag(pb, "trkn");
01267         {
01268             int64_t pos = url_ftell(pb);
01269             put_be32(pb, 0); /* size */
01270             put_tag(pb, "data");
01271             put_be32(pb, 0);        // 8 bytes empty
01272             put_be32(pb, 0);
01273             put_be16(pb, 0);        // empty
01274             put_be16(pb, track);    // track number
01275             put_be16(pb, 0);        // total track number
01276             put_be16(pb, 0);        // empty
01277             updateSize(pb, pos);
01278         }
01279         size = updateSize(pb, pos);
01280     }
01281     return size;
01282 }
01283 
01284 /* iTunes meta data list */
01285 static int mov_write_ilst_tag(ByteIOContext *pb, MOVMuxContext *mov,
01286                               AVFormatContext *s)
01287 {
01288     int64_t pos = url_ftell(pb);
01289     put_be32(pb, 0); /* size */
01290     put_tag(pb, "ilst");
01291     mov_write_string_metadata(s, pb, "\251nam", "title"    , 1);
01292     mov_write_string_metadata(s, pb, "\251ART", "author"   , 1);
01293     mov_write_string_metadata(s, pb, "\251wrt", "author"   , 1);
01294     mov_write_string_metadata(s, pb, "\251alb", "album"    , 1);
01295     mov_write_string_metadata(s, pb, "\251day", "year"     , 1);
01296     mov_write_string_tag(pb, "\251too", LIBAVFORMAT_IDENT, 0, 1);
01297     mov_write_string_metadata(s, pb, "\251cmt", "comment"  , 1);
01298     mov_write_string_metadata(s, pb, "\251gen", "genre"    , 1);
01299     mov_write_string_metadata(s, pb, "\251cpy", "copyright", 1);
01300     mov_write_trkn_tag(pb, mov, s);
01301     return updateSize(pb, pos);
01302 }
01303 
01304 /* iTunes meta data tag */
01305 static int mov_write_meta_tag(ByteIOContext *pb, MOVMuxContext *mov,
01306                               AVFormatContext *s)
01307 {
01308     int size = 0;
01309     int64_t pos = url_ftell(pb);
01310     put_be32(pb, 0); /* size */
01311     put_tag(pb, "meta");
01312     put_be32(pb, 0);
01313     mov_write_itunes_hdlr_tag(pb, mov, s);
01314     mov_write_ilst_tag(pb, mov, s);
01315     size = updateSize(pb, pos);
01316     return size;
01317 }
01318 
01319 static int utf8len(const uint8_t *b)
01320 {
01321     int len=0;
01322     int val;
01323     while(*b){
01324         GET_UTF8(val, *b++, return -1;)
01325         len++;
01326     }
01327     return len;
01328 }
01329 
01330 static int ascii_to_wc(ByteIOContext *pb, const uint8_t *b)
01331 {
01332     int val;
01333     while(*b){
01334         GET_UTF8(val, *b++, return -1;)
01335         put_be16(pb, val);
01336     }
01337     put_be16(pb, 0x00);
01338     return 0;
01339 }
01340 
01341 static uint16_t language_code(const char *str)
01342 {
01343     return (((str[0]-0x60) & 0x1F) << 10) + (((str[1]-0x60) & 0x1F) << 5) + ((str[2]-0x60) & 0x1F);
01344 }
01345 
01346 static int mov_write_3gp_udta_tag(ByteIOContext *pb, AVFormatContext *s,
01347                                   const char *tag, const char *str)
01348 {
01349     int64_t pos = url_ftell(pb);
01350     AVMetadataTag *t = av_metadata_get(s->metadata, str, NULL, 0);
01351     if (!t || !utf8len(t->value))
01352         return 0;
01353     put_be32(pb, 0);   /* size */
01354     put_tag (pb, tag); /* type */
01355     put_be32(pb, 0);   /* version + flags */
01356     if (!strcmp(tag, "yrrc"))
01357         put_be16(pb, atoi(t->value));
01358     else {
01359         put_be16(pb, language_code("eng")); /* language */
01360         ascii_to_wc(pb, t->value);
01361         if (!strcmp(tag, "albm") &&
01362             (t = av_metadata_get(s->metadata, "year", NULL, 0)))
01363             put_byte(pb, atoi(t->value));
01364     }
01365     return updateSize(pb, pos);
01366 }
01367 
01368 static int mov_write_udta_tag(ByteIOContext *pb, MOVMuxContext *mov,
01369                               AVFormatContext *s)
01370 {
01371     ByteIOContext *pb_buf;
01372     int i, ret, size;
01373     uint8_t *buf;
01374 
01375     for (i = 0; i < s->nb_streams; i++)
01376         if (mov->tracks[i].enc->flags & CODEC_FLAG_BITEXACT) {
01377             return 0;
01378         }
01379 
01380     ret = url_open_dyn_buf(&pb_buf);
01381     if(ret < 0)
01382         return ret;
01383 
01384         if (mov->mode & MODE_3GP) {
01385             mov_write_3gp_udta_tag(pb_buf, s, "titl", "title");
01386             mov_write_3gp_udta_tag(pb_buf, s, "auth", "author");
01387             mov_write_3gp_udta_tag(pb_buf, s, "gnre", "genre");
01388             mov_write_3gp_udta_tag(pb_buf, s, "dscp", "comment");
01389             mov_write_3gp_udta_tag(pb_buf, s, "albm", "album");
01390             mov_write_3gp_udta_tag(pb_buf, s, "cprt", "copyright");
01391             mov_write_3gp_udta_tag(pb_buf, s, "yrrc", "year");
01392         } else if (mov->mode == MODE_MOV) { // the title field breaks gtkpod with mp4 and my suspicion is that stuff is not valid in mp4
01393             mov_write_string_metadata(s, pb_buf, "\251nam", "title"      , 0);
01394             mov_write_string_metadata(s, pb_buf, "\251aut", "author"     , 0);
01395             mov_write_string_metadata(s, pb_buf, "\251alb", "album"      , 0);
01396             mov_write_string_metadata(s, pb_buf, "\251day", "year"       , 0);
01397             mov_write_string_tag(pb_buf, "\251enc", LIBAVFORMAT_IDENT, 0, 0);
01398             mov_write_string_metadata(s, pb_buf, "\251des", "comment"    , 0);
01399             mov_write_string_metadata(s, pb_buf, "\251gen", "genre"      , 0);
01400             mov_write_string_metadata(s, pb_buf, "\251cpy", "copyright"  , 0);
01401         } else {
01402             /* iTunes meta data */
01403             mov_write_meta_tag(pb_buf, mov, s);
01404         }
01405 
01406     if ((size = url_close_dyn_buf(pb_buf, &buf)) > 0) {
01407         put_be32(pb, size+8);
01408         put_tag(pb, "udta");
01409         put_buffer(pb, buf, size);
01410         av_free(buf);
01411     }
01412 
01413     return 0;
01414 }
01415 
01416 static void mov_write_psp_udta_tag(ByteIOContext *pb,
01417                                   const char *str, const char *lang, int type)
01418 {
01419     int len = utf8len(str)+1;
01420     if(len<=0)
01421         return;
01422     put_be16(pb, len*2+10);            /* size */
01423     put_be32(pb, type);                /* type */
01424     put_be16(pb, language_code(lang)); /* language */
01425     put_be16(pb, 0x01);                /* ? */
01426     ascii_to_wc(pb, str);
01427 }
01428 
01429 static int mov_write_uuidusmt_tag(ByteIOContext *pb, AVFormatContext *s)
01430 {
01431     AVMetadataTag *title = av_metadata_get(s->metadata, "title", NULL, 0);
01432     int64_t pos, pos2;
01433 
01434     if (title) {
01435         pos = url_ftell(pb);
01436         put_be32(pb, 0); /* size placeholder*/
01437         put_tag(pb, "uuid");
01438         put_tag(pb, "USMT");
01439         put_be32(pb, 0x21d24fce); /* 96 bit UUID */
01440         put_be32(pb, 0xbb88695c);
01441         put_be32(pb, 0xfac9c740);
01442 
01443         pos2 = url_ftell(pb);
01444         put_be32(pb, 0); /* size placeholder*/
01445         put_tag(pb, "MTDT");
01446         put_be16(pb, 4);
01447 
01448         // ?
01449         put_be16(pb, 0x0C);                 /* size */
01450         put_be32(pb, 0x0B);                 /* type */
01451         put_be16(pb, language_code("und")); /* language */
01452         put_be16(pb, 0x0);                  /* ? */
01453         put_be16(pb, 0x021C);               /* data */
01454 
01455         mov_write_psp_udta_tag(pb, LIBAVCODEC_IDENT,      "eng", 0x04);
01456         mov_write_psp_udta_tag(pb, title->value,          "eng", 0x01);
01457 //        snprintf(dt,32,"%04d/%02d/%02d %02d:%02d:%02d",t_st->tm_year+1900,t_st->tm_mon+1,t_st->tm_mday,t_st->tm_hour,t_st->tm_min,t_st->tm_sec);
01458         mov_write_psp_udta_tag(pb, "2006/04/01 11:11:11", "und", 0x03);
01459 
01460         updateSize(pb, pos2);
01461         return updateSize(pb, pos);
01462     }
01463 
01464     return 0;
01465 }
01466 
01467 static int mov_write_moov_tag(ByteIOContext *pb, MOVMuxContext *mov,
01468                               AVFormatContext *s)
01469 {
01470     int i;
01471     int64_t pos = url_ftell(pb);
01472     put_be32(pb, 0); /* size placeholder*/
01473     put_tag(pb, "moov");
01474     mov->timescale = globalTimescale;
01475 
01476     for (i=0; i<mov->nb_streams; i++) {
01477         if(mov->tracks[i].entry <= 0) continue;
01478 
01479         mov->tracks[i].time = mov->time;
01480         mov->tracks[i].trackID = i+1;
01481     }
01482 
01483     mov_write_mvhd_tag(pb, mov);
01484     //mov_write_iods_tag(pb, mov);
01485     for (i=0; i<mov->nb_streams; i++) {
01486         if(mov->tracks[i].entry > 0) {
01487             mov_write_trak_tag(pb, &(mov->tracks[i]), s->streams[i]);
01488         }
01489     }
01490 
01491     if (mov->mode == MODE_PSP)
01492         mov_write_uuidusmt_tag(pb, s);
01493     else
01494         mov_write_udta_tag(pb, mov, s);
01495 
01496     return updateSize(pb, pos);
01497 }
01498 
01499 static int mov_write_mdat_tag(ByteIOContext *pb, MOVMuxContext *mov)
01500 {
01501     put_be32(pb, 8);    // placeholder for extended size field (64 bit)
01502     put_tag(pb, mov->mode == MODE_MOV ? "wide" : "free");
01503 
01504     mov->mdat_pos = url_ftell(pb);
01505     put_be32(pb, 0); /* size placeholder*/
01506     put_tag(pb, "mdat");
01507     return 0;
01508 }
01509 
01510 /* TODO: This needs to be more general */
01511 static int mov_write_ftyp_tag(ByteIOContext *pb, AVFormatContext *s)
01512 {
01513     MOVMuxContext *mov = s->priv_data;
01514     int64_t pos = url_ftell(pb);
01515     int has_h264 = 0, has_video = 0;
01516     int minor = 0x200;
01517     int i;
01518 
01519     for (i = 0; i < s->nb_streams; i++) {
01520         AVStream *st = s->streams[i];
01521         if (st->codec->codec_type == CODEC_TYPE_VIDEO)
01522             has_video = 1;
01523         if (st->codec->codec_id == CODEC_ID_H264)
01524             has_h264 = 1;
01525     }
01526 
01527     put_be32(pb, 0); /* size */
01528     put_tag(pb, "ftyp");
01529 
01530     if (mov->mode == MODE_3GP) {
01531         put_tag(pb, has_h264 ? "3gp6"  : "3gp4");
01532         minor =     has_h264 ?   0x100 :   0x200;
01533     } else if (mov->mode & MODE_3G2) {
01534         put_tag(pb, has_h264 ? "3g2b"  : "3g2a");
01535         minor =     has_h264 ? 0x20000 : 0x10000;
01536     }else if (mov->mode == MODE_PSP)
01537         put_tag(pb, "MSNV");
01538     else if (mov->mode == MODE_MP4)
01539         put_tag(pb, "isom");
01540     else if (mov->mode == MODE_IPOD)
01541         put_tag(pb, has_video ? "M4V ":"M4A ");
01542     else
01543         put_tag(pb, "qt  ");
01544 
01545     put_be32(pb, minor);
01546 
01547     if(mov->mode == MODE_MOV)
01548         put_tag(pb, "qt  ");
01549     else{
01550         put_tag(pb, "isom");
01551         put_tag(pb, "iso2");
01552         if(has_h264)
01553             put_tag(pb, "avc1");
01554     }
01555 
01556     if (mov->mode == MODE_3GP)
01557         put_tag(pb, has_h264 ? "3gp6":"3gp4");
01558     else if (mov->mode & MODE_3G2)
01559         put_tag(pb, has_h264 ? "3g2b":"3g2a");
01560     else if (mov->mode == MODE_PSP)
01561         put_tag(pb, "MSNV");
01562     else if (mov->mode == MODE_MP4)
01563         put_tag(pb, "mp41");
01564     return updateSize(pb, pos);
01565 }
01566 
01567 static void mov_write_uuidprof_tag(ByteIOContext *pb, AVFormatContext *s)
01568 {
01569     AVCodecContext *VideoCodec = s->streams[0]->codec;
01570     AVCodecContext *AudioCodec = s->streams[1]->codec;
01571     int AudioRate = AudioCodec->sample_rate;
01572     int FrameRate = ((VideoCodec->time_base.den) * (0x10000))/ (VideoCodec->time_base.num);
01573     int audio_kbitrate= AudioCodec->bit_rate / 1000;
01574     int video_kbitrate= FFMIN(VideoCodec->bit_rate / 1000, 800 - audio_kbitrate);
01575 
01576     put_be32(pb, 0x94); /* size */
01577     put_tag(pb, "uuid");
01578     put_tag(pb, "PROF");
01579 
01580     put_be32(pb, 0x21d24fce); /* 96 bit UUID */
01581     put_be32(pb, 0xbb88695c);
01582     put_be32(pb, 0xfac9c740);
01583 
01584     put_be32(pb, 0x0);  /* ? */
01585     put_be32(pb, 0x3);  /* 3 sections ? */
01586 
01587     put_be32(pb, 0x14); /* size */
01588     put_tag(pb, "FPRF");
01589     put_be32(pb, 0x0);  /* ? */
01590     put_be32(pb, 0x0);  /* ? */
01591     put_be32(pb, 0x0);  /* ? */
01592 
01593     put_be32(pb, 0x2c);  /* size */
01594     put_tag(pb, "APRF");   /* audio */
01595     put_be32(pb, 0x0);
01596     put_be32(pb, 0x2);   /* TrackID */
01597     put_tag(pb, "mp4a");
01598     put_be32(pb, 0x20f);
01599     put_be32(pb, 0x0);
01600     put_be32(pb, audio_kbitrate);
01601     put_be32(pb, audio_kbitrate);
01602     put_be32(pb, AudioRate);
01603     put_be32(pb, AudioCodec->channels);
01604 
01605     put_be32(pb, 0x34);  /* size */
01606     put_tag(pb, "VPRF");   /* video */
01607     put_be32(pb, 0x0);
01608     put_be32(pb, 0x1);    /* TrackID */
01609     if (VideoCodec->codec_id == CODEC_ID_H264) {
01610         put_tag(pb, "avc1");
01611         put_be16(pb, 0x014D);
01612         put_be16(pb, 0x0015);
01613     } else {
01614         put_tag(pb, "mp4v");
01615         put_be16(pb, 0x0000);
01616         put_be16(pb, 0x0103);
01617     }
01618     put_be32(pb, 0x0);
01619     put_be32(pb, video_kbitrate);
01620     put_be32(pb, video_kbitrate);
01621     put_be32(pb, FrameRate);
01622     put_be32(pb, FrameRate);
01623     put_be16(pb, VideoCodec->width);
01624     put_be16(pb, VideoCodec->height);
01625     put_be32(pb, 0x010001); /* ? */
01626 }
01627 
01628 static int mov_write_header(AVFormatContext *s)
01629 {
01630     ByteIOContext *pb = s->pb;
01631     MOVMuxContext *mov = s->priv_data;
01632     int i;
01633 
01634     if (url_is_streamed(s->pb)) {
01635         av_log(s, AV_LOG_ERROR, "muxer does not support non seekable output\n");
01636         return -1;
01637     }
01638 
01639     /* Default mode == MP4 */
01640     mov->mode = MODE_MP4;
01641 
01642     if (s->oformat != NULL) {
01643         if (!strcmp("3gp", s->oformat->name)) mov->mode = MODE_3GP;
01644         else if (!strcmp("3g2", s->oformat->name)) mov->mode = MODE_3GP|MODE_3G2;
01645         else if (!strcmp("mov", s->oformat->name)) mov->mode = MODE_MOV;
01646         else if (!strcmp("psp", s->oformat->name)) mov->mode = MODE_PSP;
01647         else if (!strcmp("ipod",s->oformat->name)) mov->mode = MODE_IPOD;
01648 
01649         mov_write_ftyp_tag(pb,s);
01650         if (mov->mode == MODE_PSP) {
01651             if (s->nb_streams != 2) {
01652                 av_log(s, AV_LOG_ERROR, "PSP mode need one video and one audio stream\n");
01653                 return -1;
01654             }
01655             mov_write_uuidprof_tag(pb,s);
01656         }
01657     }
01658 
01659     for(i=0; i<s->nb_streams; i++){
01660         AVStream *st= s->streams[i];
01661         MOVTrack *track= &mov->tracks[i];
01662         AVMetadataTag *lang = av_metadata_get(st->metadata, "language", NULL,0);
01663 
01664         track->enc = st->codec;
01665         track->language = ff_mov_iso639_to_lang(lang?lang->value:"und", mov->mode!=MODE_MOV);
01666         if (track->language < 0)
01667             track->language = 0;
01668         track->mode = mov->mode;
01669         track->tag = mov_find_codec_tag(s, track);
01670         if (!track->tag) {
01671             av_log(s, AV_LOG_ERROR, "track %d: could not find tag, "
01672                    "codec not currently supported in container\n", i);
01673             return -1;
01674         }
01675         if(st->codec->codec_type == CODEC_TYPE_VIDEO){
01676             if (track->tag == MKTAG('m','x','3','p') || track->tag == MKTAG('m','x','3','n') ||
01677                 track->tag == MKTAG('m','x','4','p') || track->tag == MKTAG('m','x','4','n') ||
01678                 track->tag == MKTAG('m','x','5','p') || track->tag == MKTAG('m','x','5','n')) {
01679                 if (st->codec->width != 720 || (st->codec->height != 608 && st->codec->height != 512)) {
01680                     av_log(s, AV_LOG_ERROR, "D-10/IMX must use 720x608 or 720x512 video resolution\n");
01681                     return -1;
01682                 }
01683                 track->height = track->tag>>24 == 'n' ? 486 : 576;
01684             } else
01685                 track->height = st->codec->height;
01686             track->timescale = st->codec->time_base.den;
01687             av_set_pts_info(st, 64, 1, st->codec->time_base.den);
01688             if (track->mode == MODE_MOV && track->timescale > 100000)
01689                 av_log(s, AV_LOG_WARNING,
01690                        "WARNING codec timebase is very high. If duration is too long,\n"
01691                        "file may not be playable by quicktime. Specify a shorter timebase\n"
01692                        "or choose different container.\n");
01693         }else if(st->codec->codec_type == CODEC_TYPE_AUDIO){
01694             track->timescale = st->codec->sample_rate;
01695             av_set_pts_info(st, 64, 1, st->codec->sample_rate);
01696             if(!st->codec->frame_size && !av_get_bits_per_sample(st->codec->codec_id)) {
01697                 av_log(s, AV_LOG_ERROR, "track %d: codec frame size is not set\n", i);
01698                 return -1;
01699             }else if(st->codec->frame_size > 1){ /* assume compressed audio */
01700                 track->audio_vbr = 1;
01701             }else{
01702                 st->codec->frame_size = 1;
01703                 track->sampleSize = (av_get_bits_per_sample(st->codec->codec_id) >> 3) * st->codec->channels;
01704             }
01705             if(track->mode != MODE_MOV &&
01706                track->enc->codec_id == CODEC_ID_MP3 && track->enc->sample_rate < 16000){
01707                 av_log(s, AV_LOG_ERROR, "track %d: muxing mp3 at %dhz is not supported\n",
01708                        i, track->enc->sample_rate);
01709                 return -1;
01710             }
01711         }else if(st->codec->codec_type == CODEC_TYPE_SUBTITLE){
01712             track->timescale = st->codec->time_base.den;
01713             av_set_pts_info(st, 64, 1, st->codec->time_base.den);
01714         }
01715     }
01716 
01717     mov_write_mdat_tag(pb, mov);
01718     mov->time = s->timestamp + 0x7C25B080; //1970 based -> 1904 based
01719     mov->nb_streams = s->nb_streams;
01720 
01721     put_flush_packet(pb);
01722 
01723     return 0;
01724 }
01725 
01726 static int mov_write_packet(AVFormatContext *s, AVPacket *pkt)
01727 {
01728     MOVMuxContext *mov = s->priv_data;
01729     ByteIOContext *pb = s->pb;
01730     MOVTrack *trk = &mov->tracks[pkt->stream_index];
01731     AVCodecContext *enc = trk->enc;
01732     unsigned int samplesInChunk = 0;
01733     int size= pkt->size;
01734 
01735     if (url_is_streamed(s->pb)) return 0; /* Can't handle that */
01736     if (!size) return 0; /* Discard 0 sized packets */
01737 
01738     if (enc->codec_id == CODEC_ID_AMR_NB) {
01739         /* We must find out how many AMR blocks there are in one packet */
01740         static uint16_t packed_size[16] =
01741             {13, 14, 16, 18, 20, 21, 27, 32, 6, 0, 0, 0, 0, 0, 0, 0};
01742         int len = 0;
01743 
01744         while (len < size && samplesInChunk < 100) {
01745             len += packed_size[(pkt->data[len] >> 3) & 0x0F];
01746             samplesInChunk++;
01747         }
01748         if(samplesInChunk > 1){
01749             av_log(s, AV_LOG_ERROR, "fatal error, input is not a single packet, implement a AVParser for it\n");
01750             return -1;
01751         }
01752     } else if (trk->sampleSize)
01753         samplesInChunk = size/trk->sampleSize;
01754     else
01755         samplesInChunk = 1;
01756 
01757     /* copy extradata if it exists */
01758     if (trk->vosLen == 0 && enc->extradata_size > 0) {
01759         trk->vosLen = enc->extradata_size;
01760         trk->vosData = av_malloc(trk->vosLen);
01761         memcpy(trk->vosData, enc->extradata, trk->vosLen);
01762     }
01763 
01764     if (enc->codec_id == CODEC_ID_H264 && trk->vosLen > 0 && *(uint8_t *)trk->vosData != 1) {
01765         /* from x264 or from bytestream h264 */
01766         /* nal reformating needed */
01767         size = ff_avc_parse_nal_units(pb, pkt->data, pkt->size);
01768     } else {
01769         put_buffer(pb, pkt->data, size);
01770     }
01771 
01772     if ((enc->codec_id == CODEC_ID_DNXHD ||
01773                 enc->codec_id == CODEC_ID_AC3) && !trk->vosLen) {
01774         /* copy frame to create needed atoms */
01775         trk->vosLen = size;
01776         trk->vosData = av_malloc(size);
01777         if (!trk->vosData)
01778             return AVERROR(ENOMEM);
01779         memcpy(trk->vosData, pkt->data, size);
01780     }
01781 
01782     if (!(trk->entry % MOV_INDEX_CLUSTER_SIZE)) {
01783         trk->cluster = av_realloc(trk->cluster, (trk->entry + MOV_INDEX_CLUSTER_SIZE) * sizeof(*trk->cluster));
01784         if (!trk->cluster)
01785             return -1;
01786     }
01787 
01788     trk->cluster[trk->entry].pos = url_ftell(pb) - size;
01789     trk->cluster[trk->entry].samplesInChunk = samplesInChunk;
01790     trk->cluster[trk->entry].size = size;
01791     trk->cluster[trk->entry].entries = samplesInChunk;
01792     trk->cluster[trk->entry].dts = pkt->dts;
01793     trk->trackDuration = pkt->dts - trk->cluster[0].dts + pkt->duration;
01794 
01795     if (pkt->pts == AV_NOPTS_VALUE) {
01796         av_log(s, AV_LOG_WARNING, "pts has no value\n");
01797         pkt->pts = pkt->dts;
01798     }
01799     if (pkt->dts != pkt->pts)
01800         trk->hasBframes = 1;
01801     trk->cluster[trk->entry].cts = pkt->pts - pkt->dts;
01802     trk->cluster[trk->entry].key_frame = !!(pkt->flags & PKT_FLAG_KEY);
01803     if(trk->cluster[trk->entry].key_frame)
01804         trk->hasKeyframes++;
01805     trk->entry++;
01806     trk->sampleCount += samplesInChunk;
01807     mov->mdat_size += size;
01808 
01809     put_flush_packet(pb);
01810     return 0;
01811 }
01812 
01813 static int mov_write_trailer(AVFormatContext *s)
01814 {
01815     MOVMuxContext *mov = s->priv_data;
01816     ByteIOContext *pb = s->pb;
01817     int res = 0;
01818     int i;
01819 
01820     int64_t moov_pos = url_ftell(pb);
01821 
01822     /* Write size of mdat tag */
01823     if (mov->mdat_size+8 <= UINT32_MAX) {
01824         url_fseek(pb, mov->mdat_pos, SEEK_SET);
01825         put_be32(pb, mov->mdat_size+8);
01826     } else {
01827         /* overwrite 'wide' placeholder atom */
01828         url_fseek(pb, mov->mdat_pos - 8, SEEK_SET);
01829         put_be32(pb, 1); /* special value: real atom size will be 64 bit value after tag field */
01830         put_tag(pb, "mdat");
01831         put_be64(pb, mov->mdat_size+16);
01832     }
01833     url_fseek(pb, moov_pos, SEEK_SET);
01834 
01835     mov_write_moov_tag(pb, mov, s);
01836 
01837     for (i=0; i<mov->nb_streams; i++) {
01838         av_freep(&mov->tracks[i].cluster);
01839 
01840         if(mov->tracks[i].vosLen) av_free(mov->tracks[i].vosData);
01841 
01842     }
01843 
01844     put_flush_packet(pb);
01845 
01846     return res;
01847 }
01848 
01849 #if CONFIG_MOV_MUXER
01850 AVOutputFormat mov_muxer = {
01851     "mov",
01852     NULL_IF_CONFIG_SMALL("MOV format"),
01853     NULL,
01854     "mov",
01855     sizeof(MOVMuxContext),
01856     CODEC_ID_AAC,
01857     CODEC_ID_MPEG4,
01858     mov_write_header,
01859     mov_write_packet,
01860     mov_write_trailer,
01861     .flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS,
01862     .codec_tag = (const AVCodecTag* const []){codec_movvideo_tags, codec_movaudio_tags, 0},
01863 };
01864 #endif
01865 #if CONFIG_TGP_MUXER
01866 AVOutputFormat tgp_muxer = {
01867     "3gp",
01868     NULL_IF_CONFIG_SMALL("3GP format"),
01869     NULL,
01870     "3gp",
01871     sizeof(MOVMuxContext),
01872     CODEC_ID_AMR_NB,
01873     CODEC_ID_H263,
01874     mov_write_header,
01875     mov_write_packet,
01876     mov_write_trailer,
01877     .flags = AVFMT_GLOBALHEADER,
01878     .codec_tag = (const AVCodecTag* const []){codec_3gp_tags, 0},
01879 };
01880 #endif
01881 #if CONFIG_MP4_MUXER
01882 AVOutputFormat mp4_muxer = {
01883     "mp4",
01884     NULL_IF_CONFIG_SMALL("MP4 format"),
01885     "application/mp4",
01886     "mp4",
01887     sizeof(MOVMuxContext),
01888     CODEC_ID_AAC,
01889     CODEC_ID_MPEG4,
01890     mov_write_header,
01891     mov_write_packet,
01892     mov_write_trailer,
01893     .flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS,
01894     .codec_tag = (const AVCodecTag* const []){ff_mp4_obj_type, 0},
01895 };
01896 #endif
01897 #if CONFIG_PSP_MUXER
01898 AVOutputFormat psp_muxer = {
01899     "psp",
01900     NULL_IF_CONFIG_SMALL("PSP MP4 format"),
01901     NULL,
01902     "mp4,psp",
01903     sizeof(MOVMuxContext),
01904     CODEC_ID_AAC,
01905     CODEC_ID_MPEG4,
01906     mov_write_header,
01907     mov_write_packet,
01908     mov_write_trailer,
01909     .flags = AVFMT_GLOBALHEADER,
01910     .codec_tag = (const AVCodecTag* const []){ff_mp4_obj_type, 0},
01911 };
01912 #endif
01913 #if CONFIG_TG2_MUXER
01914 AVOutputFormat tg2_muxer = {
01915     "3g2",
01916     NULL_IF_CONFIG_SMALL("3GP2 format"),
01917     NULL,
01918     "3g2",
01919     sizeof(MOVMuxContext),
01920     CODEC_ID_AMR_NB,
01921     CODEC_ID_H263,
01922     mov_write_header,
01923     mov_write_packet,
01924     mov_write_trailer,
01925     .flags = AVFMT_GLOBALHEADER,
01926     .codec_tag = (const AVCodecTag* const []){codec_3gp_tags, 0},
01927 };
01928 #endif
01929 #if CONFIG_IPOD_MUXER
01930 AVOutputFormat ipod_muxer = {
01931     "ipod",
01932     NULL_IF_CONFIG_SMALL("iPod H.264 MP4 format"),
01933     "application/mp4",
01934     "m4v,m4a",
01935     sizeof(MOVMuxContext),
01936     CODEC_ID_AAC,
01937     CODEC_ID_H264,
01938     mov_write_header,
01939     mov_write_packet,
01940     mov_write_trailer,
01941     .flags = AVFMT_GLOBALHEADER,
01942     .codec_tag = (const AVCodecTag* const []){ff_mp4_obj_type, 0},
01943 };
01944 #endif

Generated on Tue Nov 4 2014 12:59:23 for ffmpeg by  doxygen 1.7.1