Statistics
| Branch: | Revision:

ffmpeg / libavformat / movenc.c @ ef19c7eb

History | View | Annotate | Download (33.5 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
const CodecTag codec_movaudio_tags[] = {
240
    { CODEC_ID_PCM_MULAW, MKTAG('u', 'l', 'a', 'w') },
241
    { CODEC_ID_PCM_ALAW, MKTAG('a', 'l', 'a', 'w') },
242
    { CODEC_ID_ADPCM_IMA_QT, MKTAG('i', 'm', 'a', '4') },
243
    { CODEC_ID_MACE3, MKTAG('M', 'A', 'C', '3') },
244
    { CODEC_ID_MACE6, MKTAG('M', 'A', 'C', '6') },
245
    { CODEC_ID_AAC, MKTAG('m', 'p', '4', 'a') },
246
    { CODEC_ID_AMR_NB, MKTAG('s', 'a', 'm', 'r') },
247
    { CODEC_ID_PCM_S16BE, MKTAG('t', 'w', 'o', 's') },
248
    { CODEC_ID_PCM_S16LE, MKTAG('s', 'o', 'w', 't') },
249
    { CODEC_ID_MP3, MKTAG('.', 'm', 'p', '3') },
250
    { 0, 0 },
251
};
252

    
253
static int mov_write_audio_tag(ByteIOContext *pb, MOVTrack* track)
254
{
255
    int pos = url_ftell(pb);
256
    int tag;
257
    
258
    put_be32(pb, 0); /* size */
259

    
260
    tag = codec_get_tag(codec_movaudio_tags, track->enc->codec_id);
261
    // if no mac fcc found, try with Microsoft tags
262
    if (!tag)
263
    {
264
        int tmp = codec_get_tag(codec_wav_tags, track->enc->codec_id);
265
        tag = MKTAG('m', 's', ((tmp >> 8) & 0xff), (tmp & 0xff));
266
    }
267
    put_le32(pb, tag); // store it byteswapped
268

    
269
    put_be32(pb, 0); /* Reserved */
270
    put_be16(pb, 0); /* Reserved */
271
    put_be16(pb, 1); /* Data-reference index, XXX  == 1 */
272

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

    
281
    put_be16(pb, track->enc->channels); /* Number of channels */
282
    /* TODO: Currently hard-coded to 16-bit, there doesn't seem
283
                 to be a good way to get number of bits of audio */
284
    put_be16(pb, 0x10); /* Reserved */
285

    
286
    if(track->enc->codec_id == CODEC_ID_AAC ||
287
       track->enc->codec_id == CODEC_ID_MP3)
288
    {
289
        put_be16(pb, 0xfffe); /* compression ID (vbr)*/
290
    }
291
    else
292
    {
293
        put_be16(pb, 0); /* compression ID (= 0) */
294
    }
295
    put_be16(pb, 0); /* packet size (= 0) */
296
    put_be16(pb, track->timescale); /* Time scale */
297
    put_be16(pb, 0); /* Reserved */
298

    
299
    if(track->mode == MODE_MOV && track->enc->codec_id == CODEC_ID_AAC)
300
    {
301
        /* SoundDescription V1 extended info */
302
        put_be32(pb, track->enc->frame_size); /* Samples per packet  */
303
        put_be32(pb, 1536); /* Bytes per packet */
304
        put_be32(pb, 2); /* Bytes per frame */
305
        put_be32(pb, 2); /* Bytes per sample */
306
    }
307

    
308
    if(track->enc->codec_id == CODEC_ID_AAC) {
309
        if( track->mode == MODE_MOV ) mov_write_wave_tag(pb, track);
310
        else mov_write_esds_tag(pb, track);
311
    }
312
    if(track->enc->codec_id == CODEC_ID_AMR_NB)
313
        mov_write_damr_tag(pb);
314
    return updateSize (pb, pos);
315
}
316

    
317
static int mov_write_d263_tag(ByteIOContext *pb)
318
{
319
    put_be32(pb, 0xf); /* size */
320
    put_tag(pb, "d263");
321
    put_tag(pb, "FFMP");
322
    put_be16(pb, 0x0a);
323
    put_byte(pb, 0);
324
    return 0xf;
325
}
326

    
327
/* TODO: No idea about these values */
328
static int mov_write_svq3_tag(ByteIOContext *pb)
329
{
330
    put_be32(pb, 0x15);
331
    put_tag(pb, "SMI ");
332
    put_tag(pb, "SEQH");
333
    put_be32(pb, 0x5);
334
    put_be32(pb, 0xe2c0211d);
335
    put_be32(pb, 0xc0000000);
336
    put_byte(pb, 0);   
337
    return 0x15;
338
}
339

    
340
static unsigned int descrLength(unsigned int len)
341
{
342
    if (len < 0x00000080)
343
        return 2 + len;
344
    else if (len < 0x00004000)
345
        return 3 + len;
346
    else if(len < 0x00200000)
347
        return 4 + len;
348
    else
349
        return 5 + len;
350
}
351

    
352
static void putDescr(ByteIOContext *pb, int tag, int size)
353
{
354
    uint32_t len;
355
    uint8_t  vals[4];
356

    
357
    len = size;
358
    vals[3] = (uint8_t)(len & 0x7f);
359
    len >>= 7;
360
    vals[2] = (uint8_t)((len & 0x7f) | 0x80); 
361
    len >>= 7;
362
    vals[1] = (uint8_t)((len & 0x7f) | 0x80); 
363
    len >>= 7;
364
    vals[0] = (uint8_t)((len & 0x7f) | 0x80);
365

    
366
    put_byte(pb, tag); // DescriptorTag
367

    
368
    if (size < 0x00000080)
369
    {
370
        put_byte(pb, vals[3]);
371
    }
372
    else if (size < 0x00004000)
373
    {
374
        put_byte(pb, vals[2]);
375
        put_byte(pb, vals[3]);
376
    }
377
    else if (size < 0x00200000)
378
    {
379
        put_byte(pb, vals[1]);
380
        put_byte(pb, vals[2]);
381
        put_byte(pb, vals[3]);
382
    }
383
    else if (size < 0x10000000)
384
    {
385
        put_byte(pb, vals[0]);
386
        put_byte(pb, vals[1]);
387
        put_byte(pb, vals[2]);
388
        put_byte(pb, vals[3]);
389
    }
390
}
391

    
392
static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack* track) // Basic
393
{
394
    int decoderSpecificInfoLen = track->vosLen ? descrLength(track->vosLen):0;
395
    int pos = url_ftell(pb);
396

    
397
    put_be32(pb, 0);               // size
398
    put_tag(pb, "esds");
399
    put_be32(pb, 0);               // Version
400

    
401
    // ES descriptor
402
    putDescr(pb, 0x03, 3 + descrLength(13 + decoderSpecificInfoLen) +
403
             descrLength(1));
404
    put_be16(pb, 0x0001);          // ID (= 1)
405
    put_byte(pb, 0x00);            // flags (= no flags)
406

    
407
    // DecoderConfig descriptor
408
    putDescr(pb, 0x04, 13 + decoderSpecificInfoLen);
409

    
410
    if(track->enc->codec_id == CODEC_ID_AAC)
411
        put_byte(pb, 0x40);        // Object type indication
412
    else if(track->enc->codec_id == CODEC_ID_MPEG4)
413
        put_byte(pb, 0x20);        // Object type indication (Visual 14496-2)
414

    
415
    if(track->enc->codec_type == CODEC_TYPE_AUDIO)
416
        put_byte(pb, 0x15);            // flags (= Audiostream)
417
    else
418
        put_byte(pb, 0x11);            // flags (= Visualstream)
419

    
420
    put_byte(pb, 0x0);             // Buffersize DB (24 bits)
421
    put_be16(pb, 0x0dd2);          // Buffersize DB
422

    
423
    // TODO: find real values for these
424
    put_be32(pb, 0x0002e918);     // maxbitrate
425
    put_be32(pb, 0x00017e6b);     // avg bitrate
426

    
427
    if (track->vosLen)
428
    {
429
        // DecoderSpecific info descriptor
430
        putDescr(pb, 0x05, track->vosLen);
431
        put_buffer(pb, track->vosData, track->vosLen);
432
    }
433

    
434
    // SL descriptor
435
    putDescr(pb, 0x06, 1);
436
    put_byte(pb, 0x02);
437
    return updateSize (pb, pos);
438
}
439

    
440
const CodecTag codec_movvideo_tags[] = {
441
    { CODEC_ID_SVQ1, MKTAG('S', 'V', 'Q', '1') },
442
    { CODEC_ID_SVQ3, MKTAG('S', 'V', 'Q', '3') },
443
    { CODEC_ID_MPEG4, MKTAG('m', 'p', '4', 'v') },
444
    { CODEC_ID_H263, MKTAG('s', '2', '6', '3') },
445
    { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'c', ' ') },
446
    { 0, 0 },
447
};
448

    
449
static int mov_write_video_tag(ByteIOContext *pb, MOVTrack* track)
450
{
451
    int pos = url_ftell(pb);
452
    int tag;
453

    
454
    put_be32(pb, 0); /* size */
455

    
456
    tag = codec_get_tag(codec_movvideo_tags, track->enc->codec_id);
457
    // if no mac fcc found, try with Microsoft tags
458
    if (!tag)
459
        tag = codec_get_tag(codec_bmp_tags, track->enc->codec_id);
460
    put_le32(pb, tag); // store it byteswapped
461

    
462
    put_be32(pb, 0); /* Reserved */
463
    put_be16(pb, 0); /* Reserved */
464
    put_be16(pb, 1); /* Data-reference index */
465

    
466
    put_be32(pb, 0); /* Reserved (= 02000c) */
467
    put_be32(pb, 0); /* Reserved ("SVis")*/
468
    put_be32(pb, 0); /* Reserved */
469
    put_be32(pb, 0); /* Reserved (400)*/
470
    put_be16(pb, track->enc->width); /* Video width */
471
    put_be16(pb, track->enc->height); /* Video height */
472
    put_be32(pb, 0x00480000); /* Reserved */
473
    put_be32(pb, 0x00480000); /* Reserved */
474
    put_be32(pb, 0); /* Data size (= 0) */
475
    put_be16(pb, 1); /* Frame count (= 1) */
476
    
477
    put_be32(pb, 0); /* Reserved */
478
    put_be32(pb, 0); /* Reserved */
479
    put_be32(pb, 0); /* Reserved */
480
    put_be32(pb, 0); /* Reserved */
481
    put_be32(pb, 0); /* Reserved */
482
    put_be32(pb, 0); /* Reserved */
483
    put_be32(pb, 0); /* Reserved */
484
    put_be32(pb, 0); /* Reserved */
485
    
486
    put_be16(pb, 0x18); /* Reserved */
487
    put_be16(pb, 0xffff); /* Reserved */
488
    if(track->enc->codec_id == CODEC_ID_MPEG4)
489
        mov_write_esds_tag(pb, track);
490
    else if(track->enc->codec_id == CODEC_ID_H263)
491
        mov_write_d263_tag(pb);
492
    else if(track->enc->codec_id == CODEC_ID_SVQ3)
493
        mov_write_svq3_tag(pb);    
494

    
495
    return updateSize (pb, pos);
496
}
497

    
498
static int mov_write_stsd_tag(ByteIOContext *pb, MOVTrack* track)
499
{
500
    int pos = url_ftell(pb);
501
    put_be32(pb, 0); /* size */
502
    put_tag(pb, "stsd");
503
    put_be32(pb, 0); /* version & flags */
504
    put_be32(pb, 1); /* entry count */
505
    if (track->enc->codec_type == CODEC_TYPE_VIDEO)
506
        mov_write_video_tag(pb, track);
507
    else if (track->enc->codec_type == CODEC_TYPE_AUDIO)
508
        mov_write_audio_tag(pb, track);
509
    return updateSize(pb, pos);
510
}
511

    
512
/* TODO?: Currently all samples/frames seem to have same duration */
513
/* Time to sample atom */
514
static int mov_write_stts_tag(ByteIOContext *pb, MOVTrack* track)
515
{
516
    put_be32(pb, 0x18); /* size */
517
    put_tag(pb, "stts");
518
    put_be32(pb, 0); /* version & flags */
519
    put_be32(pb, 1); /* entry count */
520

    
521
    put_be32(pb, track->sampleCount); /* sample count */
522
    put_be32(pb, track->sampleDuration); /* sample duration */
523
    return 0x18;
524
}
525

    
526
static int mov_write_dref_tag(ByteIOContext *pb)
527
{
528
    put_be32(pb, 28); /* size */
529
    put_tag(pb, "dref");
530
    put_be32(pb, 0); /* version & flags */
531
    put_be32(pb, 1); /* entry count */
532

    
533
    put_be32(pb, 0xc); /* size */
534
    put_tag(pb, "url ");
535
    put_be32(pb, 1); /* version & flags */
536

    
537
    return 28;
538
}
539

    
540
static int mov_write_stbl_tag(ByteIOContext *pb, MOVTrack* track)
541
{
542
    int pos = url_ftell(pb);
543
    put_be32(pb, 0); /* size */
544
    put_tag(pb, "stbl");
545
    mov_write_stsd_tag(pb, track);
546
    mov_write_stts_tag(pb, track);
547
    if (track->enc->codec_type == CODEC_TYPE_VIDEO &&
548
        track->hasKeyframes)
549
        mov_write_stss_tag(pb, track);
550
    mov_write_stsc_tag(pb, track);
551
    mov_write_stsz_tag(pb, track);
552
    mov_write_stco_tag(pb, track);
553
    return updateSize(pb, pos);
554
}
555

    
556
static int mov_write_dinf_tag(ByteIOContext *pb)
557
{
558
    int pos = url_ftell(pb);
559
    put_be32(pb, 0); /* size */
560
    put_tag(pb, "dinf");
561
    mov_write_dref_tag(pb);
562
    return updateSize(pb, pos);
563
}
564

    
565
static int mov_write_smhd_tag(ByteIOContext *pb)
566
{
567
    put_be32(pb, 16); /* size */
568
    put_tag(pb, "smhd");
569
    put_be32(pb, 0); /* version & flags */
570
    put_be16(pb, 0); /* reserved (balance, normally = 0) */
571
    put_be16(pb, 0); /* reserved */
572
    return 16;
573
}
574

    
575
static int mov_write_vmhd_tag(ByteIOContext *pb)
576
{
577
    put_be32(pb, 0x14); /* size (always 0x14) */
578
    put_tag(pb, "vmhd");
579
    put_be32(pb, 0x01); /* version & flags */
580
    put_be64(pb, 0); /* reserved (graphics mode = copy) */
581
    return 0x14;
582
}
583

    
584
static int mov_write_hdlr_tag(ByteIOContext *pb, MOVTrack* track)
585
{
586
    char *descr, *hdlr, *hdlr_type;
587
    int pos = url_ftell(pb);
588
    
589
    if (!track) { /* no media --> data handler */
590
        hdlr = "dhlr";
591
        hdlr_type = "url ";
592
        descr = "DataHandler";
593
    } else {
594
        hdlr = (track->mode == MODE_MOV) ? "mhlr" : "\0\0\0\0";
595
        if (track->enc->codec_type == CODEC_TYPE_VIDEO) {
596
            hdlr_type = "vide";
597
            descr = "VideoHandler";
598
        } else {
599
            hdlr_type = "soun";
600
            descr = "SoundHandler";
601
        }
602
    }
603
    
604
    put_be32(pb, 0); /* size */
605
    put_tag(pb, "hdlr");
606
    put_be32(pb, 0); /* Version & flags */
607
    put_buffer(pb, hdlr, 4); /* handler */
608
    put_tag(pb, hdlr_type); /* handler type */
609
    put_be32(pb ,0); /* reserved */
610
    put_be32(pb ,0); /* reserved */
611
    put_be32(pb ,0); /* reserved */
612
    put_byte(pb, strlen(descr)); /* string counter */
613
    put_buffer(pb, descr, strlen(descr)); /* handler description */
614
    return updateSize(pb, pos);
615
}
616

    
617
static int mov_write_minf_tag(ByteIOContext *pb, MOVTrack* track)
618
{
619
    int pos = url_ftell(pb);
620
    put_be32(pb, 0); /* size */
621
    put_tag(pb, "minf");
622
    if(track->enc->codec_type == CODEC_TYPE_VIDEO)
623
        mov_write_vmhd_tag(pb);
624
    else
625
        mov_write_smhd_tag(pb);
626
    if (track->mode == MODE_MOV) /* FIXME: Why do it for MODE_MOV only ? */
627
        mov_write_hdlr_tag(pb, NULL);
628
    mov_write_dinf_tag(pb);
629
    mov_write_stbl_tag(pb, track);
630
    return updateSize(pb, pos);
631
}
632

    
633
static int mov_write_mdhd_tag(ByteIOContext *pb, MOVTrack* track)
634
{
635
    put_be32(pb, 32); /* size */
636
    put_tag(pb, "mdhd");
637
    put_be32(pb, 0); /* Version & flags */
638
    put_be32(pb, track->time); /* creation time */
639
    put_be32(pb, track->time); /* modification time */
640
    put_be32(pb, track->timescale); /* time scale (sample rate for audio) */ 
641
    put_be32(pb, track->trackDuration); /* duration */
642
    put_be16(pb, 0); /* language, 0 = english */
643
    put_be16(pb, 0); /* reserved (quality) */
644
    return 32;
645
}
646

    
647
static int mov_write_mdia_tag(ByteIOContext *pb, MOVTrack* track)
648
{
649
    int pos = url_ftell(pb);
650
    put_be32(pb, 0); /* size */
651
    put_tag(pb, "mdia");
652
    mov_write_mdhd_tag(pb, track);
653
    mov_write_hdlr_tag(pb, track);
654
    mov_write_minf_tag(pb, track);
655
    return updateSize(pb, pos);
656
}
657

    
658
static int mov_write_tkhd_tag(ByteIOContext *pb, MOVTrack* track)
659
{
660
    int64_t maxTrackLenTemp;
661
    put_be32(pb, 0x5c); /* size (always 0x5c) */
662
    put_tag(pb, "tkhd");
663
    put_be32(pb, 0xf); /* version & flags (track enabled) */
664
    put_be32(pb, track->time); /* creation time */
665
    put_be32(pb, track->time); /* modification time */
666
    put_be32(pb, track->trackID); /* track-id */
667
    put_be32(pb, 0); /* reserved */
668
    maxTrackLenTemp = ((int64_t)globalTimescale*(int64_t)track->trackDuration)/(int64_t)track->timescale;
669
    put_be32(pb, (long)maxTrackLenTemp); /* duration */
670

    
671
    put_be32(pb, 0); /* reserved */
672
    put_be32(pb, 0); /* reserved */
673
    put_be32(pb, 0x0); /* reserved (Layer & Alternate group) */
674
    /* Volume, only for audio */
675
    if(track->enc->codec_type == CODEC_TYPE_AUDIO)
676
        put_be16(pb, 0x0100);
677
    else
678
        put_be16(pb, 0);
679
    put_be16(pb, 0); /* reserved */
680

    
681
    /* Matrix structure */
682
    put_be32(pb, 0x00010000); /* reserved */
683
    put_be32(pb, 0x0); /* reserved */
684
    put_be32(pb, 0x0); /* reserved */
685
    put_be32(pb, 0x0); /* reserved */
686
    put_be32(pb, 0x00010000); /* reserved */
687
    put_be32(pb, 0x0); /* reserved */
688
    put_be32(pb, 0x0); /* reserved */
689
    put_be32(pb, 0x0); /* reserved */
690
    put_be32(pb, 0x40000000); /* reserved */
691

    
692
    /* Track width and height, for visual only */
693
    if(track->enc->codec_type == CODEC_TYPE_VIDEO) {
694
        double sample_aspect_ratio = av_q2d(track->enc->sample_aspect_ratio);
695
        if( !sample_aspect_ratio ) sample_aspect_ratio = 1;
696
        put_be32(pb, sample_aspect_ratio * track->enc->width*0x10000);
697
        put_be32(pb, track->enc->height*0x10000);
698
    }
699
    else {
700
        put_be32(pb, 0);
701
        put_be32(pb, 0);
702
    }
703
    return 0x5c;
704
}
705

    
706
static int mov_write_trak_tag(ByteIOContext *pb, MOVTrack* track)
707
{
708
    int pos = url_ftell(pb);
709
    put_be32(pb, 0); /* size */
710
    put_tag(pb, "trak");
711
    mov_write_tkhd_tag(pb, track);
712
    mov_write_mdia_tag(pb, track);
713
    return updateSize(pb, pos);
714
}
715

    
716
/* TODO: Not sorted out, but not necessary either */
717
static int mov_write_iods_tag(ByteIOContext *pb, MOVContext *mov)
718
{
719
    put_be32(pb, 0x15); /* size */
720
    put_tag(pb, "iods");
721
    put_be32(pb, 0);    /* version & flags */
722
    put_be16(pb, 0x1007);
723
    put_byte(pb, 0);
724
    put_be16(pb, 0x4fff);
725
    put_be16(pb, 0xfffe);
726
    put_be16(pb, 0x01ff);
727
    return 0x15;
728
}
729

    
730
static int mov_write_mvhd_tag(ByteIOContext *pb, MOVContext *mov)
731
{
732
    int maxTrackID = 1, maxTrackLen = 0, i;
733
    int64_t maxTrackLenTemp;
734

    
735
    put_be32(pb, 0x6c); /* size (always 0x6c) */
736
    put_tag(pb, "mvhd");
737
    put_be32(pb, 0); /* version & flags */
738
    put_be32(pb, mov->time); /* creation time */
739
    put_be32(pb, mov->time); /* modification time */
740
    put_be32(pb, mov->timescale); /* timescale */
741
    for (i=0; i<MAX_STREAMS; i++) {
742
        if(mov->tracks[i].entry > 0) {
743
            maxTrackLenTemp = ((int64_t)globalTimescale*(int64_t)mov->tracks[i].trackDuration)/(int64_t)mov->tracks[i].timescale;
744
            if(maxTrackLen < maxTrackLenTemp)
745
                maxTrackLen = maxTrackLenTemp;
746
            if(maxTrackID < mov->tracks[i].trackID)
747
                maxTrackID = mov->tracks[i].trackID;
748
        }
749
    }
750
    put_be32(pb, maxTrackLen); /* duration of longest track */
751

    
752
    put_be32(pb, 0x00010000); /* reserved (preferred rate) 1.0 = normal */
753
    put_be16(pb, 0x0100); /* reserved (preferred volume) 1.0 = normal */
754
    put_be16(pb, 0); /* reserved */
755
    put_be32(pb, 0); /* reserved */
756
    put_be32(pb, 0); /* reserved */
757

    
758
    /* Matrix structure */
759
    put_be32(pb, 0x00010000); /* reserved */
760
    put_be32(pb, 0x0); /* reserved */
761
    put_be32(pb, 0x0); /* reserved */
762
    put_be32(pb, 0x0); /* reserved */
763
    put_be32(pb, 0x00010000); /* reserved */
764
    put_be32(pb, 0x0); /* reserved */
765
    put_be32(pb, 0x0); /* reserved */
766
    put_be32(pb, 0x0); /* reserved */
767
    put_be32(pb, 0x40000000); /* reserved */
768

    
769
    put_be32(pb, 0); /* reserved (preview time) */
770
    put_be32(pb, 0); /* reserved (preview duration) */
771
    put_be32(pb, 0); /* reserved (poster time) */
772
    put_be32(pb, 0); /* reserved (selection time) */
773
    put_be32(pb, 0); /* reserved (selection duration) */
774
    put_be32(pb, 0); /* reserved (current time) */
775
    put_be32(pb, maxTrackID+1); /* Next track id */
776
    return 0x6c;
777
}
778

    
779
static int mov_write_udta_tag(ByteIOContext *pb, MOVContext* mov,
780
                              AVFormatContext *s)
781
{
782
    int pos = url_ftell(pb);
783
    int i;
784

    
785
    put_be32(pb, 0); /* size */
786
    put_tag(pb, "udta");
787

    
788
    /* Requirements */
789
    for (i=0; i<MAX_STREAMS; i++) {
790
        if(mov->tracks[i].entry <= 0) continue;
791
        if (mov->tracks[i].enc->codec_id == CODEC_ID_AAC ||
792
            mov->tracks[i].enc->codec_id == CODEC_ID_MPEG4) {
793
            int pos = url_ftell(pb);
794
            put_be32(pb, 0); /* size */
795
            put_tag(pb, "\251req");
796
            put_be16(pb, sizeof("QuickTime 6.0 or greater") - 1);
797
            put_be16(pb, 0);
798
            put_buffer(pb, "QuickTime 6.0 or greater",
799
                       sizeof("QuickTime 6.0 or greater") - 1);
800
            updateSize(pb, pos);
801
            break;
802
        }
803
    }
804

    
805
    /* Encoder */
806
    if(!(mov->tracks[0].enc->flags & CODEC_FLAG_BITEXACT))
807
    {
808
        int pos = url_ftell(pb);
809
        put_be32(pb, 0); /* size */
810
        put_tag(pb, "\251enc");
811
        put_be16(pb, sizeof(LIBAVFORMAT_IDENT) - 1); /* string length */
812
        put_be16(pb, 0);
813
        put_buffer(pb, LIBAVFORMAT_IDENT, sizeof(LIBAVFORMAT_IDENT) - 1);
814
        updateSize(pb, pos);
815
    }
816

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

    
828
    if( s->author[0] )
829
    {
830
        int pos = url_ftell(pb);
831
        put_be32(pb, 0); /* size */
832
        put_tag(pb, /*"\251aut"*/ "\251day" );
833
        put_be16(pb, strlen(s->author)); /* string length */
834
        put_be16(pb, 0);
835
        put_buffer(pb, s->author, strlen(s->author));
836
        updateSize(pb, pos);
837
    }
838

    
839
    if( s->comment[0] )
840
    {
841
        int pos = url_ftell(pb);
842
        put_be32(pb, 0); /* size */
843
        put_tag(pb, "\251des");
844
        put_be16(pb, strlen(s->comment)); /* string length */
845
        put_be16(pb, 0);
846
        put_buffer(pb, s->comment, strlen(s->comment));
847
        updateSize(pb, pos);
848
    }
849

    
850
    return updateSize(pb, pos);
851
}
852

    
853
static int mov_write_moov_tag(ByteIOContext *pb, MOVContext *mov,
854
                              AVFormatContext *s)
855
{
856
    int pos, i;
857
    pos = url_ftell(pb);
858
    put_be32(pb, 0); /* size placeholder*/
859
    put_tag(pb, "moov");
860
    mov->timescale = globalTimescale;
861

    
862
    for (i=0; i<MAX_STREAMS; i++) {
863
        if(mov->tracks[i].entry <= 0) continue;
864

    
865
        if(mov->tracks[i].enc->codec_type == CODEC_TYPE_VIDEO) {
866
            mov->tracks[i].timescale = mov->tracks[i].enc->frame_rate;
867
            mov->tracks[i].sampleDuration = mov->tracks[i].enc->frame_rate_base;
868
        }
869
        else if(mov->tracks[i].enc->codec_type == CODEC_TYPE_AUDIO) {
870
            /* If AMR, track timescale = 8000, AMR_WB = 16000 */
871
            if(mov->tracks[i].enc->codec_id == CODEC_ID_AMR_NB) {
872
                mov->tracks[i].sampleDuration = 160;  // Bytes per chunk
873
                mov->tracks[i].timescale = 8000;
874
            }
875
            else {
876
                mov->tracks[i].timescale = mov->tracks[i].enc->sample_rate;
877
                mov->tracks[i].sampleDuration = mov->tracks[i].enc->frame_size;
878
            }
879
        }
880

    
881
        mov->tracks[i].trackDuration = 
882
            mov->tracks[i].sampleCount * mov->tracks[i].sampleDuration;
883
        mov->tracks[i].time = mov->time;
884
        mov->tracks[i].trackID = i+1;
885
    }
886

    
887
    mov_write_mvhd_tag(pb, mov);
888
    //mov_write_iods_tag(pb, mov);
889
    for (i=0; i<MAX_STREAMS; i++) {
890
        if(mov->tracks[i].entry > 0) {
891
            mov_write_trak_tag(pb, &(mov->tracks[i]));
892
        }
893
    }
894

    
895
    mov_write_udta_tag(pb, mov, s);
896

    
897
    return updateSize(pb, pos);
898
}
899

    
900
int mov_write_mdat_tag(ByteIOContext *pb, MOVContext* mov)
901
{
902
    mov->mdat_pos = url_ftell(pb); 
903
    put_be32(pb, 0); /* size placeholder*/
904
    put_tag(pb, "mdat");
905
    return 0;
906
}
907

    
908
/* TODO: This needs to be more general */
909
int mov_write_ftyp_tag(ByteIOContext *pb, AVFormatContext *s)
910
{
911
    MOVContext *mov = s->priv_data;
912

    
913
    put_be32(pb, 0x14 ); /* size */
914
    put_tag(pb, "ftyp");
915

    
916
    if ( mov->mode == MODE_3GP )
917
        put_tag(pb, "3gp4");
918
    else
919
        put_tag(pb, "isom");
920

    
921
    put_be32(pb, 0x200 );
922

    
923
    if ( mov->mode == MODE_3GP )
924
        put_tag(pb, "3gp4");
925
    else
926
        put_tag(pb, "mp41");
927

    
928
    return 0x14;
929
}
930

    
931
static int mov_write_header(AVFormatContext *s)
932
{
933
    ByteIOContext *pb = &s->pb;
934
    MOVContext *mov = s->priv_data;
935
    int i;
936

    
937
    for(i=0; i<s->nb_streams; i++){
938
        AVCodecContext *c= &s->streams[i]->codec;
939

    
940
        if      (c->codec_type == CODEC_TYPE_VIDEO){
941
            if (!codec_get_tag(codec_movvideo_tags, c->codec_id)){
942
                if(!codec_get_tag(codec_bmp_tags, c->codec_id))
943
                    return -1;
944
                else
945
                    av_log(s, AV_LOG_INFO, "Warning, using MS style video codec tag, the file may be unplayable!\n");
946
            }
947
        }else if(c->codec_type == CODEC_TYPE_AUDIO){
948
            if (!codec_get_tag(codec_movaudio_tags, c->codec_id)){
949
                if(!codec_get_tag(codec_wav_tags, c->codec_id))
950
                    return -1;
951
                else
952
                    av_log(s, AV_LOG_INFO, "Warning, using MS style audio codec tag, the file may be unplayable!\n");
953
            }
954
        }
955
    }
956

    
957
    /* Default mode == MP4 */
958
    mov->mode = MODE_MP4;
959

    
960
    if (s->oformat != NULL) {
961
        if (!strcmp("3gp", s->oformat->name)) mov->mode = MODE_3GP;
962
        else if (!strcmp("mov", s->oformat->name)) mov->mode = MODE_MOV;
963

    
964
        if ( mov->mode == MODE_3GP || mov->mode == MODE_MP4 )
965
            mov_write_ftyp_tag(pb,s);
966
    }
967

    
968
    for (i=0; i<MAX_STREAMS; i++) {
969
        mov->tracks[i].mode = mov->mode;
970
    }
971

    
972
    put_flush_packet(pb);
973

    
974
    return 0;
975
}
976

    
977
static int mov_write_packet(AVFormatContext *s, AVPacket *pkt)
978
{
979
    MOVContext *mov = s->priv_data;
980
    ByteIOContext *pb = &s->pb;
981
    AVCodecContext *enc = &s->streams[pkt->stream_index]->codec;
982
    MOVTrack* trk = &mov->tracks[pkt->stream_index];
983
    int cl, id;
984
    unsigned int samplesInChunk = 0;
985
    int size= pkt->size;
986

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

    
990
    if (enc->codec_type == CODEC_TYPE_VIDEO ) {
991
        samplesInChunk = 1;
992
    }
993
    else if (enc->codec_type == CODEC_TYPE_AUDIO ) {
994
        if( enc->codec_id == CODEC_ID_AMR_NB) {
995
            /* We must find out how many AMR blocks there are in one packet */
996
            static uint16_t packed_size[16] =
997
                {13, 14, 16, 18, 20, 21, 27, 32, 6, 0, 0, 0, 0, 0, 0, 0};
998
            int len = 0;
999

    
1000
            while (len < size && samplesInChunk < 100) {
1001
                len += packed_size[(pkt->data[len] >> 3) & 0x0F];
1002
                samplesInChunk++;
1003
            }
1004
        }
1005
        else if(enc->codec_id == CODEC_ID_PCM_ALAW) {
1006
            samplesInChunk = size/enc->channels;
1007
        }
1008
        else if(enc->codec_id == CODEC_ID_PCM_S16BE || enc->codec_id == CODEC_ID_PCM_S16LE) {
1009
            samplesInChunk = size/(2*enc->channels);
1010
        }            
1011
        else {
1012
            samplesInChunk = 1;
1013
        }
1014
    }
1015

    
1016
    if ((enc->codec_id == CODEC_ID_MPEG4 || enc->codec_id == CODEC_ID_AAC)
1017
        && trk->vosLen == 0) {
1018
//        assert(enc->extradata_size);
1019

    
1020
        trk->vosLen = enc->extradata_size;
1021
        trk->vosData = av_malloc(trk->vosLen);
1022
        memcpy(trk->vosData, enc->extradata, trk->vosLen);
1023
    }
1024

    
1025
    cl = trk->entry / MOV_INDEX_CLUSTER_SIZE;
1026
    id = trk->entry % MOV_INDEX_CLUSTER_SIZE;
1027

    
1028
    if (trk->ents_allocated <= trk->entry) {
1029
        trk->cluster = av_realloc(trk->cluster, (cl+1)*sizeof(void*)); 
1030
        if (!trk->cluster)
1031
            return -1;
1032
        trk->cluster[cl] = av_malloc(MOV_INDEX_CLUSTER_SIZE*sizeof(MOVIentry));
1033
        if (!trk->cluster[cl])
1034
            return -1;
1035
        trk->ents_allocated += MOV_INDEX_CLUSTER_SIZE;
1036
    }
1037
    if (mov->mdat_written == 0) {
1038
        mov_write_mdat_tag(pb, mov);
1039
        mov->mdat_written = 1;
1040
        mov->time = s->timestamp;
1041
    }
1042

    
1043
    trk->cluster[cl][id].pos = url_ftell(pb);
1044
    trk->cluster[cl][id].samplesInChunk = samplesInChunk;
1045
    trk->cluster[cl][id].size = size;
1046
    trk->cluster[cl][id].entries = samplesInChunk;
1047
    if(enc->codec_type == CODEC_TYPE_VIDEO) {
1048
        trk->cluster[cl][id].key_frame = !!(pkt->flags & PKT_FLAG_KEY);
1049
        if(trk->cluster[cl][id].key_frame)
1050
            trk->hasKeyframes = 1;
1051
    }
1052
    trk->enc = enc;
1053
    trk->entry++;
1054
    trk->sampleCount += samplesInChunk;
1055
    trk->mdat_size += size;
1056

    
1057
    put_buffer(pb, pkt->data, size);
1058

    
1059
    put_flush_packet(pb);
1060
    return 0;
1061
}
1062

    
1063
static int mov_write_trailer(AVFormatContext *s)
1064
{
1065
    MOVContext *mov = s->priv_data;
1066
    ByteIOContext *pb = &s->pb;
1067
    int res = 0;
1068
    int i, j;
1069

    
1070
    offset_t moov_pos = url_ftell(pb);
1071

    
1072
    /* Write size of mdat tag */
1073
    for (i=0, j=0; i<MAX_STREAMS; i++) {
1074
        if(mov->tracks[i].ents_allocated > 0) {
1075
            j += mov->tracks[i].mdat_size;
1076
        }
1077
    }
1078
    url_fseek(pb, mov->mdat_pos, SEEK_SET);
1079
    put_be32(pb, j+8);
1080
    url_fseek(pb, moov_pos, SEEK_SET);
1081

    
1082
    mov_write_moov_tag(pb, mov, s);
1083

    
1084
    for (i=0; i<MAX_STREAMS; i++) {
1085
        for (j=0; j<mov->tracks[i].ents_allocated/MOV_INDEX_CLUSTER_SIZE; j++) {
1086
            av_free(mov->tracks[i].cluster[j]);
1087
        }
1088
        av_free(mov->tracks[i].cluster);
1089
        if( mov->tracks[i].vosLen ) av_free( mov->tracks[i].vosData );
1090

    
1091
        mov->tracks[i].cluster = NULL;
1092
        mov->tracks[i].ents_allocated = mov->tracks[i].entry = 0;
1093
    }
1094

    
1095
    put_flush_packet(pb);
1096

    
1097
    return res;
1098
}
1099

    
1100
static AVOutputFormat mov_oformat = {
1101
    "mov",
1102
    "mov format",
1103
    NULL,
1104
    "mov",
1105
    sizeof(MOVContext),
1106
    CODEC_ID_AAC,
1107
    CODEC_ID_MPEG4,
1108
    mov_write_header,
1109
    mov_write_packet,
1110
    mov_write_trailer,
1111
};
1112

    
1113
static AVOutputFormat _3gp_oformat = {
1114
    "3gp",
1115
    "3gp format",
1116
    NULL,
1117
    "3gp",
1118
    sizeof(MOVContext),
1119
    CODEC_ID_AMR_NB,
1120
    CODEC_ID_H263,
1121
    mov_write_header,
1122
    mov_write_packet,
1123
    mov_write_trailer,
1124
};
1125

    
1126
static AVOutputFormat mp4_oformat = {
1127
    "mp4",
1128
    "mp4 format",
1129
    "application/mp4",
1130
    "mp4,m4a",
1131
    sizeof(MOVContext),
1132
    CODEC_ID_AAC,
1133
    CODEC_ID_MPEG4,
1134
    mov_write_header,
1135
    mov_write_packet,
1136
    mov_write_trailer,
1137
};
1138

    
1139
int movenc_init(void)
1140
{
1141
    av_register_output_format(&mov_oformat);
1142
    av_register_output_format(&_3gp_oformat);
1143
    av_register_output_format(&mp4_oformat);
1144
    return 0;
1145
}