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

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

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

50
static const AVOption options[] = {
51
    { "movflags", "MOV muxer flags", offsetof(MOVMuxContext, flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
52 53 54 55 56 57
    { "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" },
58
    { "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" },
59
    { "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" },
60
    FF_RTP_FLAG_OPTS(MOVMuxContext, rtp_flags),
61 62 63 64 65 66 67
    { "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},
68
    { "brand",    "Override major brand", offsetof(MOVMuxContext, major_brand),   AV_OPT_TYPE_STRING, {.str = NULL}, .flags = AV_OPT_FLAG_ENCODING_PARAM },
69 70 71
    { NULL },
};

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

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

    return curpos - pos;
89 90
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    return 11;
}

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

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

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

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

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

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

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

    // 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)
313 314 315
    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)
316
        avio_w8(pb, 0x15); // flags (= Audiostream)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
317
    else
318
        avio_w8(pb, 0x11); // flags (= Visualstream)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
319

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    /* extra padding for stsd needed */