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
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 */
486 487 488 489 490 491 492

    /* framerate */
    if (track->st->avg_frame_rate.num > 0 && track->st->avg_frame_rate.den > 0)
        put_bits32(&pbc, track->st->avg_frame_rate.num / track->st->avg_frame_rate.den);
    else
        put_bits32(&pbc, 0xffffffff);

Martin Storsjö's avatar
Martin Storsjö committed
493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516
    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;
}

517
static int mov_write_glbl_tag(AVIOContext *pb, MOVTrack *track)
518
{
519
    avio_wb32(pb, track->vos_len + 8);
520
    ffio_wfourcc(pb, "glbl");
521 522
    avio_write(pb, track->vos_data, track->vos_len);
    return 8 + track->vos_len;
523 524
}

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

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

569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587
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;
}

588
static int mov_write_audio_tag(AVIOContext *pb, MOVTrack *track)
589
{
590
    int64_t pos = avio_tell(pb);
591 592 593 594
    int version = 0;
    uint32_t tag = track->tag;

    if (track->mode == MODE_MOV) {
595 596 597
        if (mov_get_lpcm_flags(track->enc->codec_id))
            tag = AV_RL32("lpcm");
        version = 2;
598
    }
599

600 601 602 603 604
    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 */
605

606
    /* SoundDescription */
607 608 609
    avio_wb16(pb, version); /* Version */
    avio_wb16(pb, 0); /* Revision level */
    avio_wb32(pb, 0); /* Reserved */
610

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

631
        avio_wb16(pb, 0); /* packet size (= 0) */
632 633
        avio_wb16(pb, track->enc->sample_rate <= UINT16_MAX ?
                      track->enc->sample_rate : 0);
634
        avio_wb16(pb, 0); /* Reserved */
635
    }
636

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

658 659 660
    if (track->mode == MODE_MOV && track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
        mov_write_chan_tag(pb, track);

661
    return update_size(pb, pos);
662 663
}

664
static int mov_write_d263_tag(AVIOContext *pb)
665
{
666
    avio_wb32(pb, 0xf); /* size */
667 668
    ffio_wfourcc(pb, "d263");
    ffio_wfourcc(pb, "FFMP");
669
    avio_w8(pb, 0); /* decoder version */
670
    /* FIXME use AVCodecContext level/profile, when encoder will set values */
671 672
    avio_w8(pb, 0xa); /* level */
    avio_w8(pb, 0); /* profile */
673 674 675
    return 0xf;
}

676
/* TODO: No idea about these values */
677
static int mov_write_svq3_tag(AVIOContext *pb)
678
{
679
    avio_wb32(pb, 0x15);
680 681
    ffio_wfourcc(pb, "SMI ");
    ffio_wfourcc(pb, "SEQH");
682 683 684 685
    avio_wb32(pb, 0x5);
    avio_wb32(pb, 0xe2c0211d);
    avio_wb32(pb, 0xc0000000);
    avio_w8(pb, 0);
686
    return 0x15;
687 688
}

689
static int mov_write_avcc_tag(AVIOContext *pb, MOVTrack *track)
690
{
691
    int64_t pos = avio_tell(pb);
692

693
    avio_wb32(pb, 0);
694
    ffio_wfourcc(pb, "avcC");
695 696
    ff_isom_write_avcc(pb, track->vos_data, track->vos_len);
    return update_size(pb, pos);
697 698
}

Tim Walker's avatar
Tim Walker committed
699 700 701 702 703 704 705 706 707 708
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);
}

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

720
    avio_wb32(pb, 24); /* size */
721 722 723
    ffio_wfourcc(pb, "APRG");
    ffio_wfourcc(pb, "APRG");
    ffio_wfourcc(pb, "0001");
724 725
    avio_wb32(pb, 1); /* unknown */
    avio_wb32(pb, 0); /* unknown */
726

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