movenc.c 131 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
    { "brand",    "Override major brand", offsetof(MOVMuxContext, major_brand),   AV_OPT_TYPE_STRING, {.str = NULL}, .flags = AV_OPT_FLAG_ENCODING_PARAM },
68 69 70
    { NULL },
};

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

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

    return curpos - pos;
88 89
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    return 11;
}

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

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

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

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

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

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

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

    // 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)
312 313 314
    if (track->enc->codec_id == AV_CODEC_ID_DVD_SUBTITLE)
        avio_w8(pb, (0x38 << 2) | 1); // flags (= NeroSubpicStream)
    else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
315
        avio_w8(pb, 0x15); // flags (= Audiostream)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
316
    else
317
        avio_w8(pb, 0x11); // flags (= Visualstream)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
318

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

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

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

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

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

350 351 352 353 354 355 356 357 358
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);
}

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

381
    return update_size(pb, pos);
382 383
}

384
static int mov_write_wave_tag(AVIOContext *pb, MOVTrack *track)
385
{
386
    int64_t pos = avio_tell(pb);
387

388
    avio_wb32(pb, 0);     /* size */
389
    ffio_wfourcc(pb, "wave");
390

391
    avio_wb32(pb, 12);    /* size */
392
    ffio_wfourcc(pb, "frma");
393
    avio_wl32(pb, track->tag);
394

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

412 413
    avio_wb32(pb, 8);     /* size */
    avio_wb32(pb, 0);     /* null tag */
414

415
    return update_size(pb, pos);
416 417
}

Martin Storsjö's avatar
Martin Storsjö committed
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 507 508 509
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;
}

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

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

547 548 549 550 551 552 553 554 555 556 557 558 559 560 561
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;
}

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

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

    if (track->mode == MODE_MOV) {
588 589 590
        if (mov_get_lpcm_flags(track->enc->codec_id))
            tag = AV_RL32("lpcm");
        version = 2;
591
    }
592

593 594 595 596 597
    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 */
598

599
    /* SoundDescription */
600 601 602
    avio_wb16(pb, version); /* Version */
    avio_wb16(pb, 0); /* Revision level */
    avio_wb32(pb, 0); /* Reserved */
603

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

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

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

651 652 653
    if (track->mode == MODE_MOV && track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
        mov_write_chan_tag(pb, track);

654
    return update_size(pb, pos);
655 656
}

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

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

682
static int mov_write_avcc_tag(AVIOContext *pb, MOVTrack *track)
683
{
684
    int64_t pos = avio_tell(pb);
685

686
    avio_wb32(pb, 0);
687
    ffio_wfourcc(pb, "avcC");
688 689
    ff_isom_write_avcc(pb, track->vos_data, track->vos_len);
    return update_size(pb, pos);
690 691
}

Tim Walker's avatar
Tim Walker committed
692 693 694 695 696 697 698 699 700 701
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);
}

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

713
    avio_wb32(pb, 24); /* size */
714 715 716
    ffio_wfourcc(pb, "APRG");
    ffio_wfourcc(pb, "APRG");
    ffio_wfourcc(pb, "0001");
717 718
    avio_wb32(pb, 1); /* unknown */
    avio_wb32(pb, 0); /* unknown */
719

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

    /* extra padding for stsd needed */
746
    avio_wb32(pb, 0);
747 748 749
    return 0;
}