]> git.sesse.net Git - ffmpeg/blob - libavformat/movenc.c
bit-exact
[ffmpeg] / libavformat / movenc.c
1 /*
2  * MOV, 3GP, MP4 encoder.
3  * Copyright (c) 2003 Thomas Raivio.
4  * Copyright (c) 2004 Gildas Bazin <gbazin at videolan dot org>.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 #include "avformat.h"
21 #include "avi.h"
22 #include "avio.h"
23
24 #undef NDEBUG
25 #include <assert.h>
26
27 #define MOV_INDEX_CLUSTER_SIZE 16384
28 #define globalTimescale 1000
29
30 #define MODE_MP4 0
31 #define MODE_MOV 1
32 #define MODE_3GP 2
33
34 typedef struct MOVIentry {
35     unsigned int flags, pos, size;
36     unsigned int samplesInChunk;
37     char         key_frame;
38     unsigned int entries;
39 } MOVIentry;
40
41 typedef struct MOVIndex {
42     int         mode;
43     int         entry;
44     int         mdat_size;
45     int         ents_allocated;
46     long        timescale;
47     long        time;
48     long        trackDuration;
49     long        sampleCount;
50     long        sampleDuration;
51     int         hasKeyframes;
52     int         trackID;
53     AVCodecContext *enc;
54
55     int         vosLen;
56     uint8_t     *vosData;
57     MOVIentry** cluster;
58 } MOVTrack;
59
60 typedef struct {
61     int     mode;
62     long    time;
63     int     nb_streams;
64     int     mdat_written;
65     offset_t mdat_pos;
66     long    timescale;
67     MOVTrack tracks[MAX_STREAMS];
68 } MOVContext;
69
70 static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack* track);
71
72 //FIXME supprt 64bit varaint with wide placeholders
73 static int updateSize (ByteIOContext *pb, int pos)
74 {
75     long curpos = url_ftell(pb);
76     url_fseek(pb, pos, SEEK_SET);
77     put_be32(pb, curpos - pos); /* rewrite size */
78     url_fseek(pb, curpos, SEEK_SET);
79
80     return curpos - pos;
81 }
82
83 /* Chunk offset atom */
84 static int mov_write_stco_tag(ByteIOContext *pb, MOVTrack* track)
85 {
86     int i;
87     int pos = url_ftell(pb);
88     put_be32(pb, 0); /* size */
89     put_tag(pb, "stco");
90     put_be32(pb, 0); /* version & flags */
91     put_be32(pb, track->entry); /* entry count */
92     for (i=0; i<track->entry; i++) {
93         int cl = i / MOV_INDEX_CLUSTER_SIZE;
94         int id = i % MOV_INDEX_CLUSTER_SIZE;
95         put_be32(pb, track->cluster[cl][id].pos);
96     }
97     return updateSize (pb, pos);
98 }
99
100 /* Sample size atom */
101 static int mov_write_stsz_tag(ByteIOContext *pb, MOVTrack* track)
102 {
103     int equalChunks = 1;
104     int i, j, entries = 0, tst = -1, oldtst = -1;
105
106     int pos = url_ftell(pb);
107     put_be32(pb, 0); /* size */
108     put_tag(pb, "stsz");
109     put_be32(pb, 0); /* version & flags */
110
111     for (i=0; i<track->entry; i++) {
112         int cl = i / MOV_INDEX_CLUSTER_SIZE;
113         int id = i % MOV_INDEX_CLUSTER_SIZE;
114         tst = track->cluster[cl][id].size/track->cluster[cl][id].entries;
115         if(oldtst != -1 && tst != oldtst) {
116             equalChunks = 0;
117         }
118         oldtst = tst;
119         entries += track->cluster[cl][id].entries;
120     }
121     if (equalChunks) {
122         int sSize = track->cluster[0][0].size/track->cluster[0][0].entries;
123         put_be32(pb, sSize); // sample size 
124         put_be32(pb, entries); // sample count
125     }
126     else {
127         put_be32(pb, 0); // sample size 
128         put_be32(pb, entries); // sample count 
129         for (i=0; i<track->entry; i++) {
130             int cl = i / MOV_INDEX_CLUSTER_SIZE;
131             int id = i % MOV_INDEX_CLUSTER_SIZE;
132             for ( j=0; j<track->cluster[cl][id].entries; j++) {
133                 put_be32(pb, track->cluster[cl][id].size /
134                          track->cluster[cl][id].entries);
135             }
136         }
137     }
138     return updateSize (pb, pos);
139 }
140
141 /* Sample to chunk atom */
142 static int mov_write_stsc_tag(ByteIOContext *pb, MOVTrack* track)
143 {
144     int index = 0, oldval = -1, i, entryPos, curpos;
145
146     int pos = url_ftell(pb);
147     put_be32(pb, 0); /* size */
148     put_tag(pb, "stsc");
149     put_be32(pb, 0); // version & flags 
150     entryPos = url_ftell(pb);
151     put_be32(pb, track->entry); // entry count 
152     for (i=0; i<track->entry; i++) {
153         int cl = i / MOV_INDEX_CLUSTER_SIZE;
154         int id = i % MOV_INDEX_CLUSTER_SIZE;
155         if(oldval != track->cluster[cl][id].samplesInChunk)
156         {
157             put_be32(pb, i+1); // first chunk 
158             put_be32(pb, track->cluster[cl][id].samplesInChunk); // samples per chunk
159             put_be32(pb, 0x1); // sample description index 
160             oldval = track->cluster[cl][id].samplesInChunk;
161             index++;
162         }
163     }
164     curpos = url_ftell(pb);
165     url_fseek(pb, entryPos, SEEK_SET);
166     put_be32(pb, index); // rewrite size 
167     url_fseek(pb, curpos, SEEK_SET);
168
169     return updateSize (pb, pos);
170 }
171
172 /* Sync sample atom */
173 static int mov_write_stss_tag(ByteIOContext *pb, MOVTrack* track)
174 {
175     long curpos;
176     int i, index = 0, entryPos;
177     int pos = url_ftell(pb);
178     put_be32(pb, 0); // size 
179     put_tag(pb, "stss");
180     put_be32(pb, 0); // version & flags 
181     entryPos = url_ftell(pb);
182     put_be32(pb, track->entry); // entry count 
183     for (i=0; i<track->entry; i++) {
184         int cl = i / MOV_INDEX_CLUSTER_SIZE;
185         int id = i % MOV_INDEX_CLUSTER_SIZE;
186         if(track->cluster[cl][id].key_frame == 1) {
187             put_be32(pb, i+1);
188             index++;
189         }
190     }
191     curpos = url_ftell(pb);
192     url_fseek(pb, entryPos, SEEK_SET);
193     put_be32(pb, index); // rewrite size 
194     url_fseek(pb, curpos, SEEK_SET);
195     return updateSize (pb, pos);
196 }
197
198 static int mov_write_damr_tag(ByteIOContext *pb)
199 {
200     put_be32(pb, 0x11); /* size */
201     put_tag(pb, "damr");
202     put_tag(pb, "FFMP");
203     put_byte(pb, 0);
204
205     put_be16(pb, 0x80); /* Mode set (all modes for AMR_NB) */
206     put_be16(pb, 0xa); /* Mode change period (no restriction) */
207     //put_be16(pb, 0x81ff); /* Mode set (all modes for AMR_NB) */
208     //put_be16(pb, 1); /* Mode change period (no restriction) */
209     return 0x11;
210 }
211
212 static int mov_write_wave_tag(ByteIOContext *pb, MOVTrack* track)
213 {
214     int pos = url_ftell(pb);
215
216     put_be32(pb, 0);     /* size */
217     put_tag(pb, "wave");
218
219     put_be32(pb, 12);    /* size */
220     put_tag(pb, "frma");
221     put_tag(pb, "mp4a");
222
223     put_be32(pb, 12);    /* size */
224     put_tag(pb, "mp4a");
225     put_be32(pb, 0);
226
227     mov_write_esds_tag(pb, track);
228
229     put_be32(pb, 12);    /* size */
230     put_tag(pb, "srcq");
231     put_be32(pb, 0x40);
232
233     put_be32(pb, 8);     /* size */
234     put_be32(pb, 0);     /* null tag */
235
236     return updateSize (pb, pos);
237 }
238
239 const CodecTag codec_movaudio_tags[] = {
240     { CODEC_ID_PCM_MULAW, MKTAG('u', 'l', 'a', 'w') },
241     { CODEC_ID_PCM_ALAW, MKTAG('a', 'l', 'a', 'w') },
242     { CODEC_ID_ADPCM_IMA_QT, MKTAG('i', 'm', 'a', '4') },
243     { CODEC_ID_MACE3, MKTAG('M', 'A', 'C', '3') },
244     { CODEC_ID_MACE6, MKTAG('M', 'A', 'C', '6') },
245     { CODEC_ID_AAC, MKTAG('m', 'p', '4', 'a') },
246     { CODEC_ID_AMR_NB, MKTAG('s', 'a', 'm', 'r') },
247     { CODEC_ID_PCM_S16BE, MKTAG('t', 'w', 'o', 's') },
248     { CODEC_ID_PCM_S16LE, MKTAG('s', 'o', 'w', 't') },
249     { CODEC_ID_MP3, MKTAG('.', 'm', 'p', '3') },
250     { 0, 0 },
251 };
252
253 static int mov_write_audio_tag(ByteIOContext *pb, MOVTrack* track)
254 {
255     int pos = url_ftell(pb), tag;
256     
257     put_be32(pb, 0); /* size */
258
259     tag = codec_get_tag(codec_movaudio_tags, track->enc->codec_id);
260     // if no mac fcc found, try with Microsoft tags
261     if (!tag)
262     {
263         int tmp = codec_get_tag(codec_wav_tags, track->enc->codec_id);
264         if (tmp)
265             tag = MKTAG('m', 's', ((tmp >> 8) & 0xff), (tmp & 0xff));
266     }
267     if (!tag)
268         put_tag(pb, "    ");
269     else
270         put_le32(pb, tag); // store it byteswapped
271
272     put_be32(pb, 0); /* Reserved */
273     put_be16(pb, 0); /* Reserved */
274     put_be16(pb, 1); /* Data-reference index, XXX  == 1 */
275
276     /* SoundDescription */
277     if(track->mode == MODE_MOV && track->enc->codec_id == CODEC_ID_AAC)
278         put_be16(pb, 1); /* Version 1 */
279     else
280         put_be16(pb, 0); /* Version 0 */
281     put_be16(pb, 0); /* Revision level */
282     put_be32(pb, 0); /* Reserved */
283
284     put_be16(pb, track->enc->channels); /* Number of channels */
285     /* TODO: Currently hard-coded to 16-bit, there doesn't seem
286                  to be a good way to get number of bits of audio */
287     put_be16(pb, 0x10); /* Reserved */
288     put_be16(pb, 0); /* compression ID (= 0) */
289     put_be16(pb, 0); /* packet size (= 0) */
290     put_be16(pb, track->timescale); /* Time scale */
291     put_be16(pb, 0); /* Reserved */
292
293     if(track->mode == MODE_MOV && track->enc->codec_id == CODEC_ID_AAC)
294     {
295         /* SoundDescription V1 extended info */
296         put_be32(pb, track->enc->frame_size); /* Samples per packet  */
297         put_be32(pb, 1536); /* Bytes per packet */
298         put_be32(pb, 2); /* Bytes per frame */
299         put_be32(pb, 2); /* Bytes per sample */
300     }
301
302     if(track->enc->codec_id == CODEC_ID_AAC) {
303         if( track->mode == MODE_MOV ) mov_write_wave_tag(pb, track);
304         else mov_write_esds_tag(pb, track);
305     }
306     if(track->enc->codec_id == CODEC_ID_AMR_NB)
307         mov_write_damr_tag(pb);
308     return updateSize (pb, pos);
309 }
310
311 static int mov_write_d263_tag(ByteIOContext *pb)
312 {
313     put_be32(pb, 0xf); /* size */
314     put_tag(pb, "d263");
315     put_tag(pb, "FFMP");
316     put_be16(pb, 0x0a);
317     put_byte(pb, 0);
318     return 0xf;
319 }
320
321 /* TODO: No idea about these values */
322 static int mov_write_svq3_tag(ByteIOContext *pb)
323 {
324     put_be32(pb, 0x15);
325     put_tag(pb, "SMI ");
326     put_tag(pb, "SEQH");
327     put_be32(pb, 0x5);
328     put_be32(pb, 0xe2c0211d);
329     put_be32(pb, 0xc0000000);
330     put_byte(pb, 0);   
331     return 0x15;
332 }
333
334 static unsigned int descrLength(unsigned int len)
335 {
336     if (len < 0x00000080)
337         return 2 + len;
338     else if (len < 0x00004000)
339         return 3 + len;
340     else if(len < 0x00200000)
341         return 4 + len;
342     else
343         return 5 + len;
344 }
345
346 static void putDescr(ByteIOContext *pb, int tag, int size)
347 {
348     uint32_t len;
349     uint8_t  vals[4];
350
351     len = size;
352     vals[3] = (uint8_t)(len & 0x7f);
353     len >>= 7;
354     vals[2] = (uint8_t)((len & 0x7f) | 0x80); 
355     len >>= 7;
356     vals[1] = (uint8_t)((len & 0x7f) | 0x80); 
357     len >>= 7;
358     vals[0] = (uint8_t)((len & 0x7f) | 0x80);
359
360     put_byte(pb, tag); // DescriptorTag
361
362     if (size < 0x00000080)
363     {
364         put_byte(pb, vals[3]);
365     }
366     else if (size < 0x00004000)
367     {
368         put_byte(pb, vals[2]);
369         put_byte(pb, vals[3]);
370     }
371     else if (size < 0x00200000)
372     {
373         put_byte(pb, vals[1]);
374         put_byte(pb, vals[2]);
375         put_byte(pb, vals[3]);
376     }
377     else if (size < 0x10000000)
378     {
379         put_byte(pb, vals[0]);
380         put_byte(pb, vals[1]);
381         put_byte(pb, vals[2]);
382         put_byte(pb, vals[3]);
383     }
384 }
385
386 static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack* track) // Basic
387 {
388     int decoderSpecificInfoLen = track->vosLen ? descrLength(track->vosLen):0;
389     int pos = url_ftell(pb);
390
391     put_be32(pb, 0);               // size
392     put_tag(pb, "esds");
393     put_be32(pb, 0);               // Version
394
395     // ES descriptor
396     putDescr(pb, 0x03, 3 + descrLength(13 + decoderSpecificInfoLen) +
397              descrLength(1));
398     put_be16(pb, 0x0001);          // ID (= 1)
399     put_byte(pb, 0x00);            // flags (= no flags)
400
401     // DecoderConfig descriptor
402     putDescr(pb, 0x04, 13 + decoderSpecificInfoLen);
403
404     if(track->enc->codec_id == CODEC_ID_AAC)
405         put_byte(pb, 0x40);        // Object type indication
406     else if(track->enc->codec_id == CODEC_ID_MPEG4)
407         put_byte(pb, 0x20);        // Object type indication (Visual 14496-2)
408
409     if(track->enc->codec_type == CODEC_TYPE_AUDIO)
410         put_byte(pb, 0x15);            // flags (= Audiostream)
411     else
412         put_byte(pb, 0x11);            // flags (= Visualstream)
413
414     put_byte(pb, 0x0);             // Buffersize DB (24 bits)
415     put_be16(pb, 0x0dd2);          // Buffersize DB
416
417     // TODO: find real values for these
418     put_be32(pb, 0x0002e918);     // maxbitrate
419     put_be32(pb, 0x00017e6b);     // avg bitrate
420
421     if (track->vosLen)
422     {
423         // DecoderSpecific info descriptor
424         putDescr(pb, 0x05, track->vosLen);
425         put_buffer(pb, track->vosData, track->vosLen);
426     }
427
428     // SL descriptor
429     putDescr(pb, 0x06, 1);
430     put_byte(pb, 0x02);
431     return updateSize (pb, pos);
432 }
433
434 const CodecTag codec_movvideo_tags[] = {
435     { CODEC_ID_SVQ1, MKTAG('S', 'V', 'Q', '1') },
436     { CODEC_ID_SVQ3, MKTAG('S', 'V', 'Q', '3') },
437     { CODEC_ID_MPEG4, MKTAG('m', 'p', '4', 'v') },
438     { CODEC_ID_H263, MKTAG('s', '2', '6', '3') },
439     { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'c', ' ') },
440     { 0, 0 },
441 };
442
443 static int mov_write_video_tag(ByteIOContext *pb, MOVTrack* track)
444 {
445     int pos = url_ftell(pb), tag;
446
447     put_be32(pb, 0); /* size */
448
449     tag = codec_get_tag(codec_movvideo_tags, track->enc->codec_id);
450     // if no mac fcc found, try with Microsoft tags
451     if (!tag)
452         tag = codec_get_tag(codec_bmp_tags, track->enc->codec_id);
453     if (!tag)
454         put_tag(pb, "    ");
455     else
456         put_le32(pb, tag); // store it byteswapped
457
458     put_be32(pb, 0); /* Reserved */
459     put_be16(pb, 0); /* Reserved */
460     put_be16(pb, 1); /* Data-reference index */
461
462     put_be32(pb, 0); /* Reserved (= 02000c) */
463     put_be32(pb, 0); /* Reserved ("SVis")*/
464     put_be32(pb, 0); /* Reserved */
465     put_be32(pb, 0); /* Reserved (400)*/
466     put_be16(pb, track->enc->width); /* Video width */
467     put_be16(pb, track->enc->height); /* Video height */
468     put_be32(pb, 0x00480000); /* Reserved */
469     put_be32(pb, 0x00480000); /* Reserved */
470     put_be32(pb, 0); /* Data size (= 0) */
471     put_be16(pb, 1); /* Frame count (= 1) */
472     
473     put_be32(pb, 0); /* Reserved */
474     put_be32(pb, 0); /* Reserved */
475     put_be32(pb, 0); /* Reserved */
476     put_be32(pb, 0); /* Reserved */
477     put_be32(pb, 0); /* Reserved */
478     put_be32(pb, 0); /* Reserved */
479     put_be32(pb, 0); /* Reserved */
480     put_be32(pb, 0); /* Reserved */
481     
482     put_be16(pb, 0x18); /* Reserved */
483     put_be16(pb, 0xffff); /* Reserved */
484     if(track->enc->codec_id == CODEC_ID_MPEG4)
485         mov_write_esds_tag(pb, track);
486     else if(track->enc->codec_id == CODEC_ID_H263)
487         mov_write_d263_tag(pb);
488     else if(track->enc->codec_id == CODEC_ID_SVQ3)
489         mov_write_svq3_tag(pb);    
490
491     return updateSize (pb, pos);
492 }
493
494 static int mov_write_stsd_tag(ByteIOContext *pb, MOVTrack* track)
495 {
496     int pos = url_ftell(pb);
497     put_be32(pb, 0); /* size */
498     put_tag(pb, "stsd");
499     put_be32(pb, 0); /* version & flags */
500     put_be32(pb, 1); /* entry count */
501     if (track->enc->codec_type == CODEC_TYPE_VIDEO)
502         mov_write_video_tag(pb, track);
503     else if (track->enc->codec_type == CODEC_TYPE_AUDIO)
504         mov_write_audio_tag(pb, track);
505     return updateSize(pb, pos);
506 }
507
508 /* TODO?: Currently all samples/frames seem to have same duration */
509 /* Time to sample atom */
510 static int mov_write_stts_tag(ByteIOContext *pb, MOVTrack* track)
511 {
512     put_be32(pb, 0x18); /* size */
513     put_tag(pb, "stts");
514     put_be32(pb, 0); /* version & flags */
515     put_be32(pb, 1); /* entry count */
516
517     put_be32(pb, track->sampleCount); /* sample count */
518     put_be32(pb, track->sampleDuration); /* sample duration */
519     return 0x18;
520 }
521
522 static int mov_write_dref_tag(ByteIOContext *pb)
523 {
524     put_be32(pb, 28); /* size */
525     put_tag(pb, "dref");
526     put_be32(pb, 0); /* version & flags */
527     put_be32(pb, 1); /* entry count */
528
529     put_be32(pb, 0xc); /* size */
530     put_tag(pb, "url ");
531     put_be32(pb, 1); /* version & flags */
532
533     return 28;
534 }
535
536 static int mov_write_stbl_tag(ByteIOContext *pb, MOVTrack* track)
537 {
538     int pos = url_ftell(pb);
539     put_be32(pb, 0); /* size */
540     put_tag(pb, "stbl");
541     mov_write_stsd_tag(pb, track);
542     mov_write_stts_tag(pb, track);
543     if (track->enc->codec_type == CODEC_TYPE_VIDEO &&
544         track->hasKeyframes)
545         mov_write_stss_tag(pb, track);
546     mov_write_stsc_tag(pb, track);
547     mov_write_stsz_tag(pb, track);
548     mov_write_stco_tag(pb, track);
549     return updateSize(pb, pos);
550 }
551
552 static int mov_write_dinf_tag(ByteIOContext *pb)
553 {
554     int pos = url_ftell(pb);
555     put_be32(pb, 0); /* size */
556     put_tag(pb, "dinf");
557     mov_write_dref_tag(pb);
558     return updateSize(pb, pos);
559 }
560
561 static int mov_write_smhd_tag(ByteIOContext *pb)
562 {
563     put_be32(pb, 16); /* size */
564     put_tag(pb, "smhd");
565     put_be32(pb, 0); /* version & flags */
566     put_be16(pb, 0); /* reserved (balance, normally = 0) */
567     put_be16(pb, 0); /* reserved */
568     return 16;
569 }
570
571 static int mov_write_vmhd_tag(ByteIOContext *pb)
572 {
573     put_be32(pb, 0x14); /* size (always 0x14) */
574     put_tag(pb, "vmhd");
575     put_be32(pb, 0x01); /* version & flags */
576     put_be64(pb, 0); /* reserved (graphics mode = copy) */
577     return 0x14;
578 }
579
580 static int mov_write_hdlr_tag(ByteIOContext *pb, MOVTrack* track)
581 {
582     char *descr, *hdlr, *hdlr_type;
583     int pos = url_ftell(pb);
584     
585     if (!track) { /* no media --> data handler */
586         hdlr = "dhlr";
587         hdlr_type = "url ";
588         descr = "DataHandler";
589     } else {
590         hdlr = (track->mode == MODE_MOV) ? "mhlr" : "\0\0\0\0";
591         if (track->enc->codec_type == CODEC_TYPE_VIDEO) {
592             hdlr_type = "vide";
593             descr = "VideoHandler";
594         } else {
595             hdlr_type = "soun";
596             descr = "SoundHandler";
597         }
598     }
599     
600     put_be32(pb, 0); /* size */
601     put_tag(pb, "hdlr");
602     put_be32(pb, 0); /* Version & flags */
603     put_buffer(pb, hdlr, 4); /* handler */
604     put_tag(pb, hdlr_type); /* handler type */
605     put_be32(pb ,0); /* reserved */
606     put_be32(pb ,0); /* reserved */
607     put_be32(pb ,0); /* reserved */
608     put_byte(pb, strlen(descr)); /* string counter */
609     put_buffer(pb, descr, strlen(descr)); /* handler description */
610     return updateSize(pb, pos);
611 }
612
613 static int mov_write_minf_tag(ByteIOContext *pb, MOVTrack* track)
614 {
615     int pos = url_ftell(pb);
616     put_be32(pb, 0); /* size */
617     put_tag(pb, "minf");
618     if(track->enc->codec_type == CODEC_TYPE_VIDEO)
619         mov_write_vmhd_tag(pb);
620     else
621         mov_write_smhd_tag(pb);
622     if (track->mode == MODE_MOV) /* FIXME: Why do it for MODE_MOV only ? */
623         mov_write_hdlr_tag(pb, NULL);
624     mov_write_dinf_tag(pb);
625     mov_write_stbl_tag(pb, track);
626     return updateSize(pb, pos);
627 }
628
629 static int mov_write_mdhd_tag(ByteIOContext *pb, MOVTrack* track)
630 {
631     put_be32(pb, 32); /* size */
632     put_tag(pb, "mdhd");
633     put_be32(pb, 0); /* Version & flags */
634     put_be32(pb, track->time); /* creation time */
635     put_be32(pb, track->time); /* modification time */
636     put_be32(pb, track->timescale); /* time scale (sample rate for audio) */ 
637     put_be32(pb, track->trackDuration); /* duration */
638     put_be16(pb, 0); /* language, 0 = english */
639     put_be16(pb, 0); /* reserved (quality) */
640     return 32;
641 }
642
643 static int mov_write_mdia_tag(ByteIOContext *pb, MOVTrack* track)
644 {
645     int pos = url_ftell(pb);
646     put_be32(pb, 0); /* size */
647     put_tag(pb, "mdia");
648     mov_write_mdhd_tag(pb, track);
649     mov_write_hdlr_tag(pb, track);
650     mov_write_minf_tag(pb, track);
651     return updateSize(pb, pos);
652 }
653
654 static int mov_write_tkhd_tag(ByteIOContext *pb, MOVTrack* track)
655 {
656     int64_t maxTrackLenTemp;
657     put_be32(pb, 0x5c); /* size (always 0x5c) */
658     put_tag(pb, "tkhd");
659     put_be32(pb, 0xf); /* version & flags (track enabled) */
660     put_be32(pb, track->time); /* creation time */
661     put_be32(pb, track->time); /* modification time */
662     put_be32(pb, track->trackID); /* track-id */
663     put_be32(pb, 0); /* reserved */
664     maxTrackLenTemp = ((int64_t)globalTimescale*(int64_t)track->trackDuration)/(int64_t)track->timescale;
665     put_be32(pb, (long)maxTrackLenTemp); /* duration */
666
667     put_be32(pb, 0); /* reserved */
668     put_be32(pb, 0); /* reserved */
669     put_be32(pb, 0x0); /* reserved (Layer & Alternate group) */
670     /* Volume, only for audio */
671     if(track->enc->codec_type == CODEC_TYPE_AUDIO)
672         put_be16(pb, 0x0100);
673     else
674         put_be16(pb, 0);
675     put_be16(pb, 0); /* reserved */
676
677     /* Matrix structure */
678     put_be32(pb, 0x00010000); /* reserved */
679     put_be32(pb, 0x0); /* reserved */
680     put_be32(pb, 0x0); /* reserved */
681     put_be32(pb, 0x0); /* reserved */
682     put_be32(pb, 0x00010000); /* reserved */
683     put_be32(pb, 0x0); /* reserved */
684     put_be32(pb, 0x0); /* reserved */
685     put_be32(pb, 0x0); /* reserved */
686     put_be32(pb, 0x40000000); /* reserved */
687
688     /* Track width and height, for visual only */
689     if(track->enc->codec_type == CODEC_TYPE_VIDEO) {
690         double sample_aspect_ratio = av_q2d(track->enc->sample_aspect_ratio);
691         if( !sample_aspect_ratio ) sample_aspect_ratio = 1;
692         put_be32(pb, sample_aspect_ratio * track->enc->width*0x10000);
693         put_be32(pb, track->enc->height*0x10000);
694     }
695     else {
696         put_be32(pb, 0);
697         put_be32(pb, 0);
698     }
699     return 0x5c;
700 }
701
702 static int mov_write_trak_tag(ByteIOContext *pb, MOVTrack* track)
703 {
704     int pos = url_ftell(pb);
705     put_be32(pb, 0); /* size */
706     put_tag(pb, "trak");
707     mov_write_tkhd_tag(pb, track);
708     mov_write_mdia_tag(pb, track);
709     return updateSize(pb, pos);
710 }
711
712 /* TODO: Not sorted out, but not necessary either */
713 static int mov_write_iods_tag(ByteIOContext *pb, MOVContext *mov)
714 {
715     put_be32(pb, 0x15); /* size */
716     put_tag(pb, "iods");
717     put_be32(pb, 0);    /* version & flags */
718     put_be16(pb, 0x1007);
719     put_byte(pb, 0);
720     put_be16(pb, 0x4fff);
721     put_be16(pb, 0xfffe);
722     put_be16(pb, 0x01ff);
723     return 0x15;
724 }
725
726 static int mov_write_mvhd_tag(ByteIOContext *pb, MOVContext *mov)
727 {
728     int maxTrackID = 1, maxTrackLen = 0, i;
729     int64_t maxTrackLenTemp;
730
731     put_be32(pb, 0x6c); /* size (always 0x6c) */
732     put_tag(pb, "mvhd");
733     put_be32(pb, 0); /* version & flags */
734     put_be32(pb, mov->time); /* creation time */
735     put_be32(pb, mov->time); /* modification time */
736     put_be32(pb, mov->timescale); /* timescale */
737     for (i=0; i<MAX_STREAMS; i++) {
738         if(mov->tracks[i].entry > 0) {
739             maxTrackLenTemp = ((int64_t)globalTimescale*(int64_t)mov->tracks[i].trackDuration)/(int64_t)mov->tracks[i].timescale;
740             if(maxTrackLen < maxTrackLenTemp)
741                 maxTrackLen = maxTrackLenTemp;
742             if(maxTrackID < mov->tracks[i].trackID)
743                 maxTrackID = mov->tracks[i].trackID;
744         }
745     }
746     put_be32(pb, maxTrackLen); /* duration of longest track */
747
748     put_be32(pb, 0x00010000); /* reserved (preferred rate) 1.0 = normal */
749     put_be16(pb, 0x0100); /* reserved (preferred volume) 1.0 = normal */
750     put_be16(pb, 0); /* reserved */
751     put_be32(pb, 0); /* reserved */
752     put_be32(pb, 0); /* reserved */
753
754     /* Matrix structure */
755     put_be32(pb, 0x00010000); /* reserved */
756     put_be32(pb, 0x0); /* reserved */
757     put_be32(pb, 0x0); /* reserved */
758     put_be32(pb, 0x0); /* reserved */
759     put_be32(pb, 0x00010000); /* reserved */
760     put_be32(pb, 0x0); /* reserved */
761     put_be32(pb, 0x0); /* reserved */
762     put_be32(pb, 0x0); /* reserved */
763     put_be32(pb, 0x40000000); /* reserved */
764
765     put_be32(pb, 0); /* reserved (preview time) */
766     put_be32(pb, 0); /* reserved (preview duration) */
767     put_be32(pb, 0); /* reserved (poster time) */
768     put_be32(pb, 0); /* reserved (selection time) */
769     put_be32(pb, 0); /* reserved (selection duration) */
770     put_be32(pb, 0); /* reserved (current time) */
771     put_be32(pb, maxTrackID+1); /* Next track id */
772     return 0x6c;
773 }
774
775 static int mov_write_udta_tag(ByteIOContext *pb, MOVContext* mov,
776                               AVFormatContext *s)
777 {
778     int pos = url_ftell(pb);
779     int i;
780
781     put_be32(pb, 0); /* size */
782     put_tag(pb, "udta");
783
784     /* Requirements */
785     for (i=0; i<MAX_STREAMS; i++) {
786         if(mov->tracks[i].entry <= 0) continue;
787         if (mov->tracks[i].enc->codec_id == CODEC_ID_AAC ||
788             mov->tracks[i].enc->codec_id == CODEC_ID_MPEG4) {
789             int pos = url_ftell(pb);
790             put_be32(pb, 0); /* size */
791             put_tag(pb, "\251req");
792             put_be16(pb, sizeof("QuickTime 6.0 or greater") - 1);
793             put_be16(pb, 0);
794             put_buffer(pb, "QuickTime 6.0 or greater",
795                        sizeof("QuickTime 6.0 or greater") - 1);
796             updateSize(pb, pos);
797             break;
798         }
799     }
800
801     /* Encoder */
802     if(!(mov->tracks[0].enc->flags & CODEC_FLAG_BITEXACT))
803     {
804         int pos = url_ftell(pb);
805         put_be32(pb, 0); /* size */
806         put_tag(pb, "\251enc");
807         put_be16(pb, sizeof(LIBAVFORMAT_IDENT) - 1); /* string length */
808         put_be16(pb, 0);
809         put_buffer(pb, LIBAVFORMAT_IDENT, sizeof(LIBAVFORMAT_IDENT) - 1);
810         updateSize(pb, pos);
811     }
812
813     if( s->title[0] )
814     {
815         int pos = url_ftell(pb);
816         put_be32(pb, 0); /* size */
817         put_tag(pb, "\251nam");
818         put_be16(pb, strlen(s->title)); /* string length */
819         put_be16(pb, 0);
820         put_buffer(pb, s->title, strlen(s->title));
821         updateSize(pb, pos);
822     }
823
824     if( s->author[0] )
825     {
826         int pos = url_ftell(pb);
827         put_be32(pb, 0); /* size */
828         put_tag(pb, /*"\251aut"*/ "\251day" );
829         put_be16(pb, strlen(s->author)); /* string length */
830         put_be16(pb, 0);
831         put_buffer(pb, s->author, strlen(s->author));
832         updateSize(pb, pos);
833     }
834
835     if( s->comment[0] )
836     {
837         int pos = url_ftell(pb);
838         put_be32(pb, 0); /* size */
839         put_tag(pb, "\251des");
840         put_be16(pb, strlen(s->comment)); /* string length */
841         put_be16(pb, 0);
842         put_buffer(pb, s->comment, strlen(s->comment));
843         updateSize(pb, pos);
844     }
845
846     return updateSize(pb, pos);
847 }
848
849 static int mov_write_moov_tag(ByteIOContext *pb, MOVContext *mov,
850                               AVFormatContext *s)
851 {
852     int pos, i;
853     pos = url_ftell(pb);
854     put_be32(pb, 0); /* size placeholder*/
855     put_tag(pb, "moov");
856     mov->timescale = globalTimescale;
857
858     for (i=0; i<MAX_STREAMS; i++) {
859         if(mov->tracks[i].entry <= 0) continue;
860
861         if(mov->tracks[i].enc->codec_type == CODEC_TYPE_VIDEO) {
862             mov->tracks[i].timescale = mov->tracks[i].enc->frame_rate;
863             mov->tracks[i].sampleDuration = mov->tracks[i].enc->frame_rate_base;
864         }
865         else if(mov->tracks[i].enc->codec_type == CODEC_TYPE_AUDIO) {
866             /* If AMR, track timescale = 8000, AMR_WB = 16000 */
867             if(mov->tracks[i].enc->codec_id == CODEC_ID_AMR_NB) {
868                 mov->tracks[i].sampleDuration = 160;  // Bytes per chunk
869                 mov->tracks[i].timescale = 8000;
870             }
871             else {
872                 mov->tracks[i].timescale = mov->tracks[i].enc->sample_rate;
873                 mov->tracks[i].sampleDuration = mov->tracks[i].enc->frame_size;
874             }
875         }
876
877         mov->tracks[i].trackDuration = 
878             mov->tracks[i].sampleCount * mov->tracks[i].sampleDuration;
879         mov->tracks[i].time = mov->time;
880         mov->tracks[i].trackID = i+1;
881     }
882
883     mov_write_mvhd_tag(pb, mov);
884     //mov_write_iods_tag(pb, mov);
885     for (i=0; i<MAX_STREAMS; i++) {
886         if(mov->tracks[i].entry > 0) {
887             mov_write_trak_tag(pb, &(mov->tracks[i]));
888         }
889     }
890
891     mov_write_udta_tag(pb, mov, s);
892
893     return updateSize(pb, pos);
894 }
895
896 int mov_write_mdat_tag(ByteIOContext *pb, MOVContext* mov)
897 {
898     mov->mdat_pos = url_ftell(pb); 
899     put_be32(pb, 0); /* size placeholder*/
900     put_tag(pb, "mdat");
901     return 0;
902 }
903
904 /* TODO: This needs to be more general */
905 int mov_write_ftyp_tag(ByteIOContext *pb, AVFormatContext *s)
906 {
907     MOVContext *mov = s->priv_data;
908
909     put_be32(pb, 0x14 ); /* size */
910     put_tag(pb, "ftyp");
911
912     if ( mov->mode == MODE_3GP )
913         put_tag(pb, "3gp4");
914     else
915         put_tag(pb, "isom");
916
917     put_be32(pb, 0x200 );
918
919     if ( mov->mode == MODE_3GP )
920         put_tag(pb, "3gp4");
921     else
922         put_tag(pb, "mp41");
923
924     return 0x14;
925 }
926
927 static int mov_write_header(AVFormatContext *s)
928 {
929     ByteIOContext *pb = &s->pb;
930     MOVContext *mov = s->priv_data;
931     int i;
932
933     /* Default mode == MP4 */
934     mov->mode = MODE_MP4;
935
936     if (s->oformat != NULL) {
937         if (!strcmp("3gp", s->oformat->name)) mov->mode = MODE_3GP;
938         else if (!strcmp("mov", s->oformat->name)) mov->mode = MODE_MOV;
939
940         if ( mov->mode == MODE_3GP || mov->mode == MODE_MP4 )
941             mov_write_ftyp_tag(pb,s);
942     }
943
944     for (i=0; i<MAX_STREAMS; i++) {
945         mov->tracks[i].mode = mov->mode;
946     }
947
948     put_flush_packet(pb);
949
950     return 0;
951 }
952
953 static int mov_write_packet(AVFormatContext *s, int stream_index,
954                             const uint8_t *buf, int size, int64_t pts)
955 {
956     MOVContext *mov = s->priv_data;
957     ByteIOContext *pb = &s->pb;
958     AVCodecContext *enc = &s->streams[stream_index]->codec;
959     MOVTrack* trk = &mov->tracks[stream_index];
960     int cl, id;
961     unsigned int samplesInChunk = 0;
962
963     if (url_is_streamed(&s->pb)) return 0; /* Can't handle that */
964     if (!size) return 0; /* Discard 0 sized packets */
965
966     if (enc->codec_type == CODEC_TYPE_VIDEO ) {
967         samplesInChunk = 1;
968     }
969     else if (enc->codec_type == CODEC_TYPE_AUDIO ) {
970         if( enc->codec_id == CODEC_ID_AMR_NB) {
971             /* We must find out how many AMR blocks there are in one packet */
972             static uint16_t packed_size[16] =
973                 {13, 14, 16, 18, 20, 21, 27, 32, 6, 0, 0, 0, 0, 0, 0, 0};
974             int len = 0;
975
976             while (len < size && samplesInChunk < 100) {
977                 len += packed_size[(buf[len] >> 3) & 0x0F];
978                 samplesInChunk++;
979             }
980         }
981         else if(enc->codec_id == CODEC_ID_PCM_ALAW) {
982             samplesInChunk = size/enc->channels;
983         }
984         else if(enc->codec_id == CODEC_ID_PCM_S16BE || enc->codec_id == CODEC_ID_PCM_S16LE) {
985             samplesInChunk = size/(2*enc->channels);
986         }           
987         else {
988             samplesInChunk = 1;
989         }
990     }
991
992     if ((enc->codec_id == CODEC_ID_MPEG4 || enc->codec_id == CODEC_ID_AAC)
993         && trk->vosLen == 0) {
994 //        assert(enc->extradata_size);
995
996         trk->vosLen = enc->extradata_size;
997         trk->vosData = av_malloc(trk->vosLen);
998         memcpy(trk->vosData, enc->extradata, trk->vosLen);
999     }
1000
1001     cl = trk->entry / MOV_INDEX_CLUSTER_SIZE;
1002     id = trk->entry % MOV_INDEX_CLUSTER_SIZE;
1003
1004     if (trk->ents_allocated <= trk->entry) {
1005         trk->cluster = av_realloc(trk->cluster, (cl+1)*sizeof(void*)); 
1006         if (!trk->cluster)
1007             return -1;
1008         trk->cluster[cl] = av_malloc(MOV_INDEX_CLUSTER_SIZE*sizeof(MOVIentry));
1009         if (!trk->cluster[cl])
1010             return -1;
1011         trk->ents_allocated += MOV_INDEX_CLUSTER_SIZE;
1012     }
1013     if (mov->mdat_written == 0) {
1014         mov_write_mdat_tag(pb, mov);
1015         mov->mdat_written = 1;
1016         mov->time = s->timestamp;
1017     }
1018
1019     trk->cluster[cl][id].pos = url_ftell(pb);
1020     trk->cluster[cl][id].samplesInChunk = samplesInChunk;
1021     trk->cluster[cl][id].size = size;
1022     trk->cluster[cl][id].entries = samplesInChunk;
1023     if(enc->codec_type == CODEC_TYPE_VIDEO) {
1024         trk->cluster[cl][id].key_frame = enc->coded_frame->key_frame;
1025         if(enc->coded_frame->pict_type == FF_I_TYPE)
1026             trk->hasKeyframes = 1;
1027     }
1028     trk->enc = enc;
1029     trk->entry++;
1030     trk->sampleCount += samplesInChunk;
1031     trk->mdat_size += size;
1032
1033     put_buffer(pb, buf, size);
1034
1035     put_flush_packet(pb);
1036     return 0;
1037 }
1038
1039 static int mov_write_trailer(AVFormatContext *s)
1040 {
1041     MOVContext *mov = s->priv_data;
1042     ByteIOContext *pb = &s->pb;
1043     int res = 0;
1044     int i, j;
1045
1046     offset_t moov_pos = url_ftell(pb);
1047
1048     /* Write size of mdat tag */
1049     for (i=0, j=0; i<MAX_STREAMS; i++) {
1050         if(mov->tracks[i].ents_allocated > 0) {
1051             j += mov->tracks[i].mdat_size;
1052         }
1053     }
1054     url_fseek(pb, mov->mdat_pos, SEEK_SET);
1055     put_be32(pb, j+8);
1056     url_fseek(pb, moov_pos, SEEK_SET);
1057
1058     mov_write_moov_tag(pb, mov, s);
1059
1060     for (i=0; i<MAX_STREAMS; i++) {
1061         for (j=0; j<mov->tracks[i].ents_allocated/MOV_INDEX_CLUSTER_SIZE; j++) {
1062             av_free(mov->tracks[i].cluster[j]);
1063         }
1064         av_free(mov->tracks[i].cluster);
1065         if( mov->tracks[i].vosLen ) av_free( mov->tracks[i].vosData );
1066
1067         mov->tracks[i].cluster = NULL;
1068         mov->tracks[i].ents_allocated = mov->tracks[i].entry = 0;
1069     }
1070
1071     put_flush_packet(pb);
1072
1073     return res;
1074 }
1075
1076 static AVOutputFormat mov_oformat = {
1077     "mov",
1078     "mov format",
1079     NULL,
1080     "mov",
1081     sizeof(MOVContext),
1082     CODEC_ID_AAC,
1083     CODEC_ID_MPEG4,
1084     mov_write_header,
1085     mov_write_packet,
1086     mov_write_trailer,
1087 };
1088
1089 static AVOutputFormat _3gp_oformat = {
1090     "3gp",
1091     "3gp format",
1092     NULL,
1093     "3gp",
1094     sizeof(MOVContext),
1095     CODEC_ID_AMR_NB,
1096     CODEC_ID_H263,
1097     mov_write_header,
1098     mov_write_packet,
1099     mov_write_trailer,
1100 };
1101
1102 static AVOutputFormat mp4_oformat = {
1103     "mp4",
1104     "mp4 format",
1105     "application/mp4",
1106     "mp4,m4a",
1107     sizeof(MOVContext),
1108     CODEC_ID_AAC,
1109     CODEC_ID_MPEG4,
1110     mov_write_header,
1111     mov_write_packet,
1112     mov_write_trailer,
1113 };
1114
1115 int movenc_init(void)
1116 {
1117     av_register_output_format(&mov_oformat);
1118     av_register_output_format(&_3gp_oformat);
1119     av_register_output_format(&mp4_oformat);
1120     return 0;
1121 }