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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Martin Storsjö's avatar
Martin Storsjö committed
416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507
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;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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