movenc.c 127 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 "movenc.h"
25
#include "avformat.h"
26
#include "avio_internal.h"
27
#include "riff.h"
28
#include "avio.h"
29
#include "isom.h"
30
#include "avc.h"
31
#include "libavcodec/get_bits.h"
32
#include "libavcodec/put_bits.h"
Martin Storsjö's avatar
Martin Storsjö committed
33
#include "libavcodec/vc1.h"
34 35
#include "internal.h"
#include "libavutil/avstring.h"
36
#include "libavutil/intfloat.h"
37
#include "libavutil/mathematics.h"
38
#include "libavutil/opt.h"
39
#include "libavutil/dict.h"
40
#include "rtpenc.h"
41
#include "mov_chan.h"
42

43 44 45
#undef NDEBUG
#include <assert.h>

46
static const AVOption options[] = {
47
    { "movflags", "MOV muxer flags", offsetof(MOVMuxContext, flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
48 49 50 51 52 53
    { "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" },
54
    { "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" },
55
    { "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" },
56
    FF_RTP_FLAG_OPTS(MOVMuxContext, rtp_flags),
57 58 59 60 61 62 63
    { "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},
64 65 66
    { NULL },
};

67 68 69 70 71 72
#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,\
73 74
};

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

    return curpos - pos;
84 85
}

86 87 88 89 90 91 92
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;
}

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

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

121
    int64_t pos = avio_tell(pb);
122
    avio_wb32(pb, 0); /* size */
123
    ffio_wfourcc(pb, "stsz");
124
    avio_wb32(pb, 0); /* version & flags */
125

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

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

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

177
    return update_size(pb, pos);
178 179
}

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

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

212 213 214
    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
215 216 217
    return 0x11;
}

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

225
    if (track->vos_len < 7)
226 227
        return -1;

228
    avio_wb32(pb, 11);
229
    ffio_wfourcc(pb, "dac3");
230

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

    flush_put_bits(&pbc);
257
    avio_write(pb, buf, sizeof(buf));
258 259 260 261

    return 11;
}

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

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

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

286
    avio_wb32(pb, 0); // size
287
    ffio_wfourcc(pb, "esds");
288
    avio_wb32(pb, 0); // Version
Baptiste Coudurier's avatar
Baptiste Coudurier committed
289 290

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

    // DecoderConfig descriptor
296
    put_descr(pb, 0x04, 13 + decoder_specific_info_len);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
297 298

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

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

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

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

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

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

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

344 345 346 347 348 349 350 351 352
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);
}

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

375
    return update_size(pb, pos);
376 377
}

378
static int mov_write_wave_tag(AVIOContext *pb, MOVTrack *track)
379
{
380
    int64_t pos = avio_tell(pb);
381

382
    avio_wb32(pb, 0);     /* size */
383
    ffio_wfourcc(pb, "wave");
384

385
    avio_wb32(pb, 12);    /* size */
386
    ffio_wfourcc(pb, "frma");
387
    avio_wl32(pb, track->tag);
388

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

406 407
    avio_wb32(pb, 8);     /* size */
    avio_wb32(pb, 0);     /* null tag */
408

409
    return update_size(pb, pos);
410 411
}

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

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

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

541 542 543 544 545 546 547 548 549 550 551 552 553 554 555
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;
}

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

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

    if (track->mode == MODE_MOV) {
582 583 584
        if (mov_get_lpcm_flags(track->enc->codec_id))
            tag = AV_RL32("lpcm");
        version = 2;
585
    }
586

587 588 589 590 591
    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 */
592

593
    /* SoundDescription */
594 595 596
    avio_wb16(pb, version); /* Version */
    avio_wb16(pb, 0); /* Revision level */
    avio_wb32(pb, 0); /* Reserved */
597

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

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

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

645 646 647
    if (track->mode == MODE_MOV && track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
        mov_write_chan_tag(pb, track);

648
    return update_size(pb, pos);
649 650
}

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

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

676
static int mov_write_avcc_tag(AVIOContext *pb, MOVTrack *track)
677
{
678
    int64_t pos = avio_tell(pb);
679

680
    avio_wb32(pb, 0);
681
    ffio_wfourcc(pb, "avcC");
682 683
    ff_isom_write_avcc(pb, track->vos_data, track->vos_len);
    return update_size(pb, pos);
684 685
}

686
/* also used by all avid codecs (dv, imx, meridien) and their variants */
687
static int mov_write_avid_tag(AVIOContext *pb, MOVTrack *track)
688 689
{
    int i;
690
    avio_wb32(pb, 24); /* size */
691 692 693
    ffio_wfourcc(pb, "ACLR");
    ffio_wfourcc(pb, "ACLR");
    ffio_wfourcc(pb, "0001");
694
    avio_wb32(pb, 2); /* yuv range: full 1 / normal 2 */
695
    avio_wb32(pb, 0); /* unknown */
696

697
    avio_wb32(pb, 24); /* size */
698 699 700
    ffio_wfourcc(pb, "APRG");
    ffio_wfourcc(pb, "APRG");
    ffio_wfourcc(pb, "0001");
701 702
    avio_wb32(pb, 1); /* unknown */
    avio_wb32(pb, 0); /* unknown */
703

704
    avio_wb32(pb, 120); /* size */
705 706 707
    ffio_wfourcc(pb, "ARES");
    ffio_wfourcc(pb, "ARES");
    ffio_wfourcc(pb, "0001");
708
    avio_wb32(pb, AV_RB32(track->vos_data + 0x28)); /* dnxhd cid, some id ? */
709
    avio_wb32(pb, track->enc->width);
710
    /* values below are based on samples created with quicktime and avid codecs */
711
    if (track->vos_data[5] & 2) { // interlaced
712
        avio_wb32(pb, track->enc->height / 2);
713 714 715
        avio_wb32(pb, 2); /* unknown */
        avio_wb32(pb, 0); /* unknown */
        avio_wb32(pb, 4); /* unknown */
716
    } else {
717 718 719
        avio_wb32(pb, track->enc->height);
        avio_wb32(pb, 1); /* unknown */
        avio_wb32(pb, 0); /* unknown */
720
        if (track->enc->height == 1080)
721
            avio_wb32(pb, 5); /* unknown */
722
        else
723
            avio_wb32(pb, 6); /* unknown */
724 725 726
    }
    /* padding */
    for (i = 0; i < 10; i++)
727
        avio_wb64(pb, 0);
728 729

    /* extra padding for stsd needed */
730
    avio_wb32(pb, 0);
731 732 733
    return 0;
}

734
static int mp4_get_codec_tag(AVFormatContext *s, MOVTrack *track)
735
{
Baptiste Coudurier's avatar
Baptiste Coudurier committed
736
    int tag = track->enc->codec_tag;
737

738
    if (!ff_codec_get_tag(ff_mp4_obj_type, track->enc->codec_id))
739 740
        return 0;

741