Statistics
| Branch: | Revision:

ffmpeg / libavformat / movenc.c @ 69dde1ad

History | View | Annotate | Download (31.6 KB)

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
static int mov_write_audio_tag(ByteIOContext *pb, MOVTrack* track)
240
{
241
    int pos = url_ftell(pb);
242
    put_be32(pb, 0); /* size */
243

    
244
    if(track->enc->codec_id == CODEC_ID_PCM_MULAW)
245
      put_tag(pb, "ulaw");
246
    else if(track->enc->codec_id == CODEC_ID_PCM_ALAW)
247
      put_tag(pb, "alaw");
248
    else if(track->enc->codec_id == CODEC_ID_ADPCM_IMA_QT)
249
      put_tag(pb, "ima4");
250
    else if(track->enc->codec_id == CODEC_ID_MACE3)
251
      put_tag(pb, "MAC3");
252
    else if(track->enc->codec_id == CODEC_ID_MACE6)
253
      put_tag(pb, "MAC6");
254
    else if(track->enc->codec_id == CODEC_ID_AAC)
255
      put_tag(pb, "mp4a");
256
    else if(track->enc->codec_id == CODEC_ID_AMR_NB)
257
      put_tag(pb, "samr");
258
    else
259
      put_tag(pb, "    ");
260

    
261
    put_be32(pb, 0); /* Reserved */
262
    put_be16(pb, 0); /* Reserved */
263
    put_be16(pb, 1); /* Data-reference index, XXX  == 1 */
264

    
265
    /* SoundDescription */
266
    if(track->mode == MODE_MOV && track->enc->codec_id == CODEC_ID_AAC)
267
        put_be16(pb, 1); /* Version 1 */
268
    else
269
        put_be16(pb, 0); /* Version 0 */
270
    put_be16(pb, 0); /* Revision level */
271
    put_be32(pb, 0); /* Reserved */
272

    
273
    put_be16(pb, track->enc->channels); /* Number of channels */
274
    /* TODO: Currently hard-coded to 16-bit, there doesn't seem
275
                 to be a good way to get number of bits of audio */
276
    put_be16(pb, 0x10); /* Reserved */
277
    put_be16(pb, 0xfffe); /* compression ID (= 0) */
278
    put_be16(pb, 0xac); /* packet size (= 0) */
279
    put_be16(pb, track->timescale); /* Time scale */
280
    put_be16(pb, 0); /* Reserved */
281

    
282
    if(track->mode == MODE_MOV && track->enc->codec_id == CODEC_ID_AAC)
283
    {
284
        /* SoundDescription V1 extended info */
285
        put_be32(pb, track->enc->frame_size); /* Samples per packet  */
286
        put_be32(pb, 1536); /* Bytes per packet */
287
        put_be32(pb, 2); /* Bytes per frame */
288
        put_be32(pb, 2); /* Bytes per sample */
289
    }
290

    
291
    if(track->enc->codec_id == CODEC_ID_AAC) {
292
        if( track->mode == MODE_MOV ) mov_write_wave_tag(pb, track);
293
        else mov_write_esds_tag(pb, track);
294
    }
295
    if(track->enc->codec_id == CODEC_ID_AMR_NB)
296
        mov_write_damr_tag(pb);
297
    return updateSize (pb, pos);
298
}
299

    
300
static int mov_write_d263_tag(ByteIOContext *pb)
301
{
302
    put_be32(pb, 0xf); /* size */
303
    put_tag(pb, "d263");
304
    put_tag(pb, "FFMP");
305
    put_be16(pb, 0x0a);
306
    put_byte(pb, 0);
307
    return 0xf;
308
}
309

    
310
/* TODO: No idea about these values */
311
static int mov_write_svq3_tag(ByteIOContext *pb)
312
{
313
    put_be32(pb, 0x15);
314
    put_tag(pb, "SMI ");
315
    put_tag(pb, "SEQH");
316
    put_be32(pb, 0x5);
317
    put_be32(pb, 0xe2c0211d);
318
    put_be32(pb, 0xc0000000);
319
    put_byte(pb, 0);   
320
    return 0x15;
321
}
322

    
323
static unsigned int descrLength(unsigned int len)
324
{
325
    if (len < 0x00000080)
326
        return 2 + len;
327
    else if (len < 0x00004000)
328
        return 3 + len;
329
    else if(len < 0x00200000)
330
        return 4 + len;
331
    else
332
        return 5 + len;
333
}
334

    
335
static void putDescr(ByteIOContext *pb, int tag, int size)
336
{
337
    uint32_t len;
338
    uint8_t  vals[4];
339

    
340
    len = size;
341
    vals[3] = (uint8_t)(len & 0x7f);
342
    len >>= 7;
343
    vals[2] = (uint8_t)((len & 0x7f) | 0x80); 
344
    len >>= 7;
345
    vals[1] = (uint8_t)((len & 0x7f) | 0x80); 
346
    len >>= 7;
347
    vals[0] = (uint8_t)((len & 0x7f) | 0x80);
348

    
349
    put_byte(pb, tag); // DescriptorTag
350

    
351
    if (size < 0x00000080)
352
    {
353
        put_byte(pb, vals[3]);
354
    }
355
    else if (size < 0x00004000)
356
    {
357
        put_byte(pb, vals[2]);
358
        put_byte(pb, vals[3]);
359
    }
360
    else if (size < 0x00200000)
361
    {
362
        put_byte(pb, vals[1]);
363
        put_byte(pb, vals[2]);
364
        put_byte(pb, vals[3]);
365
    }
366
    else if (size < 0x10000000)
367
    {
368
        put_byte(pb, vals[0]);
369
        put_byte(pb, vals[1]);
370
        put_byte(pb, vals[2]);
371
        put_byte(pb, vals[3]);
372
    }
373
}
374

    
375
static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack* track) // Basic
376
{
377
    int decoderSpecificInfoLen = track->vosLen ? descrLength(track->vosLen):0;
378
    int pos = url_ftell(pb);
379

    
380
    put_be32(pb, 0);               // size
381
    put_tag(pb, "esds");
382
    put_be32(pb, 0);               // Version
383

    
384
    // ES descriptor
385
    putDescr(pb, 0x03, 3 + descrLength(13 + decoderSpecificInfoLen) +
386
             descrLength(1));
387
    put_be16(pb, 0x0001);          // ID (= 1)
388
    put_byte(pb, 0x00);            // flags (= no flags)
389

    
390
    // DecoderConfig descriptor
391
    putDescr(pb, 0x04, 13 + decoderSpecificInfoLen);
392

    
393
    if(track->enc->codec_id == CODEC_ID_AAC)
394
        put_byte(pb, 0x40);        // Object type indication
395
    else if(track->enc->codec_id == CODEC_ID_MPEG4)
396
        put_byte(pb, 0x20);        // Object type indication (Visual 14496-2)
397

    
398
    if(track->enc->codec_type == CODEC_TYPE_AUDIO)
399
        put_byte(pb, 0x15);            // flags (= Audiostream)
400
    else
401
        put_byte(pb, 0x11);            // flags (= Visualstream)
402

    
403
    put_byte(pb, 0x0);             // Buffersize DB (24 bits)
404
    put_be16(pb, 0x0dd2);          // Buffersize DB
405

    
406
    // TODO: find real values for these
407
    put_be32(pb, 0x0002e918);     // maxbitrate
408
    put_be32(pb, 0x00017e6b);     // avg bitrate
409

    
410
    if (track->vosLen)
411
    {
412
        // DecoderSpecific info descriptor
413
        putDescr(pb, 0x05, track->vosLen);
414
        put_buffer(pb, track->vosData, track->vosLen);
415
    }
416

    
417
    // SL descriptor
418
    putDescr(pb, 0x06, descrLength(1));
419
    put_byte(pb, 0x02);
420
    return updateSize (pb, pos);
421
}
422

    
423
static int mov_write_video_tag(ByteIOContext *pb, MOVTrack* track)
424
{
425
    int pos = url_ftell(pb);
426
    put_be32(pb, 0); /* size */
427
    if(track->enc->codec_id == CODEC_ID_SVQ1)
428
      put_tag(pb, "SVQ1");
429
    else if(track->enc->codec_id == CODEC_ID_SVQ3)
430
      put_tag(pb, "SVQ3");
431
    else if(track->enc->codec_id == CODEC_ID_MPEG4)
432
      put_tag(pb, "mp4v");
433
    else if(track->enc->codec_id == CODEC_ID_H263)
434
      put_tag(pb, "s263");
435
    else
436
      put_tag(pb, "    "); /* Unknown tag */
437

    
438
    put_be32(pb, 0); /* Reserved */
439
    put_be16(pb, 0); /* Reserved */
440
    put_be16(pb, 1); /* Data-reference index */
441

    
442
    put_be32(pb, 0); /* Reserved (= 02000c) */
443
    put_be32(pb, 0); /* Reserved ("SVis")*/
444
    put_be32(pb, 0); /* Reserved */
445
    put_be32(pb, 0); /* Reserved (400)*/
446
    put_be16(pb, track->enc->width); /* Video width */
447
    put_be16(pb, track->enc->height); /* Video height */
448
    put_be32(pb, 0x00480000); /* Reserved */
449
    put_be32(pb, 0x00480000); /* Reserved */
450
    put_be32(pb, 0); /* Reserved */
451
    put_be32(pb, 0); /* Reserved */
452
    put_be32(pb, 0); /* Reserved */
453
    put_be32(pb, 0); /* Reserved */
454
    put_be32(pb, 0); /* Reserved */
455
    put_be32(pb, 0); /* Reserved */
456

    
457
    put_be16(pb, 0); /* Reserved */
458
    put_be32(pb, 0); /* Reserved */
459
    put_be32(pb, 0); /* Reserved */
460
    put_be32(pb, 0); /* Reserved */
461
    put_be16(pb, 0x18); /* Reserved */
462
    put_be16(pb, 0xffff); /* Reserved */
463
    if(track->enc->codec_id == CODEC_ID_MPEG4)
464
        mov_write_esds_tag(pb, track);
465
    else if(track->enc->codec_id == CODEC_ID_H263)
466
        mov_write_d263_tag(pb);
467
    else if(track->enc->codec_id == CODEC_ID_SVQ3)
468
        mov_write_svq3_tag(pb);    
469

    
470
    return updateSize (pb, pos);
471
}
472

    
473
static int mov_write_stsd_tag(ByteIOContext *pb, MOVTrack* track)
474
{
475
    int pos = url_ftell(pb);
476
    put_be32(pb, 0); /* size */
477
    put_tag(pb, "stsd");
478
    put_be32(pb, 0); /* version & flags */
479
    put_be32(pb, 1); /* entry count */
480
    if (track->enc->codec_type == CODEC_TYPE_VIDEO)
481
        mov_write_video_tag(pb, track);
482
    else if (track->enc->codec_type == CODEC_TYPE_AUDIO)
483
        mov_write_audio_tag(pb, track);
484
    return updateSize(pb, pos);
485
}
486

    
487
/* TODO?: Currently all samples/frames seem to have same duration */
488
/* Time to sample atom */
489
static int mov_write_stts_tag(ByteIOContext *pb, MOVTrack* track)
490
{
491
    put_be32(pb, 0x18); /* size */
492
    put_tag(pb, "stts");
493
    put_be32(pb, 0); /* version & flags */
494
    put_be32(pb, 1); /* entry count */
495

    
496
    put_be32(pb, track->sampleCount); /* sample count */
497
    put_be32(pb, track->sampleDuration); /* sample duration */
498
    return 0x18;
499
}
500

    
501
static int mov_write_dref_tag(ByteIOContext *pb)
502
{
503
    put_be32(pb, 28); /* size */
504
    put_tag(pb, "dref");
505
    put_be32(pb, 0); /* version & flags */
506
    put_be32(pb, 1); /* entry count */
507

    
508
    put_be32(pb, 0xc); /* size */
509
    put_tag(pb, "url ");
510
    put_be32(pb, 1); /* version & flags */
511

    
512
    return 28;
513
}
514

    
515
static int mov_write_stbl_tag(ByteIOContext *pb, MOVTrack* track)
516
{
517
    int pos = url_ftell(pb);
518
    put_be32(pb, 0); /* size */
519
    put_tag(pb, "stbl");
520
    mov_write_stsd_tag(pb, track);
521
    mov_write_stts_tag(pb, track);
522
    if (track->enc->codec_type == CODEC_TYPE_VIDEO &&
523
        track->hasKeyframes)
524
        mov_write_stss_tag(pb, track);
525
    mov_write_stsc_tag(pb, track);
526
    mov_write_stsz_tag(pb, track);
527
    mov_write_stco_tag(pb, track);
528
    return updateSize(pb, pos);
529
}
530

    
531
static int mov_write_dinf_tag(ByteIOContext *pb)
532
{
533
    int pos = url_ftell(pb);
534
    put_be32(pb, 0); /* size */
535
    put_tag(pb, "dinf");
536
    mov_write_dref_tag(pb);
537
    return updateSize(pb, pos);
538
}
539

    
540
static int mov_write_smhd_tag(ByteIOContext *pb)
541
{
542
    put_be32(pb, 16); /* size */
543
    put_tag(pb, "smhd");
544
    put_be32(pb, 0); /* version & flags */
545
    put_be16(pb, 0); /* reserved (balance, normally = 0) */
546
    put_be16(pb, 0); /* reserved */
547
    return 16;
548
}
549

    
550
static int mov_write_vmhd_tag(ByteIOContext *pb)
551
{
552
    put_be32(pb, 0x14); /* size (always 0x14) */
553
    put_tag(pb, "vmhd");
554
    put_be32(pb, 0x01); /* version & flags */
555
    put_be64(pb, 0); /* reserved (graphics mode = copy) */
556
    return 0x14;
557
}
558

    
559
static int mov_write_minf_tag(ByteIOContext *pb, MOVTrack* track)
560
{
561
    int pos = url_ftell(pb);
562
    put_be32(pb, 0); /* size */
563
    put_tag(pb, "minf");
564
    if(track->enc->codec_type == CODEC_TYPE_VIDEO)
565
        mov_write_vmhd_tag(pb);
566
    else
567
        mov_write_smhd_tag(pb);
568
    mov_write_dinf_tag(pb);
569
    mov_write_stbl_tag(pb, track);
570
    return updateSize(pb, pos);
571
}
572

    
573
static int mov_write_hdlr_tag(ByteIOContext *pb, MOVTrack* track)
574
{
575
    char *str;
576
    int pos = url_ftell(pb);
577
    put_be32(pb, 0); /* size */
578
    put_tag(pb, "hdlr");
579
    put_be32(pb, 0); /* Version & flags */
580
    put_be32(pb, 0); /* reserved */
581
    if(track->enc->codec_type == CODEC_TYPE_VIDEO)
582
        put_tag(pb, "vide"); /* handler type */
583
    else
584
        put_tag(pb, "soun"); /* handler type */
585
    put_be32(pb ,0); /* reserved */
586
    put_be32(pb ,0); /* reserved */
587
    put_be32(pb ,0); /* reserved */
588
    if(track->enc->codec_type == CODEC_TYPE_VIDEO)
589
        str = "VideoHandler";
590
    else
591
        str = "SoundHandler";
592
    put_byte(pb, strlen(str)); /* string counter */
593
    put_buffer(pb, str, strlen(str));
594
    return updateSize(pb, pos);
595
}
596

    
597
static int mov_write_mdhd_tag(ByteIOContext *pb, MOVTrack* track)
598
{
599
    put_be32(pb, 32); /* size */
600
    put_tag(pb, "mdhd");
601
    put_be32(pb, 0); /* Version & flags */
602
    put_be32(pb, track->time); /* creation time */
603
    put_be32(pb, track->time); /* modification time */
604
    put_be32(pb, track->timescale); /* time scale (sample rate for audio) */ 
605
    put_be32(pb, track->trackDuration); /* duration */
606
    put_be16(pb, 0); /* language, 0 = english */
607
    put_be16(pb, 0); /* reserved (quality) */
608
    return 32;
609
}
610

    
611
static int mov_write_mdia_tag(ByteIOContext *pb, MOVTrack* track)
612
{
613
    int pos = url_ftell(pb);
614
    put_be32(pb, 0); /* size */
615
    put_tag(pb, "mdia");
616
    mov_write_mdhd_tag(pb, track);
617
    mov_write_hdlr_tag(pb, track);
618
    mov_write_minf_tag(pb, track);
619
    return updateSize(pb, pos);
620
}
621

    
622
static int mov_write_tkhd_tag(ByteIOContext *pb, MOVTrack* track)
623
{
624
    int64_t maxTrackLenTemp;
625
    put_be32(pb, 0x5c); /* size (always 0x5c) */
626
    put_tag(pb, "tkhd");
627
    put_be32(pb, 0xf); /* version & flags (track enabled) */
628
    put_be32(pb, track->time); /* creation time */
629
    put_be32(pb, track->time); /* modification time */
630
    put_be32(pb, track->trackID); /* track-id */
631
    put_be32(pb, 0); /* reserved */
632
    maxTrackLenTemp = ((int64_t)globalTimescale*(int64_t)track->trackDuration)/(int64_t)track->timescale;
633
    put_be32(pb, (long)maxTrackLenTemp); /* duration */
634

    
635
    put_be32(pb, 0); /* reserved */
636
    put_be32(pb, 0); /* reserved */
637
    put_be32(pb, 0x0); /* reserved (Layer & Alternate group) */
638
    /* Volume, only for audio */
639
    if(track->enc->codec_type == CODEC_TYPE_AUDIO)
640
        put_be16(pb, 0x0100);
641
    else
642
        put_be16(pb, 0);
643
    put_be16(pb, 0); /* reserved */
644

    
645
    /* Matrix structure */
646
    put_be32(pb, 0x00010000); /* reserved */
647
    put_be32(pb, 0x0); /* reserved */
648
    put_be32(pb, 0x0); /* reserved */
649
    put_be32(pb, 0x0); /* reserved */
650
    put_be32(pb, 0x00010000); /* reserved */
651
    put_be32(pb, 0x0); /* reserved */
652
    put_be32(pb, 0x0); /* reserved */
653
    put_be32(pb, 0x0); /* reserved */
654
    put_be32(pb, 0x40000000); /* reserved */
655

    
656
    /* Track width and height, for visual only */
657
    if(track->enc->codec_type == CODEC_TYPE_VIDEO) {
658
        double sample_aspect_ratio = av_q2d(track->enc->sample_aspect_ratio);
659
        if( !sample_aspect_ratio ) sample_aspect_ratio = 1;
660
        put_be32(pb, sample_aspect_ratio * track->enc->width*0x10000);
661
        put_be32(pb, track->enc->height*0x10000);
662
    }
663
    else {
664
        put_be32(pb, 0);
665
        put_be32(pb, 0);
666
    }
667
    return 0x5c;
668
}
669

    
670
static int mov_write_trak_tag(ByteIOContext *pb, MOVTrack* track)
671
{
672
    int pos = url_ftell(pb);
673
    put_be32(pb, 0); /* size */
674
    put_tag(pb, "trak");
675
    mov_write_tkhd_tag(pb, track);
676
    mov_write_mdia_tag(pb, track);
677
    return updateSize(pb, pos);
678
}
679

    
680
/* TODO: Not sorted out, but not necessary either */
681
static int mov_write_iods_tag(ByteIOContext *pb, MOVContext *mov)
682
{
683
    put_be32(pb, 0x15); /* size */
684
    put_tag(pb, "iods");
685
    put_be32(pb, 0);    /* version & flags */
686
    put_be16(pb, 0x1007);
687
    put_byte(pb, 0);
688
    put_be16(pb, 0x4fff);
689
    put_be16(pb, 0xfffe);
690
    put_be16(pb, 0x01ff);
691
    return 0x15;
692
}
693

    
694
static int mov_write_mvhd_tag(ByteIOContext *pb, MOVContext *mov)
695
{
696
    int maxTrackID = 1, maxTrackLen = 0, i;
697
    int64_t maxTrackLenTemp;
698

    
699
    put_be32(pb, 0x6c); /* size (always 0x6c) */
700
    put_tag(pb, "mvhd");
701
    put_be32(pb, 0); /* version & flags */
702
    put_be32(pb, mov->time); /* creation time */
703
    put_be32(pb, mov->time); /* modification time */
704
    put_be32(pb, mov->timescale); /* timescale */
705
    for (i=0; i<MAX_STREAMS; i++) {
706
        if(mov->tracks[i].entry > 0) {
707
            maxTrackLenTemp = ((int64_t)globalTimescale*(int64_t)mov->tracks[i].trackDuration)/(int64_t)mov->tracks[i].timescale;
708
            if(maxTrackLen < maxTrackLenTemp)
709
                maxTrackLen = maxTrackLenTemp;
710
            if(maxTrackID < mov->tracks[i].trackID)
711
                maxTrackID = mov->tracks[i].trackID;
712
        }
713
    }
714
    put_be32(pb, maxTrackLen); /* duration of longest track */
715

    
716
    put_be32(pb, 0x00010000); /* reserved (preferred rate) 1.0 = normal */
717
    put_be16(pb, 0x0100); /* reserved (preferred volume) 1.0 = normal */
718
    put_be16(pb, 0); /* reserved */
719
    put_be32(pb, 0); /* reserved */
720
    put_be32(pb, 0); /* reserved */
721

    
722
    /* Matrix structure */
723
    put_be32(pb, 0x00010000); /* reserved */
724
    put_be32(pb, 0x0); /* reserved */
725
    put_be32(pb, 0x0); /* reserved */
726
    put_be32(pb, 0x0); /* reserved */
727
    put_be32(pb, 0x00010000); /* reserved */
728
    put_be32(pb, 0x0); /* reserved */
729
    put_be32(pb, 0x0); /* reserved */
730
    put_be32(pb, 0x0); /* reserved */
731
    put_be32(pb, 0x40000000); /* reserved */
732

    
733
    put_be32(pb, 0); /* reserved (preview time) */
734
    put_be32(pb, 0); /* reserved (preview duration) */
735
    put_be32(pb, 0); /* reserved (poster time) */
736
    put_be32(pb, 0); /* reserved (selection time) */
737
    put_be32(pb, 0); /* reserved (selection duration) */
738
    put_be32(pb, 0); /* reserved (current time) */
739
    put_be32(pb, maxTrackID+1); /* Next track id */
740
    return 0x6c;
741
}
742

    
743
static int mov_write_udta_tag(ByteIOContext *pb, MOVContext* mov,
744
                              AVFormatContext *s)
745
{
746
    int pos = url_ftell(pb);
747
    int i;
748

    
749
    put_be32(pb, 0); /* size */
750
    put_tag(pb, "udta");
751

    
752
    /* Requirements */
753
    for (i=0; i<MAX_STREAMS; i++) {
754
        if(mov->tracks[i].entry <= 0) continue;
755
        if (mov->tracks[i].enc->codec_id == CODEC_ID_AAC ||
756
            mov->tracks[i].enc->codec_id == CODEC_ID_MPEG4) {
757
            int pos = url_ftell(pb);
758
            put_be32(pb, 0); /* size */
759
            put_tag(pb, "\251req");
760
            put_be16(pb, sizeof("QuickTime 6.0 or greater") - 1);
761
            put_be16(pb, 0);
762
            put_buffer(pb, "QuickTime 6.0 or greater",
763
                       sizeof("QuickTime 6.0 or greater") - 1);
764
            updateSize(pb, pos);
765
            break;
766
        }
767
    }
768

    
769
    /* Encoder */
770
    {
771
        int pos = url_ftell(pb);
772
        put_be32(pb, 0); /* size */
773
        put_tag(pb, "\251enc");
774
        put_be16(pb, sizeof(LIBAVFORMAT_IDENT) - 1); /* string length */
775
        put_be16(pb, 0);
776
        put_buffer(pb, LIBAVFORMAT_IDENT, sizeof(LIBAVFORMAT_IDENT) - 1);
777
        updateSize(pb, pos);
778
    }
779

    
780
    if( s->title[0] )
781
    {
782
        int pos = url_ftell(pb);
783
        put_be32(pb, 0); /* size */
784
        put_tag(pb, "\251nam");
785
        put_be16(pb, strlen(s->title)); /* string length */
786
        put_be16(pb, 0);
787
        put_buffer(pb, s->title, strlen(s->title));
788
        updateSize(pb, pos);
789
    }
790

    
791
    if( s->author[0] )
792
    {
793
        int pos = url_ftell(pb);
794
        put_be32(pb, 0); /* size */
795
        put_tag(pb, /*"\251aut"*/ "\251day" );
796
        put_be16(pb, strlen(s->author)); /* string length */
797
        put_be16(pb, 0);
798
        put_buffer(pb, s->author, strlen(s->author));
799
        updateSize(pb, pos);
800
    }
801

    
802
    if( s->comment[0] )
803
    {
804
        int pos = url_ftell(pb);
805
        put_be32(pb, 0); /* size */
806
        put_tag(pb, "\251des");
807
        put_be16(pb, strlen(s->comment)); /* string length */
808
        put_be16(pb, 0);
809
        put_buffer(pb, s->comment, strlen(s->comment));
810
        updateSize(pb, pos);
811
    }
812

    
813
    return updateSize(pb, pos);
814
}
815

    
816
static int mov_write_moov_tag(ByteIOContext *pb, MOVContext *mov,
817
                              AVFormatContext *s)
818
{
819
    int pos, i;
820
    pos = url_ftell(pb);
821
    put_be32(pb, 0); /* size placeholder*/
822
    put_tag(pb, "moov");
823
    mov->timescale = globalTimescale;
824

    
825
    for (i=0; i<MAX_STREAMS; i++) {
826
        if(mov->tracks[i].entry <= 0) continue;
827

    
828
        if(mov->tracks[i].enc->codec_type == CODEC_TYPE_VIDEO) {
829
            mov->tracks[i].timescale = mov->tracks[i].enc->frame_rate;
830
            mov->tracks[i].sampleDuration = mov->tracks[i].enc->frame_rate_base;
831
        }
832
        else if(mov->tracks[i].enc->codec_type == CODEC_TYPE_AUDIO) {
833
            /* If AMR, track timescale = 8000, AMR_WB = 16000 */
834
            if(mov->tracks[i].enc->codec_id == CODEC_ID_AMR_NB) {
835
                mov->tracks[i].sampleDuration = 160;  // Bytes per chunk
836
                mov->tracks[i].timescale = 8000;
837
            }
838
            else {
839
                mov->tracks[i].timescale = mov->tracks[i].enc->sample_rate;
840
                mov->tracks[i].sampleDuration = mov->tracks[i].enc->frame_size;
841
            }
842
        }
843

    
844
        mov->tracks[i].trackDuration = 
845
            mov->tracks[i].sampleCount * mov->tracks[i].sampleDuration;
846
        mov->tracks[i].time = mov->time;
847
        mov->tracks[i].trackID = i+1;
848
    }
849

    
850
    mov_write_mvhd_tag(pb, mov);
851
    //mov_write_iods_tag(pb, mov);
852
    for (i=0; i<MAX_STREAMS; i++) {
853
        if(mov->tracks[i].entry > 0) {
854
            mov_write_trak_tag(pb, &(mov->tracks[i]));
855
        }
856
    }
857

    
858
    mov_write_udta_tag(pb, mov, s);
859

    
860
    return updateSize(pb, pos);
861
}
862

    
863
int mov_write_mdat_tag(ByteIOContext *pb, MOVContext* mov)
864
{
865
    mov->mdat_pos = url_ftell(pb); 
866
    put_be32(pb, 0); /* size placeholder*/
867
    put_tag(pb, "mdat");
868
    return 0;
869
}
870

    
871
/* TODO: This needs to be more general */
872
int mov_write_ftyp_tag(ByteIOContext *pb, AVFormatContext *s)
873
{
874
    MOVContext *mov = s->priv_data;
875

    
876
    put_be32(pb, 0x14 ); /* size */
877
    put_tag(pb, "ftyp");
878

    
879
    if ( mov->mode == MODE_3GP )
880
        put_tag(pb, "3gp4");
881
    else
882
        put_tag(pb, "isom");
883

    
884
    put_be32(pb, 0x200 );
885

    
886
    if ( mov->mode == MODE_3GP )
887
        put_tag(pb, "3gp4");
888
    else
889
        put_tag(pb, "mp41");
890

    
891
    return 0x14;
892
}
893

    
894
static int mov_write_header(AVFormatContext *s)
895
{
896
    ByteIOContext *pb = &s->pb;
897
    MOVContext *mov = s->priv_data;
898
    int i;
899

    
900
    /* Default mode == MP4 */
901
    mov->mode = MODE_MP4;
902

    
903
    if (s->oformat != NULL) {
904
        if (!strcmp("3gp", s->oformat->name)) mov->mode = MODE_3GP;
905
        else if (!strcmp("mov", s->oformat->name)) mov->mode = MODE_MOV;
906

    
907
        if ( mov->mode == MODE_3GP || mov->mode == MODE_MP4 )
908
            mov_write_ftyp_tag(pb,s);
909
    }
910

    
911
    for (i=0; i<MAX_STREAMS; i++) {
912
        mov->tracks[i].mode = mov->mode;
913
    }
914

    
915
    put_flush_packet(pb);
916

    
917
    return 0;
918
}
919

    
920
static int Timestamp() {
921
    return 1067949799U+(24107*86400); //its the modification time of this line :)
922
}
923

    
924
static int mov_write_packet(AVFormatContext *s, int stream_index,
925
                            const uint8_t *buf, int size, int64_t pts)
926
{
927
    MOVContext *mov = s->priv_data;
928
    ByteIOContext *pb = &s->pb;
929
    AVCodecContext *enc = &s->streams[stream_index]->codec;
930
    MOVTrack* trk = &mov->tracks[stream_index];
931
    int cl, id;
932
    unsigned int samplesInChunk = 0;
933

    
934
    if (url_is_streamed(&s->pb)) return 0; /* Can't handle that */
935
    if (!size) return 0; /* Discard 0 sized packets */
936

    
937
    if (enc->codec_type == CODEC_TYPE_VIDEO ) {
938
        samplesInChunk = 1;
939
    }
940
    else if (enc->codec_type == CODEC_TYPE_AUDIO ) {
941
        if( enc->codec_id == CODEC_ID_AMR_NB) {
942
            /* We must find out how many AMR blocks there are in one packet */
943
            static uint16_t packed_size[16] =
944
                {13, 14, 16, 18, 20, 21, 27, 32, 6, 0, 0, 0, 0, 0, 0, 0};
945
            int len = 0;
946

    
947
            while (len < size && samplesInChunk < 100) {
948
                len += packed_size[(buf[len] >> 3) & 0x0F];
949
                samplesInChunk++;
950
            }
951
        }
952
        else if(enc->codec_id == CODEC_ID_PCM_ALAW) {
953
            samplesInChunk = size/enc->channels;
954
        }
955
        else {
956
            samplesInChunk = 1;
957
        }
958
    }
959

    
960
    if ((enc->codec_id == CODEC_ID_MPEG4 || enc->codec_id == CODEC_ID_AAC)
961
        && trk->vosLen == 0) {
962
        assert(enc->extradata_size);
963

    
964
        trk->vosLen = enc->extradata_size;
965
        trk->vosData = av_malloc(trk->vosLen);
966
        memcpy(trk->vosData, enc->extradata, trk->vosLen);
967
    }
968

    
969
    cl = trk->entry / MOV_INDEX_CLUSTER_SIZE;
970
    id = trk->entry % MOV_INDEX_CLUSTER_SIZE;
971

    
972
    if (trk->ents_allocated <= trk->entry) {
973
        trk->cluster = av_realloc(trk->cluster, (cl+1)*sizeof(void*)); 
974
        if (!trk->cluster)
975
            return -1;
976
        trk->cluster[cl] = av_malloc(MOV_INDEX_CLUSTER_SIZE*sizeof(MOVIentry));
977
        if (!trk->cluster[cl])
978
            return -1;
979
        trk->ents_allocated += MOV_INDEX_CLUSTER_SIZE;
980
    }
981
    if (mov->mdat_written == 0) {
982
        mov_write_mdat_tag(pb, mov);
983
        mov->mdat_written = 1;
984
        mov->time = Timestamp();
985
    }
986

    
987
    trk->cluster[cl][id].pos = url_ftell(pb);
988
    trk->cluster[cl][id].samplesInChunk = samplesInChunk;
989
    trk->cluster[cl][id].size = size;
990
    trk->cluster[cl][id].entries = samplesInChunk;
991
    if(enc->codec_type == CODEC_TYPE_VIDEO) {
992
        trk->cluster[cl][id].key_frame = enc->coded_frame->key_frame;
993
        if(enc->coded_frame->pict_type == FF_I_TYPE)
994
            trk->hasKeyframes = 1;
995
    }
996
    trk->enc = enc;
997
    trk->entry++;
998
    trk->sampleCount += samplesInChunk;
999
    trk->mdat_size += size;
1000

    
1001
    put_buffer(pb, buf, size);
1002

    
1003
    put_flush_packet(pb);
1004
    return 0;
1005
}
1006

    
1007
static int mov_write_trailer(AVFormatContext *s)
1008
{
1009
    MOVContext *mov = s->priv_data;
1010
    ByteIOContext *pb = &s->pb;
1011
    int res = 0;
1012
    int i, j;
1013

    
1014
    offset_t moov_pos = url_ftell(pb);
1015

    
1016
    /* Write size of mdat tag */
1017
    for (i=0, j=0; i<MAX_STREAMS; i++) {
1018
        if(mov->tracks[i].ents_allocated > 0) {
1019
            j += mov->tracks[i].mdat_size;
1020
        }
1021
    }
1022
    url_fseek(pb, mov->mdat_pos, SEEK_SET);
1023
    put_be32(pb, j+8);
1024
    url_fseek(pb, moov_pos, SEEK_SET);
1025

    
1026
    mov_write_moov_tag(pb, mov, s);
1027

    
1028
    for (i=0; i<MAX_STREAMS; i++) {
1029
        for (j=0; j<mov->tracks[i].ents_allocated/MOV_INDEX_CLUSTER_SIZE; j++) {
1030
            av_free(mov->tracks[i].cluster[j]);
1031
        }
1032
        av_free(mov->tracks[i].cluster);
1033
        if( mov->tracks[i].vosLen ) av_free( mov->tracks[i].vosData );
1034

    
1035
        mov->tracks[i].cluster = NULL;
1036
        mov->tracks[i].ents_allocated = mov->tracks[i].entry = 0;
1037
    }
1038

    
1039
    put_flush_packet(pb);
1040

    
1041
    return res;
1042
}
1043

    
1044
static AVOutputFormat mov_oformat = {
1045
    "mov",
1046
    "mov format",
1047
    NULL,
1048
    "mov",
1049
    sizeof(MOVContext),
1050
    CODEC_ID_AAC,
1051
    CODEC_ID_MPEG4,
1052
    mov_write_header,
1053
    mov_write_packet,
1054
    mov_write_trailer,
1055
};
1056

    
1057
static AVOutputFormat _3gp_oformat = {
1058
    "3gp",
1059
    "3gp format",
1060
    NULL,
1061
    "3gp",
1062
    sizeof(MOVContext),
1063
    CODEC_ID_AMR_NB,
1064
    CODEC_ID_H263,
1065
    mov_write_header,
1066
    mov_write_packet,
1067
    mov_write_trailer,
1068
};
1069

    
1070
static AVOutputFormat mp4_oformat = {
1071
    "mp4",
1072
    "mp4 format",
1073
    "application/mp4",
1074
    "mp4,m4a",
1075
    sizeof(MOVContext),
1076
    CODEC_ID_AAC,
1077
    CODEC_ID_MPEG4,
1078
    mov_write_header,
1079
    mov_write_packet,
1080
    mov_write_trailer,
1081
};
1082

    
1083
int movenc_init(void)
1084
{
1085
    av_register_output_format(&mov_oformat);
1086
    av_register_output_format(&_3gp_oformat);
1087
    av_register_output_format(&mp4_oformat);
1088
    return 0;
1089
}