Statistics
| Branch: | Revision:

ffmpeg / libavformat / movenc.c @ 7be806f3

History | View | Annotate | Download (44.7 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
#define MODE_PSP 3 // example working PSP command line: 
34
// ffmpeg -i testinput.avi  -f psp -r 14.985 -s 320x240 -b 768 -ar 24000 -ab 32 M4V00001.MP4
35

    
36
typedef struct MOVIentry {
37
    unsigned int flags, pos, size;
38
    unsigned int samplesInChunk;
39
    char         key_frame;
40
    unsigned int entries;
41
} MOVIentry;
42

    
43
typedef struct MOVIndex {
44
    int         mode;
45
    int         entry;
46
    int         mdat_size;
47
    int         ents_allocated;
48
    long        timescale;
49
    long        time;
50
    long        trackDuration;
51
    long        sampleCount;
52
    long        sampleDuration;
53
    int         hasKeyframes;
54
    int         trackID;
55
    AVCodecContext *enc;
56

    
57
    int         vosLen;
58
    uint8_t     *vosData;
59
    MOVIentry** cluster;
60
} MOVTrack;
61

    
62
typedef struct MOVContext {
63
    int     mode;
64
    long    time;
65
    int     nb_streams;
66
    int     mdat_written;
67
    offset_t mdat_pos;
68
    long    timescale;
69
    MOVTrack tracks[MAX_STREAMS];
70
} MOVContext;
71

    
72
static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack* track);
73

    
74
//FIXME supprt 64bit varaint with wide placeholders
75
static int updateSize (ByteIOContext *pb, int pos)
76
{
77
    long curpos = url_ftell(pb);
78
    url_fseek(pb, pos, SEEK_SET);
79
    put_be32(pb, curpos - pos); /* rewrite size */
80
    url_fseek(pb, curpos, SEEK_SET);
81

    
82
    return curpos - pos;
83
}
84

    
85
/* Chunk offset atom */
86
static int mov_write_stco_tag(ByteIOContext *pb, MOVTrack* track)
87
{
88
    int i;
89
    int pos = url_ftell(pb);
90
    put_be32(pb, 0); /* size */
91
    put_tag(pb, "stco");
92
    put_be32(pb, 0); /* version & flags */
93
    put_be32(pb, track->entry); /* entry count */
94
    for (i=0; i<track->entry; i++) {
95
        int cl = i / MOV_INDEX_CLUSTER_SIZE;
96
        int id = i % MOV_INDEX_CLUSTER_SIZE;
97
        put_be32(pb, track->cluster[cl][id].pos);
98
    }
99
    return updateSize (pb, pos);
100
}
101

    
102
/* Sample size atom */
103
static int mov_write_stsz_tag(ByteIOContext *pb, MOVTrack* track)
104
{
105
    int equalChunks = 1;
106
    int i, j, entries = 0, tst = -1, oldtst = -1;
107

    
108
    int pos = url_ftell(pb);
109
    put_be32(pb, 0); /* size */
110
    put_tag(pb, "stsz");
111
    put_be32(pb, 0); /* version & flags */
112

    
113
    for (i=0; i<track->entry; i++) {
114
        int cl = i / MOV_INDEX_CLUSTER_SIZE;
115
        int id = i % MOV_INDEX_CLUSTER_SIZE;
116
        tst = track->cluster[cl][id].size/track->cluster[cl][id].entries;
117
        if(oldtst != -1 && tst != oldtst) {
118
            equalChunks = 0;
119
        }
120
        oldtst = tst;
121
        entries += track->cluster[cl][id].entries;
122
    }
123
    if (equalChunks) {
124
        int sSize = track->cluster[0][0].size/track->cluster[0][0].entries;
125
        put_be32(pb, sSize); // sample size 
126
        put_be32(pb, entries); // sample count
127
    }
128
    else {
129
        put_be32(pb, 0); // sample size 
130
        put_be32(pb, entries); // sample count 
131
        for (i=0; i<track->entry; i++) {
132
            int cl = i / MOV_INDEX_CLUSTER_SIZE;
133
            int id = i % MOV_INDEX_CLUSTER_SIZE;
134
            for ( j=0; j<track->cluster[cl][id].entries; j++) {
135
                put_be32(pb, track->cluster[cl][id].size /
136
                         track->cluster[cl][id].entries);
137
            }
138
        }
139
    }
140
    return updateSize (pb, pos);
141
}
142

    
143
/* Sample to chunk atom */
144
static int mov_write_stsc_tag(ByteIOContext *pb, MOVTrack* track)
145
{
146
    int index = 0, oldval = -1, i, entryPos, curpos;
147

    
148
    int pos = url_ftell(pb);
149
    put_be32(pb, 0); /* size */
150
    put_tag(pb, "stsc");
151
    put_be32(pb, 0); // version & flags 
152
    entryPos = url_ftell(pb);
153
    put_be32(pb, track->entry); // entry count 
154
    for (i=0; i<track->entry; i++) {
155
        int cl = i / MOV_INDEX_CLUSTER_SIZE;
156
        int id = i % MOV_INDEX_CLUSTER_SIZE;
157
        if(oldval != track->cluster[cl][id].samplesInChunk)
158
        {
159
            put_be32(pb, i+1); // first chunk 
160
            put_be32(pb, track->cluster[cl][id].samplesInChunk); // samples per chunk
161
            put_be32(pb, 0x1); // sample description index 
162
            oldval = track->cluster[cl][id].samplesInChunk;
163
            index++;
164
        }
165
    }
166
    curpos = url_ftell(pb);
167
    url_fseek(pb, entryPos, SEEK_SET);
168
    put_be32(pb, index); // rewrite size 
169
    url_fseek(pb, curpos, SEEK_SET);
170

    
171
    return updateSize (pb, pos);
172
}
173

    
174
/* Sync sample atom */
175
static int mov_write_stss_tag(ByteIOContext *pb, MOVTrack* track)
176
{
177
    long curpos;
178
    int i, index = 0, entryPos;
179
    int pos = url_ftell(pb);
180
    put_be32(pb, 0); // size 
181
    put_tag(pb, "stss");
182
    put_be32(pb, 0); // version & flags 
183
    entryPos = url_ftell(pb);
184
    put_be32(pb, track->entry); // entry count 
185
    for (i=0; i<track->entry; i++) {
186
        int cl = i / MOV_INDEX_CLUSTER_SIZE;
187
        int id = i % MOV_INDEX_CLUSTER_SIZE;
188
        if(track->cluster[cl][id].key_frame == 1) {
189
            put_be32(pb, i+1);
190
            index++;
191
        }
192
    }
193
    curpos = url_ftell(pb);
194
    url_fseek(pb, entryPos, SEEK_SET);
195
    put_be32(pb, index); // rewrite size 
196
    url_fseek(pb, curpos, SEEK_SET);
197
    return updateSize (pb, pos);
198
}
199

    
200
static int mov_write_damr_tag(ByteIOContext *pb)
201
{
202
    put_be32(pb, 0x11); /* size */
203
    put_tag(pb, "damr");
204
    put_tag(pb, "FFMP");
205
    put_byte(pb, 0);
206

    
207
    put_be16(pb, 0x80); /* Mode set (all modes for AMR_NB) */
208
    put_be16(pb, 0xa); /* Mode change period (no restriction) */
209
    //put_be16(pb, 0x81ff); /* Mode set (all modes for AMR_NB) */
210
    //put_be16(pb, 1); /* Mode change period (no restriction) */
211
    return 0x11;
212
}
213

    
214
static int mov_write_wave_tag(ByteIOContext *pb, MOVTrack* track)
215
{
216
    int pos = url_ftell(pb);
217

    
218
    put_be32(pb, 0);     /* size */
219
    put_tag(pb, "wave");
220

    
221
    put_be32(pb, 12);    /* size */
222
    put_tag(pb, "frma");
223
    put_tag(pb, "mp4a");
224

    
225
    put_be32(pb, 12);    /* size */
226
    put_tag(pb, "mp4a");
227
    put_be32(pb, 0);
228

    
229
    mov_write_esds_tag(pb, track);
230

    
231
    put_be32(pb, 12);    /* size */
232
    put_tag(pb, "srcq");
233
    put_be32(pb, 0x40);
234

    
235
    put_be32(pb, 8);     /* size */
236
    put_be32(pb, 0);     /* null tag */
237

    
238
    return updateSize (pb, pos);
239
}
240

    
241
const CodecTag codec_movaudio_tags[] = {
242
    { CODEC_ID_PCM_MULAW, MKTAG('u', 'l', 'a', 'w') },
243
    { CODEC_ID_PCM_ALAW, MKTAG('a', 'l', 'a', 'w') },
244
    { CODEC_ID_ADPCM_IMA_QT, MKTAG('i', 'm', 'a', '4') },
245
    { CODEC_ID_MACE3, MKTAG('M', 'A', 'C', '3') },
246
    { CODEC_ID_MACE6, MKTAG('M', 'A', 'C', '6') },
247
    { CODEC_ID_AAC, MKTAG('m', 'p', '4', 'a') },
248
    { CODEC_ID_AMR_NB, MKTAG('s', 'a', 'm', 'r') },
249
    { CODEC_ID_PCM_S16BE, MKTAG('t', 'w', 'o', 's') },
250
    { CODEC_ID_PCM_S16LE, MKTAG('s', 'o', 'w', 't') },
251
    { CODEC_ID_MP3, MKTAG('.', 'm', 'p', '3') },
252
    { 0, 0 },
253
};
254

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

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

    
273
    put_be32(pb, 0); /* Reserved */
274
    put_be16(pb, 0); /* Reserved */
275
    put_be16(pb, 1); /* Data-reference index, XXX  == 1 */
276

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

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

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

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

    
312
    if(track->enc->codec_id == CODEC_ID_AAC) {
313
        if( track->mode == MODE_MOV ) mov_write_wave_tag(pb, track);
314
        else mov_write_esds_tag(pb, track);
315
    }
316
    if(track->enc->codec_id == CODEC_ID_AMR_NB)
317
        mov_write_damr_tag(pb);
318
    return updateSize (pb, pos);
319
}
320

    
321
static int mov_write_d263_tag(ByteIOContext *pb)
322
{
323
    put_be32(pb, 0xf); /* size */
324
    put_tag(pb, "d263");
325
    put_tag(pb, "FFMP");
326
    put_be16(pb, 0x0a);
327
    put_byte(pb, 0);
328
    return 0xf;
329
}
330

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

    
344
static unsigned int descrLength(unsigned int len)
345
{
346
    if (len < 0x00000080)
347
        return 2 + len;
348
    else if (len < 0x00004000)
349
        return 3 + len;
350
    else if(len < 0x00200000)
351
        return 4 + len;
352
    else
353
        return 5 + len;
354
}
355

    
356
static void putDescr(ByteIOContext *pb, int tag, int size)
357
{
358
    uint32_t len;
359
    uint8_t  vals[4];
360

    
361
    len = size;
362
    vals[3] = (uint8_t)(len & 0x7f);
363
    len >>= 7;
364
    vals[2] = (uint8_t)((len & 0x7f) | 0x80); 
365
    len >>= 7;
366
    vals[1] = (uint8_t)((len & 0x7f) | 0x80); 
367
    len >>= 7;
368
    vals[0] = (uint8_t)((len & 0x7f) | 0x80);
369

    
370
    put_byte(pb, tag); // DescriptorTag
371

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

    
396
static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack* track) // Basic
397
{
398
    int decoderSpecificInfoLen;
399
    int pos = url_ftell(pb);
400
    void *vosDataBackup=track->vosData;
401
    int vosLenBackup=track->vosLen;
402
    
403
    // we should be able to have these passed in, via vosData, then we wouldn't need to attack this routine at all
404
    static const char PSPAACData[]={0x13,0x10};
405
    static const char PSPMP4Data[]={0x00,0x00,0x01,0xB0,0x03,0x00,0x00,0x01,0xB5,0x09,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x20,0x00,0x84,0x5D,0x4C,0x28,0x50,0x20,0xF0,0xA3,0x1F };
406
    
407
    
408
    if (track->mode == MODE_PSP)  // fails on psp if this is not here
409
    {
410
        if (track->enc->codec_id == CODEC_ID_AAC)
411
        {
412
            track->vosLen = 2;
413
            track->vosData = PSPAACData;
414
        }
415

    
416
        if (track->enc->codec_id == CODEC_ID_MPEG4)
417
        {
418
            track->vosLen = 28;
419
            track->vosData = PSPMP4Data;
420
        }
421
    }
422

    
423
    decoderSpecificInfoLen = track->vosLen ? descrLength(track->vosLen):0;
424

    
425
    put_be32(pb, 0);               // size
426
    put_tag(pb, "esds");
427
    put_be32(pb, 0);               // Version
428

    
429
    // ES descriptor
430
    putDescr(pb, 0x03, 3 + descrLength(13 + decoderSpecificInfoLen) +
431
             descrLength(1));
432
    put_be16(pb, 0x0001);          // ID (= 1)
433
    put_byte(pb, 0x00);            // flags (= no flags)
434

    
435
    // DecoderConfig descriptor
436
    putDescr(pb, 0x04, 13 + decoderSpecificInfoLen);
437

    
438
    if(track->enc->codec_id == CODEC_ID_AAC)
439
        put_byte(pb, 0x40);        // Object type indication
440
    else if(track->enc->codec_id == CODEC_ID_MPEG4)
441
        put_byte(pb, 0x20);        // Object type indication (Visual 14496-2)
442

    
443
    if(track->enc->codec_type == CODEC_TYPE_AUDIO)
444
        put_byte(pb, 0x15);            // flags (= Audiostream)
445
    else
446
        put_byte(pb, 0x11);            // flags (= Visualstream)
447

    
448
    put_byte(pb, 0x0);             // Buffersize DB (24 bits)
449
    put_be16(pb, 0x0dd2);          // Buffersize DB
450

    
451
    // TODO: find real values for these
452
    put_be32(pb, track->enc->bit_rate);     // maxbitrate
453
    put_be32(pb, track->enc->bit_rate);     // avg bitrate
454

    
455
    if (track->vosLen)
456
    {
457
        // DecoderSpecific info descriptor
458
        putDescr(pb, 0x05, track->vosLen);
459
        put_buffer(pb, track->vosData, track->vosLen);
460
    }
461

    
462
    track->vosData = vosDataBackup;
463
    track->vosLen = vosLenBackup;
464

    
465
    // SL descriptor
466
    putDescr(pb, 0x06, 1);
467
    put_byte(pb, 0x02);
468
    return updateSize (pb, pos);
469
}
470

    
471
const CodecTag codec_movvideo_tags[] = {
472
    { CODEC_ID_SVQ1, MKTAG('S', 'V', 'Q', '1') },
473
    { CODEC_ID_SVQ3, MKTAG('S', 'V', 'Q', '3') },
474
    { CODEC_ID_MPEG4, MKTAG('m', 'p', '4', 'v') },
475
    { CODEC_ID_H263, MKTAG('s', '2', '6', '3') },
476
    { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'c', ' ') },
477
    { 0, 0 },
478
};
479

    
480
static int mov_write_video_tag(ByteIOContext *pb, MOVTrack* track)
481
{
482
    int pos = url_ftell(pb);
483
    char compressor_name[32];
484
    int tag;
485

    
486
    put_be32(pb, 0); /* size */
487

    
488
    tag = track->enc->codec_tag;
489
    if (!tag)
490
    tag = codec_get_tag(codec_movvideo_tags, track->enc->codec_id);
491
    // if no mac fcc found, try with Microsoft tags
492
    if (!tag)
493
        tag = codec_get_tag(codec_bmp_tags, track->enc->codec_id);
494
    put_le32(pb, tag); // store it byteswapped
495

    
496
    put_be32(pb, 0); /* Reserved */
497
    put_be16(pb, 0); /* Reserved */
498
    put_be16(pb, 1); /* Data-reference index */
499

    
500
    put_be16(pb, 0); /* Codec stream version */
501
    put_be16(pb, 0); /* Codec stream revision (=0) */
502
    put_tag(pb, "FFMP"); /* Vendor */
503
    if(track->enc->codec_id == CODEC_ID_RAWVIDEO) {
504
        put_be32(pb, 0); /* Temporal Quality */
505
        put_be32(pb, 0x400); /* Spatial Quality = lossless*/
506
    } else {
507
        put_be32(pb, 0x200); /* Temporal Quality = normal */
508
        put_be32(pb, 0x200); /* Spatial Quality = normal */
509
    }
510
    put_be16(pb, track->enc->width); /* Video width */
511
    put_be16(pb, track->enc->height); /* Video height */
512
    put_be32(pb, 0x00480000); /* Horizontal resolution 72dpi */
513
    put_be32(pb, 0x00480000); /* Vertical resolution 72dpi */
514
    put_be32(pb, 0); /* Data size (= 0) */
515
    put_be16(pb, 1); /* Frame count (= 1) */
516
    
517
    memset(compressor_name,0,32);
518
    if (track->enc->codec && track->enc->codec->name)
519
        strncpy(compressor_name,track->enc->codec->name,31);
520
    put_byte(pb, strlen(compressor_name));
521
    put_buffer(pb, compressor_name, 31);
522
    
523
    put_be16(pb, 0x18); /* Reserved */
524
    put_be16(pb, 0xffff); /* Reserved */
525
    if(track->enc->codec_id == CODEC_ID_MPEG4)
526
        mov_write_esds_tag(pb, track);
527
    else if(track->enc->codec_id == CODEC_ID_H263)
528
        mov_write_d263_tag(pb);
529
    else if(track->enc->codec_id == CODEC_ID_SVQ3)
530
        mov_write_svq3_tag(pb);    
531

    
532
    return updateSize (pb, pos);
533
}
534

    
535
static int mov_write_stsd_tag(ByteIOContext *pb, MOVTrack* track)
536
{
537
    int pos = url_ftell(pb);
538
    put_be32(pb, 0); /* size */
539
    put_tag(pb, "stsd");
540
    put_be32(pb, 0); /* version & flags */
541
    put_be32(pb, 1); /* entry count */
542
    if (track->enc->codec_type == CODEC_TYPE_VIDEO)
543
        mov_write_video_tag(pb, track);
544
    else if (track->enc->codec_type == CODEC_TYPE_AUDIO)
545
        mov_write_audio_tag(pb, track);
546
    return updateSize(pb, pos);
547
}
548

    
549
/* TODO?: Currently all samples/frames seem to have same duration */
550
/* Time to sample atom */
551
static int mov_write_stts_tag(ByteIOContext *pb, MOVTrack* track)
552
{
553
    put_be32(pb, 0x18); /* size */
554
    put_tag(pb, "stts");
555
    put_be32(pb, 0); /* version & flags */
556
    put_be32(pb, 1); /* entry count */
557

    
558
    put_be32(pb, track->sampleCount); /* sample count */
559
    put_be32(pb, track->sampleDuration); /* sample duration */
560
    return 0x18;
561
}
562

    
563
static int mov_write_dref_tag(ByteIOContext *pb)
564
{
565
    put_be32(pb, 28); /* size */
566
    put_tag(pb, "dref");
567
    put_be32(pb, 0); /* version & flags */
568
    put_be32(pb, 1); /* entry count */
569

    
570
    put_be32(pb, 0xc); /* size */
571
    put_tag(pb, "url ");
572
    put_be32(pb, 1); /* version & flags */
573

    
574
    return 28;
575
}
576

    
577
static int mov_write_stbl_tag(ByteIOContext *pb, MOVTrack* track)
578
{
579
    int pos = url_ftell(pb);
580
    put_be32(pb, 0); /* size */
581
    put_tag(pb, "stbl");
582
    mov_write_stsd_tag(pb, track);
583
    mov_write_stts_tag(pb, track);
584
    if (track->enc->codec_type == CODEC_TYPE_VIDEO &&
585
        track->hasKeyframes)
586
        mov_write_stss_tag(pb, track);
587
    mov_write_stsc_tag(pb, track);
588
    mov_write_stsz_tag(pb, track);
589
    mov_write_stco_tag(pb, track);
590
    return updateSize(pb, pos);
591
}
592

    
593
static int mov_write_dinf_tag(ByteIOContext *pb)
594
{
595
    int pos = url_ftell(pb);
596
    put_be32(pb, 0); /* size */
597
    put_tag(pb, "dinf");
598
    mov_write_dref_tag(pb);
599
    return updateSize(pb, pos);
600
}
601

    
602
static int mov_write_smhd_tag(ByteIOContext *pb)
603
{
604
    put_be32(pb, 16); /* size */
605
    put_tag(pb, "smhd");
606
    put_be32(pb, 0); /* version & flags */
607
    put_be16(pb, 0); /* reserved (balance, normally = 0) */
608
    put_be16(pb, 0); /* reserved */
609
    return 16;
610
}
611

    
612
static int mov_write_vmhd_tag(ByteIOContext *pb)
613
{
614
    put_be32(pb, 0x14); /* size (always 0x14) */
615
    put_tag(pb, "vmhd");
616
    put_be32(pb, 0x01); /* version & flags */
617
    put_be64(pb, 0); /* reserved (graphics mode = copy) */
618
    return 0x14;
619
}
620

    
621
static int mov_write_hdlr_tag(ByteIOContext *pb, MOVTrack* track)
622
{
623
    char *descr, *hdlr, *hdlr_type;
624
    int pos = url_ftell(pb);
625
    
626
    if (!track) { /* no media --> data handler */
627
        hdlr = "dhlr";
628
        hdlr_type = "url ";
629
        descr = "DataHandler";
630
    } else {
631
        hdlr = (track->mode == MODE_MOV) ? "mhlr" : "\0\0\0\0";
632
        if (track->enc->codec_type == CODEC_TYPE_VIDEO) {
633
            hdlr_type = "vide";
634
            descr = "VideoHandler";
635
        } else {
636
            hdlr_type = "soun";
637
            descr = "SoundHandler";
638
        }
639
    }
640
    
641
    put_be32(pb, 0); /* size */
642
    put_tag(pb, "hdlr");
643
    put_be32(pb, 0); /* Version & flags */
644
    put_buffer(pb, hdlr, 4); /* handler */
645
    put_tag(pb, hdlr_type); /* handler type */
646
    put_be32(pb ,0); /* reserved */
647
    put_be32(pb ,0); /* reserved */
648
    put_be32(pb ,0); /* reserved */
649
    put_byte(pb, strlen(descr)); /* string counter */
650
    put_buffer(pb, descr, strlen(descr)); /* handler description */
651
    return updateSize(pb, pos);
652
}
653

    
654
static int mov_write_minf_tag(ByteIOContext *pb, MOVTrack* track)
655
{
656
    int pos = url_ftell(pb);
657
    put_be32(pb, 0); /* size */
658
    put_tag(pb, "minf");
659
    if(track->enc->codec_type == CODEC_TYPE_VIDEO)
660
        mov_write_vmhd_tag(pb);
661
    else
662
        mov_write_smhd_tag(pb);
663
    if (track->mode == MODE_MOV) /* FIXME: Why do it for MODE_MOV only ? */
664
        mov_write_hdlr_tag(pb, NULL);
665
    mov_write_dinf_tag(pb);
666
    mov_write_stbl_tag(pb, track);
667
    return updateSize(pb, pos);
668
}
669

    
670
static int mov_write_mdhd_tag(ByteIOContext *pb, MOVTrack* track)
671
{
672
    put_be32(pb, 32); /* size */
673
    put_tag(pb, "mdhd");
674
    put_be32(pb, 0); /* Version & flags */
675
    put_be32(pb, track->time); /* creation time */
676
    put_be32(pb, track->time); /* modification time */
677
    put_be32(pb, track->timescale); /* time scale (sample rate for audio) */ 
678
    put_be32(pb, track->trackDuration); /* duration */
679
    put_be16(pb, 0); /* language, 0 = english */
680
    put_be16(pb, 0); /* reserved (quality) */
681
    return 32;
682
}
683

    
684
static int mov_write_mdia_tag(ByteIOContext *pb, MOVTrack* track)
685
{
686
    int pos = url_ftell(pb);
687
    put_be32(pb, 0); /* size */
688
    put_tag(pb, "mdia");
689
    mov_write_mdhd_tag(pb, track);
690
    mov_write_hdlr_tag(pb, track);
691
    mov_write_minf_tag(pb, track);
692
    return updateSize(pb, pos);
693
}
694

    
695
static int mov_write_tkhd_tag(ByteIOContext *pb, MOVTrack* track)
696
{
697
    int64_t maxTrackLenTemp;
698
    put_be32(pb, 0x5c); /* size (always 0x5c) */
699
    put_tag(pb, "tkhd");
700
    put_be32(pb, 0xf); /* version & flags (track enabled) */
701
    put_be32(pb, track->time); /* creation time */
702
    put_be32(pb, track->time); /* modification time */
703
    put_be32(pb, track->trackID); /* track-id */
704
    put_be32(pb, 0); /* reserved */
705
    maxTrackLenTemp = ((int64_t)globalTimescale*(int64_t)track->trackDuration)/(int64_t)track->timescale;
706
    put_be32(pb, (long)maxTrackLenTemp); /* duration */
707

    
708
    put_be32(pb, 0); /* reserved */
709
    put_be32(pb, 0); /* reserved */
710
    put_be32(pb, 0x0); /* reserved (Layer & Alternate group) */
711
    /* Volume, only for audio */
712
    if(track->enc->codec_type == CODEC_TYPE_AUDIO)
713
        put_be16(pb, 0x0100);
714
    else
715
        put_be16(pb, 0);
716
    put_be16(pb, 0); /* reserved */
717

    
718
    /* Matrix structure */
719
    put_be32(pb, 0x00010000); /* reserved */
720
    put_be32(pb, 0x0); /* reserved */
721
    put_be32(pb, 0x0); /* reserved */
722
    put_be32(pb, 0x0); /* reserved */
723
    put_be32(pb, 0x00010000); /* reserved */
724
    put_be32(pb, 0x0); /* reserved */
725
    put_be32(pb, 0x0); /* reserved */
726
    put_be32(pb, 0x0); /* reserved */
727
    put_be32(pb, 0x40000000); /* reserved */
728

    
729
    /* Track width and height, for visual only */
730
    if(track->enc->codec_type == CODEC_TYPE_VIDEO) {
731
        double sample_aspect_ratio = av_q2d(track->enc->sample_aspect_ratio);
732
        if( !sample_aspect_ratio ) sample_aspect_ratio = 1;
733
        put_be32(pb, sample_aspect_ratio * track->enc->width*0x10000);
734
        put_be32(pb, track->enc->height*0x10000);
735
    }
736
    else {
737
        put_be32(pb, 0);
738
        put_be32(pb, 0);
739
    }
740
    return 0x5c;
741
}
742

    
743
// This box seems important for the psp playback ... without it the movie seems to hang
744
static int mov_write_edts_tag(ByteIOContext *pb, MOVTrack *track)
745
{
746
    int64_t maxTrackLenTemp;
747
    put_be32(pb, 0x24); /* size  */
748
    put_tag(pb, "edts");
749
    put_be32(pb, 0x1c); /* size  */
750
    put_tag(pb, "elst");
751
    put_be32(pb, 0x0);
752
    put_be32(pb, 0x1);
753

    
754
    maxTrackLenTemp = ((int64_t)globalTimescale*(int64_t)track->trackDuration)/(int64_t)track->timescale;
755
    put_be32(pb, (long)maxTrackLenTemp); /* duration   ... doesn't seem to effect psp */
756

    
757
    put_be32(pb, 0x0);
758
    put_be32(pb, 0x00010000);
759
    return 0x24;
760
}
761

    
762
// goes at the end of each track!  ... Critical for PSP playback ("Incompatible data" without it)
763
static int mov_write_uuid_tag_psp(ByteIOContext *pb, MOVTrack *mov)
764
{
765
    put_be32(pb, 0x34); /* size ... reports as 28 in mp4box! */
766
    put_tag(pb, "uuid");
767
    put_tag(pb, "USMT");
768
    put_be32(pb, 0x21d24fce);
769
    put_be32(pb, 0xbb88695c);
770
    put_be32(pb, 0xfac9c740);
771
    put_be32(pb, 0x1c);     // another size here!
772
    put_tag(pb, "MTDT");
773
    put_be32(pb, 0x00010012);
774
    put_be32(pb, 0x0a);
775
    put_be32(pb, 0x55c40000);
776
    put_be32(pb, 0x1);
777
    put_be32(pb, 0x0);
778
    return 0x34;
779
}
780

    
781
static int mov_write_trak_tag(ByteIOContext *pb, MOVTrack* track)
782
{
783
    int pos = url_ftell(pb);
784
    put_be32(pb, 0); /* size */
785
    put_tag(pb, "trak");
786
    mov_write_tkhd_tag(pb, track);
787
    if (track->mode == MODE_PSP) 
788
        mov_write_edts_tag(pb, track);  // PSP Movies require edts box
789
    mov_write_mdia_tag(pb, track);
790
    if (track->mode == MODE_PSP) 
791
        mov_write_uuid_tag_psp(pb,track);  // PSP Movies require this uuid box
792
    return updateSize(pb, pos);
793
}
794

    
795
/* TODO: Not sorted out, but not necessary either */
796
static int mov_write_iods_tag(ByteIOContext *pb, MOVContext *mov)
797
{
798
    put_be32(pb, 0x15); /* size */
799
    put_tag(pb, "iods");
800
    put_be32(pb, 0);    /* version & flags */
801
    put_be16(pb, 0x1007);
802
    put_byte(pb, 0);
803
    put_be16(pb, 0x4fff);
804
    put_be16(pb, 0xfffe);
805
    put_be16(pb, 0x01ff);
806
    return 0x15;
807
}
808

    
809
static int mov_write_mvhd_tag(ByteIOContext *pb, MOVContext *mov)
810
{
811
    int maxTrackID = 1, maxTrackLen = 0, i;
812
    int64_t maxTrackLenTemp;
813

    
814
    put_be32(pb, 0x6c); /* size (always 0x6c) */
815
    put_tag(pb, "mvhd");
816
    put_be32(pb, 0); /* version & flags */
817
    put_be32(pb, mov->time); /* creation time */
818
    put_be32(pb, mov->time); /* modification time */
819
    put_be32(pb, mov->timescale); /* timescale */
820
    for (i=0; i<MAX_STREAMS; i++) {
821
        if(mov->tracks[i].entry > 0) {
822
            maxTrackLenTemp = ((int64_t)globalTimescale*(int64_t)mov->tracks[i].trackDuration)/(int64_t)mov->tracks[i].timescale;
823
            if(maxTrackLen < maxTrackLenTemp)
824
                maxTrackLen = maxTrackLenTemp;
825
            if(maxTrackID < mov->tracks[i].trackID)
826
                maxTrackID = mov->tracks[i].trackID;
827
        }
828
    }
829
    put_be32(pb, maxTrackLen); /* duration of longest track */
830

    
831
    put_be32(pb, 0x00010000); /* reserved (preferred rate) 1.0 = normal */
832
    put_be16(pb, 0x0100); /* reserved (preferred volume) 1.0 = normal */
833
    put_be16(pb, 0); /* reserved */
834
    put_be32(pb, 0); /* reserved */
835
    put_be32(pb, 0); /* reserved */
836

    
837
    /* Matrix structure */
838
    put_be32(pb, 0x00010000); /* reserved */
839
    put_be32(pb, 0x0); /* reserved */
840
    put_be32(pb, 0x0); /* reserved */
841
    put_be32(pb, 0x0); /* reserved */
842
    put_be32(pb, 0x00010000); /* reserved */
843
    put_be32(pb, 0x0); /* reserved */
844
    put_be32(pb, 0x0); /* reserved */
845
    put_be32(pb, 0x0); /* reserved */
846
    put_be32(pb, 0x40000000); /* reserved */
847

    
848
    put_be32(pb, 0); /* reserved (preview time) */
849
    put_be32(pb, 0); /* reserved (preview duration) */
850
    put_be32(pb, 0); /* reserved (poster time) */
851
    put_be32(pb, 0); /* reserved (selection time) */
852
    put_be32(pb, 0); /* reserved (selection duration) */
853
    put_be32(pb, 0); /* reserved (current time) */
854
    put_be32(pb, maxTrackID+1); /* Next track id */
855
    return 0x6c;
856
}
857

    
858
static int mov_write_itunes_hdlr_tag(ByteIOContext *pb, MOVContext* mov,
859
                                     AVFormatContext *s)
860
{
861
    int pos = url_ftell(pb);
862
    put_be32(pb, 0); /* size */
863
    put_tag(pb, "hdlr");
864
    put_be32(pb, 0);
865
    put_be32(pb, 0);
866
    put_tag(pb, "mdir");
867
    put_tag(pb, "appl");
868
    put_be32(pb, 0);
869
    put_be32(pb, 0);
870
    put_be16(pb, 0);
871
    return updateSize(pb, pos);
872
}
873

    
874
/* helper function to write a data tag with the specified string as data */
875
static int mov_write_string_data_tag(ByteIOContext *pb, MOVContext* mov,
876
                                     AVFormatContext *s, const char *data)
877
{
878
    int pos = url_ftell(pb);
879
    put_be32(pb, 0); /* size */
880
    put_tag(pb, "data");
881
    put_be32(pb, 1);
882
    put_be32(pb, 0);
883
    put_buffer(pb, data, strlen(data));
884
    return updateSize(pb, pos);
885
}
886

    
887
/* iTunes name of the song/movie */
888
static int mov_write_nam_tag(ByteIOContext *pb, MOVContext* mov,
889
                             AVFormatContext *s)
890
{
891
    int size = 0;
892
    if ( s->title[0] ) {
893
        int pos = url_ftell(pb);
894
        put_be32(pb, 0); /* size */
895
        put_tag(pb, "\251nam");
896
        mov_write_string_data_tag(pb, mov, s, s->title);
897
        size = updateSize(pb, pos);
898
    }
899
    return size;
900
}
901

    
902
/* iTunes name of the artist/performer */
903
static int mov_write_ART_tag(ByteIOContext *pb, MOVContext* mov,
904
                             AVFormatContext *s)
905
{
906
    int size = 0;
907
    if ( s->author[0] ) {
908
        int pos = url_ftell(pb);
909
        put_be32(pb, 0); /* size */
910
        put_tag(pb, "\251ART");
911
        // we use the author here as this is the only thing that we have...
912
        mov_write_string_data_tag(pb, mov, s, s->author);
913
        size = updateSize(pb, pos);
914
    }
915
    return size;
916
}
917

    
918
/* iTunes name of the writer */
919
static int mov_write_wrt_tag(ByteIOContext *pb, MOVContext* mov,
920
                             AVFormatContext *s)
921
{
922
    int size = 0;
923
    if ( s->author[0] ) {
924
        int pos = url_ftell(pb);
925
        put_be32(pb, 0); /* size */
926
        put_tag(pb, "\251wrt");
927
        mov_write_string_data_tag(pb, mov, s, s->author);
928
        size = updateSize(pb, pos);
929
    }
930
    return size;
931
}
932

    
933
/* iTunes name of the album */
934
static int mov_write_alb_tag(ByteIOContext *pb, MOVContext* mov,
935
                             AVFormatContext *s)
936
{
937
    int size = 0;
938
    if ( s->album[0] ) {
939
        int pos = url_ftell(pb);
940
        put_be32(pb, 0); /* size */
941
        put_tag(pb, "\251alb");
942
        mov_write_string_data_tag(pb, mov, s, s->album);
943
        size = updateSize(pb, pos);
944
    }
945
    return size;
946
}
947

    
948
/* iTunes year */
949
static int mov_write_day_tag(ByteIOContext *pb, MOVContext* mov,
950
                             AVFormatContext *s)
951
{
952
    char year[5];
953
    int size = 0;
954
    if ( s->year ) {
955
        int pos = url_ftell(pb);
956
        put_be32(pb, 0); /* size */
957
        put_tag(pb, "\251day");
958
        snprintf(year, 5, "%04d", s->year);
959
        mov_write_string_data_tag(pb, mov, s, year);
960
        size = updateSize(pb, pos);
961
    }
962
    return size;
963
}
964

    
965
/* iTunes tool used to create the file */
966
static int mov_write_too_tag(ByteIOContext *pb, MOVContext* mov,
967
                             AVFormatContext *s)
968
{
969
    int pos = url_ftell(pb);
970
    put_be32(pb, 0); /* size */
971
    put_tag(pb, "\251too");
972
    mov_write_string_data_tag(pb, mov, s, LIBAVFORMAT_IDENT);
973
    return updateSize(pb, pos);
974
}
975

    
976
/* iTunes comment */
977
static int mov_write_cmt_tag(ByteIOContext *pb, MOVContext* mov,
978
                             AVFormatContext *s)
979
{
980
    int size = 0;
981
    if ( s->comment[0] ) {
982
        int pos = url_ftell(pb);
983
        put_be32(pb, 0); /* size */
984
        put_tag(pb, "\251cmt");
985
        mov_write_string_data_tag(pb, mov, s, s->comment);
986
        size = updateSize(pb, pos);
987
    }
988
    return size;
989
}
990

    
991
/* iTunes custom genre */
992
static int mov_write_gen_tag(ByteIOContext *pb, MOVContext* mov,
993
                             AVFormatContext *s)
994
{
995
    int size = 0;
996
    if ( s->genre[0] ) {
997
        int pos = url_ftell(pb);
998
        put_be32(pb, 0); /* size */
999
        put_tag(pb, "\251gen");
1000
        mov_write_string_data_tag(pb, mov, s, s->genre);
1001
        size = updateSize(pb, pos);
1002
    }
1003
    return size;
1004
}
1005

    
1006
/* iTunes track number */
1007
static int mov_write_trkn_tag(ByteIOContext *pb, MOVContext* mov,
1008
                              AVFormatContext *s)
1009
{
1010
    int size = 0;
1011
    if ( s->track ) {
1012
        int pos = url_ftell(pb);
1013
        put_be32(pb, 0); /* size */
1014
        put_tag(pb, "trkn");
1015
        {
1016
            int pos = url_ftell(pb);
1017
            put_be32(pb, 0); /* size */
1018
            put_tag(pb, "data");
1019
            put_be32(pb, 0);        // 8 bytes empty
1020
            put_be32(pb, 0);
1021
            put_be16(pb, 0);        // empty
1022
            put_be16(pb, s->track); // track number
1023
            put_be16(pb, 0);        // total track number
1024
            put_be16(pb, 0);        // empty
1025
            updateSize(pb, pos);
1026
        }
1027
        size = updateSize(pb, pos);
1028
    }
1029
    return size;
1030
}
1031

    
1032
/* iTunes meta data list */
1033
static int mov_write_ilst_tag(ByteIOContext *pb, MOVContext* mov,
1034
                              AVFormatContext *s)
1035
{
1036
    int pos = url_ftell(pb);
1037
    put_be32(pb, 0); /* size */
1038
    put_tag(pb, "ilst");
1039
    mov_write_nam_tag(pb, mov, s);
1040
    mov_write_ART_tag(pb, mov, s);
1041
    mov_write_wrt_tag(pb, mov, s);
1042
    mov_write_alb_tag(pb, mov, s);
1043
    mov_write_day_tag(pb, mov, s);
1044
    mov_write_too_tag(pb, mov, s);
1045
    mov_write_cmt_tag(pb, mov, s);
1046
    mov_write_gen_tag(pb, mov, s);
1047
    mov_write_trkn_tag(pb, mov, s);
1048
    return updateSize(pb, pos);
1049
}
1050

    
1051
/* iTunes meta data tag */
1052
static int mov_write_meta_tag(ByteIOContext *pb, MOVContext* mov,
1053
                              AVFormatContext *s)
1054
{
1055
    int size = 0;
1056

    
1057
    // only save meta tag if required
1058
    if ( s->title[0] || s->author[0] || s->album[0] || s->year || 
1059
         s->comment[0] || s->genre[0] || s->track ) {
1060
        int pos = url_ftell(pb);
1061
        put_be32(pb, 0); /* size */
1062
        put_tag(pb, "meta");
1063
        put_be32(pb, 0);
1064
        mov_write_itunes_hdlr_tag(pb, mov, s);
1065
        mov_write_ilst_tag(pb, mov, s);
1066
        size = updateSize(pb, pos);
1067
    }
1068
    return size;
1069
}
1070
    
1071
static int mov_write_udta_tag(ByteIOContext *pb, MOVContext* mov,
1072
                              AVFormatContext *s)
1073
{
1074
    int pos = url_ftell(pb);
1075
    int i;
1076

    
1077
    put_be32(pb, 0); /* size */
1078
    put_tag(pb, "udta");
1079

    
1080
    /* iTunes meta data */
1081
    mov_write_meta_tag(pb, mov, s);
1082

    
1083
    /* Requirements */
1084
    for (i=0; i<MAX_STREAMS; i++) {
1085
        if(mov->tracks[i].entry <= 0) continue;
1086
        if (mov->tracks[i].enc->codec_id == CODEC_ID_AAC ||
1087
            mov->tracks[i].enc->codec_id == CODEC_ID_MPEG4) {
1088
            int pos = url_ftell(pb);
1089
            put_be32(pb, 0); /* size */
1090
            put_tag(pb, "\251req");
1091
            put_be16(pb, sizeof("QuickTime 6.0 or greater") - 1);
1092
            put_be16(pb, 0);
1093
            put_buffer(pb, "QuickTime 6.0 or greater",
1094
                       sizeof("QuickTime 6.0 or greater") - 1);
1095
            updateSize(pb, pos);
1096
            break;
1097
        }
1098
    }
1099

    
1100
    /* Encoder */
1101
    if(mov->tracks[0].enc && !(mov->tracks[0].enc->flags & CODEC_FLAG_BITEXACT))
1102
    {
1103
        int pos = url_ftell(pb);
1104
        put_be32(pb, 0); /* size */
1105
        put_tag(pb, "\251enc");
1106
        put_be16(pb, sizeof(LIBAVFORMAT_IDENT) - 1); /* string length */
1107
        put_be16(pb, 0);
1108
        put_buffer(pb, LIBAVFORMAT_IDENT, sizeof(LIBAVFORMAT_IDENT) - 1);
1109
        updateSize(pb, pos);
1110
    }
1111

    
1112
    if( s->title[0] )
1113
    {
1114
        int pos = url_ftell(pb);
1115
        put_be32(pb, 0); /* size */
1116
        put_tag(pb, "\251nam");
1117
        put_be16(pb, strlen(s->title)); /* string length */
1118
        put_be16(pb, 0);
1119
        put_buffer(pb, s->title, strlen(s->title));
1120
        updateSize(pb, pos);
1121
    }
1122

    
1123
    if( s->author[0] )
1124
    {
1125
        int pos = url_ftell(pb);
1126
        put_be32(pb, 0); /* size */
1127
        put_tag(pb, /*"\251aut"*/ "\251day" );
1128
        put_be16(pb, strlen(s->author)); /* string length */
1129
        put_be16(pb, 0);
1130
        put_buffer(pb, s->author, strlen(s->author));
1131
        updateSize(pb, pos);
1132
    }
1133

    
1134
    if( s->comment[0] )
1135
    {
1136
        int pos = url_ftell(pb);
1137
        put_be32(pb, 0); /* size */
1138
        put_tag(pb, "\251des");
1139
        put_be16(pb, strlen(s->comment)); /* string length */
1140
        put_be16(pb, 0);
1141
        put_buffer(pb, s->comment, strlen(s->comment));
1142
        updateSize(pb, pos);
1143
    }
1144

    
1145
    return updateSize(pb, pos);
1146
}
1147

    
1148
static int mov_write_moov_tag(ByteIOContext *pb, MOVContext *mov,
1149
                              AVFormatContext *s)
1150
{
1151
    int pos, i;
1152
    pos = url_ftell(pb);
1153
    put_be32(pb, 0); /* size placeholder*/
1154
    put_tag(pb, "moov");
1155
    mov->timescale = globalTimescale;
1156

    
1157
    for (i=0; i<MAX_STREAMS; i++) {
1158
        if(mov->tracks[i].entry <= 0) continue;
1159

    
1160
        if(mov->tracks[i].enc->codec_type == CODEC_TYPE_VIDEO) {
1161
            mov->tracks[i].timescale = mov->tracks[i].enc->frame_rate;
1162
            mov->tracks[i].sampleDuration = mov->tracks[i].enc->frame_rate_base;
1163
        }
1164
        else if(mov->tracks[i].enc->codec_type == CODEC_TYPE_AUDIO) {
1165
            /* If AMR, track timescale = 8000, AMR_WB = 16000 */
1166
            if(mov->tracks[i].enc->codec_id == CODEC_ID_AMR_NB) {
1167
                mov->tracks[i].sampleDuration = 160;  // Bytes per chunk
1168
                mov->tracks[i].timescale = 8000;
1169
            }
1170
            else {
1171
                mov->tracks[i].timescale = mov->tracks[i].enc->sample_rate;
1172
                mov->tracks[i].sampleDuration = mov->tracks[i].enc->frame_size;
1173
            }
1174
        }
1175

    
1176
        mov->tracks[i].trackDuration = 
1177
            mov->tracks[i].sampleCount * mov->tracks[i].sampleDuration;
1178
        mov->tracks[i].time = mov->time;
1179
        mov->tracks[i].trackID = i+1;
1180
    }
1181

    
1182
    mov_write_mvhd_tag(pb, mov);
1183
    //mov_write_iods_tag(pb, mov);
1184
    for (i=0; i<MAX_STREAMS; i++) {
1185
        if(mov->tracks[i].entry > 0) {
1186
            mov_write_trak_tag(pb, &(mov->tracks[i]));
1187
        }
1188
    }
1189

    
1190
    mov_write_udta_tag(pb, mov, s);
1191

    
1192
    return updateSize(pb, pos);
1193
}
1194

    
1195
int mov_write_mdat_tag(ByteIOContext *pb, MOVContext* mov)
1196
{
1197
    mov->mdat_pos = url_ftell(pb); 
1198
    put_be32(pb, 0); /* size placeholder*/
1199
    put_tag(pb, "mdat");
1200
    return 0;
1201
}
1202

    
1203
/* TODO: This needs to be more general */
1204
int mov_write_ftyp_tag(ByteIOContext *pb, AVFormatContext *s)
1205
{
1206
    MOVContext *mov = s->priv_data;
1207

    
1208
    put_be32(pb, 0x14 ); /* size */
1209
    put_tag(pb, "ftyp");
1210

    
1211
    if ( mov->mode == MODE_3GP )
1212
        put_tag(pb, "3gp4");
1213
    else if ( mov->mode == MODE_PSP )
1214
        put_tag(pb, "MSNV");
1215
    else
1216
        put_tag(pb, "isom");
1217

    
1218
    put_be32(pb, 0x200 );
1219

    
1220
    if ( mov->mode == MODE_3GP )
1221
        put_tag(pb, "3gp4");
1222
    else if ( mov->mode == MODE_PSP )
1223
        put_tag(pb, "MSNV");
1224
    else
1225
        put_tag(pb, "mp41");
1226

    
1227
    return 0x14;
1228
}
1229

    
1230
static void mov_write_uuidprof_tag(ByteIOContext *pb, AVFormatContext *s)
1231
{
1232
    int AudioRate = s->streams[1]->codec.sample_rate;
1233
    int FrameRate = ((s->streams[0]->codec.frame_rate) * (0x10000))/ (s->streams[0]->codec.frame_rate_base);
1234
 
1235
    //printf("audiorate = %d\n",AudioRate);
1236
    //printf("framerate = %d / %d = 0x%x\n",s->streams[0]->codec.frame_rate,s->streams[0]->codec.frame_rate_base,FrameRate);
1237

    
1238
    put_be32(pb, 0x94 ); /* size */
1239
    put_tag(pb, "uuid");
1240
    put_tag(pb, "PROF");
1241

    
1242
    put_be32(pb, 0x21d24fce ); /* 96 bit UUID */
1243
    put_be32(pb, 0xbb88695c );
1244
    put_be32(pb, 0xfac9c740 );
1245

    
1246
    put_be32(pb, 0x0 );  /* ? */
1247
    put_be32(pb, 0x3 );  /* 3 sections ? */
1248

    
1249
    put_be32(pb, 0x14 ); /* size */
1250
    put_tag(pb, "FPRF");
1251
    put_be32(pb, 0x0 );  /* ? */
1252
    put_be32(pb, 0x0 );  /* ? */
1253
    put_be32(pb, 0x0 );  /* ? */
1254

    
1255
    put_be32(pb, 0x2c );  /* size */
1256
    put_tag(pb, "APRF");   /* audio */
1257
    put_be32(pb, 0x0 );
1258
    put_be32(pb, 0x2 );
1259
    put_tag(pb, "mp4a");
1260
    put_be32(pb, 0x20f );
1261
    put_be32(pb, 0x0 );
1262
    put_be32(pb, 0x40 );
1263
    put_be32(pb, 0x40 );
1264
    put_be32(pb, AudioRate ); //24000   ... audio rate?
1265
    put_be32(pb, 0x2 );
1266

    
1267
    put_be32(pb, 0x34 );  /* size */
1268
    put_tag(pb, "VPRF");   /* video */
1269
    put_be32(pb, 0x0 );
1270
    put_be32(pb, 0x1 );
1271
    put_tag(pb, "mp4v");
1272
    put_be32(pb, 0x103 );
1273
    put_be32(pb, 0x0 );
1274
    put_be32(pb, 0xc0 );
1275
    put_be32(pb, 0xc0 );
1276
    put_be32(pb, FrameRate);  // was 0xefc29   
1277
    put_be32(pb, FrameRate );  // was 0xefc29
1278
    put_be16(pb, s->streams[0]->codec.width);
1279
    put_be16(pb, s->streams[0]->codec.height);
1280
    put_be32(pb, 0x010001 );
1281
}
1282

    
1283
static int mov_write_header(AVFormatContext *s)
1284
{
1285
    ByteIOContext *pb = &s->pb;
1286
    MOVContext *mov = s->priv_data;
1287
    int i;
1288

    
1289
    for(i=0; i<s->nb_streams; i++){
1290
        AVCodecContext *c= &s->streams[i]->codec;
1291

    
1292
        if      (c->codec_type == CODEC_TYPE_VIDEO){
1293
            if (!codec_get_tag(codec_movvideo_tags, c->codec_id)){
1294
                if(!codec_get_tag(codec_bmp_tags, c->codec_id))
1295
                    return -1;
1296
                else
1297
                    av_log(s, AV_LOG_INFO, "Warning, using MS style video codec tag, the file may be unplayable!\n");
1298
            }
1299
        }else if(c->codec_type == CODEC_TYPE_AUDIO){
1300
            if (!codec_get_tag(codec_movaudio_tags, c->codec_id)){
1301
                if(!codec_get_tag(codec_wav_tags, c->codec_id))
1302
                    return -1;
1303
                else
1304
                    av_log(s, AV_LOG_INFO, "Warning, using MS style audio codec tag, the file may be unplayable!\n");
1305
            }
1306
        }
1307
    }
1308

    
1309
    /* Default mode == MP4 */
1310
    mov->mode = MODE_MP4;
1311

    
1312
    if (s->oformat != NULL) {
1313
        if (!strcmp("3gp", s->oformat->name)) mov->mode = MODE_3GP;
1314
        else if (!strcmp("mov", s->oformat->name)) mov->mode = MODE_MOV;
1315
        else if (!strcmp("psp", s->oformat->name)) mov->mode = MODE_PSP;
1316

    
1317
        if ( mov->mode == MODE_3GP || mov->mode == MODE_MP4 || mov->mode == MODE_PSP )
1318
            mov_write_ftyp_tag(pb,s);
1319
        if ( mov->mode == MODE_PSP ) {
1320
            if ( s->nb_streams != 2 ) {
1321
                av_log(s, AV_LOG_ERROR, "PSP mode need one video and one audio stream\n");
1322
                return -1;
1323
            }
1324
            mov_write_uuidprof_tag(pb,s);
1325
        }
1326
    }
1327

    
1328
    for (i=0; i<MAX_STREAMS; i++) {
1329
        mov->tracks[i].mode = mov->mode;
1330
    }
1331

    
1332
    put_flush_packet(pb);
1333

    
1334
    return 0;
1335
}
1336

    
1337
static int mov_write_packet(AVFormatContext *s, AVPacket *pkt)
1338
{
1339
    MOVContext *mov = s->priv_data;
1340
    ByteIOContext *pb = &s->pb;
1341
    AVCodecContext *enc = &s->streams[pkt->stream_index]->codec;
1342
    MOVTrack* trk = &mov->tracks[pkt->stream_index];
1343
    int cl, id;
1344
    unsigned int samplesInChunk = 0;
1345
    int size= pkt->size;
1346

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

    
1350
    if (enc->codec_type == CODEC_TYPE_VIDEO ) {
1351
        samplesInChunk = 1;
1352
    }
1353
    else if (enc->codec_type == CODEC_TYPE_AUDIO ) {
1354
        if( enc->codec_id == CODEC_ID_AMR_NB) {
1355
            /* We must find out how many AMR blocks there are in one packet */
1356
            static uint16_t packed_size[16] =
1357
                {13, 14, 16, 18, 20, 21, 27, 32, 6, 0, 0, 0, 0, 0, 0, 0};
1358
            int len = 0;
1359

    
1360
            while (len < size && samplesInChunk < 100) {
1361
                len += packed_size[(pkt->data[len] >> 3) & 0x0F];
1362
                samplesInChunk++;
1363
            }
1364
        }
1365
        else if(enc->codec_id == CODEC_ID_PCM_ALAW) {
1366
            samplesInChunk = size/enc->channels;
1367
        }
1368
        else if(enc->codec_id == CODEC_ID_PCM_S16BE || enc->codec_id == CODEC_ID_PCM_S16LE) {
1369
            samplesInChunk = size/(2*enc->channels);
1370
        }            
1371
        else {
1372
            samplesInChunk = 1;
1373
        }
1374
    }
1375

    
1376
    if ((enc->codec_id == CODEC_ID_MPEG4 || enc->codec_id == CODEC_ID_AAC)
1377
        && trk->vosLen == 0) {
1378
//        assert(enc->extradata_size);
1379

    
1380
        trk->vosLen = enc->extradata_size;
1381
        trk->vosData = av_malloc(trk->vosLen);
1382
        memcpy(trk->vosData, enc->extradata, trk->vosLen);
1383
    }
1384

    
1385
    cl = trk->entry / MOV_INDEX_CLUSTER_SIZE;
1386
    id = trk->entry % MOV_INDEX_CLUSTER_SIZE;
1387

    
1388
    if (trk->ents_allocated <= trk->entry) {
1389
        trk->cluster = av_realloc(trk->cluster, (cl+1)*sizeof(void*)); 
1390
        if (!trk->cluster)
1391
            return -1;
1392
        trk->cluster[cl] = av_malloc(MOV_INDEX_CLUSTER_SIZE*sizeof(MOVIentry));
1393
        if (!trk->cluster[cl])
1394
            return -1;
1395
        trk->ents_allocated += MOV_INDEX_CLUSTER_SIZE;
1396
    }
1397
    if (mov->mdat_written == 0) {
1398
        mov_write_mdat_tag(pb, mov);
1399
        mov->mdat_written = 1;
1400
        mov->time = s->timestamp;
1401
    }
1402

    
1403
    trk->cluster[cl][id].pos = url_ftell(pb);
1404
    trk->cluster[cl][id].samplesInChunk = samplesInChunk;
1405
    trk->cluster[cl][id].size = size;
1406
    trk->cluster[cl][id].entries = samplesInChunk;
1407
    if(enc->codec_type == CODEC_TYPE_VIDEO) {
1408
        trk->cluster[cl][id].key_frame = !!(pkt->flags & PKT_FLAG_KEY);
1409
        if(trk->cluster[cl][id].key_frame)
1410
            trk->hasKeyframes = 1;
1411
    }
1412
    trk->enc = enc;
1413
    trk->entry++;
1414
    trk->sampleCount += samplesInChunk;
1415
    trk->mdat_size += size;
1416

    
1417
    put_buffer(pb, pkt->data, size);
1418

    
1419
    put_flush_packet(pb);
1420
    return 0;
1421
}
1422

    
1423
static int mov_write_trailer(AVFormatContext *s)
1424
{
1425
    MOVContext *mov = s->priv_data;
1426
    ByteIOContext *pb = &s->pb;
1427
    int res = 0;
1428
    int i, j;
1429

    
1430
    offset_t moov_pos = url_ftell(pb);
1431

    
1432
    /* Write size of mdat tag */
1433
    for (i=0, j=0; i<MAX_STREAMS; i++) {
1434
        if(mov->tracks[i].ents_allocated > 0) {
1435
            j += mov->tracks[i].mdat_size;
1436
        }
1437
    }
1438
    url_fseek(pb, mov->mdat_pos, SEEK_SET);
1439
    put_be32(pb, j+8);
1440
    url_fseek(pb, moov_pos, SEEK_SET);
1441

    
1442
    mov_write_moov_tag(pb, mov, s);
1443

    
1444
    for (i=0; i<MAX_STREAMS; i++) {
1445
        for (j=0; j<mov->tracks[i].ents_allocated/MOV_INDEX_CLUSTER_SIZE; j++) {
1446
            av_free(mov->tracks[i].cluster[j]);
1447
        }
1448
        av_free(mov->tracks[i].cluster);
1449
        if( mov->tracks[i].vosLen ) av_free( mov->tracks[i].vosData );
1450

    
1451
        mov->tracks[i].cluster = NULL;
1452
        mov->tracks[i].ents_allocated = mov->tracks[i].entry = 0;
1453
    }
1454

    
1455
    put_flush_packet(pb);
1456

    
1457
    return res;
1458
}
1459

    
1460
static AVOutputFormat mov_oformat = {
1461
    "mov",
1462
    "mov format",
1463
    NULL,
1464
    "mov",
1465
    sizeof(MOVContext),
1466
    CODEC_ID_AAC,
1467
    CODEC_ID_MPEG4,
1468
    mov_write_header,
1469
    mov_write_packet,
1470
    mov_write_trailer,
1471
};
1472

    
1473
static AVOutputFormat _3gp_oformat = {
1474
    "3gp",
1475
    "3gp format",
1476
    NULL,
1477
    "3gp",
1478
    sizeof(MOVContext),
1479
    CODEC_ID_AMR_NB,
1480
    CODEC_ID_H263,
1481
    mov_write_header,
1482
    mov_write_packet,
1483
    mov_write_trailer,
1484
};
1485

    
1486
static AVOutputFormat mp4_oformat = {
1487
    "mp4",
1488
    "mp4 format",
1489
    "application/mp4",
1490
    "mp4,m4a",
1491
    sizeof(MOVContext),
1492
    CODEC_ID_AAC,
1493
    CODEC_ID_MPEG4,
1494
    mov_write_header,
1495
    mov_write_packet,
1496
    mov_write_trailer,
1497
};
1498

    
1499
static AVOutputFormat psp_oformat = {
1500
    "psp",
1501
    "psp mp4 format",
1502
    NULL,
1503
    "mp4,psp",
1504
    sizeof(MOVContext),
1505
    CODEC_ID_AAC,
1506
    CODEC_ID_MPEG4,
1507
    mov_write_header,
1508
    mov_write_packet,
1509
    mov_write_trailer,
1510
};
1511

    
1512
int movenc_init(void)
1513
{
1514
    av_register_output_format(&mov_oformat);
1515
    av_register_output_format(&_3gp_oformat);
1516
    av_register_output_format(&mp4_oformat);
1517
    av_register_output_format(&psp_oformat);
1518
    return 0;
1519
}