movenc.c 128 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 25
#include <stdint.h>

26
#include "movenc.h"
27
#include "avformat.h"
28
#include "avio_internal.h"
29
#include "riff.h"
30
#include "avio.h"
31
#include "isom.h"
32
#include "avc.h"
33
#include "libavcodec/get_bits.h"
34
#include "libavcodec/put_bits.h"
Martin Storsjö's avatar
Martin Storsjö committed
35
#include "libavcodec/vc1.h"
36 37
#include "internal.h"
#include "libavutil/avstring.h"
38
#include "libavutil/intfloat.h"
39
#include "libavutil/mathematics.h"
40
#include "libavutil/opt.h"
41
#include "libavutil/dict.h"
Tim Walker's avatar
Tim Walker committed
42
#include "hevc.h"
43
#include "rtpenc.h"
44
#include "mov_chan.h"
45

46 47 48
#undef NDEBUG
#include <assert.h>

49
static const AVOption options[] = {
50
    { "movflags", "MOV muxer flags", offsetof(MOVMuxContext, flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
51 52 53 54 55 56
    { "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" },
57
    { "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" },
58
    { "omit_tfhd_offset", "Omit the base data offset in tfhd atoms", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_OMIT_TFHD_OFFSET}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
59
    FF_RTP_FLAG_OPTS(MOVMuxContext, rtp_flags),
60 61 62 63 64 65 66
    { "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},
67 68 69
    { NULL },
};

70 71 72 73 74 75
#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,\
76 77
};

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

    return curpos - pos;
87 88
}

89 90 91 92 93 94 95
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;
}

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

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

124
    int64_t pos = avio_tell(pb);
125
    avio_wb32(pb, 0); /* size */
126
    ffio_wfourcc(pb, "stsz");
127
    avio_wb32(pb, 0); /* version & flags */
128

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

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

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

180
    return update_size(pb, pos);
181 182
}

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

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

215 216 217
    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
218 219 220
    return 0x11;
}

221
static int mov_write_ac3_tag(AVIOContext *pb, MOVTrack *track)
222 223 224 225 226 227
{
    GetBitContext gbc;
    PutBitContext pbc;
    uint8_t buf[3];
    int fscod, bsid, bsmod, acmod, lfeon, frmsizecod;

228
    if (track->vos_len < 7)
229 230
        return -1;

231
    avio_wb32(pb, 11);
232
    ffio_wfourcc(pb, "dac3");
233

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

    flush_put_bits(&pbc);
260
    avio_write(pb, buf, sizeof(buf));
261 262 263 264

    return 11;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

347 348 349 350 351 352 353 354 355
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);
}

356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377
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

378
    return update_size(pb, pos);
379 380
}

381
static int mov_write_wave_tag(AVIOContext *pb, MOVTrack *track)
382
{
383
    int64_t pos = avio_tell(pb);
384

385
    avio_wb32(pb, 0);     /* size */
386
    ffio_wfourcc(pb, "wave");
387

388
    avio_wb32(pb, 12);    /* size */
389
    ffio_wfourcc(pb, "frma");
390
    avio_wl32(pb, track->tag);
391

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

409 410
    avio_wb32(pb, 8);     /* size */
    avio_wb32(pb, 0);     /* null tag */
411

412
    return update_size(pb, pos);
413 414
}

Martin Storsjö's avatar
Martin Storsjö committed
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 503 504 505 506
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;
}

507
static int mov_write_glbl_tag(AVIOContext *pb, MOVTrack *track)
508
{
509
    avio_wb32(pb, track->vos_len + 8);
510
    ffio_wfourcc(pb, "glbl");
511 512
    avio_write(pb, track->vos_data, track->vos_len);
    return 8 + track->vos_len;
513 514
}

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

544 545 546 547 548 549 550 551 552 553 554 555 556 557 558
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;
}

559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577
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;
}

578
static int mov_write_audio_tag(AVIOContext *pb, MOVTrack *track)
579
{
580
    int64_t pos = avio_tell(pb);
581 582 583 584
    int version = 0;
    uint32_t tag = track->tag;

    if (track->mode == MODE_MOV) {
585 586 587
        if (mov_get_lpcm_flags(track->enc->codec_id))
            tag = AV_RL32("lpcm");
        version = 2;
588
    }
589

590 591 592 593 594
    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 */
595

596
    /* SoundDescription */
597 598 599
    avio_wb16(pb, version); /* Version */
    avio_wb16(pb, 0); /* Revision level */
    avio_wb32(pb, 0); /* Reserved */
600

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

621
        avio_wb16(pb, 0); /* packet size (= 0) */
622 623
        avio_wb16(pb, track->enc->sample_rate <= UINT16_MAX ?
                      track->enc->sample_rate : 0);
624
        avio_wb16(pb, 0); /* Reserved */
625
    }
626

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

648 649 650
    if (track->mode == MODE_MOV && track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
        mov_write_chan_tag(pb, track);

651
    return update_size(pb, pos);
652 653
}

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

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

679
static int mov_write_avcc_tag(AVIOContext *pb, MOVTrack *track)
680
{
681
    int64_t pos = avio_tell(pb);
682

683
    avio_wb32(pb, 0);
684
    ffio_wfourcc(pb, "avcC");
685 686
    ff_isom_write_avcc(pb, track->vos_data, track->vos_len);
    return update_size(pb, pos);
687 688
}

Tim Walker's avatar
Tim Walker committed
689 690 691 692 693 694 695 696 697 698
static int mov_write_hvcc_tag(AVIOContext *pb, MOVTrack *track)
{
    int64_t pos = avio_tell(pb);

    avio_wb32(pb, 0);
    ffio_wfourcc(pb, "hvcC");
    ff_isom_write_hvcc(pb, track->vos_data, track->vos_len, 0);
    return update_size(pb, pos);
}

699
/* also used by all avid codecs (dv, imx, meridien) and their variants */
700
static int mov_write_avid_tag(AVIOContext *pb, MOVTrack *track)
701 702
{
    int i;
703
    avio_wb32(pb, 24); /* size */
704 705 706
    ffio_wfourcc(pb, "ACLR");
    ffio_wfourcc(pb, "ACLR");
    ffio_wfourcc(pb, "0001");
707
    avio_wb32(pb, 2); /* yuv range: full 1 / normal 2 */
708
    avio_wb32(pb, 0); /* unknown */
709

710
    avio_wb32(pb, 24); /* size */
711 712 713
    ffio_wfourcc(pb, "APRG");
    ffio_wfourcc(pb, "APRG");
    ffio_wfourcc(pb, "0001");
714 715
    avio_wb32(pb, 1); /* unknown */
    avio_wb32(pb, 0); /* unknown */
716

717
    avio_wb32(pb, 120); /* size */
718 719 720
    ffio_wfourcc(pb, "ARES");
    ffio_wfourcc(pb, "ARES");
    ffio_wfourcc(pb, "0001");
721
    avio_wb32(pb, AV_RB32(track->vos_data + 0x28)); /* dnxhd cid, some id ? */
722
    avio_wb32(pb, track->enc->width);
723
    /* values below are based on samples created with quicktime and avid codecs */
724
    if (track->vos_data[5] & 2) { // interlaced
725
        avio_wb32(pb, track->enc->height / 2);
726 727 728
        avio_wb32(pb, 2); /* unknown */
        avio_wb32(pb, 0); /* unknown */
        avio_wb32(pb, 4); /* unknown */
729
    } else {
730 731 732
        avio_wb32(pb, track->enc->height);
        avio_wb32(pb, 1); /* unknown */
        avio_wb32(pb, 0); /* unknown */
733
        if (track->enc->height == 1080)
734
            avio_wb32(pb, 5); /* unknown */
735
        else
736
            avio_wb32(pb, 6); /* unknown */
737 738 739
    }
    /* padding */
    for (i = 0; i < 10; i++)
740
        avio_wb64(pb, 0);
741 742

    /* extra padding for stsd needed */
743
    avio_wb32(pb, 0);
744 745 746
    return 0;
}

747
static int mp4_get_codec_tag(AVFormatContext *s, MOVTrack *track)
748