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

24
#include "movenc.h"
25
#include "avformat.h"
26
#include "avio_internal.h"
27
#include "riff.h"
28
#include "avio.h"
29
#include "isom.h"
30
#include "avc.h"
31
#include "libavcodec/get_bits.h"
32
#include "libavcodec/put_bits.h"
33 34
#include "internal.h"
#include "libavutil/avstring.h"
35
#include "libavutil/intfloat.h"
36
#include "libavutil/mathematics.h"
37
#include "libavutil/opt.h"
38
#include "libavutil/dict.h"
39
#include "rtpenc.h"
40
#include "mov_chan.h"
41

42 43 44
#undef NDEBUG
#include <assert.h>

45
static const AVOption options[] = {
46 47
    { "movflags", "MOV muxer flags", offsetof(MOVMuxContext, flags), AV_OPT_TYPE_FLAGS, {.dbl = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
    { "rtphint", "Add RTP hint tracks", 0, AV_OPT_TYPE_CONST, {.dbl = FF_MOV_FLAG_RTP_HINT}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
48 49 50
    { "empty_moov", "Make the initial moov atom empty (not supported by QuickTime)", 0, AV_OPT_TYPE_CONST, {.dbl = FF_MOV_FLAG_EMPTY_MOOV}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
    { "frag_keyframe", "Fragment at video keyframes", 0, AV_OPT_TYPE_CONST, {.dbl = FF_MOV_FLAG_FRAG_KEYFRAME}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
    { "separate_moof", "Write separate moof/mdat atoms for each track", 0, AV_OPT_TYPE_CONST, {.dbl = FF_MOV_FLAG_SEPARATE_MOOF}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
51
    { "frag_custom", "Flush fragments on caller requests", 0, AV_OPT_TYPE_CONST, {.dbl = FF_MOV_FLAG_FRAG_CUSTOM}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
52
    { "isml", "Create a live smooth streaming feed (for pushing to a publishing point)", 0, AV_OPT_TYPE_CONST, {.dbl = FF_MOV_FLAG_ISML}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
53
    FF_RTP_FLAG_OPTS(MOVMuxContext, rtp_flags),
54 55 56
    { "skip_iods", "Skip writing iods atom.", offsetof(MOVMuxContext, iods_skip), AV_OPT_TYPE_INT, {.dbl = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
    { "iods_audio_profile", "iods audio profile atom.", offsetof(MOVMuxContext, iods_audio_profile), AV_OPT_TYPE_INT, {.dbl = -1}, -1, 255, AV_OPT_FLAG_ENCODING_PARAM},
    { "iods_video_profile", "iods video profile atom.", offsetof(MOVMuxContext, iods_video_profile), AV_OPT_TYPE_INT, {.dbl = -1}, -1, 255, AV_OPT_FLAG_ENCODING_PARAM},
57 58
    { "frag_duration", "Maximum fragment duration", offsetof(MOVMuxContext, max_fragment_duration), AV_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
    { "frag_size", "Maximum fragment size", offsetof(MOVMuxContext, max_fragment_size), AV_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
59
    { "ism_lookahead", "Number of lookahead entries for ISM files", offsetof(MOVMuxContext, ism_lookahead), AV_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
60 61 62
    { NULL },
};

63 64 65 66 67 68
#define MOV_CLASS(flavor)\
static const AVClass flavor ## _muxer_class = {\
    .class_name = #flavor " muxer",\
    .item_name  = av_default_item_name,\
    .option     = options,\
    .version    = LIBAVUTIL_VERSION_INT,\
69 70
};

Diego Biurrun's avatar
Diego Biurrun committed
71
//FIXME support 64 bit variant with wide placeholders
72
static int64_t update_size(AVIOContext *pb, int64_t pos)
73
{
74
    int64_t curpos = avio_tell(pb);
75
    avio_seek(pb, pos, SEEK_SET);
76
    avio_wb32(pb, curpos - pos); /* rewrite size */
77
    avio_seek(pb, curpos, SEEK_SET);
78 79

    return curpos - pos;
80 81
}

82
/* Chunk offset atom */
83
static int mov_write_stco_tag(AVIOContext *pb, MOVTrack *track)
84 85
{
    int i;
Benjamin Larsson's avatar
Benjamin Larsson committed
86
    int mode64 = 0; //   use 32 bit size variant if possible
87
    int64_t pos = avio_tell(pb);
88
    avio_wb32(pb, 0); /* size */
89 90
    if (pos > UINT32_MAX) {
        mode64 = 1;
91
        ffio_wfourcc(pb, "co64");
92
    } else
93
        ffio_wfourcc(pb, "stco");
94 95
    avio_wb32(pb, 0); /* version & flags */
    avio_wb32(pb, track->entry); /* entry count */
96
    for (i=0; i<track->entry; i++) {
97
        if(mode64 == 1)
98
            avio_wb64(pb, track->cluster[i].pos);
99
        else
100
            avio_wb32(pb, track->cluster[i].pos);
101
    }
102
    return update_size(pb, pos);
103 104
}

105
/* Sample size atom */
106
static int mov_write_stsz_tag(AVIOContext *pb, MOVTrack *track)
107
{
108
    int equalChunks = 1;
109
    int i, j, entries = 0, tst = -1, oldtst = -1;
110

111
    int64_t pos = avio_tell(pb);
112
    avio_wb32(pb, 0); /* size */
113
    ffio_wfourcc(pb, "stsz");
114
    avio_wb32(pb, 0); /* version & flags */
115

116
    for (i=0; i<track->entry; i++) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
117
        tst = track->cluster[i].size/track->cluster[i].entries;
118 119
        if(oldtst != -1 && tst != oldtst) {
            equalChunks = 0;
120 121
        }
        oldtst = tst;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
122
        entries += track->cluster[i].entries;
123
    }
124 125
    if (equalChunks && track->entry) {
        int sSize = track->entry ? track->cluster[0].size/track->cluster[0].entries : 0;
Alex Converse's avatar
Alex Converse committed
126
        sSize = FFMAX(1, sSize); // adpcm mono case could make sSize == 0
127 128
        avio_wb32(pb, sSize); // sample size
        avio_wb32(pb, entries); // sample count
129
    }
130
    else {
131 132
        avio_wb32(pb, 0); // sample size
        avio_wb32(pb, entries); // sample count
133
        for (i=0; i<track->entry; i++) {
134
            for (j=0; j<track->cluster[i].entries; j++) {
135
                avio_wb32(pb, track->cluster[i].size /
Baptiste Coudurier's avatar
Baptiste Coudurier committed
136
                         track->cluster[i].entries);
137
            }
138 139
        }
    }
140
    return update_size(pb, pos);
141 142
}

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

149
    int64_t pos = avio_tell(pb);
150
    avio_wb32(pb, 0); /* size */
151
    ffio_wfourcc(pb, "stsc");
152
    avio_wb32(pb, 0); // version & flags
153
    entryPos = avio_tell(pb);
154
    avio_wb32(pb, track->entry); // entry count
155
    for (i=0; i<track->entry; i++) {
156
        if (oldval != track->cluster[i].samples_in_chunk)
157
        {
158
            avio_wb32(pb, i+1); // first chunk
159
            avio_wb32(pb, track->cluster[i].samples_in_chunk); // samples per chunk
160
            avio_wb32(pb, 0x1); // sample description index
161
            oldval = track->cluster[i].samples_in_chunk;
162
            index++;
163 164
        }
    }
165
    curpos = avio_tell(pb);
166
    avio_seek(pb, entryPos, SEEK_SET);
167
    avio_wb32(pb, index); // rewrite size
168
    avio_seek(pb, curpos, SEEK_SET);
169

170
    return update_size(pb, pos);
171 172
}

173
/* Sync sample atom */
174
static int mov_write_stss_tag(AVIOContext *pb, MOVTrack *track, uint32_t flag)
175
{
176
    int64_t curpos, entryPos;
177
    int i, index = 0;
178
    int64_t pos = avio_tell(pb);
179
    avio_wb32(pb, 0); // size
180
    ffio_wfourcc(pb, flag == MOV_SYNC_SAMPLE ? "stss" : "stps");
181
    avio_wb32(pb, 0); // version & flags
182
    entryPos = avio_tell(pb);
183
    avio_wb32(pb, track->entry); // entry count
184
    for (i=0; i<track->entry; i++) {
185
        if (track->cluster[i].flags & flag) {
186
            avio_wb32(pb, i+1);
187 188 189
            index++;
        }
    }
190
    curpos = avio_tell(pb);
191
    avio_seek(pb, entryPos, SEEK_SET);
192
    avio_wb32(pb, index); // rewrite size
193
    avio_seek(pb, curpos, SEEK_SET);
194
    return update_size(pb, pos);
195 196
}

197
static int mov_write_amr_tag(AVIOContext *pb, MOVTrack *track)
198
{
199
    avio_wb32(pb, 0x11); /* size */
200 201 202
    if (track->mode == MODE_MOV) ffio_wfourcc(pb, "samr");
    else                         ffio_wfourcc(pb, "damr");
    ffio_wfourcc(pb, "FFMP");
203
    avio_w8(pb, 0); /* decoder version */
Baptiste Coudurier's avatar
Baptiste Coudurier committed
204

205 206 207
    avio_wb16(pb, 0x81FF); /* Mode set (all modes for AMR_NB) */
    avio_w8(pb, 0x00); /* Mode change period (no restriction) */
    avio_w8(pb, 0x01); /* Frames per sample */
Baptiste Coudurier's avatar
Baptiste Coudurier committed
208 209 210
    return 0x11;
}

211
static int mov_write_ac3_tag(AVIOContext *pb, MOVTrack *track)
212 213 214 215 216 217
{
    GetBitContext gbc;
    PutBitContext pbc;
    uint8_t buf[3];
    int fscod, bsid, bsmod, acmod, lfeon, frmsizecod;

218
    if (track->vos_len < 7)
219 220
        return -1;

221
    avio_wb32(pb, 11);
222
    ffio_wfourcc(pb, "dac3");
223

224
    init_get_bits(&gbc, track->vos_data + 4, (track->vos_len - 4) * 8);
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
    fscod      = get_bits(&gbc, 2);
    frmsizecod = get_bits(&gbc, 6);
    bsid       = get_bits(&gbc, 5);
    bsmod      = get_bits(&gbc, 3);
    acmod      = get_bits(&gbc, 3);
    if (acmod == 2) {
        skip_bits(&gbc, 2); // dsurmod
    } else {
        if ((acmod & 1) && acmod != 1)
            skip_bits(&gbc, 2); // cmixlev
        if (acmod & 4)
            skip_bits(&gbc, 2); // surmixlev
    }
    lfeon = get_bits1(&gbc);

    init_put_bits(&pbc, buf, sizeof(buf));
    put_bits(&pbc, 2, fscod);
    put_bits(&pbc, 5, bsid);
    put_bits(&pbc, 3, bsmod);
    put_bits(&pbc, 3, acmod);
    put_bits(&pbc, 1, lfeon);
    put_bits(&pbc, 5, frmsizecod>>1); // bit_rate_code
    put_bits(&pbc, 5, 0); // reserved

    flush_put_bits(&pbc);
250
    avio_write(pb, buf, sizeof(buf));
251 252 253 254

    return 11;
}

Baptiste Coudurier's avatar
Baptiste Coudurier committed
255 256
/**
 * This function writes extradata "as is".
Diego Biurrun's avatar
Diego Biurrun committed
257
 * Extradata must be formatted like a valid atom (with size and tag).
Baptiste Coudurier's avatar
Baptiste Coudurier committed
258
 */
259
static int mov_write_extradata_tag(AVIOContext *pb, MOVTrack *track)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
260
{
261
    avio_write(pb, track->enc->extradata, track->enc->extradata_size);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
262 263 264
    return track->enc->extradata_size;
}

265
static int mov_write_enda_tag(AVIOContext *pb)
266
{
267
    avio_wb32(pb, 10);
268
    ffio_wfourcc(pb, "enda");
269
    avio_wb16(pb, 1); /* little endian */
270 271 272
    return 10;
}

273
static void put_descr(AVIOContext *pb, int tag, unsigned int size)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
274
{
275
    int i = 3;
276
    avio_w8(pb, tag);
Michael Niedermayer's avatar
Michael Niedermayer committed
277
    for(; i>0; i--)
278 279
        avio_w8(pb, (size>>(7*i)) | 0x80);
    avio_w8(pb, size & 0x7F);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
280 281
}

282
static int mov_write_esds_tag(AVIOContext *pb, MOVTrack *track) // Basic
Baptiste Coudurier's avatar
Baptiste Coudurier committed
283
{
284
    int64_t pos = avio_tell(pb);
285
    int decoder_specific_info_len = track->vos_len ? 5 + track->vos_len : 0;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
286

287
    avio_wb32(pb, 0); // size
288
    ffio_wfourcc(pb, "esds");
289
    avio_wb32(pb, 0); // Version
Baptiste Coudurier's avatar
Baptiste Coudurier committed
290 291

    // ES descriptor
292 293
    put_descr(pb, 0x03, 3 + 5+13 + decoder_specific_info_len + 5+1);
    avio_wb16(pb, track->track_id);
294
    avio_w8(pb, 0x00); // flags (= no flags)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
295 296

    // DecoderConfig descriptor
297
    put_descr(pb, 0x04, 13 + decoder_specific_info_len);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
298 299

    // Object type indication
300 301
    if ((track->enc->codec_id == CODEC_ID_MP2 ||
         track->enc->codec_id == CODEC_ID_MP3) &&
302
        track->enc->sample_rate > 24000)
303
        avio_w8(pb, 0x6B); // 11172-3
304
    else
305
        avio_w8(pb, ff_codec_get_tag(ff_mp4_obj_type, track->enc->codec_id));
Baptiste Coudurier's avatar
Baptiste Coudurier committed
306 307 308

    // the following fields is made of 6 bits to identify the streamtype (4 for video, 5 for audio)
    // plus 1 bit to indicate upstream and 1 bit set to 1 (reserved)
309
    if(track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
310
        avio_w8(pb, 0x15); // flags (= Audiostream)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
311
    else
312
        avio_w8(pb, 0x11); // flags (= Visualstream)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
313

314 315
    avio_w8(pb,  track->enc->rc_buffer_size>>(3+16));      // Buffersize DB (24 bits)
    avio_wb16(pb, (track->enc->rc_buffer_size>>3)&0xFFFF); // Buffersize DB
Baptiste Coudurier's avatar
Baptiste Coudurier committed
316

317
    avio_wb32(pb, FFMAX(track->enc->bit_rate, track->enc->rc_max_rate)); // maxbitrate (FIXME should be max rate in any 1 sec window)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
318
    if(track->enc->rc_max_rate != track->enc->rc_min_rate || track->enc->rc_min_rate==0)
319
        avio_wb32(pb, 0); // vbr
Baptiste Coudurier's avatar
Baptiste Coudurier committed
320
    else
321
        avio_wb32(pb, track->enc->rc_max_rate); // avg bitrate
Baptiste Coudurier's avatar
Baptiste Coudurier committed
322

323
    if (track->vos_len) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
324
        // DecoderSpecific info descriptor
325 326
        put_descr(pb, 0x05, track->vos_len);
        avio_write(pb, track->vos_data, track->vos_len);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
327 328 329
    }

    // SL descriptor
330
    put_descr(pb, 0x06, 1);
331
    avio_w8(pb, 0x02);
332
    return update_size(pb, pos);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
333 334
}

335 336 337 338 339 340 341 342
static int mov_pcm_le_gt16(enum CodecID codec_id)
{
    return codec_id == CODEC_ID_PCM_S24LE ||
           codec_id == CODEC_ID_PCM_S32LE ||
           codec_id == CODEC_ID_PCM_F32LE ||
           codec_id == CODEC_ID_PCM_F64LE;
}

343
static int mov_write_ms_tag(AVIOContext *pb, MOVTrack *track)
344
{
345
    int64_t pos = avio_tell(pb);
346 347
    avio_wb32(pb, 0);
    avio_wl32(pb, track->tag); // store it byteswapped
348
    track->enc->codec_tag = av_bswap16(track->tag >> 16);
349
    ff_put_wav_header(pb, track->enc);
350
    return update_size(pb, pos);
351 352
}

353 354 355 356 357 358 359 360 361
static int mov_write_wfex_tag(AVIOContext *pb, MOVTrack *track)
{
    int64_t pos = avio_tell(pb);
    avio_wb32(pb, 0);
    ffio_wfourcc(pb, "wfex");
    ff_put_wav_header(pb, track->enc);
    return update_size(pb, pos);
}

362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383
static int mov_write_chan_tag(AVIOContext *pb, MOVTrack *track)
{
    uint32_t layout_tag, bitmap;
    int64_t pos = avio_tell(pb);

    layout_tag = ff_mov_get_channel_layout_tag(track->enc->codec_id,
                                               track->enc->channel_layout,
                                               &bitmap);
    if (!layout_tag) {
        av_log(track->enc, AV_LOG_WARNING, "not writing 'chan' tag due to "
               "lack of channel information\n");
        return 0;
    }

    avio_wb32(pb, 0);           // Size
    ffio_wfourcc(pb, "chan");   // Type
    avio_w8(pb, 0);             // Version
    avio_wb24(pb, 0);           // Flags
    avio_wb32(pb, layout_tag);  // mChannelLayoutTag
    avio_wb32(pb, bitmap);      // mChannelBitmap
    avio_wb32(pb, 0);           // mNumberChannelDescriptions

384
    return update_size(pb, pos);
385 386
}

387
static int mov_write_wave_tag(AVIOContext *pb, MOVTrack *track)
388
{
389
    int64_t pos = avio_tell(pb);
390

391
    avio_wb32(pb, 0);     /* size */
392
    ffio_wfourcc(pb, "wave");
393

394
    avio_wb32(pb, 12);    /* size */
395
    ffio_wfourcc(pb, "frma");
396
    avio_wl32(pb, track->tag);
397

398
    if (track->enc->codec_id == CODEC_ID_AAC) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
399
        /* useless atom needed by mplayer, ipod, not needed by quicktime */
400
        avio_wb32(pb, 12); /* size */
401
        ffio_wfourcc(pb, "mp4a");
402
        avio_wb32(pb, 0);
403
        mov_write_esds_tag(pb, track);
404
    } else if (mov_pcm_le_gt16(track->enc->codec_id)) {
405
        mov_write_enda_tag(pb);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
406
    } else if (track->enc->codec_id == CODEC_ID_AMR_NB) {
407
        mov_write_amr_tag(pb, track);
408
    } else if (track->enc->codec_id == CODEC_ID_AC3) {
409
        mov_write_chan_tag(pb, track);
410
        mov_write_ac3_tag(pb, track);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
411 412
    } else if (track->enc->codec_id == CODEC_ID_ALAC) {
        mov_write_extradata_tag(pb, track);
413 414 415
    } else if (track->enc->codec_id == CODEC_ID_ADPCM_MS ||
               track->enc->codec_id == CODEC_ID_ADPCM_IMA_WAV) {
        mov_write_ms_tag(pb, track);
416
    }
417

418 419
    avio_wb32(pb, 8);     /* size */
    avio_wb32(pb, 0);     /* null tag */
420

421
    return update_size(pb, pos);
422 423
}

424
static int mov_write_glbl_tag(AVIOContext *pb, MOVTrack *track)
425
{
426
    avio_wb32(pb, track->vos_len + 8);
427
    ffio_wfourcc(pb, "glbl");
428 429
    avio_write(pb, track->vos_data, track->vos_len);
    return 8 + track->vos_len;
430 431
}

432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460
/**
 * Compute flags for 'lpcm' tag.
 * See CoreAudioTypes and AudioStreamBasicDescription at Apple.
 */
static int mov_get_lpcm_flags(enum CodecID codec_id)
{
    switch (codec_id) {
    case CODEC_ID_PCM_F32BE:
    case CODEC_ID_PCM_F64BE:
        return 11;
    case CODEC_ID_PCM_F32LE:
    case CODEC_ID_PCM_F64LE:
        return 9;
    case CODEC_ID_PCM_U8:
        return 10;
    case CODEC_ID_PCM_S16BE:
    case CODEC_ID_PCM_S24BE:
    case CODEC_ID_PCM_S32BE:
        return 14;
    case CODEC_ID_PCM_S8:
    case CODEC_ID_PCM_S16LE:
    case CODEC_ID_PCM_S24LE:
    case CODEC_ID_PCM_S32LE:
        return 12;
    default:
        return 0;
    }
}

461
static int mov_write_audio_tag(AVIOContext *pb, MOVTrack *track)
462
{
463
    int64_t pos = avio_tell(pb);
464 465 466 467
    int version = 0;
    uint32_t tag = track->tag;

    if (track->mode == MODE_MOV) {
468 469 470
        if (mov_get_lpcm_flags(track->enc->codec_id))
            tag = AV_RL32("lpcm");
        version = 2;
471
    }
472

473 474 475 476 477
    avio_wb32(pb, 0); /* size */
    avio_wl32(pb, tag); // store it byteswapped
    avio_wb32(pb, 0); /* Reserved */
    avio_wb16(pb, 0); /* Reserved */
    avio_wb16(pb, 1); /* Data-reference index, XXX  == 1 */
478

479
    /* SoundDescription */
480 481 482
    avio_wb16(pb, version); /* Version */
    avio_wb16(pb, 0); /* Revision level */
    avio_wb32(pb, 0); /* Reserved */
483

484
    if (version == 2) {
485 486 487 488 489 490
        avio_wb16(pb, 3);
        avio_wb16(pb, 16);
        avio_wb16(pb, 0xfffe);
        avio_wb16(pb, 0);
        avio_wb32(pb, 0x00010000);
        avio_wb32(pb, 72);
491
        avio_wb64(pb, av_double2int(track->enc->sample_rate));
492 493 494 495
        avio_wb32(pb, track->enc->channels);
        avio_wb32(pb, 0x7F000000);
        avio_wb32(pb, av_get_bits_per_sample(track->enc->codec_id));
        avio_wb32(pb, mov_get_lpcm_flags(track->enc->codec_id));
496
        avio_wb32(pb, track->sample_size);
497
        avio_wb32(pb, track->audio_vbr ? track->enc->frame_size : 1);
498
    } else {
499 500 501 502
        /* reserved for mp4/3gp */
        avio_wb16(pb, 2);
        avio_wb16(pb, 16);
        avio_wb16(pb, 0);
503

504
        avio_wb16(pb, 0); /* packet size (= 0) */
505
        avio_wb16(pb, track->enc->sample_rate);
506
        avio_wb16(pb, 0); /* Reserved */
507
    }
508

509 510
    if(track->mode == MODE_MOV &&
       (track->enc->codec_id == CODEC_ID_AAC ||
511
        track->enc->codec_id == CODEC_ID_AC3 ||
512
        track->enc->codec_id == CODEC_ID_AMR_NB ||
513
        track->enc->codec_id == CODEC_ID_ALAC ||
514 515
        track->enc->codec_id == CODEC_ID_ADPCM_MS ||
        track->enc->codec_id == CODEC_ID_ADPCM_IMA_WAV ||
516
        mov_pcm_le_gt16(track->enc->codec_id)))
517
        mov_write_wave_tag(pb, track);
518
    else if(track->tag == MKTAG('m','p','4','a'))
Baptiste Coudurier's avatar
Baptiste Coudurier committed
519 520
        mov_write_esds_tag(pb, track);
    else if(track->enc->codec_id == CODEC_ID_AMR_NB)
521
        mov_write_amr_tag(pb, track);
522 523
    else if(track->enc->codec_id == CODEC_ID_AC3)
        mov_write_ac3_tag(pb, track);
524
    else if(track->enc->codec_id == CODEC_ID_ALAC)
525
        mov_write_extradata_tag(pb, track);
526 527
    else if (track->enc->codec_id == CODEC_ID_WMAPRO)
        mov_write_wfex_tag(pb, track);
528
    else if (track->vos_len > 0)
529
        mov_write_glbl_tag(pb, track);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
530

531
    return update_size(pb, pos);
532 533
}

534
static int mov_write_d263_tag(AVIOContext *pb)
535
{
536
    avio_wb32(pb, 0xf); /* size */
537 538
    ffio_wfourcc(pb, "d263");
    ffio_wfourcc(pb, "FFMP");
539
    avio_w8(pb, 0); /* decoder version */
540
    /* FIXME use AVCodecContext level/profile, when encoder will set values */
541 542
    avio_w8(pb, 0xa); /* level */
    avio_w8(pb, 0); /* profile */
543 544 545
    return 0xf;
}

546
/* TODO: No idea about these values */
547
static int mov_write_svq3_tag(AVIOContext *pb)
548
{
549
    avio_wb32(pb, 0x15);
550 551
    ffio_wfourcc(pb, "SMI ");
    ffio_wfourcc(pb, "SEQH");
552 553 554 555
    avio_wb32(pb, 0x5);
    avio_wb32(pb, 0xe2c0211d);
    avio_wb32(pb, 0xc0000000);
    avio_w8(pb, 0);
556
    return 0x15;
557 558
}

559
static int mov_write_avcc_tag(AVIOContext *pb, MOVTrack *track)
560
{
561
    int64_t pos = avio_tell(pb);
562

563
    avio_wb32(pb, 0);
564
    ffio_wfourcc(pb, "avcC");
565 566
    ff_isom_write_avcc(pb, track->vos_data, track->vos_len);
    return update_size(pb, pos);
567 568
}

569
/* also used by all avid codecs (dv, imx, meridien) and their variants */
570
static int mov_write_avid_tag(AVIOContext *pb, MOVTrack *track)
571 572
{
    int i;
573
    avio_wb32(pb, 24); /* size */
574 575 576
    ffio_wfourcc(pb, "ACLR");
    ffio_wfourcc(pb, "ACLR");
    ffio_wfourcc(pb, "0001");
577
    avio_wb32(pb, 2); /* yuv range: full 1 / normal 2 */
578
    avio_wb32(pb, 0); /* unknown */
579

580
    avio_wb32(pb, 24); /* size */
581 582 583
    ffio_wfourcc(pb, "APRG");
    ffio_wfourcc(pb, "APRG");
    ffio_wfourcc(pb, "0001");
584 585
    avio_wb32(pb, 1); /* unknown */
    avio_wb32(pb, 0); /* unknown */
586

587
    avio_wb32(pb, 120); /* size */
588 589 590
    ffio_wfourcc(pb, "ARES");
    ffio_wfourcc(pb, "ARES");
    ffio_wfourcc(pb, "0001");
591
    avio_wb32(pb, AV_RB32(track->vos_data + 0x28)); /* dnxhd cid, some id ? */
592
    avio_wb32(pb, track->enc->width);
593
    /* values below are based on samples created with quicktime and avid codecs */
594
    if (track->vos_data[5] & 2) { // interlaced
595 596 597 598
        avio_wb32(pb, track->enc->height/2);
        avio_wb32(pb, 2); /* unknown */
        avio_wb32(pb, 0); /* unknown */
        avio_wb32(pb, 4); /* unknown */
599
    } else {
600 601 602
        avio_wb32(pb, track->enc->height);
        avio_wb32(pb, 1); /* unknown */
        avio_wb32(pb, 0); /* unknown */
603
        if (track->enc->height == 1080)
604
            avio_wb32(pb, 5); /* unknown */
605
        else
606
            avio_wb32(pb, 6); /* unknown */
607 608 609
    }
    /* padding */
    for (i = 0; i < 10; i++)
610
        avio_wb64(pb, 0);
611 612

    /* extra padding for stsd needed */
613
    avio_wb32(pb, 0);
614 615 616
    return 0;
}

617
static int mp4_get_codec_tag(AVFormatContext *s, MOVTrack *track)
618
{
Baptiste Coudurier's avatar
Baptiste Coudurier committed
619
    int tag = track->enc->codec_tag;
620

621
    if (!ff_codec_get_tag(ff_mp4_obj_type, track->enc->codec_id))
622 623 624 625 626 627
        return 0;

    if      (track->enc->codec_id == CODEC_ID_H264)      tag = MKTAG('a','v','c','1');
    else if (track->enc->codec_id == CODEC_ID_AC3)       tag = MKTAG('a','c','-','3');
    else if (track->enc->codec_id == CODEC_ID_DIRAC)     tag = MKTAG('d','r','a','c');
    else if (track->enc->codec_id == CODEC_ID_MOV_TEXT)  tag = MKTAG('t','x','3','g');
628 629
    else if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) tag = MKTAG('m','p','4','v');
    else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) tag = MKTAG('m','p','4','a');
630 631 632 633

    return tag;
}

634 635 636 637 638 639 640 641 642 643 644
static const AVCodecTag codec_ipod_tags[] = {
    { CODEC_ID_H264,   MKTAG('a','v','c','1') },
    { CODEC_ID_MPEG4,  MKTAG('m','p','4','v') },
    { CODEC_ID_AAC,    MKTAG('m','p','4','a') },
    { CODEC_ID_ALAC,   MKTAG('a','l','a','c') },
    { CODEC_ID_AC3,    MKTAG('a','c','-','3') },
    { CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') },
    { CODEC_ID_MOV_TEXT, MKTAG('t','e','x','t') },
    { CODEC_ID_NONE, 0 },
};

645 646 647 648
static int ipod_get_codec_tag(AVFormatContext *s, MOVTrack *track)
{
    int tag = track->enc->codec_tag;

649
    // keep original tag for subs, ipod supports both formats
650
    if (!(track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE &&
651
        (tag == MKTAG('t','x','3','g') ||
652
         tag == MKTAG('t','e','x','t'))))
653
        tag = ff_codec_get_tag(codec_ipod_tags, track->enc->codec_id);
654

655
    if (!av_match_ext(s->filename, "m4a") && !av_match_ext(s->filename, "m4v"))
656 657
        av_log(s, AV_LOG_WARNING, "Warning, extension is not .m4a nor .m4v "
               "Quicktime/Ipod might not play the file\n");
658 659 660 661 662 663 664 665

    return tag;
}

static int mov_get_dv_codec_tag(AVFormatContext *s, MOVTrack *track)
{
    int tag;

666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682
    if (track->enc->width == 720) /* SD */
        if (track->enc->height == 480) /* NTSC */
            if  (track->enc->pix_fmt == PIX_FMT_YUV422P) tag = MKTAG('d','v','5','n');
            else                                         tag = MKTAG('d','v','c',' ');
        else if (track->enc->pix_fmt == PIX_FMT_YUV422P) tag = MKTAG('d','v','5','p');
        else if (track->enc->pix_fmt == PIX_FMT_YUV420P) tag = MKTAG('d','v','c','p');
        else                                             tag = MKTAG('d','v','p','p');
    else if (track->enc->height == 720) /* HD 720 line */
        if  (track->enc->time_base.den == 50)            tag = MKTAG('d','v','h','q');
        else                                             tag = MKTAG('d','v','h','p');
    else if (track->enc->height == 1080) /* HD 1080 line */
        if  (track->enc->time_base.den == 25)            tag = MKTAG('d','v','h','5');
        else                                             tag = MKTAG('d','v','h','6');
    else {
        av_log(s, AV_LOG_ERROR, "unsupported height for dv codec\n");
        return 0;
    }
683 684 685 686

    return tag;
}

687 688 689 690 691 692 693
static const struct {
    enum PixelFormat pix_fmt;
    uint32_t tag;
    unsigned bps;
} mov_pix_fmt_tags[] = {
    { PIX_FMT_YUYV422, MKTAG('y','u','v','s'),  0 },
    {