movenc.c 122 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"
Martin Storsjö's avatar
Martin Storsjö committed
33
#include "libavcodec/vc1.h"
34 35
#include "internal.h"
#include "libavutil/avstring.h"
36
#include "libavutil/intfloat.h"
37
#include "libavutil/mathematics.h"
38
#include "libavutil/opt.h"
39
#include "libavutil/dict.h"
40
#include "rtpenc.h"
41
#include "mov_chan.h"
42

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

46
static const AVOption options[] = {
47
    { "movflags", "MOV muxer flags", offsetof(MOVMuxContext, flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
48 49 50 51 52 53
    { "rtphint", "Add RTP hint tracks", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_RTP_HINT}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
    { "empty_moov", "Make the initial moov atom empty (not supported by QuickTime)", 0, AV_OPT_TYPE_CONST, {.i64 = 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, {.i64 = 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, {.i64 = FF_MOV_FLAG_SEPARATE_MOOF}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
    { "frag_custom", "Flush fragments on caller requests", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_FRAG_CUSTOM}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
    { "isml", "Create a live smooth streaming feed (for pushing to a publishing point)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_ISML}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
54
    { "faststart", "Run a second pass to put the index (moov atom) at the beginning of the file", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_FASTSTART}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
55
    FF_RTP_FLAG_OPTS(MOVMuxContext, rtp_flags),
56 57 58 59 60 61 62
    { "skip_iods", "Skip writing iods atom.", offsetof(MOVMuxContext, iods_skip), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
    { "iods_audio_profile", "iods audio profile atom.", offsetof(MOVMuxContext, iods_audio_profile), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 255, AV_OPT_FLAG_ENCODING_PARAM},
    { "iods_video_profile", "iods video profile atom.", offsetof(MOVMuxContext, iods_video_profile), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 255, AV_OPT_FLAG_ENCODING_PARAM},
    { "frag_duration", "Maximum fragment duration", offsetof(MOVMuxContext, max_fragment_duration), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
    { "min_frag_duration", "Minimum fragment duration", offsetof(MOVMuxContext, min_fragment_duration), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
    { "frag_size", "Maximum fragment size", offsetof(MOVMuxContext, max_fragment_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
    { "ism_lookahead", "Number of lookahead entries for ISM files", offsetof(MOVMuxContext, ism_lookahead), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
63 64 65
    { NULL },
};

66 67 68 69 70 71
#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,\
72 73
};

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

    return curpos - pos;
83 84
}

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

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

114
    int64_t pos = avio_tell(pb);
115
    avio_wb32(pb, 0); /* size */
116
    ffio_wfourcc(pb, "stsz");
117
    avio_wb32(pb, 0); /* version & flags */
118

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

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

150
    int64_t pos = avio_tell(pb);
151
    avio_wb32(pb, 0); /* size */
152
    ffio_wfourcc(pb, "stsc");
153
    avio_wb32(pb, 0); // version & flags
154
    entryPos = avio_tell(pb);
155
    avio_wb32(pb, track->entry); // entry count
156 157 158
    for (i = 0; i < track->entry; i++) {
        if (oldval != track->cluster[i].samples_in_chunk) {
            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
    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);
246
    put_bits(&pbc, 5, frmsizecod >> 1); // bit_rate_code
247 248 249
    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 void put_descr(AVIOContext *pb, int tag, unsigned int size)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
266
{
267
    int i = 3;
268
    avio_w8(pb, tag);
269 270
    for (; i > 0; i--)
        avio_w8(pb, (size >> (7 * i)) | 0x80);
271
    avio_w8(pb, size & 0x7F);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
272 273
}

274
static int mov_write_esds_tag(AVIOContext *pb, MOVTrack *track) // Basic
Baptiste Coudurier's avatar
Baptiste Coudurier committed
275
{
276
    int64_t pos = avio_tell(pb);
277
    int decoder_specific_info_len = track->vos_len ? 5 + track->vos_len : 0;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
278

279
    avio_wb32(pb, 0); // size
280
    ffio_wfourcc(pb, "esds");
281
    avio_wb32(pb, 0); // Version
Baptiste Coudurier's avatar
Baptiste Coudurier committed
282 283

    // ES descriptor
284 285
    put_descr(pb, 0x03, 3 + 5+13 + decoder_specific_info_len + 5+1);
    avio_wb16(pb, track->track_id);
286
    avio_w8(pb, 0x00); // flags (= no flags)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
287 288

    // DecoderConfig descriptor
289
    put_descr(pb, 0x04, 13 + decoder_specific_info_len);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
290 291

    // Object type indication
292 293
    if ((track->enc->codec_id == AV_CODEC_ID_MP2 ||
         track->enc->codec_id == AV_CODEC_ID_MP3) &&
294
        track->enc->sample_rate > 24000)
295
        avio_w8(pb, 0x6B); // 11172-3
296
    else
297
        avio_w8(pb, ff_codec_get_tag(ff_mp4_obj_type, track->enc->codec_id));
Baptiste Coudurier's avatar
Baptiste Coudurier committed
298 299 300

    // 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)
301
    if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
302
        avio_w8(pb, 0x15); // flags (= Audiostream)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
303
    else
304
        avio_w8(pb, 0x11); // flags (= Visualstream)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
305

306
    avio_wb24(pb, track->enc->rc_buffer_size >> 3); // Buffersize DB
Baptiste Coudurier's avatar
Baptiste Coudurier committed
307

308
    avio_wb32(pb, FFMAX(track->enc->bit_rate, track->enc->rc_max_rate)); // maxbitrate (FIXME should be max rate in any 1 sec window)
309 310
    if (track->enc->rc_max_rate != track->enc->rc_min_rate ||
        track->enc->rc_min_rate == 0)
311
        avio_wb32(pb, 0); // vbr
Baptiste Coudurier's avatar
Baptiste Coudurier committed
312
    else
313
        avio_wb32(pb, track->enc->rc_max_rate); // avg bitrate
Baptiste Coudurier's avatar
Baptiste Coudurier committed
314

315
    if (track->vos_len) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
316
        // DecoderSpecific info descriptor
317 318
        put_descr(pb, 0x05, track->vos_len);
        avio_write(pb, track->vos_data, track->vos_len);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
319 320 321
    }

    // SL descriptor
322
    put_descr(pb, 0x06, 1);
323
    avio_w8(pb, 0x02);
324
    return update_size(pb, pos);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
325 326
}

327
static int mov_write_ms_tag(AVIOContext *pb, MOVTrack *track)
328
{
329
    int64_t pos = avio_tell(pb);
330 331
    avio_wb32(pb, 0);
    avio_wl32(pb, track->tag); // store it byteswapped
332
    track->enc->codec_tag = av_bswap16(track->tag >> 16);
333
    ff_put_wav_header(pb, track->enc);
334
    return update_size(pb, pos);
335 336
}

337 338 339 340 341 342 343 344 345
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);
}

346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
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

368
    return update_size(pb, pos);
369 370
}

371
static int mov_write_wave_tag(AVIOContext *pb, MOVTrack *track)
372
{
373
    int64_t pos = avio_tell(pb);
374

375
    avio_wb32(pb, 0);     /* size */
376
    ffio_wfourcc(pb, "wave");
377

378
    avio_wb32(pb, 12);    /* size */
379
    ffio_wfourcc(pb, "frma");
380
    avio_wl32(pb, track->tag);
381

382
    if (track->enc->codec_id == AV_CODEC_ID_AAC) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
383
        /* useless atom needed by mplayer, ipod, not needed by quicktime */
384
        avio_wb32(pb, 12); /* size */
385
        ffio_wfourcc(pb, "mp4a");
386
        avio_wb32(pb, 0);
387
        mov_write_esds_tag(pb, track);
388
    } else if (track->enc->codec_id == AV_CODEC_ID_AMR_NB) {
389
        mov_write_amr_tag(pb, track);
390
    } else if (track->enc->codec_id == AV_CODEC_ID_AC3) {
391
        mov_write_ac3_tag(pb, track);
392
    } else if (track->enc->codec_id == AV_CODEC_ID_ALAC) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
393
        mov_write_extradata_tag(pb, track);
394 395
    } else if (track->enc->codec_id == AV_CODEC_ID_ADPCM_MS ||
               track->enc->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) {
396
        mov_write_ms_tag(pb, track);
397
    }
398

399 400
    avio_wb32(pb, 8);     /* size */
    avio_wb32(pb, 0);     /* null tag */
401

402
    return update_size(pb, pos);
403 404
}

Martin Storsjö's avatar
Martin Storsjö committed
405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 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 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496
static int mov_write_dvc1_structs(MOVTrack *track, uint8_t *buf)
{
    uint8_t *unescaped;
    const uint8_t *start, *next, *end = track->vos_data + track->vos_len;
    int unescaped_size, seq_found = 0;
    int level = 0, interlace = 0;
    int packet_seq   = track->vc1_info.packet_seq;
    int packet_entry = track->vc1_info.packet_entry;
    int slices       = track->vc1_info.slices;
    PutBitContext pbc;

    if (track->start_dts == AV_NOPTS_VALUE) {
        /* No packets written yet, vc1_info isn't authoritative yet. */
        /* Assume inline sequence and entry headers. This will be
         * overwritten at the end if the file is seekable. */
        packet_seq = packet_entry = 1;
    }

    unescaped = av_mallocz(track->vos_len + FF_INPUT_BUFFER_PADDING_SIZE);
    if (!unescaped)
        return AVERROR(ENOMEM);
    start = find_next_marker(track->vos_data, end);
    for (next = start; next < end; start = next) {
        GetBitContext gb;
        int size;
        next = find_next_marker(start + 4, end);
        size = next - start - 4;
        if (size <= 0)
            continue;
        unescaped_size = vc1_unescape_buffer(start + 4, size, unescaped);
        init_get_bits(&gb, unescaped, 8 * unescaped_size);
        if (AV_RB32(start) == VC1_CODE_SEQHDR) {
            int profile = get_bits(&gb, 2);
            if (profile != PROFILE_ADVANCED) {
                av_free(unescaped);
                return AVERROR(ENOSYS);
            }
            seq_found = 1;
            level = get_bits(&gb, 3);
            /* chromaformat, frmrtq_postproc, bitrtq_postproc, postprocflag,
             * width, height */
            skip_bits_long(&gb, 2 + 3 + 5 + 1 + 2*12);
            skip_bits(&gb, 1); /* broadcast */
            interlace = get_bits1(&gb);
            skip_bits(&gb, 4); /* tfcntrflag, finterpflag, reserved, psf */
        }
    }
    if (!seq_found) {
        av_free(unescaped);
        return AVERROR(ENOSYS);
    }

    init_put_bits(&pbc, buf, 7);
    /* VC1DecSpecStruc */
    put_bits(&pbc, 4, 12); /* profile - advanced */
    put_bits(&pbc, 3, level);
    put_bits(&pbc, 1, 0); /* reserved */
    /* VC1AdvDecSpecStruc */
    put_bits(&pbc, 3, level);
    put_bits(&pbc, 1, 0); /* cbr */
    put_bits(&pbc, 6, 0); /* reserved */
    put_bits(&pbc, 1, !interlace); /* no interlace */
    put_bits(&pbc, 1, !packet_seq); /* no multiple seq */
    put_bits(&pbc, 1, !packet_entry); /* no multiple entry */
    put_bits(&pbc, 1, !slices); /* no slice code */
    put_bits(&pbc, 1, 0); /* no bframe */
    put_bits(&pbc, 1, 0); /* reserved */
    put_bits32(&pbc, track->enc->time_base.den); /* framerate */
    flush_put_bits(&pbc);

    av_free(unescaped);

    return 0;
}

static int mov_write_dvc1_tag(AVIOContext *pb, MOVTrack *track)
{
    uint8_t buf[7] = { 0 };
    int ret;

    if ((ret = mov_write_dvc1_structs(track, buf)) < 0)
        return ret;

    avio_wb32(pb, track->vos_len + 8 + sizeof(buf));
    ffio_wfourcc(pb, "dvc1");
    track->vc1_info.struct_offset = avio_tell(pb);
    avio_write(pb, buf, sizeof(buf));
    avio_write(pb, track->vos_data, track->vos_len);

    return 0;
}

497
static int mov_write_glbl_tag(AVIOContext *pb, MOVTrack *track)
498
{
499
    avio_wb32(pb, track->vos_len + 8);
500
    ffio_wfourcc(pb, "glbl");
501 502
    avio_write(pb, track->vos_data, track->vos_len);
    return 8 + track->vos_len;
503 504
}

505 506 507 508
/**
 * Compute flags for 'lpcm' tag.
 * See CoreAudioTypes and AudioStreamBasicDescription at Apple.
 */
509
static int mov_get_lpcm_flags(enum AVCodecID codec_id)
510 511
{
    switch (codec_id) {
512 513
    case AV_CODEC_ID_PCM_F32BE:
    case AV_CODEC_ID_PCM_F64BE:
514
        return 11;
515 516
    case AV_CODEC_ID_PCM_F32LE:
    case AV_CODEC_ID_PCM_F64LE:
517
        return 9;
518
    case AV_CODEC_ID_PCM_U8:
519
        return 10;
520 521 522
    case AV_CODEC_ID_PCM_S16BE:
    case AV_CODEC_ID_PCM_S24BE:
    case AV_CODEC_ID_PCM_S32BE:
523
        return 14;
524 525 526 527
    case AV_CODEC_ID_PCM_S8:
    case AV_CODEC_ID_PCM_S16LE:
    case AV_CODEC_ID_PCM_S24LE:
    case AV_CODEC_ID_PCM_S32LE:
528 529 530 531 532 533
        return 12;
    default:
        return 0;
    }
}

534 535 536 537 538 539 540 541 542 543 544 545 546 547 548
static int get_cluster_duration(MOVTrack *track, int cluster_idx)
{
    int64_t next_dts;

    if (cluster_idx >= track->entry)
        return 0;

    if (cluster_idx + 1 == track->entry)
        next_dts = track->track_duration + track->start_dts;
    else
        next_dts = track->cluster[cluster_idx + 1].dts;

    return next_dts - track->cluster[cluster_idx].dts;
}

549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567
static int get_samples_per_packet(MOVTrack *track)
{
    int i, first_duration;

    /* use 1 for raw PCM */
    if (!track->audio_vbr)
        return 1;

    /* check to see if duration is constant for all clusters */
    if (!track->entry)
        return 0;
    first_duration = get_cluster_duration(track, 0);
    for (i = 1; i < track->entry; i++) {
        if (get_cluster_duration(track, i) != first_duration)
            return 0;
    }
    return first_duration;
}

568
static int mov_write_audio_tag(AVIOContext *pb, MOVTrack *track)
569
{
570
    int64_t pos = avio_tell(pb);
571 572 573 574
    int version = 0;
    uint32_t tag = track->tag;

    if (track->mode == MODE_MOV) {
575 576 577
        if (mov_get_lpcm_flags(track->enc->codec_id))
            tag = AV_RL32("lpcm");
        version = 2;
578
    }
579

580 581 582 583 584
    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 */
585

586
    /* SoundDescription */
587 588 589
    avio_wb16(pb, version); /* Version */
    avio_wb16(pb, 0); /* Revision level */
    avio_wb32(pb, 0); /* Reserved */
590

591
    if (version == 2) {
592 593 594 595 596 597
        avio_wb16(pb, 3);
        avio_wb16(pb, 16);
        avio_wb16(pb, 0xfffe);
        avio_wb16(pb, 0);
        avio_wb32(pb, 0x00010000);
        avio_wb32(pb, 72);
598
        avio_wb64(pb, av_double2int(track->enc->sample_rate));
599 600 601 602
        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));
603
        avio_wb32(pb, track->sample_size);
604
        avio_wb32(pb, get_samples_per_packet(track));
605
    } else {
606 607 608 609
        /* reserved for mp4/3gp */
        avio_wb16(pb, 2);
        avio_wb16(pb, 16);
        avio_wb16(pb, 0);
610

611
        avio_wb16(pb, 0); /* packet size (= 0) */
612 613
        avio_wb16(pb, track->enc->sample_rate <= UINT16_MAX ?
                      track->enc->sample_rate : 0);
614
        avio_wb16(pb, 0); /* Reserved */
615
    }
616

617 618 619 620 621 622 623
    if (track->mode == MODE_MOV &&
        (track->enc->codec_id == AV_CODEC_ID_AAC           ||
         track->enc->codec_id == AV_CODEC_ID_AC3           ||
         track->enc->codec_id == AV_CODEC_ID_AMR_NB        ||
         track->enc->codec_id == AV_CODEC_ID_ALAC          ||
         track->enc->codec_id == AV_CODEC_ID_ADPCM_MS      ||
         track->enc->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV))
624
        mov_write_wave_tag(pb, track);
625
    else if (track->tag == MKTAG('m','p','4','a'))
Baptiste Coudurier's avatar
Baptiste Coudurier committed
626
        mov_write_esds_tag(pb, track);
627
    else if (track->enc->codec_id == AV_CODEC_ID_AMR_NB)
628
        mov_write_amr_tag(pb, track);
629
    else if (track->enc->codec_id == AV_CODEC_ID_AC3)
630
        mov_write_ac3_tag(pb, track);
631
    else if (track->enc->codec_id == AV_CODEC_ID_ALAC)
632
        mov_write_extradata_tag(pb, track);
633
    else if (track->enc->codec_id == AV_CODEC_ID_WMAPRO)
634
        mov_write_wfex_tag(pb, track);
635
    else if (track->vos_len > 0)
636
        mov_write_glbl_tag(pb, track);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
637

638 639 640
    if (track->mode == MODE_MOV && track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
        mov_write_chan_tag(pb, track);

641
    return update_size(pb, pos);
642 643
}

644
static int mov_write_d263_tag(AVIOContext *pb)
645
{
646
    avio_wb32(pb, 0xf); /* size */
647 648
    ffio_wfourcc(pb, "d263");
    ffio_wfourcc(pb, "FFMP");
649
    avio_w8(pb, 0); /* decoder version */
650
    /* FIXME use AVCodecContext level/profile, when encoder will set values */
651 652
    avio_w8(pb, 0xa); /* level */
    avio_w8(pb, 0); /* profile */
653 654 655
    return 0xf;
}

656
/* TODO: No idea about these values */
657
static int mov_write_svq3_tag(AVIOContext *pb)
658
{
659
    avio_wb32(pb, 0x15);
660 661
    ffio_wfourcc(pb, "SMI ");
    ffio_wfourcc(pb, "SEQH");
662 663 664 665
    avio_wb32(pb, 0x5);
    avio_wb32(pb, 0xe2c0211d);
    avio_wb32(pb, 0xc0000000);
    avio_w8(pb, 0);
666
    return 0x15;
667 668
}

669
static int mov_write_avcc_tag(AVIOContext *pb, MOVTrack *track)
670
{
671
    int64_t pos = avio_tell(pb);
672

673
    avio_wb32(pb, 0);
674
    ffio_wfourcc(pb, "avcC");
675 676
    ff_isom_write_avcc(pb, track->vos_data, track->vos_len);
    return update_size(pb, pos);
677 678
}

679
/* also used by all avid codecs (dv, imx, meridien) and their variants */
680
static int mov_write_avid_tag(AVIOContext *pb, MOVTrack *track)
681 682
{
    int i;
683
    avio_wb32(pb, 24); /* size */
684 685 686
    ffio_wfourcc(pb, "ACLR");
    ffio_wfourcc(pb, "ACLR");
    ffio_wfourcc(pb, "0001");
687
    avio_wb32(pb, 2); /* yuv range: full 1 / normal 2 */
688
    avio_wb32(pb, 0); /* unknown */
689

690
    avio_wb32(pb, 24); /* size */
691 692 693
    ffio_wfourcc(pb, "APRG");
    ffio_wfourcc(pb, "APRG");
    ffio_wfourcc(pb, "0001");
694 695
    avio_wb32(pb, 1); /* unknown */
    avio_wb32(pb, 0); /* unknown */
696

697
    avio_wb32(pb, 120); /* size */
698 699 700
    ffio_wfourcc(pb, "ARES");
    ffio_wfourcc(pb, "ARES");
    ffio_wfourcc(pb, "0001");
701
    avio_wb32(pb, AV_RB32(track->vos_data + 0x28)); /* dnxhd cid, some id ? */
702
    avio_wb32(pb, track->enc->width);
703
    /* values below are based on samples created with quicktime and avid codecs */
704
    if (track->vos_data[5] & 2) { // interlaced
705
        avio_wb32(pb, track->enc->height / 2);
706 707 708
        avio_wb32(pb, 2); /* unknown */
        avio_wb32(pb, 0); /* unknown */
        avio_wb32(pb, 4); /* unknown */
709
    } else {
710 711 712
        avio_wb32(pb, track->enc->height);
        avio_wb32(pb, 1); /* unknown */
        avio_wb32(pb, 0); /* unknown */
713
        if (track->enc->height == 1080)
714
            avio_wb32(pb, 5); /* unknown */
715
        else
716
            avio_wb32(pb, 6); /* unknown */
717 718 719
    }
    /* padding */
    for (i = 0; i < 10; i++)
720
        avio_wb64(pb, 0);
721 722

    /* extra padding for stsd needed */
723
    avio_wb32(pb, 0);
724 725 726
    return 0;
}

727
static int mp4_get_codec_tag(AVFormatContext *s, MOVTrack *track)
728
{
Baptiste Coudurier's avatar
Baptiste Coudurier committed
729
    int tag = track->enc->codec_tag;
730

731
    if (!ff_codec_get_tag(ff_mp4_obj_type, track->enc->codec_id))
732 733
        return 0;

734 735 736 737 738
    if      (track->enc->codec_id == AV_CODEC_ID_H264)      tag = MKTAG('a','v','c','1');
    else if (track->enc->codec_id == AV_CODEC_ID_AC3)       tag = MKTAG('a','c','-','3');
    else if (track->enc->codec_id == AV_CODEC_ID_DIRAC)     tag = MKTAG('d','r','a','c');
    else if (track->enc->codec_id == AV_CODEC_ID_MOV_TEXT)  tag = MKTAG('t','x','3','g');
    else if (track->enc->codec_id == AV_CODEC_ID_VC1)       tag = MKTAG('v','c','-','1');
739 740
    else if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO)  tag = MKTAG('m','p','4','v');
    else