Statistics
| Branch: | Revision:

ffmpeg / libavformat / movenc.c @ a336965e

History | View | Annotate | Download (55.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
 */
20
#include "avformat.h"
21
#include "avi.h"
22
#include "avio.h"
23
#include "mov.h"
24

    
25
#undef NDEBUG
26
#include <assert.h>
27

    
28
#define MOV_INDEX_CLUSTER_SIZE 16384
29
#define globalTimescale 1000
30

    
31
#define MODE_MP4 0
32
#define MODE_MOV 1
33
#define MODE_3GP 2
34
#define MODE_PSP 3 // example working PSP command line:
35
// ffmpeg -i testinput.avi  -f psp -r 14.985 -s 320x240 -b 768 -ar 24000 -ab 32 M4V00001.MP4
36
#define MODE_3G2 4
37

    
38
typedef struct MOVIentry {
39
    unsigned int flags, size;
40
    uint64_t     pos;
41
    unsigned int samplesInChunk;
42
    char         key_frame;
43
    unsigned int entries;
44
    int64_t      cts;
45
} MOVIentry;
46

    
47
typedef struct MOVIndex {
48
    int         mode;
49
    int         entry;
50
    uint64_t    mdat_size;
51
    int         ents_allocated;
52
    long        timescale;
53
    long        time;
54
    int64_t     trackDuration;
55
    long        sampleCount;
56
    long        sampleDuration;
57
    int         hasKeyframes;
58
    int         hasBframes;
59
    int         language;
60
    int         trackID;
61
    AVCodecContext *enc;
62

    
63
    int         vosLen;
64
    uint8_t     *vosData;
65
    MOVIentry** cluster;
66
} MOVTrack;
67

    
68
typedef struct MOVContext {
69
    int     mode;
70
    int64_t time;
71
    int     nb_streams;
72
    int     mdat_written;
73
    offset_t mdat_pos;
74
    long    timescale;
75
    MOVTrack tracks[MAX_STREAMS];
76
} MOVContext;
77

    
78
static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack* track);
79

    
80
/* output language code from iso639 language name */
81
extern int ff_mov_iso639_to_lang(const char *lang, int mp4);
82

    
83
//FIXME supprt 64bit varaint with wide placeholders
84
static offset_t updateSize (ByteIOContext *pb, offset_t pos)
85
{
86
    offset_t curpos = url_ftell(pb);
87
    url_fseek(pb, pos, SEEK_SET);
88
    put_be32(pb, curpos - pos); /* rewrite size */
89
    url_fseek(pb, curpos, SEEK_SET);
90

    
91
    return curpos - pos;
92
}
93

    
94
/* Chunk offset atom */
95
static int mov_write_stco_tag(ByteIOContext *pb, MOVTrack* track)
96
{
97
    int i;
98
    int mode64 = 0; //   use 32 bit size variant if possible
99
    offset_t pos = url_ftell(pb);
100
    put_be32(pb, 0); /* size */
101
    if (pos > UINT32_MAX) {
102
        mode64 = 1;
103
        put_tag(pb, "co64");
104
    } else
105
        put_tag(pb, "stco");
106
    put_be32(pb, 0); /* version & flags */
107
    put_be32(pb, track->entry); /* entry count */
108
    for (i=0; i<track->entry; i++) {
109
        int cl = i / MOV_INDEX_CLUSTER_SIZE;
110
        int id = i % MOV_INDEX_CLUSTER_SIZE;
111
        if(mode64 == 1)
112
            put_be64(pb, track->cluster[cl][id].pos);
113
        else
114
            put_be32(pb, track->cluster[cl][id].pos);
115
    }
116
    return updateSize (pb, pos);
117
}
118

    
119
/* Sample size atom */
120
static int mov_write_stsz_tag(ByteIOContext *pb, MOVTrack* track)
121
{
122
    int equalChunks = 1;
123
    int i, j, entries = 0, tst = -1, oldtst = -1;
124

    
125
    offset_t pos = url_ftell(pb);
126
    put_be32(pb, 0); /* size */
127
    put_tag(pb, "stsz");
128
    put_be32(pb, 0); /* version & flags */
129

    
130
    for (i=0; i<track->entry; i++) {
131
        int cl = i / MOV_INDEX_CLUSTER_SIZE;
132
        int id = i % MOV_INDEX_CLUSTER_SIZE;
133
        tst = track->cluster[cl][id].size/track->cluster[cl][id].entries;
134
        if(oldtst != -1 && tst != oldtst) {
135
            equalChunks = 0;
136
        }
137
        oldtst = tst;
138
        entries += track->cluster[cl][id].entries;
139
    }
140
    if (equalChunks) {
141
        int sSize = track->cluster[0][0].size/track->cluster[0][0].entries;
142
        put_be32(pb, sSize); // sample size
143
        put_be32(pb, entries); // sample count
144
    }
145
    else {
146
        put_be32(pb, 0); // sample size
147
        put_be32(pb, entries); // sample count
148
        for (i=0; i<track->entry; i++) {
149
            int cl = i / MOV_INDEX_CLUSTER_SIZE;
150
            int id = i % MOV_INDEX_CLUSTER_SIZE;
151
            for ( j=0; j<track->cluster[cl][id].entries; j++) {
152
                put_be32(pb, track->cluster[cl][id].size /
153
                         track->cluster[cl][id].entries);
154
            }
155
        }
156
    }
157
    return updateSize (pb, pos);
158
}
159

    
160
/* Sample to chunk atom */
161
static int mov_write_stsc_tag(ByteIOContext *pb, MOVTrack* track)
162
{
163
    int index = 0, oldval = -1, i;
164
    offset_t entryPos, curpos;
165

    
166
    offset_t pos = url_ftell(pb);
167
    put_be32(pb, 0); /* size */
168
    put_tag(pb, "stsc");
169
    put_be32(pb, 0); // version & flags
170
    entryPos = url_ftell(pb);
171
    put_be32(pb, track->entry); // entry count
172
    for (i=0; i<track->entry; i++) {
173
        int cl = i / MOV_INDEX_CLUSTER_SIZE;
174
        int id = i % MOV_INDEX_CLUSTER_SIZE;
175
        if(oldval != track->cluster[cl][id].samplesInChunk)
176
        {
177
            put_be32(pb, i+1); // first chunk
178
            put_be32(pb, track->cluster[cl][id].samplesInChunk); // samples per chunk
179
            put_be32(pb, 0x1); // sample description index
180
            oldval = track->cluster[cl][id].samplesInChunk;
181
            index++;
182
        }
183
    }
184
    curpos = url_ftell(pb);
185
    url_fseek(pb, entryPos, SEEK_SET);
186
    put_be32(pb, index); // rewrite size
187
    url_fseek(pb, curpos, SEEK_SET);
188

    
189
    return updateSize (pb, pos);
190
}
191

    
192
/* Sync sample atom */
193
static int mov_write_stss_tag(ByteIOContext *pb, MOVTrack* track)
194
{
195
    offset_t curpos, entryPos;
196
    int i, index = 0;
197
    offset_t pos = url_ftell(pb);
198
    put_be32(pb, 0); // size
199
    put_tag(pb, "stss");
200
    put_be32(pb, 0); // version & flags
201
    entryPos = url_ftell(pb);
202
    put_be32(pb, track->entry); // entry count
203
    for (i=0; i<track->entry; i++) {
204
        int cl = i / MOV_INDEX_CLUSTER_SIZE;
205
        int id = i % MOV_INDEX_CLUSTER_SIZE;
206
        if(track->cluster[cl][id].key_frame == 1) {
207
            put_be32(pb, i+1);
208
            index++;
209
        }
210
    }
211
    curpos = url_ftell(pb);
212
    url_fseek(pb, entryPos, SEEK_SET);
213
    put_be32(pb, index); // rewrite size
214
    url_fseek(pb, curpos, SEEK_SET);
215
    return updateSize (pb, pos);
216
}
217

    
218
static int mov_write_damr_tag(ByteIOContext *pb)
219
{
220
    put_be32(pb, 0x11); /* size */
221
    put_tag(pb, "damr");
222
    put_tag(pb, "FFMP");
223
    put_byte(pb, 0);
224

    
225
    put_be16(pb, 0x80); /* Mode set (all modes for AMR_NB) */
226
    put_be16(pb, 0xa); /* Mode change period (no restriction) */
227
    //put_be16(pb, 0x81ff); /* Mode set (all modes for AMR_NB) */
228
    //put_be16(pb, 1); /* Mode change period (no restriction) */
229
    return 0x11;
230
}
231

    
232
static int mov_write_wave_tag(ByteIOContext *pb, MOVTrack* track)
233
{
234
    offset_t pos = url_ftell(pb);
235

    
236
    put_be32(pb, 0);     /* size */
237
    put_tag(pb, "wave");
238

    
239
    put_be32(pb, 12);    /* size */
240
    put_tag(pb, "frma");
241
    put_tag(pb, "mp4a");
242

    
243
    put_be32(pb, 12);    /* size */
244
    put_tag(pb, "mp4a");
245
    put_be32(pb, 0);
246

    
247
    mov_write_esds_tag(pb, track);
248

    
249
    put_be32(pb, 12);    /* size */
250
    put_tag(pb, "srcq");
251
    put_be32(pb, 0x40);
252

    
253
    put_be32(pb, 8);     /* size */
254
    put_be32(pb, 0);     /* null tag */
255

    
256
    return updateSize (pb, pos);
257
}
258

    
259
static const CodecTag codec_movaudio_tags[] = {
260
    { CODEC_ID_PCM_MULAW, MKTAG('u', 'l', 'a', 'w') },
261
    { CODEC_ID_PCM_ALAW, MKTAG('a', 'l', 'a', 'w') },
262
    { CODEC_ID_ADPCM_IMA_QT, MKTAG('i', 'm', 'a', '4') },
263
    { CODEC_ID_MACE3, MKTAG('M', 'A', 'C', '3') },
264
    { CODEC_ID_MACE6, MKTAG('M', 'A', 'C', '6') },
265
    { CODEC_ID_AAC, MKTAG('m', 'p', '4', 'a') },
266
    { CODEC_ID_AMR_NB, MKTAG('s', 'a', 'm', 'r') },
267
    { CODEC_ID_AMR_WB, MKTAG('s', 'a', 'w', 'b') },
268
    { CODEC_ID_PCM_S16BE, MKTAG('t', 'w', 'o', 's') },
269
    { CODEC_ID_PCM_S16LE, MKTAG('s', 'o', 'w', 't') },
270
    { CODEC_ID_MP3, MKTAG('.', 'm', 'p', '3') },
271
    { CODEC_ID_NONE, 0 },
272
};
273

    
274
static int mov_write_audio_tag(ByteIOContext *pb, MOVTrack* track)
275
{
276
    offset_t pos = url_ftell(pb);
277
    int tag;
278

    
279
    put_be32(pb, 0); /* size */
280

    
281
    tag = track->enc->codec_tag;
282
    if (!tag)
283
    tag = codec_get_tag(codec_movaudio_tags, track->enc->codec_id);
284
    // if no mac fcc found, try with Microsoft tags
285
    if (!tag)
286
    {
287
        int tmp = codec_get_tag(codec_wav_tags, track->enc->codec_id);
288
        tag = MKTAG('m', 's', ((tmp >> 8) & 0xff), (tmp & 0xff));
289
    }
290
    put_le32(pb, tag); // store it byteswapped
291

    
292
    put_be32(pb, 0); /* Reserved */
293
    put_be16(pb, 0); /* Reserved */
294
    put_be16(pb, 1); /* Data-reference index, XXX  == 1 */
295

    
296
    /* SoundDescription */
297
    if(track->mode == MODE_MOV && track->enc->codec_id == CODEC_ID_AAC)
298
        put_be16(pb, 1); /* Version 1 */
299
    else
300
        put_be16(pb, 0); /* Version 0 */
301
    put_be16(pb, 0); /* Revision level */
302
    put_be32(pb, 0); /* Reserved */
303

    
304
    put_be16(pb, track->enc->channels); /* Number of channels */
305
    /* TODO: Currently hard-coded to 16-bit, there doesn't seem
306
                 to be a good way to get number of bits of audio */
307
    put_be16(pb, 0x10); /* Reserved */
308

    
309
    if(track->enc->codec_id == CODEC_ID_AAC ||
310
       track->enc->codec_id == CODEC_ID_MP3)
311
    {
312
        put_be16(pb, 0xfffe); /* compression ID (vbr)*/
313
    }
314
    else
315
    {
316
        put_be16(pb, 0); /* compression ID (= 0) */
317
    }
318
    put_be16(pb, 0); /* packet size (= 0) */
319
    put_be16(pb, track->timescale); /* Time scale */
320
    put_be16(pb, 0); /* Reserved */
321

    
322
    if(track->mode == MODE_MOV && track->enc->codec_id == CODEC_ID_AAC)
323
    {
324
        /* SoundDescription V1 extended info */
325
        put_be32(pb, track->enc->frame_size); /* Samples per packet  */
326
        put_be32(pb, 1536); /* Bytes per packet */
327
        put_be32(pb, 2); /* Bytes per frame */
328
        put_be32(pb, 2); /* Bytes per sample */
329
    }
330

    
331
    if(track->enc->codec_id == CODEC_ID_AAC) {
332
        if( track->mode == MODE_MOV ) mov_write_wave_tag(pb, track);
333
        else mov_write_esds_tag(pb, track);
334
    }
335
    if(track->enc->codec_id == CODEC_ID_AMR_NB)
336
        mov_write_damr_tag(pb);
337
    return updateSize (pb, pos);
338
}
339

    
340
static int mov_write_d263_tag(ByteIOContext *pb)
341
{
342
    put_be32(pb, 0xf); /* size */
343
    put_tag(pb, "d263");
344
    put_tag(pb, "FFMP");
345
    put_be16(pb, 0x0a);
346
    put_byte(pb, 0);
347
    return 0xf;
348
}
349

    
350
/* TODO: No idea about these values */
351
static int mov_write_svq3_tag(ByteIOContext *pb)
352
{
353
    put_be32(pb, 0x15);
354
    put_tag(pb, "SMI ");
355
    put_tag(pb, "SEQH");
356
    put_be32(pb, 0x5);
357
    put_be32(pb, 0xe2c0211d);
358
    put_be32(pb, 0xc0000000);
359
    put_byte(pb, 0);
360
    return 0x15;
361
}
362

    
363
static uint8_t *avc_find_startcode( uint8_t *p, uint8_t *end )
364
{
365
    uint8_t *a = p + 4 - ((int)p & 3);
366

    
367
    for( end -= 3; p < a && p < end; p++ ) {
368
        if( p[0] == 0 && p[1] == 0 && p[2] == 1 )
369
            return p;
370
    }
371

    
372
    for( end -= 3; p < end; p += 4 ) {
373
        uint32_t x = *(uint32_t*)p;
374
//      if( (x - 0x01000100) & (~x) & 0x80008000 ) // little endian
375
//      if( (x - 0x00010001) & (~x) & 0x00800080 ) // big endian
376
        if( (x - 0x01010101) & (~x) & 0x80808080 ) { // generic
377
            if( p[1] == 0 ) {
378
                if( p[0] == 0 && p[2] == 1 )
379
                    return p;
380
                if( p[2] == 0 && p[3] == 1 )
381
                    return p+1;
382
            }
383
            if( p[3] == 0 ) {
384
                if( p[2] == 0 && p[4] == 1 )
385
                    return p+2;
386
                if( p[4] == 0 && p[5] == 1 )
387
                    return p+3;
388
            }
389
        }
390
    }
391

    
392
    for( end += 3; p < end; p++ ) {
393
        if( p[0] == 0 && p[1] == 0 && p[2] == 1 )
394
            return p;
395
    }
396

    
397
    return end + 3;
398
}
399

    
400
static void avc_parse_nal_units(uint8_t **buf, int *size)
401
{
402
    ByteIOContext pb;
403
    uint8_t *p = *buf;
404
    uint8_t *end = p + *size;
405
    uint8_t *nal_start, *nal_end;
406

    
407
    url_open_dyn_buf(&pb);
408
    nal_start = avc_find_startcode(p, end);
409
    while (nal_start < end) {
410
        while(!*(nal_start++));
411
        nal_end = avc_find_startcode(nal_start, end);
412
        put_be32(&pb, nal_end - nal_start);
413
        put_buffer(&pb, nal_start, nal_end - nal_start);
414
        nal_start = nal_end;
415
    }
416
    av_freep(buf);
417
    *size = url_close_dyn_buf(&pb, buf);
418
}
419

    
420
static int mov_write_avcc_tag(ByteIOContext *pb, MOVTrack *track)
421
{
422
    offset_t pos = url_ftell(pb);
423

    
424
    put_be32(pb, 0);
425
    put_tag(pb, "avcC");
426
    if (track->vosLen > 6) {
427
        /* check for h264 start code */
428
        if (BE_32(track->vosData) == 0x00000001) {
429
            uint8_t *buf, *end;
430
            uint32_t sps_size=0, pps_size=0;
431
            uint8_t *sps=0, *pps=0;
432

    
433
            avc_parse_nal_units(&track->vosData, &track->vosLen);
434
            buf = track->vosData;
435
            end = track->vosData + track->vosLen;
436

    
437
            put_byte(pb, 1); /* version */
438
            put_byte(pb, 77); /* profile */
439
            put_byte(pb, 64); /* profile compat */
440
            put_byte(pb, 30); /* level */
441
            put_byte(pb, 0xff); /* 6 bits reserved (111111) + 2 bits nal size length - 1 (11) */
442
            put_byte(pb, 0xe1); /* 3 bits reserved (111) + 5 bits number of sps (00001) */
443

    
444
            /* look for sps and pps */
445
            while (buf < end) {
446
                unsigned int size;
447
                uint8_t nal_type;
448
                size = BE_32(buf);
449
                nal_type = buf[4] & 0x1f;
450
                if (nal_type == 7) { /* SPS */
451
                    sps = buf + 4;
452
                    sps_size = size;
453
                } else if (nal_type == 8) { /* PPS */
454
                    pps = buf + 4;
455
                    pps_size = size;
456
                }
457
                buf += size + 4;
458
            }
459
            assert(sps);
460
            assert(pps);
461
            put_be16(pb, sps_size);
462
            put_buffer(pb, sps, sps_size);
463
            put_byte(pb, 1); /* number of pps */
464
            put_be16(pb, pps_size);
465
            put_buffer(pb, pps, pps_size);
466
        } else {
467
            put_buffer(pb, track->vosData, track->vosLen);
468
        }
469
    }
470
    return updateSize(pb, pos);
471
}
472

    
473
static unsigned int descrLength(unsigned int len)
474
{
475
    if (len < 0x00000080)
476
        return 2 + len;
477
    else if (len < 0x00004000)
478
        return 3 + len;
479
    else if(len < 0x00200000)
480
        return 4 + len;
481
    else
482
        return 5 + len;
483
}
484

    
485
static void putDescr(ByteIOContext *pb, int tag, int size)
486
{
487
    uint32_t len;
488
    uint8_t  vals[4];
489

    
490
    len = size;
491
    vals[3] = (uint8_t)(len & 0x7f);
492
    len >>= 7;
493
    vals[2] = (uint8_t)((len & 0x7f) | 0x80);
494
    len >>= 7;
495
    vals[1] = (uint8_t)((len & 0x7f) | 0x80);
496
    len >>= 7;
497
    vals[0] = (uint8_t)((len & 0x7f) | 0x80);
498

    
499
    put_byte(pb, tag); // DescriptorTag
500

    
501
    if (size < 0x00000080)
502
    {
503
        put_byte(pb, vals[3]);
504
    }
505
    else if (size < 0x00004000)
506
    {
507
        put_byte(pb, vals[2]);
508
        put_byte(pb, vals[3]);
509
    }
510
    else if (size < 0x00200000)
511
    {
512
        put_byte(pb, vals[1]);
513
        put_byte(pb, vals[2]);
514
        put_byte(pb, vals[3]);
515
    }
516
    else if (size < 0x10000000)
517
    {
518
        put_byte(pb, vals[0]);
519
        put_byte(pb, vals[1]);
520
        put_byte(pb, vals[2]);
521
        put_byte(pb, vals[3]);
522
    }
523
}
524

    
525
static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack* track) // Basic
526
{
527
    int decoderSpecificInfoLen;
528
    offset_t pos = url_ftell(pb);
529

    
530
    decoderSpecificInfoLen = track->vosLen ? descrLength(track->vosLen):0;
531

    
532
    put_be32(pb, 0);               // size
533
    put_tag(pb, "esds");
534
    put_be32(pb, 0);               // Version
535

    
536
    // ES descriptor
537
    putDescr(pb, 0x03, 3 + descrLength(13 + decoderSpecificInfoLen) +
538
             descrLength(1));
539
    put_be16(pb, track->trackID);
540
    put_byte(pb, 0x00);            // flags (= no flags)
541

    
542
    // DecoderConfig descriptor
543
    putDescr(pb, 0x04, 13 + decoderSpecificInfoLen);
544

    
545
    // Object type indication
546
    put_byte(pb, codec_get_tag(ff_mov_obj_type, track->enc->codec_id));
547

    
548
    // the following fields is made of 6 bits to identify the streamtype (4 for video, 5 for audio)
549
    // plus 1 bit to indicate upstream and 1 bit set to 1 (reserved)
550
    if(track->enc->codec_type == CODEC_TYPE_AUDIO)
551
        put_byte(pb, 0x15);            // flags (= Audiostream)
552
    else
553
        put_byte(pb, 0x11);            // flags (= Visualstream)
554

    
555
    put_byte(pb,  track->enc->rc_buffer_size>>(3+16));             // Buffersize DB (24 bits)
556
    put_be16(pb, (track->enc->rc_buffer_size>>3)&0xFFFF);          // Buffersize DB
557

    
558
    put_be32(pb, FFMAX(track->enc->bit_rate, track->enc->rc_max_rate));     // maxbitrate  (FIXME should be max rate in any 1 sec window)
559
    if(track->enc->rc_max_rate != track->enc->rc_min_rate || track->enc->rc_min_rate==0)
560
        put_be32(pb, 0);     // vbr
561
    else
562
        put_be32(pb, track->enc->rc_max_rate);     // avg bitrate
563

    
564
    if (track->vosLen)
565
    {
566
        // DecoderSpecific info descriptor
567
        putDescr(pb, 0x05, track->vosLen);
568
        put_buffer(pb, track->vosData, track->vosLen);
569
    }
570

    
571

    
572
    // SL descriptor
573
    putDescr(pb, 0x06, 1);
574
    put_byte(pb, 0x02);
575
    return updateSize (pb, pos);
576
}
577

    
578
static const CodecTag codec_movvideo_tags[] = {
579
    { CODEC_ID_SVQ1, MKTAG('S', 'V', 'Q', '1') },
580
    { CODEC_ID_SVQ3, MKTAG('S', 'V', 'Q', '3') },
581
    { CODEC_ID_MPEG4, MKTAG('m', 'p', '4', 'v') },
582
    { CODEC_ID_H263, MKTAG('s', '2', '6', '3') },
583
    { CODEC_ID_H264, MKTAG('a', 'v', 'c', '1') },
584
    /* special handling in mov_find_video_codec_tag */
585
    { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'c', ' ') }, /* DV NTSC */
586
    { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'c', 'p') }, /* DV PAL */
587
    { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'p', 'p') }, /* DVCPRO PAL */
588
    { CODEC_ID_DVVIDEO, MKTAG('d', 'v', '5', 'n') }, /* DVCPRO50 NTSC */
589
    { CODEC_ID_DVVIDEO, MKTAG('d', 'v', '5', 'p') }, /* DVCPRO50 PAL */
590
    { CODEC_ID_NONE, 0 },
591
};
592

    
593
static int mov_find_video_codec_tag(MOVTrack* track)
594
{
595
    int tag;
596

    
597
    tag = track->enc->codec_tag;
598
    if (!tag) {
599
        if (track->enc->codec_id == CODEC_ID_DVVIDEO) {
600
            if (track->enc->height == 480) { /* NTSC */
601
                if (track->enc->pix_fmt == PIX_FMT_YUV422P)
602
                    tag = MKTAG('d', 'v', '5', 'n');
603
                else
604
                    tag = MKTAG('d', 'v', 'c', ' ');
605
            } else { /* assume PAL */
606
                if (track->enc->pix_fmt == PIX_FMT_YUV422P)
607
                    tag = MKTAG('d', 'v', '5', 'p');
608
                else if (track->enc->pix_fmt == PIX_FMT_YUV420P)
609
                    tag = MKTAG('d', 'v', 'c', 'p');
610
                else
611
                    tag = MKTAG('d', 'v', 'p', 'p');
612
            }
613
        } else {
614
            tag = codec_get_tag(codec_movvideo_tags, track->enc->codec_id);
615
        }
616
    }
617
    // if no mac fcc found, try with Microsoft tags
618
    if (!tag)
619
        tag = codec_get_tag(codec_bmp_tags, track->enc->codec_id);
620
    assert(tag);
621
    return tag;
622
}
623

    
624
static int mov_write_video_tag(ByteIOContext *pb, MOVTrack* track)
625
{
626
    offset_t pos = url_ftell(pb);
627
    char compressor_name[32];
628
    int tag;
629

    
630
    put_be32(pb, 0); /* size */
631

    
632
    tag = mov_find_video_codec_tag(track);
633
    put_le32(pb, tag); // store it byteswapped
634

    
635
    put_be32(pb, 0); /* Reserved */
636
    put_be16(pb, 0); /* Reserved */
637
    put_be16(pb, 1); /* Data-reference index */
638

    
639
    put_be16(pb, 0); /* Codec stream version */
640
    put_be16(pb, 0); /* Codec stream revision (=0) */
641
    put_tag(pb, "FFMP"); /* Vendor */
642
    if(track->enc->codec_id == CODEC_ID_RAWVIDEO) {
643
        put_be32(pb, 0); /* Temporal Quality */
644
        put_be32(pb, 0x400); /* Spatial Quality = lossless*/
645
    } else {
646
        put_be32(pb, 0x200); /* Temporal Quality = normal */
647
        put_be32(pb, 0x200); /* Spatial Quality = normal */
648
    }
649
    put_be16(pb, track->enc->width); /* Video width */
650
    put_be16(pb, track->enc->height); /* Video height */
651
    put_be32(pb, 0x00480000); /* Horizontal resolution 72dpi */
652
    put_be32(pb, 0x00480000); /* Vertical resolution 72dpi */
653
    put_be32(pb, 0); /* Data size (= 0) */
654
    put_be16(pb, 1); /* Frame count (= 1) */
655

    
656
    memset(compressor_name,0,32);
657
    if (track->enc->codec && track->enc->codec->name)
658
        strncpy(compressor_name,track->enc->codec->name,31);
659
    put_byte(pb, strlen(compressor_name));
660
    put_buffer(pb, compressor_name, 31);
661

    
662
    put_be16(pb, 0x18); /* Reserved */
663
    put_be16(pb, 0xffff); /* Reserved */
664
    if(track->enc->codec_id == CODEC_ID_MPEG4)
665
        mov_write_esds_tag(pb, track);
666
    else if(track->enc->codec_id == CODEC_ID_H263)
667
        mov_write_d263_tag(pb);
668
    else if(track->enc->codec_id == CODEC_ID_SVQ3)
669
        mov_write_svq3_tag(pb);
670
    else if(track->enc->codec_id == CODEC_ID_H264)
671
        mov_write_avcc_tag(pb, track);
672

    
673
    return updateSize (pb, pos);
674
}
675

    
676
static int mov_write_stsd_tag(ByteIOContext *pb, MOVTrack* track)
677
{
678
    offset_t pos = url_ftell(pb);
679
    put_be32(pb, 0); /* size */
680
    put_tag(pb, "stsd");
681
    put_be32(pb, 0); /* version & flags */
682
    put_be32(pb, 1); /* entry count */
683
    if (track->enc->codec_type == CODEC_TYPE_VIDEO)
684
        mov_write_video_tag(pb, track);
685
    else if (track->enc->codec_type == CODEC_TYPE_AUDIO)
686
        mov_write_audio_tag(pb, track);
687
    return updateSize(pb, pos);
688
}
689

    
690
static int mov_write_ctts_tag(ByteIOContext *pb, MOVTrack* track)
691
{
692
    Time2Sample *ctts_entries;
693
    uint32_t entries = 0;
694
    uint32_t atom_size;
695
    int i;
696

    
697
    ctts_entries = av_malloc((track->entry + 1) * sizeof(*ctts_entries)); /* worst case */
698
    ctts_entries[0].count = 1;
699
    ctts_entries[0].duration = track->cluster[0][0].cts;
700
    for (i=1; i<track->entry; i++) {
701
        int cl = i / MOV_INDEX_CLUSTER_SIZE;
702
        int id = i % MOV_INDEX_CLUSTER_SIZE;
703
        if (track->cluster[cl][id].cts == ctts_entries[entries].duration) {
704
            ctts_entries[entries].count++; /* compress */
705
        } else {
706
            entries++;
707
            ctts_entries[entries].duration = track->cluster[cl][id].cts;
708
            ctts_entries[entries].count = 1;
709
        }
710
    }
711
    entries++; /* last one */
712
    atom_size = 16 + (entries * 8);
713
    put_be32(pb, atom_size); /* size */
714
    put_tag(pb, "ctts");
715
    put_be32(pb, 0); /* version & flags */
716
    put_be32(pb, entries); /* entry count */
717
    for (i=0; i<entries; i++) {
718
        put_be32(pb, ctts_entries[i].count);
719
        put_be32(pb, ctts_entries[i].duration);
720
    }
721
    av_free(ctts_entries);
722
    return atom_size;
723
}
724

    
725
/* TODO: */
726
/* Time to sample atom */
727
static int mov_write_stts_tag(ByteIOContext *pb, MOVTrack* track)
728
{
729
    put_be32(pb, 0x18); /* size */
730
    put_tag(pb, "stts");
731
    put_be32(pb, 0); /* version & flags */
732
    put_be32(pb, 1); /* entry count */
733

    
734
    put_be32(pb, track->sampleCount); /* sample count */
735
    put_be32(pb, track->sampleDuration); /* sample duration */
736
    return 0x18;
737
}
738

    
739
static int mov_write_dref_tag(ByteIOContext *pb)
740
{
741
    put_be32(pb, 28); /* size */
742
    put_tag(pb, "dref");
743
    put_be32(pb, 0); /* version & flags */
744
    put_be32(pb, 1); /* entry count */
745

    
746
    put_be32(pb, 0xc); /* size */
747
    put_tag(pb, "url ");
748
    put_be32(pb, 1); /* version & flags */
749

    
750
    return 28;
751
}
752

    
753
static int mov_write_stbl_tag(ByteIOContext *pb, MOVTrack* track)
754
{
755
    offset_t pos = url_ftell(pb);
756
    put_be32(pb, 0); /* size */
757
    put_tag(pb, "stbl");
758
    mov_write_stsd_tag(pb, track);
759
    mov_write_stts_tag(pb, track);
760
    if (track->enc->codec_type == CODEC_TYPE_VIDEO &&
761
        track->hasKeyframes)
762
        mov_write_stss_tag(pb, track);
763
    if (track->enc->codec_type == CODEC_TYPE_VIDEO &&
764
        track->hasBframes)
765
        mov_write_ctts_tag(pb, track);
766
    mov_write_stsc_tag(pb, track);
767
    mov_write_stsz_tag(pb, track);
768
    mov_write_stco_tag(pb, track);
769
    return updateSize(pb, pos);
770
}
771

    
772
static int mov_write_dinf_tag(ByteIOContext *pb)
773
{
774
    offset_t pos = url_ftell(pb);
775
    put_be32(pb, 0); /* size */
776
    put_tag(pb, "dinf");
777
    mov_write_dref_tag(pb);
778
    return updateSize(pb, pos);
779
}
780

    
781
static int mov_write_smhd_tag(ByteIOContext *pb)
782
{
783
    put_be32(pb, 16); /* size */
784
    put_tag(pb, "smhd");
785
    put_be32(pb, 0); /* version & flags */
786
    put_be16(pb, 0); /* reserved (balance, normally = 0) */
787
    put_be16(pb, 0); /* reserved */
788
    return 16;
789
}
790

    
791
static int mov_write_vmhd_tag(ByteIOContext *pb)
792
{
793
    put_be32(pb, 0x14); /* size (always 0x14) */
794
    put_tag(pb, "vmhd");
795
    put_be32(pb, 0x01); /* version & flags */
796
    put_be64(pb, 0); /* reserved (graphics mode = copy) */
797
    return 0x14;
798
}
799

    
800
static int mov_write_hdlr_tag(ByteIOContext *pb, MOVTrack* track)
801
{
802
    char *descr, *hdlr, *hdlr_type;
803
    offset_t pos = url_ftell(pb);
804

    
805
    if (!track) { /* no media --> data handler */
806
        hdlr = "dhlr";
807
        hdlr_type = "url ";
808
        descr = "DataHandler";
809
    } else {
810
        hdlr = (track->mode == MODE_MOV) ? "mhlr" : "\0\0\0\0";
811
        if (track->enc->codec_type == CODEC_TYPE_VIDEO) {
812
            hdlr_type = "vide";
813
            descr = "VideoHandler";
814
        } else {
815
            hdlr_type = "soun";
816
            descr = "SoundHandler";
817
        }
818
    }
819

    
820
    put_be32(pb, 0); /* size */
821
    put_tag(pb, "hdlr");
822
    put_be32(pb, 0); /* Version & flags */
823
    put_buffer(pb, hdlr, 4); /* handler */
824
    put_tag(pb, hdlr_type); /* handler type */
825
    put_be32(pb ,0); /* reserved */
826
    put_be32(pb ,0); /* reserved */
827
    put_be32(pb ,0); /* reserved */
828
    put_byte(pb, strlen(descr)); /* string counter */
829
    put_buffer(pb, descr, strlen(descr)); /* handler description */
830
    return updateSize(pb, pos);
831
}
832

    
833
static int mov_write_minf_tag(ByteIOContext *pb, MOVTrack* track)
834
{
835
    offset_t pos = url_ftell(pb);
836
    put_be32(pb, 0); /* size */
837
    put_tag(pb, "minf");
838
    if(track->enc->codec_type == CODEC_TYPE_VIDEO)
839
        mov_write_vmhd_tag(pb);
840
    else
841
        mov_write_smhd_tag(pb);
842
    if (track->mode == MODE_MOV) /* FIXME: Why do it for MODE_MOV only ? */
843
        mov_write_hdlr_tag(pb, NULL);
844
    mov_write_dinf_tag(pb);
845
    mov_write_stbl_tag(pb, track);
846
    return updateSize(pb, pos);
847
}
848

    
849
static int mov_write_mdhd_tag(ByteIOContext *pb, MOVTrack* track)
850
{
851
    int version = track->trackDuration < INT32_MAX ? 0 : 1;
852

    
853
    (version == 1) ? put_be32(pb, 44) : put_be32(pb, 32); /* size */
854
    put_tag(pb, "mdhd");
855
    put_byte(pb, version);
856
    put_be24(pb, 0); /* flags */
857
    if (version == 1) {
858
        put_be64(pb, track->time);
859
        put_be64(pb, track->time);
860
    } else {
861
        put_be32(pb, track->time); /* creation time */
862
        put_be32(pb, track->time); /* modification time */
863
    }
864
    put_be32(pb, track->timescale); /* time scale (sample rate for audio) */
865
    (version == 1) ? put_be64(pb, track->trackDuration) : put_be32(pb, track->trackDuration); /* duration */
866
    put_be16(pb, track->language); /* language */
867
    put_be16(pb, 0); /* reserved (quality) */
868
    return 32;
869
}
870

    
871
static int mov_write_mdia_tag(ByteIOContext *pb, MOVTrack* track)
872
{
873
    offset_t pos = url_ftell(pb);
874
    put_be32(pb, 0); /* size */
875
    put_tag(pb, "mdia");
876
    mov_write_mdhd_tag(pb, track);
877
    mov_write_hdlr_tag(pb, track);
878
    mov_write_minf_tag(pb, track);
879
    return updateSize(pb, pos);
880
}
881

    
882
static int mov_write_tkhd_tag(ByteIOContext *pb, MOVTrack* track)
883
{
884
    int64_t duration = av_rescale_rnd(track->trackDuration, globalTimescale, track->timescale, AV_ROUND_UP);
885
    int version = duration < INT32_MAX ? 0 : 1;
886

    
887
    (version == 1) ? put_be32(pb, 104) : put_be32(pb, 92); /* size */
888
    put_tag(pb, "tkhd");
889
    put_byte(pb, version);
890
    put_be24(pb, 0xf); /* flags (track enabled) */
891
    if (version == 1) {
892
        put_be64(pb, track->time);
893
        put_be64(pb, track->time);
894
    } else {
895
        put_be32(pb, track->time); /* creation time */
896
        put_be32(pb, track->time); /* modification time */
897
    }
898
    put_be32(pb, track->trackID); /* track-id */
899
    put_be32(pb, 0); /* reserved */
900
    (version == 1) ? put_be64(pb, duration) : put_be32(pb, duration);
901

    
902
    put_be32(pb, 0); /* reserved */
903
    put_be32(pb, 0); /* reserved */
904
    put_be32(pb, 0x0); /* reserved (Layer & Alternate group) */
905
    /* Volume, only for audio */
906
    if(track->enc->codec_type == CODEC_TYPE_AUDIO)
907
        put_be16(pb, 0x0100);
908
    else
909
        put_be16(pb, 0);
910
    put_be16(pb, 0); /* reserved */
911

    
912
    /* Matrix structure */
913
    put_be32(pb, 0x00010000); /* reserved */
914
    put_be32(pb, 0x0); /* reserved */
915
    put_be32(pb, 0x0); /* reserved */
916
    put_be32(pb, 0x0); /* reserved */
917
    put_be32(pb, 0x00010000); /* reserved */
918
    put_be32(pb, 0x0); /* reserved */
919
    put_be32(pb, 0x0); /* reserved */
920
    put_be32(pb, 0x0); /* reserved */
921
    put_be32(pb, 0x40000000); /* reserved */
922

    
923
    /* Track width and height, for visual only */
924
    if(track->enc->codec_type == CODEC_TYPE_VIDEO) {
925
        double sample_aspect_ratio = av_q2d(track->enc->sample_aspect_ratio);
926
        if( !sample_aspect_ratio ) sample_aspect_ratio = 1;
927
        put_be32(pb, sample_aspect_ratio * track->enc->width*0x10000);
928
        put_be32(pb, track->enc->height*0x10000);
929
    }
930
    else {
931
        put_be32(pb, 0);
932
        put_be32(pb, 0);
933
    }
934
    return 0x5c;
935
}
936

    
937
// This box seems important for the psp playback ... without it the movie seems to hang
938
static int mov_write_edts_tag(ByteIOContext *pb, MOVTrack *track)
939
{
940
    put_be32(pb, 0x24); /* size  */
941
    put_tag(pb, "edts");
942
    put_be32(pb, 0x1c); /* size  */
943
    put_tag(pb, "elst");
944
    put_be32(pb, 0x0);
945
    put_be32(pb, 0x1);
946

    
947
    put_be32(pb, av_rescale_rnd(track->trackDuration, globalTimescale, track->timescale, AV_ROUND_UP)); /* duration   ... doesn't seem to effect psp */
948

    
949
    if (track->hasBframes)
950
        put_be32(pb, track->sampleDuration); /* first pts is 1 */
951
    else
952
        put_be32(pb, 0);
953
    put_be32(pb, 0x00010000);
954
    return 0x24;
955
}
956

    
957
// goes at the end of each track!  ... Critical for PSP playback ("Incompatible data" without it)
958
static int mov_write_uuid_tag_psp(ByteIOContext *pb, MOVTrack *mov)
959
{
960
    put_be32(pb, 0x34); /* size ... reports as 28 in mp4box! */
961
    put_tag(pb, "uuid");
962
    put_tag(pb, "USMT");
963
    put_be32(pb, 0x21d24fce);
964
    put_be32(pb, 0xbb88695c);
965
    put_be32(pb, 0xfac9c740);
966
    put_be32(pb, 0x1c);     // another size here!
967
    put_tag(pb, "MTDT");
968
    put_be32(pb, 0x00010012);
969
    put_be32(pb, 0x0a);
970
    put_be32(pb, 0x55c40000);
971
    put_be32(pb, 0x1);
972
    put_be32(pb, 0x0);
973
    return 0x34;
974
}
975

    
976
static int mov_write_trak_tag(ByteIOContext *pb, MOVTrack* track)
977
{
978
    offset_t pos = url_ftell(pb);
979
    put_be32(pb, 0); /* size */
980
    put_tag(pb, "trak");
981
    mov_write_tkhd_tag(pb, track);
982
    if (track->mode == MODE_PSP || track->hasBframes)
983
        mov_write_edts_tag(pb, track);  // PSP Movies require edts box
984
    mov_write_mdia_tag(pb, track);
985
    if (track->mode == MODE_PSP)
986
        mov_write_uuid_tag_psp(pb,track);  // PSP Movies require this uuid box
987
    return updateSize(pb, pos);
988
}
989

    
990
#if 0
991
/* TODO: Not sorted out, but not necessary either */
992
static int mov_write_iods_tag(ByteIOContext *pb, MOVContext *mov)
993
{
994
    put_be32(pb, 0x15); /* size */
995
    put_tag(pb, "iods");
996
    put_be32(pb, 0);    /* version & flags */
997
    put_be16(pb, 0x1007);
998
    put_byte(pb, 0);
999
    put_be16(pb, 0x4fff);
1000
    put_be16(pb, 0xfffe);
1001
    put_be16(pb, 0x01ff);
1002
    return 0x15;
1003
}
1004
#endif
1005

    
1006
static int mov_write_mvhd_tag(ByteIOContext *pb, MOVContext *mov)
1007
{
1008
    int maxTrackID = 1, i;
1009
    int64_t maxTrackLenTemp, maxTrackLen = 0;
1010
    int version;
1011

    
1012
    for (i=0; i<MAX_STREAMS; i++) {
1013
        if(mov->tracks[i].entry > 0) {
1014
            maxTrackLenTemp = av_rescale_rnd(mov->tracks[i].trackDuration, globalTimescale, mov->tracks[i].timescale, AV_ROUND_UP);
1015
            if(maxTrackLen < maxTrackLenTemp)
1016
                maxTrackLen = maxTrackLenTemp;
1017
            if(maxTrackID < mov->tracks[i].trackID)
1018
                maxTrackID = mov->tracks[i].trackID;
1019
        }
1020
    }
1021

    
1022
    version = maxTrackLen < UINT32_MAX ? 0 : 1;
1023
    (version == 1) ? put_be32(pb, 120) : put_be32(pb, 108); /* size */
1024
    put_tag(pb, "mvhd");
1025
    put_byte(pb, version);
1026
    put_be24(pb, 0); /* flags */
1027
    if (version == 1) {
1028
        put_be64(pb, mov->time);
1029
        put_be64(pb, mov->time);
1030
    } else {
1031
        put_be32(pb, mov->time); /* creation time */
1032
        put_be32(pb, mov->time); /* modification time */
1033
    }
1034
    put_be32(pb, mov->timescale); /* timescale */
1035
    (version == 1) ? put_be64(pb, maxTrackLen) : put_be32(pb, maxTrackLen); /* duration of longest track */
1036

    
1037
    put_be32(pb, 0x00010000); /* reserved (preferred rate) 1.0 = normal */
1038
    put_be16(pb, 0x0100); /* reserved (preferred volume) 1.0 = normal */
1039
    put_be16(pb, 0); /* reserved */
1040
    put_be32(pb, 0); /* reserved */
1041
    put_be32(pb, 0); /* reserved */
1042

    
1043
    /* Matrix structure */
1044
    put_be32(pb, 0x00010000); /* reserved */
1045
    put_be32(pb, 0x0); /* reserved */
1046
    put_be32(pb, 0x0); /* reserved */
1047
    put_be32(pb, 0x0); /* reserved */
1048
    put_be32(pb, 0x00010000); /* reserved */
1049
    put_be32(pb, 0x0); /* reserved */
1050
    put_be32(pb, 0x0); /* reserved */
1051
    put_be32(pb, 0x0); /* reserved */
1052
    put_be32(pb, 0x40000000); /* reserved */
1053

    
1054
    put_be32(pb, 0); /* reserved (preview time) */
1055
    put_be32(pb, 0); /* reserved (preview duration) */
1056
    put_be32(pb, 0); /* reserved (poster time) */
1057
    put_be32(pb, 0); /* reserved (selection time) */
1058
    put_be32(pb, 0); /* reserved (selection duration) */
1059
    put_be32(pb, 0); /* reserved (current time) */
1060
    put_be32(pb, maxTrackID+1); /* Next track id */
1061
    return 0x6c;
1062
}
1063

    
1064
static int mov_write_itunes_hdlr_tag(ByteIOContext *pb, MOVContext* mov,
1065
                                     AVFormatContext *s)
1066
{
1067
    offset_t pos = url_ftell(pb);
1068
    put_be32(pb, 0); /* size */
1069
    put_tag(pb, "hdlr");
1070
    put_be32(pb, 0);
1071
    put_be32(pb, 0);
1072
    put_tag(pb, "mdir");
1073
    put_tag(pb, "appl");
1074
    put_be32(pb, 0);
1075
    put_be32(pb, 0);
1076
    put_be16(pb, 0);
1077
    return updateSize(pb, pos);
1078
}
1079

    
1080
/* helper function to write a data tag with the specified string as data */
1081
static int mov_write_string_data_tag(ByteIOContext *pb, MOVContext* mov,
1082
                                     AVFormatContext *s, const char *data)
1083
{
1084
    offset_t pos = url_ftell(pb);
1085
    put_be32(pb, 0); /* size */
1086
    put_tag(pb, "data");
1087
    put_be32(pb, 1);
1088
    put_be32(pb, 0);
1089
    put_buffer(pb, data, strlen(data));
1090
    return updateSize(pb, pos);
1091
}
1092

    
1093
/* iTunes name of the song/movie */
1094
static int mov_write_nam_tag(ByteIOContext *pb, MOVContext* mov,
1095
                             AVFormatContext *s)
1096
{
1097
    int size = 0;
1098
    if ( s->title[0] ) {
1099
        offset_t pos = url_ftell(pb);
1100
        put_be32(pb, 0); /* size */
1101
        put_tag(pb, "\251nam");
1102
        mov_write_string_data_tag(pb, mov, s, s->title);
1103
        size = updateSize(pb, pos);
1104
    }
1105
    return size;
1106
}
1107

    
1108
/* iTunes name of the artist/performer */
1109
static int mov_write_ART_tag(ByteIOContext *pb, MOVContext* mov,
1110
                             AVFormatContext *s)
1111
{
1112
    int size = 0;
1113
    if ( s->author[0] ) {
1114
        offset_t pos = url_ftell(pb);
1115
        put_be32(pb, 0); /* size */
1116
        put_tag(pb, "\251ART");
1117
        // we use the author here as this is the only thing that we have...
1118
        mov_write_string_data_tag(pb, mov, s, s->author);
1119
        size = updateSize(pb, pos);
1120
    }
1121
    return size;
1122
}
1123

    
1124
/* iTunes name of the writer */
1125
static int mov_write_wrt_tag(ByteIOContext *pb, MOVContext* mov,
1126
                             AVFormatContext *s)
1127
{
1128
    int size = 0;
1129
    if ( s->author[0] ) {
1130
        offset_t pos = url_ftell(pb);
1131
        put_be32(pb, 0); /* size */
1132
        put_tag(pb, "\251wrt");
1133
        mov_write_string_data_tag(pb, mov, s, s->author);
1134
        size = updateSize(pb, pos);
1135
    }
1136
    return size;
1137
}
1138

    
1139
/* iTunes name of the album */
1140
static int mov_write_alb_tag(ByteIOContext *pb, MOVContext* mov,
1141
                             AVFormatContext *s)
1142
{
1143
    int size = 0;
1144
    if ( s->album[0] ) {
1145
        offset_t pos = url_ftell(pb);
1146
        put_be32(pb, 0); /* size */
1147
        put_tag(pb, "\251alb");
1148
        mov_write_string_data_tag(pb, mov, s, s->album);
1149
        size = updateSize(pb, pos);
1150
    }
1151
    return size;
1152
}
1153

    
1154
/* iTunes year */
1155
static int mov_write_day_tag(ByteIOContext *pb, MOVContext* mov,
1156
                             AVFormatContext *s)
1157
{
1158
    char year[5];
1159
    int size = 0;
1160
    if ( s->year ) {
1161
        offset_t pos = url_ftell(pb);
1162
        put_be32(pb, 0); /* size */
1163
        put_tag(pb, "\251day");
1164
        snprintf(year, 5, "%04d", s->year);
1165
        mov_write_string_data_tag(pb, mov, s, year);
1166
        size = updateSize(pb, pos);
1167
    }
1168
    return size;
1169
}
1170

    
1171
/* iTunes tool used to create the file */
1172
static int mov_write_too_tag(ByteIOContext *pb, MOVContext* mov,
1173
                             AVFormatContext *s)
1174
{
1175
    offset_t pos = url_ftell(pb);
1176
    put_be32(pb, 0); /* size */
1177
    put_tag(pb, "\251too");
1178
    mov_write_string_data_tag(pb, mov, s, LIBAVFORMAT_IDENT);
1179
    return updateSize(pb, pos);
1180
}
1181

    
1182
/* iTunes comment */
1183
static int mov_write_cmt_tag(ByteIOContext *pb, MOVContext* mov,
1184
                             AVFormatContext *s)
1185
{
1186
    int size = 0;
1187
    if ( s->comment[0] ) {
1188
        offset_t pos = url_ftell(pb);
1189
        put_be32(pb, 0); /* size */
1190
        put_tag(pb, "\251cmt");
1191
        mov_write_string_data_tag(pb, mov, s, s->comment);
1192
        size = updateSize(pb, pos);
1193
    }
1194
    return size;
1195
}
1196

    
1197
/* iTunes custom genre */
1198
static int mov_write_gen_tag(ByteIOContext *pb, MOVContext* mov,
1199
                             AVFormatContext *s)
1200
{
1201
    int size = 0;
1202
    if ( s->genre[0] ) {
1203
        offset_t pos = url_ftell(pb);
1204
        put_be32(pb, 0); /* size */
1205
        put_tag(pb, "\251gen");
1206
        mov_write_string_data_tag(pb, mov, s, s->genre);
1207
        size = updateSize(pb, pos);
1208
    }
1209
    return size;
1210
}
1211

    
1212
/* iTunes track number */
1213
static int mov_write_trkn_tag(ByteIOContext *pb, MOVContext* mov,
1214
                              AVFormatContext *s)
1215
{
1216
    int size = 0;
1217
    if ( s->track ) {
1218
        offset_t pos = url_ftell(pb);
1219
        put_be32(pb, 0); /* size */
1220
        put_tag(pb, "trkn");
1221
        {
1222
            offset_t pos = url_ftell(pb);
1223
            put_be32(pb, 0); /* size */
1224
            put_tag(pb, "data");
1225
            put_be32(pb, 0);        // 8 bytes empty
1226
            put_be32(pb, 0);
1227
            put_be16(pb, 0);        // empty
1228
            put_be16(pb, s->track); // track number
1229
            put_be16(pb, 0);        // total track number
1230
            put_be16(pb, 0);        // empty
1231
            updateSize(pb, pos);
1232
        }
1233
        size = updateSize(pb, pos);
1234
    }
1235
    return size;
1236
}
1237

    
1238
/* iTunes meta data list */
1239
static int mov_write_ilst_tag(ByteIOContext *pb, MOVContext* mov,
1240
                              AVFormatContext *s)
1241
{
1242
    offset_t pos = url_ftell(pb);
1243
    put_be32(pb, 0); /* size */
1244
    put_tag(pb, "ilst");
1245
    mov_write_nam_tag(pb, mov, s);
1246
    mov_write_ART_tag(pb, mov, s);
1247
    mov_write_wrt_tag(pb, mov, s);
1248
    mov_write_alb_tag(pb, mov, s);
1249
    mov_write_day_tag(pb, mov, s);
1250
    mov_write_too_tag(pb, mov, s);
1251
    mov_write_cmt_tag(pb, mov, s);
1252
    mov_write_gen_tag(pb, mov, s);
1253
    mov_write_trkn_tag(pb, mov, s);
1254
    return updateSize(pb, pos);
1255
}
1256

    
1257
/* iTunes meta data tag */
1258
static int mov_write_meta_tag(ByteIOContext *pb, MOVContext* mov,
1259
                              AVFormatContext *s)
1260
{
1261
    int size = 0;
1262

    
1263
    // only save meta tag if required
1264
    if ( s->title[0] || s->author[0] || s->album[0] || s->year ||
1265
         s->comment[0] || s->genre[0] || s->track ) {
1266
        offset_t pos = url_ftell(pb);
1267
        put_be32(pb, 0); /* size */
1268
        put_tag(pb, "meta");
1269
        put_be32(pb, 0);
1270
        mov_write_itunes_hdlr_tag(pb, mov, s);
1271
        mov_write_ilst_tag(pb, mov, s);
1272
        size = updateSize(pb, pos);
1273
    }
1274
    return size;
1275
}
1276

    
1277
static int mov_write_udta_tag(ByteIOContext *pb, MOVContext* mov,
1278
                              AVFormatContext *s)
1279
{
1280
    offset_t pos = url_ftell(pb);
1281
    int i;
1282

    
1283
    put_be32(pb, 0); /* size */
1284
    put_tag(pb, "udta");
1285

    
1286
    /* iTunes meta data */
1287
    mov_write_meta_tag(pb, mov, s);
1288

    
1289
    /* Requirements */
1290
    for (i=0; i<MAX_STREAMS; i++) {
1291
        if(mov->tracks[i].entry <= 0) continue;
1292
        if (mov->tracks[i].enc->codec_id == CODEC_ID_AAC ||
1293
            mov->tracks[i].enc->codec_id == CODEC_ID_MPEG4) {
1294
            offset_t pos = url_ftell(pb);
1295
            put_be32(pb, 0); /* size */
1296
            put_tag(pb, "\251req");
1297
            put_be16(pb, sizeof("QuickTime 6.0 or greater") - 1);
1298
            put_be16(pb, 0);
1299
            put_buffer(pb, "QuickTime 6.0 or greater",
1300
                       sizeof("QuickTime 6.0 or greater") - 1);
1301
            updateSize(pb, pos);
1302
            break;
1303
        }
1304
    }
1305

    
1306
    /* Encoder */
1307
    if(mov->tracks[0].enc && !(mov->tracks[0].enc->flags & CODEC_FLAG_BITEXACT))
1308
    {
1309
        offset_t pos = url_ftell(pb);
1310
        put_be32(pb, 0); /* size */
1311
        put_tag(pb, "\251enc");
1312
        put_be16(pb, sizeof(LIBAVFORMAT_IDENT) - 1); /* string length */
1313
        put_be16(pb, 0);
1314
        put_buffer(pb, LIBAVFORMAT_IDENT, sizeof(LIBAVFORMAT_IDENT) - 1);
1315
        updateSize(pb, pos);
1316
    }
1317

    
1318
    if( s->title[0] )
1319
    {
1320
        offset_t pos = url_ftell(pb);
1321
        put_be32(pb, 0); /* size */
1322
        put_tag(pb, "\251nam");
1323
        put_be16(pb, strlen(s->title)); /* string length */
1324
        put_be16(pb, 0);
1325
        put_buffer(pb, s->title, strlen(s->title));
1326
        updateSize(pb, pos);
1327
    }
1328

    
1329
    if( s->author[0] )
1330
    {
1331
        offset_t pos = url_ftell(pb);
1332
        put_be32(pb, 0); /* size */
1333
        put_tag(pb, /*"\251aut"*/ "\251day" );
1334
        put_be16(pb, strlen(s->author)); /* string length */
1335
        put_be16(pb, 0);
1336
        put_buffer(pb, s->author, strlen(s->author));
1337
        updateSize(pb, pos);
1338
    }
1339

    
1340
    if( s->comment[0] )
1341
    {
1342
        offset_t pos = url_ftell(pb);
1343
        put_be32(pb, 0); /* size */
1344
        put_tag(pb, "\251des");
1345
        put_be16(pb, strlen(s->comment)); /* string length */
1346
        put_be16(pb, 0);
1347
        put_buffer(pb, s->comment, strlen(s->comment));
1348
        updateSize(pb, pos);
1349
    }
1350

    
1351
    return updateSize(pb, pos);
1352
}
1353

    
1354

    
1355
static size_t ascii_to_wc (ByteIOContext *pb, char *b, size_t n)
1356
{
1357
    size_t i;
1358
    unsigned char c;
1359
    for (i = 0; i < n - 1; i++) {
1360
        c = b[i];
1361
        if (! (0x20 <= c && c <= 0x7f ))
1362
            c = 0x3f;  /* '?' */
1363
        put_be16(pb, c);
1364
    }
1365
    put_be16(pb, 0x00);
1366
    return 2*n;
1367
}
1368

    
1369
static uint16_t language_code (char *str)
1370
{
1371
    return ((((str[0]-'a') & 0x1F)<<10) + (((str[1]-'a') & 0x1F)<<5) + ((str[2]-'a') & 0x1F));
1372
}
1373

    
1374
static int mov_write_uuidusmt_tag (ByteIOContext *pb, AVFormatContext *s)
1375
{
1376
    size_t len, size;
1377
    offset_t pos, curpos;
1378

    
1379
    size = 0;
1380
    if (s->title[0]) {
1381
        pos = url_ftell(pb);
1382
        put_be32(pb, 0); /* size placeholder*/
1383
        put_tag(pb, "uuid");
1384
        put_tag(pb, "USMT");
1385
        put_be32(pb, 0x21d24fce ); /* 96 bit UUID */
1386
        put_be32(pb, 0xbb88695c );
1387
        put_be32(pb, 0xfac9c740 );
1388
        size += 24;
1389

    
1390
        put_be32(pb, 0); /* size placeholder*/
1391
        put_tag(pb, "MTDT");
1392
        put_be16(pb, 1);
1393
        size += 10;
1394

    
1395
        // Title
1396
        len = strlen(s->title)+1;
1397
        put_be16(pb, len*2+10);             /* size */
1398
        put_be32(pb, 0x01);                 /* type */
1399
        put_be16(pb, language_code("und")); /* language */
1400
        put_be16(pb, 0x01);                 /* ? */
1401
        ascii_to_wc (pb, s->title, len);
1402
        size += len*2+10;
1403

    
1404
        // size
1405
        curpos = url_ftell(pb);
1406
        url_fseek(pb, pos, SEEK_SET);
1407
        put_be32(pb, size);
1408
        url_fseek(pb, pos+24, SEEK_SET);
1409
        put_be32(pb, size-24);
1410
        url_fseek(pb, curpos, SEEK_SET);
1411
    }
1412

    
1413
    return size;
1414
}
1415

    
1416
static int mov_write_moov_tag(ByteIOContext *pb, MOVContext *mov,
1417
                              AVFormatContext *s)
1418
{
1419
    int i;
1420
    offset_t pos = url_ftell(pb);
1421
    put_be32(pb, 0); /* size placeholder*/
1422
    put_tag(pb, "moov");
1423
    mov->timescale = globalTimescale;
1424

    
1425
    for (i=0; i<MAX_STREAMS; i++) {
1426
        if(mov->tracks[i].entry <= 0) continue;
1427

    
1428
        if(mov->tracks[i].enc->codec_type == CODEC_TYPE_VIDEO) {
1429
            mov->tracks[i].timescale = mov->tracks[i].enc->time_base.den;
1430
            mov->tracks[i].sampleDuration = mov->tracks[i].enc->time_base.num;
1431
        }
1432
        else if(mov->tracks[i].enc->codec_type == CODEC_TYPE_AUDIO) {
1433
            /* If AMR, track timescale = 8000, AMR_WB = 16000 */
1434
            if(mov->tracks[i].enc->codec_id == CODEC_ID_AMR_NB) {
1435
                mov->tracks[i].sampleDuration = 160;  // Bytes per chunk
1436
                mov->tracks[i].timescale = 8000;
1437
            }
1438
            else {
1439
                mov->tracks[i].timescale = mov->tracks[i].enc->sample_rate;
1440
                mov->tracks[i].sampleDuration = mov->tracks[i].enc->frame_size;
1441
            }
1442
        }
1443

    
1444
        mov->tracks[i].trackDuration =
1445
            (int64_t)mov->tracks[i].sampleCount * mov->tracks[i].sampleDuration;
1446
        mov->tracks[i].time = mov->time;
1447
        mov->tracks[i].trackID = i+1;
1448
    }
1449

    
1450
    mov_write_mvhd_tag(pb, mov);
1451
    //mov_write_iods_tag(pb, mov);
1452
    for (i=0; i<MAX_STREAMS; i++) {
1453
        if(mov->tracks[i].entry > 0) {
1454
            mov_write_trak_tag(pb, &(mov->tracks[i]));
1455
        }
1456
    }
1457

    
1458
    if (mov->mode == MODE_PSP)
1459
        mov_write_uuidusmt_tag(pb, s);
1460
    else
1461
    mov_write_udta_tag(pb, mov, s);
1462

    
1463
    return updateSize(pb, pos);
1464
}
1465

    
1466
int mov_write_mdat_tag(ByteIOContext *pb, MOVContext* mov)
1467
{
1468
    put_be32(pb, 8);    // placeholder for extended size field (64 bit)
1469
    put_tag(pb, "wide");
1470

    
1471
    mov->mdat_pos = url_ftell(pb);
1472
    put_be32(pb, 0); /* size placeholder*/
1473
    put_tag(pb, "mdat");
1474
    return 0;
1475
}
1476

    
1477
/* TODO: This needs to be more general */
1478
static void mov_write_ftyp_tag (ByteIOContext *pb, AVFormatContext *s)
1479
{
1480
    MOVContext *mov = s->priv_data;
1481

    
1482
    put_be32(pb, 0x14 ); /* size */
1483
    put_tag(pb, "ftyp");
1484

    
1485
    if ( mov->mode == MODE_3GP )
1486
        put_tag(pb, "3gp4");
1487
    else if ( mov->mode == MODE_3G2 )
1488
        put_tag(pb, "3g2a");
1489
    else if ( mov->mode == MODE_PSP )
1490
        put_tag(pb, "MSNV");
1491
    else if ( mov->mode == MODE_MP4 )
1492
        put_tag(pb, "isom");
1493
    else
1494
        put_tag(pb, "qt  ");
1495

    
1496
    put_be32(pb, 0x200 );
1497

    
1498
    if ( mov->mode == MODE_3GP )
1499
        put_tag(pb, "3gp4");
1500
    else if ( mov->mode == MODE_3G2 )
1501
        put_tag(pb, "3g2a");
1502
    else if ( mov->mode == MODE_PSP )
1503
        put_tag(pb, "MSNV");
1504
    else if ( mov->mode == MODE_MP4 )
1505
        put_tag(pb, "mp41");
1506
    else
1507
        put_tag(pb, "qt  ");
1508
}
1509

    
1510
static void mov_write_uuidprof_tag(ByteIOContext *pb, AVFormatContext *s)
1511
{
1512
    AVCodecContext *VideoCodec = s->streams[0]->codec;
1513
    AVCodecContext *AudioCodec = s->streams[1]->codec;
1514
    int AudioRate = AudioCodec->sample_rate;
1515
    int FrameRate = ((VideoCodec->time_base.den) * (0x10000))/ (VideoCodec->time_base.num);
1516
    int audio_kbitrate= AudioCodec->bit_rate / 1000;
1517
    int video_kbitrate= FFMIN(VideoCodec->bit_rate / 1000, 800 - audio_kbitrate);
1518

    
1519
    put_be32(pb, 0x94 ); /* size */
1520
    put_tag(pb, "uuid");
1521
    put_tag(pb, "PROF");
1522

    
1523
    put_be32(pb, 0x21d24fce ); /* 96 bit UUID */
1524
    put_be32(pb, 0xbb88695c );
1525
    put_be32(pb, 0xfac9c740 );
1526

    
1527
    put_be32(pb, 0x0 );  /* ? */
1528
    put_be32(pb, 0x3 );  /* 3 sections ? */
1529

    
1530
    put_be32(pb, 0x14 ); /* size */
1531
    put_tag(pb, "FPRF");
1532
    put_be32(pb, 0x0 );  /* ? */
1533
    put_be32(pb, 0x0 );  /* ? */
1534
    put_be32(pb, 0x0 );  /* ? */
1535

    
1536
    put_be32(pb, 0x2c );  /* size */
1537
    put_tag(pb, "APRF");   /* audio */
1538
    put_be32(pb, 0x0 );
1539
    put_be32(pb, 0x2 );   /* TrackID */
1540
    put_tag(pb, "mp4a");
1541
    put_be32(pb, 0x20f );
1542
    put_be32(pb, 0x0 );
1543
    put_be32(pb, audio_kbitrate);
1544
    put_be32(pb, audio_kbitrate);
1545
    put_be32(pb, AudioRate );
1546
    put_be32(pb, AudioCodec->channels );
1547

    
1548
    put_be32(pb, 0x34 );  /* size */
1549
    put_tag(pb, "VPRF");   /* video */
1550
    put_be32(pb, 0x0 );
1551
    put_be32(pb, 0x1 );    /* TrackID */
1552
    if (VideoCodec->codec_id == CODEC_ID_H264) {
1553
        put_tag(pb, "avc1");
1554
        put_be16(pb, 0x014D );
1555
        put_be16(pb, 0x0015 );
1556
    } else {
1557
        put_tag(pb, "mp4v");
1558
        put_be16(pb, 0x0000 );
1559
        put_be16(pb, 0x0103 );
1560
    }
1561
    put_be32(pb, 0x0 );
1562
    put_be32(pb, video_kbitrate);
1563
    put_be32(pb, video_kbitrate);
1564
    put_be32(pb, FrameRate);
1565
    put_be32(pb, FrameRate);
1566
    put_be16(pb, VideoCodec->width);
1567
    put_be16(pb, VideoCodec->height);
1568
    put_be32(pb, 0x010001); /* ? */
1569
}
1570

    
1571
static int mov_write_header(AVFormatContext *s)
1572
{
1573
    ByteIOContext *pb = &s->pb;
1574
    MOVContext *mov = s->priv_data;
1575
    int i;
1576

    
1577
    /* Default mode == MP4 */
1578
    mov->mode = MODE_MP4;
1579

    
1580
    if (s->oformat != NULL) {
1581
        if (!strcmp("3gp", s->oformat->name)) mov->mode = MODE_3GP;
1582
        else if (!strcmp("3g2", s->oformat->name)) mov->mode = MODE_3G2;
1583
        else if (!strcmp("mov", s->oformat->name)) mov->mode = MODE_MOV;
1584
        else if (!strcmp("psp", s->oformat->name)) mov->mode = MODE_PSP;
1585

    
1586
        mov_write_ftyp_tag(pb,s);
1587
        if ( mov->mode == MODE_PSP ) {
1588
            if ( s->nb_streams != 2 ) {
1589
                av_log(s, AV_LOG_ERROR, "PSP mode need one video and one audio stream\n");
1590
                return -1;
1591
            }
1592
            mov_write_uuidprof_tag(pb,s);
1593
        }
1594
    }
1595

    
1596
    for(i=0; i<s->nb_streams; i++){
1597
        AVCodecContext *c= s->streams[i]->codec;
1598

    
1599
        if(c->codec_type == CODEC_TYPE_VIDEO){
1600
            av_set_pts_info(s->streams[i], 64, 1, c->time_base.den);
1601
            if (!codec_get_tag(codec_movvideo_tags, c->codec_id)){
1602
                if(!codec_get_tag(codec_bmp_tags, c->codec_id))
1603
                    return -1;
1604
                else
1605
                    av_log(s, AV_LOG_INFO, "Warning, using MS style video codec tag, the file may be unplayable!\n");
1606
            }
1607
        }else if(c->codec_type == CODEC_TYPE_AUDIO){
1608
            av_set_pts_info(s->streams[i], 64, 1, c->sample_rate);
1609
            if (!codec_get_tag(codec_movaudio_tags, c->codec_id)){
1610
                if(!codec_get_tag(codec_wav_tags, c->codec_id))
1611
                    return -1;
1612
                else
1613
                    av_log(s, AV_LOG_INFO, "Warning, using MS style audio codec tag, the file may be unplayable!\n");
1614
            }
1615
        }
1616
        mov->tracks[i].language = ff_mov_iso639_to_lang(s->streams[i]->language, mov->mode != MODE_MOV);
1617
    }
1618

    
1619
    for (i=0; i<MAX_STREAMS; i++) {
1620
        mov->tracks[i].mode = mov->mode;
1621
    }
1622

    
1623
    put_flush_packet(pb);
1624

    
1625
    return 0;
1626
}
1627

    
1628
static int mov_write_packet(AVFormatContext *s, AVPacket *pkt)
1629
{
1630
    MOVContext *mov = s->priv_data;
1631
    ByteIOContext *pb = &s->pb;
1632
    AVCodecContext *enc = s->streams[pkt->stream_index]->codec;
1633
    MOVTrack* trk = &mov->tracks[pkt->stream_index];
1634
    int cl, id;
1635
    unsigned int samplesInChunk = 0;
1636
    int size= pkt->size;
1637

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

    
1641
    if (enc->codec_type == CODEC_TYPE_VIDEO ) {
1642
        samplesInChunk = 1;
1643
    }
1644
    else if (enc->codec_type == CODEC_TYPE_AUDIO ) {
1645
        if( enc->codec_id == CODEC_ID_AMR_NB) {
1646
            /* We must find out how many AMR blocks there are in one packet */
1647
            static uint16_t packed_size[16] =
1648
                {13, 14, 16, 18, 20, 21, 27, 32, 6, 0, 0, 0, 0, 0, 0, 0};
1649
            int len = 0;
1650

    
1651
            while (len < size && samplesInChunk < 100) {
1652
                len += packed_size[(pkt->data[len] >> 3) & 0x0F];
1653
                samplesInChunk++;
1654
            }
1655
        }
1656
        else if(enc->codec_id == CODEC_ID_PCM_ALAW) {
1657
            samplesInChunk = size/enc->channels;
1658
        }
1659
        else if(enc->codec_id == CODEC_ID_PCM_S16BE || enc->codec_id == CODEC_ID_PCM_S16LE) {
1660
            samplesInChunk = size/(2*enc->channels);
1661
        }
1662
        else {
1663
            samplesInChunk = 1;
1664
        }
1665
    }
1666

    
1667
    if ((enc->codec_id == CODEC_ID_MPEG4 || enc->codec_id == CODEC_ID_AAC)
1668
        && trk->vosLen == 0) {
1669
//        assert(enc->extradata_size);
1670

    
1671
        trk->vosLen = enc->extradata_size;
1672
        trk->vosData = av_malloc(trk->vosLen);
1673
        memcpy(trk->vosData, enc->extradata, trk->vosLen);
1674
    }
1675

    
1676
    if (enc->codec_id == CODEC_ID_H264) {
1677
        if (trk->vosLen == 0) {
1678
            /* copy extradata */
1679
            trk->vosLen = enc->extradata_size;
1680
            trk->vosData = av_malloc(trk->vosLen);
1681
            memcpy(trk->vosData, enc->extradata, trk->vosLen);
1682
        }
1683
        if (*(uint8_t *)trk->vosData != 1) {
1684
            /* from x264 or from bytestream h264 */
1685
            /* nal reformating needed */
1686
            avc_parse_nal_units(&pkt->data, &pkt->size);
1687
            assert(pkt->size);
1688
            size = pkt->size;
1689
        }
1690
    }
1691

    
1692
    cl = trk->entry / MOV_INDEX_CLUSTER_SIZE;
1693
    id = trk->entry % MOV_INDEX_CLUSTER_SIZE;
1694

    
1695
    if (trk->ents_allocated <= trk->entry) {
1696
        trk->cluster = av_realloc(trk->cluster, (cl+1)*sizeof(void*));
1697
        if (!trk->cluster)
1698
            return -1;
1699
        trk->cluster[cl] = av_malloc(MOV_INDEX_CLUSTER_SIZE*sizeof(MOVIentry));
1700
        if (!trk->cluster[cl])
1701
            return -1;
1702
        trk->ents_allocated += MOV_INDEX_CLUSTER_SIZE;
1703
    }
1704
    if (mov->mdat_written == 0) {
1705
        mov_write_mdat_tag(pb, mov);
1706
        mov->mdat_written = 1;
1707
        mov->time = s->timestamp + 0x7C25B080; //1970 based -> 1904 based
1708
    }
1709

    
1710
    trk->cluster[cl][id].pos = url_ftell(pb);
1711
    trk->cluster[cl][id].samplesInChunk = samplesInChunk;
1712
    trk->cluster[cl][id].size = size;
1713
    trk->cluster[cl][id].entries = samplesInChunk;
1714
    if(enc->codec_type == CODEC_TYPE_VIDEO) {
1715
        if (pkt->dts != pkt->pts)
1716
            trk->hasBframes = 1;
1717
        trk->cluster[cl][id].cts = pkt->pts - pkt->dts;
1718
        trk->cluster[cl][id].key_frame = !!(pkt->flags & PKT_FLAG_KEY);
1719
        if(trk->cluster[cl][id].key_frame)
1720
            trk->hasKeyframes = 1;
1721
    }
1722
    trk->enc = enc;
1723
    trk->entry++;
1724
    trk->sampleCount += samplesInChunk;
1725
    trk->mdat_size += size;
1726

    
1727
    put_buffer(pb, pkt->data, size);
1728

    
1729
    put_flush_packet(pb);
1730
    return 0;
1731
}
1732

    
1733
static int mov_write_trailer(AVFormatContext *s)
1734
{
1735
    MOVContext *mov = s->priv_data;
1736
    ByteIOContext *pb = &s->pb;
1737
    int res = 0;
1738
    int i;
1739
    uint64_t j;
1740

    
1741
    offset_t moov_pos = url_ftell(pb);
1742

    
1743
    /* Write size of mdat tag */
1744
    for (i=0, j=0; i<MAX_STREAMS; i++) {
1745
        if(mov->tracks[i].ents_allocated > 0) {
1746
            j += mov->tracks[i].mdat_size;
1747
        }
1748
    }
1749
    if (j+8 <= UINT32_MAX) {
1750
        url_fseek(pb, mov->mdat_pos, SEEK_SET);
1751
        put_be32(pb, j+8);
1752
    } else {
1753
        /* overwrite 'wide' placeholder atom */
1754
        url_fseek(pb, mov->mdat_pos - 8, SEEK_SET);
1755
        put_be32(pb, 1); /* special value: real atom size will be 64 bit value after tag field */
1756
        put_tag(pb, "mdat");
1757
        put_be64(pb, j+16);
1758
    }
1759
    url_fseek(pb, moov_pos, SEEK_SET);
1760

    
1761
    mov_write_moov_tag(pb, mov, s);
1762

    
1763
    for (i=0; i<MAX_STREAMS; i++) {
1764
        for (j=0; j<mov->tracks[i].ents_allocated/MOV_INDEX_CLUSTER_SIZE; j++) {
1765
            av_free(mov->tracks[i].cluster[j]);
1766
        }
1767
        av_free(mov->tracks[i].cluster);
1768
        if( mov->tracks[i].vosLen ) av_free( mov->tracks[i].vosData );
1769

    
1770
        mov->tracks[i].cluster = NULL;
1771
        mov->tracks[i].ents_allocated = mov->tracks[i].entry = 0;
1772
    }
1773

    
1774
    put_flush_packet(pb);
1775

    
1776
    return res;
1777
}
1778

    
1779
static AVOutputFormat mov_oformat = {
1780
    "mov",
1781
    "mov format",
1782
    NULL,
1783
    "mov",
1784
    sizeof(MOVContext),
1785
    CODEC_ID_AAC,
1786
    CODEC_ID_MPEG4,
1787
    mov_write_header,
1788
    mov_write_packet,
1789
    mov_write_trailer,
1790
    .flags = AVFMT_GLOBALHEADER,
1791
};
1792

    
1793
static AVOutputFormat _3gp_oformat = {
1794
    "3gp",
1795
    "3gp format",
1796
    NULL,
1797
    "3gp",
1798
    sizeof(MOVContext),
1799
    CODEC_ID_AMR_NB,
1800
    CODEC_ID_H263,
1801
    mov_write_header,
1802
    mov_write_packet,
1803
    mov_write_trailer,
1804
    .flags = AVFMT_GLOBALHEADER,
1805
};
1806

    
1807
static AVOutputFormat mp4_oformat = {
1808
    "mp4",
1809
    "mp4 format",
1810
    "application/mp4",
1811
    "mp4,m4a",
1812
    sizeof(MOVContext),
1813
    CODEC_ID_AAC,
1814
    CODEC_ID_MPEG4,
1815
    mov_write_header,
1816
    mov_write_packet,
1817
    mov_write_trailer,
1818
    .flags = AVFMT_GLOBALHEADER,
1819
};
1820

    
1821
static AVOutputFormat psp_oformat = {
1822
    "psp",
1823
    "psp mp4 format",
1824
    NULL,
1825
    "mp4,psp",
1826
    sizeof(MOVContext),
1827
    CODEC_ID_AAC,
1828
    CODEC_ID_MPEG4,
1829
    mov_write_header,
1830
    mov_write_packet,
1831
    mov_write_trailer,
1832
    .flags = AVFMT_GLOBALHEADER,
1833
};
1834

    
1835
static AVOutputFormat _3g2_oformat = {
1836
    "3g2",
1837
    "3gp2 format",
1838
    NULL,
1839
    "3g2",
1840
    sizeof(MOVContext),
1841
    CODEC_ID_AMR_NB,
1842
    CODEC_ID_H263,
1843
    mov_write_header,
1844
    mov_write_packet,
1845
    mov_write_trailer,
1846
    .flags = AVFMT_GLOBALHEADER,
1847
};
1848

    
1849
int movenc_init(void)
1850
{
1851
    av_register_output_format(&mov_oformat);
1852
    av_register_output_format(&_3gp_oformat);
1853
    av_register_output_format(&mp4_oformat);
1854
    av_register_output_format(&psp_oformat);
1855
    av_register_output_format(&_3g2_oformat);
1856
    return 0;
1857
}