uninitalized variables fix by (Gildas Bazin <gbazin at altern dot org>)
[ffmpeg.git] / libavformat / movenc.c
1 /*
2  * MOV, 3GP, MP4 encoder.
3  * Copyright (c) 2003 Thomas Raivio.
4  * Enhancements by Gildas Bazin <gbazin@netcourrier.com>
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 typedef struct MOVIentry {
31     unsigned int flags, pos, size;
32     unsigned int samplesInChunk;
33     char         key_frame;
34     unsigned int entries;
35 } MOVIentry;
36
37 typedef struct MOVIndex {
38     int         entry;
39     int         mdat_size;
40     int         ents_allocated;
41     long        timescale;
42     long        time;
43     long        trackDuration;
44     long        sampleCount;
45     long        sampleDuration;
46     int         hasKeyframes;
47     int         trackID;
48     AVCodecContext *enc;
49
50     int         vosLen;
51     uint8_t     *vosData;
52     MOVIentry** cluster;
53 } MOVTrack;
54
55 typedef struct {
56     long    time;
57     int     nb_streams;
58     int     mdat_written;
59     offset_t mdat_pos;
60     offset_t movi_list;
61     long    timescale;
62     MOVTrack tracks[MAX_STREAMS];
63 } MOVContext;
64
65 static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack* track);
66
67 //FIXME supprt 64bit varaint with wide placeholders
68 static int updateSize (ByteIOContext *pb, int pos)
69 {
70     long curpos = url_ftell(pb);
71     url_fseek(pb, pos, SEEK_SET);
72     put_be32(pb, curpos - pos); /* rewrite size */
73     url_fseek(pb, curpos, SEEK_SET);
74
75     return curpos - pos;
76 }
77
78 /* Chunk offset atom */
79 static int mov_write_stco_tag(ByteIOContext *pb, MOVTrack* track)
80 {
81     int i;
82     int pos = url_ftell(pb);
83     put_be32(pb, 0); /* size */
84     put_tag(pb, "stco");
85     put_be32(pb, 0); /* version & flags */
86     put_be32(pb, track->entry); /* entry count */
87     for (i=0; i<track->entry; i++) {
88         int cl = i / MOV_INDEX_CLUSTER_SIZE;
89         int id = i % MOV_INDEX_CLUSTER_SIZE;
90         put_be32(pb, track->cluster[cl][id].pos);
91     }
92     return updateSize (pb, pos);
93 }
94
95 /* Sample size atom */
96 static int mov_write_stsz_tag(ByteIOContext *pb, MOVTrack* track)
97 {
98     int equalChunks = 1;
99     int i, j, entries = 0, tst = -1, oldtst = -1;
100
101     int pos = url_ftell(pb);
102     put_be32(pb, 0); /* size */
103     put_tag(pb, "stsz");
104     put_be32(pb, 0); /* version & flags */
105
106     for (i=0; i<track->entry; i++) {
107         int cl = i / MOV_INDEX_CLUSTER_SIZE;
108         int id = i % MOV_INDEX_CLUSTER_SIZE;
109         tst = track->cluster[cl][id].size/track->cluster[cl][id].entries;
110         if(oldtst != -1 && tst != oldtst) {
111             equalChunks = 0;
112         }
113         oldtst = tst;
114         entries += track->cluster[cl][id].entries;
115     }
116     if (equalChunks) {
117         int sSize = track->cluster[0][0].size/track->cluster[0][0].entries;
118         put_be32(pb, sSize); // sample size 
119         put_be32(pb, entries); // sample count
120     }
121     else {
122         put_be32(pb, 0); // sample size 
123         put_be32(pb, entries); // sample count 
124         for (i=0; i<track->entry; i++) {
125             int cl = i / MOV_INDEX_CLUSTER_SIZE;
126             int id = i % MOV_INDEX_CLUSTER_SIZE;
127             for ( j=0; j<track->cluster[cl][id].entries; j++) {
128                 put_be32(pb, track->cluster[cl][id].size /
129                          track->cluster[cl][id].entries);
130             }
131         }
132     }
133     return updateSize (pb, pos);
134 }
135
136 /* Sample to chunk atom */
137 static int mov_write_stsc_tag(ByteIOContext *pb, MOVTrack* track)
138 {
139     int index = 0, oldval = -1, i, entryPos, curpos;
140
141     int pos = url_ftell(pb);
142     put_be32(pb, 0); /* size */
143     put_tag(pb, "stsc");
144     put_be32(pb, 0); // version & flags 
145     entryPos = url_ftell(pb);
146     put_be32(pb, track->entry); // entry count 
147     for (i=0; i<track->entry; i++) {
148         int cl = i / MOV_INDEX_CLUSTER_SIZE;
149         int id = i % MOV_INDEX_CLUSTER_SIZE;
150         if(oldval != track->cluster[cl][id].samplesInChunk)
151         {
152             put_be32(pb, i+1); // first chunk 
153             put_be32(pb, track->cluster[cl][id].samplesInChunk); // samples per chunk
154             put_be32(pb, 0x1); // sample description index 
155             oldval = track->cluster[cl][id].samplesInChunk;
156             index++;
157         }
158     }
159     curpos = url_ftell(pb);
160     url_fseek(pb, entryPos, SEEK_SET);
161     put_be32(pb, index); // rewrite size 
162     url_fseek(pb, curpos, SEEK_SET);
163
164     return updateSize (pb, pos);
165 }
166
167 /* Sync sample atom */
168 static int mov_write_stss_tag(ByteIOContext *pb, MOVTrack* track)
169 {
170     long curpos;
171     int i, index = 0, entryPos;
172     int pos = url_ftell(pb);
173     put_be32(pb, 0); // size 
174     put_tag(pb, "stss");
175     put_be32(pb, 0); // version & flags 
176     entryPos = url_ftell(pb);
177     put_be32(pb, track->entry); // entry count 
178     for (i=0; i<track->entry; i++) {
179         int cl = i / MOV_INDEX_CLUSTER_SIZE;
180         int id = i % MOV_INDEX_CLUSTER_SIZE;
181         if(track->cluster[cl][id].key_frame == 1) {
182             put_be32(pb, i+1);
183             index++;
184         }
185     }
186     curpos = url_ftell(pb);
187     url_fseek(pb, entryPos, SEEK_SET);
188     put_be32(pb, index); // rewrite size 
189     url_fseek(pb, curpos, SEEK_SET);
190     return updateSize (pb, pos);
191 }
192
193 static int mov_write_damr_tag(ByteIOContext *pb)
194 {
195     put_be32(pb, 0x11); /* size */
196     put_tag(pb, "damr");
197     put_tag(pb, "FFMP");
198     put_byte(pb, 0);
199
200     put_be16(pb, 0x80); /* Mode set (all modes for AMR_NB) */
201     put_be16(pb, 0xa); /* Mode change period (no restriction) */
202     //put_be16(pb, 0x81ff); /* Mode set (all modes for AMR_NB) */
203     //put_be16(pb, 1); /* Mode change period (no restriction) */
204     return 0x11;
205 }
206
207 static int mov_write_audio_tag(ByteIOContext *pb, MOVTrack* track)
208 {
209     int pos = url_ftell(pb);
210     put_be32(pb, 0); /* size */
211
212     if(track->enc->codec_id == CODEC_ID_PCM_MULAW)
213       put_tag(pb, "ulaw");
214     else if(track->enc->codec_id == CODEC_ID_PCM_ALAW)
215       put_tag(pb, "alaw");
216     else if(track->enc->codec_id == CODEC_ID_ADPCM_IMA_QT)
217       put_tag(pb, "ima4");
218     else if(track->enc->codec_id == CODEC_ID_MACE3)
219       put_tag(pb, "MAC3");
220     else if(track->enc->codec_id == CODEC_ID_MACE6)
221       put_tag(pb, "MAC6");
222     else if(track->enc->codec_id == CODEC_ID_AAC)
223       put_tag(pb, "mp4a");
224     else if(track->enc->codec_id == CODEC_ID_AMR_NB)
225       put_tag(pb, "samr");
226     else
227       put_tag(pb, "    ");
228
229     put_be32(pb, 0); /* Reserved */
230     put_be16(pb, 0); /* Reserved */
231     put_be16(pb, 1); /* Data-reference index, XXX  == 1 */
232     /* SoundDescription */
233     put_be16(pb, 0); /* Version */
234     put_be16(pb, 0); /* Revision level */
235     put_be32(pb, 0); /* Reserved */
236
237     put_be16(pb, track->enc->channels); /* Number of channels */
238     /* TODO: Currently hard-coded to 16-bit, there doesn't seem
239                  to be a good way to get number of bits of audio */
240     put_be16(pb, 0x10); /* Reserved */
241     put_be16(pb, 0); /* compression ID (= 0) */
242     put_be16(pb, 0); /* packet size (= 0) */
243     put_be16(pb, track->timescale); /* Time scale */
244     put_be16(pb, 0); /* Reserved */
245
246     if(track->enc->codec_id == CODEC_ID_AAC)
247         mov_write_esds_tag(pb, track);
248     if(track->enc->codec_id == CODEC_ID_AMR_NB)
249         mov_write_damr_tag(pb);
250     return updateSize (pb, pos);
251 }
252
253 static int mov_write_d263_tag(ByteIOContext *pb)
254 {
255     put_be32(pb, 0xf); /* size */
256     put_tag(pb, "d263");
257     put_tag(pb, "FFMP");
258     put_be16(pb, 0x0a);
259     put_byte(pb, 0);
260     return 0xf;
261 }
262
263 /* TODO: No idea about these values */
264 static int mov_write_svq3_tag(ByteIOContext *pb)
265 {
266     put_be32(pb, 0x15);
267     put_tag(pb, "SMI ");
268     put_tag(pb, "SEQH");
269     put_be32(pb, 0x5);
270     put_be32(pb, 0xe2c0211d);
271     put_be32(pb, 0xc0000000);
272     put_byte(pb, 0);   
273     return 0x15;
274 }
275
276 static unsigned int descrLength(unsigned int len)
277 {
278     if (len < 0x00000080)
279         return 2 + len;
280     else if (len < 0x00004000)
281         return 3 + len;
282     else if(len < 0x00200000)
283         return 4 + len;
284     else
285         return 5 + len;
286 }
287
288 static void putDescr(ByteIOContext *pb, int tag, int size)
289 {
290     uint32_t len;
291     uint8_t  vals[4];
292
293     len = size;
294     vals[3] = (uint8_t)(len & 0x7f);
295     len >>= 7;
296     vals[2] = (uint8_t)((len & 0x7f) | 0x80); 
297     len >>= 7;
298     vals[1] = (uint8_t)((len & 0x7f) | 0x80); 
299     len >>= 7;
300     vals[0] = (uint8_t)((len & 0x7f) | 0x80);
301
302     put_byte(pb, tag); // DescriptorTag
303
304     if (size < 0x00000080)
305     {
306         put_byte(pb, vals[3]);
307     }
308     else if (size < 0x00004000)
309     {
310         put_byte(pb, vals[2]);
311         put_byte(pb, vals[3]);
312     }
313     else if (size < 0x00200000)
314     {
315         put_byte(pb, vals[1]);
316         put_byte(pb, vals[2]);
317         put_byte(pb, vals[3]);
318     }
319     else if (size < 0x10000000)
320     {
321         put_byte(pb, vals[0]);
322         put_byte(pb, vals[1]);
323         put_byte(pb, vals[2]);
324         put_byte(pb, vals[3]);
325     }
326 }
327
328 static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack* track) // Basic
329 {
330     int decoderSpecificInfoLen = track->vosLen ? descrLength(track->vosLen):0;
331     int pos = url_ftell(pb);
332
333     put_be32(pb, 0);               // size
334     put_tag(pb, "esds");
335     put_be32(pb, 0);               // Version
336
337     // ES descriptor
338     putDescr(pb, 0x03, 3 + descrLength(13 + decoderSpecificInfoLen) +
339              descrLength(1));
340     put_be16(pb, 0x0001);          // ID (= 1)
341     put_byte(pb, 0x00);            // flags (= no flags)
342
343     // DecoderConfig descriptor
344     putDescr(pb, 0x04, 13 + decoderSpecificInfoLen);
345
346     if(track->enc->codec_id == CODEC_ID_AAC)
347         put_byte(pb, 0x40);        // Object type indication
348     else if(track->enc->codec_id == CODEC_ID_MPEG4)
349         put_byte(pb, 0x20);        // Object type indication (Visual 14496-2)
350
351     if(track->enc->codec_type == CODEC_TYPE_AUDIO)
352         put_byte(pb, 0x15);            // flags (= Audiostream)
353     else
354         put_byte(pb, 0x11);            // flags (= Visualstream)
355
356     put_byte(pb, 0x0);             // Buffersize DB (24 bits)
357     put_be16(pb, 0x0dd2);          // Buffersize DB
358
359     // TODO: find real values for these
360     put_be32(pb, 0x0002e918);     // maxbitrate
361     put_be32(pb, 0x00017e6b);     // avg bitrate
362
363     if (track->vosLen)
364     {
365         // DecoderSpecific info descriptor
366         putDescr(pb, 0x05, track->vosLen);
367         put_buffer(pb, track->vosData, track->vosLen);
368     }
369
370     // SL descriptor
371     putDescr(pb, 0x06, descrLength(1));
372     put_byte(pb, 0x02);
373     return updateSize (pb, pos);
374 }
375
376 static int mov_write_video_tag(ByteIOContext *pb, MOVTrack* track)
377 {
378     int pos = url_ftell(pb);
379     put_be32(pb, 0); /* size */
380     if(track->enc->codec_id == CODEC_ID_SVQ1)
381       put_tag(pb, "SVQ1");
382     else if(track->enc->codec_id == CODEC_ID_SVQ3)
383       put_tag(pb, "SVQ3");
384     else if(track->enc->codec_id == CODEC_ID_MPEG4)
385       put_tag(pb, "mp4v");
386     else if(track->enc->codec_id == CODEC_ID_H263)
387       put_tag(pb, "s263");
388     else
389       put_tag(pb, "    "); /* Unknown tag */
390
391     put_be32(pb, 0); /* Reserved */
392     put_be16(pb, 0); /* Reserved */
393     put_be16(pb, 1); /* Data-reference index */
394
395     put_be32(pb, 0); /* Reserved (= 02000c) */
396     put_be32(pb, 0); /* Reserved ("SVis")*/
397     put_be32(pb, 0); /* Reserved */
398     put_be32(pb, 0); /* Reserved (400)*/
399     put_be16(pb, track->enc->width); /* Video width */
400     put_be16(pb, track->enc->height); /* Video height */
401     put_be32(pb, 0x00480000); /* Reserved */
402     put_be32(pb, 0x00480000); /* Reserved */
403     put_be32(pb, 0); /* Reserved */
404     put_be32(pb, 0); /* Reserved */
405     put_be32(pb, 0); /* Reserved */
406     put_be32(pb, 0); /* Reserved */
407     put_be32(pb, 0); /* Reserved */
408     put_be32(pb, 0); /* Reserved */
409
410     put_be16(pb, 0); /* Reserved */
411     put_be32(pb, 0); /* Reserved */
412     put_be32(pb, 0); /* Reserved */
413     put_be32(pb, 0); /* Reserved */
414     put_be16(pb, 0x18); /* Reserved */
415     put_be16(pb, 0xffff); /* Reserved */
416     if(track->enc->codec_id == CODEC_ID_MPEG4)
417         mov_write_esds_tag(pb, track);
418     else if(track->enc->codec_id == CODEC_ID_H263)
419         mov_write_d263_tag(pb);
420     else if(track->enc->codec_id == CODEC_ID_SVQ3)
421         mov_write_svq3_tag(pb);    
422
423     return updateSize (pb, pos);
424 }
425
426 static int mov_write_stsd_tag(ByteIOContext *pb, MOVTrack* track)
427 {
428     int pos = url_ftell(pb);
429     put_be32(pb, 0); /* size */
430     put_tag(pb, "stsd");
431     put_be32(pb, 0); /* version & flags */
432     put_be32(pb, 1); /* entry count */
433     if (track->enc->codec_type == CODEC_TYPE_VIDEO)
434         mov_write_video_tag(pb, track);
435     else if (track->enc->codec_type == CODEC_TYPE_AUDIO)
436         mov_write_audio_tag(pb, track);
437     return updateSize(pb, pos);
438 }
439
440 /* TODO?: Currently all samples/frames seem to have same duration */
441 /* Time to sample atom */
442 static int mov_write_stts_tag(ByteIOContext *pb, MOVTrack* track)
443 {
444     put_be32(pb, 0x18); /* size */
445     put_tag(pb, "stts");
446     put_be32(pb, 0); /* version & flags */
447     put_be32(pb, 1); /* entry count */
448
449     put_be32(pb, track->sampleCount); /* sample count */
450     put_be32(pb, track->sampleDuration); /* sample duration */
451     return 0x18;
452 }
453
454 static int mov_write_dref_tag(ByteIOContext *pb)
455 {
456     put_be32(pb, 28); /* size */
457     put_tag(pb, "dref");
458     put_be32(pb, 0); /* version & flags */
459     put_be32(pb, 1); /* entry count */
460
461     put_be32(pb, 0xc); /* size */
462     put_tag(pb, "url ");
463     put_be32(pb, 1); /* version & flags */
464
465     return 28;
466 }
467
468 static int mov_write_stbl_tag(ByteIOContext *pb, MOVTrack* track)
469 {
470     int pos = url_ftell(pb);
471     put_be32(pb, 0); /* size */
472     put_tag(pb, "stbl");
473     mov_write_stsd_tag(pb, track);
474     mov_write_stts_tag(pb, track);
475     if (track->enc->codec_type == CODEC_TYPE_VIDEO &&
476         track->hasKeyframes)
477         mov_write_stss_tag(pb, track);
478     mov_write_stsc_tag(pb, track);
479     mov_write_stsz_tag(pb, track);
480     mov_write_stco_tag(pb, track);
481     return updateSize(pb, pos);
482 }
483
484 static int mov_write_dinf_tag(ByteIOContext *pb)
485 {
486     int pos = url_ftell(pb);
487     put_be32(pb, 0); /* size */
488     put_tag(pb, "dinf");
489     mov_write_dref_tag(pb);
490     return updateSize(pb, pos);
491 }
492
493 static int mov_write_smhd_tag(ByteIOContext *pb)
494 {
495     put_be32(pb, 16); /* size */
496     put_tag(pb, "smhd");
497     put_be32(pb, 0); /* version & flags */
498     put_be16(pb, 0); /* reserved (balance, normally = 0) */
499     put_be16(pb, 0); /* reserved */
500     return 16;
501 }
502
503 static int mov_write_vmhd_tag(ByteIOContext *pb)
504 {
505     put_be32(pb, 0x14); /* size (always 0x14) */
506     put_tag(pb, "vmhd");
507     put_be32(pb, 0x01); /* version & flags */
508     put_be64(pb, 0); /* reserved (graphics mode = copy) */
509     return 0x14;
510 }
511
512 static int mov_write_minf_tag(ByteIOContext *pb, MOVTrack* track)
513 {
514     int pos = url_ftell(pb);
515     put_be32(pb, 0); /* size */
516     put_tag(pb, "minf");
517     if(track->enc->codec_type == CODEC_TYPE_VIDEO)
518         mov_write_vmhd_tag(pb);
519     else
520         mov_write_smhd_tag(pb);
521     mov_write_dinf_tag(pb);
522     mov_write_stbl_tag(pb, track);
523     return updateSize(pb, pos);
524 }
525
526 static int mov_write_hdlr_tag(ByteIOContext *pb, MOVTrack* track)
527 {
528     char *str;
529     int pos = url_ftell(pb);
530     put_be32(pb, 0); /* size */
531     put_tag(pb, "hdlr");
532     put_be32(pb, 0); /* Version & flags */
533     put_be32(pb, 0); /* reserved */
534     if(track->enc->codec_type == CODEC_TYPE_VIDEO)
535         put_tag(pb, "vide"); /* handler type */
536     else
537         put_tag(pb, "soun"); /* handler type */
538     put_be32(pb ,0); /* reserved */
539     put_be32(pb ,0); /* reserved */
540     put_be32(pb ,0); /* reserved */
541     if(track->enc->codec_type == CODEC_TYPE_VIDEO)
542         str = "VideoHandler";
543     else
544         str = "SoundHandler";
545     put_byte(pb, strlen(str)); /* string counter */
546     put_buffer(pb, str, strlen(str));
547     return updateSize(pb, pos);
548 }
549
550 static int mov_write_mdhd_tag(ByteIOContext *pb, MOVTrack* track)
551 {
552     put_be32(pb, 32); /* size */
553     put_tag(pb, "mdhd");
554     put_be32(pb, 0); /* Version & flags */
555     put_be32(pb, track->time); /* creation time */
556     put_be32(pb, track->time); /* modification time */
557     put_be32(pb, track->timescale); /* time scale (sample rate for audio) */ 
558     put_be32(pb, track->trackDuration); /* duration */
559     put_be16(pb, 0); /* language, 0 = english */
560     put_be16(pb, 0); /* reserved (quality) */
561     return 32;
562 }
563
564 static int mov_write_mdia_tag(ByteIOContext *pb, MOVTrack* track)
565 {
566     int pos = url_ftell(pb);
567     put_be32(pb, 0); /* size */
568     put_tag(pb, "mdia");
569     mov_write_mdhd_tag(pb, track);
570     mov_write_hdlr_tag(pb, track);
571     mov_write_minf_tag(pb, track);
572     return updateSize(pb, pos);
573 }
574
575 static int mov_write_tkhd_tag(ByteIOContext *pb, MOVTrack* track)
576 {
577     int64_t maxTrackLenTemp;
578     put_be32(pb, 0x5c); /* size (always 0x5c) */
579     put_tag(pb, "tkhd");
580     put_be32(pb, 0xf); /* version & flags (track enabled) */
581     put_be32(pb, track->time); /* creation time */
582     put_be32(pb, track->time); /* modification time */
583     put_be32(pb, track->trackID); /* track-id */
584     put_be32(pb, 0); /* reserved */
585     maxTrackLenTemp = ((int64_t)globalTimescale*(int64_t)track->trackDuration)/(int64_t)track->timescale;
586     put_be32(pb, (long)maxTrackLenTemp); /* duration */
587
588     put_be32(pb, 0); /* reserved */
589     put_be32(pb, 0); /* reserved */
590     put_be32(pb, 0x0); /* reserved (Layer & Alternate group) */
591     /* Volume, only for audio */
592     if(track->enc->codec_type == CODEC_TYPE_AUDIO)
593         put_be16(pb, 0x0100);
594     else
595         put_be16(pb, 0);
596     put_be16(pb, 0); /* reserved */
597
598     /* Matrix structure */
599     put_be32(pb, 0x00010000); /* reserved */
600     put_be32(pb, 0x0); /* reserved */
601     put_be32(pb, 0x0); /* reserved */
602     put_be32(pb, 0x0); /* reserved */
603     put_be32(pb, 0x00010000); /* reserved */
604     put_be32(pb, 0x0); /* reserved */
605     put_be32(pb, 0x0); /* reserved */
606     put_be32(pb, 0x0); /* reserved */
607     put_be32(pb, 0x40000000); /* reserved */
608
609     /* Track width and height, for visual only */
610     if(track->enc->codec_type == CODEC_TYPE_VIDEO) {
611         put_be32(pb, track->enc->width*0x10000);
612         put_be32(pb, track->enc->height*0x10000);
613     }
614     else {
615         put_be32(pb, 0);
616         put_be32(pb, 0);
617     }
618     return 0x5c;
619 }
620
621 static int mov_write_trak_tag(ByteIOContext *pb, MOVTrack* track)
622 {
623     int pos = url_ftell(pb);
624     put_be32(pb, 0); /* size */
625     put_tag(pb, "trak");
626     mov_write_tkhd_tag(pb, track);
627     mov_write_mdia_tag(pb, track);
628     return updateSize(pb, pos);
629 }
630
631 /* TODO: Not sorted out, but not necessary either */
632 static int mov_write_iods_tag(ByteIOContext *pb, MOVContext *mov)
633 {
634     put_be32(pb, 0x15); /* size */
635     put_tag(pb, "iods");
636     put_be32(pb, 0);    /* version & flags */
637     put_be16(pb, 0x1007);
638     put_byte(pb, 0);
639     put_be16(pb, 0x4fff);
640     put_be16(pb, 0xfffe);
641     put_be16(pb, 0x01ff);
642     return 0x15;
643 }
644
645 static int mov_write_mvhd_tag(ByteIOContext *pb, MOVContext *mov)
646 {
647     int maxTrackID = 1, maxTrackLen = 0, i;
648     int64_t maxTrackLenTemp;
649
650     put_be32(pb, 0x6c); /* size (always 0x6c) */
651     put_tag(pb, "mvhd");
652     put_be32(pb, 0); /* version & flags */
653     put_be32(pb, mov->time); /* creation time */
654     put_be32(pb, mov->time); /* modification time */
655     put_be32(pb, mov->timescale); /* timescale */
656     for (i=0; i<MAX_STREAMS; i++) {
657         if(mov->tracks[i].entry > 0) {
658             maxTrackLenTemp = ((int64_t)globalTimescale*(int64_t)mov->tracks[i].trackDuration)/(int64_t)mov->tracks[i].timescale;
659             if(maxTrackLen < maxTrackLenTemp)
660                 maxTrackLen = maxTrackLenTemp;
661             if(maxTrackID < mov->tracks[i].trackID)
662                 maxTrackID = mov->tracks[i].trackID;
663         }
664     }
665     put_be32(pb, maxTrackLen); /* duration of longest track */
666
667     put_be32(pb, 0x00010000); /* reserved (preferred rate) 1.0 = normal */
668     put_be16(pb, 0x0100); /* reserved (preferred volume) 1.0 = normal */
669     put_be16(pb, 0); /* reserved */
670     put_be32(pb, 0); /* reserved */
671     put_be32(pb, 0); /* reserved */
672
673     /* Matrix structure */
674     put_be32(pb, 0x00010000); /* reserved */
675     put_be32(pb, 0x0); /* reserved */
676     put_be32(pb, 0x0); /* reserved */
677     put_be32(pb, 0x0); /* reserved */
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, 0x40000000); /* reserved */
683
684     put_be32(pb, 0); /* reserved (preview time) */
685     put_be32(pb, 0); /* reserved (preview duration) */
686     put_be32(pb, 0); /* reserved (poster time) */
687     put_be32(pb, 0); /* reserved (selection time) */
688     put_be32(pb, 0); /* reserved (selection duration) */
689     put_be32(pb, 0); /* reserved (current time) */
690     put_be32(pb, maxTrackID+1); /* Next track id */
691     return 0x6c;
692 }
693
694 static int mov_write_moov_tag(ByteIOContext *pb, MOVContext *mov)
695 {
696     int pos, i;
697     pos = url_ftell(pb);
698     put_be32(pb, 0); /* size placeholder*/
699     put_tag(pb, "moov");
700     mov->timescale = globalTimescale;
701
702     for (i=0; i<MAX_STREAMS; i++) {
703         if(mov->tracks[i].entry <= 0) continue;
704
705         if(mov->tracks[i].enc->codec_type == CODEC_TYPE_VIDEO) {
706             mov->tracks[i].timescale = mov->tracks[i].enc->frame_rate;
707             mov->tracks[i].sampleDuration = mov->tracks[i].enc->frame_rate_base;
708         }
709         else if(mov->tracks[i].enc->codec_type == CODEC_TYPE_AUDIO) {
710             /* If AMR, track timescale = 8000, AMR_WB = 16000 */
711             if(mov->tracks[i].enc->codec_id == CODEC_ID_AMR_NB) {
712                 mov->tracks[i].sampleDuration = 160;  // Bytes per chunk
713                 mov->tracks[i].timescale = 8000;
714             }
715             else {
716                 mov->tracks[i].timescale = mov->tracks[i].enc->sample_rate;
717                 mov->tracks[i].sampleDuration = mov->tracks[i].enc->frame_size;
718             }
719         }
720
721         mov->tracks[i].trackDuration = 
722             mov->tracks[i].sampleCount * mov->tracks[i].sampleDuration;
723         mov->tracks[i].time = mov->time;
724         mov->tracks[i].trackID = i+1;
725     }
726
727     mov_write_mvhd_tag(pb, mov);
728     //mov_write_iods_tag(pb, mov);
729     for (i=0; i<MAX_STREAMS; i++) {
730         if(mov->tracks[i].entry > 0) {
731             mov_write_trak_tag(pb, &(mov->tracks[i]));
732         }
733     }
734
735     return updateSize(pb, pos);
736 }
737
738 int mov_write_mdat_tag(ByteIOContext *pb, MOVContext* mov)
739 {
740     mov->mdat_pos = url_ftell(pb); 
741     put_be32(pb, 0); /* size placeholder*/
742     put_tag(pb, "mdat");
743     return 0;
744 }
745
746 /* TODO: This needs to be more general */
747 int mov_write_ftyp_tag(ByteIOContext *pb, AVFormatContext *s)
748 {
749     put_be32(pb, 0x14 ); /* size */
750     put_tag(pb, "ftyp");
751
752     if (!strcmp("3gp", s->oformat->name))
753         put_tag(pb, "3gp4");
754     else
755         put_tag(pb, "isom");
756
757     put_be32(pb, 0x200 );
758
759     if (!strcmp("3gp", s->oformat->name))
760         put_tag(pb, "3gp4");
761     else
762         put_tag(pb, "mp41");
763
764     return 0x14;
765 }
766
767 static int mov_write_header(AVFormatContext *s)
768 {
769     ByteIOContext *pb = &s->pb;
770
771     if(s->oformat != NULL) {
772     if(!strcmp("3gp", s->oformat->name) || !strcmp("mp4", s->oformat->name))
773         mov_write_ftyp_tag(pb,s);
774     }
775
776     put_flush_packet(pb);
777
778     return 0;
779 }
780
781 static int Timestamp() {
782     return 1067949799U+(24107*86400); //its the modification time of this line :)
783 }
784
785 static int mov_write_packet(AVFormatContext *s, int stream_index,
786                             const uint8_t *buf, int size, int64_t pts)
787 {
788     MOVContext *mov = s->priv_data;
789     ByteIOContext *pb = &s->pb;
790     AVCodecContext *enc = &s->streams[stream_index]->codec;
791     MOVTrack* trk = &mov->tracks[stream_index];
792     int cl, id;
793     unsigned int samplesInChunk = 0;
794
795     if (url_is_streamed(&s->pb)) return 0; /* Can't handle that */
796     if (!size) return 0; /* Discard 0 sized packets */
797
798     if (enc->codec_type == CODEC_TYPE_VIDEO ) {
799         samplesInChunk = 1;
800     }
801     else if (enc->codec_type == CODEC_TYPE_AUDIO ) {
802         if( enc->codec_id == CODEC_ID_AMR_NB) {
803             /* We must find out how many AMR blocks there are in one packet */
804             static uint16_t packed_size[16] =
805                 {13, 14, 16, 18, 20, 21, 27, 32, 6, 0, 0, 0, 0, 0, 0, 0};
806             int len = 0;
807
808             while (len < size && samplesInChunk < 100) {
809                 len += packed_size[(buf[len] >> 3) & 0x0F];
810                 samplesInChunk++;
811             }
812         }
813         else if(enc->codec_id == CODEC_ID_PCM_ALAW) {
814             samplesInChunk = size/enc->channels;
815         }
816         else {
817             samplesInChunk = 1;
818         }
819     }
820
821     if ((enc->codec_id == CODEC_ID_MPEG4 || enc->codec_id == CODEC_ID_AAC)
822         && trk->vosLen == 0) {
823         assert(enc->extradata_size);
824
825         trk->vosLen = enc->extradata_size;
826         trk->vosData = av_malloc(trk->vosLen);
827         memcpy(trk->vosData, enc->extradata, trk->vosLen);
828     }
829
830     cl = trk->entry / MOV_INDEX_CLUSTER_SIZE;
831     id = trk->entry % MOV_INDEX_CLUSTER_SIZE;
832
833     if (trk->ents_allocated <= trk->entry) {
834         trk->cluster = av_realloc(trk->cluster, (cl+1)*sizeof(void*)); 
835         if (!trk->cluster)
836             return -1;
837         trk->cluster[cl] = av_malloc(MOV_INDEX_CLUSTER_SIZE*sizeof(MOVIentry));
838         if (!trk->cluster[cl])
839             return -1;
840         trk->ents_allocated += MOV_INDEX_CLUSTER_SIZE;
841     }
842     if (mov->mdat_written == 0) {
843         mov_write_mdat_tag(pb, mov);
844         mov->mdat_written = 1;
845         mov->time = Timestamp();
846     }
847
848     trk->cluster[cl][id].pos = url_ftell(pb) - mov->movi_list;
849     trk->cluster[cl][id].samplesInChunk = samplesInChunk;
850     trk->cluster[cl][id].size = size;
851     trk->cluster[cl][id].entries = samplesInChunk;
852     if(enc->codec_type == CODEC_TYPE_VIDEO) {
853         trk->cluster[cl][id].key_frame = enc->coded_frame->key_frame;
854         if(enc->coded_frame->pict_type == FF_I_TYPE)
855             trk->hasKeyframes = 1;
856     }
857     trk->enc = enc;
858     trk->entry++;
859     trk->sampleCount += samplesInChunk;
860     trk->mdat_size += size;
861
862     put_buffer(pb, buf, size);
863
864     put_flush_packet(pb);
865     return 0;
866 }
867
868 static int mov_write_trailer(AVFormatContext *s)
869 {
870     MOVContext *mov = s->priv_data;
871     ByteIOContext *pb = &s->pb;
872     int res = 0;
873     int i, j;
874     offset_t file_size;
875
876     file_size = url_ftell(pb);
877     j = 0;
878
879     /* Write size of mdat tag */
880     for (i=0; i<MAX_STREAMS; i++) {
881         if(mov->tracks[i].ents_allocated > 0) {
882             j += mov->tracks[i].mdat_size;
883         }
884     }
885     url_fseek(pb, mov->mdat_pos, SEEK_SET);
886     put_be32(pb, j+8);
887     url_fseek(pb, file_size, SEEK_SET);
888
889     mov_write_moov_tag(pb, mov);
890
891     for (i=0; i<MAX_STREAMS; i++) {
892         for (j=0; j<mov->tracks[i].ents_allocated/MOV_INDEX_CLUSTER_SIZE; j++) {
893             av_free(mov->tracks[i].cluster[j]);
894         }
895         av_free(mov->tracks[i].cluster);
896         mov->tracks[i].cluster = NULL;
897         mov->tracks[i].ents_allocated = mov->tracks[i].entry = 0;
898     }
899     put_flush_packet(pb);
900
901     return res;
902 }
903
904 static AVOutputFormat mov_oformat = {
905     "mov",
906     "mov format",
907     NULL,
908     "mov",
909     sizeof(MOVContext),
910     CODEC_ID_PCM_ALAW,
911     CODEC_ID_MPEG4,
912     mov_write_header,
913     mov_write_packet,
914     mov_write_trailer,
915 };
916
917 static AVOutputFormat _3gp_oformat = {
918     "3gp",
919     "3gp format",
920     NULL,
921     "3gp",
922     sizeof(MOVContext),
923     CODEC_ID_AMR_NB,
924     CODEC_ID_H263,
925     mov_write_header,
926     mov_write_packet,
927     mov_write_trailer,
928 };
929
930 static AVOutputFormat mp4_oformat = {
931     "mp4",
932     "mp4 format",
933     "application/mp4",
934     "mp4,m4a",
935     sizeof(MOVContext),
936     CODEC_ID_AAC,
937     CODEC_ID_MPEG4,
938     mov_write_header,
939     mov_write_packet,
940     mov_write_trailer,
941 };
942
943 int movenc_init(void)
944 {
945     av_register_output_format(&mov_oformat);
946     av_register_output_format(&_3gp_oformat);
947     av_register_output_format(&mp4_oformat);
948     return 0;
949 }