movenc.c 125 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 86 87 88 89 90 91
static int co64_required(const MOVTrack *track)
{
    if (track->entry > 0 && track->cluster[track->entry - 1].pos + track->data_offset > UINT32_MAX)
        return 1;
    return 0;
}

92
/* Chunk offset atom */
93
static int mov_write_stco_tag(AVIOContext *pb, MOVTrack *track)
94 95
{
    int i;
96
    int mode64 = co64_required(track); // use 32 bit size variant if possible
97
    int64_t pos = avio_tell(pb);
98
    avio_wb32(pb, 0); /* size */
99
    if (mode64) {
100
        ffio_wfourcc(pb, "co64");
101
    } else
102
        ffio_wfourcc(pb, "stco");
103 104
    avio_wb32(pb, 0); /* version & flags */
    avio_wb32(pb, track->entry); /* entry count */
105 106
    for (i = 0; i < track->entry; i++) {
        if (mode64 == 1)
107
            avio_wb64(pb, track->cluster[i].pos + track->data_offset);
108
        else
109
            avio_wb32(pb, track->cluster[i].pos + track->data_offset);
110
    }
111
    return update_size(pb, pos);
112 113
}

114
/* Sample size atom */
115
static int mov_write_stsz_tag(AVIOContext *pb, MOVTrack *track)
116
{
117
    int equalChunks = 1;
118
    int i, j, entries = 0, tst = -1, oldtst = -1;
119

120
    int64_t pos = avio_tell(pb);
121
    avio_wb32(pb, 0); /* size */
122
    ffio_wfourcc(pb, "stsz");
123
    avio_wb32(pb, 0); /* version & flags */
124

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

150
/* Sample to chunk atom */
151
static int mov_write_stsc_tag(AVIOContext *pb, MOVTrack *track)
152
{
153
    int index = 0, oldval = -1, i;
154
    int64_t entryPos, curpos;
155

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

176
    return update_size(pb, pos);
177 178
}

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

203
static int mov_write_amr_tag(AVIOContext *pb, MOVTrack *track)
204
{
205
    avio_wb32(pb, 0x11); /* size */
206 207 208
    if (track->mode == MODE_MOV) ffio_wfourcc(pb, "samr");
    else                         ffio_wfourcc(pb, "damr");
    ffio_wfourcc(pb, "FFMP");
209
    avio_w8(pb, 0); /* decoder version */
Baptiste Coudurier's avatar
Baptiste Coudurier committed
210

211 212 213
    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
214 215 216
    return 0x11;
}

217
static int mov_write_ac3_tag(AVIOContext *pb, MOVTrack *track)
218 219 220 221 222 223
{
    GetBitContext gbc;
    PutBitContext pbc;
    uint8_t buf[3];
    int fscod, bsid, bsmod, acmod, lfeon, frmsizecod;

224
    if (track->vos_len < 7)
225 226
        return -1;

227
    avio_wb32(pb, 11);
228
    ffio_wfourcc(pb, "dac3");
229

230
    init_get_bits(&gbc, track->vos_data + 4, (track->vos_len - 4) * 8);
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251
    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);
252
    put_bits(&pbc, 5, frmsizecod >> 1); // bit_rate_code
253 254 255
    put_bits(&pbc, 5, 0); // reserved

    flush_put_bits(&pbc);
256
    avio_write(pb, buf, sizeof(buf));
257 258 259 260

    return 11;
}

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

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

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

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

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

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

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

    // 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)
307
    if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
308
        avio_w8(pb, 0x15); // flags (= Audiostream)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
309
    else
310
        avio_w8(pb, 0x11); // flags (= Visualstream)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
311

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

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

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

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

333
static int mov_write_ms_tag(AVIOContext *pb, MOVTrack *track)
334
{
335
    int64_t pos = avio_tell(pb);
336 337
    avio_wb32(pb, 0);
    avio_wl32(pb, track->tag); // store it byteswapped
338
    track->enc->codec_tag = av_bswap16(track->tag >> 16);
339
    ff_put_wav_header(pb, track->enc);
340
    return update_size(pb, pos);
341 342
}

343 344 345 346 347 348 349 350 351
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);
}

352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373
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

374
    return update_size(pb, pos);
375 376
}

377
static int mov_write_wave_tag(AVIOContext *pb, MOVTrack *track)
378
{
379
    int64_t pos = avio_tell(pb);
380

381
    avio_wb32(pb, 0);     /* size */
382
    ffio_wfourcc(pb, "wave");
383

384
    avio_wb32(pb, 12);    /* size */
385
    ffio_wfourcc(pb, "frma");
386
    avio_wl32(pb, track->tag);
387

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

405 406
    avio_wb32(pb, 8);     /* size */
    avio_wb32(pb, 0);     /* null tag */
407

408
    return update_size(pb, pos);
409 410
}

Martin Storsjö's avatar
Martin Storsjö committed
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 497 498 499 500 501 502
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;
}

503
static int mov_write_glbl_tag(AVIOContext *pb, MOVTrack *track)
504
{
505
    avio_wb32(pb, track->vos_len + 8);
506
    ffio_wfourcc(pb, "glbl");
507 508
    avio_write(pb, track->vos_data, track->vos_len);
    return 8 + track->vos_len;
509 510
}

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

540 541 542 543 544 545 546 547 548 549 550 551 552 553 554
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;
}

555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573
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;
}

574
static int mov_write_audio_tag(AVIOContext *pb, MOVTrack *track)
575
{
576
    int64_t pos = avio_tell(pb);
577 578 579 580
    int version = 0;
    uint32_t tag = track->tag;

    if (track->mode == MODE_MOV) {
581 582 583
        if (mov_get_lpcm_flags(track->enc->codec_id))
            tag = AV_RL32("lpcm");
        version = 2;
584
    }
585

586 587 588 589 590
    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 */
591

592
    /* SoundDescription */
593 594 595
    avio_wb16(pb, version); /* Version */
    avio_wb16(pb, 0); /* Revision level */
    avio_wb32(pb, 0); /* Reserved */
596

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

617
        avio_wb16(pb, 0); /* packet size (= 0) */
618 619
        avio_wb16(pb, track->enc->sample_rate <= UINT16_MAX ?
                      track->enc->sample_rate : 0);
620
        avio_wb16(pb, 0); /* Reserved */
621
    }
622

623 624 625 626 627 628 629
    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))
630
        mov_write_wave_tag(pb, track);
631
    else if (track->tag == MKTAG('m','p','4','a'))
Baptiste Coudurier's avatar
Baptiste Coudurier committed
632
        mov_write_esds_tag(pb, track);
633
    else if (track->enc->codec_id == AV_CODEC_ID_AMR_NB)
634
        mov_write_amr_tag(pb, track);
635
    else if (track->enc->codec_id == AV_CODEC_ID_AC3)
636
        mov_write_ac3_tag(pb, track);
637
    else if (track->enc->codec_id == AV_CODEC_ID_ALAC)
638
        mov_write_extradata_tag(pb, track);
639
    else if (track->enc->codec_id == AV_CODEC_ID_WMAPRO)
640
        mov_write_wfex_tag(pb, track);
641
    else if (track->vos_len > 0)
642
        mov_write_glbl_tag(pb, track);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
643

644 645 646
    if (track->mode == MODE_MOV && track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
        mov_write_chan_tag(pb, track);

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

650
static int mov_write_d263_tag(AVIOContext *pb)
651
{
652
    avio_wb32(pb, 0xf); /* size */
653 654
    ffio_wfourcc(pb, "d263");
    ffio_wfourcc(pb, "FFMP");
655
    avio_w8(pb, 0); /* decoder version */
656
    /* FIXME use AVCodecContext level/profile, when encoder will set values */
657 658
    avio_w8(pb, 0xa); /* level */
    avio_w8(pb, 0); /* profile */
659 660 661
    return 0xf;
}

662
/* TODO: No idea about these values */
663
static int mov_write_svq3_tag(AVIOContext *pb)
664
{
665
    avio_wb32(pb, 0x15);
666 667
    ffio_wfourcc(pb, "SMI ");
    ffio_wfourcc(pb, "SEQH");
668 669 670 671
    avio_wb32(pb, 0x5);
    avio_wb32(pb, 0xe2c0211d);
    avio_wb32(pb, 0xc0000000);
    avio_w8(pb, 0);
672
    return 0x15;
673 674
}

675
static int mov_write_avcc_tag(AVIOContext *pb, MOVTrack *track)
676
{
677
    int64_t pos = avio_tell(pb);
678

679
    avio_wb32(pb, 0);
680
    ffio_wfourcc(pb, "avcC");
681 682
    ff_isom_write_avcc(pb, track->vos_data, track->vos_len);
    return update_size(pb, pos);
683 684
}

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

696
    avio_wb32(pb, 24); /* size */
697 698 699
    ffio_wfourcc(pb, "APRG");
    ffio_wfourcc(pb, "APRG");
    ffio_wfourcc(pb, "0001");
700 701
    avio_wb32(pb, 1); /* unknown */
    avio_wb32(pb, 0); /* unknown */
702

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

    /* extra padding for stsd needed */
729
    avio_wb32(pb, 0);
730 731 732
    return 0;
}

733
static int mp4_get_codec_tag(AVFormatContext *s, MOVTrack *track)
734
{
Baptiste Coudurier's avatar
Baptiste Coudurier committed
735
    int tag = track->enc->codec_tag;
736

737
    if (!ff_codec_get_tag(ff_mp4_obj_type, track->enc->codec_id))
738 739
        return 0;

740 741 742 743 744
    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