Statistics
| Branch: | Revision:

ffmpeg / libavformat / movenc.c @ ce072b2d

History | View | Annotate | Download (56.1 KB)

1
/*
2
 * MOV, 3GP, MP4 muxer
3
 * Copyright (c) 2003 Thomas Raivio.
4
 * Copyright (c) 2004 Gildas Bazin <gbazin at videolan dot org>.
5
 *
6
 * This file is part of FFmpeg.
7
 *
8
 * FFmpeg is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public
10
 * License as published by the Free Software Foundation; either
11
 * version 2.1 of the License, or (at your option) any later version.
12
 *
13
 * FFmpeg is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public
19
 * License along with FFmpeg; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
 */
22
#include "avformat.h"
23
#include "riff.h"
24
#include "avio.h"
25
#include "isom.h"
26
#include "avc.h"
27

    
28
#undef NDEBUG
29
#include <assert.h>
30

    
31
#define MOV_INDEX_CLUSTER_SIZE 16384
32
#define globalTimescale 1000
33

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

    
42
typedef struct MOVIentry {
43
    unsigned int flags, size;
44
    uint64_t     pos;
45
    unsigned int samplesInChunk;
46
    char         key_frame;
47
    unsigned int entries;
48
    int64_t      cts;
49
    int64_t      dts;
50
} MOVIentry;
51

    
52
typedef struct MOVIndex {
53
    int         mode;
54
    int         entry;
55
    long        timescale;
56
    long        time;
57
    int64_t     trackDuration;
58
    long        sampleCount;
59
    long        sampleSize;
60
    int         hasKeyframes;
61
    int         hasBframes;
62
    int         language;
63
    int         trackID;
64
    int         tag; ///< stsd fourcc
65
    AVCodecContext *enc;
66

    
67
    int         vosLen;
68
    uint8_t     *vosData;
69
    MOVIentry   *cluster;
70
    int         audio_vbr;
71
} MOVTrack;
72

    
73
typedef struct MOVContext {
74
    int     mode;
75
    int64_t time;
76
    int     nb_streams;
77
    offset_t mdat_pos;
78
    uint64_t mdat_size;
79
    long    timescale;
80
    MOVTrack tracks[MAX_STREAMS];
81
} MOVContext;
82

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

    
91
    return curpos - pos;
92
}
93

    
94
/* Chunk offset atom */
95
static int mov_write_stco_tag(ByteIOContext *pb, MOVTrack *track)
96
{
97
    int i;
98
    int mode64 = 0; //   use 32 bit size variant if possible
99
    offset_t pos = url_ftell(pb);
100
    put_be32(pb, 0); /* size */
101
    if (pos > UINT32_MAX) {
102
        mode64 = 1;
103
        put_tag(pb, "co64");
104
    } else
105
        put_tag(pb, "stco");
106
    put_be32(pb, 0); /* version & flags */
107
    put_be32(pb, track->entry); /* entry count */
108
    for (i=0; i<track->entry; i++) {
109
        if(mode64 == 1)
110
            put_be64(pb, track->cluster[i].pos);
111
        else
112
            put_be32(pb, track->cluster[i].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
        tst = track->cluster[i].size/track->cluster[i].entries;
130
        if(oldtst != -1 && tst != oldtst) {
131
            equalChunks = 0;
132
        }
133
        oldtst = tst;
134
        entries += track->cluster[i].entries;
135
    }
136
    if (equalChunks) {
137
        int sSize = track->cluster[0].size/track->cluster[0].entries;
138
        put_be32(pb, sSize); // sample size
139
        put_be32(pb, entries); // sample count
140
    }
141
    else {
142
        put_be32(pb, 0); // sample size
143
        put_be32(pb, entries); // sample count
144
        for (i=0; i<track->entry; i++) {
145
            for (j=0; j<track->cluster[i].entries; j++) {
146
                put_be32(pb, track->cluster[i].size /
147
                         track->cluster[i].entries);
148
            }
149
        }
150
    }
151
    return updateSize(pb, pos);
152
}
153

    
154
/* Sample to chunk atom */
155
static int mov_write_stsc_tag(ByteIOContext *pb, MOVTrack *track)
156
{
157
    int index = 0, oldval = -1, i;
158
    offset_t entryPos, curpos;
159

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

    
181
    return updateSize(pb, pos);
182
}
183

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

    
208
static int mov_write_amr_tag(ByteIOContext *pb, MOVTrack *track)
209
{
210
    put_be32(pb, 0x11); /* size */
211
    if (track->mode == MODE_MOV) put_tag(pb, "samr");
212
    else                         put_tag(pb, "damr");
213
    put_tag(pb, "FFMP");
214
    put_byte(pb, 0); /* decoder version */
215

    
216
    put_be16(pb, 0x81FF); /* Mode set (all modes for AMR_NB) */
217
    put_byte(pb, 0x00); /* Mode change period (no restriction) */
218
    put_byte(pb, 0x01); /* Frames per sample */
219
    return 0x11;
220
}
221

    
222
/**
223
 * This function writes extradata "as is".
224
 * Extradata must be formated like a valid atom (with size and tag)
225
 */
226
static int mov_write_extradata_tag(ByteIOContext *pb, MOVTrack *track)
227
{
228
    put_buffer(pb, track->enc->extradata, track->enc->extradata_size);
229
    return track->enc->extradata_size;
230
}
231

    
232
static int mov_write_enda_tag(ByteIOContext *pb)
233
{
234
    put_be32(pb, 10);
235
    put_tag(pb, "enda");
236
    put_be16(pb, 1); /* little endian */
237
    return 10;
238
}
239

    
240
static unsigned int descrLength(unsigned int len)
241
{
242
    int i;
243
    for(i=1; len>>(7*i); i++);
244
    return len + 1 + i;
245
}
246

    
247
static void putDescr(ByteIOContext *pb, int tag, unsigned int size)
248
{
249
    int i= descrLength(size) - size - 2;
250
    put_byte(pb, tag);
251
    for(; i>0; i--)
252
        put_byte(pb, (size>>(7*i)) | 0x80);
253
    put_byte(pb, size & 0x7F);
254
}
255

    
256
static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack *track) // Basic
257
{
258
    offset_t pos = url_ftell(pb);
259
    int decoderSpecificInfoLen = track->vosLen ? descrLength(track->vosLen):0;
260

    
261
    put_be32(pb, 0); // size
262
    put_tag(pb, "esds");
263
    put_be32(pb, 0); // Version
264

    
265
    // ES descriptor
266
    putDescr(pb, 0x03, 3 + descrLength(13 + decoderSpecificInfoLen) +
267
             descrLength(1));
268
    put_be16(pb, track->trackID);
269
    put_byte(pb, 0x00); // flags (= no flags)
270

    
271
    // DecoderConfig descriptor
272
    putDescr(pb, 0x04, 13 + decoderSpecificInfoLen);
273

    
274
    // Object type indication
275
    put_byte(pb, codec_get_tag(ff_mp4_obj_type, track->enc->codec_id));
276

    
277
    // the following fields is made of 6 bits to identify the streamtype (4 for video, 5 for audio)
278
    // plus 1 bit to indicate upstream and 1 bit set to 1 (reserved)
279
    if(track->enc->codec_type == CODEC_TYPE_AUDIO)
280
        put_byte(pb, 0x15); // flags (= Audiostream)
281
    else
282
        put_byte(pb, 0x11); // flags (= Visualstream)
283

    
284
    put_byte(pb,  track->enc->rc_buffer_size>>(3+16));    // Buffersize DB (24 bits)
285
    put_be16(pb, (track->enc->rc_buffer_size>>3)&0xFFFF); // Buffersize DB
286

    
287
    put_be32(pb, FFMAX(track->enc->bit_rate, track->enc->rc_max_rate)); // maxbitrate (FIXME should be max rate in any 1 sec window)
288
    if(track->enc->rc_max_rate != track->enc->rc_min_rate || track->enc->rc_min_rate==0)
289
        put_be32(pb, 0); // vbr
290
    else
291
        put_be32(pb, track->enc->rc_max_rate); // avg bitrate
292

    
293
    if (track->vosLen) {
294
        // DecoderSpecific info descriptor
295
        putDescr(pb, 0x05, track->vosLen);
296
        put_buffer(pb, track->vosData, track->vosLen);
297
    }
298

    
299
    // SL descriptor
300
    putDescr(pb, 0x06, 1);
301
    put_byte(pb, 0x02);
302
    return updateSize(pb, pos);
303
}
304

    
305
static int mov_write_wave_tag(ByteIOContext *pb, MOVTrack *track)
306
{
307
    offset_t pos = url_ftell(pb);
308

    
309
    put_be32(pb, 0);     /* size */
310
    put_tag(pb, "wave");
311

    
312
    put_be32(pb, 12);    /* size */
313
    put_tag(pb, "frma");
314
    put_le32(pb, track->tag);
315

    
316
    if (track->enc->codec_id == CODEC_ID_AAC) {
317
        /* useless atom needed by mplayer, ipod, not needed by quicktime */
318
        put_be32(pb, 12); /* size */
319
        put_tag(pb, "mp4a");
320
        put_be32(pb, 0);
321
        mov_write_esds_tag(pb, track);
322
    } else if (track->enc->codec_id == CODEC_ID_PCM_S24LE ||
323
               track->enc->codec_id == CODEC_ID_PCM_S32LE) {
324
        mov_write_enda_tag(pb);
325
    } else if (track->enc->codec_id == CODEC_ID_AMR_NB) {
326
        mov_write_amr_tag(pb, track);
327
    } else if (track->enc->codec_id == CODEC_ID_ALAC) {
328
        mov_write_extradata_tag(pb, track);
329
    }
330

    
331
    put_be32(pb, 8);     /* size */
332
    put_be32(pb, 0);     /* null tag */
333

    
334
    return updateSize(pb, pos);
335
}
336

    
337
static int mov_write_glbl_tag(ByteIOContext *pb, MOVTrack *track)
338
{
339
    put_be32(pb, track->vosLen+8);
340
    put_tag(pb, "glbl");
341
    put_buffer(pb, track->vosData, track->vosLen);
342
    return 8+track->vosLen;
343
}
344

    
345
static int mov_write_audio_tag(ByteIOContext *pb, MOVTrack *track)
346
{
347
    offset_t pos = url_ftell(pb);
348
    int version = track->mode == MODE_MOV &&
349
        (track->audio_vbr ||
350
         track->enc->codec_id == CODEC_ID_PCM_S32LE ||
351
         track->enc->codec_id == CODEC_ID_PCM_S24LE);
352

    
353
    put_be32(pb, 0); /* size */
354
    put_le32(pb, track->tag); // store it byteswapped
355
    put_be32(pb, 0); /* Reserved */
356
    put_be16(pb, 0); /* Reserved */
357
    put_be16(pb, 1); /* Data-reference index, XXX  == 1 */
358

    
359
    /* SoundDescription */
360
    put_be16(pb, version); /* Version */
361
    put_be16(pb, 0); /* Revision level */
362
    put_be32(pb, 0); /* Reserved */
363

    
364
    if (track->mode == MODE_MOV) {
365
        put_be16(pb, track->enc->channels);
366
        if (track->enc->codec_id == CODEC_ID_PCM_U8 ||
367
            track->enc->codec_id == CODEC_ID_PCM_S8)
368
            put_be16(pb, 8); /* bits per sample */
369
        else
370
            put_be16(pb, 16);
371
        put_be16(pb, track->audio_vbr ? -2 : 0); /* compression ID */
372
    } else { /* reserved for mp4/3gp */
373
        put_be16(pb, 2);
374
        put_be16(pb, 16);
375
        put_be16(pb, 0);
376
    }
377

    
378
    put_be16(pb, 0); /* packet size (= 0) */
379
    put_be16(pb, track->timescale); /* Time scale */
380
    put_be16(pb, 0); /* Reserved */
381

    
382
    if(version == 1) { /* SoundDescription V1 extended info */
383
        put_be32(pb, track->enc->frame_size); /* Samples per packet */
384
        put_be32(pb, track->sampleSize / track->enc->channels); /* Bytes per packet */
385
        put_be32(pb, track->sampleSize); /* Bytes per frame */
386
        put_be32(pb, 2); /* Bytes per sample */
387
    }
388

    
389
    if(track->mode == MODE_MOV &&
390
       (track->enc->codec_id == CODEC_ID_AAC ||
391
        track->enc->codec_id == CODEC_ID_AMR_NB ||
392
        track->enc->codec_id == CODEC_ID_PCM_S24LE ||
393
        track->enc->codec_id == CODEC_ID_PCM_S32LE ||
394
        track->enc->codec_id == CODEC_ID_ALAC))
395
        mov_write_wave_tag(pb, track);
396
    else if(track->tag == MKTAG('m','p','4','a'))
397
        mov_write_esds_tag(pb, track);
398
    else if(track->enc->codec_id == CODEC_ID_AMR_NB)
399
        mov_write_amr_tag(pb, track);
400
    else if (track->enc->codec_id == CODEC_ID_ALAC)
401
        mov_write_extradata_tag(pb, track);
402
    else if(track->vosLen > 0)
403
        mov_write_glbl_tag(pb, track);
404

    
405
    return updateSize(pb, pos);
406
}
407

    
408
static int mov_write_d263_tag(ByteIOContext *pb)
409
{
410
    put_be32(pb, 0xf); /* size */
411
    put_tag(pb, "d263");
412
    put_tag(pb, "FFMP");
413
    put_byte(pb, 0); /* decoder version */
414
    /* FIXME use AVCodecContext level/profile, when encoder will set values */
415
    put_byte(pb, 0xa); /* level */
416
    put_byte(pb, 0); /* profile */
417
    return 0xf;
418
}
419

    
420
/* TODO: No idea about these values */
421
static int mov_write_svq3_tag(ByteIOContext *pb)
422
{
423
    put_be32(pb, 0x15);
424
    put_tag(pb, "SMI ");
425
    put_tag(pb, "SEQH");
426
    put_be32(pb, 0x5);
427
    put_be32(pb, 0xe2c0211d);
428
    put_be32(pb, 0xc0000000);
429
    put_byte(pb, 0);
430
    return 0x15;
431
}
432

    
433
static int mov_write_avcc_tag(ByteIOContext *pb, MOVTrack *track)
434
{
435
    offset_t pos = url_ftell(pb);
436

    
437
    put_be32(pb, 0);
438
    put_tag(pb, "avcC");
439
    ff_isom_write_avcc(pb, track->vosData, track->vosLen);
440
    return updateSize(pb, pos);
441
}
442

    
443
/* also used by all avid codecs (dv, imx, meridien) and their variants */
444
static int mov_write_avid_tag(ByteIOContext *pb, MOVTrack *track)
445
{
446
    int i;
447
    put_be32(pb, 24); /* size */
448
    put_tag(pb, "ACLR");
449
    put_tag(pb, "ACLR");
450
    put_tag(pb, "0001");
451
    put_be32(pb, 1); /* yuv 1 / rgb 2 ? */
452
    put_be32(pb, 0); /* unknown */
453

    
454
    put_be32(pb, 24); /* size */
455
    put_tag(pb, "APRG");
456
    put_tag(pb, "APRG");
457
    put_tag(pb, "0001");
458
    put_be32(pb, 1); /* unknown */
459
    put_be32(pb, 0); /* unknown */
460

    
461
    put_be32(pb, 120); /* size */
462
    put_tag(pb, "ARES");
463
    put_tag(pb, "ARES");
464
    put_tag(pb, "0001");
465
    put_be32(pb, AV_RB32(track->vosData + 0x28)); /* dnxhd cid, some id ? */
466
    put_be32(pb, track->enc->width);
467
    /* values below are based on samples created with quicktime and avid codecs */
468
    if (track->vosData[5] & 2) { // interlaced
469
        put_be32(pb, track->enc->height/2);
470
        put_be32(pb, 2); /* unknown */
471
        put_be32(pb, 0); /* unknown */
472
        put_be32(pb, 4); /* unknown */
473
    } else {
474
        put_be32(pb, track->enc->height);
475
        put_be32(pb, 1); /* unknown */
476
        put_be32(pb, 0); /* unknown */
477
        if (track->enc->height == 1080)
478
            put_be32(pb, 5); /* unknown */
479
        else
480
            put_be32(pb, 6); /* unknown */
481
    }
482
    /* padding */
483
    for (i = 0; i < 10; i++)
484
        put_be64(pb, 0);
485

    
486
    /* extra padding for stsd needed */
487
    put_be32(pb, 0);
488
    return 0;
489
}
490

    
491
static const AVCodecTag codec_3gp_tags[] = {
492
    { CODEC_ID_H263,   MKTAG('s','2','6','3') },
493
    { CODEC_ID_H264,   MKTAG('a','v','c','1') },
494
    { CODEC_ID_MPEG4,  MKTAG('m','p','4','v') },
495
    { CODEC_ID_AAC,    MKTAG('m','p','4','a') },
496
    { CODEC_ID_AMR_NB, MKTAG('s','a','m','r') },
497
    { CODEC_ID_AMR_WB, MKTAG('s','a','w','b') },
498
};
499

    
500
static const AVCodecTag mov_pix_fmt_tags[] = {
501
    { PIX_FMT_YUYV422, MKTAG('y','u','v','s') },
502
    { PIX_FMT_UYVY422, MKTAG('2','v','u','y') },
503
    { PIX_FMT_BGR555,  MKTAG('r','a','w',' ') },
504
    { PIX_FMT_RGB24,   MKTAG('r','a','w',' ') },
505
    { PIX_FMT_BGR32_1, MKTAG('r','a','w',' ') },
506
};
507

    
508
static const AVCodecTag codec_ipod_tags[] = {
509
    { CODEC_ID_H264,   MKTAG('a','v','c','1') },
510
    { CODEC_ID_MPEG4,  MKTAG('m','p','4','v') },
511
    { CODEC_ID_AAC,    MKTAG('m','p','4','a') },
512
    { CODEC_ID_ALAC,   MKTAG('a','l','a','c') },
513
};
514

    
515
static int mov_find_codec_tag(AVFormatContext *s, MOVTrack *track)
516
{
517
    int tag = track->enc->codec_tag;
518
    if (track->mode == MODE_MP4 || track->mode == MODE_PSP) {
519
        if (!codec_get_tag(ff_mp4_obj_type, track->enc->codec_id))
520
            return 0;
521
        if (track->enc->codec_id == CODEC_ID_H264)           tag = MKTAG('a','v','c','1');
522
        else if (track->enc->codec_type == CODEC_TYPE_VIDEO) tag = MKTAG('m','p','4','v');
523
        else if (track->enc->codec_type == CODEC_TYPE_AUDIO) tag = MKTAG('m','p','4','a');
524
    } else if (track->mode == MODE_IPOD) {
525
        tag = codec_get_tag(codec_ipod_tags, track->enc->codec_id);
526
        if (!match_ext(s->filename, "m4a") && !match_ext(s->filename, "m4v"))
527
            av_log(s, AV_LOG_WARNING, "Warning, extension is not .m4a nor .m4v "
528
                   "Quicktime/Ipod might not play the file\n");
529
    } else if (track->mode == MODE_3GP || track->mode == MODE_3G2) {
530
        tag = codec_get_tag(codec_3gp_tags, track->enc->codec_id);
531
    } else if (!tag || (track->enc->strict_std_compliance >= FF_COMPLIANCE_NORMAL &&
532
                        (tag == MKTAG('d','v','c','p') ||
533
                         track->enc->codec_id == CODEC_ID_RAWVIDEO))) {
534
        if (track->enc->codec_id == CODEC_ID_DVVIDEO) {
535
            if (track->enc->height == 480) /* NTSC */
536
                if  (track->enc->pix_fmt == PIX_FMT_YUV422P) tag = MKTAG('d','v','5','n');
537
                else                                         tag = MKTAG('d','v','c',' ');
538
            else if (track->enc->pix_fmt == PIX_FMT_YUV422P) tag = MKTAG('d','v','5','p');
539
            else if (track->enc->pix_fmt == PIX_FMT_YUV420P) tag = MKTAG('d','v','c','p');
540
            else                                             tag = MKTAG('d','v','p','p');
541
        } else if (track->enc->codec_id == CODEC_ID_RAWVIDEO) {
542
            tag = codec_get_tag(mov_pix_fmt_tags, track->enc->pix_fmt);
543
            if (!tag) // restore tag
544
                tag = track->enc->codec_tag;
545
        } else {
546
            if (track->enc->codec_type == CODEC_TYPE_VIDEO) {
547
                tag = codec_get_tag(codec_movvideo_tags, track->enc->codec_id);
548
                if (!tag) { // if no mac fcc found, try with Microsoft tags
549
                    tag = codec_get_tag(codec_bmp_tags, track->enc->codec_id);
550
                    if (tag)
551
                        av_log(s, AV_LOG_INFO, "Warning, using MS style video codec tag, "
552
                               "the file may be unplayable!\n");
553
                }
554
            } else if (track->enc->codec_type == CODEC_TYPE_AUDIO) {
555
                tag = codec_get_tag(codec_movaudio_tags, track->enc->codec_id);
556
                if (!tag) { // if no mac fcc found, try with Microsoft tags
557
                    int ms_tag = codec_get_tag(codec_wav_tags, track->enc->codec_id);
558
                    if (ms_tag) {
559
                        tag = MKTAG('m', 's', ((ms_tag >> 8) & 0xff), (ms_tag & 0xff));
560
                        av_log(s, AV_LOG_INFO, "Warning, using MS style audio codec tag, "
561
                               "the file may be unplayable!\n");
562
                    }
563
                }
564
            }
565
        }
566
    }
567
    return tag;
568
}
569

    
570
/** Write uuid atom.
571
 * Needed to make file play in iPods running newest firmware
572
 * goes after avcC atom in moov.trak.mdia.minf.stbl.stsd.avc1
573
 */
574
static int mov_write_uuid_tag_ipod(ByteIOContext *pb)
575
{
576
    put_be32(pb, 28);
577
    put_tag(pb, "uuid");
578
    put_be32(pb, 0x6b6840f2);
579
    put_be32(pb, 0x5f244fc5);
580
    put_be32(pb, 0xba39a51b);
581
    put_be32(pb, 0xcf0323f3);
582
    put_be32(pb, 0x0);
583
    return 28;
584
}
585

    
586
static int mov_write_video_tag(ByteIOContext *pb, MOVTrack *track)
587
{
588
    offset_t pos = url_ftell(pb);
589
    char compressor_name[32];
590

    
591
    put_be32(pb, 0); /* size */
592
    put_le32(pb, track->tag); // store it byteswapped
593
    put_be32(pb, 0); /* Reserved */
594
    put_be16(pb, 0); /* Reserved */
595
    put_be16(pb, 1); /* Data-reference index */
596

    
597
    put_be16(pb, 0); /* Codec stream version */
598
    put_be16(pb, 0); /* Codec stream revision (=0) */
599
    if (track->mode == MODE_MOV) {
600
        put_tag(pb, "FFMP"); /* Vendor */
601
        if(track->enc->codec_id == CODEC_ID_RAWVIDEO) {
602
            put_be32(pb, 0); /* Temporal Quality */
603
            put_be32(pb, 0x400); /* Spatial Quality = lossless*/
604
        } else {
605
            put_be32(pb, 0x200); /* Temporal Quality = normal */
606
            put_be32(pb, 0x200); /* Spatial Quality = normal */
607
        }
608
    } else {
609
        put_be32(pb, 0); /* Reserved */
610
        put_be32(pb, 0); /* Reserved */
611
        put_be32(pb, 0); /* Reserved */
612
    }
613
    put_be16(pb, track->enc->width); /* Video width */
614
    put_be16(pb, track->enc->height); /* Video height */
615
    put_be32(pb, 0x00480000); /* Horizontal resolution 72dpi */
616
    put_be32(pb, 0x00480000); /* Vertical resolution 72dpi */
617
    put_be32(pb, 0); /* Data size (= 0) */
618
    put_be16(pb, 1); /* Frame count (= 1) */
619

    
620
    memset(compressor_name,0,32);
621
    /* FIXME not sure, ISO 14496-1 draft where it shall be set to 0 */
622
    if (track->mode == MODE_MOV && track->enc->codec && track->enc->codec->name)
623
        strncpy(compressor_name,track->enc->codec->name,31);
624
    put_byte(pb, strlen(compressor_name));
625
    put_buffer(pb, compressor_name, 31);
626

    
627
    if (track->mode == MODE_MOV && track->enc->bits_per_sample)
628
        put_be16(pb, track->enc->bits_per_sample);
629
    else
630
        put_be16(pb, 0x18); /* Reserved */
631
    put_be16(pb, 0xffff); /* Reserved */
632
    if(track->tag == MKTAG('m','p','4','v'))
633
        mov_write_esds_tag(pb, track);
634
    else if(track->enc->codec_id == CODEC_ID_H263)
635
        mov_write_d263_tag(pb);
636
    else if(track->enc->codec_id == CODEC_ID_SVQ3)
637
        mov_write_svq3_tag(pb);
638
    else if(track->enc->codec_id == CODEC_ID_DNXHD)
639
        mov_write_avid_tag(pb, track);
640
    else if(track->enc->codec_id == CODEC_ID_H264) {
641
        mov_write_avcc_tag(pb, track);
642
        if(track->mode == MODE_IPOD)
643
            mov_write_uuid_tag_ipod(pb);
644
    } else if(track->vosLen > 0)
645
        mov_write_glbl_tag(pb, track);
646

    
647
    return updateSize(pb, pos);
648
}
649

    
650
static int mov_write_stsd_tag(ByteIOContext *pb, MOVTrack *track)
651
{
652
    offset_t pos = url_ftell(pb);
653
    put_be32(pb, 0); /* size */
654
    put_tag(pb, "stsd");
655
    put_be32(pb, 0); /* version & flags */
656
    put_be32(pb, 1); /* entry count */
657
    if (track->enc->codec_type == CODEC_TYPE_VIDEO)
658
        mov_write_video_tag(pb, track);
659
    else if (track->enc->codec_type == CODEC_TYPE_AUDIO)
660
        mov_write_audio_tag(pb, track);
661
    return updateSize(pb, pos);
662
}
663

    
664
static int mov_write_ctts_tag(ByteIOContext *pb, MOVTrack *track)
665
{
666
    MOV_stts_t *ctts_entries;
667
    uint32_t entries = 0;
668
    uint32_t atom_size;
669
    int i;
670

    
671
    ctts_entries = av_malloc((track->entry + 1) * sizeof(*ctts_entries)); /* worst case */
672
    ctts_entries[0].count = 1;
673
    ctts_entries[0].duration = track->cluster[0].cts;
674
    for (i=1; i<track->entry; i++) {
675
        if (track->cluster[i].cts == ctts_entries[entries].duration) {
676
            ctts_entries[entries].count++; /* compress */
677
        } else {
678
            entries++;
679
            ctts_entries[entries].duration = track->cluster[i].cts;
680
            ctts_entries[entries].count = 1;
681
        }
682
    }
683
    entries++; /* last one */
684
    atom_size = 16 + (entries * 8);
685
    put_be32(pb, atom_size); /* size */
686
    put_tag(pb, "ctts");
687
    put_be32(pb, 0); /* version & flags */
688
    put_be32(pb, entries); /* entry count */
689
    for (i=0; i<entries; i++) {
690
        put_be32(pb, ctts_entries[i].count);
691
        put_be32(pb, ctts_entries[i].duration);
692
    }
693
    av_free(ctts_entries);
694
    return atom_size;
695
}
696

    
697
/* Time to sample atom */
698
static int mov_write_stts_tag(ByteIOContext *pb, MOVTrack *track)
699
{
700
    MOV_stts_t *stts_entries;
701
    uint32_t entries = -1;
702
    uint32_t atom_size;
703
    int i;
704

    
705
    if (track->enc->codec_type == CODEC_TYPE_AUDIO && !track->audio_vbr) {
706
        stts_entries = av_malloc(sizeof(*stts_entries)); /* one entry */
707
        stts_entries[0].count = track->sampleCount;
708
        stts_entries[0].duration = 1;
709
        entries = 1;
710
    } else {
711
        stts_entries = av_malloc(track->entry * sizeof(*stts_entries)); /* worst case */
712
        for (i=0; i<track->entry; i++) {
713
            int64_t duration = i + 1 == track->entry ?
714
                track->trackDuration - track->cluster[i].dts + track->cluster[0].dts : /* readjusting */
715
                track->cluster[i+1].dts - track->cluster[i].dts;
716
            if (i && duration == stts_entries[entries].duration) {
717
                stts_entries[entries].count++; /* compress */
718
            } else {
719
                entries++;
720
                stts_entries[entries].duration = duration;
721
                stts_entries[entries].count = 1;
722
            }
723
        }
724
        entries++; /* last one */
725
    }
726
    atom_size = 16 + (entries * 8);
727
    put_be32(pb, atom_size); /* size */
728
    put_tag(pb, "stts");
729
    put_be32(pb, 0); /* version & flags */
730
    put_be32(pb, entries); /* entry count */
731
    for (i=0; i<entries; i++) {
732
        put_be32(pb, stts_entries[i].count);
733
        put_be32(pb, stts_entries[i].duration);
734
    }
735
    av_free(stts_entries);
736
    return atom_size;
737
}
738

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

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

    
750
    return 28;
751
}
752

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

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

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

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

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

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

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

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

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

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

    
869
    if(version!=0 && track->mode == MODE_MOV){
870
        av_log(NULL, AV_LOG_ERROR,
871
            "FATAL error, file duration too long for timebase, this file will not be\n"
872
            "playable with quicktime. Choose a different timebase or a different\n"
873
            "container format\n");
874
    }
875

    
876
    return 32;
877
}
878

    
879
static int mov_write_mdia_tag(ByteIOContext *pb, MOVTrack *track)
880
{
881
    offset_t pos = url_ftell(pb);
882
    put_be32(pb, 0); /* size */
883
    put_tag(pb, "mdia");
884
    mov_write_mdhd_tag(pb, track);
885
    mov_write_hdlr_tag(pb, track);
886
    mov_write_minf_tag(pb, track);
887
    return updateSize(pb, pos);
888
}
889

    
890
static int mov_write_tkhd_tag(ByteIOContext *pb, MOVTrack *track)
891
{
892
    int64_t duration = av_rescale_rnd(track->trackDuration, globalTimescale, track->timescale, AV_ROUND_UP);
893
    int version = duration < INT32_MAX ? 0 : 1;
894

    
895
    (version == 1) ? put_be32(pb, 104) : put_be32(pb, 92); /* size */
896
    put_tag(pb, "tkhd");
897
    put_byte(pb, version);
898
    put_be24(pb, 0xf); /* flags (track enabled) */
899
    if (version == 1) {
900
        put_be64(pb, track->time);
901
        put_be64(pb, track->time);
902
    } else {
903
        put_be32(pb, track->time); /* creation time */
904
        put_be32(pb, track->time); /* modification time */
905
    }
906
    put_be32(pb, track->trackID); /* track-id */
907
    put_be32(pb, 0); /* reserved */
908
    (version == 1) ? put_be64(pb, duration) : put_be32(pb, duration);
909

    
910
    put_be32(pb, 0); /* reserved */
911
    put_be32(pb, 0); /* reserved */
912
    put_be32(pb, 0x0); /* reserved (Layer & Alternate group) */
913
    /* Volume, only for audio */
914
    if(track->enc->codec_type == CODEC_TYPE_AUDIO)
915
        put_be16(pb, 0x0100);
916
    else
917
        put_be16(pb, 0);
918
    put_be16(pb, 0); /* reserved */
919

    
920
    /* Matrix structure */
921
    put_be32(pb, 0x00010000); /* reserved */
922
    put_be32(pb, 0x0); /* reserved */
923
    put_be32(pb, 0x0); /* reserved */
924
    put_be32(pb, 0x0); /* reserved */
925
    put_be32(pb, 0x00010000); /* reserved */
926
    put_be32(pb, 0x0); /* reserved */
927
    put_be32(pb, 0x0); /* reserved */
928
    put_be32(pb, 0x0); /* reserved */
929
    put_be32(pb, 0x40000000); /* reserved */
930

    
931
    /* Track width and height, for visual only */
932
    if(track->enc->codec_type == CODEC_TYPE_VIDEO) {
933
        double sample_aspect_ratio = av_q2d(track->enc->sample_aspect_ratio);
934
        if(!sample_aspect_ratio) sample_aspect_ratio = 1;
935
        put_be32(pb, sample_aspect_ratio * track->enc->width*0x10000);
936
        put_be32(pb, track->enc->height*0x10000);
937
    }
938
    else {
939
        put_be32(pb, 0);
940
        put_be32(pb, 0);
941
    }
942
    return 0x5c;
943
}
944

    
945
// This box seems important for the psp playback ... without it the movie seems to hang
946
static int mov_write_edts_tag(ByteIOContext *pb, MOVTrack *track)
947
{
948
    put_be32(pb, 0x24); /* size  */
949
    put_tag(pb, "edts");
950
    put_be32(pb, 0x1c); /* size  */
951
    put_tag(pb, "elst");
952
    put_be32(pb, 0x0);
953
    put_be32(pb, 0x1);
954

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

    
957
    put_be32(pb, track->cluster[0].cts); /* first pts is cts since dts is 0 */
958
    put_be32(pb, 0x00010000);
959
    return 0x24;
960
}
961

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

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

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

    
1011
static int mov_write_mvhd_tag(ByteIOContext *pb, MOVContext *mov)
1012
{
1013
    int maxTrackID = 1, i;
1014
    int64_t maxTrackLenTemp, maxTrackLen = 0;
1015
    int version;
1016

    
1017
    for (i=0; i<mov->nb_streams; i++) {
1018
        if(mov->tracks[i].entry > 0) {
1019
            maxTrackLenTemp = av_rescale_rnd(mov->tracks[i].trackDuration, globalTimescale, mov->tracks[i].timescale, AV_ROUND_UP);
1020
            if(maxTrackLen < maxTrackLenTemp)
1021
                maxTrackLen = maxTrackLenTemp;
1022
            if(maxTrackID < mov->tracks[i].trackID)
1023
                maxTrackID = mov->tracks[i].trackID;
1024
        }
1025
    }
1026

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

    
1042
    put_be32(pb, 0x00010000); /* reserved (preferred rate) 1.0 = normal */
1043
    put_be16(pb, 0x0100); /* reserved (preferred volume) 1.0 = normal */
1044
    put_be16(pb, 0); /* reserved */
1045
    put_be32(pb, 0); /* reserved */
1046
    put_be32(pb, 0); /* reserved */
1047

    
1048
    /* Matrix structure */
1049
    put_be32(pb, 0x00010000); /* reserved */
1050
    put_be32(pb, 0x0); /* reserved */
1051
    put_be32(pb, 0x0); /* reserved */
1052
    put_be32(pb, 0x0); /* reserved */
1053
    put_be32(pb, 0x00010000); /* reserved */
1054
    put_be32(pb, 0x0); /* reserved */
1055
    put_be32(pb, 0x0); /* reserved */
1056
    put_be32(pb, 0x0); /* reserved */
1057
    put_be32(pb, 0x40000000); /* reserved */
1058

    
1059
    put_be32(pb, 0); /* reserved (preview time) */
1060
    put_be32(pb, 0); /* reserved (preview duration) */
1061
    put_be32(pb, 0); /* reserved (poster time) */
1062
    put_be32(pb, 0); /* reserved (selection time) */
1063
    put_be32(pb, 0); /* reserved (selection duration) */
1064
    put_be32(pb, 0); /* reserved (current time) */
1065
    put_be32(pb, maxTrackID+1); /* Next track id */
1066
    return 0x6c;
1067
}
1068

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

    
1085
/* helper function to write a data tag with the specified string as data */
1086
static int mov_write_string_data_tag(ByteIOContext *pb, const char *data, int long_style)
1087
{
1088
    if(long_style){
1089
        offset_t pos = url_ftell(pb);
1090
        put_be32(pb, 0); /* size */
1091
        put_tag(pb, "data");
1092
        put_be32(pb, 1);
1093
        put_be32(pb, 0);
1094
        put_buffer(pb, data, strlen(data));
1095
        return updateSize(pb, pos);
1096
    }else{
1097
        put_be16(pb, strlen(data)); /* string length */
1098
        put_be16(pb, 0);
1099
        put_buffer(pb, data, strlen(data));
1100
        return strlen(data) + 4;
1101
    }
1102
}
1103

    
1104
static int mov_write_string_tag(ByteIOContext *pb, const char *name, const char *value, int long_style){
1105
    int size = 0;
1106
    if (value && value[0]) {
1107
        offset_t pos = url_ftell(pb);
1108
        put_be32(pb, 0); /* size */
1109
        put_tag(pb, name);
1110
        mov_write_string_data_tag(pb, value, long_style);
1111
        size= updateSize(pb, pos);
1112
    }
1113
    return size;
1114
}
1115

    
1116
/* iTunes year */
1117
static int mov_write_day_tag(ByteIOContext *pb, int year, int long_style)
1118
{
1119
    if(year){
1120
        char year_str[5];
1121
        snprintf(year_str, sizeof(year_str), "%04d", year);
1122
        return mov_write_string_tag(pb, "\251day", year_str, long_style);
1123
    }else
1124
        return 0;
1125
}
1126

    
1127
/* iTunes track number */
1128
static int mov_write_trkn_tag(ByteIOContext *pb, MOVContext *mov,
1129
                              AVFormatContext *s)
1130
{
1131
    int size = 0;
1132
    if (s->track) {
1133
        offset_t pos = url_ftell(pb);
1134
        put_be32(pb, 0); /* size */
1135
        put_tag(pb, "trkn");
1136
        {
1137
            offset_t pos = url_ftell(pb);
1138
            put_be32(pb, 0); /* size */
1139
            put_tag(pb, "data");
1140
            put_be32(pb, 0);        // 8 bytes empty
1141
            put_be32(pb, 0);
1142
            put_be16(pb, 0);        // empty
1143
            put_be16(pb, s->track); // track number
1144
            put_be16(pb, 0);        // total track number
1145
            put_be16(pb, 0);        // empty
1146
            updateSize(pb, pos);
1147
        }
1148
        size = updateSize(pb, pos);
1149
    }
1150
    return size;
1151
}
1152

    
1153
/* iTunes meta data list */
1154
static int mov_write_ilst_tag(ByteIOContext *pb, MOVContext *mov,
1155
                              AVFormatContext *s)
1156
{
1157
    offset_t pos = url_ftell(pb);
1158
    put_be32(pb, 0); /* size */
1159
    put_tag(pb, "ilst");
1160
    mov_write_string_tag(pb, "\251nam", s->title         , 1);
1161
    mov_write_string_tag(pb, "\251ART", s->author        , 1);
1162
    mov_write_string_tag(pb, "\251wrt", s->author        , 1);
1163
    mov_write_string_tag(pb, "\251alb", s->album         , 1);
1164
    mov_write_day_tag(pb, s->year ,1);
1165
    mov_write_string_tag(pb, "\251too", LIBAVFORMAT_IDENT, 1);
1166
    mov_write_string_tag(pb, "\251cmt", s->comment       , 1);
1167
    mov_write_string_tag(pb, "\251gen", s->genre         , 1);
1168
    mov_write_trkn_tag(pb, mov, s);
1169
    return updateSize(pb, pos);
1170
}
1171

    
1172
/* iTunes meta data tag */
1173
static int mov_write_meta_tag(ByteIOContext *pb, MOVContext *mov,
1174
                              AVFormatContext *s)
1175
{
1176
    int size = 0;
1177

    
1178
    // only save meta tag if required
1179
    if (s->title[0] || s->author[0] || s->album[0] || s->year ||
1180
        s->comment[0] || s->genre[0] || s->track) {
1181
        offset_t pos = url_ftell(pb);
1182
        put_be32(pb, 0); /* size */
1183
        put_tag(pb, "meta");
1184
        put_be32(pb, 0);
1185
        mov_write_itunes_hdlr_tag(pb, mov, s);
1186
        mov_write_ilst_tag(pb, mov, s);
1187
        size = updateSize(pb, pos);
1188
    }
1189
    return size;
1190
}
1191

    
1192
static int utf8len(const uint8_t *b)
1193
{
1194
    int len=0;
1195
    int val;
1196
    while(*b){
1197
        GET_UTF8(val, *b++, return -1;)
1198
        len++;
1199
    }
1200
    return len;
1201
}
1202

    
1203
static int ascii_to_wc(ByteIOContext *pb, const uint8_t *b)
1204
{
1205
    int val;
1206
    while(*b){
1207
        GET_UTF8(val, *b++, return -1;)
1208
        put_be16(pb, val);
1209
    }
1210
    put_be16(pb, 0x00);
1211
    return 0;
1212
}
1213

    
1214
static uint16_t language_code(const char *str)
1215
{
1216
    return (((str[0]-0x60) & 0x1F) << 10) + (((str[1]-0x60) & 0x1F) << 5) + ((str[2]-0x60) & 0x1F);
1217
}
1218

    
1219
static int mov_write_3gp_udta_tag(ByteIOContext *pb, AVFormatContext *s,
1220
                                  const char *tag, const char *str)
1221
{
1222
    offset_t pos = url_ftell(pb);
1223
    if (!utf8len(str))
1224
        return 0;
1225
    put_be32(pb, 0);   /* size */
1226
    put_tag (pb, tag); /* type */
1227
    put_be32(pb, 0);   /* version + flags */
1228
    if (!strcmp(tag, "yrrc"))
1229
        put_be16(pb, s->year);
1230
    else {
1231
        put_be16(pb, language_code("eng")); /* language */
1232
        ascii_to_wc(pb, str);
1233
        if (!strcmp(tag, "albm") && s->year)
1234
            put_byte(pb, s->year);
1235
    }
1236
    return updateSize(pb, pos);
1237
}
1238

    
1239
static int mov_write_udta_tag(ByteIOContext *pb, MOVContext *mov,
1240
                              AVFormatContext *s)
1241
{
1242
    int i;
1243
    int bitexact = 0;
1244

    
1245
    for (i = 0; i < s->nb_streams; i++)
1246
        if (mov->tracks[i].enc->flags & CODEC_FLAG_BITEXACT) {
1247
            bitexact = 1;
1248
            break;
1249
        }
1250

    
1251
    if (!bitexact && (s->title[0] || s->author[0] || s->album[0] || s->year ||
1252
                      s->comment[0] || s->genre[0]  || s->track)) {
1253
        offset_t pos = url_ftell(pb);
1254

    
1255
        put_be32(pb, 0); /* size */
1256
        put_tag(pb, "udta");
1257

    
1258
        if (mov->mode == MODE_3GP || mov->mode == MODE_3G2) {
1259
            mov_write_3gp_udta_tag(pb, s, "titl", s->title);
1260
            mov_write_3gp_udta_tag(pb, s, "auth", s->author);
1261
            mov_write_3gp_udta_tag(pb, s, "gnre", s->genre);
1262
            mov_write_3gp_udta_tag(pb, s, "dscp", s->comment);
1263
            mov_write_3gp_udta_tag(pb, s, "albm", s->album);
1264
            mov_write_3gp_udta_tag(pb, s, "yrrc", "nil");
1265
        } else if (mov->mode == MODE_MOV) { // the title field breaks gtkpod with mp4 and my suspicion is that stuff is not valid in mp4
1266
            mov_write_string_tag(pb, "\251nam", s->title         , 0);
1267
            mov_write_string_tag(pb, "\251aut", s->author        , 0);
1268
            mov_write_string_tag(pb, "\251alb", s->album         , 0);
1269
            mov_write_day_tag(pb, s->year, 0);
1270
            mov_write_string_tag(pb, "\251enc", LIBAVFORMAT_IDENT, 0);
1271
            mov_write_string_tag(pb, "\251des", s->comment       , 0);
1272
            mov_write_string_tag(pb, "\251gen", s->genre         , 0);
1273
        } else {
1274
            /* iTunes meta data */
1275
            mov_write_meta_tag(pb, mov, s);
1276
        }
1277
        return updateSize(pb, pos);
1278
    }
1279

    
1280
    return 0;
1281
}
1282

    
1283
static void mov_write_psp_udta_tag(ByteIOContext *pb,
1284
                                  const char *str, const char *lang, int type)
1285
{
1286
    int len = utf8len(str)+1;
1287
    if(len<=0)
1288
        return;
1289
    put_be16(pb, len*2+10);            /* size */
1290
    put_be32(pb, type);                /* type */
1291
    put_be16(pb, language_code(lang)); /* language */
1292
    put_be16(pb, 0x01);                /* ? */
1293
    ascii_to_wc(pb, str);
1294
}
1295

    
1296
static int mov_write_uuidusmt_tag(ByteIOContext *pb, AVFormatContext *s)
1297
{
1298
    offset_t pos, pos2;
1299

    
1300
    if (s->title[0]) {
1301
        pos = url_ftell(pb);
1302
        put_be32(pb, 0); /* size placeholder*/
1303
        put_tag(pb, "uuid");
1304
        put_tag(pb, "USMT");
1305
        put_be32(pb, 0x21d24fce); /* 96 bit UUID */
1306
        put_be32(pb, 0xbb88695c);
1307
        put_be32(pb, 0xfac9c740);
1308

    
1309
        pos2 = url_ftell(pb);
1310
        put_be32(pb, 0); /* size placeholder*/
1311
        put_tag(pb, "MTDT");
1312
        put_be16(pb, 4);
1313

    
1314
        // ?
1315
        put_be16(pb, 0x0C);                 /* size */
1316
        put_be32(pb, 0x0B);                 /* type */
1317
        put_be16(pb, language_code("und")); /* language */
1318
        put_be16(pb, 0x0);                  /* ? */
1319
        put_be16(pb, 0x021C);               /* data */
1320

    
1321
        mov_write_psp_udta_tag(pb, LIBAVCODEC_IDENT,      "eng", 0x04);
1322
        mov_write_psp_udta_tag(pb, s->title,              "eng", 0x01);
1323
//        snprintf(dt,32,"%04d/%02d/%02d %02d:%02d:%02d",t_st->tm_year+1900,t_st->tm_mon+1,t_st->tm_mday,t_st->tm_hour,t_st->tm_min,t_st->tm_sec);
1324
        mov_write_psp_udta_tag(pb, "2006/04/01 11:11:11", "und", 0x03);
1325

    
1326
        updateSize(pb, pos2);
1327
        return updateSize(pb, pos);
1328
    }
1329

    
1330
    return 0;
1331
}
1332

    
1333
static int mov_write_moov_tag(ByteIOContext *pb, MOVContext *mov,
1334
                              AVFormatContext *s)
1335
{
1336
    int i;
1337
    offset_t pos = url_ftell(pb);
1338
    put_be32(pb, 0); /* size placeholder*/
1339
    put_tag(pb, "moov");
1340
    mov->timescale = globalTimescale;
1341

    
1342
    for (i=0; i<mov->nb_streams; i++) {
1343
        if(mov->tracks[i].entry <= 0) continue;
1344

    
1345
        mov->tracks[i].time = mov->time;
1346
        mov->tracks[i].trackID = i+1;
1347
    }
1348

    
1349
    mov_write_mvhd_tag(pb, mov);
1350
    //mov_write_iods_tag(pb, mov);
1351
    for (i=0; i<mov->nb_streams; i++) {
1352
        if(mov->tracks[i].entry > 0) {
1353
            mov_write_trak_tag(pb, &(mov->tracks[i]));
1354
        }
1355
    }
1356

    
1357
    if (mov->mode == MODE_PSP)
1358
        mov_write_uuidusmt_tag(pb, s);
1359
    else
1360
        mov_write_udta_tag(pb, mov, s);
1361

    
1362
    return updateSize(pb, pos);
1363
}
1364

    
1365
static int mov_write_mdat_tag(ByteIOContext *pb, MOVContext *mov)
1366
{
1367
    put_be32(pb, 8);    // placeholder for extended size field (64 bit)
1368
    put_tag(pb, mov->mode == MODE_MOV ? "wide" : "free");
1369

    
1370
    mov->mdat_pos = url_ftell(pb);
1371
    put_be32(pb, 0); /* size placeholder*/
1372
    put_tag(pb, "mdat");
1373
    return 0;
1374
}
1375

    
1376
/* TODO: This needs to be more general */
1377
static void mov_write_ftyp_tag(ByteIOContext *pb, AVFormatContext *s)
1378
{
1379
    MOVContext *mov = s->priv_data;
1380
    int i;
1381

    
1382
    put_be32(pb, 0x14); /* size */
1383
    put_tag(pb, "ftyp");
1384

    
1385
    if (mov->mode == MODE_3GP)
1386
        put_tag(pb, "3gp4");
1387
    else if (mov->mode == MODE_3G2)
1388
        put_tag(pb, "3g2a");
1389
    else if (mov->mode == MODE_PSP)
1390
        put_tag(pb, "MSNV");
1391
    else if (mov->mode == MODE_MP4)
1392
        put_tag(pb, "isom");
1393
    else if (mov->mode == MODE_IPOD) {
1394
        for (i = 0; i < s->nb_streams; i++)
1395
            if (s->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO) {
1396
                put_tag(pb, "M4V ");
1397
                break;
1398
            }
1399
        if (i == s->nb_streams)
1400
            put_tag(pb, "M4A ");
1401
    } else
1402
        put_tag(pb, "qt  ");
1403

    
1404
    put_be32(pb, 0x200);
1405

    
1406
    if (mov->mode == MODE_3GP)
1407
        put_tag(pb, "3gp4");
1408
    else if (mov->mode == MODE_3G2)
1409
        put_tag(pb, "3g2a");
1410
    else if (mov->mode == MODE_PSP)
1411
        put_tag(pb, "MSNV");
1412
    else if (mov->mode == MODE_MP4)
1413
        put_tag(pb, "mp41");
1414
    else if (mov->mode == MODE_IPOD)
1415
        put_tag(pb, "isom");
1416
    else
1417
        put_tag(pb, "qt  ");
1418
}
1419

    
1420
static void mov_write_uuidprof_tag(ByteIOContext *pb, AVFormatContext *s)
1421
{
1422
    AVCodecContext *VideoCodec = s->streams[0]->codec;
1423
    AVCodecContext *AudioCodec = s->streams[1]->codec;
1424
    int AudioRate = AudioCodec->sample_rate;
1425
    int FrameRate = ((VideoCodec->time_base.den) * (0x10000))/ (VideoCodec->time_base.num);
1426
    int audio_kbitrate= AudioCodec->bit_rate / 1000;
1427
    int video_kbitrate= FFMIN(VideoCodec->bit_rate / 1000, 800 - audio_kbitrate);
1428

    
1429
    put_be32(pb, 0x94); /* size */
1430
    put_tag(pb, "uuid");
1431
    put_tag(pb, "PROF");
1432

    
1433
    put_be32(pb, 0x21d24fce); /* 96 bit UUID */
1434
    put_be32(pb, 0xbb88695c);
1435
    put_be32(pb, 0xfac9c740);
1436

    
1437
    put_be32(pb, 0x0);  /* ? */
1438
    put_be32(pb, 0x3);  /* 3 sections ? */
1439

    
1440
    put_be32(pb, 0x14); /* size */
1441
    put_tag(pb, "FPRF");
1442
    put_be32(pb, 0x0);  /* ? */
1443
    put_be32(pb, 0x0);  /* ? */
1444
    put_be32(pb, 0x0);  /* ? */
1445

    
1446
    put_be32(pb, 0x2c);  /* size */
1447
    put_tag(pb, "APRF");   /* audio */
1448
    put_be32(pb, 0x0);
1449
    put_be32(pb, 0x2);   /* TrackID */
1450
    put_tag(pb, "mp4a");
1451
    put_be32(pb, 0x20f);
1452
    put_be32(pb, 0x0);
1453
    put_be32(pb, audio_kbitrate);
1454
    put_be32(pb, audio_kbitrate);
1455
    put_be32(pb, AudioRate);
1456
    put_be32(pb, AudioCodec->channels);
1457

    
1458
    put_be32(pb, 0x34);  /* size */
1459
    put_tag(pb, "VPRF");   /* video */
1460
    put_be32(pb, 0x0);
1461
    put_be32(pb, 0x1);    /* TrackID */
1462
    if (VideoCodec->codec_id == CODEC_ID_H264) {
1463
        put_tag(pb, "avc1");
1464
        put_be16(pb, 0x014D);
1465
        put_be16(pb, 0x0015);
1466
    } else {
1467
        put_tag(pb, "mp4v");
1468
        put_be16(pb, 0x0000);
1469
        put_be16(pb, 0x0103);
1470
    }
1471
    put_be32(pb, 0x0);
1472
    put_be32(pb, video_kbitrate);
1473
    put_be32(pb, video_kbitrate);
1474
    put_be32(pb, FrameRate);
1475
    put_be32(pb, FrameRate);
1476
    put_be16(pb, VideoCodec->width);
1477
    put_be16(pb, VideoCodec->height);
1478
    put_be32(pb, 0x010001); /* ? */
1479
}
1480

    
1481
static int mov_write_header(AVFormatContext *s)
1482
{
1483
    ByteIOContext *pb = s->pb;
1484
    MOVContext *mov = s->priv_data;
1485
    int i;
1486

    
1487
    if (url_is_streamed(s->pb)) {
1488
        av_log(s, AV_LOG_ERROR, "muxer does not support non seekable output\n");
1489
        return -1;
1490
    }
1491

    
1492
    /* Default mode == MP4 */
1493
    mov->mode = MODE_MP4;
1494

    
1495
    if (s->oformat != NULL) {
1496
        if (!strcmp("3gp", s->oformat->name)) mov->mode = MODE_3GP;
1497
        else if (!strcmp("3g2", s->oformat->name)) mov->mode = MODE_3G2;
1498
        else if (!strcmp("mov", s->oformat->name)) mov->mode = MODE_MOV;
1499
        else if (!strcmp("psp", s->oformat->name)) mov->mode = MODE_PSP;
1500
        else if (!strcmp("ipod",s->oformat->name)) mov->mode = MODE_IPOD;
1501

    
1502
        mov_write_ftyp_tag(pb,s);
1503
        if (mov->mode == MODE_PSP) {
1504
            if (s->nb_streams != 2) {
1505
                av_log(s, AV_LOG_ERROR, "PSP mode need one video and one audio stream\n");
1506
                return -1;
1507
            }
1508
            mov_write_uuidprof_tag(pb,s);
1509
        }
1510
    }
1511

    
1512
    for(i=0; i<s->nb_streams; i++){
1513
        AVStream *st= s->streams[i];
1514
        MOVTrack *track= &mov->tracks[i];
1515

    
1516
        track->enc = st->codec;
1517
        track->language = ff_mov_iso639_to_lang(st->language, mov->mode != MODE_MOV);
1518
        track->mode = mov->mode;
1519
        track->tag = mov_find_codec_tag(s, track);
1520
        if (!track->tag) {
1521
            av_log(s, AV_LOG_ERROR, "track %d: could not find tag for codec\n", i);
1522
            return -1;
1523
        }
1524
        if(st->codec->codec_type == CODEC_TYPE_VIDEO){
1525
            track->timescale = st->codec->time_base.den;
1526
            av_set_pts_info(st, 64, 1, st->codec->time_base.den);
1527
            if (track->mode == MODE_MOV && track->timescale > 100000)
1528
                av_log(s, AV_LOG_WARNING,
1529
                       "WARNING codec timebase is very high. If duration is too long,\n"
1530
                       "file may not be playable by quicktime. Specify a shorter timebase\n"
1531
                       "or choose different container.\n");
1532
        }else if(st->codec->codec_type == CODEC_TYPE_AUDIO){
1533
            track->timescale = st->codec->sample_rate;
1534
            av_set_pts_info(st, 64, 1, st->codec->sample_rate);
1535
            if(!st->codec->frame_size){
1536
                av_log(s, AV_LOG_ERROR, "track %d: codec frame size is not set\n", i);
1537
                return -1;
1538
            }else if(st->codec->frame_size > 1){ /* assume compressed audio */
1539
                track->audio_vbr = 1;
1540
            }else{
1541
                track->sampleSize = (av_get_bits_per_sample(st->codec->codec_id) >> 3) * st->codec->channels;
1542
            }
1543
        }
1544
    }
1545

    
1546
    mov_write_mdat_tag(pb, mov);
1547
    mov->time = s->timestamp + 0x7C25B080; //1970 based -> 1904 based
1548
    mov->nb_streams = s->nb_streams;
1549

    
1550
    put_flush_packet(pb);
1551

    
1552
    return 0;
1553
}
1554

    
1555
static int mov_write_packet(AVFormatContext *s, AVPacket *pkt)
1556
{
1557
    MOVContext *mov = s->priv_data;
1558
    ByteIOContext *pb = s->pb;
1559
    MOVTrack *trk = &mov->tracks[pkt->stream_index];
1560
    AVCodecContext *enc = trk->enc;
1561
    unsigned int samplesInChunk = 0;
1562
    int size= pkt->size;
1563

    
1564
    if (url_is_streamed(s->pb)) return 0; /* Can't handle that */
1565
    if (!size) return 0; /* Discard 0 sized packets */
1566

    
1567
    if (enc->codec_id == CODEC_ID_AMR_NB) {
1568
        /* We must find out how many AMR blocks there are in one packet */
1569
        static uint16_t packed_size[16] =
1570
            {13, 14, 16, 18, 20, 21, 27, 32, 6, 0, 0, 0, 0, 0, 0, 0};
1571
        int len = 0;
1572

    
1573
        while (len < size && samplesInChunk < 100) {
1574
            len += packed_size[(pkt->data[len] >> 3) & 0x0F];
1575
            samplesInChunk++;
1576
        }
1577
        if(samplesInChunk > 1){
1578
            av_log(s, AV_LOG_ERROR, "fatal error, input is not a single packet, implement a AVParser for it\n");
1579
            return -1;
1580
        }
1581
    } else if (trk->sampleSize)
1582
        samplesInChunk = size/trk->sampleSize;
1583
    else
1584
        samplesInChunk = 1;
1585

    
1586
    /* copy extradata if it exists */
1587
    if (trk->vosLen == 0 && enc->extradata_size > 0) {
1588
        trk->vosLen = enc->extradata_size;
1589
        trk->vosData = av_malloc(trk->vosLen);
1590
        memcpy(trk->vosData, enc->extradata, trk->vosLen);
1591
    }
1592

    
1593
    if (enc->codec_id == CODEC_ID_H264 && trk->vosLen > 0 && *(uint8_t *)trk->vosData != 1) {
1594
        /* from x264 or from bytestream h264 */
1595
        /* nal reformating needed */
1596
        int ret = ff_avc_parse_nal_units(pkt->data, &pkt->data, &pkt->size);
1597
        if (ret < 0)
1598
            return ret;
1599
        assert(pkt->size);
1600
        size = pkt->size;
1601
    } else if (enc->codec_id == CODEC_ID_DNXHD && !trk->vosLen) {
1602
        /* copy frame header to create needed atoms */
1603
        if (size < 640)
1604
            return -1;
1605
        trk->vosLen = 640;
1606
        trk->vosData = av_malloc(trk->vosLen);
1607
        memcpy(trk->vosData, pkt->data, 640);
1608
    }
1609

    
1610
    if (!(trk->entry % MOV_INDEX_CLUSTER_SIZE)) {
1611
        trk->cluster = av_realloc(trk->cluster, (trk->entry + MOV_INDEX_CLUSTER_SIZE) * sizeof(*trk->cluster));
1612
        if (!trk->cluster)
1613
            return -1;
1614
    }
1615

    
1616
    trk->cluster[trk->entry].pos = url_ftell(pb);
1617
    trk->cluster[trk->entry].samplesInChunk = samplesInChunk;
1618
    trk->cluster[trk->entry].size = size;
1619
    trk->cluster[trk->entry].entries = samplesInChunk;
1620
    trk->cluster[trk->entry].dts = pkt->dts;
1621
    trk->trackDuration = pkt->dts - trk->cluster[0].dts + pkt->duration;
1622

    
1623
    if (pkt->pts == AV_NOPTS_VALUE) {
1624
        av_log(s, AV_LOG_WARNING, "pts has no value\n");
1625
        pkt->pts = pkt->dts;
1626
    }
1627
    if (pkt->dts != pkt->pts)
1628
        trk->hasBframes = 1;
1629
    trk->cluster[trk->entry].cts = pkt->pts - pkt->dts;
1630
    trk->cluster[trk->entry].key_frame = !!(pkt->flags & PKT_FLAG_KEY);
1631
    if(trk->cluster[trk->entry].key_frame)
1632
        trk->hasKeyframes++;
1633
    trk->entry++;
1634
    trk->sampleCount += samplesInChunk;
1635
    mov->mdat_size += size;
1636

    
1637
    put_buffer(pb, pkt->data, size);
1638

    
1639
    put_flush_packet(pb);
1640
    return 0;
1641
}
1642

    
1643
static int mov_write_trailer(AVFormatContext *s)
1644
{
1645
    MOVContext *mov = s->priv_data;
1646
    ByteIOContext *pb = s->pb;
1647
    int res = 0;
1648
    int i;
1649

    
1650
    offset_t moov_pos = url_ftell(pb);
1651

    
1652
    /* Write size of mdat tag */
1653
    if (mov->mdat_size+8 <= UINT32_MAX) {
1654
        url_fseek(pb, mov->mdat_pos, SEEK_SET);
1655
        put_be32(pb, mov->mdat_size+8);
1656
    } else {
1657
        /* overwrite 'wide' placeholder atom */
1658
        url_fseek(pb, mov->mdat_pos - 8, SEEK_SET);
1659
        put_be32(pb, 1); /* special value: real atom size will be 64 bit value after tag field */
1660
        put_tag(pb, "mdat");
1661
        put_be64(pb, mov->mdat_size+16);
1662
    }
1663
    url_fseek(pb, moov_pos, SEEK_SET);
1664

    
1665
    mov_write_moov_tag(pb, mov, s);
1666

    
1667
    for (i=0; i<mov->nb_streams; i++) {
1668
        av_freep(&mov->tracks[i].cluster);
1669

    
1670
        if(mov->tracks[i].vosLen) av_free(mov->tracks[i].vosData);
1671

    
1672
    }
1673

    
1674
    put_flush_packet(pb);
1675

    
1676
    return res;
1677
}
1678

    
1679
#ifdef CONFIG_MOV_MUXER
1680
AVOutputFormat mov_muxer = {
1681
    "mov",
1682
    NULL_IF_CONFIG_SMALL("MOV format"),
1683
    NULL,
1684
    "mov",
1685
    sizeof(MOVContext),
1686
    CODEC_ID_AAC,
1687
    CODEC_ID_MPEG4,
1688
    mov_write_header,
1689
    mov_write_packet,
1690
    mov_write_trailer,
1691
    .flags = AVFMT_GLOBALHEADER,
1692
    .codec_tag = (const AVCodecTag*[]){codec_movvideo_tags, codec_movaudio_tags, 0},
1693
};
1694
#endif
1695
#ifdef CONFIG_TGP_MUXER
1696
AVOutputFormat tgp_muxer = {
1697
    "3gp",
1698
    NULL_IF_CONFIG_SMALL("3GP format"),
1699
    NULL,
1700
    "3gp",
1701
    sizeof(MOVContext),
1702
    CODEC_ID_AMR_NB,
1703
    CODEC_ID_H263,
1704
    mov_write_header,
1705
    mov_write_packet,
1706
    mov_write_trailer,
1707
    .flags = AVFMT_GLOBALHEADER,
1708
    .codec_tag = (const AVCodecTag*[]){codec_3gp_tags, 0},
1709
};
1710
#endif
1711
#ifdef CONFIG_MP4_MUXER
1712
AVOutputFormat mp4_muxer = {
1713
    "mp4",
1714
    NULL_IF_CONFIG_SMALL("MP4 format"),
1715
    "application/mp4",
1716
    "mp4",
1717
    sizeof(MOVContext),
1718
    CODEC_ID_AAC,
1719
    CODEC_ID_MPEG4,
1720
    mov_write_header,
1721
    mov_write_packet,
1722
    mov_write_trailer,
1723
    .flags = AVFMT_GLOBALHEADER,
1724
    .codec_tag = (const AVCodecTag*[]){ff_mp4_obj_type, 0},
1725
};
1726
#endif
1727
#ifdef CONFIG_PSP_MUXER
1728
AVOutputFormat psp_muxer = {
1729
    "psp",
1730
    NULL_IF_CONFIG_SMALL("PSP MP4 format"),
1731
    NULL,
1732
    "mp4,psp",
1733
    sizeof(MOVContext),
1734
    CODEC_ID_AAC,
1735
    CODEC_ID_MPEG4,
1736
    mov_write_header,
1737
    mov_write_packet,
1738
    mov_write_trailer,
1739
    .flags = AVFMT_GLOBALHEADER,
1740
    .codec_tag = (const AVCodecTag*[]){ff_mp4_obj_type, 0},
1741
};
1742
#endif
1743
#ifdef CONFIG_TG2_MUXER
1744
AVOutputFormat tg2_muxer = {
1745
    "3g2",
1746
    NULL_IF_CONFIG_SMALL("3GP2 format"),
1747
    NULL,
1748
    "3g2",
1749
    sizeof(MOVContext),
1750
    CODEC_ID_AMR_NB,
1751
    CODEC_ID_H263,
1752
    mov_write_header,
1753
    mov_write_packet,
1754
    mov_write_trailer,
1755
    .flags = AVFMT_GLOBALHEADER,
1756
    .codec_tag = (const AVCodecTag*[]){codec_3gp_tags, 0},
1757
};
1758
#endif
1759
#ifdef CONFIG_IPOD_MUXER
1760
AVOutputFormat ipod_muxer = {
1761
    "ipod",
1762
    NULL_IF_CONFIG_SMALL("iPod H.264 MP4 format"),
1763
    "application/mp4",
1764
    "m4v,m4a",
1765
    sizeof(MOVContext),
1766
    CODEC_ID_AAC,
1767
    CODEC_ID_H264,
1768
    mov_write_header,
1769
    mov_write_packet,
1770
    mov_write_trailer,
1771
    .flags = AVFMT_GLOBALHEADER,
1772
    .codec_tag = (const AVCodecTag*[]){ff_mp4_obj_type, 0},
1773
};
1774
#endif