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 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"
42
#include "rtpenc.h"
43
#include "mov_chan.h"
44

45 46 47
#undef NDEBUG
#include <assert.h>

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

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

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

    return curpos - pos;
86 87
}

88 89 90 91 92 93 94
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;
}

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

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

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

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

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

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

179
    return update_size(pb, pos);
180 181
}

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

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

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

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

227
    if (track->vos_len < 7)
228 229
        return -1;

230
    avio_wb32(pb, 11);
231
    ffio_wfourcc(pb, "dac3");
232

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

    flush_put_bits(&pbc);
259
    avio_write(pb, buf, sizeof(buf));
260 261 262 263

    return 11;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

377
    return update_size(pb, pos);
378 379
}

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

384
    avio_wb32(pb, 0);     /* size */
385
    ffio_wfourcc(pb, "wave");
386

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

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

408 409
    avio_wb32(pb, 8);     /* size */
    avio_wb32(pb, 0);     /* null tag */
410

411
    return update_size(pb, pos);
412 413
}

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

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

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

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

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

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

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

589 590 591 592 593
    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 */
594

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

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

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

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

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

650
    return update_size(pb, pos);
651 652
}

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

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

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

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

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

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

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

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

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

740
    if (!ff_codec_get_tag(ff_mp4_obj_type, track->enc->codec_id))
741