Statistics
| Branch: | Revision:

ffmpeg / libavformat / movenc.c @ 5a757507

History | View | Annotate | Download (32.3 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 if(track->enc->codec_id == CODEC_ID_PCM_S16BE)
259
      put_tag(pb, "twos");
260
    else if(track->enc->codec_id == CODEC_ID_PCM_S16LE)
261
      put_tag(pb, "sowt");
262
    else
263
      put_tag(pb, "    ");
264

    
265
    put_be32(pb, 0); /* Reserved */
266
    put_be16(pb, 0); /* Reserved */
267
    put_be16(pb, 1); /* Data-reference index, XXX  == 1 */
268

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

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

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

    
295
    if(track->enc->codec_id == CODEC_ID_AAC) {
296
        if( track->mode == MODE_MOV ) mov_write_wave_tag(pb, track);
297
        else mov_write_esds_tag(pb, track);
298
    }
299
    if(track->enc->codec_id == CODEC_ID_AMR_NB)
300
        mov_write_damr_tag(pb);
301
    return updateSize (pb, pos);
302
}
303

    
304
static int mov_write_d263_tag(ByteIOContext *pb)
305
{
306
    put_be32(pb, 0xf); /* size */
307
    put_tag(pb, "d263");
308
    put_tag(pb, "FFMP");
309
    put_be16(pb, 0x0a);
310
    put_byte(pb, 0);
311
    return 0xf;
312
}
313

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

    
327
static unsigned int descrLength(unsigned int len)
328
{
329
    if (len < 0x00000080)
330
        return 2 + len;
331
    else if (len < 0x00004000)
332
        return 3 + len;
333
    else if(len < 0x00200000)
334
        return 4 + len;
335
    else
336
        return 5 + len;
337
}
338

    
339
static void putDescr(ByteIOContext *pb, int tag, int size)
340
{
341
    uint32_t len;
342
    uint8_t  vals[4];
343

    
344
    len = size;
345
    vals[3] = (uint8_t)(len & 0x7f);
346
    len >>= 7;
347
    vals[2] = (uint8_t)((len & 0x7f) | 0x80); 
348
    len >>= 7;
349
    vals[1] = (uint8_t)((len & 0x7f) | 0x80); 
350
    len >>= 7;
351
    vals[0] = (uint8_t)((len & 0x7f) | 0x80);
352

    
353
    put_byte(pb, tag); // DescriptorTag
354

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

    
379
static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack* track) // Basic
380
{
381
    int decoderSpecificInfoLen = track->vosLen ? descrLength(track->vosLen):0;
382
    int pos = url_ftell(pb);
383

    
384
    put_be32(pb, 0);               // size
385
    put_tag(pb, "esds");
386
    put_be32(pb, 0);               // Version
387

    
388
    // ES descriptor
389
    putDescr(pb, 0x03, 3 + descrLength(13 + decoderSpecificInfoLen) +
390
             descrLength(1));
391
    put_be16(pb, 0x0001);          // ID (= 1)
392
    put_byte(pb, 0x00);            // flags (= no flags)
393

    
394
    // DecoderConfig descriptor
395
    putDescr(pb, 0x04, 13 + decoderSpecificInfoLen);
396

    
397
    if(track->enc->codec_id == CODEC_ID_AAC)
398
        put_byte(pb, 0x40);        // Object type indication
399
    else if(track->enc->codec_id == CODEC_ID_MPEG4)
400
        put_byte(pb, 0x20);        // Object type indication (Visual 14496-2)
401

    
402
    if(track->enc->codec_type == CODEC_TYPE_AUDIO)
403
        put_byte(pb, 0x15);            // flags (= Audiostream)
404
    else
405
        put_byte(pb, 0x11);            // flags (= Visualstream)
406

    
407
    put_byte(pb, 0x0);             // Buffersize DB (24 bits)
408
    put_be16(pb, 0x0dd2);          // Buffersize DB
409

    
410
    // TODO: find real values for these
411
    put_be32(pb, 0x0002e918);     // maxbitrate
412
    put_be32(pb, 0x00017e6b);     // avg bitrate
413

    
414
    if (track->vosLen)
415
    {
416
        // DecoderSpecific info descriptor
417
        putDescr(pb, 0x05, track->vosLen);
418
        put_buffer(pb, track->vosData, track->vosLen);
419
    }
420

    
421
    // SL descriptor
422
    putDescr(pb, 0x06, 1);
423
    put_byte(pb, 0x02);
424
    return updateSize (pb, pos);
425
}
426

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

    
444
    put_be32(pb, 0); /* Reserved */
445
    put_be16(pb, 0); /* Reserved */
446
    put_be16(pb, 1); /* Data-reference index */
447

    
448
    put_be32(pb, 0); /* Reserved (= 02000c) */
449
    put_be32(pb, 0); /* Reserved ("SVis")*/
450
    put_be32(pb, 0); /* Reserved */
451
    put_be32(pb, 0); /* Reserved (400)*/
452
    put_be16(pb, track->enc->width); /* Video width */
453
    put_be16(pb, track->enc->height); /* Video height */
454
    put_be32(pb, 0x00480000); /* Reserved */
455
    put_be32(pb, 0x00480000); /* Reserved */
456
    put_be32(pb, 0); /* Data size (= 0) */
457
    put_be16(pb, 1); /* Frame count (= 1) */
458
    
459
    put_be32(pb, 0); /* Reserved */
460
    put_be32(pb, 0); /* Reserved */
461
    put_be32(pb, 0); /* Reserved */
462
    put_be32(pb, 0); /* Reserved */
463
    put_be32(pb, 0); /* Reserved */
464
    put_be32(pb, 0); /* Reserved */
465
    put_be32(pb, 0); /* Reserved */
466
    put_be32(pb, 0); /* Reserved */
467
    
468
    put_be16(pb, 0x18); /* Reserved */
469
    put_be16(pb, 0xffff); /* Reserved */
470
    if(track->enc->codec_id == CODEC_ID_MPEG4)
471
        mov_write_esds_tag(pb, track);
472
    else if(track->enc->codec_id == CODEC_ID_H263)
473
        mov_write_d263_tag(pb);
474
    else if(track->enc->codec_id == CODEC_ID_SVQ3)
475
        mov_write_svq3_tag(pb);    
476

    
477
    return updateSize (pb, pos);
478
}
479

    
480
static int mov_write_stsd_tag(ByteIOContext *pb, MOVTrack* track)
481
{
482
    int pos = url_ftell(pb);
483
    put_be32(pb, 0); /* size */
484
    put_tag(pb, "stsd");
485
    put_be32(pb, 0); /* version & flags */
486
    put_be32(pb, 1); /* entry count */
487
    if (track->enc->codec_type == CODEC_TYPE_VIDEO)
488
        mov_write_video_tag(pb, track);
489
    else if (track->enc->codec_type == CODEC_TYPE_AUDIO)
490
        mov_write_audio_tag(pb, track);
491
    return updateSize(pb, pos);
492
}
493

    
494
/* TODO?: Currently all samples/frames seem to have same duration */
495
/* Time to sample atom */
496
static int mov_write_stts_tag(ByteIOContext *pb, MOVTrack* track)
497
{
498
    put_be32(pb, 0x18); /* size */
499
    put_tag(pb, "stts");
500
    put_be32(pb, 0); /* version & flags */
501
    put_be32(pb, 1); /* entry count */
502

    
503
    put_be32(pb, track->sampleCount); /* sample count */
504
    put_be32(pb, track->sampleDuration); /* sample duration */
505
    return 0x18;
506
}
507

    
508
static int mov_write_dref_tag(ByteIOContext *pb)
509
{
510
    put_be32(pb, 28); /* size */
511
    put_tag(pb, "dref");
512
    put_be32(pb, 0); /* version & flags */
513
    put_be32(pb, 1); /* entry count */
514

    
515
    put_be32(pb, 0xc); /* size */
516
    put_tag(pb, "url ");
517
    put_be32(pb, 1); /* version & flags */
518

    
519
    return 28;
520
}
521

    
522
static int mov_write_stbl_tag(ByteIOContext *pb, MOVTrack* track)
523
{
524
    int pos = url_ftell(pb);
525
    put_be32(pb, 0); /* size */
526
    put_tag(pb, "stbl");
527
    mov_write_stsd_tag(pb, track);
528
    mov_write_stts_tag(pb, track);
529
    if (track->enc->codec_type == CODEC_TYPE_VIDEO &&
530
        track->hasKeyframes)
531
        mov_write_stss_tag(pb, track);
532
    mov_write_stsc_tag(pb, track);
533
    mov_write_stsz_tag(pb, track);
534
    mov_write_stco_tag(pb, track);
535
    return updateSize(pb, pos);
536
}
537

    
538
static int mov_write_dinf_tag(ByteIOContext *pb)
539
{
540
    int pos = url_ftell(pb);
541
    put_be32(pb, 0); /* size */
542
    put_tag(pb, "dinf");
543
    mov_write_dref_tag(pb);
544
    return updateSize(pb, pos);
545
}
546

    
547
static int mov_write_smhd_tag(ByteIOContext *pb)
548
{
549
    put_be32(pb, 16); /* size */
550
    put_tag(pb, "smhd");
551
    put_be32(pb, 0); /* version & flags */
552
    put_be16(pb, 0); /* reserved (balance, normally = 0) */
553
    put_be16(pb, 0); /* reserved */
554
    return 16;
555
}
556

    
557
static int mov_write_vmhd_tag(ByteIOContext *pb)
558
{
559
    put_be32(pb, 0x14); /* size (always 0x14) */
560
    put_tag(pb, "vmhd");
561
    put_be32(pb, 0x01); /* version & flags */
562
    put_be64(pb, 0); /* reserved (graphics mode = copy) */
563
    return 0x14;
564
}
565

    
566
static int mov_write_hdlr_tag(ByteIOContext *pb, MOVTrack* track)
567
{
568
    char *descr, *hdlr, *hdlr_type;
569
    int pos = url_ftell(pb);
570
    
571
    if (!track) { /* no media --> data handler */
572
        hdlr = "dhlr";
573
        hdlr_type = "url ";
574
        descr = "DataHandler";
575
    } else {
576
        hdlr = (track->mode == MODE_MOV) ? "mhlr" : "\0\0\0\0";
577
        if (track->enc->codec_type == CODEC_TYPE_VIDEO) {
578
            hdlr_type = "vide";
579
            descr = "VideoHandler";
580
        } else {
581
            hdlr_type = "soun";
582
            descr = "SoundHandler";
583
        }
584
    }
585
    
586
    put_be32(pb, 0); /* size */
587
    put_tag(pb, "hdlr");
588
    put_be32(pb, 0); /* Version & flags */
589
    put_buffer(pb, hdlr, 4); /* handler */
590
    put_tag(pb, hdlr_type); /* handler type */
591
    put_be32(pb ,0); /* reserved */
592
    put_be32(pb ,0); /* reserved */
593
    put_be32(pb ,0); /* reserved */
594
    put_byte(pb, strlen(descr)); /* string counter */
595
    put_buffer(pb, descr, strlen(descr)); /* handler description */
596
    return updateSize(pb, pos);
597
}
598

    
599
static int mov_write_minf_tag(ByteIOContext *pb, MOVTrack* track)
600
{
601
    int pos = url_ftell(pb);
602
    put_be32(pb, 0); /* size */
603
    put_tag(pb, "minf");
604
    if(track->enc->codec_type == CODEC_TYPE_VIDEO)
605
        mov_write_vmhd_tag(pb);
606
    else
607
        mov_write_smhd_tag(pb);
608
    if (track->mode == MODE_MOV) /* FIXME: Why do it for MODE_MOV only ? */
609
        mov_write_hdlr_tag(pb, NULL);
610
    mov_write_dinf_tag(pb);
611
    mov_write_stbl_tag(pb, track);
612
    return updateSize(pb, pos);
613
}
614

    
615
static int mov_write_mdhd_tag(ByteIOContext *pb, MOVTrack* track)
616
{
617
    put_be32(pb, 32); /* size */
618
    put_tag(pb, "mdhd");
619
    put_be32(pb, 0); /* Version & flags */
620
    put_be32(pb, track->time); /* creation time */
621
    put_be32(pb, track->time); /* modification time */
622
    put_be32(pb, track->timescale); /* time scale (sample rate for audio) */ 
623
    put_be32(pb, track->trackDuration); /* duration */
624
    put_be16(pb, 0); /* language, 0 = english */
625
    put_be16(pb, 0); /* reserved (quality) */
626
    return 32;
627
}
628

    
629
static int mov_write_mdia_tag(ByteIOContext *pb, MOVTrack* track)
630
{
631
    int pos = url_ftell(pb);
632
    put_be32(pb, 0); /* size */
633
    put_tag(pb, "mdia");
634
    mov_write_mdhd_tag(pb, track);
635
    mov_write_hdlr_tag(pb, track);
636
    mov_write_minf_tag(pb, track);
637
    return updateSize(pb, pos);
638
}
639

    
640
static int mov_write_tkhd_tag(ByteIOContext *pb, MOVTrack* track)
641
{
642
    int64_t maxTrackLenTemp;
643
    put_be32(pb, 0x5c); /* size (always 0x5c) */
644
    put_tag(pb, "tkhd");
645
    put_be32(pb, 0xf); /* version & flags (track enabled) */
646
    put_be32(pb, track->time); /* creation time */
647
    put_be32(pb, track->time); /* modification time */
648
    put_be32(pb, track->trackID); /* track-id */
649
    put_be32(pb, 0); /* reserved */
650
    maxTrackLenTemp = ((int64_t)globalTimescale*(int64_t)track->trackDuration)/(int64_t)track->timescale;
651
    put_be32(pb, (long)maxTrackLenTemp); /* duration */
652

    
653
    put_be32(pb, 0); /* reserved */
654
    put_be32(pb, 0); /* reserved */
655
    put_be32(pb, 0x0); /* reserved (Layer & Alternate group) */
656
    /* Volume, only for audio */
657
    if(track->enc->codec_type == CODEC_TYPE_AUDIO)
658
        put_be16(pb, 0x0100);
659
    else
660
        put_be16(pb, 0);
661
    put_be16(pb, 0); /* reserved */
662

    
663
    /* Matrix structure */
664
    put_be32(pb, 0x00010000); /* reserved */
665
    put_be32(pb, 0x0); /* reserved */
666
    put_be32(pb, 0x0); /* reserved */
667
    put_be32(pb, 0x0); /* reserved */
668
    put_be32(pb, 0x00010000); /* reserved */
669
    put_be32(pb, 0x0); /* reserved */
670
    put_be32(pb, 0x0); /* reserved */
671
    put_be32(pb, 0x0); /* reserved */
672
    put_be32(pb, 0x40000000); /* reserved */
673

    
674
    /* Track width and height, for visual only */
675
    if(track->enc->codec_type == CODEC_TYPE_VIDEO) {
676
        double sample_aspect_ratio = av_q2d(track->enc->sample_aspect_ratio);
677
        if( !sample_aspect_ratio ) sample_aspect_ratio = 1;
678
        put_be32(pb, sample_aspect_ratio * track->enc->width*0x10000);
679
        put_be32(pb, track->enc->height*0x10000);
680
    }
681
    else {
682
        put_be32(pb, 0);
683
        put_be32(pb, 0);
684
    }
685
    return 0x5c;
686
}
687

    
688
static int mov_write_trak_tag(ByteIOContext *pb, MOVTrack* track)
689
{
690
    int pos = url_ftell(pb);
691
    put_be32(pb, 0); /* size */
692
    put_tag(pb, "trak");
693
    mov_write_tkhd_tag(pb, track);
694
    mov_write_mdia_tag(pb, track);
695
    return updateSize(pb, pos);
696
}
697

    
698
/* TODO: Not sorted out, but not necessary either */
699
static int mov_write_iods_tag(ByteIOContext *pb, MOVContext *mov)
700
{
701
    put_be32(pb, 0x15); /* size */
702
    put_tag(pb, "iods");
703
    put_be32(pb, 0);    /* version & flags */
704
    put_be16(pb, 0x1007);
705
    put_byte(pb, 0);
706
    put_be16(pb, 0x4fff);
707
    put_be16(pb, 0xfffe);
708
    put_be16(pb, 0x01ff);
709
    return 0x15;
710
}
711

    
712
static int mov_write_mvhd_tag(ByteIOContext *pb, MOVContext *mov)
713
{
714
    int maxTrackID = 1, maxTrackLen = 0, i;
715
    int64_t maxTrackLenTemp;
716

    
717
    put_be32(pb, 0x6c); /* size (always 0x6c) */
718
    put_tag(pb, "mvhd");
719
    put_be32(pb, 0); /* version & flags */
720
    put_be32(pb, mov->time); /* creation time */
721
    put_be32(pb, mov->time); /* modification time */
722
    put_be32(pb, mov->timescale); /* timescale */
723
    for (i=0; i<MAX_STREAMS; i++) {
724
        if(mov->tracks[i].entry > 0) {
725
            maxTrackLenTemp = ((int64_t)globalTimescale*(int64_t)mov->tracks[i].trackDuration)/(int64_t)mov->tracks[i].timescale;
726
            if(maxTrackLen < maxTrackLenTemp)
727
                maxTrackLen = maxTrackLenTemp;
728
            if(maxTrackID < mov->tracks[i].trackID)
729
                maxTrackID = mov->tracks[i].trackID;
730
        }
731
    }
732
    put_be32(pb, maxTrackLen); /* duration of longest track */
733

    
734
    put_be32(pb, 0x00010000); /* reserved (preferred rate) 1.0 = normal */
735
    put_be16(pb, 0x0100); /* reserved (preferred volume) 1.0 = normal */
736
    put_be16(pb, 0); /* reserved */
737
    put_be32(pb, 0); /* reserved */
738
    put_be32(pb, 0); /* reserved */
739

    
740
    /* Matrix structure */
741
    put_be32(pb, 0x00010000); /* reserved */
742
    put_be32(pb, 0x0); /* reserved */
743
    put_be32(pb, 0x0); /* reserved */
744
    put_be32(pb, 0x0); /* reserved */
745
    put_be32(pb, 0x00010000); /* reserved */
746
    put_be32(pb, 0x0); /* reserved */
747
    put_be32(pb, 0x0); /* reserved */
748
    put_be32(pb, 0x0); /* reserved */
749
    put_be32(pb, 0x40000000); /* reserved */
750

    
751
    put_be32(pb, 0); /* reserved (preview time) */
752
    put_be32(pb, 0); /* reserved (preview duration) */
753
    put_be32(pb, 0); /* reserved (poster time) */
754
    put_be32(pb, 0); /* reserved (selection time) */
755
    put_be32(pb, 0); /* reserved (selection duration) */
756
    put_be32(pb, 0); /* reserved (current time) */
757
    put_be32(pb, maxTrackID+1); /* Next track id */
758
    return 0x6c;
759
}
760

    
761
static int mov_write_udta_tag(ByteIOContext *pb, MOVContext* mov,
762
                              AVFormatContext *s)
763
{
764
    int pos = url_ftell(pb);
765
    int i;
766

    
767
    put_be32(pb, 0); /* size */
768
    put_tag(pb, "udta");
769

    
770
    /* Requirements */
771
    for (i=0; i<MAX_STREAMS; i++) {
772
        if(mov->tracks[i].entry <= 0) continue;
773
        if (mov->tracks[i].enc->codec_id == CODEC_ID_AAC ||
774
            mov->tracks[i].enc->codec_id == CODEC_ID_MPEG4) {
775
            int pos = url_ftell(pb);
776
            put_be32(pb, 0); /* size */
777
            put_tag(pb, "\251req");
778
            put_be16(pb, sizeof("QuickTime 6.0 or greater") - 1);
779
            put_be16(pb, 0);
780
            put_buffer(pb, "QuickTime 6.0 or greater",
781
                       sizeof("QuickTime 6.0 or greater") - 1);
782
            updateSize(pb, pos);
783
            break;
784
        }
785
    }
786

    
787
    /* Encoder */
788
    {
789
        int pos = url_ftell(pb);
790
        put_be32(pb, 0); /* size */
791
        put_tag(pb, "\251enc");
792
        put_be16(pb, sizeof(LIBAVFORMAT_IDENT) - 1); /* string length */
793
        put_be16(pb, 0);
794
        put_buffer(pb, LIBAVFORMAT_IDENT, sizeof(LIBAVFORMAT_IDENT) - 1);
795
        updateSize(pb, pos);
796
    }
797

    
798
    if( s->title[0] )
799
    {
800
        int pos = url_ftell(pb);
801
        put_be32(pb, 0); /* size */
802
        put_tag(pb, "\251nam");
803
        put_be16(pb, strlen(s->title)); /* string length */
804
        put_be16(pb, 0);
805
        put_buffer(pb, s->title, strlen(s->title));
806
        updateSize(pb, pos);
807
    }
808

    
809
    if( s->author[0] )
810
    {
811
        int pos = url_ftell(pb);
812
        put_be32(pb, 0); /* size */
813
        put_tag(pb, /*"\251aut"*/ "\251day" );
814
        put_be16(pb, strlen(s->author)); /* string length */
815
        put_be16(pb, 0);
816
        put_buffer(pb, s->author, strlen(s->author));
817
        updateSize(pb, pos);
818
    }
819

    
820
    if( s->comment[0] )
821
    {
822
        int pos = url_ftell(pb);
823
        put_be32(pb, 0); /* size */
824
        put_tag(pb, "\251des");
825
        put_be16(pb, strlen(s->comment)); /* string length */
826
        put_be16(pb, 0);
827
        put_buffer(pb, s->comment, strlen(s->comment));
828
        updateSize(pb, pos);
829
    }
830

    
831
    return updateSize(pb, pos);
832
}
833

    
834
static int mov_write_moov_tag(ByteIOContext *pb, MOVContext *mov,
835
                              AVFormatContext *s)
836
{
837
    int pos, i;
838
    pos = url_ftell(pb);
839
    put_be32(pb, 0); /* size placeholder*/
840
    put_tag(pb, "moov");
841
    mov->timescale = globalTimescale;
842

    
843
    for (i=0; i<MAX_STREAMS; i++) {
844
        if(mov->tracks[i].entry <= 0) continue;
845

    
846
        if(mov->tracks[i].enc->codec_type == CODEC_TYPE_VIDEO) {
847
            mov->tracks[i].timescale = mov->tracks[i].enc->frame_rate;
848
            mov->tracks[i].sampleDuration = mov->tracks[i].enc->frame_rate_base;
849
        }
850
        else if(mov->tracks[i].enc->codec_type == CODEC_TYPE_AUDIO) {
851
            /* If AMR, track timescale = 8000, AMR_WB = 16000 */
852
            if(mov->tracks[i].enc->codec_id == CODEC_ID_AMR_NB) {
853
                mov->tracks[i].sampleDuration = 160;  // Bytes per chunk
854
                mov->tracks[i].timescale = 8000;
855
            }
856
            else {
857
                mov->tracks[i].timescale = mov->tracks[i].enc->sample_rate;
858
                mov->tracks[i].sampleDuration = mov->tracks[i].enc->frame_size;
859
            }
860
        }
861

    
862
        mov->tracks[i].trackDuration = 
863
            mov->tracks[i].sampleCount * mov->tracks[i].sampleDuration;
864
        mov->tracks[i].time = mov->time;
865
        mov->tracks[i].trackID = i+1;
866
    }
867

    
868
    mov_write_mvhd_tag(pb, mov);
869
    //mov_write_iods_tag(pb, mov);
870
    for (i=0; i<MAX_STREAMS; i++) {
871
        if(mov->tracks[i].entry > 0) {
872
            mov_write_trak_tag(pb, &(mov->tracks[i]));
873
        }
874
    }
875

    
876
    mov_write_udta_tag(pb, mov, s);
877

    
878
    return updateSize(pb, pos);
879
}
880

    
881
int mov_write_mdat_tag(ByteIOContext *pb, MOVContext* mov)
882
{
883
    mov->mdat_pos = url_ftell(pb); 
884
    put_be32(pb, 0); /* size placeholder*/
885
    put_tag(pb, "mdat");
886
    return 0;
887
}
888

    
889
/* TODO: This needs to be more general */
890
int mov_write_ftyp_tag(ByteIOContext *pb, AVFormatContext *s)
891
{
892
    MOVContext *mov = s->priv_data;
893

    
894
    put_be32(pb, 0x14 ); /* size */
895
    put_tag(pb, "ftyp");
896

    
897
    if ( mov->mode == MODE_3GP )
898
        put_tag(pb, "3gp4");
899
    else
900
        put_tag(pb, "isom");
901

    
902
    put_be32(pb, 0x200 );
903

    
904
    if ( mov->mode == MODE_3GP )
905
        put_tag(pb, "3gp4");
906
    else
907
        put_tag(pb, "mp41");
908

    
909
    return 0x14;
910
}
911

    
912
static int mov_write_header(AVFormatContext *s)
913
{
914
    ByteIOContext *pb = &s->pb;
915
    MOVContext *mov = s->priv_data;
916
    int i;
917

    
918
    /* Default mode == MP4 */
919
    mov->mode = MODE_MP4;
920

    
921
    if (s->oformat != NULL) {
922
        if (!strcmp("3gp", s->oformat->name)) mov->mode = MODE_3GP;
923
        else if (!strcmp("mov", s->oformat->name)) mov->mode = MODE_MOV;
924

    
925
        if ( mov->mode == MODE_3GP || mov->mode == MODE_MP4 )
926
            mov_write_ftyp_tag(pb,s);
927
    }
928

    
929
    for (i=0; i<MAX_STREAMS; i++) {
930
        mov->tracks[i].mode = mov->mode;
931
    }
932

    
933
    put_flush_packet(pb);
934

    
935
    return 0;
936
}
937

    
938
static int Timestamp(void) {
939
    return 1067949799U+(24107*86400); //its the modification time of this line :)
940
}
941

    
942
static int mov_write_packet(AVFormatContext *s, int stream_index,
943
                            const uint8_t *buf, int size, int64_t pts)
944
{
945
    MOVContext *mov = s->priv_data;
946
    ByteIOContext *pb = &s->pb;
947
    AVCodecContext *enc = &s->streams[stream_index]->codec;
948
    MOVTrack* trk = &mov->tracks[stream_index];
949
    int cl, id;
950
    unsigned int samplesInChunk = 0;
951

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

    
955
    if (enc->codec_type == CODEC_TYPE_VIDEO ) {
956
        samplesInChunk = 1;
957
    }
958
    else if (enc->codec_type == CODEC_TYPE_AUDIO ) {
959
        if( enc->codec_id == CODEC_ID_AMR_NB) {
960
            /* We must find out how many AMR blocks there are in one packet */
961
            static uint16_t packed_size[16] =
962
                {13, 14, 16, 18, 20, 21, 27, 32, 6, 0, 0, 0, 0, 0, 0, 0};
963
            int len = 0;
964

    
965
            while (len < size && samplesInChunk < 100) {
966
                len += packed_size[(buf[len] >> 3) & 0x0F];
967
                samplesInChunk++;
968
            }
969
        }
970
        else if(enc->codec_id == CODEC_ID_PCM_ALAW) {
971
            samplesInChunk = size/enc->channels;
972
        }
973
        else if(enc->codec_id == CODEC_ID_PCM_S16BE || enc->codec_id == CODEC_ID_PCM_S16LE) {
974
            samplesInChunk = size/(2*enc->channels);
975
        }            
976
        else {
977
            samplesInChunk = 1;
978
        }
979
    }
980

    
981
    if ((enc->codec_id == CODEC_ID_MPEG4 || enc->codec_id == CODEC_ID_AAC)
982
        && trk->vosLen == 0) {
983
        assert(enc->extradata_size);
984

    
985
        trk->vosLen = enc->extradata_size;
986
        trk->vosData = av_malloc(trk->vosLen);
987
        memcpy(trk->vosData, enc->extradata, trk->vosLen);
988
    }
989

    
990
    cl = trk->entry / MOV_INDEX_CLUSTER_SIZE;
991
    id = trk->entry % MOV_INDEX_CLUSTER_SIZE;
992

    
993
    if (trk->ents_allocated <= trk->entry) {
994
        trk->cluster = av_realloc(trk->cluster, (cl+1)*sizeof(void*)); 
995
        if (!trk->cluster)
996
            return -1;
997
        trk->cluster[cl] = av_malloc(MOV_INDEX_CLUSTER_SIZE*sizeof(MOVIentry));
998
        if (!trk->cluster[cl])
999
            return -1;
1000
        trk->ents_allocated += MOV_INDEX_CLUSTER_SIZE;
1001
    }
1002
    if (mov->mdat_written == 0) {
1003
        mov_write_mdat_tag(pb, mov);
1004
        mov->mdat_written = 1;
1005
        mov->time = Timestamp();
1006
    }
1007

    
1008
    trk->cluster[cl][id].pos = url_ftell(pb);
1009
    trk->cluster[cl][id].samplesInChunk = samplesInChunk;
1010
    trk->cluster[cl][id].size = size;
1011
    trk->cluster[cl][id].entries = samplesInChunk;
1012
    if(enc->codec_type == CODEC_TYPE_VIDEO) {
1013
        trk->cluster[cl][id].key_frame = enc->coded_frame->key_frame;
1014
        if(enc->coded_frame->pict_type == FF_I_TYPE)
1015
            trk->hasKeyframes = 1;
1016
    }
1017
    trk->enc = enc;
1018
    trk->entry++;
1019
    trk->sampleCount += samplesInChunk;
1020
    trk->mdat_size += size;
1021

    
1022
    put_buffer(pb, buf, size);
1023

    
1024
    put_flush_packet(pb);
1025
    return 0;
1026
}
1027

    
1028
static int mov_write_trailer(AVFormatContext *s)
1029
{
1030
    MOVContext *mov = s->priv_data;
1031
    ByteIOContext *pb = &s->pb;
1032
    int res = 0;
1033
    int i, j;
1034

    
1035
    offset_t moov_pos = url_ftell(pb);
1036

    
1037
    /* Write size of mdat tag */
1038
    for (i=0, j=0; i<MAX_STREAMS; i++) {
1039
        if(mov->tracks[i].ents_allocated > 0) {
1040
            j += mov->tracks[i].mdat_size;
1041
        }
1042
    }
1043
    url_fseek(pb, mov->mdat_pos, SEEK_SET);
1044
    put_be32(pb, j+8);
1045
    url_fseek(pb, moov_pos, SEEK_SET);
1046

    
1047
    mov_write_moov_tag(pb, mov, s);
1048

    
1049
    for (i=0; i<MAX_STREAMS; i++) {
1050
        for (j=0; j<mov->tracks[i].ents_allocated/MOV_INDEX_CLUSTER_SIZE; j++) {
1051
            av_free(mov->tracks[i].cluster[j]);
1052
        }
1053
        av_free(mov->tracks[i].cluster);
1054
        if( mov->tracks[i].vosLen ) av_free( mov->tracks[i].vosData );
1055

    
1056
        mov->tracks[i].cluster = NULL;
1057
        mov->tracks[i].ents_allocated = mov->tracks[i].entry = 0;
1058
    }
1059

    
1060
    put_flush_packet(pb);
1061

    
1062
    return res;
1063
}
1064

    
1065
static AVOutputFormat mov_oformat = {
1066
    "mov",
1067
    "mov format",
1068
    NULL,
1069
    "mov",
1070
    sizeof(MOVContext),
1071
    CODEC_ID_AAC,
1072
    CODEC_ID_MPEG4,
1073
    mov_write_header,
1074
    mov_write_packet,
1075
    mov_write_trailer,
1076
};
1077

    
1078
static AVOutputFormat _3gp_oformat = {
1079
    "3gp",
1080
    "3gp format",
1081
    NULL,
1082
    "3gp",
1083
    sizeof(MOVContext),
1084
    CODEC_ID_AMR_NB,
1085
    CODEC_ID_H263,
1086
    mov_write_header,
1087
    mov_write_packet,
1088
    mov_write_trailer,
1089
};
1090

    
1091
static AVOutputFormat mp4_oformat = {
1092
    "mp4",
1093
    "mp4 format",
1094
    "application/mp4",
1095
    "mp4,m4a",
1096
    sizeof(MOVContext),
1097
    CODEC_ID_AAC,
1098
    CODEC_ID_MPEG4,
1099
    mov_write_header,
1100
    mov_write_packet,
1101
    mov_write_trailer,
1102
};
1103

    
1104
int movenc_init(void)
1105
{
1106
    av_register_output_format(&mov_oformat);
1107
    av_register_output_format(&_3gp_oformat);
1108
    av_register_output_format(&mp4_oformat);
1109
    return 0;
1110
}