]> git.sesse.net Git - ffmpeg/blob - libavformat/movenc.c
Merge remote-tracking branch 'qatar/master'
[ffmpeg] / libavformat / movenc.c
1 /*
2  * MOV, 3GP, MP4 muxer
3  * Copyright (c) 2003 Thomas Raivio
4  * Copyright (c) 2004 Gildas Bazin <gbazin at videolan dot org>
5  * Copyright (c) 2009 Baptiste Coudurier <baptiste dot coudurier at gmail dot com>
6  *
7  * This file is part of FFmpeg.
8  *
9  * FFmpeg is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * FFmpeg is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with FFmpeg; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  */
23
24 #include "movenc.h"
25 #include "avformat.h"
26 #include "avio_internal.h"
27 #include "riff.h"
28 #include "avio.h"
29 #include "isom.h"
30 #include "avc.h"
31 #include "libavcodec/get_bits.h"
32 #include "libavcodec/put_bits.h"
33 #include "internal.h"
34 #include "libavutil/avstring.h"
35 #include "libavutil/intfloat.h"
36 #include "libavutil/mathematics.h"
37 #include "libavutil/opt.h"
38 #include "libavutil/dict.h"
39 #include "rtpenc.h"
40 #include "mov_chan.h"
41
42 #undef NDEBUG
43 #include <assert.h>
44
45 static const AVOption options[] = {
46     { "movflags", "MOV muxer flags", offsetof(MOVMuxContext, flags), AV_OPT_TYPE_FLAGS, {.dbl = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
47     { "rtphint", "Add RTP hint tracks", 0, AV_OPT_TYPE_CONST, {.dbl = FF_MOV_FLAG_RTP_HINT}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
48     { "moov_size", "maximum moov size so it can be placed at the begin", offsetof(MOVMuxContext, reserved_moov_size), AV_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, 0 },
49     { "empty_moov", "Make the initial moov atom empty (not supported by QuickTime)", 0, AV_OPT_TYPE_CONST, {.dbl = FF_MOV_FLAG_EMPTY_MOOV}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
50     { "frag_keyframe", "Fragment at video keyframes", 0, AV_OPT_TYPE_CONST, {.dbl = FF_MOV_FLAG_FRAG_KEYFRAME}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
51     { "separate_moof", "Write separate moof/mdat atoms for each track", 0, AV_OPT_TYPE_CONST, {.dbl = FF_MOV_FLAG_SEPARATE_MOOF}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
52     { "frag_custom", "Flush fragments on caller requests", 0, AV_OPT_TYPE_CONST, {.dbl = FF_MOV_FLAG_FRAG_CUSTOM}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
53     { "isml", "Create a live smooth streaming feed (for pushing to a publishing point)", 0, AV_OPT_TYPE_CONST, {.dbl = FF_MOV_FLAG_ISML}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
54     FF_RTP_FLAG_OPTS(MOVMuxContext, rtp_flags),
55     { "skip_iods", "Skip writing iods atom.", offsetof(MOVMuxContext, iods_skip), AV_OPT_TYPE_INT, {.dbl = 1}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
56     { "iods_audio_profile", "iods audio profile atom.", offsetof(MOVMuxContext, iods_audio_profile), AV_OPT_TYPE_INT, {.dbl = -1}, -1, 255, AV_OPT_FLAG_ENCODING_PARAM},
57     { "iods_video_profile", "iods video profile atom.", offsetof(MOVMuxContext, iods_video_profile), AV_OPT_TYPE_INT, {.dbl = -1}, -1, 255, AV_OPT_FLAG_ENCODING_PARAM},
58     { "frag_duration", "Maximum fragment duration", offsetof(MOVMuxContext, max_fragment_duration), AV_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
59     { "frag_size", "Maximum fragment size", offsetof(MOVMuxContext, max_fragment_size), AV_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
60     { "ism_lookahead", "Number of lookahead entries for ISM files", offsetof(MOVMuxContext, ism_lookahead), AV_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
61     { NULL },
62 };
63
64 #define MOV_CLASS(flavor)\
65 static const AVClass flavor ## _muxer_class = {\
66     .class_name = #flavor " muxer",\
67     .item_name  = av_default_item_name,\
68     .option     = options,\
69     .version    = LIBAVUTIL_VERSION_INT,\
70 };
71
72 //FIXME support 64 bit variant with wide placeholders
73 static int64_t updateSize(AVIOContext *pb, int64_t pos)
74 {
75     int64_t curpos = avio_tell(pb);
76     avio_seek(pb, pos, SEEK_SET);
77     avio_wb32(pb, curpos - pos); /* rewrite size */
78     avio_seek(pb, curpos, SEEK_SET);
79
80     return curpos - pos;
81 }
82
83 /* Chunk offset atom */
84 static int mov_write_stco_tag(AVIOContext *pb, MOVTrack *track)
85 {
86     int i;
87     int mode64 = 0; //   use 32 bit size variant if possible
88     int64_t pos = avio_tell(pb);
89     avio_wb32(pb, 0); /* size */
90     if (pos > UINT32_MAX) {
91         mode64 = 1;
92         ffio_wfourcc(pb, "co64");
93     } else
94         ffio_wfourcc(pb, "stco");
95     avio_wb32(pb, 0); /* version & flags */
96     avio_wb32(pb, track->chunkCount); /* entry count */
97     for (i=0; i<track->entry; i++) {
98         if(!track->cluster[i].chunkNum)
99             continue;
100         if(mode64 == 1)
101             avio_wb64(pb, track->cluster[i].pos);
102         else
103             avio_wb32(pb, track->cluster[i].pos);
104     }
105     return updateSize(pb, pos);
106 }
107
108 /* Sample size atom */
109 static int mov_write_stsz_tag(AVIOContext *pb, MOVTrack *track)
110 {
111     int equalChunks = 1;
112     int i, j, entries = 0, tst = -1, oldtst = -1;
113
114     int64_t pos = avio_tell(pb);
115     avio_wb32(pb, 0); /* size */
116     ffio_wfourcc(pb, "stsz");
117     avio_wb32(pb, 0); /* version & flags */
118
119     for (i=0; i<track->entry; i++) {
120         tst = track->cluster[i].size/track->cluster[i].entries;
121         if(oldtst != -1 && tst != oldtst) {
122             equalChunks = 0;
123         }
124         oldtst = tst;
125         entries += track->cluster[i].entries;
126     }
127     if (equalChunks && track->entry) {
128         int sSize = track->entry ? track->cluster[0].size/track->cluster[0].entries : 0;
129         sSize = FFMAX(1, sSize); // adpcm mono case could make sSize == 0
130         avio_wb32(pb, sSize); // sample size
131         avio_wb32(pb, entries); // sample count
132     }
133     else {
134         avio_wb32(pb, 0); // sample size
135         avio_wb32(pb, entries); // sample count
136         for (i=0; i<track->entry; i++) {
137             for (j=0; j<track->cluster[i].entries; j++) {
138                 avio_wb32(pb, track->cluster[i].size /
139                          track->cluster[i].entries);
140             }
141         }
142     }
143     return updateSize(pb, pos);
144 }
145
146 /* Sample to chunk atom */
147 static int mov_write_stsc_tag(AVIOContext *pb, MOVTrack *track)
148 {
149     int index = 0, oldval = -1, i;
150     int64_t entryPos, curpos;
151
152     int64_t pos = avio_tell(pb);
153     avio_wb32(pb, 0); /* size */
154     ffio_wfourcc(pb, "stsc");
155     avio_wb32(pb, 0); // version & flags
156     entryPos = avio_tell(pb);
157     avio_wb32(pb, track->chunkCount); // entry count
158     for (i=0; i<track->entry; i++) {
159         if(oldval != track->cluster[i].samplesInChunk && track->cluster[i].chunkNum)
160         {
161             avio_wb32(pb, track->cluster[i].chunkNum); // first chunk
162             avio_wb32(pb, track->cluster[i].samplesInChunk); // samples per chunk
163             avio_wb32(pb, 0x1); // sample description index
164             oldval = track->cluster[i].samplesInChunk;
165             index++;
166         }
167     }
168     curpos = avio_tell(pb);
169     avio_seek(pb, entryPos, SEEK_SET);
170     avio_wb32(pb, index); // rewrite size
171     avio_seek(pb, curpos, SEEK_SET);
172
173     return updateSize(pb, pos);
174 }
175
176 /* Sync sample atom */
177 static int mov_write_stss_tag(AVIOContext *pb, MOVTrack *track, uint32_t flag)
178 {
179     int64_t curpos, entryPos;
180     int i, index = 0;
181     int64_t pos = avio_tell(pb);
182     avio_wb32(pb, 0); // size
183     ffio_wfourcc(pb, flag == MOV_SYNC_SAMPLE ? "stss" : "stps");
184     avio_wb32(pb, 0); // version & flags
185     entryPos = avio_tell(pb);
186     avio_wb32(pb, track->entry); // entry count
187     for (i=0; i<track->entry; i++) {
188         if (track->cluster[i].flags & flag) {
189             avio_wb32(pb, i+1);
190             index++;
191         }
192     }
193     curpos = avio_tell(pb);
194     avio_seek(pb, entryPos, SEEK_SET);
195     avio_wb32(pb, index); // rewrite size
196     avio_seek(pb, curpos, SEEK_SET);
197     return updateSize(pb, pos);
198 }
199
200 static int mov_write_amr_tag(AVIOContext *pb, MOVTrack *track)
201 {
202     avio_wb32(pb, 0x11); /* size */
203     if (track->mode == MODE_MOV) ffio_wfourcc(pb, "samr");
204     else                         ffio_wfourcc(pb, "damr");
205     ffio_wfourcc(pb, "FFMP");
206     avio_w8(pb, 0); /* decoder version */
207
208     avio_wb16(pb, 0x81FF); /* Mode set (all modes for AMR_NB) */
209     avio_w8(pb, 0x00); /* Mode change period (no restriction) */
210     avio_w8(pb, 0x01); /* Frames per sample */
211     return 0x11;
212 }
213
214 static int mov_write_ac3_tag(AVIOContext *pb, MOVTrack *track)
215 {
216     GetBitContext gbc;
217     PutBitContext pbc;
218     uint8_t buf[3];
219     int fscod, bsid, bsmod, acmod, lfeon, frmsizecod;
220
221     if (track->vosLen < 7)
222         return -1;
223
224     avio_wb32(pb, 11);
225     ffio_wfourcc(pb, "dac3");
226
227     init_get_bits(&gbc, track->vosData+4, (track->vosLen-4) * 8);
228     fscod      = get_bits(&gbc, 2);
229     frmsizecod = get_bits(&gbc, 6);
230     bsid       = get_bits(&gbc, 5);
231     bsmod      = get_bits(&gbc, 3);
232     acmod      = get_bits(&gbc, 3);
233     if (acmod == 2) {
234         skip_bits(&gbc, 2); // dsurmod
235     } else {
236         if ((acmod & 1) && acmod != 1)
237             skip_bits(&gbc, 2); // cmixlev
238         if (acmod & 4)
239             skip_bits(&gbc, 2); // surmixlev
240     }
241     lfeon = get_bits1(&gbc);
242
243     init_put_bits(&pbc, buf, sizeof(buf));
244     put_bits(&pbc, 2, fscod);
245     put_bits(&pbc, 5, bsid);
246     put_bits(&pbc, 3, bsmod);
247     put_bits(&pbc, 3, acmod);
248     put_bits(&pbc, 1, lfeon);
249     put_bits(&pbc, 5, frmsizecod>>1); // bit_rate_code
250     put_bits(&pbc, 5, 0); // reserved
251
252     flush_put_bits(&pbc);
253     avio_write(pb, buf, sizeof(buf));
254
255     return 11;
256 }
257
258 /**
259  * This function writes extradata "as is".
260  * Extradata must be formatted like a valid atom (with size and tag).
261  */
262 static int mov_write_extradata_tag(AVIOContext *pb, MOVTrack *track)
263 {
264     avio_write(pb, track->enc->extradata, track->enc->extradata_size);
265     return track->enc->extradata_size;
266 }
267
268 static int mov_write_enda_tag(AVIOContext *pb)
269 {
270     avio_wb32(pb, 10);
271     ffio_wfourcc(pb, "enda");
272     avio_wb16(pb, 1); /* little endian */
273     return 10;
274 }
275
276 static void putDescr(AVIOContext *pb, int tag, unsigned int size)
277 {
278     int i = 3;
279     avio_w8(pb, tag);
280     for(; i>0; i--)
281         avio_w8(pb, (size>>(7*i)) | 0x80);
282     avio_w8(pb, size & 0x7F);
283 }
284
285 static unsigned compute_avg_bitrate(MOVTrack *track)
286 {
287     uint64_t size = 0;
288     int i;
289     for (i = 0; i < track->entry; i++)
290         size += track->cluster[i].size;
291     return size * 8 * track->timescale / track->trackDuration;
292 }
293
294 static int mov_write_esds_tag(AVIOContext *pb, MOVTrack *track) // Basic
295 {
296     int64_t pos = avio_tell(pb);
297     int decoderSpecificInfoLen = track->vosLen ? 5+track->vosLen : 0;
298     unsigned avg_bitrate;
299
300     avio_wb32(pb, 0); // size
301     ffio_wfourcc(pb, "esds");
302     avio_wb32(pb, 0); // Version
303
304     // ES descriptor
305     putDescr(pb, 0x03, 3 + 5+13 + decoderSpecificInfoLen + 5+1);
306     avio_wb16(pb, track->trackID);
307     avio_w8(pb, 0x00); // flags (= no flags)
308
309     // DecoderConfig descriptor
310     putDescr(pb, 0x04, 13 + decoderSpecificInfoLen);
311
312     // Object type indication
313     if ((track->enc->codec_id == CODEC_ID_MP2 ||
314          track->enc->codec_id == CODEC_ID_MP3) &&
315         track->enc->sample_rate > 24000)
316         avio_w8(pb, 0x6B); // 11172-3
317     else
318         avio_w8(pb, ff_codec_get_tag(ff_mp4_obj_type, track->enc->codec_id));
319
320     // the following fields is made of 6 bits to identify the streamtype (4 for video, 5 for audio)
321     // plus 1 bit to indicate upstream and 1 bit set to 1 (reserved)
322     if(track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
323         avio_w8(pb, 0x15); // flags (= Audiostream)
324     else
325         avio_w8(pb, 0x11); // flags (= Visualstream)
326
327     avio_w8(pb,  track->enc->rc_buffer_size>>(3+16));      // Buffersize DB (24 bits)
328     avio_wb16(pb, (track->enc->rc_buffer_size>>3)&0xFFFF); // Buffersize DB
329
330     avg_bitrate = compute_avg_bitrate(track);
331     // maxbitrate (FIXME should be max rate in any 1 sec window)
332     avio_wb32(pb, FFMAX3(track->enc->bit_rate, track->enc->rc_max_rate, avg_bitrate));
333     avio_wb32(pb, avg_bitrate);
334
335     if (track->vosLen) {
336         // DecoderSpecific info descriptor
337         putDescr(pb, 0x05, track->vosLen);
338         avio_write(pb, track->vosData, track->vosLen);
339     }
340
341     // SL descriptor
342     putDescr(pb, 0x06, 1);
343     avio_w8(pb, 0x02);
344     return updateSize(pb, pos);
345 }
346
347 static int mov_pcm_le_gt16(enum CodecID codec_id)
348 {
349     return codec_id == CODEC_ID_PCM_S24LE ||
350            codec_id == CODEC_ID_PCM_S32LE ||
351            codec_id == CODEC_ID_PCM_F32LE ||
352            codec_id == CODEC_ID_PCM_F64LE;
353 }
354
355 static int mov_write_ms_tag(AVIOContext *pb, MOVTrack *track)
356 {
357     int64_t pos = avio_tell(pb);
358     avio_wb32(pb, 0);
359     avio_wl32(pb, track->tag); // store it byteswapped
360     track->enc->codec_tag = av_bswap16(track->tag >> 16);
361     ff_put_wav_header(pb, track->enc);
362     return updateSize(pb, pos);
363 }
364
365 static int mov_write_chan_tag(AVIOContext *pb, MOVTrack *track)
366 {
367     uint32_t layout_tag, bitmap;
368     int64_t pos = avio_tell(pb);
369
370     layout_tag = ff_mov_get_channel_layout_tag(track->enc->codec_id,
371                                                track->enc->channel_layout,
372                                                &bitmap);
373     if (!layout_tag) {
374         av_log(track->enc, AV_LOG_WARNING, "not writing 'chan' tag due to "
375                "lack of channel information\n");
376         return 0;
377     }
378
379     avio_wb32(pb, 0);           // Size
380     ffio_wfourcc(pb, "chan");   // Type
381     avio_w8(pb, 0);             // Version
382     avio_wb24(pb, 0);           // Flags
383     avio_wb32(pb, layout_tag);  // mChannelLayoutTag
384     avio_wb32(pb, bitmap);      // mChannelBitmap
385     avio_wb32(pb, 0);           // mNumberChannelDescriptions
386
387     return updateSize(pb, pos);
388 }
389
390 static int mov_write_wave_tag(AVIOContext *pb, MOVTrack *track)
391 {
392     int64_t pos = avio_tell(pb);
393
394     avio_wb32(pb, 0);     /* size */
395     ffio_wfourcc(pb, "wave");
396
397     avio_wb32(pb, 12);    /* size */
398     ffio_wfourcc(pb, "frma");
399     avio_wl32(pb, track->tag);
400
401     if (track->enc->codec_id == CODEC_ID_AAC) {
402         /* useless atom needed by mplayer, ipod, not needed by quicktime */
403         avio_wb32(pb, 12); /* size */
404         ffio_wfourcc(pb, "mp4a");
405         avio_wb32(pb, 0);
406         mov_write_esds_tag(pb, track);
407     } else if (mov_pcm_le_gt16(track->enc->codec_id)) {
408         mov_write_enda_tag(pb);
409     } else if (track->enc->codec_id == CODEC_ID_AMR_NB) {
410         mov_write_amr_tag(pb, track);
411     } else if (track->enc->codec_id == CODEC_ID_AC3) {
412         mov_write_chan_tag(pb, track);
413         mov_write_ac3_tag(pb, track);
414     } else if (track->enc->codec_id == CODEC_ID_ALAC) {
415         mov_write_extradata_tag(pb, track);
416     } else if (track->enc->codec_id == CODEC_ID_ADPCM_MS ||
417                track->enc->codec_id == CODEC_ID_ADPCM_IMA_WAV) {
418         mov_write_ms_tag(pb, track);
419     }
420
421     avio_wb32(pb, 8);     /* size */
422     avio_wb32(pb, 0);     /* null tag */
423
424     return updateSize(pb, pos);
425 }
426
427 static int mov_write_glbl_tag(AVIOContext *pb, MOVTrack *track)
428 {
429     avio_wb32(pb, track->vosLen+8);
430     ffio_wfourcc(pb, "glbl");
431     avio_write(pb, track->vosData, track->vosLen);
432     return 8+track->vosLen;
433 }
434
435 /**
436  * Compute flags for 'lpcm' tag.
437  * See CoreAudioTypes and AudioStreamBasicDescription at Apple.
438  */
439 static int mov_get_lpcm_flags(enum CodecID codec_id)
440 {
441     switch (codec_id) {
442     case CODEC_ID_PCM_F32BE:
443     case CODEC_ID_PCM_F64BE:
444         return 11;
445     case CODEC_ID_PCM_F32LE:
446     case CODEC_ID_PCM_F64LE:
447         return 9;
448     case CODEC_ID_PCM_U8:
449         return 10;
450     case CODEC_ID_PCM_S16BE:
451     case CODEC_ID_PCM_S24BE:
452     case CODEC_ID_PCM_S32BE:
453         return 14;
454     case CODEC_ID_PCM_S8:
455     case CODEC_ID_PCM_S16LE:
456     case CODEC_ID_PCM_S24LE:
457     case CODEC_ID_PCM_S32LE:
458         return 12;
459     default:
460         return 0;
461     }
462 }
463
464 static int mov_write_audio_tag(AVIOContext *pb, MOVTrack *track)
465 {
466     int64_t pos = avio_tell(pb);
467     int version = 0;
468     uint32_t tag = track->tag;
469
470     if (track->mode == MODE_MOV) {
471         if (track->timescale > UINT16_MAX) {
472             if (mov_get_lpcm_flags(track->enc->codec_id))
473                 tag = AV_RL32("lpcm");
474             version = 2;
475         } else if (track->audio_vbr || mov_pcm_le_gt16(track->enc->codec_id) ||
476                    track->enc->codec_id == CODEC_ID_ADPCM_MS ||
477                    track->enc->codec_id == CODEC_ID_ADPCM_IMA_WAV) {
478             version = 1;
479         }
480     }
481
482     avio_wb32(pb, 0); /* size */
483     avio_wl32(pb, tag); // store it byteswapped
484     avio_wb32(pb, 0); /* Reserved */
485     avio_wb16(pb, 0); /* Reserved */
486     avio_wb16(pb, 1); /* Data-reference index, XXX  == 1 */
487
488     /* SoundDescription */
489     avio_wb16(pb, version); /* Version */
490     avio_wb16(pb, 0); /* Revision level */
491     avio_wb32(pb, 0); /* Reserved */
492
493     if (version == 2) {
494         avio_wb16(pb, 3);
495         avio_wb16(pb, 16);
496         avio_wb16(pb, 0xfffe);
497         avio_wb16(pb, 0);
498         avio_wb32(pb, 0x00010000);
499         avio_wb32(pb, 72);
500         avio_wb64(pb, av_double2int(track->enc->sample_rate));
501         avio_wb32(pb, track->enc->channels);
502         avio_wb32(pb, 0x7F000000);
503         avio_wb32(pb, av_get_bits_per_sample(track->enc->codec_id));
504         avio_wb32(pb, mov_get_lpcm_flags(track->enc->codec_id));
505         avio_wb32(pb, track->sampleSize);
506         avio_wb32(pb, track->enc->frame_size);
507     } else {
508         if (track->mode == MODE_MOV) {
509             avio_wb16(pb, track->enc->channels);
510             if (track->enc->codec_id == CODEC_ID_PCM_U8 ||
511                 track->enc->codec_id == CODEC_ID_PCM_S8)
512                 avio_wb16(pb, 8); /* bits per sample */
513             else
514                 avio_wb16(pb, 16);
515             avio_wb16(pb, track->audio_vbr ? -2 : 0); /* compression ID */
516         } else { /* reserved for mp4/3gp */
517             avio_wb16(pb, 2);
518             avio_wb16(pb, 16);
519             avio_wb16(pb, 0);
520         }
521
522         avio_wb16(pb, 0); /* packet size (= 0) */
523         avio_wb16(pb, track->enc->sample_rate);
524         avio_wb16(pb, 0); /* Reserved */
525     }
526
527     if(version == 1) { /* SoundDescription V1 extended info */
528         avio_wb32(pb, track->enc->frame_size); /* Samples per packet */
529         avio_wb32(pb, track->sampleSize / track->enc->channels); /* Bytes per packet */
530         avio_wb32(pb, track->sampleSize); /* Bytes per frame */
531         avio_wb32(pb, 2); /* Bytes per sample */
532     }
533
534     if(track->mode == MODE_MOV &&
535        (track->enc->codec_id == CODEC_ID_AAC ||
536         track->enc->codec_id == CODEC_ID_AC3 ||
537         track->enc->codec_id == CODEC_ID_AMR_NB ||
538         track->enc->codec_id == CODEC_ID_ALAC ||
539         track->enc->codec_id == CODEC_ID_ADPCM_MS ||
540         track->enc->codec_id == CODEC_ID_ADPCM_IMA_WAV ||
541         mov_pcm_le_gt16(track->enc->codec_id)))
542         mov_write_wave_tag(pb, track);
543     else if(track->tag == MKTAG('m','p','4','a'))
544         mov_write_esds_tag(pb, track);
545     else if(track->enc->codec_id == CODEC_ID_AMR_NB)
546         mov_write_amr_tag(pb, track);
547     else if(track->enc->codec_id == CODEC_ID_AC3)
548         mov_write_ac3_tag(pb, track);
549     else if(track->enc->codec_id == CODEC_ID_ALAC)
550         mov_write_extradata_tag(pb, track);
551     else if(track->vosLen > 0)
552         mov_write_glbl_tag(pb, track);
553
554     return updateSize(pb, pos);
555 }
556
557 static int mov_write_d263_tag(AVIOContext *pb)
558 {
559     avio_wb32(pb, 0xf); /* size */
560     ffio_wfourcc(pb, "d263");
561     ffio_wfourcc(pb, "FFMP");
562     avio_w8(pb, 0); /* decoder version */
563     /* FIXME use AVCodecContext level/profile, when encoder will set values */
564     avio_w8(pb, 0xa); /* level */
565     avio_w8(pb, 0); /* profile */
566     return 0xf;
567 }
568
569 /* TODO: No idea about these values */
570 static int mov_write_svq3_tag(AVIOContext *pb)
571 {
572     avio_wb32(pb, 0x15);
573     ffio_wfourcc(pb, "SMI ");
574     ffio_wfourcc(pb, "SEQH");
575     avio_wb32(pb, 0x5);
576     avio_wb32(pb, 0xe2c0211d);
577     avio_wb32(pb, 0xc0000000);
578     avio_w8(pb, 0);
579     return 0x15;
580 }
581
582 static int mov_write_avcc_tag(AVIOContext *pb, MOVTrack *track)
583 {
584     int64_t pos = avio_tell(pb);
585
586     avio_wb32(pb, 0);
587     ffio_wfourcc(pb, "avcC");
588     ff_isom_write_avcc(pb, track->vosData, track->vosLen);
589     return updateSize(pb, pos);
590 }
591
592 /* also used by all avid codecs (dv, imx, meridien) and their variants */
593 static int mov_write_avid_tag(AVIOContext *pb, MOVTrack *track)
594 {
595     int i;
596     avio_wb32(pb, 24); /* size */
597     ffio_wfourcc(pb, "ACLR");
598     ffio_wfourcc(pb, "ACLR");
599     ffio_wfourcc(pb, "0001");
600     avio_wb32(pb, 2); /* yuv range: full 1 / normal 2 */
601     avio_wb32(pb, 0); /* unknown */
602
603     avio_wb32(pb, 24); /* size */
604     ffio_wfourcc(pb, "APRG");
605     ffio_wfourcc(pb, "APRG");
606     ffio_wfourcc(pb, "0001");
607     avio_wb32(pb, 1); /* unknown */
608     avio_wb32(pb, 0); /* unknown */
609
610     avio_wb32(pb, 120); /* size */
611     ffio_wfourcc(pb, "ARES");
612     ffio_wfourcc(pb, "ARES");
613     ffio_wfourcc(pb, "0001");
614     avio_wb32(pb, AV_RB32(track->vosData + 0x28)); /* dnxhd cid, some id ? */
615     avio_wb32(pb, track->enc->width);
616     /* values below are based on samples created with quicktime and avid codecs */
617     if (track->vosData[5] & 2) { // interlaced
618         avio_wb32(pb, track->enc->height/2);
619         avio_wb32(pb, 2); /* unknown */
620         avio_wb32(pb, 0); /* unknown */
621         avio_wb32(pb, 4); /* unknown */
622     } else {
623         avio_wb32(pb, track->enc->height);
624         avio_wb32(pb, 1); /* unknown */
625         avio_wb32(pb, 0); /* unknown */
626         if (track->enc->height == 1080)
627             avio_wb32(pb, 5); /* unknown */
628         else
629             avio_wb32(pb, 6); /* unknown */
630     }
631     /* padding */
632     for (i = 0; i < 10; i++)
633         avio_wb64(pb, 0);
634
635     /* extra padding for stsd needed */
636     avio_wb32(pb, 0);
637     return 0;
638 }
639
640 static int mp4_get_codec_tag(AVFormatContext *s, MOVTrack *track)
641 {
642     int tag = track->enc->codec_tag;
643
644     if (!ff_codec_get_tag(ff_mp4_obj_type, track->enc->codec_id))
645         return 0;
646
647     if      (track->enc->codec_id == CODEC_ID_H264)      tag = MKTAG('a','v','c','1');
648     else if (track->enc->codec_id == CODEC_ID_AC3)       tag = MKTAG('a','c','-','3');
649     else if (track->enc->codec_id == CODEC_ID_DIRAC)     tag = MKTAG('d','r','a','c');
650     else if (track->enc->codec_id == CODEC_ID_MOV_TEXT)  tag = MKTAG('t','x','3','g');
651     else if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) tag = MKTAG('m','p','4','v');
652     else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) tag = MKTAG('m','p','4','a');
653
654     return tag;
655 }
656
657 static const AVCodecTag codec_ipod_tags[] = {
658     { CODEC_ID_H264,   MKTAG('a','v','c','1') },
659     { CODEC_ID_MPEG4,  MKTAG('m','p','4','v') },
660     { CODEC_ID_AAC,    MKTAG('m','p','4','a') },
661     { CODEC_ID_ALAC,   MKTAG('a','l','a','c') },
662     { CODEC_ID_AC3,    MKTAG('a','c','-','3') },
663     { CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') },
664     { CODEC_ID_MOV_TEXT, MKTAG('t','e','x','t') },
665     { CODEC_ID_NONE, 0 },
666 };
667
668 static int ipod_get_codec_tag(AVFormatContext *s, MOVTrack *track)
669 {
670     int tag = track->enc->codec_tag;
671
672     // keep original tag for subs, ipod supports both formats
673     if (!(track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE &&
674         (tag == MKTAG('t','x','3','g') ||
675          tag == MKTAG('t','e','x','t'))))
676         tag = ff_codec_get_tag(codec_ipod_tags, track->enc->codec_id);
677
678     if (!av_match_ext(s->filename, "m4a") && !av_match_ext(s->filename, "m4v"))
679         av_log(s, AV_LOG_WARNING, "Warning, extension is not .m4a nor .m4v "
680                "Quicktime/Ipod might not play the file\n");
681
682     return tag;
683 }
684
685 static int mov_get_dv_codec_tag(AVFormatContext *s, MOVTrack *track)
686 {
687     int tag;
688
689     if (track->enc->width == 720) /* SD */
690         if (track->enc->height == 480) /* NTSC */
691             if  (track->enc->pix_fmt == PIX_FMT_YUV422P) tag = MKTAG('d','v','5','n');
692             else                                         tag = MKTAG('d','v','c',' ');
693         else if (track->enc->pix_fmt == PIX_FMT_YUV422P) tag = MKTAG('d','v','5','p');
694         else if (track->enc->pix_fmt == PIX_FMT_YUV420P) tag = MKTAG('d','v','c','p');
695         else                                             tag = MKTAG('d','v','p','p');
696     else if (track->enc->height == 720) /* HD 720 line */
697         if  (track->enc->time_base.den == 50)            tag = MKTAG('d','v','h','q');
698         else                                             tag = MKTAG('d','v','h','p');
699     else if (track->enc->height == 1080) /* HD 1080 line */
700         if  (track->enc->time_base.den == 25)            tag = MKTAG('d','v','h','5');
701         else                                             tag = MKTAG('d','v','h','6');
702     else {
703         av_log(s, AV_LOG_ERROR, "unsupported height for dv codec\n");
704         return 0;
705     }
706
707     return tag;
708 }
709
710 static const struct {
711     enum PixelFormat pix_fmt;
712     uint32_t tag;
713     unsigned bps;
714 } mov_pix_fmt_tags[] = {
715     { PIX_FMT_YUYV422, MKTAG('y','u','v','s'),  0 },
716     { PIX_FMT_UYVY422, MKTAG('2','v','u','y'),  0 },
717     { PIX_FMT_RGB555BE,MKTAG('r','a','w',' '), 16 },
718     { PIX_FMT_RGB555LE,MKTAG('L','5','5','5'), 16 },
719     { PIX_FMT_RGB565LE,MKTAG('L','5','6','5'), 16 },
720     { PIX_FMT_RGB565BE,MKTAG('B','5','6','5'), 16 },
721     { PIX_FMT_GRAY16BE,MKTAG('b','1','6','g'), 16 },
722     { PIX_FMT_RGB24,   MKTAG('r','a','w',' '), 24 },
723     { PIX_FMT_BGR24,   MKTAG('2','4','B','G'), 24 },
724     { PIX_FMT_ARGB,    MKTAG('r','a','w',' '), 32 },
725     { PIX_FMT_BGRA,    MKTAG('B','G','R','A'), 32 },
726     { PIX_FMT_RGBA,    MKTAG('R','G','B','A'), 32 },
727     { PIX_FMT_ABGR,    MKTAG('A','B','G','R'), 32 },
728     { PIX_FMT_RGB48BE, MKTAG('b','4','8','r'), 48 },
729 };
730
731 static int mov_get_rawvideo_codec_tag(AVFormatContext *s, MOVTrack *track)
732 {
733     int tag = track->enc->codec_tag;
734     int i;
735
736     for (i = 0; i < FF_ARRAY_ELEMS(mov_pix_fmt_tags); i++) {
737         if (track->enc->pix_fmt == mov_pix_fmt_tags[i].pix_fmt) {
738             tag = mov_pix_fmt_tags[i].tag;
739             track->enc->bits_per_coded_sample = mov_pix_fmt_tags[i].bps;
740             break;
741         }
742     }
743
744     return tag;
745 }
746
747 static int mov_get_codec_tag(AVFormatContext *s, MOVTrack *track)
748 {
749     int tag = track->enc->codec_tag;
750
751     if (!tag || (track->enc->strict_std_compliance >= FF_COMPLIANCE_NORMAL &&
752                  (track->enc->codec_id == CODEC_ID_DVVIDEO ||
753                   track->enc->codec_id == CODEC_ID_RAWVIDEO ||
754                   track->enc->codec_id == CODEC_ID_H263 ||
755                   av_get_bits_per_sample(track->enc->codec_id)))) { // pcm audio
756         if (track->enc->codec_id == CODEC_ID_DVVIDEO)
757             tag = mov_get_dv_codec_tag(s, track);
758         else if (track->enc->codec_id == CODEC_ID_RAWVIDEO)
759             tag = mov_get_rawvideo_codec_tag(s, track);
760         else if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) {
761             tag = ff_codec_get_tag(codec_movvideo_tags, track->enc->codec_id);
762             if (!tag) { // if no mac fcc found, try with Microsoft tags
763                 tag = ff_codec_get_tag(ff_codec_bmp_tags, track->enc->codec_id);
764                 if (tag)
765                     av_log(s, AV_LOG_WARNING, "Using MS style video codec tag, "
766                            "the file may be unplayable!\n");
767             }
768         } else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) {
769             tag = ff_codec_get_tag(codec_movaudio_tags, track->enc->codec_id);
770             if (!tag) { // if no mac fcc found, try with Microsoft tags
771                 int ms_tag = ff_codec_get_tag(ff_codec_wav_tags, track->enc->codec_id);
772                 if (ms_tag) {
773                     tag = MKTAG('m', 's', ((ms_tag >> 8) & 0xff), (ms_tag & 0xff));
774                     av_log(s, AV_LOG_WARNING, "Using MS style audio codec tag, "
775                            "the file may be unplayable!\n");
776                 }
777             }
778         } else if (track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE)
779             tag = ff_codec_get_tag(ff_codec_movsubtitle_tags, track->enc->codec_id);
780     }
781
782     return tag;
783 }
784
785 static const AVCodecTag codec_3gp_tags[] = {
786     { CODEC_ID_H263,   MKTAG('s','2','6','3') },
787     { CODEC_ID_H264,   MKTAG('a','v','c','1') },
788     { CODEC_ID_MPEG4,  MKTAG('m','p','4','v') },
789     { CODEC_ID_AAC,    MKTAG('m','p','4','a') },
790     { CODEC_ID_AMR_NB, MKTAG('s','a','m','r') },
791     { CODEC_ID_AMR_WB, MKTAG('s','a','w','b') },
792     { CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') },
793     { CODEC_ID_NONE, 0 },
794 };
795
796 static int mov_find_codec_tag(AVFormatContext *s, MOVTrack *track)
797 {
798     int tag = track->enc->codec_tag;
799
800     if (track->mode == MODE_MP4 || track->mode == MODE_PSP || track->mode == MODE_ISM)
801         tag = mp4_get_codec_tag(s, track);
802     else if (track->mode == MODE_IPOD)
803         tag = ipod_get_codec_tag(s, track);
804     else if (track->mode & MODE_3GP)
805         tag = ff_codec_get_tag(codec_3gp_tags, track->enc->codec_id);
806     else
807         tag = mov_get_codec_tag(s, track);
808
809     return tag;
810 }
811
812 /** Write uuid atom.
813  * Needed to make file play in iPods running newest firmware
814  * goes after avcC atom in moov.trak.mdia.minf.stbl.stsd.avc1
815  */
816 static int mov_write_uuid_tag_ipod(AVIOContext *pb)
817 {
818     avio_wb32(pb, 28);
819     ffio_wfourcc(pb, "uuid");
820     avio_wb32(pb, 0x6b6840f2);
821     avio_wb32(pb, 0x5f244fc5);
822     avio_wb32(pb, 0xba39a51b);
823     avio_wb32(pb, 0xcf0323f3);
824     avio_wb32(pb, 0x0);
825     return 28;
826 }
827
828 static const uint16_t fiel_data[] = {
829     0x0000, 0x0100, 0x0201, 0x0206, 0x0209, 0x020e
830 };
831
832 static int mov_write_fiel_tag(AVIOContext *pb, MOVTrack *track)
833 {
834     unsigned mov_field_order = 0;
835     if (track->enc->field_order < FF_ARRAY_ELEMS(fiel_data))
836         mov_field_order = fiel_data[track->enc->field_order];
837     else
838         return 0;
839     avio_wb32(pb, 10);
840     ffio_wfourcc(pb, "fiel");
841     avio_wb16(pb, mov_field_order);
842     return 10;
843 }
844
845 static int mov_write_subtitle_tag(AVIOContext *pb, MOVTrack *track)
846 {
847     int64_t pos = avio_tell(pb);
848     avio_wb32(pb, 0);    /* size */
849     avio_wl32(pb, track->tag); // store it byteswapped
850     avio_wb32(pb, 0);    /* Reserved */
851     avio_wb16(pb, 0);    /* Reserved */
852     avio_wb16(pb, 1);    /* Data-reference index */
853
854     if (track->enc->extradata_size)
855         avio_write(pb, track->enc->extradata, track->enc->extradata_size);
856
857     return updateSize(pb, pos);
858 }
859
860 static int mov_write_pasp_tag(AVIOContext *pb, MOVTrack *track)
861 {
862     AVRational sar;
863     av_reduce(&sar.num, &sar.den, track->enc->sample_aspect_ratio.num,
864               track->enc->sample_aspect_ratio.den, INT_MAX);
865
866     avio_wb32(pb, 16);
867     ffio_wfourcc(pb, "pasp");
868     avio_wb32(pb, sar.num);
869     avio_wb32(pb, sar.den);
870     return 16;
871 }
872
873 static int mov_write_video_tag(AVIOContext *pb, MOVTrack *track)
874 {
875     int64_t pos = avio_tell(pb);
876     char compressor_name[32];
877
878     avio_wb32(pb, 0); /* size */
879     avio_wl32(pb, track->tag); // store it byteswapped
880     avio_wb32(pb, 0); /* Reserved */
881     avio_wb16(pb, 0); /* Reserved */
882     avio_wb16(pb, 1); /* Data-reference index */
883
884     avio_wb16(pb, 0); /* Codec stream version */
885     avio_wb16(pb, 0); /* Codec stream revision (=0) */
886     if (track->mode == MODE_MOV) {
887         ffio_wfourcc(pb, "FFMP"); /* Vendor */
888         if(track->enc->codec_id == CODEC_ID_RAWVIDEO) {
889             avio_wb32(pb, 0); /* Temporal Quality */
890             avio_wb32(pb, 0x400); /* Spatial Quality = lossless*/
891         } else {
892             avio_wb32(pb, 0x200); /* Temporal Quality = normal */
893             avio_wb32(pb, 0x200); /* Spatial Quality = normal */
894         }
895     } else {
896         avio_wb32(pb, 0); /* Reserved */
897         avio_wb32(pb, 0); /* Reserved */
898         avio_wb32(pb, 0); /* Reserved */
899     }
900     avio_wb16(pb, track->enc->width); /* Video width */
901     avio_wb16(pb, track->height); /* Video height */
902     avio_wb32(pb, 0x00480000); /* Horizontal resolution 72dpi */
903     avio_wb32(pb, 0x00480000); /* Vertical resolution 72dpi */
904     avio_wb32(pb, 0); /* Data size (= 0) */
905     avio_wb16(pb, 1); /* Frame count (= 1) */
906
907     memset(compressor_name,0,32);
908     /* FIXME not sure, ISO 14496-1 draft where it shall be set to 0 */
909     if (track->mode == MODE_MOV && track->enc->codec && track->enc->codec->name)
910         av_strlcpy(compressor_name,track->enc->codec->name,32);
911     avio_w8(pb, strlen(compressor_name));
912     avio_write(pb, compressor_name, 31);
913
914     if (track->mode == MODE_MOV && track->enc->bits_per_coded_sample)
915         avio_wb16(pb, track->enc->bits_per_coded_sample);
916     else
917         avio_wb16(pb, 0x18); /* Reserved */
918     avio_wb16(pb, 0xffff); /* Reserved */
919     if(track->tag == MKTAG('m','p','4','v'))
920         mov_write_esds_tag(pb, track);
921     else if(track->enc->codec_id == CODEC_ID_H263)
922         mov_write_d263_tag(pb);
923     else if(track->enc->codec_id == CODEC_ID_SVQ3)
924         mov_write_svq3_tag(pb);
925     else if(track->enc->codec_id == CODEC_ID_DNXHD)
926         mov_write_avid_tag(pb, track);
927     else if(track->enc->codec_id == CODEC_ID_H264) {
928         mov_write_avcc_tag(pb, track);
929         if(track->mode == MODE_IPOD)
930             mov_write_uuid_tag_ipod(pb);
931     } else if (track->enc->field_order != AV_FIELD_UNKNOWN)
932         mov_write_fiel_tag(pb, track);
933     else if(track->vosLen > 0)
934         mov_write_glbl_tag(pb, track);
935
936     if (track->enc->sample_aspect_ratio.den && track->enc->sample_aspect_ratio.num &&
937         track->enc->sample_aspect_ratio.den != track->enc->sample_aspect_ratio.num) {
938         mov_write_pasp_tag(pb, track);
939     }
940
941     return updateSize(pb, pos);
942 }
943
944 static int mov_write_rtp_tag(AVIOContext *pb, MOVTrack *track)
945 {
946     int64_t pos = avio_tell(pb);
947     avio_wb32(pb, 0); /* size */
948     ffio_wfourcc(pb, "rtp ");
949     avio_wb32(pb, 0); /* Reserved */
950     avio_wb16(pb, 0); /* Reserved */
951     avio_wb16(pb, 1); /* Data-reference index */
952
953     avio_wb16(pb, 1); /* Hint track version */
954     avio_wb16(pb, 1); /* Highest compatible version */
955     avio_wb32(pb, track->max_packet_size); /* Max packet size */
956
957     avio_wb32(pb, 12); /* size */
958     ffio_wfourcc(pb, "tims");
959     avio_wb32(pb, track->timescale);
960
961     return updateSize(pb, pos);
962 }
963
964 static int mov_write_stsd_tag(AVIOContext *pb, MOVTrack *track)
965 {
966     int64_t pos = avio_tell(pb);
967     avio_wb32(pb, 0); /* size */
968     ffio_wfourcc(pb, "stsd");
969     avio_wb32(pb, 0); /* version & flags */
970     avio_wb32(pb, 1); /* entry count */
971     if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO)
972         mov_write_video_tag(pb, track);
973     else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
974         mov_write_audio_tag(pb, track);
975     else if (track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE)
976         mov_write_subtitle_tag(pb, track);
977     else if (track->enc->codec_tag == MKTAG('r','t','p',' '))
978         mov_write_rtp_tag(pb, track);
979     return updateSize(pb, pos);
980 }
981
982 static int mov_write_ctts_tag(AVIOContext *pb, MOVTrack *track)
983 {
984     MOVStts *ctts_entries;
985     uint32_t entries = 0;
986     uint32_t atom_size;
987     int i;
988
989     ctts_entries = av_malloc((track->entry + 1) * sizeof(*ctts_entries)); /* worst case */
990     ctts_entries[0].count = 1;
991     ctts_entries[0].duration = track->cluster[0].cts;
992     for (i=1; i<track->entry; i++) {
993         if (track->cluster[i].cts == ctts_entries[entries].duration) {
994             ctts_entries[entries].count++; /* compress */
995         } else {
996             entries++;
997             ctts_entries[entries].duration = track->cluster[i].cts;
998             ctts_entries[entries].count = 1;
999         }
1000     }
1001     entries++; /* last one */
1002     atom_size = 16 + (entries * 8);
1003     avio_wb32(pb, atom_size); /* size */
1004     ffio_wfourcc(pb, "ctts");
1005     avio_wb32(pb, 0); /* version & flags */
1006     avio_wb32(pb, entries); /* entry count */
1007     for (i=0; i<entries; i++) {
1008         avio_wb32(pb, ctts_entries[i].count);
1009         avio_wb32(pb, ctts_entries[i].duration);
1010     }
1011     av_free(ctts_entries);
1012     return atom_size;
1013 }
1014
1015 /* Time to sample atom */
1016 static int mov_write_stts_tag(AVIOContext *pb, MOVTrack *track)
1017 {
1018     MOVStts *stts_entries;
1019     uint32_t entries = -1;
1020     uint32_t atom_size;
1021     int i;
1022
1023     if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO && !track->audio_vbr) {
1024         stts_entries = av_malloc(sizeof(*stts_entries)); /* one entry */
1025         stts_entries[0].count = track->sampleCount;
1026         stts_entries[0].duration = 1;
1027         entries = 1;
1028     } else {
1029         stts_entries = track->entry ?
1030                        av_malloc(track->entry * sizeof(*stts_entries)) : /* worst case */
1031                        NULL;
1032         for (i=0; i<track->entry; i++) {
1033             int64_t duration = i + 1 == track->entry ?
1034                 track->trackDuration - track->cluster[i].dts + track->start_dts : /* readjusting */
1035                 track->cluster[i+1].dts - track->cluster[i].dts;
1036             if (i && duration == stts_entries[entries].duration) {
1037                 stts_entries[entries].count++; /* compress */
1038             } else {
1039                 entries++;
1040                 stts_entries[entries].duration = duration;
1041                 stts_entries[entries].count = 1;
1042             }
1043         }
1044         entries++; /* last one */
1045     }
1046     atom_size = 16 + (entries * 8);
1047     avio_wb32(pb, atom_size); /* size */
1048     ffio_wfourcc(pb, "stts");
1049     avio_wb32(pb, 0); /* version & flags */
1050     avio_wb32(pb, entries); /* entry count */
1051     for (i=0; i<entries; i++) {
1052         avio_wb32(pb, stts_entries[i].count);
1053         avio_wb32(pb, stts_entries[i].duration);
1054     }
1055     av_free(stts_entries);
1056     return atom_size;
1057 }
1058
1059 static int mov_write_dref_tag(AVIOContext *pb)
1060 {
1061     avio_wb32(pb, 28); /* size */
1062     ffio_wfourcc(pb, "dref");
1063     avio_wb32(pb, 0); /* version & flags */
1064     avio_wb32(pb, 1); /* entry count */
1065
1066     avio_wb32(pb, 0xc); /* size */
1067     //FIXME add the alis and rsrc atom
1068     ffio_wfourcc(pb, "url ");
1069     avio_wb32(pb, 1); /* version & flags */
1070
1071     return 28;
1072 }
1073
1074 static int mov_write_stbl_tag(AVIOContext *pb, MOVTrack *track)
1075 {
1076     int64_t pos = avio_tell(pb);
1077     avio_wb32(pb, 0); /* size */
1078     ffio_wfourcc(pb, "stbl");
1079     mov_write_stsd_tag(pb, track);
1080     mov_write_stts_tag(pb, track);
1081     if ((track->enc->codec_type == AVMEDIA_TYPE_VIDEO ||
1082          track->enc->codec_tag == MKTAG('r','t','p',' ')) &&
1083         track->hasKeyframes && track->hasKeyframes < track->entry)
1084         mov_write_stss_tag(pb, track, MOV_SYNC_SAMPLE);
1085     if (track->mode == MODE_MOV && track->flags & MOV_TRACK_STPS)
1086         mov_write_stss_tag(pb, track, MOV_PARTIAL_SYNC_SAMPLE);
1087     if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO &&
1088         track->flags & MOV_TRACK_CTTS)
1089         mov_write_ctts_tag(pb, track);
1090     mov_write_stsc_tag(pb, track);
1091     mov_write_stsz_tag(pb, track);
1092     mov_write_stco_tag(pb, track);
1093     return updateSize(pb, pos);
1094 }
1095
1096 static int mov_write_dinf_tag(AVIOContext *pb)
1097 {
1098     int64_t pos = avio_tell(pb);
1099     avio_wb32(pb, 0); /* size */
1100     ffio_wfourcc(pb, "dinf");
1101     mov_write_dref_tag(pb);
1102     return updateSize(pb, pos);
1103 }
1104
1105 static int mov_write_nmhd_tag(AVIOContext *pb)
1106 {
1107     avio_wb32(pb, 12);
1108     ffio_wfourcc(pb, "nmhd");
1109     avio_wb32(pb, 0);
1110     return 12;
1111 }
1112
1113 static int mov_write_gmhd_tag(AVIOContext *pb)
1114 {
1115     avio_wb32(pb, 0x20);   /* size */
1116     ffio_wfourcc(pb, "gmhd");
1117     avio_wb32(pb, 0x18);   /* gmin size */
1118     ffio_wfourcc(pb, "gmin");/* generic media info */
1119     avio_wb32(pb, 0);      /* version & flags */
1120     avio_wb16(pb, 0x40);   /* graphics mode = */
1121     avio_wb16(pb, 0x8000); /* opColor (r?) */
1122     avio_wb16(pb, 0x8000); /* opColor (g?) */
1123     avio_wb16(pb, 0x8000); /* opColor (b?) */
1124     avio_wb16(pb, 0);      /* balance */
1125     avio_wb16(pb, 0);      /* reserved */
1126     return 0x20;
1127 }
1128
1129 static int mov_write_smhd_tag(AVIOContext *pb)
1130 {
1131     avio_wb32(pb, 16); /* size */
1132     ffio_wfourcc(pb, "smhd");
1133     avio_wb32(pb, 0); /* version & flags */
1134     avio_wb16(pb, 0); /* reserved (balance, normally = 0) */
1135     avio_wb16(pb, 0); /* reserved */
1136     return 16;
1137 }
1138
1139 static int mov_write_vmhd_tag(AVIOContext *pb)
1140 {
1141     avio_wb32(pb, 0x14); /* size (always 0x14) */
1142     ffio_wfourcc(pb, "vmhd");
1143     avio_wb32(pb, 0x01); /* version & flags */
1144     avio_wb64(pb, 0); /* reserved (graphics mode = copy) */
1145     return 0x14;
1146 }
1147
1148 static int mov_write_hdlr_tag(AVIOContext *pb, MOVTrack *track)
1149 {
1150     const char *hdlr, *descr = NULL, *hdlr_type = NULL;
1151     int64_t pos = avio_tell(pb);
1152
1153     if (!track) { /* no media --> data handler */
1154         hdlr = "dhlr";
1155         hdlr_type = "url ";
1156         descr = "DataHandler";
1157     } else {
1158         hdlr = (track->mode == MODE_MOV) ? "mhlr" : "\0\0\0\0";
1159         if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) {
1160             hdlr_type = "vide";
1161             descr = "VideoHandler";
1162         } else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) {
1163             hdlr_type = "soun";
1164             descr = "SoundHandler";
1165         } else if (track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE) {
1166             if (track->tag == MKTAG('t','x','3','g')) hdlr_type = "sbtl";
1167             else                                      hdlr_type = "text";
1168             descr = "SubtitleHandler";
1169         } else if (track->enc->codec_tag == MKTAG('r','t','p',' ')) {
1170             hdlr_type = "hint";
1171             descr = "HintHandler";
1172         }
1173     }
1174
1175     avio_wb32(pb, 0); /* size */
1176     ffio_wfourcc(pb, "hdlr");
1177     avio_wb32(pb, 0); /* Version & flags */
1178     avio_write(pb, hdlr, 4); /* handler */
1179     ffio_wfourcc(pb, hdlr_type); /* handler type */
1180     avio_wb32(pb ,0); /* reserved */
1181     avio_wb32(pb ,0); /* reserved */
1182     avio_wb32(pb ,0); /* reserved */
1183     if (!track || track->mode == MODE_MOV)
1184         avio_w8(pb, strlen(descr)); /* pascal string */
1185     avio_write(pb, descr, strlen(descr)); /* handler description */
1186     if (track && track->mode != MODE_MOV)
1187         avio_w8(pb, 0); /* c string */
1188     return updateSize(pb, pos);
1189 }
1190
1191 static int mov_write_hmhd_tag(AVIOContext *pb)
1192 {
1193     /* This atom must be present, but leaving the values at zero
1194      * seems harmless. */
1195     avio_wb32(pb, 28); /* size */
1196     ffio_wfourcc(pb, "hmhd");
1197     avio_wb32(pb, 0); /* version, flags */
1198     avio_wb16(pb, 0); /* maxPDUsize */
1199     avio_wb16(pb, 0); /* avgPDUsize */
1200     avio_wb32(pb, 0); /* maxbitrate */
1201     avio_wb32(pb, 0); /* avgbitrate */
1202     avio_wb32(pb, 0); /* reserved */
1203     return 28;
1204 }
1205
1206 static int mov_write_minf_tag(AVIOContext *pb, MOVTrack *track)
1207 {
1208     int64_t pos = avio_tell(pb);
1209     avio_wb32(pb, 0); /* size */
1210     ffio_wfourcc(pb, "minf");
1211     if(track->enc->codec_type == AVMEDIA_TYPE_VIDEO)
1212         mov_write_vmhd_tag(pb);
1213     else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
1214         mov_write_smhd_tag(pb);
1215     else if (track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE) {
1216         if (track->tag == MKTAG('t','e','x','t')) mov_write_gmhd_tag(pb);
1217         else                                      mov_write_nmhd_tag(pb);
1218     } else if (track->tag == MKTAG('r','t','p',' ')) {
1219         mov_write_hmhd_tag(pb);
1220     }
1221     if (track->mode == MODE_MOV) /* FIXME: Why do it for MODE_MOV only ? */
1222         mov_write_hdlr_tag(pb, NULL);
1223     mov_write_dinf_tag(pb);
1224     mov_write_stbl_tag(pb, track);
1225     return updateSize(pb, pos);
1226 }
1227
1228 static int mov_write_mdhd_tag(AVIOContext *pb, MOVTrack *track)
1229 {
1230     int version = track->trackDuration < INT32_MAX ? 0 : 1;
1231
1232     (version == 1) ? avio_wb32(pb, 44) : avio_wb32(pb, 32); /* size */
1233     ffio_wfourcc(pb, "mdhd");
1234     avio_w8(pb, version);
1235     avio_wb24(pb, 0); /* flags */
1236     if (version == 1) {
1237         avio_wb64(pb, track->time);
1238         avio_wb64(pb, track->time);
1239     } else {
1240         avio_wb32(pb, track->time); /* creation time */
1241         avio_wb32(pb, track->time); /* modification time */
1242     }
1243     avio_wb32(pb, track->timescale); /* time scale (sample rate for audio) */
1244     (version == 1) ? avio_wb64(pb, track->trackDuration) : avio_wb32(pb, track->trackDuration); /* duration */
1245     avio_wb16(pb, track->language); /* language */
1246     avio_wb16(pb, 0); /* reserved (quality) */
1247
1248     if(version!=0 && track->mode == MODE_MOV){
1249         av_log(NULL, AV_LOG_ERROR,
1250             "FATAL error, file duration too long for timebase, this file will not be\n"
1251             "playable with quicktime. Choose a different timebase or a different\n"
1252             "container format\n");
1253     }
1254
1255     return 32;
1256 }
1257
1258 static int mov_write_mdia_tag(AVIOContext *pb, MOVTrack *track)
1259 {
1260     int64_t pos = avio_tell(pb);
1261     avio_wb32(pb, 0); /* size */
1262     ffio_wfourcc(pb, "mdia");
1263     mov_write_mdhd_tag(pb, track);
1264     mov_write_hdlr_tag(pb, track);
1265     mov_write_minf_tag(pb, track);
1266     return updateSize(pb, pos);
1267 }
1268
1269 static int mov_write_tkhd_tag(AVIOContext *pb, MOVTrack *track, AVStream *st)
1270 {
1271     int64_t duration = av_rescale_rnd(track->trackDuration, MOV_TIMESCALE,
1272                                       track->timescale, AV_ROUND_UP);
1273     int version = duration < INT32_MAX ? 0 : 1;
1274
1275     (version == 1) ? avio_wb32(pb, 104) : avio_wb32(pb, 92); /* size */
1276     ffio_wfourcc(pb, "tkhd");
1277     avio_w8(pb, version);
1278     avio_wb24(pb, 0xf); /* flags (track enabled) */
1279     if (version == 1) {
1280         avio_wb64(pb, track->time);
1281         avio_wb64(pb, track->time);
1282     } else {
1283         avio_wb32(pb, track->time); /* creation time */
1284         avio_wb32(pb, track->time); /* modification time */
1285     }
1286     avio_wb32(pb, track->trackID); /* track-id */
1287     avio_wb32(pb, 0); /* reserved */
1288     (version == 1) ? avio_wb64(pb, duration) : avio_wb32(pb, duration);
1289
1290     avio_wb32(pb, 0); /* reserved */
1291     avio_wb32(pb, 0); /* reserved */
1292     avio_wb16(pb, 0); /* layer */
1293     avio_wb16(pb, st ? st->codec->codec_type : 0); /* alternate group) */
1294     /* Volume, only for audio */
1295     if(track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
1296         avio_wb16(pb, 0x0100);
1297     else
1298         avio_wb16(pb, 0);
1299     avio_wb16(pb, 0); /* reserved */
1300
1301     /* Matrix structure */
1302     avio_wb32(pb, 0x00010000); /* reserved */
1303     avio_wb32(pb, 0x0); /* reserved */
1304     avio_wb32(pb, 0x0); /* reserved */
1305     avio_wb32(pb, 0x0); /* reserved */
1306     avio_wb32(pb, 0x00010000); /* reserved */
1307     avio_wb32(pb, 0x0); /* reserved */
1308     avio_wb32(pb, 0x0); /* reserved */
1309     avio_wb32(pb, 0x0); /* reserved */
1310     avio_wb32(pb, 0x40000000); /* reserved */
1311
1312     /* Track width and height, for visual only */
1313     if(st && (track->enc->codec_type == AVMEDIA_TYPE_VIDEO ||
1314               track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE)) {
1315         if(track->mode == MODE_MOV) {
1316             avio_wb32(pb, track->enc->width << 16);
1317             avio_wb32(pb, track->height << 16);
1318         } else {
1319             double sample_aspect_ratio = av_q2d(st->sample_aspect_ratio);
1320             if(!sample_aspect_ratio || track->height != track->enc->height)
1321                 sample_aspect_ratio = 1;
1322             avio_wb32(pb, sample_aspect_ratio * track->enc->width*0x10000);
1323             avio_wb32(pb, track->height*0x10000);
1324         }
1325     }
1326     else {
1327         avio_wb32(pb, 0);
1328         avio_wb32(pb, 0);
1329     }
1330     return 0x5c;
1331 }
1332
1333 static int mov_write_tapt_tag(AVIOContext *pb, MOVTrack *track)
1334 {
1335     int32_t width = av_rescale(track->enc->sample_aspect_ratio.num, track->enc->width,
1336                                track->enc->sample_aspect_ratio.den);
1337
1338     int64_t pos = avio_tell(pb);
1339
1340     avio_wb32(pb, 0); /* size */
1341     ffio_wfourcc(pb, "tapt");
1342
1343     avio_wb32(pb, 20);
1344     ffio_wfourcc(pb, "clef");
1345     avio_wb32(pb, 0);
1346     avio_wb32(pb, width << 16);
1347     avio_wb32(pb, track->enc->height << 16);
1348
1349     avio_wb32(pb, 20);
1350     ffio_wfourcc(pb, "enof");
1351     avio_wb32(pb, 0);
1352     avio_wb32(pb, track->enc->width << 16);
1353     avio_wb32(pb, track->enc->height << 16);
1354
1355     return updateSize(pb, pos);
1356 }
1357
1358 // This box seems important for the psp playback ... without it the movie seems to hang
1359 static int mov_write_edts_tag(AVIOContext *pb, MOVTrack *track)
1360 {
1361     int64_t duration = av_rescale_rnd(track->trackDuration, MOV_TIMESCALE,
1362                                       track->timescale, AV_ROUND_UP);
1363     int version = duration < INT32_MAX ? 0 : 1;
1364     int entry_size, entry_count, size;
1365     int64_t delay, start_ct = track->cluster[0].cts;
1366     delay = av_rescale_rnd(track->cluster[0].dts + start_ct, MOV_TIMESCALE,
1367                            track->timescale, AV_ROUND_DOWN);
1368     version |= delay < INT32_MAX ? 0 : 1;
1369
1370     entry_size = (version == 1) ? 20 : 12;
1371     entry_count = 1 + (delay > 0);
1372     size = 24 + entry_count * entry_size;
1373
1374     /* write the atom data */
1375     avio_wb32(pb, size);
1376     ffio_wfourcc(pb, "edts");
1377     avio_wb32(pb, size - 8);
1378     ffio_wfourcc(pb, "elst");
1379     avio_w8(pb, version);
1380     avio_wb24(pb, 0); /* flags */
1381
1382     avio_wb32(pb, entry_count);
1383     if (delay > 0) { /* add an empty edit to delay presentation */
1384         if (version == 1) {
1385             avio_wb64(pb, delay);
1386             avio_wb64(pb, -1);
1387         } else {
1388             avio_wb32(pb, delay);
1389             avio_wb32(pb, -1);
1390         }
1391         avio_wb32(pb, 0x00010000);
1392     }
1393
1394     /* duration */
1395     if (version == 1) {
1396         avio_wb64(pb, duration);
1397         avio_wb64(pb, start_ct);
1398     } else {
1399         avio_wb32(pb, duration);
1400         avio_wb32(pb, start_ct);
1401     }
1402     avio_wb32(pb, 0x00010000);
1403     return size;
1404 }
1405
1406 static int mov_write_tref_tag(AVIOContext *pb, MOVTrack *track)
1407 {
1408     avio_wb32(pb, 20);   // size
1409     ffio_wfourcc(pb, "tref");
1410     avio_wb32(pb, 12);   // size (subatom)
1411     avio_wl32(pb, track->tref_tag);
1412     avio_wb32(pb, track->tref_id);
1413     return 20;
1414 }
1415
1416 // goes at the end of each track!  ... Critical for PSP playback ("Incompatible data" without it)
1417 static int mov_write_uuid_tag_psp(AVIOContext *pb, MOVTrack *mov)
1418 {
1419     avio_wb32(pb, 0x34); /* size ... reports as 28 in mp4box! */
1420     ffio_wfourcc(pb, "uuid");
1421     ffio_wfourcc(pb, "USMT");
1422     avio_wb32(pb, 0x21d24fce);
1423     avio_wb32(pb, 0xbb88695c);
1424     avio_wb32(pb, 0xfac9c740);
1425     avio_wb32(pb, 0x1c);     // another size here!
1426     ffio_wfourcc(pb, "MTDT");
1427     avio_wb32(pb, 0x00010012);
1428     avio_wb32(pb, 0x0a);
1429     avio_wb32(pb, 0x55c40000);
1430     avio_wb32(pb, 0x1);
1431     avio_wb32(pb, 0x0);
1432     return 0x34;
1433 }
1434
1435 static int mov_write_udta_sdp(AVIOContext *pb, AVFormatContext *ctx, int index)
1436 {
1437     char buf[1000] = "";
1438     int len;
1439
1440     ff_sdp_write_media(buf, sizeof(buf), ctx->streams[0]->codec, NULL, NULL, 0, 0, ctx);
1441     av_strlcatf(buf, sizeof(buf), "a=control:streamid=%d\r\n", index);
1442     len = strlen(buf);
1443
1444     avio_wb32(pb, len + 24);
1445     ffio_wfourcc(pb, "udta");
1446     avio_wb32(pb, len + 16);
1447     ffio_wfourcc(pb, "hnti");
1448     avio_wb32(pb, len + 8);
1449     ffio_wfourcc(pb, "sdp ");
1450     avio_write(pb, buf, len);
1451     return len + 24;
1452 }
1453
1454 static int mov_write_trak_tag(AVIOContext *pb, MOVMuxContext *mov,
1455                               MOVTrack *track, AVStream *st)
1456 {
1457     int64_t pos = avio_tell(pb);
1458     avio_wb32(pb, 0); /* size */
1459     ffio_wfourcc(pb, "trak");
1460     mov_write_tkhd_tag(pb, track, st);
1461     if (!(mov->flags & FF_MOV_FLAG_FRAGMENT)) // EDTS with fragments is tricky as we dont know the duration when its written
1462         mov_write_edts_tag(pb, track);  // PSP Movies and several other cases require edts box
1463     if (track->tref_tag)
1464         mov_write_tref_tag(pb, track);
1465     mov_write_mdia_tag(pb, track);
1466     if (track->mode == MODE_PSP)
1467         mov_write_uuid_tag_psp(pb,track);  // PSP Movies require this uuid box
1468     if (track->tag == MKTAG('r','t','p',' '))
1469         mov_write_udta_sdp(pb, track->rtp_ctx, track->trackID);
1470     if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO && track->mode == MODE_MOV) {
1471         double sample_aspect_ratio = av_q2d(st->sample_aspect_ratio);
1472         if (0.0 != sample_aspect_ratio && 1.0 != sample_aspect_ratio)
1473             mov_write_tapt_tag(pb, track);
1474     };
1475     return updateSize(pb, pos);
1476 }
1477
1478 static int mov_write_iods_tag(AVIOContext *pb, MOVMuxContext *mov)
1479 {
1480     int i, has_audio = 0, has_video = 0;
1481     int64_t pos = avio_tell(pb);
1482     int audio_profile = mov->iods_audio_profile;
1483     int video_profile = mov->iods_video_profile;
1484     for (i = 0; i < mov->nb_streams; i++) {
1485         if(mov->tracks[i].entry > 0) {
1486             has_audio |= mov->tracks[i].enc->codec_type == AVMEDIA_TYPE_AUDIO;
1487             has_video |= mov->tracks[i].enc->codec_type == AVMEDIA_TYPE_VIDEO;
1488         }
1489     }
1490     if (audio_profile < 0)
1491         audio_profile = 0xFF - has_audio;
1492     if (video_profile < 0)
1493         video_profile = 0xFF - has_video;
1494     avio_wb32(pb, 0x0); /* size */
1495     ffio_wfourcc(pb, "iods");
1496     avio_wb32(pb, 0);    /* version & flags */
1497     putDescr(pb, 0x10, 7);
1498     avio_wb16(pb, 0x004f);
1499     avio_w8(pb, 0xff);
1500     avio_w8(pb, 0xff);
1501     avio_w8(pb, audio_profile);
1502     avio_w8(pb, video_profile);
1503     avio_w8(pb, 0xff);
1504     return updateSize(pb, pos);
1505 }
1506
1507 static int mov_write_trex_tag(AVIOContext *pb, MOVTrack *track)
1508 {
1509     avio_wb32(pb, 0x20); /* size */
1510     ffio_wfourcc(pb, "trex");
1511     avio_wb32(pb, 0);   /* version & flags */
1512     avio_wb32(pb, track->trackID); /* track ID */
1513     avio_wb32(pb, 1);   /* default sample description index */
1514     avio_wb32(pb, 0);   /* default sample duration */
1515     avio_wb32(pb, 0);   /* default sample size */
1516     avio_wb32(pb, 0);   /* default sample flags */
1517     return 0;
1518 }
1519
1520 static int mov_write_mvex_tag(AVIOContext *pb, MOVMuxContext *mov)
1521 {
1522     int64_t pos = avio_tell(pb);
1523     int i;
1524     avio_wb32(pb, 0x0); /* size */
1525     ffio_wfourcc(pb, "mvex");
1526     for (i = 0; i < mov->nb_streams; i++)
1527         mov_write_trex_tag(pb, &mov->tracks[i]);
1528     return updateSize(pb, pos);
1529 }
1530
1531 static int mov_write_mvhd_tag(AVIOContext *pb, MOVMuxContext *mov)
1532 {
1533     int maxTrackID = 1, i;
1534     int64_t maxTrackLenTemp, maxTrackLen = 0;
1535     int version;
1536
1537     for (i=0; i<mov->nb_streams; i++) {
1538         if(mov->tracks[i].entry > 0) {
1539             maxTrackLenTemp = av_rescale_rnd(mov->tracks[i].trackDuration,
1540                                              MOV_TIMESCALE,
1541                                              mov->tracks[i].timescale,
1542                                              AV_ROUND_UP);
1543             if(maxTrackLen < maxTrackLenTemp)
1544                 maxTrackLen = maxTrackLenTemp;
1545             if(maxTrackID < mov->tracks[i].trackID)
1546                 maxTrackID = mov->tracks[i].trackID;
1547         }
1548     }
1549
1550     version = maxTrackLen < UINT32_MAX ? 0 : 1;
1551     (version == 1) ? avio_wb32(pb, 120) : avio_wb32(pb, 108); /* size */
1552     ffio_wfourcc(pb, "mvhd");
1553     avio_w8(pb, version);
1554     avio_wb24(pb, 0); /* flags */
1555     if (version == 1) {
1556         avio_wb64(pb, mov->time);
1557         avio_wb64(pb, mov->time);
1558     } else {
1559         avio_wb32(pb, mov->time); /* creation time */
1560         avio_wb32(pb, mov->time); /* modification time */
1561     }
1562     avio_wb32(pb, MOV_TIMESCALE);
1563     (version == 1) ? avio_wb64(pb, maxTrackLen) : avio_wb32(pb, maxTrackLen); /* duration of longest track */
1564
1565     avio_wb32(pb, 0x00010000); /* reserved (preferred rate) 1.0 = normal */
1566     avio_wb16(pb, 0x0100); /* reserved (preferred volume) 1.0 = normal */
1567     avio_wb16(pb, 0); /* reserved */
1568     avio_wb32(pb, 0); /* reserved */
1569     avio_wb32(pb, 0); /* reserved */
1570
1571     /* Matrix structure */
1572     avio_wb32(pb, 0x00010000); /* reserved */
1573     avio_wb32(pb, 0x0); /* reserved */
1574     avio_wb32(pb, 0x0); /* reserved */
1575     avio_wb32(pb, 0x0); /* reserved */
1576     avio_wb32(pb, 0x00010000); /* reserved */
1577     avio_wb32(pb, 0x0); /* reserved */
1578     avio_wb32(pb, 0x0); /* reserved */
1579     avio_wb32(pb, 0x0); /* reserved */
1580     avio_wb32(pb, 0x40000000); /* reserved */
1581
1582     avio_wb32(pb, 0); /* reserved (preview time) */
1583     avio_wb32(pb, 0); /* reserved (preview duration) */
1584     avio_wb32(pb, 0); /* reserved (poster time) */
1585     avio_wb32(pb, 0); /* reserved (selection time) */
1586     avio_wb32(pb, 0); /* reserved (selection duration) */
1587     avio_wb32(pb, 0); /* reserved (current time) */
1588     avio_wb32(pb, maxTrackID+1); /* Next track id */
1589     return 0x6c;
1590 }
1591
1592 static int mov_write_itunes_hdlr_tag(AVIOContext *pb, MOVMuxContext *mov,
1593                                      AVFormatContext *s)
1594 {
1595     avio_wb32(pb, 33); /* size */
1596     ffio_wfourcc(pb, "hdlr");
1597     avio_wb32(pb, 0);
1598     avio_wb32(pb, 0);
1599     ffio_wfourcc(pb, "mdir");
1600     ffio_wfourcc(pb, "appl");
1601     avio_wb32(pb, 0);
1602     avio_wb32(pb, 0);
1603     avio_w8(pb, 0);
1604     return 33;
1605 }
1606
1607 /* helper function to write a data tag with the specified string as data */
1608 static int mov_write_string_data_tag(AVIOContext *pb, const char *data, int lang, int long_style)
1609 {
1610     if(long_style){
1611         int size = 16 + strlen(data);
1612         avio_wb32(pb, size); /* size */
1613         ffio_wfourcc(pb, "data");
1614         avio_wb32(pb, 1);
1615         avio_wb32(pb, 0);
1616         avio_write(pb, data, strlen(data));
1617         return size;
1618     }else{
1619         if (!lang)
1620             lang = ff_mov_iso639_to_lang("und", 1);
1621         avio_wb16(pb, strlen(data)); /* string length */
1622         avio_wb16(pb, lang);
1623         avio_write(pb, data, strlen(data));
1624         return strlen(data) + 4;
1625     }
1626 }
1627
1628 static int mov_write_string_tag(AVIOContext *pb, const char *name, const char *value, int lang, int long_style){
1629     int size = 0;
1630     if (value && value[0]) {
1631         int64_t pos = avio_tell(pb);
1632         avio_wb32(pb, 0); /* size */
1633         ffio_wfourcc(pb, name);
1634         mov_write_string_data_tag(pb, value, lang, long_style);
1635         size= updateSize(pb, pos);
1636     }
1637     return size;
1638 }
1639
1640 static int mov_write_string_metadata(AVFormatContext *s, AVIOContext *pb,
1641                                      const char *name, const char *tag,
1642                                      int long_style)
1643 {
1644     int l, lang = 0, len, len2;
1645     AVDictionaryEntry *t, *t2 = NULL;
1646     char tag2[16];
1647
1648     if (!(t = av_dict_get(s->metadata, tag, NULL, 0)))
1649         return 0;
1650
1651     len = strlen(t->key);
1652     snprintf(tag2, sizeof(tag2), "%s-", tag);
1653     while ((t2 = av_dict_get(s->metadata, tag2, t2, AV_DICT_IGNORE_SUFFIX))) {
1654         len2 = strlen(t2->key);
1655         if (len2 == len+4 && !strcmp(t->value, t2->value)
1656             && (l=ff_mov_iso639_to_lang(&t2->key[len2-3], 1)) >= 0) {
1657             lang = l;
1658             break;
1659         }
1660     }
1661     return mov_write_string_tag(pb, name, t->value, lang, long_style);
1662 }
1663
1664 /* iTunes track number */
1665 static int mov_write_trkn_tag(AVIOContext *pb, MOVMuxContext *mov,
1666                               AVFormatContext *s)
1667 {
1668     AVDictionaryEntry *t = av_dict_get(s->metadata, "track", NULL, 0);
1669     int size = 0, track = t ? atoi(t->value) : 0;
1670     if (track) {
1671         avio_wb32(pb, 32); /* size */
1672         ffio_wfourcc(pb, "trkn");
1673             avio_wb32(pb, 24); /* size */
1674             ffio_wfourcc(pb, "data");
1675             avio_wb32(pb, 0);        // 8 bytes empty
1676             avio_wb32(pb, 0);
1677             avio_wb16(pb, 0);        // empty
1678             avio_wb16(pb, track);    // track number
1679             avio_wb16(pb, 0);        // total track number
1680             avio_wb16(pb, 0);        // empty
1681         size = 32;
1682     }
1683     return size;
1684 }
1685
1686 /* iTunes meta data list */
1687 static int mov_write_ilst_tag(AVIOContext *pb, MOVMuxContext *mov,
1688                               AVFormatContext *s)
1689 {
1690     int64_t pos = avio_tell(pb);
1691     avio_wb32(pb, 0); /* size */
1692     ffio_wfourcc(pb, "ilst");
1693     mov_write_string_metadata(s, pb, "\251nam", "title"    , 1);
1694     mov_write_string_metadata(s, pb, "\251ART", "artist"   , 1);
1695     mov_write_string_metadata(s, pb, "aART", "album_artist", 1);
1696     mov_write_string_metadata(s, pb, "\251wrt", "composer" , 1);
1697     mov_write_string_metadata(s, pb, "\251alb", "album"    , 1);
1698     mov_write_string_metadata(s, pb, "\251day", "date"     , 1);
1699     mov_write_string_tag(pb, "\251too", LIBAVFORMAT_IDENT, 0, 1);
1700     mov_write_string_metadata(s, pb, "\251cmt", "comment"  , 1);
1701     mov_write_string_metadata(s, pb, "\251gen", "genre"    , 1);
1702     mov_write_string_metadata(s, pb, "\251cpy", "copyright", 1);
1703     mov_write_string_metadata(s, pb, "\251grp", "grouping" , 1);
1704     mov_write_string_metadata(s, pb, "\251lyr", "lyrics"   , 1);
1705     mov_write_string_metadata(s, pb, "desc",    "description",1);
1706     mov_write_string_metadata(s, pb, "ldes",    "synopsis" , 1);
1707     mov_write_string_metadata(s, pb, "tvsh",    "show"     , 1);
1708     mov_write_string_metadata(s, pb, "tven",    "episode_id",1);
1709     mov_write_string_metadata(s, pb, "tvnn",    "network"  , 1);
1710     mov_write_trkn_tag(pb, mov, s);
1711     return updateSize(pb, pos);
1712 }
1713
1714 /* iTunes meta data tag */
1715 static int mov_write_meta_tag(AVIOContext *pb, MOVMuxContext *mov,
1716                               AVFormatContext *s)
1717 {
1718     int size = 0;
1719     int64_t pos = avio_tell(pb);
1720     avio_wb32(pb, 0); /* size */
1721     ffio_wfourcc(pb, "meta");
1722     avio_wb32(pb, 0);
1723     mov_write_itunes_hdlr_tag(pb, mov, s);
1724     mov_write_ilst_tag(pb, mov, s);
1725     size = updateSize(pb, pos);
1726     return size;
1727 }
1728
1729 static int utf8len(const uint8_t *b)
1730 {
1731     int len=0;
1732     int val;
1733     while(*b){
1734         GET_UTF8(val, *b++, return -1;)
1735         len++;
1736     }
1737     return len;
1738 }
1739
1740 static int ascii_to_wc(AVIOContext *pb, const uint8_t *b)
1741 {
1742     int val;
1743     while(*b){
1744         GET_UTF8(val, *b++, return -1;)
1745         avio_wb16(pb, val);
1746     }
1747     avio_wb16(pb, 0x00);
1748     return 0;
1749 }
1750
1751 static uint16_t language_code(const char *str)
1752 {
1753     return (((str[0]-0x60) & 0x1F) << 10) + (((str[1]-0x60) & 0x1F) << 5) + ((str[2]-0x60) & 0x1F);
1754 }
1755
1756 static int mov_write_3gp_udta_tag(AVIOContext *pb, AVFormatContext *s,
1757                                   const char *tag, const char *str)
1758 {
1759     int64_t pos = avio_tell(pb);
1760     AVDictionaryEntry *t = av_dict_get(s->metadata, str, NULL, 0);
1761     if (!t || !utf8len(t->value))
1762         return 0;
1763     avio_wb32(pb, 0);   /* size */
1764     ffio_wfourcc(pb, tag); /* type */
1765     avio_wb32(pb, 0);   /* version + flags */
1766     if (!strcmp(tag, "yrrc"))
1767         avio_wb16(pb, atoi(t->value));
1768     else {
1769         avio_wb16(pb, language_code("eng")); /* language */
1770         avio_write(pb, t->value, strlen(t->value)+1); /* UTF8 string value */
1771         if (!strcmp(tag, "albm") &&
1772             (t = av_dict_get(s->metadata, "track", NULL, 0)))
1773             avio_w8(pb, atoi(t->value));
1774     }
1775     return updateSize(pb, pos);
1776 }
1777
1778 static int mov_write_chpl_tag(AVIOContext *pb, AVFormatContext *s)
1779 {
1780     int64_t pos = avio_tell(pb);
1781     int i, nb_chapters = FFMIN(s->nb_chapters, 255);
1782
1783     avio_wb32(pb, 0);            // size
1784     ffio_wfourcc(pb, "chpl");
1785     avio_wb32(pb, 0x01000000);   // version + flags
1786     avio_wb32(pb, 0);            // unknown
1787     avio_w8(pb, nb_chapters);
1788
1789     for (i = 0; i < nb_chapters; i++) {
1790         AVChapter *c = s->chapters[i];
1791         AVDictionaryEntry *t;
1792         avio_wb64(pb, av_rescale_q(c->start, c->time_base, (AVRational){1,10000000}));
1793
1794         if ((t = av_dict_get(c->metadata, "title", NULL, 0))) {
1795             int len = FFMIN(strlen(t->value), 255);
1796             avio_w8(pb, len);
1797             avio_write(pb, t->value, len);
1798         } else
1799             avio_w8(pb, 0);
1800     }
1801     return updateSize(pb, pos);
1802 }
1803
1804 static int mov_write_udta_tag(AVIOContext *pb, MOVMuxContext *mov,
1805                               AVFormatContext *s)
1806 {
1807     AVIOContext *pb_buf;
1808     int i, ret, size;
1809     uint8_t *buf;
1810
1811     for (i = 0; i < s->nb_streams; i++)
1812         if (mov->tracks[i].enc->flags & CODEC_FLAG_BITEXACT) {
1813             return 0;
1814         }
1815
1816     ret = avio_open_dyn_buf(&pb_buf);
1817     if(ret < 0)
1818         return ret;
1819
1820     if (mov->mode & MODE_3GP) {
1821         mov_write_3gp_udta_tag(pb_buf, s, "perf", "artist");
1822         mov_write_3gp_udta_tag(pb_buf, s, "titl", "title");
1823         mov_write_3gp_udta_tag(pb_buf, s, "auth", "author");
1824         mov_write_3gp_udta_tag(pb_buf, s, "gnre", "genre");
1825         mov_write_3gp_udta_tag(pb_buf, s, "dscp", "comment");
1826         mov_write_3gp_udta_tag(pb_buf, s, "albm", "album");
1827         mov_write_3gp_udta_tag(pb_buf, s, "cprt", "copyright");
1828         mov_write_3gp_udta_tag(pb_buf, s, "yrrc", "date");
1829     } else if (mov->mode == MODE_MOV) { // the title field breaks gtkpod with mp4 and my suspicion is that stuff is not valid in mp4
1830         mov_write_string_metadata(s, pb_buf, "\251ART", "artist"     , 0);
1831         mov_write_string_metadata(s, pb_buf, "\251nam", "title"      , 0);
1832         mov_write_string_metadata(s, pb_buf, "\251aut", "author"     , 0);
1833         mov_write_string_metadata(s, pb_buf, "\251alb", "album"      , 0);
1834         mov_write_string_metadata(s, pb_buf, "\251day", "date"       , 0);
1835         mov_write_string_metadata(s, pb_buf, "\251swr", "encoder"    , 0);
1836         mov_write_string_metadata(s, pb_buf, "\251des", "comment"    , 0);
1837         mov_write_string_metadata(s, pb_buf, "\251gen", "genre"      , 0);
1838         mov_write_string_metadata(s, pb_buf, "\251cpy", "copyright"  , 0);
1839     } else {
1840         /* iTunes meta data */
1841         mov_write_meta_tag(pb_buf, mov, s);
1842     }
1843
1844     if (s->nb_chapters)
1845         mov_write_chpl_tag(pb_buf, s);
1846
1847     if ((size = avio_close_dyn_buf(pb_buf, &buf)) > 0) {
1848         avio_wb32(pb, size+8);
1849         ffio_wfourcc(pb, "udta");
1850         avio_write(pb, buf, size);
1851     }
1852     av_free(buf);
1853
1854     return 0;
1855 }
1856
1857 static void mov_write_psp_udta_tag(AVIOContext *pb,
1858                                   const char *str, const char *lang, int type)
1859 {
1860     int len = utf8len(str)+1;
1861     if(len<=0)
1862         return;
1863     avio_wb16(pb, len*2+10);            /* size */
1864     avio_wb32(pb, type);                /* type */
1865     avio_wb16(pb, language_code(lang)); /* language */
1866     avio_wb16(pb, 0x01);                /* ? */
1867     ascii_to_wc(pb, str);
1868 }
1869
1870 static int mov_write_uuidusmt_tag(AVIOContext *pb, AVFormatContext *s)
1871 {
1872     AVDictionaryEntry *title = av_dict_get(s->metadata, "title", NULL, 0);
1873     int64_t pos, pos2;
1874
1875     if (title) {
1876         pos = avio_tell(pb);
1877         avio_wb32(pb, 0); /* size placeholder*/
1878         ffio_wfourcc(pb, "uuid");
1879         ffio_wfourcc(pb, "USMT");
1880         avio_wb32(pb, 0x21d24fce); /* 96 bit UUID */
1881         avio_wb32(pb, 0xbb88695c);
1882         avio_wb32(pb, 0xfac9c740);
1883
1884         pos2 = avio_tell(pb);
1885         avio_wb32(pb, 0); /* size placeholder*/
1886         ffio_wfourcc(pb, "MTDT");
1887         avio_wb16(pb, 4);
1888
1889         // ?
1890         avio_wb16(pb, 0x0C);                 /* size */
1891         avio_wb32(pb, 0x0B);                 /* type */
1892         avio_wb16(pb, language_code("und")); /* language */
1893         avio_wb16(pb, 0x0);                  /* ? */
1894         avio_wb16(pb, 0x021C);               /* data */
1895
1896         mov_write_psp_udta_tag(pb, LIBAVCODEC_IDENT,      "eng", 0x04);
1897         mov_write_psp_udta_tag(pb, title->value,          "eng", 0x01);
1898 //        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);
1899         mov_write_psp_udta_tag(pb, "2006/04/01 11:11:11", "und", 0x03);
1900
1901         updateSize(pb, pos2);
1902         return updateSize(pb, pos);
1903     }
1904
1905     return 0;
1906 }
1907
1908 static void build_chunks(MOVTrack *trk)
1909 {
1910     int i;
1911     MOVIentry *chunk= &trk->cluster[0];
1912     uint64_t chunkSize = chunk->size;
1913     chunk->chunkNum= 1;
1914     trk->chunkCount= 1;
1915     for(i=1; i<trk->entry; i++){
1916         if(chunk->pos + chunkSize == trk->cluster[i].pos &&
1917             chunkSize + trk->cluster[i].size < (1<<20)){
1918             chunkSize             += trk->cluster[i].size;
1919             chunk->samplesInChunk += trk->cluster[i].entries;
1920         }else{
1921             trk->cluster[i].chunkNum = chunk->chunkNum+1;
1922             chunk=&trk->cluster[i];
1923             chunkSize = chunk->size;
1924             trk->chunkCount++;
1925         }
1926     }
1927 }
1928
1929 static int mov_write_moov_tag(AVIOContext *pb, MOVMuxContext *mov,
1930                               AVFormatContext *s)
1931 {
1932     int i;
1933     int64_t pos = avio_tell(pb);
1934     avio_wb32(pb, 0); /* size placeholder*/
1935     ffio_wfourcc(pb, "moov");
1936
1937     for (i=0; i<mov->nb_streams; i++) {
1938         if (mov->tracks[i].entry <= 0 && !(mov->flags & FF_MOV_FLAG_FRAGMENT))
1939             continue;
1940
1941         mov->tracks[i].time = mov->time;
1942         mov->tracks[i].trackID = i+1;
1943
1944         build_chunks(&mov->tracks[i]);
1945     }
1946
1947     if (mov->chapter_track)
1948         for (i=0; i<s->nb_streams; i++) {
1949             mov->tracks[i].tref_tag = MKTAG('c','h','a','p');
1950             mov->tracks[i].tref_id = mov->tracks[mov->chapter_track].trackID;
1951         }
1952     for (i = 0; i < mov->nb_streams; i++) {
1953         if (mov->tracks[i].tag == MKTAG('r','t','p',' ')) {
1954             mov->tracks[i].tref_tag = MKTAG('h','i','n','t');
1955             mov->tracks[i].tref_id =
1956                 mov->tracks[mov->tracks[i].src_track].trackID;
1957         }
1958     }
1959
1960     mov_write_mvhd_tag(pb, mov);
1961     if (mov->mode != MODE_MOV && !mov->iods_skip)
1962         mov_write_iods_tag(pb, mov);
1963     for (i=0; i<mov->nb_streams; i++) {
1964         if (mov->tracks[i].entry > 0 || mov->flags & FF_MOV_FLAG_FRAGMENT) {
1965             mov_write_trak_tag(pb, mov, &(mov->tracks[i]), i < s->nb_streams ? s->streams[i] : NULL);
1966         }
1967     }
1968     if (mov->flags & FF_MOV_FLAG_FRAGMENT)
1969         mov_write_mvex_tag(pb, mov); /* QuickTime requires trak to precede this */
1970
1971     if (mov->mode == MODE_PSP)
1972         mov_write_uuidusmt_tag(pb, s);
1973     else
1974         mov_write_udta_tag(pb, mov, s);
1975
1976     return updateSize(pb, pos);
1977 }
1978
1979 static void param_write_int(AVIOContext *pb, const char *name, int value)
1980 {
1981     avio_printf(pb, "<param name=\"%s\" value=\"%d\" valuetype=\"data\"/>\n", name, value);
1982 }
1983
1984 static void param_write_string(AVIOContext *pb, const char *name, const char *value)
1985 {
1986     avio_printf(pb, "<param name=\"%s\" value=\"%s\" valuetype=\"data\"/>\n", name, value);
1987 }
1988
1989 static void param_write_hex(AVIOContext *pb, const char *name, const uint8_t *value, int len)
1990 {
1991     char buf[150];
1992     len = FFMIN(sizeof(buf)/2 - 1, len);
1993     ff_data_to_hex(buf, value, len, 0);
1994     buf[2*len] = '\0';
1995     avio_printf(pb, "<param name=\"%s\" value=\"%s\" valuetype=\"data\"/>\n", name, buf);
1996 }
1997
1998 static void write_h264_extradata(AVIOContext *pb, AVCodecContext *enc)
1999 {
2000     uint16_t sps_size, pps_size, len;
2001     char buf[150];
2002     sps_size = AV_RB16(&enc->extradata[6]);
2003     if (11 + sps_size > enc->extradata_size)
2004         return;
2005     pps_size = AV_RB16(&enc->extradata[9 + sps_size]);
2006     if (11 + sps_size + pps_size > enc->extradata_size)
2007         return;
2008     len = FFMIN(sizeof(buf)/2 - 1, sps_size);
2009     ff_data_to_hex(buf, &enc->extradata[8], len, 0);
2010     buf[2*len] = '\0';
2011     avio_printf(pb, "<param name=\"CodecPrivateData\" value=\"00000001%s", buf);
2012     len = FFMIN(sizeof(buf)/2 - 1, pps_size);
2013     ff_data_to_hex(buf, &enc->extradata[11 + sps_size], len, 0);
2014     buf[2*len] = '\0';
2015     avio_printf(pb, "00000001%s\" valuetype=\"data\"/>\n", buf);
2016 }
2017
2018 static int mov_write_isml_manifest(AVIOContext *pb, MOVMuxContext *mov)
2019 {
2020     int64_t pos = avio_tell(pb);
2021     int i;
2022     const uint8_t uuid[] = {
2023         0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
2024         0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
2025     };
2026
2027     avio_wb32(pb, 0);
2028     ffio_wfourcc(pb, "uuid");
2029     avio_write(pb, uuid, sizeof(uuid));
2030     avio_wb32(pb, 0);
2031
2032     avio_printf(pb, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
2033     avio_printf(pb, "<smil xmlns=\"http://www.w3.org/2001/SMIL20/Language\">\n");
2034     avio_printf(pb, "<head>\n");
2035     avio_printf(pb, "<meta name=\"creator\" content=\"%s\" />\n",
2036                     LIBAVFORMAT_IDENT);
2037     avio_printf(pb, "</head>\n");
2038     avio_printf(pb, "<body>\n");
2039     avio_printf(pb, "<switch>\n");
2040     for (i = 0; i < mov->nb_streams; i++) {
2041         MOVTrack *track = &mov->tracks[i];
2042         const char *type;
2043         /* track->trackID is initialized in write_moov, and thus isn't known
2044          * here yet */
2045         int track_id = i + 1;
2046
2047         if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) {
2048             type = "video";
2049         } else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) {
2050             type = "audio";
2051         } else {
2052             continue;
2053         }
2054         avio_printf(pb, "<%s systemBitrate=\"%d\">\n", type,
2055                                                        track->enc->bit_rate);
2056         param_write_int(pb, "systemBitrate", track->enc->bit_rate);
2057         param_write_int(pb, "trackID", track_id);
2058         if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) {
2059             if (track->enc->codec_id == CODEC_ID_H264 &&
2060                 track->enc->extradata_size >= 11 &&
2061                 track->enc->extradata[0] == 1) {
2062                 write_h264_extradata(pb, track->enc);
2063             } else {
2064                 param_write_hex(pb, "CodecPrivateData", track->enc->extradata,
2065                                 track->enc->extradata_size);
2066             }
2067             if (track->enc->codec_id == CODEC_ID_H264) {
2068                 param_write_string(pb, "FourCC", "H264");
2069             } else if (track->enc->codec_id == CODEC_ID_VC1) {
2070                 param_write_string(pb, "FourCC", "WVC1");
2071             }
2072             param_write_int(pb, "MaxWidth", track->enc->width);
2073             param_write_int(pb, "MaxHeight", track->enc->height);
2074             param_write_int(pb, "DisplayWidth", track->enc->width);
2075             param_write_int(pb, "DisplayHeight", track->enc->height);
2076         } else {
2077             if (track->enc->codec_id == CODEC_ID_AAC) {
2078                 param_write_string(pb, "FourCC", "AACL");
2079             } else if (track->enc->codec_id == CODEC_ID_WMAPRO) {
2080                 param_write_string(pb, "FourCC", "WMAP");
2081             }
2082             param_write_hex(pb, "CodecPrivateData", track->enc->extradata,
2083                             track->enc->extradata_size);
2084             param_write_int(pb, "AudioTag", ff_codec_get_tag(ff_codec_wav_tags,
2085                                                 track->enc->codec_id));
2086             param_write_int(pb, "Channels", track->enc->channels);
2087             param_write_int(pb, "SamplingRate", track->enc->sample_rate);
2088             param_write_int(pb, "BitsPerSample", 16);
2089             param_write_int(pb, "PacketSize", track->enc->block_align ?
2090                                               track->enc->block_align : 4);
2091         }
2092         avio_printf(pb, "</%s>\n", type);
2093     }
2094     avio_printf(pb, "</switch>\n");
2095     avio_printf(pb, "</body>\n");
2096     avio_printf(pb, "</smil>\n");
2097
2098     return updateSize(pb, pos);
2099 }
2100
2101 static int mov_write_mfhd_tag(AVIOContext *pb, MOVMuxContext *mov)
2102 {
2103     avio_wb32(pb, 16);
2104     ffio_wfourcc(pb, "mfhd");
2105     avio_wb32(pb, 0);
2106     avio_wb32(pb, mov->fragments);
2107     return 0;
2108 }
2109
2110 static int mov_write_tfhd_tag(AVIOContext *pb, MOVTrack *track,
2111                               int64_t moof_offset)
2112 {
2113     int64_t pos = avio_tell(pb);
2114     /* default-sample-size + default-sample-duration + base-data-offset */
2115     uint32_t flags = 0x19;
2116     if (!track->entry) {
2117         flags |= 0x010000; /* duration-is-empty */
2118     } else {
2119         flags |= 0x20; /* default-sample-flags-present */
2120     }
2121
2122     /* Don't set a default sample size when creating data for silverlight,
2123      * the player refuses to play files with that set. */
2124     if (track->mode == MODE_ISM)
2125         flags &= ~0x10;
2126
2127     avio_wb32(pb, 0); /* size placeholder */
2128     ffio_wfourcc(pb, "tfhd");
2129     avio_w8(pb, 0); /* version */
2130     avio_wb24(pb, flags);
2131
2132     avio_wb32(pb, track->trackID); /* track-id */
2133     if (flags & 0x01)
2134         avio_wb64(pb, moof_offset);
2135     if (flags & 0x08) {
2136         track->default_duration = track->audio_vbr ? track->enc->frame_size : 1;
2137         avio_wb32(pb, track->default_duration);
2138     }
2139     if (flags & 0x10) {
2140         track->default_size = track->entry ? track->cluster[0].size : 1;
2141         avio_wb32(pb, track->default_size);
2142     } else
2143         track->default_size = -1;
2144
2145     if (flags & 0x20) {
2146         track->default_sample_flags =
2147             track->enc->codec_type == AVMEDIA_TYPE_VIDEO ?
2148             0x01010000 : 0x02000000;
2149         avio_wb32(pb, track->default_sample_flags);
2150     }
2151
2152     return updateSize(pb, pos);
2153 }
2154
2155 static uint32_t get_sample_flags(MOVTrack *track, MOVIentry *entry)
2156 {
2157     return entry->flags & MOV_SYNC_SAMPLE ? 0x02000000 : 0x01010000;
2158 }
2159
2160 static int mov_write_trun_tag(AVIOContext *pb, MOVTrack *track)
2161 {
2162     int64_t pos = avio_tell(pb);
2163     uint32_t flags = 1; /* data-offset-present */
2164     int i;
2165
2166     for (i = 0; i < track->entry; i++) {
2167         int64_t duration = i + 1 == track->entry ?
2168             track->trackDuration - track->cluster[i].dts + track->start_dts :
2169             track->cluster[i + 1].dts - track->cluster[i].dts;
2170         if (duration != track->default_duration)
2171             flags |= 0x100; /* sample-duration-present */
2172         if (track->cluster[i].size != track->default_size)
2173             flags |= 0x200; /* sample-size-present */
2174         if (i > 0 && get_sample_flags(track, &track->cluster[i]) != track->default_sample_flags)
2175             flags |= 0x400; /* sample-flags-present */
2176     }
2177     if (!(flags & 0x400))
2178         flags |= 0x4; /* first-sample-flags-present */
2179     if (track->flags & MOV_TRACK_CTTS)
2180         flags |= 0x800; /* sample-composition-time-offsets-present */
2181
2182     avio_wb32(pb, 0); /* size placeholder */
2183     ffio_wfourcc(pb, "trun");
2184     avio_w8(pb, 0); /* version */
2185     avio_wb24(pb, flags);
2186
2187     avio_wb32(pb, track->entry); /* sample count */
2188     track->moof_size_offset = avio_tell(pb);
2189     avio_wb32(pb, 0); /* data offset */
2190     if (flags & 0x4) /* first sample flags */
2191         avio_wb32(pb, get_sample_flags(track, &track->cluster[0]));
2192
2193     for (i = 0; i < track->entry; i++) {
2194         int64_t duration = i + 1 == track->entry ?
2195             track->trackDuration - track->cluster[i].dts + track->start_dts :
2196             track->cluster[i + 1].dts - track->cluster[i].dts;
2197         if (flags & 0x100)
2198             avio_wb32(pb, duration);
2199         if (flags & 0x200)
2200             avio_wb32(pb, track->cluster[i].size);
2201         if (flags & 0x400)
2202             avio_wb32(pb, get_sample_flags(track, &track->cluster[i]));
2203         if (flags & 0x800)
2204             avio_wb32(pb, track->cluster[i].cts);
2205     }
2206
2207     return updateSize(pb, pos);
2208 }
2209
2210 static int mov_write_tfxd_tag(AVIOContext *pb, MOVTrack *track)
2211 {
2212     int64_t pos = avio_tell(pb);
2213     const uint8_t uuid[] = {
2214         0x6d, 0x1d, 0x9b, 0x05, 0x42, 0xd5, 0x44, 0xe6,
2215         0x80, 0xe2, 0x14, 0x1d, 0xaf, 0xf7, 0x57, 0xb2
2216     };
2217
2218     avio_wb32(pb, 0); /* size placeholder */
2219     ffio_wfourcc(pb, "uuid");
2220     avio_write(pb, uuid, sizeof(uuid));
2221     avio_w8(pb, 1);
2222     avio_wb24(pb, 0);
2223     avio_wb64(pb, track->frag_start);
2224     avio_wb64(pb, track->start_dts + track->trackDuration -
2225                   track->cluster[0].dts);
2226
2227     return updateSize(pb, pos);
2228 }
2229
2230 static int mov_write_tfrf_tag(AVIOContext *pb, MOVMuxContext *mov,
2231                               MOVTrack *track, int entry)
2232 {
2233     int n = track->nb_frag_info - 1 - entry, i;
2234     int size = 8 + 16 + 4 + 1 + 16*n;
2235     const uint8_t uuid[] = {
2236         0xd4, 0x80, 0x7e, 0xf2, 0xca, 0x39, 0x46, 0x95,
2237         0x8e, 0x54, 0x26, 0xcb, 0x9e, 0x46, 0xa7, 0x9f
2238     };
2239
2240     if (entry < 0)
2241         return 0;
2242
2243     avio_seek(pb, track->frag_info[entry].tfrf_offset, SEEK_SET);
2244     avio_wb32(pb, size);
2245     ffio_wfourcc(pb, "uuid");
2246     avio_write(pb, uuid, sizeof(uuid));
2247     avio_w8(pb, 1);
2248     avio_wb24(pb, 0);
2249     avio_w8(pb, n);
2250     for (i = 0; i < n; i++) {
2251         int index = entry + 1 + i;
2252         avio_wb64(pb, track->frag_info[index].time);
2253         avio_wb64(pb, track->frag_info[index].duration);
2254     }
2255     if (n < mov->ism_lookahead) {
2256         int free_size = 16*(mov->ism_lookahead - n);
2257         avio_wb32(pb, free_size);
2258         ffio_wfourcc(pb, "free");
2259         for (i = 0; i < free_size - 8; i++)
2260             avio_w8(pb, 0);
2261     }
2262
2263     return 0;
2264 }
2265
2266 static int mov_write_tfrf_tags(AVIOContext *pb, MOVMuxContext *mov,
2267                                MOVTrack *track)
2268 {
2269     int64_t pos = avio_tell(pb);
2270     int i;
2271     for (i = 0; i < mov->ism_lookahead; i++) {
2272         /* Update the tfrf tag for the last ism_lookahead fragments,
2273          * nb_frag_info - 1 is the next fragment to be written. */
2274         mov_write_tfrf_tag(pb, mov, track, track->nb_frag_info - 2 - i);
2275     }
2276     avio_seek(pb, pos, SEEK_SET);
2277     return 0;
2278 }
2279
2280 static int mov_write_traf_tag(AVIOContext *pb, MOVMuxContext *mov,
2281                               MOVTrack *track, int64_t moof_offset)
2282 {
2283     int64_t pos = avio_tell(pb);
2284     avio_wb32(pb, 0); /* size placeholder */
2285     ffio_wfourcc(pb, "traf");
2286
2287     mov_write_tfhd_tag(pb, track, moof_offset);
2288     mov_write_trun_tag(pb, track);
2289     if (mov->mode == MODE_ISM) {
2290         mov_write_tfxd_tag(pb, track);
2291
2292         if (mov->ism_lookahead) {
2293             int i, size = 16 + 4 + 1 + 16*mov->ism_lookahead;
2294
2295             track->tfrf_offset = avio_tell(pb);
2296             avio_wb32(pb, 8 + size);
2297             ffio_wfourcc(pb, "free");
2298             for (i = 0; i < size; i++)
2299                 avio_w8(pb, 0);
2300         }
2301     }
2302
2303     return updateSize(pb, pos);
2304 }
2305
2306 static int mov_write_moof_tag(AVIOContext *pb, MOVMuxContext *mov, int tracks)
2307 {
2308     int64_t pos = avio_tell(pb), end;
2309     int i, moof_size;
2310
2311     avio_wb32(pb, 0); /* size placeholder */
2312     ffio_wfourcc(pb, "moof");
2313
2314     mov_write_mfhd_tag(pb, mov);
2315     for (i = 0; i < mov->nb_streams; i++) {
2316         MOVTrack *track = &mov->tracks[i];
2317         if (tracks >= 0 && i != tracks)
2318             continue;
2319         if (!track->entry)
2320             continue;
2321         mov_write_traf_tag(pb, mov, track, pos);
2322     }
2323
2324     end = avio_tell(pb);
2325     moof_size = end - pos;
2326     for (i = 0; i < mov->nb_streams; i++) {
2327         MOVTrack *track = &mov->tracks[i];
2328         if (tracks >= 0 && i != tracks)
2329             continue;
2330         if (!track->entry)
2331             continue;
2332         avio_seek(pb, mov->tracks[i].moof_size_offset, SEEK_SET);
2333         avio_wb32(pb, moof_size + 8 + mov->tracks[i].data_offset);
2334     }
2335     avio_seek(pb, end, SEEK_SET);
2336
2337     return updateSize(pb, pos);
2338 }
2339
2340 static int mov_write_tfra_tag(AVIOContext *pb, MOVTrack *track)
2341 {
2342     int64_t pos = avio_tell(pb);
2343     int i;
2344
2345     avio_wb32(pb, 0); /* size placeholder */
2346     ffio_wfourcc(pb, "tfra");
2347     avio_w8(pb, 1); /* version */
2348     avio_wb24(pb, 0);
2349
2350     avio_wb32(pb, track->trackID);
2351     avio_wb32(pb, 0); /* length of traf/trun/sample num */
2352     avio_wb32(pb, track->nb_frag_info);
2353     for (i = 0; i < track->nb_frag_info; i++) {
2354         avio_wb64(pb, track->frag_info[i].time);
2355         avio_wb64(pb, track->frag_info[i].offset);
2356         avio_w8(pb, 1); /* traf number */
2357         avio_w8(pb, 1); /* trun number */
2358         avio_w8(pb, 1); /* sample number */
2359     }
2360
2361     return updateSize(pb, pos);
2362 }
2363
2364 static int mov_write_mfra_tag(AVIOContext *pb, MOVMuxContext *mov)
2365 {
2366     int64_t pos = avio_tell(pb);
2367     int i;
2368
2369     avio_wb32(pb, 0); /* size placeholder */
2370     ffio_wfourcc(pb, "mfra");
2371     /* An empty mfra atom is enough to indicate to the publishing point that
2372      * the stream has ended. */
2373     if (mov->flags & FF_MOV_FLAG_ISML)
2374         return updateSize(pb, pos);
2375
2376     for (i = 0; i < mov->nb_streams; i++) {
2377         MOVTrack *track = &mov->tracks[i];
2378         if (track->nb_frag_info)
2379             mov_write_tfra_tag(pb, track);
2380     }
2381
2382     avio_wb32(pb, 16);
2383     ffio_wfourcc(pb, "mfro");
2384     avio_wb32(pb, 0); /* version + flags */
2385     avio_wb32(pb, avio_tell(pb) + 4 - pos);
2386
2387     return updateSize(pb, pos);
2388 }
2389
2390 static int mov_write_mdat_tag(AVIOContext *pb, MOVMuxContext *mov)
2391 {
2392     avio_wb32(pb, 8);    // placeholder for extended size field (64 bit)
2393     ffio_wfourcc(pb, mov->mode == MODE_MOV ? "wide" : "free");
2394
2395     mov->mdat_pos = avio_tell(pb);
2396     avio_wb32(pb, 0); /* size placeholder*/
2397     ffio_wfourcc(pb, "mdat");
2398     return 0;
2399 }
2400
2401 /* TODO: This needs to be more general */
2402 static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s)
2403 {
2404     MOVMuxContext *mov = s->priv_data;
2405     int64_t pos = avio_tell(pb);
2406     int has_h264 = 0, has_video = 0;
2407     int minor = 0x200;
2408     int i;
2409
2410     for (i = 0; i < s->nb_streams; i++) {
2411         AVStream *st = s->streams[i];
2412         if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
2413             has_video = 1;
2414         if (st->codec->codec_id == CODEC_ID_H264)
2415             has_h264 = 1;
2416     }
2417
2418     avio_wb32(pb, 0); /* size */
2419     ffio_wfourcc(pb, "ftyp");
2420
2421     if (mov->mode == MODE_3GP) {
2422         ffio_wfourcc(pb, has_h264 ? "3gp6"  : "3gp4");
2423         minor =     has_h264 ?   0x100 :   0x200;
2424     } else if (mov->mode & MODE_3G2) {
2425         ffio_wfourcc(pb, has_h264 ? "3g2b"  : "3g2a");
2426         minor =     has_h264 ? 0x20000 : 0x10000;
2427     }else if (mov->mode == MODE_PSP)
2428         ffio_wfourcc(pb, "MSNV");
2429     else if (mov->mode == MODE_MP4)
2430         ffio_wfourcc(pb, "isom");
2431     else if (mov->mode == MODE_IPOD)
2432         ffio_wfourcc(pb, has_video ? "M4V ":"M4A ");
2433     else if (mov->mode == MODE_ISM)
2434         ffio_wfourcc(pb, "isml");
2435     else
2436         ffio_wfourcc(pb, "qt  ");
2437
2438     avio_wb32(pb, minor);
2439
2440     if(mov->mode == MODE_MOV)
2441         ffio_wfourcc(pb, "qt  ");
2442     else if (mov->mode == MODE_ISM) {
2443         ffio_wfourcc(pb, "piff");
2444         ffio_wfourcc(pb, "iso2");
2445     } else {
2446         ffio_wfourcc(pb, "isom");
2447         ffio_wfourcc(pb, "iso2");
2448         if(has_h264)
2449             ffio_wfourcc(pb, "avc1");
2450     }
2451
2452     if (mov->mode == MODE_3GP)
2453         ffio_wfourcc(pb, has_h264 ? "3gp6":"3gp4");
2454     else if (mov->mode & MODE_3G2)
2455         ffio_wfourcc(pb, has_h264 ? "3g2b":"3g2a");
2456     else if (mov->mode == MODE_PSP)
2457         ffio_wfourcc(pb, "MSNV");
2458     else if (mov->mode == MODE_MP4)
2459         ffio_wfourcc(pb, "mp41");
2460     return updateSize(pb, pos);
2461 }
2462
2463 static void mov_write_uuidprof_tag(AVIOContext *pb, AVFormatContext *s)
2464 {
2465     AVCodecContext *VideoCodec = s->streams[0]->codec;
2466     AVCodecContext *AudioCodec = s->streams[1]->codec;
2467     int AudioRate = AudioCodec->sample_rate;
2468     int FrameRate = ((VideoCodec->time_base.den) * (0x10000))/ (VideoCodec->time_base.num);
2469     int audio_kbitrate= AudioCodec->bit_rate / 1000;
2470     int video_kbitrate= FFMIN(VideoCodec->bit_rate / 1000, 800 - audio_kbitrate);
2471
2472     avio_wb32(pb, 0x94); /* size */
2473     ffio_wfourcc(pb, "uuid");
2474     ffio_wfourcc(pb, "PROF");
2475
2476     avio_wb32(pb, 0x21d24fce); /* 96 bit UUID */
2477     avio_wb32(pb, 0xbb88695c);
2478     avio_wb32(pb, 0xfac9c740);
2479
2480     avio_wb32(pb, 0x0);  /* ? */
2481     avio_wb32(pb, 0x3);  /* 3 sections ? */
2482
2483     avio_wb32(pb, 0x14); /* size */
2484     ffio_wfourcc(pb, "FPRF");
2485     avio_wb32(pb, 0x0);  /* ? */
2486     avio_wb32(pb, 0x0);  /* ? */
2487     avio_wb32(pb, 0x0);  /* ? */
2488
2489     avio_wb32(pb, 0x2c);  /* size */
2490     ffio_wfourcc(pb, "APRF");/* audio */
2491     avio_wb32(pb, 0x0);
2492     avio_wb32(pb, 0x2);   /* TrackID */
2493     ffio_wfourcc(pb, "mp4a");
2494     avio_wb32(pb, 0x20f);
2495     avio_wb32(pb, 0x0);
2496     avio_wb32(pb, audio_kbitrate);
2497     avio_wb32(pb, audio_kbitrate);
2498     avio_wb32(pb, AudioRate);
2499     avio_wb32(pb, AudioCodec->channels);
2500
2501     avio_wb32(pb, 0x34);  /* size */
2502     ffio_wfourcc(pb, "VPRF");   /* video */
2503     avio_wb32(pb, 0x0);
2504     avio_wb32(pb, 0x1);    /* TrackID */
2505     if (VideoCodec->codec_id == CODEC_ID_H264) {
2506         ffio_wfourcc(pb, "avc1");
2507         avio_wb16(pb, 0x014D);
2508         avio_wb16(pb, 0x0015);
2509     } else {
2510         ffio_wfourcc(pb, "mp4v");
2511         avio_wb16(pb, 0x0000);
2512         avio_wb16(pb, 0x0103);
2513     }
2514     avio_wb32(pb, 0x0);
2515     avio_wb32(pb, video_kbitrate);
2516     avio_wb32(pb, video_kbitrate);
2517     avio_wb32(pb, FrameRate);
2518     avio_wb32(pb, FrameRate);
2519     avio_wb16(pb, VideoCodec->width);
2520     avio_wb16(pb, VideoCodec->height);
2521     avio_wb32(pb, 0x010001); /* ? */
2522 }
2523
2524 static int mov_parse_mpeg2_frame(AVPacket *pkt, uint32_t *flags)
2525 {
2526     uint32_t c = -1;
2527     int i, closed_gop = 0;
2528
2529     for (i = 0; i < pkt->size - 4; i++) {
2530         c = (c<<8) + pkt->data[i];
2531         if (c == 0x1b8) { // gop
2532             closed_gop = pkt->data[i+4]>>6 & 0x01;
2533         } else if (c == 0x100) { // pic
2534             int temp_ref = (pkt->data[i+1]<<2) | (pkt->data[i+2]>>6);
2535             if (!temp_ref || closed_gop) // I picture is not reordered
2536                 *flags = MOV_SYNC_SAMPLE;
2537             else
2538                 *flags = MOV_PARTIAL_SYNC_SAMPLE;
2539             break;
2540         }
2541     }
2542     return 0;
2543 }
2544
2545 static int mov_flush_fragment(AVFormatContext *s)
2546 {
2547     MOVMuxContext *mov = s->priv_data;
2548     int i, first_track = -1;
2549     int64_t mdat_size = 0;
2550
2551     if (!(mov->flags & FF_MOV_FLAG_FRAGMENT))
2552         return 0;
2553
2554     if (!(mov->flags & FF_MOV_FLAG_EMPTY_MOOV) && mov->fragments == 0) {
2555         int64_t pos = avio_tell(s->pb);
2556
2557         for (i = 0; i < mov->nb_streams; i++)
2558             if (!mov->tracks[i].entry)
2559                 break;
2560         /* Don't write the initial moov unless all tracks have data */
2561         if (i < mov->nb_streams)
2562             return 0;
2563         avio_seek(s->pb, mov->mdat_pos, SEEK_SET);
2564         avio_wb32(s->pb, mov->mdat_size + 8);
2565         avio_seek(s->pb, pos, SEEK_SET);
2566         mov_write_moov_tag(s->pb, mov, s);
2567         mov->fragments++;
2568         mov->mdat_size = 0;
2569         for (i = 0; i < mov->nb_streams; i++) {
2570             if (mov->tracks[i].entry)
2571                 mov->tracks[i].frag_start += mov->tracks[i].start_dts +
2572                                              mov->tracks[i].trackDuration -
2573                                              mov->tracks[i].cluster[0].dts;
2574             mov->tracks[i].entry = 0;
2575         }
2576         avio_flush(s->pb);
2577         return 0;
2578     }
2579
2580     for (i = 0; i < mov->nb_streams; i++) {
2581         MOVTrack *track = &mov->tracks[i];
2582         if (mov->flags & FF_MOV_FLAG_SEPARATE_MOOF)
2583             track->data_offset = 0;
2584         else
2585             track->data_offset = mdat_size;
2586         if (!track->mdat_buf)
2587             continue;
2588         mdat_size += avio_tell(track->mdat_buf);
2589         if (first_track < 0)
2590             first_track = i;
2591     }
2592
2593     if (!mdat_size)
2594         return 0;
2595
2596     for (i = 0; i < mov->nb_streams; i++) {
2597         MOVTrack *track = &mov->tracks[i];
2598         int buf_size, write_moof = 1, moof_tracks = -1;
2599         uint8_t *buf;
2600         int64_t duration = 0;
2601
2602         if (track->entry)
2603             duration = track->start_dts + track->trackDuration -
2604                        track->cluster[0].dts;
2605         if (mov->flags & FF_MOV_FLAG_SEPARATE_MOOF) {
2606             if (!track->mdat_buf)
2607                 continue;
2608             mdat_size = avio_tell(track->mdat_buf);
2609             moof_tracks = i;
2610         } else {
2611             write_moof = i == first_track;
2612         }
2613
2614         if (write_moof) {
2615             MOVFragmentInfo *info;
2616             avio_flush(s->pb);
2617             track->nb_frag_info++;
2618             track->frag_info = av_realloc(track->frag_info,
2619                                           sizeof(*track->frag_info) *
2620                                           track->nb_frag_info);
2621             info = &track->frag_info[track->nb_frag_info - 1];
2622             info->offset   = avio_tell(s->pb);
2623             info->time     = mov->tracks[i].frag_start;
2624             info->duration = duration;
2625             mov_write_tfrf_tags(s->pb, mov, track);
2626
2627             mov_write_moof_tag(s->pb, mov, moof_tracks);
2628             info->tfrf_offset = track->tfrf_offset;
2629             mov->fragments++;
2630
2631             avio_wb32(s->pb, mdat_size + 8);
2632             ffio_wfourcc(s->pb, "mdat");
2633         }
2634
2635         if (track->entry)
2636             track->frag_start += duration;
2637         track->entry = 0;
2638         if (!track->mdat_buf)
2639             continue;
2640         buf_size = avio_close_dyn_buf(track->mdat_buf, &buf);
2641         track->mdat_buf = NULL;
2642
2643         avio_write(s->pb, buf, buf_size);
2644         av_free(buf);
2645     }
2646
2647     mov->mdat_size = 0;
2648
2649     avio_flush(s->pb);
2650     return 0;
2651 }
2652
2653 static int mov_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
2654 {
2655     MOVMuxContext *mov = s->priv_data;
2656     AVIOContext *pb = s->pb;
2657     MOVTrack *trk = &mov->tracks[pkt->stream_index];
2658     AVCodecContext *enc = trk->enc;
2659     unsigned int samplesInChunk = 0;
2660     int size= pkt->size;
2661     uint8_t *reformatted_data = NULL;
2662
2663     if (!s->pb->seekable && !(mov->flags & FF_MOV_FLAG_EMPTY_MOOV))
2664         return 0; /* Can't handle that */
2665
2666     if (!size) return 0; /* Discard 0 sized packets */
2667
2668     if ((mov->max_fragment_duration && trk->entry &&
2669          av_rescale_q(pkt->dts - trk->cluster[0].dts,
2670                       s->streams[pkt->stream_index]->time_base,
2671                       AV_TIME_BASE_Q) >= mov->max_fragment_duration) ||
2672          (mov->max_fragment_size && mov->mdat_size + size >= mov->max_fragment_size) ||
2673          (mov->flags & FF_MOV_FLAG_FRAG_KEYFRAME &&
2674           enc->codec_type == AVMEDIA_TYPE_VIDEO &&
2675           trk->entry && pkt->flags & AV_PKT_FLAG_KEY)) {
2676         mov_flush_fragment(s);
2677     }
2678
2679     if (mov->flags & FF_MOV_FLAG_FRAGMENT && mov->fragments > 0) {
2680         if (!trk->mdat_buf) {
2681             int ret;
2682             if ((ret = avio_open_dyn_buf(&trk->mdat_buf)) < 0)
2683                 return ret;
2684         }
2685         pb = trk->mdat_buf;
2686     }
2687
2688     if (enc->codec_id == CODEC_ID_AMR_NB) {
2689         /* We must find out how many AMR blocks there are in one packet */
2690         static uint16_t packed_size[16] =
2691             {13, 14, 16, 18, 20, 21, 27, 32, 6, 0, 0, 0, 0, 0, 0, 1};
2692         int len = 0;
2693
2694         while (len < size && samplesInChunk < 100) {
2695             len += packed_size[(pkt->data[len] >> 3) & 0x0F];
2696             samplesInChunk++;
2697         }
2698         if(samplesInChunk > 1){
2699             av_log(s, AV_LOG_ERROR, "fatal error, input is not a single packet, implement a AVParser for it\n");
2700             return -1;
2701         }
2702     } else if (enc->codec_id == CODEC_ID_ADPCM_MS ||
2703                enc->codec_id == CODEC_ID_ADPCM_IMA_WAV) {
2704         samplesInChunk = enc->frame_size;
2705     } else if (trk->sampleSize)
2706         samplesInChunk = size/trk->sampleSize;
2707     else
2708         samplesInChunk = 1;
2709
2710     /* copy extradata if it exists */
2711     if (trk->vosLen == 0 && enc->extradata_size > 0) {
2712         trk->vosLen = enc->extradata_size;
2713         trk->vosData = av_malloc(trk->vosLen);
2714         memcpy(trk->vosData, enc->extradata, trk->vosLen);
2715     }
2716
2717     if (enc->codec_id == CODEC_ID_H264 && trk->vosLen > 0 && *(uint8_t *)trk->vosData != 1) {
2718         /* from x264 or from bytestream h264 */
2719         /* nal reformating needed */
2720         if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams) {
2721             ff_avc_parse_nal_units_buf(pkt->data, &reformatted_data,
2722                                        &size);
2723             avio_write(pb, reformatted_data, size);
2724         } else {
2725             size = ff_avc_parse_nal_units(pb, pkt->data, pkt->size);
2726         }
2727     } else if (enc->codec_id == CODEC_ID_AAC && pkt->size > 2 &&
2728                (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) {
2729         av_log(s, AV_LOG_ERROR, "malformated aac bitstream, use -absf aac_adtstoasc\n");
2730         return -1;
2731     } else {
2732         avio_write(pb, pkt->data, size);
2733     }
2734
2735     if ((enc->codec_id == CODEC_ID_DNXHD ||
2736          enc->codec_id == CODEC_ID_AC3) && !trk->vosLen) {
2737         /* copy frame to create needed atoms */
2738         trk->vosLen = size;
2739         trk->vosData = av_malloc(size);
2740         if (!trk->vosData)
2741             return AVERROR(ENOMEM);
2742         memcpy(trk->vosData, pkt->data, size);
2743     }
2744
2745     if (!(trk->entry % MOV_INDEX_CLUSTER_SIZE)) {
2746         trk->cluster = av_realloc_f(trk->cluster, sizeof(*trk->cluster), (trk->entry + MOV_INDEX_CLUSTER_SIZE));
2747         if (!trk->cluster)
2748             return -1;
2749     }
2750
2751     trk->cluster[trk->entry].pos = avio_tell(pb) - size;
2752     trk->cluster[trk->entry].samplesInChunk = samplesInChunk;
2753     trk->cluster[trk->entry].chunkNum = 0;
2754     trk->cluster[trk->entry].size = size;
2755     trk->cluster[trk->entry].entries = samplesInChunk;
2756     trk->cluster[trk->entry].dts = pkt->dts;
2757     if (!trk->entry && trk->start_dts != AV_NOPTS_VALUE) {
2758         /* First packet of a new fragment. We already wrote the duration
2759          * of the last packet of the previous fragment based on trackDuration,
2760          * which might not exactly match our dts. Therefore adjust the dts
2761          * of this packet to be what the previous packets duration implies. */
2762         trk->cluster[trk->entry].dts = trk->start_dts + trk->trackDuration;
2763     }
2764     if (trk->start_dts == AV_NOPTS_VALUE)
2765         trk->start_dts = pkt->dts;
2766     trk->trackDuration = pkt->dts - trk->start_dts + pkt->duration;
2767
2768     if (pkt->pts == AV_NOPTS_VALUE) {
2769         av_log(s, AV_LOG_WARNING, "pts has no value\n");
2770         pkt->pts = pkt->dts;
2771     }
2772     if (pkt->dts != pkt->pts)
2773         trk->flags |= MOV_TRACK_CTTS;
2774     trk->cluster[trk->entry].cts = pkt->pts - pkt->dts;
2775     trk->cluster[trk->entry].flags = 0;
2776     if (pkt->flags & AV_PKT_FLAG_KEY) {
2777         if (mov->mode == MODE_MOV && enc->codec_id == CODEC_ID_MPEG2VIDEO &&
2778             trk->entry > 0) { // force sync sample for the first key frame
2779             mov_parse_mpeg2_frame(pkt, &trk->cluster[trk->entry].flags);
2780             if (trk->cluster[trk->entry].flags & MOV_PARTIAL_SYNC_SAMPLE)
2781                 trk->flags |= MOV_TRACK_STPS;
2782         } else {
2783             trk->cluster[trk->entry].flags = MOV_SYNC_SAMPLE;
2784         }
2785         if (trk->cluster[trk->entry].flags & MOV_SYNC_SAMPLE)
2786             trk->hasKeyframes++;
2787     }
2788     trk->entry++;
2789     trk->sampleCount += samplesInChunk;
2790     mov->mdat_size += size;
2791
2792     avio_flush(pb);
2793
2794     if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams)
2795         ff_mov_add_hinted_packet(s, pkt, trk->hint_track, trk->entry,
2796                                  reformatted_data, size);
2797     av_free(reformatted_data);
2798     return 0;
2799 }
2800
2801 int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
2802 {
2803     if (!pkt) {
2804         mov_flush_fragment(s);
2805         return 1;
2806     } else {
2807         return mov_write_packet_internal(s, pkt);
2808     }
2809 }
2810
2811 // QuickTime chapters involve an additional text track with the chapter names
2812 // as samples, and a tref pointing from the other tracks to the chapter one.
2813 static void mov_create_chapter_track(AVFormatContext *s, int tracknum)
2814 {
2815     MOVMuxContext *mov = s->priv_data;
2816     MOVTrack *track = &mov->tracks[tracknum];
2817     AVPacket pkt = { .stream_index = tracknum, .flags = AV_PKT_FLAG_KEY };
2818     int i, len;
2819
2820     track->mode = mov->mode;
2821     track->tag = MKTAG('t','e','x','t');
2822     track->timescale = MOV_TIMESCALE;
2823     track->enc = avcodec_alloc_context3(NULL);
2824     track->enc->codec_type = AVMEDIA_TYPE_SUBTITLE;
2825
2826     for (i = 0; i < s->nb_chapters; i++) {
2827         AVChapter *c = s->chapters[i];
2828         AVDictionaryEntry *t;
2829
2830         int64_t end = av_rescale_q(c->end, c->time_base, (AVRational){1,MOV_TIMESCALE});
2831         pkt.pts = pkt.dts = av_rescale_q(c->start, c->time_base, (AVRational){1,MOV_TIMESCALE});
2832         pkt.duration = end - pkt.dts;
2833
2834         if ((t = av_dict_get(c->metadata, "title", NULL, 0))) {
2835             len = strlen(t->value);
2836             pkt.size = len+2;
2837             pkt.data = av_malloc(pkt.size);
2838             AV_WB16(pkt.data, len);
2839             memcpy(pkt.data+2, t->value, len);
2840             ff_mov_write_packet(s, &pkt);
2841             av_freep(&pkt.data);
2842         }
2843     }
2844 }
2845
2846 static int mov_write_header(AVFormatContext *s)
2847 {
2848     AVIOContext *pb = s->pb;
2849     MOVMuxContext *mov = s->priv_data;
2850     AVDictionaryEntry *t;
2851     int i, hint_track = 0;
2852
2853     /* Non-seekable output is ok if EMPTY_MOOV is set, or if using the ismv
2854      * format (which sets EMPTY_MOOV later in this function). If ism_lookahead
2855      * is enabled, we don't support non-seekable output at all. */
2856     if (!s->pb->seekable &&
2857         ((!(mov->flags & FF_MOV_FLAG_EMPTY_MOOV) &&
2858           !(s->oformat && !strcmp(s->oformat->name, "ismv")))
2859          || mov->ism_lookahead)) {
2860         av_log(s, AV_LOG_ERROR, "muxer does not support non seekable output\n");
2861         return -1;
2862     }
2863
2864     /* Default mode == MP4 */
2865     mov->mode = MODE_MP4;
2866
2867     if (s->oformat != NULL) {
2868         if (!strcmp("3gp", s->oformat->name)) mov->mode = MODE_3GP;
2869         else if (!strcmp("3g2", s->oformat->name)) mov->mode = MODE_3GP|MODE_3G2;
2870         else if (!strcmp("mov", s->oformat->name)) mov->mode = MODE_MOV;
2871         else if (!strcmp("psp", s->oformat->name)) mov->mode = MODE_PSP;
2872         else if (!strcmp("ipod",s->oformat->name)) mov->mode = MODE_IPOD;
2873         else if (!strcmp("ismv",s->oformat->name)) mov->mode = MODE_ISM;
2874
2875         mov_write_ftyp_tag(pb,s);
2876         if (mov->mode == MODE_PSP) {
2877             if (s->nb_streams != 2) {
2878                 av_log(s, AV_LOG_ERROR, "PSP mode need one video and one audio stream\n");
2879                 return -1;
2880             }
2881             mov_write_uuidprof_tag(pb,s);
2882         }
2883     }
2884
2885     mov->nb_streams = s->nb_streams;
2886     if (mov->mode & (MODE_MOV|MODE_IPOD) && s->nb_chapters)
2887         mov->chapter_track = mov->nb_streams++;
2888
2889     if (mov->flags & FF_MOV_FLAG_RTP_HINT) {
2890         /* Add hint tracks for each audio and video stream */
2891         hint_track = mov->nb_streams;
2892         for (i = 0; i < s->nb_streams; i++) {
2893             AVStream *st = s->streams[i];
2894             if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO ||
2895                 st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
2896                 mov->nb_streams++;
2897             }
2898         }
2899     }
2900
2901     mov->tracks = av_mallocz(mov->nb_streams*sizeof(*mov->tracks));
2902     if (!mov->tracks)
2903         return AVERROR(ENOMEM);
2904
2905     for(i=0; i<s->nb_streams; i++){
2906         AVStream *st= s->streams[i];
2907         MOVTrack *track= &mov->tracks[i];
2908         AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL,0);
2909
2910         track->enc = st->codec;
2911         track->language = ff_mov_iso639_to_lang(lang?lang->value:"und", mov->mode!=MODE_MOV);
2912         if (track->language < 0)
2913             track->language = 0;
2914         track->mode = mov->mode;
2915         track->tag = mov_find_codec_tag(s, track);
2916         if (!track->tag) {
2917             av_log(s, AV_LOG_ERROR, "track %d: could not find tag, "
2918                    "codec not currently supported in container\n", i);
2919             goto error;
2920         }
2921         /* If hinting of this track is enabled by a later hint track,
2922          * this is updated. */
2923         track->hint_track = -1;
2924         track->start_dts = AV_NOPTS_VALUE;
2925         if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO){
2926             if (track->tag == MKTAG('m','x','3','p') || track->tag == MKTAG('m','x','3','n') ||
2927                 track->tag == MKTAG('m','x','4','p') || track->tag == MKTAG('m','x','4','n') ||
2928                 track->tag == MKTAG('m','x','5','p') || track->tag == MKTAG('m','x','5','n')) {
2929                 if (st->codec->width != 720 || (st->codec->height != 608 && st->codec->height != 512)) {
2930                     av_log(s, AV_LOG_ERROR, "D-10/IMX must use 720x608 or 720x512 video resolution\n");
2931                     goto error;
2932                 }
2933                 track->height = track->tag>>24 == 'n' ? 486 : 576;
2934             }
2935             track->timescale = st->codec->time_base.den;
2936             if (track->mode == MODE_MOV && track->timescale > 100000)
2937                 av_log(s, AV_LOG_WARNING,
2938                        "WARNING codec timebase is very high. If duration is too long,\n"
2939                        "file may not be playable by quicktime. Specify a shorter timebase\n"
2940                        "or choose different container.\n");
2941         }else if(st->codec->codec_type == AVMEDIA_TYPE_AUDIO){
2942             track->timescale = st->codec->sample_rate;
2943             if(!st->codec->frame_size && !av_get_bits_per_sample(st->codec->codec_id)) {
2944                 av_log(s, AV_LOG_ERROR, "track %d: codec frame size is not set\n", i);
2945                 goto error;
2946             }else if(st->codec->codec_id == CODEC_ID_ADPCM_MS ||
2947                      st->codec->codec_id == CODEC_ID_ADPCM_IMA_WAV){
2948                 if (!st->codec->block_align) {
2949                     av_log(s, AV_LOG_ERROR, "track %d: codec block align is not set for adpcm\n", i);
2950                     goto error;
2951                 }
2952                 track->sampleSize = st->codec->block_align;
2953             }else if(st->codec->frame_size > 1){ /* assume compressed audio */
2954                 track->audio_vbr = 1;
2955             }else{
2956                 st->codec->frame_size = 1;
2957                 track->sampleSize = (av_get_bits_per_sample(st->codec->codec_id) >> 3) * st->codec->channels;
2958             }
2959             if (track->mode != MODE_MOV) {
2960                 if (track->timescale > UINT16_MAX) {
2961                     av_log(s, AV_LOG_ERROR, "track %d: output format does not support "
2962                            "sample rate %dhz\n", i, track->timescale);
2963                     goto error;
2964                 }
2965                 if (track->enc->codec_id == CODEC_ID_MP3 && track->timescale < 16000) {
2966                     av_log(s, AV_LOG_ERROR, "track %d: muxing mp3 at %dhz is not supported\n",
2967                            i, track->enc->sample_rate);
2968                     goto error;
2969                 }
2970             }
2971         }else if(st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE){
2972             track->timescale = st->codec->time_base.den;
2973         }
2974         if (!track->height)
2975             track->height = st->codec->height;
2976         /* The ism specific timescale isn't mandatory, but is assumed by
2977          * some tools, such as mp4split. */
2978         if (mov->mode == MODE_ISM)
2979             track->timescale = 10000000;
2980
2981         avpriv_set_pts_info(st, 64, 1, track->timescale);
2982
2983         /* copy extradata if it exists */
2984         if (st->codec->extradata_size) {
2985             track->vosLen  = st->codec->extradata_size;
2986             track->vosData = av_malloc(track->vosLen);
2987             memcpy(track->vosData, st->codec->extradata, track->vosLen);
2988         }
2989     }
2990
2991     if (mov->mode == MODE_ISM) {
2992         /* If no fragmentation options have been set, set a default. */
2993         if (!(mov->flags & (FF_MOV_FLAG_FRAG_KEYFRAME |
2994                             FF_MOV_FLAG_FRAG_CUSTOM)) &&
2995             !mov->max_fragment_duration && !mov->max_fragment_size)
2996             mov->max_fragment_duration = 5000000;
2997         mov->flags |= FF_MOV_FLAG_EMPTY_MOOV | FF_MOV_FLAG_SEPARATE_MOOF;
2998     }
2999
3000     if(mov->reserved_moov_size){
3001         mov->reserved_moov_pos= avio_tell(pb);
3002         avio_skip(pb, mov->reserved_moov_size);
3003     }
3004
3005     /* Set the FRAGMENT flag if any of the fragmentation methods are
3006      * enabled. */
3007     if (mov->max_fragment_duration || mov->max_fragment_size ||
3008         mov->flags & (FF_MOV_FLAG_EMPTY_MOOV |
3009                       FF_MOV_FLAG_FRAG_KEYFRAME |
3010                       FF_MOV_FLAG_FRAG_CUSTOM))
3011         mov->flags |= FF_MOV_FLAG_FRAGMENT;
3012
3013     if (!(mov->flags & FF_MOV_FLAG_EMPTY_MOOV))
3014         mov_write_mdat_tag(pb, mov);
3015
3016     if (t = av_dict_get(s->metadata, "creation_time", NULL, 0))
3017         mov->time = ff_iso8601_to_unix_time(t->value);
3018     if (mov->time)
3019         mov->time += 0x7C25B080; // 1970 based -> 1904 based
3020
3021     if (mov->chapter_track)
3022         mov_create_chapter_track(s, mov->chapter_track);
3023
3024     if (mov->flags & FF_MOV_FLAG_RTP_HINT) {
3025         /* Initialize the hint tracks for each audio and video stream */
3026         for (i = 0; i < s->nb_streams; i++) {
3027             AVStream *st = s->streams[i];
3028             if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO ||
3029                 st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
3030                 ff_mov_init_hinting(s, hint_track, i);
3031                 hint_track++;
3032             }
3033         }
3034     }
3035
3036     avio_flush(pb);
3037
3038     if (mov->flags & FF_MOV_FLAG_ISML)
3039         mov_write_isml_manifest(pb, mov);
3040
3041     if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV) {
3042         mov_write_moov_tag(pb, mov, s);
3043         mov->fragments++;
3044     }
3045
3046     return 0;
3047  error:
3048     av_freep(&mov->tracks);
3049     return -1;
3050 }
3051
3052 static int mov_write_trailer(AVFormatContext *s)
3053 {
3054     MOVMuxContext *mov = s->priv_data;
3055     AVIOContext *pb = s->pb;
3056     int res = 0;
3057     int i;
3058
3059     int64_t moov_pos = avio_tell(pb);
3060
3061     if (!(mov->flags & FF_MOV_FLAG_FRAGMENT)) {
3062         /* Write size of mdat tag */
3063         if (mov->mdat_size + 8 <= UINT32_MAX) {
3064             avio_seek(pb, mov->mdat_pos, SEEK_SET);
3065             avio_wb32(pb, mov->mdat_size + 8);
3066         } else {
3067             /* overwrite 'wide' placeholder atom */
3068             avio_seek(pb, mov->mdat_pos - 8, SEEK_SET);
3069             /* special value: real atom size will be 64 bit value after
3070              * tag field */
3071             avio_wb32(pb, 1);
3072             ffio_wfourcc(pb, "mdat");
3073             avio_wb64(pb, mov->mdat_size + 16);
3074         }
3075         avio_seek(pb, mov->reserved_moov_size ? mov->reserved_moov_pos : moov_pos, SEEK_SET);
3076
3077         mov_write_moov_tag(pb, mov, s);
3078         if(mov->reserved_moov_size){
3079             int64_t size=  mov->reserved_moov_size - (avio_tell(pb) - mov->reserved_moov_pos);
3080             if(size < 8){
3081                 av_log(s, AV_LOG_ERROR, "reserved_moov_size is too small, needed %"PRId64" additional\n", 8-size);
3082                 return -1;
3083             }
3084             avio_wb32(pb, size);
3085             ffio_wfourcc(pb, "free");
3086             for(i=0; i<size; i++)
3087                 avio_w8(pb, 0);
3088             avio_seek(pb, moov_pos, SEEK_SET);
3089         }
3090     } else {
3091         mov_flush_fragment(s);
3092         mov_write_mfra_tag(pb, mov);
3093     }
3094
3095     if (mov->chapter_track)
3096         av_freep(&mov->tracks[mov->chapter_track].enc);
3097
3098     for (i=0; i<mov->nb_streams; i++) {
3099         if (mov->tracks[i].tag == MKTAG('r','t','p',' '))
3100             ff_mov_close_hinting(&mov->tracks[i]);
3101         av_freep(&mov->tracks[i].cluster);
3102         av_freep(&mov->tracks[i].frag_info);
3103
3104         if(mov->tracks[i].vosLen) av_free(mov->tracks[i].vosData);
3105
3106     }
3107
3108     avio_flush(pb);
3109
3110     av_freep(&mov->tracks);
3111
3112     return res;
3113 }
3114
3115 #if CONFIG_MOV_MUXER
3116 MOV_CLASS(mov)
3117 AVOutputFormat ff_mov_muxer = {
3118     .name              = "mov",
3119     .long_name         = NULL_IF_CONFIG_SMALL("MOV format"),
3120     .extensions        = "mov",
3121     .priv_data_size    = sizeof(MOVMuxContext),
3122     .audio_codec       = CODEC_ID_AAC,
3123 #if CONFIG_LIBX264_ENCODER
3124     .video_codec       = CODEC_ID_H264,
3125 #else
3126     .video_codec       = CODEC_ID_MPEG4,
3127 #endif
3128     .write_header      = mov_write_header,
3129     .write_packet      = ff_mov_write_packet,
3130     .write_trailer     = mov_write_trailer,
3131     .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH,
3132     .codec_tag = (const AVCodecTag* const []){codec_movvideo_tags, codec_movaudio_tags, 0},
3133     .priv_class = &mov_muxer_class,
3134 };
3135 #endif
3136 #if CONFIG_TGP_MUXER
3137 MOV_CLASS(tgp)
3138 AVOutputFormat ff_tgp_muxer = {
3139     .name              = "3gp",
3140     .long_name         = NULL_IF_CONFIG_SMALL("3GP format"),
3141     .extensions        = "3gp",
3142     .priv_data_size    = sizeof(MOVMuxContext),
3143     .audio_codec       = CODEC_ID_AMR_NB,
3144     .video_codec       = CODEC_ID_H263,
3145     .write_header      = mov_write_header,
3146     .write_packet      = ff_mov_write_packet,
3147     .write_trailer     = mov_write_trailer,
3148     .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH,
3149     .codec_tag = (const AVCodecTag* const []){codec_3gp_tags, 0},
3150     .priv_class = &tgp_muxer_class,
3151 };
3152 #endif
3153 #if CONFIG_MP4_MUXER
3154 MOV_CLASS(mp4)
3155 AVOutputFormat ff_mp4_muxer = {
3156     .name              = "mp4",
3157     .long_name         = NULL_IF_CONFIG_SMALL("MP4 format"),
3158     .mime_type         = "application/mp4",
3159     .extensions        = "mp4",
3160     .priv_data_size    = sizeof(MOVMuxContext),
3161     .audio_codec       = CODEC_ID_AAC,
3162 #if CONFIG_LIBX264_ENCODER
3163     .video_codec       = CODEC_ID_H264,
3164 #else
3165     .video_codec       = CODEC_ID_MPEG4,
3166 #endif
3167     .write_header      = mov_write_header,
3168     .write_packet      = ff_mov_write_packet,
3169     .write_trailer     = mov_write_trailer,
3170     .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH,
3171     .codec_tag = (const AVCodecTag* const []){ff_mp4_obj_type, 0},
3172     .priv_class = &mp4_muxer_class,
3173 };
3174 #endif
3175 #if CONFIG_PSP_MUXER
3176 MOV_CLASS(psp)
3177 AVOutputFormat ff_psp_muxer = {
3178     .name              = "psp",
3179     .long_name         = NULL_IF_CONFIG_SMALL("PSP MP4 format"),
3180     .extensions        = "mp4,psp",
3181     .priv_data_size    = sizeof(MOVMuxContext),
3182     .audio_codec       = CODEC_ID_AAC,
3183 #if CONFIG_LIBX264_ENCODER
3184     .video_codec       = CODEC_ID_H264,
3185 #else
3186     .video_codec       = CODEC_ID_MPEG4,
3187 #endif
3188     .write_header      = mov_write_header,
3189     .write_packet      = ff_mov_write_packet,
3190     .write_trailer     = mov_write_trailer,
3191     .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH,
3192     .codec_tag = (const AVCodecTag* const []){ff_mp4_obj_type, 0},
3193     .priv_class = &psp_muxer_class,
3194 };
3195 #endif
3196 #if CONFIG_TG2_MUXER
3197 MOV_CLASS(tg2)
3198 AVOutputFormat ff_tg2_muxer = {
3199     .name              = "3g2",
3200     .long_name         = NULL_IF_CONFIG_SMALL("3GP2 format"),
3201     .extensions        = "3g2",
3202     .priv_data_size    = sizeof(MOVMuxContext),
3203     .audio_codec       = CODEC_ID_AMR_NB,
3204     .video_codec       = CODEC_ID_H263,
3205     .write_header      = mov_write_header,
3206     .write_packet      = ff_mov_write_packet,
3207     .write_trailer     = mov_write_trailer,
3208     .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH,
3209     .codec_tag = (const AVCodecTag* const []){codec_3gp_tags, 0},
3210     .priv_class = &tg2_muxer_class,
3211 };
3212 #endif
3213 #if CONFIG_IPOD_MUXER
3214 MOV_CLASS(ipod)
3215 AVOutputFormat ff_ipod_muxer = {
3216     .name              = "ipod",
3217     .long_name         = NULL_IF_CONFIG_SMALL("iPod H.264 MP4 format"),
3218     .mime_type         = "application/mp4",
3219     .extensions        = "m4v,m4a",
3220     .priv_data_size    = sizeof(MOVMuxContext),
3221     .audio_codec       = CODEC_ID_AAC,
3222     .video_codec       = CODEC_ID_H264,
3223     .write_header      = mov_write_header,
3224     .write_packet      = ff_mov_write_packet,
3225     .write_trailer     = mov_write_trailer,
3226     .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH,
3227     .codec_tag = (const AVCodecTag* const []){codec_ipod_tags, 0},
3228     .priv_class = &ipod_muxer_class,
3229 };
3230 #endif
3231 #if CONFIG_ISMV_MUXER
3232 MOV_CLASS(ismv)
3233 AVOutputFormat ff_ismv_muxer = {
3234     .name              = "ismv",
3235     .long_name         = NULL_IF_CONFIG_SMALL("ISMV/ISMA (Smooth Streaming) format"),
3236     .mime_type         = "application/mp4",
3237     .extensions        = "ismv,isma",
3238     .priv_data_size    = sizeof(MOVMuxContext),
3239     .audio_codec       = CODEC_ID_AAC,
3240     .video_codec       = CODEC_ID_H264,
3241     .write_header      = mov_write_header,
3242     .write_packet      = ff_mov_write_packet,
3243     .write_trailer     = mov_write_trailer,
3244     .flags             = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH,
3245     .codec_tag         = (const AVCodecTag* const []){ff_mp4_obj_type, 0},
3246     .priv_class        = &ismv_muxer_class,
3247 };
3248 #endif