Statistics
| Branch: | Revision:

ffmpeg / libavformat / movenc.c @ e60b4ced

History | View | Annotate | Download (47.6 KB)

1
/*
2
 * MOV, 3GP, MP4 encoder.
3
 * Copyright (c) 2003 Thomas Raivio.
4
 * Copyright (c) 2004 Gildas Bazin <gbazin at videolan dot org>.
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 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
} MOVIentry;
45

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

    
61
    int         vosLen;
62
    uint8_t     *vosData;
63
    MOVIentry** cluster;
64
} MOVTrack;
65

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

    
76
static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack* track);
77

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

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

    
89
    return curpos - pos;
90
}
91

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

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

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

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

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

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

    
187
    return updateSize (pb, pos);
188
}
189

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

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

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

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

    
234
    put_be32(pb, 0);     /* size */
235
    put_tag(pb, "wave");
236

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

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

    
245
    mov_write_esds_tag(pb, track);
246

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

    
251
    put_be32(pb, 8);     /* size */
252
    put_be32(pb, 0);     /* null tag */
253

    
254
    return updateSize (pb, pos);
255
}
256

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

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

    
277
    put_be32(pb, 0); /* size */
278

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

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

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

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

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

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

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

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

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

    
361
static unsigned int descrLength(unsigned int len)
362
{
363
    if (len < 0x00000080)
364
        return 2 + len;
365
    else if (len < 0x00004000)
366
        return 3 + len;
367
    else if(len < 0x00200000)
368
        return 4 + len;
369
    else
370
        return 5 + len;
371
}
372

    
373
static void putDescr(ByteIOContext *pb, int tag, int size)
374
{
375
    uint32_t len;
376
    uint8_t  vals[4];
377

    
378
    len = size;
379
    vals[3] = (uint8_t)(len & 0x7f);
380
    len >>= 7;
381
    vals[2] = (uint8_t)((len & 0x7f) | 0x80);
382
    len >>= 7;
383
    vals[1] = (uint8_t)((len & 0x7f) | 0x80);
384
    len >>= 7;
385
    vals[0] = (uint8_t)((len & 0x7f) | 0x80);
386

    
387
    put_byte(pb, tag); // DescriptorTag
388

    
389
    if (size < 0x00000080)
390
    {
391
        put_byte(pb, vals[3]);
392
    }
393
    else if (size < 0x00004000)
394
    {
395
        put_byte(pb, vals[2]);
396
        put_byte(pb, vals[3]);
397
    }
398
    else if (size < 0x00200000)
399
    {
400
        put_byte(pb, vals[1]);
401
        put_byte(pb, vals[2]);
402
        put_byte(pb, vals[3]);
403
    }
404
    else if (size < 0x10000000)
405
    {
406
        put_byte(pb, vals[0]);
407
        put_byte(pb, vals[1]);
408
        put_byte(pb, vals[2]);
409
        put_byte(pb, vals[3]);
410
    }
411
}
412

    
413
static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack* track) // Basic
414
{
415
    int decoderSpecificInfoLen;
416
    offset_t pos = url_ftell(pb);
417

    
418
    decoderSpecificInfoLen = track->vosLen ? descrLength(track->vosLen):0;
419

    
420
    put_be32(pb, 0);               // size
421
    put_tag(pb, "esds");
422
    put_be32(pb, 0);               // Version
423

    
424
    // ES descriptor
425
    putDescr(pb, 0x03, 3 + descrLength(13 + decoderSpecificInfoLen) +
426
             descrLength(1));
427
    put_be16(pb, track->trackID);
428
    put_byte(pb, 0x00);            // flags (= no flags)
429

    
430
    // DecoderConfig descriptor
431
    putDescr(pb, 0x04, 13 + decoderSpecificInfoLen);
432

    
433
    // Object type indication
434
    put_byte(pb, codec_get_tag(ff_mov_obj_type, track->enc->codec_id));
435

    
436
    // the following fields is made of 6 bits to identify the streamtype (4 for video, 5 for audio)
437
    // plus 1 bit to indicate upstream and 1 bit set to 1 (reserved)
438
    if(track->enc->codec_type == CODEC_TYPE_AUDIO)
439
        put_byte(pb, 0x15);            // flags (= Audiostream)
440
    else
441
        put_byte(pb, 0x11);            // flags (= Visualstream)
442

    
443
    put_byte(pb,  track->enc->rc_buffer_size>>(3+16));             // Buffersize DB (24 bits)
444
    put_be16(pb, (track->enc->rc_buffer_size>>3)&0xFFFF);          // Buffersize DB
445

    
446
    put_be32(pb, FFMAX(track->enc->bit_rate, track->enc->rc_max_rate));     // maxbitrate  (FIXME should be max rate in any 1 sec window)
447
    if(track->enc->rc_max_rate != track->enc->rc_min_rate || track->enc->rc_min_rate==0)
448
        put_be32(pb, 0);     // vbr
449
    else
450
        put_be32(pb, track->enc->rc_max_rate);     // avg bitrate
451

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

    
459

    
460
    // SL descriptor
461
    putDescr(pb, 0x06, 1);
462
    put_byte(pb, 0x02);
463
    return updateSize (pb, pos);
464
}
465

    
466
static const CodecTag codec_movvideo_tags[] = {
467
    { CODEC_ID_SVQ1, MKTAG('S', 'V', 'Q', '1') },
468
    { CODEC_ID_SVQ3, MKTAG('S', 'V', 'Q', '3') },
469
    { CODEC_ID_MPEG4, MKTAG('m', 'p', '4', 'v') },
470
    { CODEC_ID_H263, MKTAG('s', '2', '6', '3') },
471
    { CODEC_ID_H264, MKTAG('a', 'v', 'c', '1') },
472
    { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'c', ' ') },
473
    { 0, 0 },
474
};
475

    
476
static int mov_write_video_tag(ByteIOContext *pb, MOVTrack* track)
477
{
478
    offset_t pos = url_ftell(pb);
479
    char compressor_name[32];
480
    int tag;
481

    
482
    put_be32(pb, 0); /* size */
483

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

    
492
    put_be32(pb, 0); /* Reserved */
493
    put_be16(pb, 0); /* Reserved */
494
    put_be16(pb, 1); /* Data-reference index */
495

    
496
    put_be16(pb, 0); /* Codec stream version */
497
    put_be16(pb, 0); /* Codec stream revision (=0) */
498
    put_tag(pb, "FFMP"); /* Vendor */
499
    if(track->enc->codec_id == CODEC_ID_RAWVIDEO) {
500
        put_be32(pb, 0); /* Temporal Quality */
501
        put_be32(pb, 0x400); /* Spatial Quality = lossless*/
502
    } else {
503
        put_be32(pb, 0x200); /* Temporal Quality = normal */
504
        put_be32(pb, 0x200); /* Spatial Quality = normal */
505
    }
506
    put_be16(pb, track->enc->width); /* Video width */
507
    put_be16(pb, track->enc->height); /* Video height */
508
    put_be32(pb, 0x00480000); /* Horizontal resolution 72dpi */
509
    put_be32(pb, 0x00480000); /* Vertical resolution 72dpi */
510
    put_be32(pb, 0); /* Data size (= 0) */
511
    put_be16(pb, 1); /* Frame count (= 1) */
512

    
513
    memset(compressor_name,0,32);
514
    if (track->enc->codec && track->enc->codec->name)
515
        strncpy(compressor_name,track->enc->codec->name,31);
516
    put_byte(pb, strlen(compressor_name));
517
    put_buffer(pb, compressor_name, 31);
518

    
519
    put_be16(pb, 0x18); /* Reserved */
520
    put_be16(pb, 0xffff); /* Reserved */
521
    if(track->enc->codec_id == CODEC_ID_MPEG4)
522
        mov_write_esds_tag(pb, track);
523
    else if(track->enc->codec_id == CODEC_ID_H263)
524
        mov_write_d263_tag(pb);
525
    else if(track->enc->codec_id == CODEC_ID_SVQ3)
526
        mov_write_svq3_tag(pb);
527

    
528
    return updateSize (pb, pos);
529
}
530

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

    
545
/* TODO: */
546
/* Time to sample atom */
547
static int mov_write_stts_tag(ByteIOContext *pb, MOVTrack* track)
548
{
549
    put_be32(pb, 0x18); /* size */
550
    put_tag(pb, "stts");
551
    put_be32(pb, 0); /* version & flags */
552
    put_be32(pb, 1); /* entry count */
553

    
554
    put_be32(pb, track->sampleCount); /* sample count */
555
    put_be32(pb, track->sampleDuration); /* sample duration */
556
    return 0x18;
557
}
558

    
559
static int mov_write_dref_tag(ByteIOContext *pb)
560
{
561
    put_be32(pb, 28); /* size */
562
    put_tag(pb, "dref");
563
    put_be32(pb, 0); /* version & flags */
564
    put_be32(pb, 1); /* entry count */
565

    
566
    put_be32(pb, 0xc); /* size */
567
    put_tag(pb, "url ");
568
    put_be32(pb, 1); /* version & flags */
569

    
570
    return 28;
571
}
572

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

    
589
static int mov_write_dinf_tag(ByteIOContext *pb)
590
{
591
    offset_t pos = url_ftell(pb);
592
    put_be32(pb, 0); /* size */
593
    put_tag(pb, "dinf");
594
    mov_write_dref_tag(pb);
595
    return updateSize(pb, pos);
596
}
597

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

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

    
617
static int mov_write_hdlr_tag(ByteIOContext *pb, MOVTrack* track)
618
{
619
    char *descr, *hdlr, *hdlr_type;
620
    offset_t pos = url_ftell(pb);
621

    
622
    if (!track) { /* no media --> data handler */
623
        hdlr = "dhlr";
624
        hdlr_type = "url ";
625
        descr = "DataHandler";
626
    } else {
627
        hdlr = (track->mode == MODE_MOV) ? "mhlr" : "\0\0\0\0";
628
        if (track->enc->codec_type == CODEC_TYPE_VIDEO) {
629
            hdlr_type = "vide";
630
            descr = "VideoHandler";
631
        } else {
632
            hdlr_type = "soun";
633
            descr = "SoundHandler";
634
        }
635
    }
636

    
637
    put_be32(pb, 0); /* size */
638
    put_tag(pb, "hdlr");
639
    put_be32(pb, 0); /* Version & flags */
640
    put_buffer(pb, hdlr, 4); /* handler */
641
    put_tag(pb, hdlr_type); /* handler type */
642
    put_be32(pb ,0); /* reserved */
643
    put_be32(pb ,0); /* reserved */
644
    put_be32(pb ,0); /* reserved */
645
    put_byte(pb, strlen(descr)); /* string counter */
646
    put_buffer(pb, descr, strlen(descr)); /* handler description */
647
    return updateSize(pb, pos);
648
}
649

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

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

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

    
691
static int mov_write_tkhd_tag(ByteIOContext *pb, MOVTrack* track)
692
{
693
    put_be32(pb, 0x5c); /* size (always 0x5c) */
694
    put_tag(pb, "tkhd");
695
    put_be32(pb, 0xf); /* version & flags (track enabled) */
696
    put_be32(pb, track->time); /* creation time */
697
    put_be32(pb, track->time); /* modification time */
698
    put_be32(pb, track->trackID); /* track-id */
699
    put_be32(pb, 0); /* reserved */
700
    put_be32(pb, av_rescale_rnd(track->trackDuration, globalTimescale, track->timescale, AV_ROUND_UP)); /* duration */
701

    
702
    put_be32(pb, 0); /* reserved */
703
    put_be32(pb, 0); /* reserved */
704
    put_be32(pb, 0x0); /* reserved (Layer & Alternate group) */
705
    /* Volume, only for audio */
706
    if(track->enc->codec_type == CODEC_TYPE_AUDIO)
707
        put_be16(pb, 0x0100);
708
    else
709
        put_be16(pb, 0);
710
    put_be16(pb, 0); /* reserved */
711

    
712
    /* Matrix structure */
713
    put_be32(pb, 0x00010000); /* reserved */
714
    put_be32(pb, 0x0); /* reserved */
715
    put_be32(pb, 0x0); /* reserved */
716
    put_be32(pb, 0x0); /* reserved */
717
    put_be32(pb, 0x00010000); /* reserved */
718
    put_be32(pb, 0x0); /* reserved */
719
    put_be32(pb, 0x0); /* reserved */
720
    put_be32(pb, 0x0); /* reserved */
721
    put_be32(pb, 0x40000000); /* reserved */
722

    
723
    /* Track width and height, for visual only */
724
    if(track->enc->codec_type == CODEC_TYPE_VIDEO) {
725
        double sample_aspect_ratio = av_q2d(track->enc->sample_aspect_ratio);
726
        if( !sample_aspect_ratio ) sample_aspect_ratio = 1;
727
        put_be32(pb, sample_aspect_ratio * track->enc->width*0x10000);
728
        put_be32(pb, track->enc->height*0x10000);
729
    }
730
    else {
731
        put_be32(pb, 0);
732
        put_be32(pb, 0);
733
    }
734
    return 0x5c;
735
}
736

    
737
// This box seems important for the psp playback ... without it the movie seems to hang
738
static int mov_write_edts_tag(ByteIOContext *pb, MOVTrack *track)
739
{
740
    put_be32(pb, 0x24); /* size  */
741
    put_tag(pb, "edts");
742
    put_be32(pb, 0x1c); /* size  */
743
    put_tag(pb, "elst");
744
    put_be32(pb, 0x0);
745
    put_be32(pb, 0x1);
746

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

    
749
    put_be32(pb, 0x0);
750
    put_be32(pb, 0x00010000);
751
    return 0x24;
752
}
753

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

    
773
static int mov_write_trak_tag(ByteIOContext *pb, MOVTrack* track)
774
{
775
    offset_t pos = url_ftell(pb);
776
    put_be32(pb, 0); /* size */
777
    put_tag(pb, "trak");
778
    mov_write_tkhd_tag(pb, track);
779
    if (track->mode == MODE_PSP)
780
        mov_write_edts_tag(pb, track);  // PSP Movies require edts box
781
    mov_write_mdia_tag(pb, track);
782
    if (track->mode == MODE_PSP)
783
        mov_write_uuid_tag_psp(pb,track);  // PSP Movies require this uuid box
784
    return updateSize(pb, pos);
785
}
786

    
787
#if 0
788
/* TODO: Not sorted out, but not necessary either */
789
static int mov_write_iods_tag(ByteIOContext *pb, MOVContext *mov)
790
{
791
    put_be32(pb, 0x15); /* size */
792
    put_tag(pb, "iods");
793
    put_be32(pb, 0);    /* version & flags */
794
    put_be16(pb, 0x1007);
795
    put_byte(pb, 0);
796
    put_be16(pb, 0x4fff);
797
    put_be16(pb, 0xfffe);
798
    put_be16(pb, 0x01ff);
799
    return 0x15;
800
}
801
#endif
802

    
803
static int mov_write_mvhd_tag(ByteIOContext *pb, MOVContext *mov)
804
{
805
    int maxTrackID = 1, i;
806
    int64_t maxTrackLenTemp, maxTrackLen = 0;
807

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

    
825
    put_be32(pb, 0x00010000); /* reserved (preferred rate) 1.0 = normal */
826
    put_be16(pb, 0x0100); /* reserved (preferred volume) 1.0 = normal */
827
    put_be16(pb, 0); /* reserved */
828
    put_be32(pb, 0); /* reserved */
829
    put_be32(pb, 0); /* reserved */
830

    
831
    /* Matrix structure */
832
    put_be32(pb, 0x00010000); /* reserved */
833
    put_be32(pb, 0x0); /* reserved */
834
    put_be32(pb, 0x0); /* reserved */
835
    put_be32(pb, 0x0); /* reserved */
836
    put_be32(pb, 0x00010000); /* reserved */
837
    put_be32(pb, 0x0); /* reserved */
838
    put_be32(pb, 0x0); /* reserved */
839
    put_be32(pb, 0x0); /* reserved */
840
    put_be32(pb, 0x40000000); /* reserved */
841

    
842
    put_be32(pb, 0); /* reserved (preview time) */
843
    put_be32(pb, 0); /* reserved (preview duration) */
844
    put_be32(pb, 0); /* reserved (poster time) */
845
    put_be32(pb, 0); /* reserved (selection time) */
846
    put_be32(pb, 0); /* reserved (selection duration) */
847
    put_be32(pb, 0); /* reserved (current time) */
848
    put_be32(pb, maxTrackID+1); /* Next track id */
849
    return 0x6c;
850
}
851

    
852
static int mov_write_itunes_hdlr_tag(ByteIOContext *pb, MOVContext* mov,
853
                                     AVFormatContext *s)
854
{
855
    offset_t pos = url_ftell(pb);
856
    put_be32(pb, 0); /* size */
857
    put_tag(pb, "hdlr");
858
    put_be32(pb, 0);
859
    put_be32(pb, 0);
860
    put_tag(pb, "mdir");
861
    put_tag(pb, "appl");
862
    put_be32(pb, 0);
863
    put_be32(pb, 0);
864
    put_be16(pb, 0);
865
    return updateSize(pb, pos);
866
}
867

    
868
/* helper function to write a data tag with the specified string as data */
869
static int mov_write_string_data_tag(ByteIOContext *pb, MOVContext* mov,
870
                                     AVFormatContext *s, const char *data)
871
{
872
    offset_t pos = url_ftell(pb);
873
    put_be32(pb, 0); /* size */
874
    put_tag(pb, "data");
875
    put_be32(pb, 1);
876
    put_be32(pb, 0);
877
    put_buffer(pb, data, strlen(data));
878
    return updateSize(pb, pos);
879
}
880

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

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

    
912
/* iTunes name of the writer */
913
static int mov_write_wrt_tag(ByteIOContext *pb, MOVContext* mov,
914
                             AVFormatContext *s)
915
{
916
    int size = 0;
917
    if ( s->author[0] ) {
918
        offset_t pos = url_ftell(pb);
919
        put_be32(pb, 0); /* size */
920
        put_tag(pb, "\251wrt");
921
        mov_write_string_data_tag(pb, mov, s, s->author);
922
        size = updateSize(pb, pos);
923
    }
924
    return size;
925
}
926

    
927
/* iTunes name of the album */
928
static int mov_write_alb_tag(ByteIOContext *pb, MOVContext* mov,
929
                             AVFormatContext *s)
930
{
931
    int size = 0;
932
    if ( s->album[0] ) {
933
        offset_t pos = url_ftell(pb);
934
        put_be32(pb, 0); /* size */
935
        put_tag(pb, "\251alb");
936
        mov_write_string_data_tag(pb, mov, s, s->album);
937
        size = updateSize(pb, pos);
938
    }
939
    return size;
940
}
941

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

    
959
/* iTunes tool used to create the file */
960
static int mov_write_too_tag(ByteIOContext *pb, MOVContext* mov,
961
                             AVFormatContext *s)
962
{
963
    offset_t pos = url_ftell(pb);
964
    put_be32(pb, 0); /* size */
965
    put_tag(pb, "\251too");
966
    mov_write_string_data_tag(pb, mov, s, LIBAVFORMAT_IDENT);
967
    return updateSize(pb, pos);
968
}
969

    
970
/* iTunes comment */
971
static int mov_write_cmt_tag(ByteIOContext *pb, MOVContext* mov,
972
                             AVFormatContext *s)
973
{
974
    int size = 0;
975
    if ( s->comment[0] ) {
976
        offset_t pos = url_ftell(pb);
977
        put_be32(pb, 0); /* size */
978
        put_tag(pb, "\251cmt");
979
        mov_write_string_data_tag(pb, mov, s, s->comment);
980
        size = updateSize(pb, pos);
981
    }
982
    return size;
983
}
984

    
985
/* iTunes custom genre */
986
static int mov_write_gen_tag(ByteIOContext *pb, MOVContext* mov,
987
                             AVFormatContext *s)
988
{
989
    int size = 0;
990
    if ( s->genre[0] ) {
991
        offset_t pos = url_ftell(pb);
992
        put_be32(pb, 0); /* size */
993
        put_tag(pb, "\251gen");
994
        mov_write_string_data_tag(pb, mov, s, s->genre);
995
        size = updateSize(pb, pos);
996
    }
997
    return size;
998
}
999

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

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

    
1045
/* iTunes meta data tag */
1046
static int mov_write_meta_tag(ByteIOContext *pb, MOVContext* mov,
1047
                              AVFormatContext *s)
1048
{
1049
    int size = 0;
1050

    
1051
    // only save meta tag if required
1052
    if ( s->title[0] || s->author[0] || s->album[0] || s->year ||
1053
         s->comment[0] || s->genre[0] || s->track ) {
1054
        offset_t pos = url_ftell(pb);
1055
        put_be32(pb, 0); /* size */
1056
        put_tag(pb, "meta");
1057
        put_be32(pb, 0);
1058
        mov_write_itunes_hdlr_tag(pb, mov, s);
1059
        mov_write_ilst_tag(pb, mov, s);
1060
        size = updateSize(pb, pos);
1061
    }
1062
    return size;
1063
}
1064

    
1065
static int mov_write_udta_tag(ByteIOContext *pb, MOVContext* mov,
1066
                              AVFormatContext *s)
1067
{
1068
    offset_t pos = url_ftell(pb);
1069
    int i;
1070

    
1071
    put_be32(pb, 0); /* size */
1072
    put_tag(pb, "udta");
1073

    
1074
    /* iTunes meta data */
1075
    mov_write_meta_tag(pb, mov, s);
1076

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

    
1094
    /* Encoder */
1095
    if(mov->tracks[0].enc && !(mov->tracks[0].enc->flags & CODEC_FLAG_BITEXACT))
1096
    {
1097
        offset_t pos = url_ftell(pb);
1098
        put_be32(pb, 0); /* size */
1099
        put_tag(pb, "\251enc");
1100
        put_be16(pb, sizeof(LIBAVFORMAT_IDENT) - 1); /* string length */
1101
        put_be16(pb, 0);
1102
        put_buffer(pb, LIBAVFORMAT_IDENT, sizeof(LIBAVFORMAT_IDENT) - 1);
1103
        updateSize(pb, pos);
1104
    }
1105

    
1106
    if( s->title[0] )
1107
    {
1108
        offset_t pos = url_ftell(pb);
1109
        put_be32(pb, 0); /* size */
1110
        put_tag(pb, "\251nam");
1111
        put_be16(pb, strlen(s->title)); /* string length */
1112
        put_be16(pb, 0);
1113
        put_buffer(pb, s->title, strlen(s->title));
1114
        updateSize(pb, pos);
1115
    }
1116

    
1117
    if( s->author[0] )
1118
    {
1119
        offset_t pos = url_ftell(pb);
1120
        put_be32(pb, 0); /* size */
1121
        put_tag(pb, /*"\251aut"*/ "\251day" );
1122
        put_be16(pb, strlen(s->author)); /* string length */
1123
        put_be16(pb, 0);
1124
        put_buffer(pb, s->author, strlen(s->author));
1125
        updateSize(pb, pos);
1126
    }
1127

    
1128
    if( s->comment[0] )
1129
    {
1130
        offset_t pos = url_ftell(pb);
1131
        put_be32(pb, 0); /* size */
1132
        put_tag(pb, "\251des");
1133
        put_be16(pb, strlen(s->comment)); /* string length */
1134
        put_be16(pb, 0);
1135
        put_buffer(pb, s->comment, strlen(s->comment));
1136
        updateSize(pb, pos);
1137
    }
1138

    
1139
    return updateSize(pb, pos);
1140
}
1141

    
1142

    
1143
static size_t ascii_to_wc (ByteIOContext *pb, char *b, size_t n)
1144
{
1145
    size_t i;
1146
    unsigned char c;
1147
    for (i = 0; i < n - 1; i++) {
1148
        c = b[i];
1149
        if (! (0x20 <= c && c <= 0x7f ))
1150
            c = 0x3f;  /* '?' */
1151
        put_be16(pb, c);
1152
    }
1153
    put_be16(pb, 0x00);
1154
    return 2*n;
1155
}
1156

    
1157
static uint16_t language_code (char *str)
1158
{
1159
    return ((((str[0]-'a') & 0x1F)<<10) + (((str[1]-'a') & 0x1F)<<5) + ((str[2]-'a') & 0x1F));
1160
}
1161

    
1162
static int mov_write_uuidusmt_tag (ByteIOContext *pb, AVFormatContext *s)
1163
{
1164
    size_t len, size;
1165
    offset_t pos, curpos;
1166

    
1167
    size = 0;
1168
    if (s->title[0]) {
1169
        pos = url_ftell(pb);
1170
        put_be32(pb, 0); /* size placeholder*/
1171
        put_tag(pb, "uuid");
1172
        put_tag(pb, "USMT");
1173
        put_be32(pb, 0x21d24fce ); /* 96 bit UUID */
1174
        put_be32(pb, 0xbb88695c );
1175
        put_be32(pb, 0xfac9c740 );
1176
        size += 24;
1177

    
1178
        put_be32(pb, 0); /* size placeholder*/
1179
        put_tag(pb, "MTDT");
1180
        put_be16(pb, 1);
1181
        size += 10;
1182

    
1183
        // Title
1184
        len = strlen(s->title)+1;
1185
        put_be16(pb, len*2+10);             /* size */
1186
        put_be32(pb, 0x01);                 /* type */
1187
        put_be16(pb, language_code("und")); /* language */
1188
        put_be16(pb, 0x01);                 /* ? */
1189
        ascii_to_wc (pb, s->title, len);
1190
        size += len*2+10;
1191

    
1192
        // size
1193
        curpos = url_ftell(pb);
1194
        url_fseek(pb, pos, SEEK_SET);
1195
        put_be32(pb, size);
1196
        url_fseek(pb, pos+24, SEEK_SET);
1197
        put_be32(pb, size-24);
1198
        url_fseek(pb, curpos, SEEK_SET);
1199
    }
1200

    
1201
    return size;
1202
}
1203

    
1204
static int mov_write_moov_tag(ByteIOContext *pb, MOVContext *mov,
1205
                              AVFormatContext *s)
1206
{
1207
    int i;
1208
    offset_t pos = url_ftell(pb);
1209
    put_be32(pb, 0); /* size placeholder*/
1210
    put_tag(pb, "moov");
1211
    mov->timescale = globalTimescale;
1212

    
1213
    for (i=0; i<MAX_STREAMS; i++) {
1214
        if(mov->tracks[i].entry <= 0) continue;
1215

    
1216
        if(mov->tracks[i].enc->codec_type == CODEC_TYPE_VIDEO) {
1217
            mov->tracks[i].timescale = mov->tracks[i].enc->time_base.den;
1218
            mov->tracks[i].sampleDuration = mov->tracks[i].enc->time_base.num;
1219
        }
1220
        else if(mov->tracks[i].enc->codec_type == CODEC_TYPE_AUDIO) {
1221
            /* If AMR, track timescale = 8000, AMR_WB = 16000 */
1222
            if(mov->tracks[i].enc->codec_id == CODEC_ID_AMR_NB) {
1223
                mov->tracks[i].sampleDuration = 160;  // Bytes per chunk
1224
                mov->tracks[i].timescale = 8000;
1225
            }
1226
            else {
1227
                mov->tracks[i].timescale = mov->tracks[i].enc->sample_rate;
1228
                mov->tracks[i].sampleDuration = mov->tracks[i].enc->frame_size;
1229
            }
1230
        }
1231

    
1232
        mov->tracks[i].trackDuration =
1233
            mov->tracks[i].sampleCount * mov->tracks[i].sampleDuration;
1234
        mov->tracks[i].time = mov->time;
1235
        mov->tracks[i].trackID = i+1;
1236
    }
1237

    
1238
    mov_write_mvhd_tag(pb, mov);
1239
    //mov_write_iods_tag(pb, mov);
1240
    for (i=0; i<MAX_STREAMS; i++) {
1241
        if(mov->tracks[i].entry > 0) {
1242
            mov_write_trak_tag(pb, &(mov->tracks[i]));
1243
        }
1244
    }
1245

    
1246
    if (mov->mode == MODE_PSP)
1247
        mov_write_uuidusmt_tag(pb, s);
1248
    else
1249
    mov_write_udta_tag(pb, mov, s);
1250

    
1251
    return updateSize(pb, pos);
1252
}
1253

    
1254
int mov_write_mdat_tag(ByteIOContext *pb, MOVContext* mov)
1255
{
1256
    put_be32(pb, 8);    // placeholder for extended size field (64 bit)
1257
    put_tag(pb, "wide");
1258

    
1259
    mov->mdat_pos = url_ftell(pb);
1260
    put_be32(pb, 0); /* size placeholder*/
1261
    put_tag(pb, "mdat");
1262
    return 0;
1263
}
1264

    
1265
/* TODO: This needs to be more general */
1266
static void mov_write_ftyp_tag (ByteIOContext *pb, AVFormatContext *s)
1267
{
1268
    MOVContext *mov = s->priv_data;
1269

    
1270
    put_be32(pb, 0x14 ); /* size */
1271
    put_tag(pb, "ftyp");
1272

    
1273
    if ( mov->mode == MODE_3GP )
1274
        put_tag(pb, "3gp4");
1275
    else if ( mov->mode == MODE_3G2 )
1276
        put_tag(pb, "3g2a");
1277
    else if ( mov->mode == MODE_PSP )
1278
        put_tag(pb, "MSNV");
1279
    else
1280
        put_tag(pb, "isom");
1281

    
1282
    put_be32(pb, 0x200 );
1283

    
1284
    if ( mov->mode == MODE_3GP )
1285
        put_tag(pb, "3gp4");
1286
    else if ( mov->mode == MODE_3G2 )
1287
        put_tag(pb, "3g2a");
1288
    else if ( mov->mode == MODE_PSP )
1289
        put_tag(pb, "MSNV");
1290
    else
1291
        put_tag(pb, "mp41");
1292
}
1293

    
1294
static void mov_write_uuidprof_tag(ByteIOContext *pb, AVFormatContext *s)
1295
{
1296
    AVCodecContext *VideoCodec = s->streams[0]->codec;
1297
    AVCodecContext *AudioCodec = s->streams[1]->codec;
1298
    int AudioRate = AudioCodec->sample_rate;
1299
    int FrameRate = ((VideoCodec->time_base.den) * (0x10000))/ (VideoCodec->time_base.num);
1300

    
1301
    put_be32(pb, 0x94 ); /* size */
1302
    put_tag(pb, "uuid");
1303
    put_tag(pb, "PROF");
1304

    
1305
    put_be32(pb, 0x21d24fce ); /* 96 bit UUID */
1306
    put_be32(pb, 0xbb88695c );
1307
    put_be32(pb, 0xfac9c740 );
1308

    
1309
    put_be32(pb, 0x0 );  /* ? */
1310
    put_be32(pb, 0x3 );  /* 3 sections ? */
1311

    
1312
    put_be32(pb, 0x14 ); /* size */
1313
    put_tag(pb, "FPRF");
1314
    put_be32(pb, 0x0 );  /* ? */
1315
    put_be32(pb, 0x0 );  /* ? */
1316
    put_be32(pb, 0x0 );  /* ? */
1317

    
1318
    put_be32(pb, 0x2c );  /* size */
1319
    put_tag(pb, "APRF");   /* audio */
1320
    put_be32(pb, 0x0 );
1321
    put_be32(pb, 0x2 );   /* TrackID */
1322
    put_tag(pb, "mp4a");
1323
    put_be32(pb, 0x20f );
1324
    put_be32(pb, 0x0 );
1325
    put_be32(pb, AudioCodec->bit_rate / 1000);
1326
    put_be32(pb, AudioCodec->bit_rate / 1000);
1327
    put_be32(pb, AudioRate );
1328
    put_be32(pb, AudioCodec->channels );
1329

    
1330
    put_be32(pb, 0x34 );  /* size */
1331
    put_tag(pb, "VPRF");   /* video */
1332
    put_be32(pb, 0x0 );
1333
    put_be32(pb, 0x1 );    /* TrackID */
1334
    put_tag(pb, "mp4v");
1335
    put_be32(pb, 0x103 );
1336
    put_be32(pb, 0x0 );
1337
    put_be32(pb, VideoCodec->bit_rate / 1000);
1338
    put_be32(pb, VideoCodec->bit_rate / 1000);
1339
    put_be32(pb, FrameRate);
1340
    put_be32(pb, FrameRate);
1341
    put_be16(pb, VideoCodec->width);
1342
    put_be16(pb, VideoCodec->height);
1343
    put_be32(pb, 0x010001); /* ? */
1344
}
1345

    
1346
static int mov_write_header(AVFormatContext *s)
1347
{
1348
    ByteIOContext *pb = &s->pb;
1349
    MOVContext *mov = s->priv_data;
1350
    int i;
1351

    
1352
    for(i=0; i<s->nb_streams; i++){
1353
        AVCodecContext *c= s->streams[i]->codec;
1354

    
1355
        if      (c->codec_type == CODEC_TYPE_VIDEO){
1356
            if (!codec_get_tag(codec_movvideo_tags, c->codec_id)){
1357
                if(!codec_get_tag(codec_bmp_tags, c->codec_id))
1358
                    return -1;
1359
                else
1360
                    av_log(s, AV_LOG_INFO, "Warning, using MS style video codec tag, the file may be unplayable!\n");
1361
            }
1362
        }else if(c->codec_type == CODEC_TYPE_AUDIO){
1363
            if (!codec_get_tag(codec_movaudio_tags, c->codec_id)){
1364
                if(!codec_get_tag(codec_wav_tags, c->codec_id))
1365
                    return -1;
1366
                else
1367
                    av_log(s, AV_LOG_INFO, "Warning, using MS style audio codec tag, the file may be unplayable!\n");
1368
            }
1369
        }
1370
        /* don't know yet if mp4 or not */
1371
        mov->tracks[i].language = ff_mov_iso639_to_lang(s->streams[i]->language, 1);
1372
    }
1373

    
1374
    /* Default mode == MP4 */
1375
    mov->mode = MODE_MP4;
1376

    
1377
    if (s->oformat != NULL) {
1378
        if (!strcmp("3gp", s->oformat->name)) mov->mode = MODE_3GP;
1379
        else if (!strcmp("3g2", s->oformat->name)) mov->mode = MODE_3G2;
1380
        else if (!strcmp("mov", s->oformat->name)) mov->mode = MODE_MOV;
1381
        else if (!strcmp("psp", s->oformat->name)) mov->mode = MODE_PSP;
1382

    
1383
        if ( mov->mode == MODE_3GP || mov->mode == MODE_3G2 ||
1384
             mov->mode == MODE_MP4 || mov->mode == MODE_PSP )
1385
            mov_write_ftyp_tag(pb,s);
1386
        if ( mov->mode == MODE_PSP ) {
1387
            if ( s->nb_streams != 2 ) {
1388
                av_log(s, AV_LOG_ERROR, "PSP mode need one video and one audio stream\n");
1389
                return -1;
1390
            }
1391
            mov_write_uuidprof_tag(pb,s);
1392
        }
1393
    }
1394

    
1395
    for (i=0; i<MAX_STREAMS; i++) {
1396
        mov->tracks[i].mode = mov->mode;
1397
    }
1398

    
1399
    put_flush_packet(pb);
1400

    
1401
    return 0;
1402
}
1403

    
1404
static int mov_write_packet(AVFormatContext *s, AVPacket *pkt)
1405
{
1406
    MOVContext *mov = s->priv_data;
1407
    ByteIOContext *pb = &s->pb;
1408
    AVCodecContext *enc = s->streams[pkt->stream_index]->codec;
1409
    MOVTrack* trk = &mov->tracks[pkt->stream_index];
1410
    int cl, id;
1411
    unsigned int samplesInChunk = 0;
1412
    int size= pkt->size;
1413

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

    
1417
    if (enc->codec_type == CODEC_TYPE_VIDEO ) {
1418
        samplesInChunk = 1;
1419
    }
1420
    else if (enc->codec_type == CODEC_TYPE_AUDIO ) {
1421
        if( enc->codec_id == CODEC_ID_AMR_NB) {
1422
            /* We must find out how many AMR blocks there are in one packet */
1423
            static uint16_t packed_size[16] =
1424
                {13, 14, 16, 18, 20, 21, 27, 32, 6, 0, 0, 0, 0, 0, 0, 0};
1425
            int len = 0;
1426

    
1427
            while (len < size && samplesInChunk < 100) {
1428
                len += packed_size[(pkt->data[len] >> 3) & 0x0F];
1429
                samplesInChunk++;
1430
            }
1431
        }
1432
        else if(enc->codec_id == CODEC_ID_PCM_ALAW) {
1433
            samplesInChunk = size/enc->channels;
1434
        }
1435
        else if(enc->codec_id == CODEC_ID_PCM_S16BE || enc->codec_id == CODEC_ID_PCM_S16LE) {
1436
            samplesInChunk = size/(2*enc->channels);
1437
        }
1438
        else {
1439
            samplesInChunk = 1;
1440
        }
1441
    }
1442

    
1443
    if ((enc->codec_id == CODEC_ID_MPEG4 || enc->codec_id == CODEC_ID_AAC)
1444
        && trk->vosLen == 0) {
1445
//        assert(enc->extradata_size);
1446

    
1447
        trk->vosLen = enc->extradata_size;
1448
        trk->vosData = av_malloc(trk->vosLen);
1449
        memcpy(trk->vosData, enc->extradata, trk->vosLen);
1450
    }
1451

    
1452
    cl = trk->entry / MOV_INDEX_CLUSTER_SIZE;
1453
    id = trk->entry % MOV_INDEX_CLUSTER_SIZE;
1454

    
1455
    if (trk->ents_allocated <= trk->entry) {
1456
        trk->cluster = av_realloc(trk->cluster, (cl+1)*sizeof(void*));
1457
        if (!trk->cluster)
1458
            return -1;
1459
        trk->cluster[cl] = av_malloc(MOV_INDEX_CLUSTER_SIZE*sizeof(MOVIentry));
1460
        if (!trk->cluster[cl])
1461
            return -1;
1462
        trk->ents_allocated += MOV_INDEX_CLUSTER_SIZE;
1463
    }
1464
    if (mov->mdat_written == 0) {
1465
        mov_write_mdat_tag(pb, mov);
1466
        mov->mdat_written = 1;
1467
        mov->time = s->timestamp + 0x7C25B080; //1970 based -> 1904 based
1468
    }
1469

    
1470
    trk->cluster[cl][id].pos = url_ftell(pb);
1471
    trk->cluster[cl][id].samplesInChunk = samplesInChunk;
1472
    trk->cluster[cl][id].size = size;
1473
    trk->cluster[cl][id].entries = samplesInChunk;
1474
    if(enc->codec_type == CODEC_TYPE_VIDEO) {
1475
        trk->cluster[cl][id].key_frame = !!(pkt->flags & PKT_FLAG_KEY);
1476
        if(trk->cluster[cl][id].key_frame)
1477
            trk->hasKeyframes = 1;
1478
    }
1479
    trk->enc = enc;
1480
    trk->entry++;
1481
    trk->sampleCount += samplesInChunk;
1482
    trk->mdat_size += size;
1483

    
1484
    put_buffer(pb, pkt->data, size);
1485

    
1486
    put_flush_packet(pb);
1487
    return 0;
1488
}
1489

    
1490
static int mov_write_trailer(AVFormatContext *s)
1491
{
1492
    MOVContext *mov = s->priv_data;
1493
    ByteIOContext *pb = &s->pb;
1494
    int res = 0;
1495
    int i;
1496
    uint64_t j;
1497

    
1498
    offset_t moov_pos = url_ftell(pb);
1499

    
1500
    /* Write size of mdat tag */
1501
    for (i=0, j=0; i<MAX_STREAMS; i++) {
1502
        if(mov->tracks[i].ents_allocated > 0) {
1503
            j += mov->tracks[i].mdat_size;
1504
        }
1505
    }
1506
    if (j+8 <= UINT32_MAX) {
1507
        url_fseek(pb, mov->mdat_pos, SEEK_SET);
1508
        put_be32(pb, j+8);
1509
    } else {
1510
        /* overwrite 'wide' placeholder atom */
1511
        url_fseek(pb, mov->mdat_pos - 8, SEEK_SET);
1512
        put_be32(pb, 1); /* special value: real atom size will be 64 bit value after tag field */
1513
        put_tag(pb, "mdat");
1514
        put_be64(pb, j+16);
1515
    }
1516
    url_fseek(pb, moov_pos, SEEK_SET);
1517

    
1518
    mov_write_moov_tag(pb, mov, s);
1519

    
1520
    for (i=0; i<MAX_STREAMS; i++) {
1521
        for (j=0; j<mov->tracks[i].ents_allocated/MOV_INDEX_CLUSTER_SIZE; j++) {
1522
            av_free(mov->tracks[i].cluster[j]);
1523
        }
1524
        av_free(mov->tracks[i].cluster);
1525
        if( mov->tracks[i].vosLen ) av_free( mov->tracks[i].vosData );
1526

    
1527
        mov->tracks[i].cluster = NULL;
1528
        mov->tracks[i].ents_allocated = mov->tracks[i].entry = 0;
1529
    }
1530

    
1531
    put_flush_packet(pb);
1532

    
1533
    return res;
1534
}
1535

    
1536
static AVOutputFormat mov_oformat = {
1537
    "mov",
1538
    "mov format",
1539
    NULL,
1540
    "mov",
1541
    sizeof(MOVContext),
1542
    CODEC_ID_AAC,
1543
    CODEC_ID_MPEG4,
1544
    mov_write_header,
1545
    mov_write_packet,
1546
    mov_write_trailer,
1547
    .flags = AVFMT_GLOBALHEADER,
1548
};
1549

    
1550
static AVOutputFormat _3gp_oformat = {
1551
    "3gp",
1552
    "3gp format",
1553
    NULL,
1554
    "3gp",
1555
    sizeof(MOVContext),
1556
    CODEC_ID_AMR_NB,
1557
    CODEC_ID_H263,
1558
    mov_write_header,
1559
    mov_write_packet,
1560
    mov_write_trailer,
1561
    .flags = AVFMT_GLOBALHEADER,
1562
};
1563

    
1564
static AVOutputFormat mp4_oformat = {
1565
    "mp4",
1566
    "mp4 format",
1567
    "application/mp4",
1568
    "mp4,m4a",
1569
    sizeof(MOVContext),
1570
    CODEC_ID_AAC,
1571
    CODEC_ID_MPEG4,
1572
    mov_write_header,
1573
    mov_write_packet,
1574
    mov_write_trailer,
1575
    .flags = AVFMT_GLOBALHEADER,
1576
};
1577

    
1578
static AVOutputFormat psp_oformat = {
1579
    "psp",
1580
    "psp mp4 format",
1581
    NULL,
1582
    "mp4,psp",
1583
    sizeof(MOVContext),
1584
    CODEC_ID_AAC,
1585
    CODEC_ID_MPEG4,
1586
    mov_write_header,
1587
    mov_write_packet,
1588
    mov_write_trailer,
1589
    .flags = AVFMT_GLOBALHEADER,
1590
};
1591

    
1592
static AVOutputFormat _3g2_oformat = {
1593
    "3g2",
1594
    "3gp2 format",
1595
    NULL,
1596
    "3g2",
1597
    sizeof(MOVContext),
1598
    CODEC_ID_AMR_NB,
1599
    CODEC_ID_H263,
1600
    mov_write_header,
1601
    mov_write_packet,
1602
    mov_write_trailer,
1603
    .flags = AVFMT_GLOBALHEADER,
1604
};
1605

    
1606
int movenc_init(void)
1607
{
1608
    av_register_output_format(&mov_oformat);
1609
    av_register_output_format(&_3gp_oformat);
1610
    av_register_output_format(&mp4_oformat);
1611
    av_register_output_format(&psp_oformat);
1612
    av_register_output_format(&_3g2_oformat);
1613
    return 0;
1614
}