• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • Examples
  • 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  * Copyright (c) 2009 Baptiste Coudurier <baptiste dot coudurier at gmail dot com>
00006  *
00007  * This file is part of FFmpeg.
00008  *
00009  * FFmpeg is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 2.1 of the License, or (at your option) any later version.
00013  *
00014  * FFmpeg is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * Lesser General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU Lesser General Public
00020  * License along with FFmpeg; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00022  */
00023 
00024 #include "movenc.h"
00025 #include "avformat.h"
00026 #include "avio_internal.h"
00027 #include "riff.h"
00028 #include "avio.h"
00029 #include "isom.h"
00030 #include "avc.h"
00031 #include "libavcodec/get_bits.h"
00032 #include "libavcodec/put_bits.h"
00033 #include "internal.h"
00034 #include "libavutil/avstring.h"
00035 #include "libavutil/opt.h"
00036 #include "libavutil/dict.h"
00037 #include "rtpenc.h"
00038 
00039 #undef NDEBUG
00040 #include <assert.h>
00041 
00042 static const AVOption options[] = {
00043     { "movflags", "MOV muxer flags", offsetof(MOVMuxContext, flags), FF_OPT_TYPE_FLAGS, {.dbl = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
00044     { "rtphint", "Add RTP hint tracks", 0, FF_OPT_TYPE_CONST, {.dbl = FF_MOV_FLAG_RTP_HINT}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
00045     FF_RTP_FLAG_OPTS(MOVMuxContext, rtp_flags),
00046     { NULL },
00047 };
00048 
00049 static const AVClass mov_muxer_class = {
00050     .class_name = "MOV/3GP/MP4/3G2 muxer",
00051     .item_name  = av_default_item_name,
00052     .option     = options,
00053     .version    = LIBAVUTIL_VERSION_INT,
00054 };
00055 
00056 //FIXME support 64 bit variant with wide placeholders
00057 static int64_t updateSize(AVIOContext *pb, int64_t pos)
00058 {
00059     int64_t curpos = avio_tell(pb);
00060     avio_seek(pb, pos, SEEK_SET);
00061     avio_wb32(pb, curpos - pos); /* rewrite size */
00062     avio_seek(pb, curpos, SEEK_SET);
00063 
00064     return curpos - pos;
00065 }
00066 
00067 /* Chunk offset atom */
00068 static int mov_write_stco_tag(AVIOContext *pb, MOVTrack *track)
00069 {
00070     int i;
00071     int mode64 = 0; //   use 32 bit size variant if possible
00072     int64_t pos = avio_tell(pb);
00073     avio_wb32(pb, 0); /* size */
00074     if (pos > UINT32_MAX) {
00075         mode64 = 1;
00076         ffio_wfourcc(pb, "co64");
00077     } else
00078         ffio_wfourcc(pb, "stco");
00079     avio_wb32(pb, 0); /* version & flags */
00080     avio_wb32(pb, track->entry); /* entry count */
00081     for (i=0; i<track->entry; i++) {
00082         if(mode64 == 1)
00083             avio_wb64(pb, track->cluster[i].pos);
00084         else
00085             avio_wb32(pb, track->cluster[i].pos);
00086     }
00087     return updateSize(pb, pos);
00088 }
00089 
00090 /* Sample size atom */
00091 static int mov_write_stsz_tag(AVIOContext *pb, MOVTrack *track)
00092 {
00093     int equalChunks = 1;
00094     int i, j, entries = 0, tst = -1, oldtst = -1;
00095 
00096     int64_t pos = avio_tell(pb);
00097     avio_wb32(pb, 0); /* size */
00098     ffio_wfourcc(pb, "stsz");
00099     avio_wb32(pb, 0); /* version & flags */
00100 
00101     for (i=0; i<track->entry; i++) {
00102         tst = track->cluster[i].size/track->cluster[i].entries;
00103         if(oldtst != -1 && tst != oldtst) {
00104             equalChunks = 0;
00105         }
00106         oldtst = tst;
00107         entries += track->cluster[i].entries;
00108     }
00109     if (equalChunks) {
00110         int sSize = track->cluster[0].size/track->cluster[0].entries;
00111         sSize = FFMAX(1, sSize); // adpcm mono case could make sSize == 0
00112         avio_wb32(pb, sSize); // sample size
00113         avio_wb32(pb, entries); // sample count
00114     }
00115     else {
00116         avio_wb32(pb, 0); // sample size
00117         avio_wb32(pb, entries); // sample count
00118         for (i=0; i<track->entry; i++) {
00119             for (j=0; j<track->cluster[i].entries; j++) {
00120                 avio_wb32(pb, track->cluster[i].size /
00121                          track->cluster[i].entries);
00122             }
00123         }
00124     }
00125     return updateSize(pb, pos);
00126 }
00127 
00128 /* Sample to chunk atom */
00129 static int mov_write_stsc_tag(AVIOContext *pb, MOVTrack *track)
00130 {
00131     int index = 0, oldval = -1, i;
00132     int64_t entryPos, curpos;
00133 
00134     int64_t pos = avio_tell(pb);
00135     avio_wb32(pb, 0); /* size */
00136     ffio_wfourcc(pb, "stsc");
00137     avio_wb32(pb, 0); // version & flags
00138     entryPos = avio_tell(pb);
00139     avio_wb32(pb, track->entry); // entry count
00140     for (i=0; i<track->entry; i++) {
00141         if(oldval != track->cluster[i].samplesInChunk)
00142         {
00143             avio_wb32(pb, i+1); // first chunk
00144             avio_wb32(pb, track->cluster[i].samplesInChunk); // samples per chunk
00145             avio_wb32(pb, 0x1); // sample description index
00146             oldval = track->cluster[i].samplesInChunk;
00147             index++;
00148         }
00149     }
00150     curpos = avio_tell(pb);
00151     avio_seek(pb, entryPos, SEEK_SET);
00152     avio_wb32(pb, index); // rewrite size
00153     avio_seek(pb, curpos, SEEK_SET);
00154 
00155     return updateSize(pb, pos);
00156 }
00157 
00158 /* Sync sample atom */
00159 static int mov_write_stss_tag(AVIOContext *pb, MOVTrack *track, uint32_t flag)
00160 {
00161     int64_t curpos, entryPos;
00162     int i, index = 0;
00163     int64_t pos = avio_tell(pb);
00164     avio_wb32(pb, 0); // size
00165     ffio_wfourcc(pb, flag == MOV_SYNC_SAMPLE ? "stss" : "stps");
00166     avio_wb32(pb, 0); // version & flags
00167     entryPos = avio_tell(pb);
00168     avio_wb32(pb, track->entry); // entry count
00169     for (i=0; i<track->entry; i++) {
00170         if (track->cluster[i].flags & flag) {
00171             avio_wb32(pb, i+1);
00172             index++;
00173         }
00174     }
00175     curpos = avio_tell(pb);
00176     avio_seek(pb, entryPos, SEEK_SET);
00177     avio_wb32(pb, index); // rewrite size
00178     avio_seek(pb, curpos, SEEK_SET);
00179     return updateSize(pb, pos);
00180 }
00181 
00182 static int mov_write_amr_tag(AVIOContext *pb, MOVTrack *track)
00183 {
00184     avio_wb32(pb, 0x11); /* size */
00185     if (track->mode == MODE_MOV) ffio_wfourcc(pb, "samr");
00186     else                         ffio_wfourcc(pb, "damr");
00187     ffio_wfourcc(pb, "FFMP");
00188     avio_w8(pb, 0); /* decoder version */
00189 
00190     avio_wb16(pb, 0x81FF); /* Mode set (all modes for AMR_NB) */
00191     avio_w8(pb, 0x00); /* Mode change period (no restriction) */
00192     avio_w8(pb, 0x01); /* Frames per sample */
00193     return 0x11;
00194 }
00195 
00196 static int mov_write_ac3_tag(AVIOContext *pb, MOVTrack *track)
00197 {
00198     GetBitContext gbc;
00199     PutBitContext pbc;
00200     uint8_t buf[3];
00201     int fscod, bsid, bsmod, acmod, lfeon, frmsizecod;
00202 
00203     if (track->vosLen < 7)
00204         return -1;
00205 
00206     avio_wb32(pb, 11);
00207     ffio_wfourcc(pb, "dac3");
00208 
00209     init_get_bits(&gbc, track->vosData+4, (track->vosLen-4) * 8);
00210     fscod      = get_bits(&gbc, 2);
00211     frmsizecod = get_bits(&gbc, 6);
00212     bsid       = get_bits(&gbc, 5);
00213     bsmod      = get_bits(&gbc, 3);
00214     acmod      = get_bits(&gbc, 3);
00215     if (acmod == 2) {
00216         skip_bits(&gbc, 2); // dsurmod
00217     } else {
00218         if ((acmod & 1) && acmod != 1)
00219             skip_bits(&gbc, 2); // cmixlev
00220         if (acmod & 4)
00221             skip_bits(&gbc, 2); // surmixlev
00222     }
00223     lfeon = get_bits1(&gbc);
00224 
00225     init_put_bits(&pbc, buf, sizeof(buf));
00226     put_bits(&pbc, 2, fscod);
00227     put_bits(&pbc, 5, bsid);
00228     put_bits(&pbc, 3, bsmod);
00229     put_bits(&pbc, 3, acmod);
00230     put_bits(&pbc, 1, lfeon);
00231     put_bits(&pbc, 5, frmsizecod>>1); // bit_rate_code
00232     put_bits(&pbc, 5, 0); // reserved
00233 
00234     flush_put_bits(&pbc);
00235     avio_write(pb, buf, sizeof(buf));
00236 
00237     return 11;
00238 }
00239 
00244 static int mov_write_extradata_tag(AVIOContext *pb, MOVTrack *track)
00245 {
00246     avio_write(pb, track->enc->extradata, track->enc->extradata_size);
00247     return track->enc->extradata_size;
00248 }
00249 
00250 static int mov_write_enda_tag(AVIOContext *pb)
00251 {
00252     avio_wb32(pb, 10);
00253     ffio_wfourcc(pb, "enda");
00254     avio_wb16(pb, 1); /* little endian */
00255     return 10;
00256 }
00257 
00258 static void putDescr(AVIOContext *pb, int tag, unsigned int size)
00259 {
00260     int i = 3;
00261     avio_w8(pb, tag);
00262     for(; i>0; i--)
00263         avio_w8(pb, (size>>(7*i)) | 0x80);
00264     avio_w8(pb, size & 0x7F);
00265 }
00266 
00267 static unsigned compute_avg_bitrate(MOVTrack *track)
00268 {
00269     uint64_t size = 0;
00270     int i;
00271     for (i = 0; i < track->entry; i++)
00272         size += track->cluster[i].size;
00273     return size * 8 * track->timescale / track->trackDuration;
00274 }
00275 
00276 static int mov_write_esds_tag(AVIOContext *pb, MOVTrack *track) // Basic
00277 {
00278     int64_t pos = avio_tell(pb);
00279     int decoderSpecificInfoLen = track->vosLen ? 5+track->vosLen : 0;
00280     unsigned avg_bitrate;
00281 
00282     avio_wb32(pb, 0); // size
00283     ffio_wfourcc(pb, "esds");
00284     avio_wb32(pb, 0); // Version
00285 
00286     // ES descriptor
00287     putDescr(pb, 0x03, 3 + 5+13 + decoderSpecificInfoLen + 5+1);
00288     avio_wb16(pb, track->trackID);
00289     avio_w8(pb, 0x00); // flags (= no flags)
00290 
00291     // DecoderConfig descriptor
00292     putDescr(pb, 0x04, 13 + decoderSpecificInfoLen);
00293 
00294     // Object type indication
00295     if ((track->enc->codec_id == CODEC_ID_MP2 ||
00296          track->enc->codec_id == CODEC_ID_MP3) &&
00297         track->enc->sample_rate > 24000)
00298         avio_w8(pb, 0x6B); // 11172-3
00299     else
00300         avio_w8(pb, ff_codec_get_tag(ff_mp4_obj_type, track->enc->codec_id));
00301 
00302     // the following fields is made of 6 bits to identify the streamtype (4 for video, 5 for audio)
00303     // plus 1 bit to indicate upstream and 1 bit set to 1 (reserved)
00304     if(track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
00305         avio_w8(pb, 0x15); // flags (= Audiostream)
00306     else
00307         avio_w8(pb, 0x11); // flags (= Visualstream)
00308 
00309     avio_w8(pb,  track->enc->rc_buffer_size>>(3+16));      // Buffersize DB (24 bits)
00310     avio_wb16(pb, (track->enc->rc_buffer_size>>3)&0xFFFF); // Buffersize DB
00311 
00312     avg_bitrate = compute_avg_bitrate(track);
00313     // maxbitrate (FIXME should be max rate in any 1 sec window)
00314     avio_wb32(pb, FFMAX3(track->enc->bit_rate, track->enc->rc_max_rate, avg_bitrate));
00315     avio_wb32(pb, avg_bitrate);
00316 
00317     if (track->vosLen) {
00318         // DecoderSpecific info descriptor
00319         putDescr(pb, 0x05, track->vosLen);
00320         avio_write(pb, track->vosData, track->vosLen);
00321     }
00322 
00323     // SL descriptor
00324     putDescr(pb, 0x06, 1);
00325     avio_w8(pb, 0x02);
00326     return updateSize(pb, pos);
00327 }
00328 
00329 static int mov_pcm_le_gt16(enum CodecID codec_id)
00330 {
00331     return codec_id == CODEC_ID_PCM_S24LE ||
00332            codec_id == CODEC_ID_PCM_S32LE ||
00333            codec_id == CODEC_ID_PCM_F32LE ||
00334            codec_id == CODEC_ID_PCM_F64LE;
00335 }
00336 
00337 static int mov_write_ms_tag(AVIOContext *pb, MOVTrack *track)
00338 {
00339     int64_t pos = avio_tell(pb);
00340     avio_wb32(pb, 0);
00341     avio_wl32(pb, track->tag); // store it byteswapped
00342     track->enc->codec_tag = av_bswap16(track->tag >> 16);
00343     ff_put_wav_header(pb, track->enc);
00344     return updateSize(pb, pos);
00345 }
00346 
00347 static int mov_write_wave_tag(AVIOContext *pb, MOVTrack *track)
00348 {
00349     int64_t pos = avio_tell(pb);
00350 
00351     avio_wb32(pb, 0);     /* size */
00352     ffio_wfourcc(pb, "wave");
00353 
00354     avio_wb32(pb, 12);    /* size */
00355     ffio_wfourcc(pb, "frma");
00356     avio_wl32(pb, track->tag);
00357 
00358     if (track->enc->codec_id == CODEC_ID_AAC) {
00359         /* useless atom needed by mplayer, ipod, not needed by quicktime */
00360         avio_wb32(pb, 12); /* size */
00361         ffio_wfourcc(pb, "mp4a");
00362         avio_wb32(pb, 0);
00363         mov_write_esds_tag(pb, track);
00364     } else if (mov_pcm_le_gt16(track->enc->codec_id)) {
00365         mov_write_enda_tag(pb);
00366     } else if (track->enc->codec_id == CODEC_ID_AMR_NB) {
00367         mov_write_amr_tag(pb, track);
00368     } else if (track->enc->codec_id == CODEC_ID_AC3) {
00369         mov_write_ac3_tag(pb, track);
00370     } else if (track->enc->codec_id == CODEC_ID_ALAC) {
00371         mov_write_extradata_tag(pb, track);
00372     } else if (track->enc->codec_id == CODEC_ID_ADPCM_MS ||
00373                track->enc->codec_id == CODEC_ID_ADPCM_IMA_WAV) {
00374         mov_write_ms_tag(pb, track);
00375     }
00376 
00377     avio_wb32(pb, 8);     /* size */
00378     avio_wb32(pb, 0);     /* null tag */
00379 
00380     return updateSize(pb, pos);
00381 }
00382 
00383 static int mov_write_glbl_tag(AVIOContext *pb, MOVTrack *track)
00384 {
00385     avio_wb32(pb, track->vosLen+8);
00386     ffio_wfourcc(pb, "glbl");
00387     avio_write(pb, track->vosData, track->vosLen);
00388     return 8+track->vosLen;
00389 }
00390 
00395 static int mov_get_lpcm_flags(enum CodecID codec_id)
00396 {
00397     switch (codec_id) {
00398     case CODEC_ID_PCM_F32BE:
00399     case CODEC_ID_PCM_F64BE:
00400         return 11;
00401     case CODEC_ID_PCM_F32LE:
00402     case CODEC_ID_PCM_F64LE:
00403         return 9;
00404     case CODEC_ID_PCM_U8:
00405         return 10;
00406     case CODEC_ID_PCM_S16BE:
00407     case CODEC_ID_PCM_S24BE:
00408     case CODEC_ID_PCM_S32BE:
00409         return 14;
00410     case CODEC_ID_PCM_S8:
00411     case CODEC_ID_PCM_S16LE:
00412     case CODEC_ID_PCM_S24LE:
00413     case CODEC_ID_PCM_S32LE:
00414         return 12;
00415     default:
00416         return 0;
00417     }
00418 }
00419 
00420 static int mov_write_audio_tag(AVIOContext *pb, MOVTrack *track)
00421 {
00422     int64_t pos = avio_tell(pb);
00423     int version = 0;
00424     uint32_t tag = track->tag;
00425 
00426     if (track->mode == MODE_MOV) {
00427         if (track->timescale > UINT16_MAX) {
00428             if (mov_get_lpcm_flags(track->enc->codec_id))
00429                 tag = AV_RL32("lpcm");
00430             version = 2;
00431         } else if (track->audio_vbr || mov_pcm_le_gt16(track->enc->codec_id) ||
00432                    track->enc->codec_id == CODEC_ID_ADPCM_MS ||
00433                    track->enc->codec_id == CODEC_ID_ADPCM_IMA_WAV) {
00434             version = 1;
00435         }
00436     }
00437 
00438     avio_wb32(pb, 0); /* size */
00439     avio_wl32(pb, tag); // store it byteswapped
00440     avio_wb32(pb, 0); /* Reserved */
00441     avio_wb16(pb, 0); /* Reserved */
00442     avio_wb16(pb, 1); /* Data-reference index, XXX  == 1 */
00443 
00444     /* SoundDescription */
00445     avio_wb16(pb, version); /* Version */
00446     avio_wb16(pb, 0); /* Revision level */
00447     avio_wb32(pb, 0); /* Reserved */
00448 
00449     if (version == 2) {
00450         avio_wb16(pb, 3);
00451         avio_wb16(pb, 16);
00452         avio_wb16(pb, 0xfffe);
00453         avio_wb16(pb, 0);
00454         avio_wb32(pb, 0x00010000);
00455         avio_wb32(pb, 72);
00456         avio_wb64(pb, av_dbl2int(track->timescale));
00457         avio_wb32(pb, track->enc->channels);
00458         avio_wb32(pb, 0x7F000000);
00459         avio_wb32(pb, av_get_bits_per_sample(track->enc->codec_id));
00460         avio_wb32(pb, mov_get_lpcm_flags(track->enc->codec_id));
00461         avio_wb32(pb, track->sampleSize);
00462         avio_wb32(pb, track->enc->frame_size);
00463     } else {
00464         if (track->mode == MODE_MOV) {
00465             avio_wb16(pb, track->enc->channels);
00466             if (track->enc->codec_id == CODEC_ID_PCM_U8 ||
00467                 track->enc->codec_id == CODEC_ID_PCM_S8)
00468                 avio_wb16(pb, 8); /* bits per sample */
00469             else
00470                 avio_wb16(pb, 16);
00471             avio_wb16(pb, track->audio_vbr ? -2 : 0); /* compression ID */
00472         } else { /* reserved for mp4/3gp */
00473             avio_wb16(pb, 2);
00474             avio_wb16(pb, 16);
00475             avio_wb16(pb, 0);
00476         }
00477 
00478         avio_wb16(pb, 0); /* packet size (= 0) */
00479         avio_wb16(pb, track->timescale); /* Time scale */
00480         avio_wb16(pb, 0); /* Reserved */
00481     }
00482 
00483     if(version == 1) { /* SoundDescription V1 extended info */
00484         avio_wb32(pb, track->enc->frame_size); /* Samples per packet */
00485         avio_wb32(pb, track->sampleSize / track->enc->channels); /* Bytes per packet */
00486         avio_wb32(pb, track->sampleSize); /* Bytes per frame */
00487         avio_wb32(pb, 2); /* Bytes per sample */
00488     }
00489 
00490     if(track->mode == MODE_MOV &&
00491        (track->enc->codec_id == CODEC_ID_AAC ||
00492         track->enc->codec_id == CODEC_ID_AC3 ||
00493         track->enc->codec_id == CODEC_ID_AMR_NB ||
00494         track->enc->codec_id == CODEC_ID_ALAC ||
00495         track->enc->codec_id == CODEC_ID_ADPCM_MS ||
00496         track->enc->codec_id == CODEC_ID_ADPCM_IMA_WAV ||
00497         mov_pcm_le_gt16(track->enc->codec_id)))
00498         mov_write_wave_tag(pb, track);
00499     else if(track->tag == MKTAG('m','p','4','a'))
00500         mov_write_esds_tag(pb, track);
00501     else if(track->enc->codec_id == CODEC_ID_AMR_NB)
00502         mov_write_amr_tag(pb, track);
00503     else if(track->enc->codec_id == CODEC_ID_AC3)
00504         mov_write_ac3_tag(pb, track);
00505     else if(track->enc->codec_id == CODEC_ID_ALAC)
00506         mov_write_extradata_tag(pb, track);
00507     else if(track->vosLen > 0)
00508         mov_write_glbl_tag(pb, track);
00509 
00510     return updateSize(pb, pos);
00511 }
00512 
00513 static int mov_write_d263_tag(AVIOContext *pb)
00514 {
00515     avio_wb32(pb, 0xf); /* size */
00516     ffio_wfourcc(pb, "d263");
00517     ffio_wfourcc(pb, "FFMP");
00518     avio_w8(pb, 0); /* decoder version */
00519     /* FIXME use AVCodecContext level/profile, when encoder will set values */
00520     avio_w8(pb, 0xa); /* level */
00521     avio_w8(pb, 0); /* profile */
00522     return 0xf;
00523 }
00524 
00525 /* TODO: No idea about these values */
00526 static int mov_write_svq3_tag(AVIOContext *pb)
00527 {
00528     avio_wb32(pb, 0x15);
00529     ffio_wfourcc(pb, "SMI ");
00530     ffio_wfourcc(pb, "SEQH");
00531     avio_wb32(pb, 0x5);
00532     avio_wb32(pb, 0xe2c0211d);
00533     avio_wb32(pb, 0xc0000000);
00534     avio_w8(pb, 0);
00535     return 0x15;
00536 }
00537 
00538 static int mov_write_avcc_tag(AVIOContext *pb, MOVTrack *track)
00539 {
00540     int64_t pos = avio_tell(pb);
00541 
00542     avio_wb32(pb, 0);
00543     ffio_wfourcc(pb, "avcC");
00544     ff_isom_write_avcc(pb, track->vosData, track->vosLen);
00545     return updateSize(pb, pos);
00546 }
00547 
00548 /* also used by all avid codecs (dv, imx, meridien) and their variants */
00549 static int mov_write_avid_tag(AVIOContext *pb, MOVTrack *track)
00550 {
00551     int i;
00552     avio_wb32(pb, 24); /* size */
00553     ffio_wfourcc(pb, "ACLR");
00554     ffio_wfourcc(pb, "ACLR");
00555     ffio_wfourcc(pb, "0001");
00556     avio_wb32(pb, 2); /* yuv range: full 1 / normal 2 */
00557     avio_wb32(pb, 0); /* unknown */
00558 
00559     avio_wb32(pb, 24); /* size */
00560     ffio_wfourcc(pb, "APRG");
00561     ffio_wfourcc(pb, "APRG");
00562     ffio_wfourcc(pb, "0001");
00563     avio_wb32(pb, 1); /* unknown */
00564     avio_wb32(pb, 0); /* unknown */
00565 
00566     avio_wb32(pb, 120); /* size */
00567     ffio_wfourcc(pb, "ARES");
00568     ffio_wfourcc(pb, "ARES");
00569     ffio_wfourcc(pb, "0001");
00570     avio_wb32(pb, AV_RB32(track->vosData + 0x28)); /* dnxhd cid, some id ? */
00571     avio_wb32(pb, track->enc->width);
00572     /* values below are based on samples created with quicktime and avid codecs */
00573     if (track->vosData[5] & 2) { // interlaced
00574         avio_wb32(pb, track->enc->height/2);
00575         avio_wb32(pb, 2); /* unknown */
00576         avio_wb32(pb, 0); /* unknown */
00577         avio_wb32(pb, 4); /* unknown */
00578     } else {
00579         avio_wb32(pb, track->enc->height);
00580         avio_wb32(pb, 1); /* unknown */
00581         avio_wb32(pb, 0); /* unknown */
00582         if (track->enc->height == 1080)
00583             avio_wb32(pb, 5); /* unknown */
00584         else
00585             avio_wb32(pb, 6); /* unknown */
00586     }
00587     /* padding */
00588     for (i = 0; i < 10; i++)
00589         avio_wb64(pb, 0);
00590 
00591     /* extra padding for stsd needed */
00592     avio_wb32(pb, 0);
00593     return 0;
00594 }
00595 
00596 static int mp4_get_codec_tag(AVFormatContext *s, MOVTrack *track)
00597 {
00598     int tag = track->enc->codec_tag;
00599 
00600     if (!ff_codec_get_tag(ff_mp4_obj_type, track->enc->codec_id))
00601         return 0;
00602 
00603     if      (track->enc->codec_id == CODEC_ID_H264)      tag = MKTAG('a','v','c','1');
00604     else if (track->enc->codec_id == CODEC_ID_AC3)       tag = MKTAG('a','c','-','3');
00605     else if (track->enc->codec_id == CODEC_ID_DIRAC)     tag = MKTAG('d','r','a','c');
00606     else if (track->enc->codec_id == CODEC_ID_MOV_TEXT)  tag = MKTAG('t','x','3','g');
00607     else if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) tag = MKTAG('m','p','4','v');
00608     else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) tag = MKTAG('m','p','4','a');
00609 
00610     return tag;
00611 }
00612 
00613 static const AVCodecTag codec_ipod_tags[] = {
00614     { CODEC_ID_H264,   MKTAG('a','v','c','1') },
00615     { CODEC_ID_MPEG4,  MKTAG('m','p','4','v') },
00616     { CODEC_ID_AAC,    MKTAG('m','p','4','a') },
00617     { CODEC_ID_ALAC,   MKTAG('a','l','a','c') },
00618     { CODEC_ID_AC3,    MKTAG('a','c','-','3') },
00619     { CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') },
00620     { CODEC_ID_MOV_TEXT, MKTAG('t','e','x','t') },
00621     { CODEC_ID_NONE, 0 },
00622 };
00623 
00624 static int ipod_get_codec_tag(AVFormatContext *s, MOVTrack *track)
00625 {
00626     int tag = track->enc->codec_tag;
00627 
00628     // keep original tag for subs, ipod supports both formats
00629     if (!(track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE &&
00630         (tag == MKTAG('t','x','3','g') ||
00631          tag == MKTAG('t','e','x','t'))))
00632         tag = ff_codec_get_tag(codec_ipod_tags, track->enc->codec_id);
00633 
00634     if (!av_match_ext(s->filename, "m4a") && !av_match_ext(s->filename, "m4v"))
00635         av_log(s, AV_LOG_WARNING, "Warning, extension is not .m4a nor .m4v "
00636                "Quicktime/Ipod might not play the file\n");
00637 
00638     return tag;
00639 }
00640 
00641 static int mov_get_dv_codec_tag(AVFormatContext *s, MOVTrack *track)
00642 {
00643     int tag;
00644 
00645     if (track->enc->width == 720) /* SD */
00646         if (track->enc->height == 480) /* NTSC */
00647             if  (track->enc->pix_fmt == PIX_FMT_YUV422P) tag = MKTAG('d','v','5','n');
00648             else                                         tag = MKTAG('d','v','c',' ');
00649         else if (track->enc->pix_fmt == PIX_FMT_YUV422P) tag = MKTAG('d','v','5','p');
00650         else if (track->enc->pix_fmt == PIX_FMT_YUV420P) tag = MKTAG('d','v','c','p');
00651         else                                             tag = MKTAG('d','v','p','p');
00652     else if (track->enc->height == 720) /* HD 720 line */
00653         if  (track->enc->time_base.den == 50)            tag = MKTAG('d','v','h','q');
00654         else                                             tag = MKTAG('d','v','h','p');
00655     else if (track->enc->height == 1080) /* HD 1080 line */
00656         if  (track->enc->time_base.den == 25)            tag = MKTAG('d','v','h','5');
00657         else                                             tag = MKTAG('d','v','h','6');
00658     else {
00659         av_log(s, AV_LOG_ERROR, "unsupported height for dv codec\n");
00660         return 0;
00661     }
00662 
00663     return tag;
00664 }
00665 
00666 static const struct {
00667     enum PixelFormat pix_fmt;
00668     uint32_t tag;
00669     unsigned bps;
00670 } mov_pix_fmt_tags[] = {
00671     { PIX_FMT_YUYV422, MKTAG('y','u','v','s'),  0 },
00672     { PIX_FMT_UYVY422, MKTAG('2','v','u','y'),  0 },
00673     { PIX_FMT_RGB555BE,MKTAG('r','a','w',' '), 16 },
00674     { PIX_FMT_RGB555LE,MKTAG('L','5','5','5'), 16 },
00675     { PIX_FMT_RGB565LE,MKTAG('L','5','6','5'), 16 },
00676     { PIX_FMT_RGB565BE,MKTAG('B','5','6','5'), 16 },
00677     { PIX_FMT_GRAY16BE,MKTAG('b','1','6','g'), 16 },
00678     { PIX_FMT_RGB24,   MKTAG('r','a','w',' '), 24 },
00679     { PIX_FMT_BGR24,   MKTAG('2','4','B','G'), 24 },
00680     { PIX_FMT_ARGB,    MKTAG('r','a','w',' '), 32 },
00681     { PIX_FMT_BGRA,    MKTAG('B','G','R','A'), 32 },
00682     { PIX_FMT_RGBA,    MKTAG('R','G','B','A'), 32 },
00683     { PIX_FMT_ABGR,    MKTAG('A','B','G','R'), 32 },
00684     { PIX_FMT_RGB48BE, MKTAG('b','4','8','r'), 48 },
00685 };
00686 
00687 static int mov_get_rawvideo_codec_tag(AVFormatContext *s, MOVTrack *track)
00688 {
00689     int tag = track->enc->codec_tag;
00690     int i;
00691 
00692     for (i = 0; i < FF_ARRAY_ELEMS(mov_pix_fmt_tags); i++) {
00693         if (track->enc->pix_fmt == mov_pix_fmt_tags[i].pix_fmt) {
00694             tag = mov_pix_fmt_tags[i].tag;
00695             track->enc->bits_per_coded_sample = mov_pix_fmt_tags[i].bps;
00696             break;
00697         }
00698     }
00699 
00700     return tag;
00701 }
00702 
00703 static int mov_get_codec_tag(AVFormatContext *s, MOVTrack *track)
00704 {
00705     int tag = track->enc->codec_tag;
00706 
00707     if (!tag || (track->enc->strict_std_compliance >= FF_COMPLIANCE_NORMAL &&
00708                  (track->enc->codec_id == CODEC_ID_DVVIDEO ||
00709                   track->enc->codec_id == CODEC_ID_RAWVIDEO ||
00710                   track->enc->codec_id == CODEC_ID_H263 ||
00711                   av_get_bits_per_sample(track->enc->codec_id)))) { // pcm audio
00712         if (track->enc->codec_id == CODEC_ID_DVVIDEO)
00713             tag = mov_get_dv_codec_tag(s, track);
00714         else if (track->enc->codec_id == CODEC_ID_RAWVIDEO)
00715             tag = mov_get_rawvideo_codec_tag(s, track);
00716         else if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) {
00717             tag = ff_codec_get_tag(codec_movvideo_tags, track->enc->codec_id);
00718             if (!tag) { // if no mac fcc found, try with Microsoft tags
00719                 tag = ff_codec_get_tag(ff_codec_bmp_tags, track->enc->codec_id);
00720                 if (tag)
00721                     av_log(s, AV_LOG_INFO, "Warning, using MS style video codec tag, "
00722                            "the file may be unplayable!\n");
00723             }
00724         } else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) {
00725             tag = ff_codec_get_tag(codec_movaudio_tags, track->enc->codec_id);
00726             if (!tag) { // if no mac fcc found, try with Microsoft tags
00727                 int ms_tag = ff_codec_get_tag(ff_codec_wav_tags, track->enc->codec_id);
00728                 if (ms_tag) {
00729                     tag = MKTAG('m', 's', ((ms_tag >> 8) & 0xff), (ms_tag & 0xff));
00730                     av_log(s, AV_LOG_INFO, "Warning, using MS style audio codec tag, "
00731                            "the file may be unplayable!\n");
00732                 }
00733             }
00734         } else if (track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE)
00735             tag = ff_codec_get_tag(ff_codec_movsubtitle_tags, track->enc->codec_id);
00736     }
00737 
00738     return tag;
00739 }
00740 
00741 static const AVCodecTag codec_3gp_tags[] = {
00742     { CODEC_ID_H263,   MKTAG('s','2','6','3') },
00743     { CODEC_ID_H264,   MKTAG('a','v','c','1') },
00744     { CODEC_ID_MPEG4,  MKTAG('m','p','4','v') },
00745     { CODEC_ID_AAC,    MKTAG('m','p','4','a') },
00746     { CODEC_ID_AMR_NB, MKTAG('s','a','m','r') },
00747     { CODEC_ID_AMR_WB, MKTAG('s','a','w','b') },
00748     { CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') },
00749     { CODEC_ID_NONE, 0 },
00750 };
00751 
00752 static int mov_find_codec_tag(AVFormatContext *s, MOVTrack *track)
00753 {
00754     int tag = track->enc->codec_tag;
00755 
00756     if (track->mode == MODE_MP4 || track->mode == MODE_PSP)
00757         tag = mp4_get_codec_tag(s, track);
00758     else if (track->mode == MODE_IPOD)
00759         tag = ipod_get_codec_tag(s, track);
00760     else if (track->mode & MODE_3GP)
00761         tag = ff_codec_get_tag(codec_3gp_tags, track->enc->codec_id);
00762     else
00763         tag = mov_get_codec_tag(s, track);
00764 
00765     return tag;
00766 }
00767 
00772 static int mov_write_uuid_tag_ipod(AVIOContext *pb)
00773 {
00774     avio_wb32(pb, 28);
00775     ffio_wfourcc(pb, "uuid");
00776     avio_wb32(pb, 0x6b6840f2);
00777     avio_wb32(pb, 0x5f244fc5);
00778     avio_wb32(pb, 0xba39a51b);
00779     avio_wb32(pb, 0xcf0323f3);
00780     avio_wb32(pb, 0x0);
00781     return 28;
00782 }
00783 
00784 static int mov_write_subtitle_tag(AVIOContext *pb, MOVTrack *track)
00785 {
00786     int64_t pos = avio_tell(pb);
00787     avio_wb32(pb, 0);    /* size */
00788     avio_wl32(pb, track->tag); // store it byteswapped
00789     avio_wb32(pb, 0);    /* Reserved */
00790     avio_wb16(pb, 0);    /* Reserved */
00791     avio_wb16(pb, 1);    /* Data-reference index */
00792 
00793     if (track->enc->extradata_size)
00794         avio_write(pb, track->enc->extradata, track->enc->extradata_size);
00795 
00796     return updateSize(pb, pos);
00797 }
00798 
00799 static int mov_write_pasp_tag(AVIOContext *pb, MOVTrack *track)
00800 {
00801     AVRational sar;
00802     av_reduce(&sar.num, &sar.den, track->enc->sample_aspect_ratio.num,
00803               track->enc->sample_aspect_ratio.den, INT_MAX);
00804 
00805     avio_wb32(pb, 16);
00806     ffio_wfourcc(pb, "pasp");
00807     avio_wb32(pb, sar.num);
00808     avio_wb32(pb, sar.den);
00809     return 16;
00810 }
00811 
00812 static int mov_write_video_tag(AVIOContext *pb, MOVTrack *track)
00813 {
00814     int64_t pos = avio_tell(pb);
00815     char compressor_name[32];
00816 
00817     avio_wb32(pb, 0); /* size */
00818     avio_wl32(pb, track->tag); // store it byteswapped
00819     avio_wb32(pb, 0); /* Reserved */
00820     avio_wb16(pb, 0); /* Reserved */
00821     avio_wb16(pb, 1); /* Data-reference index */
00822 
00823     avio_wb16(pb, 0); /* Codec stream version */
00824     avio_wb16(pb, 0); /* Codec stream revision (=0) */
00825     if (track->mode == MODE_MOV) {
00826         ffio_wfourcc(pb, "FFMP"); /* Vendor */
00827         if(track->enc->codec_id == CODEC_ID_RAWVIDEO) {
00828             avio_wb32(pb, 0); /* Temporal Quality */
00829             avio_wb32(pb, 0x400); /* Spatial Quality = lossless*/
00830         } else {
00831             avio_wb32(pb, 0x200); /* Temporal Quality = normal */
00832             avio_wb32(pb, 0x200); /* Spatial Quality = normal */
00833         }
00834     } else {
00835         avio_wb32(pb, 0); /* Reserved */
00836         avio_wb32(pb, 0); /* Reserved */
00837         avio_wb32(pb, 0); /* Reserved */
00838     }
00839     avio_wb16(pb, track->enc->width); /* Video width */
00840     avio_wb16(pb, track->height); /* Video height */
00841     avio_wb32(pb, 0x00480000); /* Horizontal resolution 72dpi */
00842     avio_wb32(pb, 0x00480000); /* Vertical resolution 72dpi */
00843     avio_wb32(pb, 0); /* Data size (= 0) */
00844     avio_wb16(pb, 1); /* Frame count (= 1) */
00845 
00846     memset(compressor_name,0,32);
00847     /* FIXME not sure, ISO 14496-1 draft where it shall be set to 0 */
00848     if (track->mode == MODE_MOV && track->enc->codec && track->enc->codec->name)
00849         av_strlcpy(compressor_name,track->enc->codec->name,32);
00850     avio_w8(pb, strlen(compressor_name));
00851     avio_write(pb, compressor_name, 31);
00852 
00853     if (track->mode == MODE_MOV && track->enc->bits_per_coded_sample)
00854         avio_wb16(pb, track->enc->bits_per_coded_sample);
00855     else
00856         avio_wb16(pb, 0x18); /* Reserved */
00857     avio_wb16(pb, 0xffff); /* Reserved */
00858     if(track->tag == MKTAG('m','p','4','v'))
00859         mov_write_esds_tag(pb, track);
00860     else if(track->enc->codec_id == CODEC_ID_H263)
00861         mov_write_d263_tag(pb);
00862     else if(track->enc->codec_id == CODEC_ID_SVQ3)
00863         mov_write_svq3_tag(pb);
00864     else if(track->enc->codec_id == CODEC_ID_DNXHD)
00865         mov_write_avid_tag(pb, track);
00866     else if(track->enc->codec_id == CODEC_ID_H264) {
00867         mov_write_avcc_tag(pb, track);
00868         if(track->mode == MODE_IPOD)
00869             mov_write_uuid_tag_ipod(pb);
00870     } else if(track->vosLen > 0)
00871         mov_write_glbl_tag(pb, track);
00872 
00873     if (track->enc->sample_aspect_ratio.den && track->enc->sample_aspect_ratio.num &&
00874         track->enc->sample_aspect_ratio.den != track->enc->sample_aspect_ratio.num) {
00875         mov_write_pasp_tag(pb, track);
00876     }
00877 
00878     return updateSize(pb, pos);
00879 }
00880 
00881 static int mov_write_rtp_tag(AVIOContext *pb, MOVTrack *track)
00882 {
00883     int64_t pos = avio_tell(pb);
00884     avio_wb32(pb, 0); /* size */
00885     ffio_wfourcc(pb, "rtp ");
00886     avio_wb32(pb, 0); /* Reserved */
00887     avio_wb16(pb, 0); /* Reserved */
00888     avio_wb16(pb, 1); /* Data-reference index */
00889 
00890     avio_wb16(pb, 1); /* Hint track version */
00891     avio_wb16(pb, 1); /* Highest compatible version */
00892     avio_wb32(pb, track->max_packet_size); /* Max packet size */
00893 
00894     avio_wb32(pb, 12); /* size */
00895     ffio_wfourcc(pb, "tims");
00896     avio_wb32(pb, track->timescale);
00897 
00898     return updateSize(pb, pos);
00899 }
00900 
00901 static int mov_write_stsd_tag(AVIOContext *pb, MOVTrack *track)
00902 {
00903     int64_t pos = avio_tell(pb);
00904     avio_wb32(pb, 0); /* size */
00905     ffio_wfourcc(pb, "stsd");
00906     avio_wb32(pb, 0); /* version & flags */
00907     avio_wb32(pb, 1); /* entry count */
00908     if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO)
00909         mov_write_video_tag(pb, track);
00910     else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
00911         mov_write_audio_tag(pb, track);
00912     else if (track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE)
00913         mov_write_subtitle_tag(pb, track);
00914     else if (track->enc->codec_tag == MKTAG('r','t','p',' '))
00915         mov_write_rtp_tag(pb, track);
00916     return updateSize(pb, pos);
00917 }
00918 
00919 static int mov_write_ctts_tag(AVIOContext *pb, MOVTrack *track)
00920 {
00921     MOVStts *ctts_entries;
00922     uint32_t entries = 0;
00923     uint32_t atom_size;
00924     int i;
00925 
00926     ctts_entries = av_malloc((track->entry + 1) * sizeof(*ctts_entries)); /* worst case */
00927     ctts_entries[0].count = 1;
00928     ctts_entries[0].duration = track->cluster[0].cts;
00929     for (i=1; i<track->entry; i++) {
00930         if (track->cluster[i].cts == ctts_entries[entries].duration) {
00931             ctts_entries[entries].count++; /* compress */
00932         } else {
00933             entries++;
00934             ctts_entries[entries].duration = track->cluster[i].cts;
00935             ctts_entries[entries].count = 1;
00936         }
00937     }
00938     entries++; /* last one */
00939     atom_size = 16 + (entries * 8);
00940     avio_wb32(pb, atom_size); /* size */
00941     ffio_wfourcc(pb, "ctts");
00942     avio_wb32(pb, 0); /* version & flags */
00943     avio_wb32(pb, entries); /* entry count */
00944     for (i=0; i<entries; i++) {
00945         avio_wb32(pb, ctts_entries[i].count);
00946         avio_wb32(pb, ctts_entries[i].duration);
00947     }
00948     av_free(ctts_entries);
00949     return atom_size;
00950 }
00951 
00952 /* Time to sample atom */
00953 static int mov_write_stts_tag(AVIOContext *pb, MOVTrack *track)
00954 {
00955     MOVStts *stts_entries;
00956     uint32_t entries = -1;
00957     uint32_t atom_size;
00958     int i;
00959 
00960     if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO && !track->audio_vbr) {
00961         stts_entries = av_malloc(sizeof(*stts_entries)); /* one entry */
00962         stts_entries[0].count = track->sampleCount;
00963         stts_entries[0].duration = 1;
00964         entries = 1;
00965     } else {
00966         stts_entries = av_malloc(track->entry * sizeof(*stts_entries)); /* worst case */
00967         for (i=0; i<track->entry; i++) {
00968             int64_t duration = i + 1 == track->entry ?
00969                 track->trackDuration - track->cluster[i].dts + track->cluster[0].dts : /* readjusting */
00970                 track->cluster[i+1].dts - track->cluster[i].dts;
00971             if (i && duration == stts_entries[entries].duration) {
00972                 stts_entries[entries].count++; /* compress */
00973             } else {
00974                 entries++;
00975                 stts_entries[entries].duration = duration;
00976                 stts_entries[entries].count = 1;
00977             }
00978         }
00979         entries++; /* last one */
00980     }
00981     atom_size = 16 + (entries * 8);
00982     avio_wb32(pb, atom_size); /* size */
00983     ffio_wfourcc(pb, "stts");
00984     avio_wb32(pb, 0); /* version & flags */
00985     avio_wb32(pb, entries); /* entry count */
00986     for (i=0; i<entries; i++) {
00987         avio_wb32(pb, stts_entries[i].count);
00988         avio_wb32(pb, stts_entries[i].duration);
00989     }
00990     av_free(stts_entries);
00991     return atom_size;
00992 }
00993 
00994 static int mov_write_dref_tag(AVIOContext *pb)
00995 {
00996     avio_wb32(pb, 28); /* size */
00997     ffio_wfourcc(pb, "dref");
00998     avio_wb32(pb, 0); /* version & flags */
00999     avio_wb32(pb, 1); /* entry count */
01000 
01001     avio_wb32(pb, 0xc); /* size */
01002     ffio_wfourcc(pb, "url ");
01003     avio_wb32(pb, 1); /* version & flags */
01004 
01005     return 28;
01006 }
01007 
01008 static int mov_write_stbl_tag(AVIOContext *pb, MOVTrack *track)
01009 {
01010     int64_t pos = avio_tell(pb);
01011     avio_wb32(pb, 0); /* size */
01012     ffio_wfourcc(pb, "stbl");
01013     mov_write_stsd_tag(pb, track);
01014     mov_write_stts_tag(pb, track);
01015     if ((track->enc->codec_type == AVMEDIA_TYPE_VIDEO ||
01016          track->enc->codec_tag == MKTAG('r','t','p',' ')) &&
01017         track->hasKeyframes && track->hasKeyframes < track->entry)
01018         mov_write_stss_tag(pb, track, MOV_SYNC_SAMPLE);
01019     if (track->mode == MODE_MOV && track->flags & MOV_TRACK_STPS)
01020         mov_write_stss_tag(pb, track, MOV_PARTIAL_SYNC_SAMPLE);
01021     if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO &&
01022         track->flags & MOV_TRACK_CTTS)
01023         mov_write_ctts_tag(pb, track);
01024     mov_write_stsc_tag(pb, track);
01025     mov_write_stsz_tag(pb, track);
01026     mov_write_stco_tag(pb, track);
01027     return updateSize(pb, pos);
01028 }
01029 
01030 static int mov_write_dinf_tag(AVIOContext *pb)
01031 {
01032     int64_t pos = avio_tell(pb);
01033     avio_wb32(pb, 0); /* size */
01034     ffio_wfourcc(pb, "dinf");
01035     mov_write_dref_tag(pb);
01036     return updateSize(pb, pos);
01037 }
01038 
01039 static int mov_write_nmhd_tag(AVIOContext *pb)
01040 {
01041     avio_wb32(pb, 12);
01042     ffio_wfourcc(pb, "nmhd");
01043     avio_wb32(pb, 0);
01044     return 12;
01045 }
01046 
01047 static int mov_write_gmhd_tag(AVIOContext *pb)
01048 {
01049     avio_wb32(pb, 0x20);   /* size */
01050     ffio_wfourcc(pb, "gmhd");
01051     avio_wb32(pb, 0x18);   /* gmin size */
01052     ffio_wfourcc(pb, "gmin");/* generic media info */
01053     avio_wb32(pb, 0);      /* version & flags */
01054     avio_wb16(pb, 0x40);   /* graphics mode = */
01055     avio_wb16(pb, 0x8000); /* opColor (r?) */
01056     avio_wb16(pb, 0x8000); /* opColor (g?) */
01057     avio_wb16(pb, 0x8000); /* opColor (b?) */
01058     avio_wb16(pb, 0);      /* balance */
01059     avio_wb16(pb, 0);      /* reserved */
01060     return 0x20;
01061 }
01062 
01063 static int mov_write_smhd_tag(AVIOContext *pb)
01064 {
01065     avio_wb32(pb, 16); /* size */
01066     ffio_wfourcc(pb, "smhd");
01067     avio_wb32(pb, 0); /* version & flags */
01068     avio_wb16(pb, 0); /* reserved (balance, normally = 0) */
01069     avio_wb16(pb, 0); /* reserved */
01070     return 16;
01071 }
01072 
01073 static int mov_write_vmhd_tag(AVIOContext *pb)
01074 {
01075     avio_wb32(pb, 0x14); /* size (always 0x14) */
01076     ffio_wfourcc(pb, "vmhd");
01077     avio_wb32(pb, 0x01); /* version & flags */
01078     avio_wb64(pb, 0); /* reserved (graphics mode = copy) */
01079     return 0x14;
01080 }
01081 
01082 static int mov_write_hdlr_tag(AVIOContext *pb, MOVTrack *track)
01083 {
01084     const char *hdlr, *descr = NULL, *hdlr_type = NULL;
01085     int64_t pos = avio_tell(pb);
01086 
01087     if (!track) { /* no media --> data handler */
01088         hdlr = "dhlr";
01089         hdlr_type = "url ";
01090         descr = "DataHandler";
01091     } else {
01092         hdlr = (track->mode == MODE_MOV) ? "mhlr" : "\0\0\0\0";
01093         if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) {
01094             hdlr_type = "vide";
01095             descr = "VideoHandler";
01096         } else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) {
01097             hdlr_type = "soun";
01098             descr = "SoundHandler";
01099         } else if (track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE) {
01100             if (track->tag == MKTAG('t','x','3','g')) hdlr_type = "sbtl";
01101             else                                      hdlr_type = "text";
01102             descr = "SubtitleHandler";
01103         } else if (track->enc->codec_tag == MKTAG('r','t','p',' ')) {
01104             hdlr_type = "hint";
01105             descr = "HintHandler";
01106         }
01107     }
01108 
01109     avio_wb32(pb, 0); /* size */
01110     ffio_wfourcc(pb, "hdlr");
01111     avio_wb32(pb, 0); /* Version & flags */
01112     avio_write(pb, hdlr, 4); /* handler */
01113     ffio_wfourcc(pb, hdlr_type); /* handler type */
01114     avio_wb32(pb ,0); /* reserved */
01115     avio_wb32(pb ,0); /* reserved */
01116     avio_wb32(pb ,0); /* reserved */
01117     if (!track || track->mode == MODE_MOV)
01118         avio_w8(pb, strlen(descr)); /* pascal string */
01119     avio_write(pb, descr, strlen(descr)); /* handler description */
01120     if (track && track->mode != MODE_MOV)
01121         avio_w8(pb, 0); /* c string */
01122     return updateSize(pb, pos);
01123 }
01124 
01125 static int mov_write_hmhd_tag(AVIOContext *pb)
01126 {
01127     /* This atom must be present, but leaving the values at zero
01128      * seems harmless. */
01129     avio_wb32(pb, 28); /* size */
01130     ffio_wfourcc(pb, "hmhd");
01131     avio_wb32(pb, 0); /* version, flags */
01132     avio_wb16(pb, 0); /* maxPDUsize */
01133     avio_wb16(pb, 0); /* avgPDUsize */
01134     avio_wb32(pb, 0); /* maxbitrate */
01135     avio_wb32(pb, 0); /* avgbitrate */
01136     avio_wb32(pb, 0); /* reserved */
01137     return 28;
01138 }
01139 
01140 static int mov_write_minf_tag(AVIOContext *pb, MOVTrack *track)
01141 {
01142     int64_t pos = avio_tell(pb);
01143     avio_wb32(pb, 0); /* size */
01144     ffio_wfourcc(pb, "minf");
01145     if(track->enc->codec_type == AVMEDIA_TYPE_VIDEO)
01146         mov_write_vmhd_tag(pb);
01147     else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
01148         mov_write_smhd_tag(pb);
01149     else if (track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE) {
01150         if (track->tag == MKTAG('t','e','x','t')) mov_write_gmhd_tag(pb);
01151         else                                      mov_write_nmhd_tag(pb);
01152     } else if (track->tag == MKTAG('r','t','p',' ')) {
01153         mov_write_hmhd_tag(pb);
01154     }
01155     if (track->mode == MODE_MOV) /* FIXME: Why do it for MODE_MOV only ? */
01156         mov_write_hdlr_tag(pb, NULL);
01157     mov_write_dinf_tag(pb);
01158     mov_write_stbl_tag(pb, track);
01159     return updateSize(pb, pos);
01160 }
01161 
01162 static int mov_write_mdhd_tag(AVIOContext *pb, MOVTrack *track)
01163 {
01164     int version = track->trackDuration < INT32_MAX ? 0 : 1;
01165 
01166     (version == 1) ? avio_wb32(pb, 44) : avio_wb32(pb, 32); /* size */
01167     ffio_wfourcc(pb, "mdhd");
01168     avio_w8(pb, version);
01169     avio_wb24(pb, 0); /* flags */
01170     if (version == 1) {
01171         avio_wb64(pb, track->time);
01172         avio_wb64(pb, track->time);
01173     } else {
01174         avio_wb32(pb, track->time); /* creation time */
01175         avio_wb32(pb, track->time); /* modification time */
01176     }
01177     avio_wb32(pb, track->timescale); /* time scale (sample rate for audio) */
01178     (version == 1) ? avio_wb64(pb, track->trackDuration) : avio_wb32(pb, track->trackDuration); /* duration */
01179     avio_wb16(pb, track->language); /* language */
01180     avio_wb16(pb, 0); /* reserved (quality) */
01181 
01182     if(version!=0 && track->mode == MODE_MOV){
01183         av_log(NULL, AV_LOG_ERROR,
01184             "FATAL error, file duration too long for timebase, this file will not be\n"
01185             "playable with quicktime. Choose a different timebase or a different\n"
01186             "container format\n");
01187     }
01188 
01189     return 32;
01190 }
01191 
01192 static int mov_write_mdia_tag(AVIOContext *pb, MOVTrack *track)
01193 {
01194     int64_t pos = avio_tell(pb);
01195     avio_wb32(pb, 0); /* size */
01196     ffio_wfourcc(pb, "mdia");
01197     mov_write_mdhd_tag(pb, track);
01198     mov_write_hdlr_tag(pb, track);
01199     mov_write_minf_tag(pb, track);
01200     return updateSize(pb, pos);
01201 }
01202 
01203 static int mov_write_tkhd_tag(AVIOContext *pb, MOVTrack *track, AVStream *st)
01204 {
01205     int64_t duration = av_rescale_rnd(track->trackDuration, MOV_TIMESCALE,
01206                                       track->timescale, AV_ROUND_UP);
01207     int version = duration < INT32_MAX ? 0 : 1;
01208 
01209     (version == 1) ? avio_wb32(pb, 104) : avio_wb32(pb, 92); /* size */
01210     ffio_wfourcc(pb, "tkhd");
01211     avio_w8(pb, version);
01212     avio_wb24(pb, 0xf); /* flags (track enabled) */
01213     if (version == 1) {
01214         avio_wb64(pb, track->time);
01215         avio_wb64(pb, track->time);
01216     } else {
01217         avio_wb32(pb, track->time); /* creation time */
01218         avio_wb32(pb, track->time); /* modification time */
01219     }
01220     avio_wb32(pb, track->trackID); /* track-id */
01221     avio_wb32(pb, 0); /* reserved */
01222     (version == 1) ? avio_wb64(pb, duration) : avio_wb32(pb, duration);
01223 
01224     avio_wb32(pb, 0); /* reserved */
01225     avio_wb32(pb, 0); /* reserved */
01226     avio_wb16(pb, 0); /* layer */
01227     avio_wb16(pb, st ? st->codec->codec_type : 0); /* alternate group) */
01228     /* Volume, only for audio */
01229     if(track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
01230         avio_wb16(pb, 0x0100);
01231     else
01232         avio_wb16(pb, 0);
01233     avio_wb16(pb, 0); /* reserved */
01234 
01235     /* Matrix structure */
01236     avio_wb32(pb, 0x00010000); /* reserved */
01237     avio_wb32(pb, 0x0); /* reserved */
01238     avio_wb32(pb, 0x0); /* reserved */
01239     avio_wb32(pb, 0x0); /* reserved */
01240     avio_wb32(pb, 0x00010000); /* reserved */
01241     avio_wb32(pb, 0x0); /* reserved */
01242     avio_wb32(pb, 0x0); /* reserved */
01243     avio_wb32(pb, 0x0); /* reserved */
01244     avio_wb32(pb, 0x40000000); /* reserved */
01245 
01246     /* Track width and height, for visual only */
01247     if(st && (track->enc->codec_type == AVMEDIA_TYPE_VIDEO ||
01248               track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE)) {
01249         if(track->mode == MODE_MOV) {
01250             avio_wb32(pb, track->enc->width << 16);
01251             avio_wb32(pb, track->height << 16);
01252         } else {
01253             double sample_aspect_ratio = av_q2d(st->sample_aspect_ratio);
01254             if(!sample_aspect_ratio || track->height != track->enc->height)
01255                 sample_aspect_ratio = 1;
01256             avio_wb32(pb, sample_aspect_ratio * track->enc->width*0x10000);
01257             avio_wb32(pb, track->height*0x10000);
01258         }
01259     }
01260     else {
01261         avio_wb32(pb, 0);
01262         avio_wb32(pb, 0);
01263     }
01264     return 0x5c;
01265 }
01266 
01267 static int mov_write_tapt_tag(AVIOContext *pb, MOVTrack *track)
01268 {
01269     int32_t width = av_rescale(track->enc->sample_aspect_ratio.num, track->enc->width,
01270                                track->enc->sample_aspect_ratio.den);
01271 
01272     int64_t pos = avio_tell(pb);
01273 
01274     avio_wb32(pb, 0); /* size */
01275     ffio_wfourcc(pb, "tapt");
01276 
01277     avio_wb32(pb, 20);
01278     ffio_wfourcc(pb, "clef");
01279     avio_wb32(pb, 0);
01280     avio_wb32(pb, width << 16);
01281     avio_wb32(pb, track->enc->height << 16);
01282 
01283     avio_wb32(pb, 20);
01284     ffio_wfourcc(pb, "enof");
01285     avio_wb32(pb, 0);
01286     avio_wb32(pb, track->enc->width << 16);
01287     avio_wb32(pb, track->enc->height << 16);
01288 
01289     return updateSize(pb, pos);
01290 };
01291 
01292 // This box seems important for the psp playback ... without it the movie seems to hang
01293 static int mov_write_edts_tag(AVIOContext *pb, MOVTrack *track)
01294 {
01295     int64_t duration = av_rescale_rnd(track->trackDuration, MOV_TIMESCALE,
01296                                       track->timescale, AV_ROUND_UP);
01297     int version = duration < INT32_MAX ? 0 : 1;
01298     int entry_size, entry_count, size;
01299     int64_t delay, start_ct = track->cluster[0].cts;
01300     delay = av_rescale_rnd(track->cluster[0].dts + start_ct, MOV_TIMESCALE,
01301                            track->timescale, AV_ROUND_DOWN);
01302     version |= delay < INT32_MAX ? 0 : 1;
01303 
01304     entry_size = (version == 1) ? 20 : 12;
01305     entry_count = 1 + (delay > 0);
01306     size = 24 + entry_count * entry_size;
01307 
01308     /* write the atom data */
01309     avio_wb32(pb, size);
01310     ffio_wfourcc(pb, "edts");
01311     avio_wb32(pb, size - 8);
01312     ffio_wfourcc(pb, "elst");
01313     avio_w8(pb, version);
01314     avio_wb24(pb, 0); /* flags */
01315 
01316     avio_wb32(pb, entry_count);
01317     if (delay > 0) { /* add an empty edit to delay presentation */
01318         if (version == 1) {
01319             avio_wb64(pb, delay);
01320             avio_wb64(pb, -1);
01321         } else {
01322             avio_wb32(pb, delay);
01323             avio_wb32(pb, -1);
01324         }
01325         avio_wb32(pb, 0x00010000);
01326     }
01327 
01328     /* duration */
01329     if (version == 1) {
01330         avio_wb64(pb, duration);
01331         avio_wb64(pb, start_ct);
01332     } else {
01333         avio_wb32(pb, duration);
01334         avio_wb32(pb, start_ct);
01335     }
01336     avio_wb32(pb, 0x00010000);
01337     return size;
01338 }
01339 
01340 static int mov_write_tref_tag(AVIOContext *pb, MOVTrack *track)
01341 {
01342     avio_wb32(pb, 20);   // size
01343     ffio_wfourcc(pb, "tref");
01344     avio_wb32(pb, 12);   // size (subatom)
01345     avio_wl32(pb, track->tref_tag);
01346     avio_wb32(pb, track->tref_id);
01347     return 20;
01348 }
01349 
01350 // goes at the end of each track!  ... Critical for PSP playback ("Incompatible data" without it)
01351 static int mov_write_uuid_tag_psp(AVIOContext *pb, MOVTrack *mov)
01352 {
01353     avio_wb32(pb, 0x34); /* size ... reports as 28 in mp4box! */
01354     ffio_wfourcc(pb, "uuid");
01355     ffio_wfourcc(pb, "USMT");
01356     avio_wb32(pb, 0x21d24fce);
01357     avio_wb32(pb, 0xbb88695c);
01358     avio_wb32(pb, 0xfac9c740);
01359     avio_wb32(pb, 0x1c);     // another size here!
01360     ffio_wfourcc(pb, "MTDT");
01361     avio_wb32(pb, 0x00010012);
01362     avio_wb32(pb, 0x0a);
01363     avio_wb32(pb, 0x55c40000);
01364     avio_wb32(pb, 0x1);
01365     avio_wb32(pb, 0x0);
01366     return 0x34;
01367 }
01368 
01369 static int mov_write_udta_sdp(AVIOContext *pb, AVFormatContext *ctx, int index)
01370 {
01371     char buf[1000] = "";
01372     int len;
01373 
01374     ff_sdp_write_media(buf, sizeof(buf), ctx->streams[0]->codec, NULL, NULL, 0, 0, ctx);
01375     av_strlcatf(buf, sizeof(buf), "a=control:streamid=%d\r\n", index);
01376     len = strlen(buf);
01377 
01378     avio_wb32(pb, len + 24);
01379     ffio_wfourcc(pb, "udta");
01380     avio_wb32(pb, len + 16);
01381     ffio_wfourcc(pb, "hnti");
01382     avio_wb32(pb, len + 8);
01383     ffio_wfourcc(pb, "sdp ");
01384     avio_write(pb, buf, len);
01385     return len + 24;
01386 }
01387 
01388 static int mov_write_trak_tag(AVIOContext *pb, MOVTrack *track, AVStream *st)
01389 {
01390     int64_t pos = avio_tell(pb);
01391     avio_wb32(pb, 0); /* size */
01392     ffio_wfourcc(pb, "trak");
01393     mov_write_tkhd_tag(pb, track, st);
01394     if (track->mode == MODE_PSP || track->flags & MOV_TRACK_CTTS || track->cluster[0].dts)
01395         mov_write_edts_tag(pb, track);  // PSP Movies require edts box
01396     if (track->tref_tag)
01397         mov_write_tref_tag(pb, track);
01398     mov_write_mdia_tag(pb, track);
01399     if (track->mode == MODE_PSP)
01400         mov_write_uuid_tag_psp(pb,track);  // PSP Movies require this uuid box
01401     if (track->tag == MKTAG('r','t','p',' '))
01402         mov_write_udta_sdp(pb, track->rtp_ctx, track->trackID);
01403     if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO && track->mode == MODE_MOV) {
01404         double sample_aspect_ratio = av_q2d(st->sample_aspect_ratio);
01405         if (0.0 != sample_aspect_ratio && 1.0 != sample_aspect_ratio)
01406             mov_write_tapt_tag(pb, track);
01407     };
01408     return updateSize(pb, pos);
01409 }
01410 
01411 #if 0
01412 /* TODO: Not sorted out, but not necessary either */
01413 static int mov_write_iods_tag(AVIOContext *pb, MOVMuxContext *mov)
01414 {
01415     avio_wb32(pb, 0x15); /* size */
01416     ffio_wfourcc(pb, "iods");
01417     avio_wb32(pb, 0);    /* version & flags */
01418     avio_wb16(pb, 0x1007);
01419     avio_w8(pb, 0);
01420     avio_wb16(pb, 0x4fff);
01421     avio_wb16(pb, 0xfffe);
01422     avio_wb16(pb, 0x01ff);
01423     return 0x15;
01424 }
01425 #endif
01426 
01427 static int mov_write_mvhd_tag(AVIOContext *pb, MOVMuxContext *mov)
01428 {
01429     int maxTrackID = 1, i;
01430     int64_t maxTrackLenTemp, maxTrackLen = 0;
01431     int version;
01432 
01433     for (i=0; i<mov->nb_streams; i++) {
01434         if(mov->tracks[i].entry > 0) {
01435             maxTrackLenTemp = av_rescale_rnd(mov->tracks[i].trackDuration,
01436                                              MOV_TIMESCALE,
01437                                              mov->tracks[i].timescale,
01438                                              AV_ROUND_UP);
01439             if(maxTrackLen < maxTrackLenTemp)
01440                 maxTrackLen = maxTrackLenTemp;
01441             if(maxTrackID < mov->tracks[i].trackID)
01442                 maxTrackID = mov->tracks[i].trackID;
01443         }
01444     }
01445 
01446     version = maxTrackLen < UINT32_MAX ? 0 : 1;
01447     (version == 1) ? avio_wb32(pb, 120) : avio_wb32(pb, 108); /* size */
01448     ffio_wfourcc(pb, "mvhd");
01449     avio_w8(pb, version);
01450     avio_wb24(pb, 0); /* flags */
01451     if (version == 1) {
01452         avio_wb64(pb, mov->time);
01453         avio_wb64(pb, mov->time);
01454     } else {
01455         avio_wb32(pb, mov->time); /* creation time */
01456         avio_wb32(pb, mov->time); /* modification time */
01457     }
01458     avio_wb32(pb, MOV_TIMESCALE);
01459     (version == 1) ? avio_wb64(pb, maxTrackLen) : avio_wb32(pb, maxTrackLen); /* duration of longest track */
01460 
01461     avio_wb32(pb, 0x00010000); /* reserved (preferred rate) 1.0 = normal */
01462     avio_wb16(pb, 0x0100); /* reserved (preferred volume) 1.0 = normal */
01463     avio_wb16(pb, 0); /* reserved */
01464     avio_wb32(pb, 0); /* reserved */
01465     avio_wb32(pb, 0); /* reserved */
01466 
01467     /* Matrix structure */
01468     avio_wb32(pb, 0x00010000); /* reserved */
01469     avio_wb32(pb, 0x0); /* reserved */
01470     avio_wb32(pb, 0x0); /* reserved */
01471     avio_wb32(pb, 0x0); /* reserved */
01472     avio_wb32(pb, 0x00010000); /* reserved */
01473     avio_wb32(pb, 0x0); /* reserved */
01474     avio_wb32(pb, 0x0); /* reserved */
01475     avio_wb32(pb, 0x0); /* reserved */
01476     avio_wb32(pb, 0x40000000); /* reserved */
01477 
01478     avio_wb32(pb, 0); /* reserved (preview time) */
01479     avio_wb32(pb, 0); /* reserved (preview duration) */
01480     avio_wb32(pb, 0); /* reserved (poster time) */
01481     avio_wb32(pb, 0); /* reserved (selection time) */
01482     avio_wb32(pb, 0); /* reserved (selection duration) */
01483     avio_wb32(pb, 0); /* reserved (current time) */
01484     avio_wb32(pb, maxTrackID+1); /* Next track id */
01485     return 0x6c;
01486 }
01487 
01488 static int mov_write_itunes_hdlr_tag(AVIOContext *pb, MOVMuxContext *mov,
01489                                      AVFormatContext *s)
01490 {
01491     avio_wb32(pb, 33); /* size */
01492     ffio_wfourcc(pb, "hdlr");
01493     avio_wb32(pb, 0);
01494     avio_wb32(pb, 0);
01495     ffio_wfourcc(pb, "mdir");
01496     ffio_wfourcc(pb, "appl");
01497     avio_wb32(pb, 0);
01498     avio_wb32(pb, 0);
01499     avio_w8(pb, 0);
01500     return 33;
01501 }
01502 
01503 /* helper function to write a data tag with the specified string as data */
01504 static int mov_write_string_data_tag(AVIOContext *pb, const char *data, int lang, int long_style)
01505 {
01506     if(long_style){
01507         int size = 16 + strlen(data);
01508         avio_wb32(pb, size); /* size */
01509         ffio_wfourcc(pb, "data");
01510         avio_wb32(pb, 1);
01511         avio_wb32(pb, 0);
01512         avio_write(pb, data, strlen(data));
01513         return size;
01514     }else{
01515         if (!lang)
01516             lang = ff_mov_iso639_to_lang("und", 1);
01517         avio_wb16(pb, strlen(data)); /* string length */
01518         avio_wb16(pb, lang);
01519         avio_write(pb, data, strlen(data));
01520         return strlen(data) + 4;
01521     }
01522 }
01523 
01524 static int mov_write_string_tag(AVIOContext *pb, const char *name, const char *value, int lang, int long_style){
01525     int size = 0;
01526     if (value && value[0]) {
01527         int64_t pos = avio_tell(pb);
01528         avio_wb32(pb, 0); /* size */
01529         ffio_wfourcc(pb, name);
01530         mov_write_string_data_tag(pb, value, lang, long_style);
01531         size= updateSize(pb, pos);
01532     }
01533     return size;
01534 }
01535 
01536 static int mov_write_string_metadata(AVFormatContext *s, AVIOContext *pb,
01537                                      const char *name, const char *tag,
01538                                      int long_style)
01539 {
01540     int l, lang = 0, len, len2;
01541     AVDictionaryEntry *t, *t2 = NULL;
01542     char tag2[16];
01543 
01544     if (!(t = av_dict_get(s->metadata, tag, NULL, 0)))
01545         return 0;
01546 
01547     len = strlen(t->key);
01548     snprintf(tag2, sizeof(tag2), "%s-", tag);
01549     while ((t2 = av_dict_get(s->metadata, tag2, t2, AV_DICT_IGNORE_SUFFIX))) {
01550         len2 = strlen(t2->key);
01551         if (len2 == len+4 && !strcmp(t->value, t2->value)
01552             && (l=ff_mov_iso639_to_lang(&t2->key[len2-3], 1)) >= 0) {
01553             lang = l;
01554             break;
01555         }
01556     }
01557     return mov_write_string_tag(pb, name, t->value, lang, long_style);
01558 }
01559 
01560 /* iTunes track number */
01561 static int mov_write_trkn_tag(AVIOContext *pb, MOVMuxContext *mov,
01562                               AVFormatContext *s)
01563 {
01564     AVDictionaryEntry *t = av_dict_get(s->metadata, "track", NULL, 0);
01565     int size = 0, track = t ? atoi(t->value) : 0;
01566     if (track) {
01567         avio_wb32(pb, 32); /* size */
01568         ffio_wfourcc(pb, "trkn");
01569             avio_wb32(pb, 24); /* size */
01570             ffio_wfourcc(pb, "data");
01571             avio_wb32(pb, 0);        // 8 bytes empty
01572             avio_wb32(pb, 0);
01573             avio_wb16(pb, 0);        // empty
01574             avio_wb16(pb, track);    // track number
01575             avio_wb16(pb, 0);        // total track number
01576             avio_wb16(pb, 0);        // empty
01577         size = 32;
01578     }
01579     return size;
01580 }
01581 
01582 /* iTunes meta data list */
01583 static int mov_write_ilst_tag(AVIOContext *pb, MOVMuxContext *mov,
01584                               AVFormatContext *s)
01585 {
01586     int64_t pos = avio_tell(pb);
01587     avio_wb32(pb, 0); /* size */
01588     ffio_wfourcc(pb, "ilst");
01589     mov_write_string_metadata(s, pb, "\251nam", "title"    , 1);
01590     mov_write_string_metadata(s, pb, "\251ART", "artist"   , 1);
01591     mov_write_string_metadata(s, pb, "aART", "album_artist", 1);
01592     mov_write_string_metadata(s, pb, "\251wrt", "composer" , 1);
01593     mov_write_string_metadata(s, pb, "\251alb", "album"    , 1);
01594     mov_write_string_metadata(s, pb, "\251day", "date"     , 1);
01595     mov_write_string_tag(pb, "\251too", LIBAVFORMAT_IDENT, 0, 1);
01596     mov_write_string_metadata(s, pb, "\251cmt", "comment"  , 1);
01597     mov_write_string_metadata(s, pb, "\251gen", "genre"    , 1);
01598     mov_write_string_metadata(s, pb, "\251cpy", "copyright", 1);
01599     mov_write_string_metadata(s, pb, "\251grp", "grouping" , 1);
01600     mov_write_string_metadata(s, pb, "\251lyr", "lyrics"   , 1);
01601     mov_write_string_metadata(s, pb, "desc",    "description",1);
01602     mov_write_string_metadata(s, pb, "ldes",    "synopsis" , 1);
01603     mov_write_string_metadata(s, pb, "tvsh",    "show"     , 1);
01604     mov_write_string_metadata(s, pb, "tven",    "episode_id",1);
01605     mov_write_string_metadata(s, pb, "tvnn",    "network"  , 1);
01606     mov_write_trkn_tag(pb, mov, s);
01607     return updateSize(pb, pos);
01608 }
01609 
01610 /* iTunes meta data tag */
01611 static int mov_write_meta_tag(AVIOContext *pb, MOVMuxContext *mov,
01612                               AVFormatContext *s)
01613 {
01614     int size = 0;
01615     int64_t pos = avio_tell(pb);
01616     avio_wb32(pb, 0); /* size */
01617     ffio_wfourcc(pb, "meta");
01618     avio_wb32(pb, 0);
01619     mov_write_itunes_hdlr_tag(pb, mov, s);
01620     mov_write_ilst_tag(pb, mov, s);
01621     size = updateSize(pb, pos);
01622     return size;
01623 }
01624 
01625 static int utf8len(const uint8_t *b)
01626 {
01627     int len=0;
01628     int val;
01629     while(*b){
01630         GET_UTF8(val, *b++, return -1;)
01631         len++;
01632     }
01633     return len;
01634 }
01635 
01636 static int ascii_to_wc(AVIOContext *pb, const uint8_t *b)
01637 {
01638     int val;
01639     while(*b){
01640         GET_UTF8(val, *b++, return -1;)
01641         avio_wb16(pb, val);
01642     }
01643     avio_wb16(pb, 0x00);
01644     return 0;
01645 }
01646 
01647 static uint16_t language_code(const char *str)
01648 {
01649     return (((str[0]-0x60) & 0x1F) << 10) + (((str[1]-0x60) & 0x1F) << 5) + ((str[2]-0x60) & 0x1F);
01650 }
01651 
01652 static int mov_write_3gp_udta_tag(AVIOContext *pb, AVFormatContext *s,
01653                                   const char *tag, const char *str)
01654 {
01655     int64_t pos = avio_tell(pb);
01656     AVDictionaryEntry *t = av_dict_get(s->metadata, str, NULL, 0);
01657     if (!t || !utf8len(t->value))
01658         return 0;
01659     avio_wb32(pb, 0);   /* size */
01660     ffio_wfourcc(pb, tag); /* type */
01661     avio_wb32(pb, 0);   /* version + flags */
01662     if (!strcmp(tag, "yrrc"))
01663         avio_wb16(pb, atoi(t->value));
01664     else {
01665         avio_wb16(pb, language_code("eng")); /* language */
01666         avio_write(pb, t->value, strlen(t->value)+1); /* UTF8 string value */
01667         if (!strcmp(tag, "albm") &&
01668             (t = av_dict_get(s->metadata, "track", NULL, 0)))
01669             avio_w8(pb, atoi(t->value));
01670     }
01671     return updateSize(pb, pos);
01672 }
01673 
01674 static int mov_write_chpl_tag(AVIOContext *pb, AVFormatContext *s)
01675 {
01676     int64_t pos = avio_tell(pb);
01677     int i, nb_chapters = FFMIN(s->nb_chapters, 255);
01678 
01679     avio_wb32(pb, 0);            // size
01680     ffio_wfourcc(pb, "chpl");
01681     avio_wb32(pb, 0x01000000);   // version + flags
01682     avio_wb32(pb, 0);            // unknown
01683     avio_w8(pb, nb_chapters);
01684 
01685     for (i = 0; i < nb_chapters; i++) {
01686         AVChapter *c = s->chapters[i];
01687         AVDictionaryEntry *t;
01688         avio_wb64(pb, av_rescale_q(c->start, c->time_base, (AVRational){1,10000000}));
01689 
01690         if ((t = av_dict_get(c->metadata, "title", NULL, 0))) {
01691             int len = FFMIN(strlen(t->value), 255);
01692             avio_w8(pb, len);
01693             avio_write(pb, t->value, len);
01694         } else
01695             avio_w8(pb, 0);
01696     }
01697     return updateSize(pb, pos);
01698 }
01699 
01700 static int mov_write_udta_tag(AVIOContext *pb, MOVMuxContext *mov,
01701                               AVFormatContext *s)
01702 {
01703     AVIOContext *pb_buf;
01704     int i, ret, size;
01705     uint8_t *buf;
01706 
01707     for (i = 0; i < s->nb_streams; i++)
01708         if (mov->tracks[i].enc->flags & CODEC_FLAG_BITEXACT) {
01709             return 0;
01710         }
01711 
01712     ret = avio_open_dyn_buf(&pb_buf);
01713     if(ret < 0)
01714         return ret;
01715 
01716         if (mov->mode & MODE_3GP) {
01717             mov_write_3gp_udta_tag(pb_buf, s, "perf", "artist");
01718             mov_write_3gp_udta_tag(pb_buf, s, "titl", "title");
01719             mov_write_3gp_udta_tag(pb_buf, s, "auth", "author");
01720             mov_write_3gp_udta_tag(pb_buf, s, "gnre", "genre");
01721             mov_write_3gp_udta_tag(pb_buf, s, "dscp", "comment");
01722             mov_write_3gp_udta_tag(pb_buf, s, "albm", "album");
01723             mov_write_3gp_udta_tag(pb_buf, s, "cprt", "copyright");
01724             mov_write_3gp_udta_tag(pb_buf, s, "yrrc", "date");
01725         } else if (mov->mode == MODE_MOV) { // the title field breaks gtkpod with mp4 and my suspicion is that stuff is not valid in mp4
01726             mov_write_string_metadata(s, pb_buf, "\251ART", "artist"     , 0);
01727             mov_write_string_metadata(s, pb_buf, "\251nam", "title"      , 0);
01728             mov_write_string_metadata(s, pb_buf, "\251aut", "author"     , 0);
01729             mov_write_string_metadata(s, pb_buf, "\251alb", "album"      , 0);
01730             mov_write_string_metadata(s, pb_buf, "\251day", "date"       , 0);
01731             mov_write_string_metadata(s, pb_buf, "\251swr", "encoder"    , 0);
01732             mov_write_string_metadata(s, pb_buf, "\251des", "comment"    , 0);
01733             mov_write_string_metadata(s, pb_buf, "\251gen", "genre"      , 0);
01734             mov_write_string_metadata(s, pb_buf, "\251cpy", "copyright"  , 0);
01735         } else {
01736             /* iTunes meta data */
01737             mov_write_meta_tag(pb_buf, mov, s);
01738         }
01739 
01740         if (s->nb_chapters)
01741             mov_write_chpl_tag(pb_buf, s);
01742 
01743     if ((size = avio_close_dyn_buf(pb_buf, &buf)) > 0) {
01744         avio_wb32(pb, size+8);
01745         ffio_wfourcc(pb, "udta");
01746         avio_write(pb, buf, size);
01747     }
01748     av_free(buf);
01749 
01750     return 0;
01751 }
01752 
01753 static void mov_write_psp_udta_tag(AVIOContext *pb,
01754                                   const char *str, const char *lang, int type)
01755 {
01756     int len = utf8len(str)+1;
01757     if(len<=0)
01758         return;
01759     avio_wb16(pb, len*2+10);            /* size */
01760     avio_wb32(pb, type);                /* type */
01761     avio_wb16(pb, language_code(lang)); /* language */
01762     avio_wb16(pb, 0x01);                /* ? */
01763     ascii_to_wc(pb, str);
01764 }
01765 
01766 static int mov_write_uuidusmt_tag(AVIOContext *pb, AVFormatContext *s)
01767 {
01768     AVDictionaryEntry *title = av_dict_get(s->metadata, "title", NULL, 0);
01769     int64_t pos, pos2;
01770 
01771     if (title) {
01772         pos = avio_tell(pb);
01773         avio_wb32(pb, 0); /* size placeholder*/
01774         ffio_wfourcc(pb, "uuid");
01775         ffio_wfourcc(pb, "USMT");
01776         avio_wb32(pb, 0x21d24fce); /* 96 bit UUID */
01777         avio_wb32(pb, 0xbb88695c);
01778         avio_wb32(pb, 0xfac9c740);
01779 
01780         pos2 = avio_tell(pb);
01781         avio_wb32(pb, 0); /* size placeholder*/
01782         ffio_wfourcc(pb, "MTDT");
01783         avio_wb16(pb, 4);
01784 
01785         // ?
01786         avio_wb16(pb, 0x0C);                 /* size */
01787         avio_wb32(pb, 0x0B);                 /* type */
01788         avio_wb16(pb, language_code("und")); /* language */
01789         avio_wb16(pb, 0x0);                  /* ? */
01790         avio_wb16(pb, 0x021C);               /* data */
01791 
01792         mov_write_psp_udta_tag(pb, LIBAVCODEC_IDENT,      "eng", 0x04);
01793         mov_write_psp_udta_tag(pb, title->value,          "eng", 0x01);
01794 //        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);
01795         mov_write_psp_udta_tag(pb, "2006/04/01 11:11:11", "und", 0x03);
01796 
01797         updateSize(pb, pos2);
01798         return updateSize(pb, pos);
01799     }
01800 
01801     return 0;
01802 }
01803 
01804 static int mov_write_moov_tag(AVIOContext *pb, MOVMuxContext *mov,
01805                               AVFormatContext *s)
01806 {
01807     int i;
01808     int64_t pos = avio_tell(pb);
01809     avio_wb32(pb, 0); /* size placeholder*/
01810     ffio_wfourcc(pb, "moov");
01811 
01812     for (i=0; i<mov->nb_streams; i++) {
01813         if(mov->tracks[i].entry <= 0) continue;
01814 
01815         mov->tracks[i].time = mov->time;
01816         mov->tracks[i].trackID = i+1;
01817     }
01818 
01819     if (mov->chapter_track)
01820         for (i=0; i<s->nb_streams; i++) {
01821             mov->tracks[i].tref_tag = MKTAG('c','h','a','p');
01822             mov->tracks[i].tref_id = mov->tracks[mov->chapter_track].trackID;
01823         }
01824     for (i = 0; i < mov->nb_streams; i++) {
01825         if (mov->tracks[i].tag == MKTAG('r','t','p',' ')) {
01826             mov->tracks[i].tref_tag = MKTAG('h','i','n','t');
01827             mov->tracks[i].tref_id =
01828                 mov->tracks[mov->tracks[i].src_track].trackID;
01829         }
01830     }
01831 
01832     mov_write_mvhd_tag(pb, mov);
01833     //mov_write_iods_tag(pb, mov);
01834     for (i=0; i<mov->nb_streams; i++) {
01835         if(mov->tracks[i].entry > 0) {
01836             mov_write_trak_tag(pb, &(mov->tracks[i]), i < s->nb_streams ? s->streams[i] : NULL);
01837         }
01838     }
01839 
01840     if (mov->mode == MODE_PSP)
01841         mov_write_uuidusmt_tag(pb, s);
01842     else
01843         mov_write_udta_tag(pb, mov, s);
01844 
01845     return updateSize(pb, pos);
01846 }
01847 
01848 static int mov_write_mdat_tag(AVIOContext *pb, MOVMuxContext *mov)
01849 {
01850     avio_wb32(pb, 8);    // placeholder for extended size field (64 bit)
01851     ffio_wfourcc(pb, mov->mode == MODE_MOV ? "wide" : "free");
01852 
01853     mov->mdat_pos = avio_tell(pb);
01854     avio_wb32(pb, 0); /* size placeholder*/
01855     ffio_wfourcc(pb, "mdat");
01856     return 0;
01857 }
01858 
01859 /* TODO: This needs to be more general */
01860 static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s)
01861 {
01862     MOVMuxContext *mov = s->priv_data;
01863     int64_t pos = avio_tell(pb);
01864     int has_h264 = 0, has_video = 0;
01865     int minor = 0x200;
01866     int i;
01867 
01868     for (i = 0; i < s->nb_streams; i++) {
01869         AVStream *st = s->streams[i];
01870         if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
01871             has_video = 1;
01872         if (st->codec->codec_id == CODEC_ID_H264)
01873             has_h264 = 1;
01874     }
01875 
01876     avio_wb32(pb, 0); /* size */
01877     ffio_wfourcc(pb, "ftyp");
01878 
01879     if (mov->mode == MODE_3GP) {
01880         ffio_wfourcc(pb, has_h264 ? "3gp6"  : "3gp4");
01881         minor =     has_h264 ?   0x100 :   0x200;
01882     } else if (mov->mode & MODE_3G2) {
01883         ffio_wfourcc(pb, has_h264 ? "3g2b"  : "3g2a");
01884         minor =     has_h264 ? 0x20000 : 0x10000;
01885     }else if (mov->mode == MODE_PSP)
01886         ffio_wfourcc(pb, "MSNV");
01887     else if (mov->mode == MODE_MP4)
01888         ffio_wfourcc(pb, "isom");
01889     else if (mov->mode == MODE_IPOD)
01890         ffio_wfourcc(pb, has_video ? "M4V ":"M4A ");
01891     else
01892         ffio_wfourcc(pb, "qt  ");
01893 
01894     avio_wb32(pb, minor);
01895 
01896     if(mov->mode == MODE_MOV)
01897         ffio_wfourcc(pb, "qt  ");
01898     else{
01899         ffio_wfourcc(pb, "isom");
01900         ffio_wfourcc(pb, "iso2");
01901         if(has_h264)
01902             ffio_wfourcc(pb, "avc1");
01903     }
01904 
01905     if (mov->mode == MODE_3GP)
01906         ffio_wfourcc(pb, has_h264 ? "3gp6":"3gp4");
01907     else if (mov->mode & MODE_3G2)
01908         ffio_wfourcc(pb, has_h264 ? "3g2b":"3g2a");
01909     else if (mov->mode == MODE_PSP)
01910         ffio_wfourcc(pb, "MSNV");
01911     else if (mov->mode == MODE_MP4)
01912         ffio_wfourcc(pb, "mp41");
01913     return updateSize(pb, pos);
01914 }
01915 
01916 static void mov_write_uuidprof_tag(AVIOContext *pb, AVFormatContext *s)
01917 {
01918     AVCodecContext *VideoCodec = s->streams[0]->codec;
01919     AVCodecContext *AudioCodec = s->streams[1]->codec;
01920     int AudioRate = AudioCodec->sample_rate;
01921     int FrameRate = ((VideoCodec->time_base.den) * (0x10000))/ (VideoCodec->time_base.num);
01922     int audio_kbitrate= AudioCodec->bit_rate / 1000;
01923     int video_kbitrate= FFMIN(VideoCodec->bit_rate / 1000, 800 - audio_kbitrate);
01924 
01925     avio_wb32(pb, 0x94); /* size */
01926     ffio_wfourcc(pb, "uuid");
01927     ffio_wfourcc(pb, "PROF");
01928 
01929     avio_wb32(pb, 0x21d24fce); /* 96 bit UUID */
01930     avio_wb32(pb, 0xbb88695c);
01931     avio_wb32(pb, 0xfac9c740);
01932 
01933     avio_wb32(pb, 0x0);  /* ? */
01934     avio_wb32(pb, 0x3);  /* 3 sections ? */
01935 
01936     avio_wb32(pb, 0x14); /* size */
01937     ffio_wfourcc(pb, "FPRF");
01938     avio_wb32(pb, 0x0);  /* ? */
01939     avio_wb32(pb, 0x0);  /* ? */
01940     avio_wb32(pb, 0x0);  /* ? */
01941 
01942     avio_wb32(pb, 0x2c);  /* size */
01943     ffio_wfourcc(pb, "APRF");/* audio */
01944     avio_wb32(pb, 0x0);
01945     avio_wb32(pb, 0x2);   /* TrackID */
01946     ffio_wfourcc(pb, "mp4a");
01947     avio_wb32(pb, 0x20f);
01948     avio_wb32(pb, 0x0);
01949     avio_wb32(pb, audio_kbitrate);
01950     avio_wb32(pb, audio_kbitrate);
01951     avio_wb32(pb, AudioRate);
01952     avio_wb32(pb, AudioCodec->channels);
01953 
01954     avio_wb32(pb, 0x34);  /* size */
01955     ffio_wfourcc(pb, "VPRF");   /* video */
01956     avio_wb32(pb, 0x0);
01957     avio_wb32(pb, 0x1);    /* TrackID */
01958     if (VideoCodec->codec_id == CODEC_ID_H264) {
01959         ffio_wfourcc(pb, "avc1");
01960         avio_wb16(pb, 0x014D);
01961         avio_wb16(pb, 0x0015);
01962     } else {
01963         ffio_wfourcc(pb, "mp4v");
01964         avio_wb16(pb, 0x0000);
01965         avio_wb16(pb, 0x0103);
01966     }
01967     avio_wb32(pb, 0x0);
01968     avio_wb32(pb, video_kbitrate);
01969     avio_wb32(pb, video_kbitrate);
01970     avio_wb32(pb, FrameRate);
01971     avio_wb32(pb, FrameRate);
01972     avio_wb16(pb, VideoCodec->width);
01973     avio_wb16(pb, VideoCodec->height);
01974     avio_wb32(pb, 0x010001); /* ? */
01975 }
01976 
01977 static int mov_parse_mpeg2_frame(AVPacket *pkt, uint32_t *flags)
01978 {
01979     uint32_t c = -1;
01980     int i, closed_gop = 0;
01981 
01982     for (i = 0; i < pkt->size - 4; i++) {
01983         c = (c<<8) + pkt->data[i];
01984         if (c == 0x1b8) { // gop
01985             closed_gop = pkt->data[i+4]>>6 & 0x01;
01986         } else if (c == 0x100) { // pic
01987             int temp_ref = (pkt->data[i+1]<<2) | (pkt->data[i+2]>>6);
01988             if (!temp_ref || closed_gop) // I picture is not reordered
01989                 *flags = MOV_SYNC_SAMPLE;
01990             else
01991                 *flags = MOV_PARTIAL_SYNC_SAMPLE;
01992             break;
01993         }
01994     }
01995     return 0;
01996 }
01997 
01998 int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
01999 {
02000     MOVMuxContext *mov = s->priv_data;
02001     AVIOContext *pb = s->pb;
02002     MOVTrack *trk = &mov->tracks[pkt->stream_index];
02003     AVCodecContext *enc = trk->enc;
02004     unsigned int samplesInChunk = 0;
02005     int size= pkt->size;
02006 
02007     if (!s->pb->seekable) return 0; /* Can't handle that */
02008     if (!size) return 0; /* Discard 0 sized packets */
02009 
02010     if (enc->codec_id == CODEC_ID_AMR_NB) {
02011         /* We must find out how many AMR blocks there are in one packet */
02012         static uint16_t packed_size[16] =
02013             {13, 14, 16, 18, 20, 21, 27, 32, 6, 0, 0, 0, 0, 0, 0, 0};
02014         int len = 0;
02015 
02016         while (len < size && samplesInChunk < 100) {
02017             len += packed_size[(pkt->data[len] >> 3) & 0x0F];
02018             samplesInChunk++;
02019         }
02020         if(samplesInChunk > 1){
02021             av_log(s, AV_LOG_ERROR, "fatal error, input is not a single packet, implement a AVParser for it\n");
02022             return -1;
02023         }
02024     } else if (enc->codec_id == CODEC_ID_ADPCM_MS ||
02025                enc->codec_id == CODEC_ID_ADPCM_IMA_WAV) {
02026         samplesInChunk = enc->frame_size;
02027     } else if (trk->sampleSize)
02028         samplesInChunk = size/trk->sampleSize;
02029     else
02030         samplesInChunk = 1;
02031 
02032     /* copy extradata if it exists */
02033     if (trk->vosLen == 0 && enc->extradata_size > 0) {
02034         trk->vosLen = enc->extradata_size;
02035         trk->vosData = av_malloc(trk->vosLen);
02036         memcpy(trk->vosData, enc->extradata, trk->vosLen);
02037     }
02038 
02039     if (enc->codec_id == CODEC_ID_H264 && trk->vosLen > 0 && *(uint8_t *)trk->vosData != 1) {
02040         /* from x264 or from bytestream h264 */
02041         /* nal reformating needed */
02042         size = ff_avc_parse_nal_units(pb, pkt->data, pkt->size);
02043     } else if (enc->codec_id == CODEC_ID_AAC && pkt->size > 2 &&
02044                (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) {
02045         av_log(s, AV_LOG_ERROR, "malformated aac bitstream, use -absf aac_adtstoasc\n");
02046         return -1;
02047     } else {
02048         avio_write(pb, pkt->data, size);
02049     }
02050 
02051     if ((enc->codec_id == CODEC_ID_DNXHD ||
02052          enc->codec_id == CODEC_ID_AC3) && !trk->vosLen) {
02053         /* copy frame to create needed atoms */
02054         trk->vosLen = size;
02055         trk->vosData = av_malloc(size);
02056         if (!trk->vosData)
02057             return AVERROR(ENOMEM);
02058         memcpy(trk->vosData, pkt->data, size);
02059     }
02060 
02061     if (!(trk->entry % MOV_INDEX_CLUSTER_SIZE)) {
02062         trk->cluster = av_realloc_f(trk->cluster, sizeof(*trk->cluster), (trk->entry + MOV_INDEX_CLUSTER_SIZE));
02063         if (!trk->cluster)
02064             return -1;
02065     }
02066 
02067     trk->cluster[trk->entry].pos = avio_tell(pb) - size;
02068     trk->cluster[trk->entry].samplesInChunk = samplesInChunk;
02069     trk->cluster[trk->entry].size = size;
02070     trk->cluster[trk->entry].entries = samplesInChunk;
02071     trk->cluster[trk->entry].dts = pkt->dts;
02072     trk->trackDuration = pkt->dts - trk->cluster[0].dts + pkt->duration;
02073 
02074     if (pkt->pts == AV_NOPTS_VALUE) {
02075         av_log(s, AV_LOG_WARNING, "pts has no value\n");
02076         pkt->pts = pkt->dts;
02077     }
02078     if (pkt->dts != pkt->pts)
02079         trk->flags |= MOV_TRACK_CTTS;
02080     trk->cluster[trk->entry].cts = pkt->pts - pkt->dts;
02081     trk->cluster[trk->entry].flags = 0;
02082     if (pkt->flags & AV_PKT_FLAG_KEY) {
02083         if (mov->mode == MODE_MOV && enc->codec_id == CODEC_ID_MPEG2VIDEO &&
02084             trk->entry > 0) { // force sync sample for the first key frame
02085             mov_parse_mpeg2_frame(pkt, &trk->cluster[trk->entry].flags);
02086             if (trk->cluster[trk->entry].flags & MOV_PARTIAL_SYNC_SAMPLE)
02087                 trk->flags |= MOV_TRACK_STPS;
02088         } else {
02089             trk->cluster[trk->entry].flags = MOV_SYNC_SAMPLE;
02090         }
02091         if (trk->cluster[trk->entry].flags & MOV_SYNC_SAMPLE)
02092             trk->hasKeyframes++;
02093     }
02094     trk->entry++;
02095     trk->sampleCount += samplesInChunk;
02096     mov->mdat_size += size;
02097 
02098     avio_flush(pb);
02099 
02100     if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams)
02101         ff_mov_add_hinted_packet(s, pkt, trk->hint_track, trk->entry);
02102     return 0;
02103 }
02104 
02105 // QuickTime chapters involve an additional text track with the chapter names
02106 // as samples, and a tref pointing from the other tracks to the chapter one.
02107 static void mov_create_chapter_track(AVFormatContext *s, int tracknum)
02108 {
02109     MOVMuxContext *mov = s->priv_data;
02110     MOVTrack *track = &mov->tracks[tracknum];
02111     AVPacket pkt = { .stream_index = tracknum, .flags = AV_PKT_FLAG_KEY };
02112     int i, len;
02113 
02114     track->mode = mov->mode;
02115     track->tag = MKTAG('t','e','x','t');
02116     track->timescale = MOV_TIMESCALE;
02117     track->enc = avcodec_alloc_context();
02118     track->enc->codec_type = AVMEDIA_TYPE_SUBTITLE;
02119 
02120     for (i = 0; i < s->nb_chapters; i++) {
02121         AVChapter *c = s->chapters[i];
02122         AVDictionaryEntry *t;
02123 
02124         int64_t end = av_rescale_q(c->end, c->time_base, (AVRational){1,MOV_TIMESCALE});
02125         pkt.pts = pkt.dts = av_rescale_q(c->start, c->time_base, (AVRational){1,MOV_TIMESCALE});
02126         pkt.duration = end - pkt.dts;
02127 
02128         if ((t = av_dict_get(c->metadata, "title", NULL, 0))) {
02129             len = strlen(t->value);
02130             pkt.size = len+2;
02131             pkt.data = av_malloc(pkt.size);
02132             AV_WB16(pkt.data, len);
02133             memcpy(pkt.data+2, t->value, len);
02134             ff_mov_write_packet(s, &pkt);
02135             av_freep(&pkt.data);
02136         }
02137     }
02138 }
02139 
02140 static int mov_write_header(AVFormatContext *s)
02141 {
02142     AVIOContext *pb = s->pb;
02143     MOVMuxContext *mov = s->priv_data;
02144     int i, hint_track = 0;
02145 
02146     if (!s->pb->seekable) {
02147         av_log(s, AV_LOG_ERROR, "muxer does not support non seekable output\n");
02148         return -1;
02149     }
02150 
02151     /* Default mode == MP4 */
02152     mov->mode = MODE_MP4;
02153 
02154     if (s->oformat != NULL) {
02155         if (!strcmp("3gp", s->oformat->name)) mov->mode = MODE_3GP;
02156         else if (!strcmp("3g2", s->oformat->name)) mov->mode = MODE_3GP|MODE_3G2;
02157         else if (!strcmp("mov", s->oformat->name)) mov->mode = MODE_MOV;
02158         else if (!strcmp("psp", s->oformat->name)) mov->mode = MODE_PSP;
02159         else if (!strcmp("ipod",s->oformat->name)) mov->mode = MODE_IPOD;
02160 
02161         mov_write_ftyp_tag(pb,s);
02162         if (mov->mode == MODE_PSP) {
02163             if (s->nb_streams != 2) {
02164                 av_log(s, AV_LOG_ERROR, "PSP mode need one video and one audio stream\n");
02165                 return -1;
02166             }
02167             mov_write_uuidprof_tag(pb,s);
02168         }
02169     }
02170 
02171     mov->nb_streams = s->nb_streams;
02172     if (mov->mode & (MODE_MOV|MODE_IPOD) && s->nb_chapters)
02173         mov->chapter_track = mov->nb_streams++;
02174 
02175 #if FF_API_FLAG_RTP_HINT
02176     if (s->flags & AVFMT_FLAG_RTP_HINT) {
02177         av_log(s, AV_LOG_WARNING, "The RTP_HINT flag is deprecated, enable it "
02178                                   "via the -movflags rtphint muxer option "
02179                                   "instead.\n");
02180         mov->flags |= FF_MOV_FLAG_RTP_HINT;
02181     }
02182 #endif
02183     if (mov->flags & FF_MOV_FLAG_RTP_HINT) {
02184         /* Add hint tracks for each audio and video stream */
02185         hint_track = mov->nb_streams;
02186         for (i = 0; i < s->nb_streams; i++) {
02187             AVStream *st = s->streams[i];
02188             if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO ||
02189                 st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
02190                 mov->nb_streams++;
02191             }
02192         }
02193     }
02194 
02195     mov->tracks = av_mallocz(mov->nb_streams*sizeof(*mov->tracks));
02196     if (!mov->tracks)
02197         return AVERROR(ENOMEM);
02198 
02199     for(i=0; i<s->nb_streams; i++){
02200         AVStream *st= s->streams[i];
02201         MOVTrack *track= &mov->tracks[i];
02202         AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL,0);
02203 
02204         track->enc = st->codec;
02205         track->language = ff_mov_iso639_to_lang(lang?lang->value:"und", mov->mode!=MODE_MOV);
02206         if (track->language < 0)
02207             track->language = 0;
02208         track->mode = mov->mode;
02209         track->tag = mov_find_codec_tag(s, track);
02210         if (!track->tag) {
02211             av_log(s, AV_LOG_ERROR, "track %d: could not find tag, "
02212                    "codec not currently supported in container\n", i);
02213             goto error;
02214         }
02215         /* If hinting of this track is enabled by a later hint track,
02216          * this is updated. */
02217         track->hint_track = -1;
02218         if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO){
02219             if (track->tag == MKTAG('m','x','3','p') || track->tag == MKTAG('m','x','3','n') ||
02220                 track->tag == MKTAG('m','x','4','p') || track->tag == MKTAG('m','x','4','n') ||
02221                 track->tag == MKTAG('m','x','5','p') || track->tag == MKTAG('m','x','5','n')) {
02222                 if (st->codec->width != 720 || (st->codec->height != 608 && st->codec->height != 512)) {
02223                     av_log(s, AV_LOG_ERROR, "D-10/IMX must use 720x608 or 720x512 video resolution\n");
02224                     goto error;
02225                 }
02226                 track->height = track->tag>>24 == 'n' ? 486 : 576;
02227             }
02228             track->timescale = st->codec->time_base.den;
02229             if (track->mode == MODE_MOV && track->timescale > 100000)
02230                 av_log(s, AV_LOG_WARNING,
02231                        "WARNING codec timebase is very high. If duration is too long,\n"
02232                        "file may not be playable by quicktime. Specify a shorter timebase\n"
02233                        "or choose different container.\n");
02234         }else if(st->codec->codec_type == AVMEDIA_TYPE_AUDIO){
02235             track->timescale = st->codec->sample_rate;
02236             if(!st->codec->frame_size && !av_get_bits_per_sample(st->codec->codec_id)) {
02237                 av_log(s, AV_LOG_ERROR, "track %d: codec frame size is not set\n", i);
02238                 goto error;
02239             }else if(st->codec->codec_id == CODEC_ID_ADPCM_MS ||
02240                      st->codec->codec_id == CODEC_ID_ADPCM_IMA_WAV){
02241                 if (!st->codec->block_align) {
02242                     av_log(s, AV_LOG_ERROR, "track %d: codec block align is not set for adpcm\n", i);
02243                     goto error;
02244                 }
02245                 track->sampleSize = st->codec->block_align;
02246             }else if(st->codec->frame_size > 1){ /* assume compressed audio */
02247                 track->audio_vbr = 1;
02248             }else{
02249                 st->codec->frame_size = 1;
02250                 track->sampleSize = (av_get_bits_per_sample(st->codec->codec_id) >> 3) * st->codec->channels;
02251             }
02252             if (track->mode != MODE_MOV) {
02253                 if (track->timescale > UINT16_MAX) {
02254                     av_log(s, AV_LOG_ERROR, "track %d: output format does not support "
02255                            "sample rate %dhz\n", i, track->timescale);
02256                     goto error;
02257                 }
02258                 if (track->enc->codec_id == CODEC_ID_MP3 && track->timescale < 16000) {
02259                     av_log(s, AV_LOG_ERROR, "track %d: muxing mp3 at %dhz is not supported\n",
02260                            i, track->enc->sample_rate);
02261                     goto error;
02262                 }
02263             }
02264         }else if(st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE){
02265             track->timescale = st->codec->time_base.den;
02266         }
02267         if (!track->height)
02268             track->height = st->codec->height;
02269 
02270         av_set_pts_info(st, 64, 1, track->timescale);
02271     }
02272 
02273     mov_write_mdat_tag(pb, mov);
02274     mov->time = s->timestamp + 0x7C25B080; //1970 based -> 1904 based
02275 
02276     if (mov->chapter_track)
02277         mov_create_chapter_track(s, mov->chapter_track);
02278 
02279     if (mov->flags & FF_MOV_FLAG_RTP_HINT) {
02280         /* Initialize the hint tracks for each audio and video stream */
02281         for (i = 0; i < s->nb_streams; i++) {
02282             AVStream *st = s->streams[i];
02283             if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO ||
02284                 st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
02285                 ff_mov_init_hinting(s, hint_track, i);
02286                 hint_track++;
02287             }
02288         }
02289     }
02290 
02291     avio_flush(pb);
02292 
02293     return 0;
02294  error:
02295     av_freep(&mov->tracks);
02296     return -1;
02297 }
02298 
02299 static int mov_write_trailer(AVFormatContext *s)
02300 {
02301     MOVMuxContext *mov = s->priv_data;
02302     AVIOContext *pb = s->pb;
02303     int res = 0;
02304     int i;
02305 
02306     int64_t moov_pos = avio_tell(pb);
02307 
02308     /* Write size of mdat tag */
02309     if (mov->mdat_size+8 <= UINT32_MAX) {
02310         avio_seek(pb, mov->mdat_pos, SEEK_SET);
02311         avio_wb32(pb, mov->mdat_size+8);
02312     } else {
02313         /* overwrite 'wide' placeholder atom */
02314         avio_seek(pb, mov->mdat_pos - 8, SEEK_SET);
02315         avio_wb32(pb, 1); /* special value: real atom size will be 64 bit value after tag field */
02316         ffio_wfourcc(pb, "mdat");
02317         avio_wb64(pb, mov->mdat_size+16);
02318     }
02319     avio_seek(pb, moov_pos, SEEK_SET);
02320 
02321     mov_write_moov_tag(pb, mov, s);
02322 
02323     if (mov->chapter_track)
02324         av_freep(&mov->tracks[mov->chapter_track].enc);
02325 
02326     for (i=0; i<mov->nb_streams; i++) {
02327         if (mov->tracks[i].tag == MKTAG('r','t','p',' '))
02328             ff_mov_close_hinting(&mov->tracks[i]);
02329         av_freep(&mov->tracks[i].cluster);
02330 
02331         if(mov->tracks[i].vosLen) av_free(mov->tracks[i].vosData);
02332 
02333     }
02334 
02335     avio_flush(pb);
02336 
02337     av_freep(&mov->tracks);
02338 
02339     return res;
02340 }
02341 
02342 #if CONFIG_MOV_MUXER
02343 AVOutputFormat ff_mov_muxer = {
02344     "mov",
02345     NULL_IF_CONFIG_SMALL("MOV format"),
02346     NULL,
02347     "mov",
02348     sizeof(MOVMuxContext),
02349     CODEC_ID_AAC,
02350     CODEC_ID_MPEG4,
02351     mov_write_header,
02352     ff_mov_write_packet,
02353     mov_write_trailer,
02354     .flags = AVFMT_GLOBALHEADER,
02355     .codec_tag = (const AVCodecTag* const []){codec_movvideo_tags, codec_movaudio_tags, 0},
02356     .priv_class = &mov_muxer_class,
02357 };
02358 #endif
02359 #if CONFIG_TGP_MUXER
02360 AVOutputFormat ff_tgp_muxer = {
02361     "3gp",
02362     NULL_IF_CONFIG_SMALL("3GP format"),
02363     NULL,
02364     "3gp",
02365     sizeof(MOVMuxContext),
02366     CODEC_ID_AMR_NB,
02367     CODEC_ID_H263,
02368     mov_write_header,
02369     ff_mov_write_packet,
02370     mov_write_trailer,
02371     .flags = AVFMT_GLOBALHEADER,
02372     .codec_tag = (const AVCodecTag* const []){codec_3gp_tags, 0},
02373     .priv_class = &mov_muxer_class,
02374 };
02375 #endif
02376 #if CONFIG_MP4_MUXER
02377 AVOutputFormat ff_mp4_muxer = {
02378     "mp4",
02379     NULL_IF_CONFIG_SMALL("MP4 format"),
02380     "application/mp4",
02381     "mp4",
02382     sizeof(MOVMuxContext),
02383     CODEC_ID_AAC,
02384     CODEC_ID_MPEG4,
02385     mov_write_header,
02386     ff_mov_write_packet,
02387     mov_write_trailer,
02388     .flags = AVFMT_GLOBALHEADER,
02389     .codec_tag = (const AVCodecTag* const []){ff_mp4_obj_type, 0},
02390     .priv_class = &mov_muxer_class,
02391 };
02392 #endif
02393 #if CONFIG_PSP_MUXER
02394 AVOutputFormat ff_psp_muxer = {
02395     "psp",
02396     NULL_IF_CONFIG_SMALL("PSP MP4 format"),
02397     NULL,
02398     "mp4,psp",
02399     sizeof(MOVMuxContext),
02400     CODEC_ID_AAC,
02401     CODEC_ID_MPEG4,
02402     mov_write_header,
02403     ff_mov_write_packet,
02404     mov_write_trailer,
02405     .flags = AVFMT_GLOBALHEADER,
02406     .codec_tag = (const AVCodecTag* const []){ff_mp4_obj_type, 0},
02407     .priv_class = &mov_muxer_class,
02408 };
02409 #endif
02410 #if CONFIG_TG2_MUXER
02411 AVOutputFormat ff_tg2_muxer = {
02412     "3g2",
02413     NULL_IF_CONFIG_SMALL("3GP2 format"),
02414     NULL,
02415     "3g2",
02416     sizeof(MOVMuxContext),
02417     CODEC_ID_AMR_NB,
02418     CODEC_ID_H263,
02419     mov_write_header,
02420     ff_mov_write_packet,
02421     mov_write_trailer,
02422     .flags = AVFMT_GLOBALHEADER,
02423     .codec_tag = (const AVCodecTag* const []){codec_3gp_tags, 0},
02424     .priv_class = &mov_muxer_class,
02425 };
02426 #endif
02427 #if CONFIG_IPOD_MUXER
02428 AVOutputFormat ff_ipod_muxer = {
02429     "ipod",
02430     NULL_IF_CONFIG_SMALL("iPod H.264 MP4 format"),
02431     "application/mp4",
02432     "m4v,m4a",
02433     sizeof(MOVMuxContext),
02434     CODEC_ID_AAC,
02435     CODEC_ID_H264,
02436     mov_write_header,
02437     ff_mov_write_packet,
02438     mov_write_trailer,
02439     .flags = AVFMT_GLOBALHEADER,
02440     .codec_tag = (const AVCodecTag* const []){codec_ipod_tags, 0},
02441     .priv_class = &mov_muxer_class,
02442 };
02443 #endif

Generated on Fri Feb 22 2013 07:24:31 for FFmpeg by  doxygen 1.7.1