movenc.c 116 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
    FF_RTP_FLAG_OPTS(MOVMuxContext, rtp_flags),
55 56 57 58 59 60 61
    { "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},
62 63 64
    { NULL },
};

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

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

    return curpos - pos;
82 83
}

84
/* Chunk offset atom */
85
static int mov_write_stco_tag(AVIOContext *pb, MOVTrack *track)
86 87
{
    int i;
Benjamin Larsson's avatar
Benjamin Larsson committed
88
    int mode64 = 0; //   use 32 bit size variant if possible
89
    int64_t pos = avio_tell(pb);
90
    avio_wb32(pb, 0); /* size */
91 92
    if (pos > UINT32_MAX) {
        mode64 = 1;
93
        ffio_wfourcc(pb, "co64");
94
    } else
95
        ffio_wfourcc(pb, "stco");
96 97
    avio_wb32(pb, 0); /* version & flags */
    avio_wb32(pb, track->entry); /* entry count */
98 99
    for (i = 0; i < track->entry; i++) {
        if (mode64 == 1)
100
            avio_wb64(pb, track->cluster[i].pos + track->data_offset);
101
        else
102
            avio_wb32(pb, track->cluster[i].pos + track->data_offset);
103
    }
104
    return update_size(pb, pos);
105 106
}

107
/* Sample size atom */
108
static int mov_write_stsz_tag(AVIOContext *pb, MOVTrack *track)
109
{
110
    int equalChunks = 1;
111
    int i, j, entries = 0, tst = -1, oldtst = -1;
112

113
    int64_t pos = avio_tell(pb);
114
    avio_wb32(pb, 0); /* size */
115
    ffio_wfourcc(pb, "stsz");
116
    avio_wb32(pb, 0); /* version & flags */
117

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

143
/* Sample to chunk atom */
144
static int mov_write_stsc_tag(AVIOContext *pb, MOVTrack *track)
145
{
146
    int index = 0, oldval = -1, i;
147
    int64_t entryPos, curpos;
148

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

169
    return update_size(pb, pos);
170 171
}

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

196
static int mov_write_amr_tag(AVIOContext *pb, MOVTrack *track)
197
{
198
    avio_wb32(pb, 0x11); /* size */
199 200 201
    if (track->mode == MODE_MOV) ffio_wfourcc(pb, "samr");
    else                         ffio_wfourcc(pb, "damr");
    ffio_wfourcc(pb, "FFMP");
202
    avio_w8(pb, 0); /* decoder version */
Baptiste Coudurier's avatar
Baptiste Coudurier committed
203

204 205 206
    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
207 208 209
    return 0x11;
}

210
static int mov_write_ac3_tag(AVIOContext *pb, MOVTrack *track)
211 212 213 214 215 216
{
    GetBitContext gbc;
    PutBitContext pbc;
    uint8_t buf[3];
    int fscod, bsid, bsmod, acmod, lfeon, frmsizecod;

217
    if (track->vos_len < 7)
218 219
        return -1;

220
    avio_wb32(pb, 11);
221
    ffio_wfourcc(pb, "dac3");
222

223
    init_get_bits(&gbc, track->vos_data + 4, (track->vos_len - 4) * 8);
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
    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);
245
    put_bits(&pbc, 5, frmsizecod >> 1); // bit_rate_code
246 247 248
    put_bits(&pbc, 5, 0); // reserved

    flush_put_bits(&pbc);
249
    avio_write(pb, buf, sizeof(buf));
250 251 252 253

    return 11;
}

Baptiste Coudurier's avatar
Baptiste Coudurier committed
254 255
/**
 * This function writes extradata "as is".
Diego Biurrun's avatar
Diego Biurrun committed
256
 * Extradata must be formatted like a valid atom (with size and tag).
Baptiste Coudurier's avatar
Baptiste Coudurier committed
257
 */
258
static int mov_write_extradata_tag(AVIOContext *pb, MOVTrack *track)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
259
{
260
    avio_write(pb, track->enc->extradata, track->enc->extradata_size);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
261 262 263
    return track->enc->extradata_size;
}

264
static void put_descr(AVIOContext *pb, int tag, unsigned int size)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
265
{
266
    int i = 3;
267
    avio_w8(pb, tag);
268 269
    for (; i > 0; i--)
        avio_w8(pb, (size >> (7 * i)) | 0x80);
270
    avio_w8(pb, size & 0x7F);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
271 272
}

273
static int mov_write_esds_tag(AVIOContext *pb, MOVTrack *track) // Basic
Baptiste Coudurier's avatar
Baptiste Coudurier committed
274
{
275
    int64_t pos = avio_tell(pb);
276
    int decoder_specific_info_len = track->vos_len ? 5 + track->vos_len : 0;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
277

278
    avio_wb32(pb, 0); // size
279
    ffio_wfourcc(pb, "esds");
280
    avio_wb32(pb, 0); // Version
Baptiste Coudurier's avatar
Baptiste Coudurier committed
281 282

    // ES descriptor
283 284
    put_descr(pb, 0x03, 3 + 5+13 + decoder_specific_info_len + 5+1);
    avio_wb16(pb, track->track_id);
285
    avio_w8(pb, 0x00); // flags (= no flags)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
286 287

    // DecoderConfig descriptor
288
    put_descr(pb, 0x04, 13 + decoder_specific_info_len);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
289 290

    // Object type indication
291 292
    if ((track->enc->codec_id == AV_CODEC_ID_MP2 ||
         track->enc->codec_id == AV_CODEC_ID_MP3) &&
293
        track->enc->sample_rate > 24000)
294
        avio_w8(pb, 0x6B); // 11172-3
295
    else
296
        avio_w8(pb, ff_codec_get_tag(ff_mp4_obj_type, track->enc->codec_id));
Baptiste Coudurier's avatar
Baptiste Coudurier committed
297 298 299

    // 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)
300
    if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
301
        avio_w8(pb, 0x15); // flags (= Audiostream)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
302
    else
303
        avio_w8(pb, 0x11); // flags (= Visualstream)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
304

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

307
    avio_wb32(pb, FFMAX(track->enc->bit_rate, track->enc->rc_max_rate)); // maxbitrate (FIXME should be max rate in any 1 sec window)
308 309
    if (track->enc->rc_max_rate != track->enc->rc_min_rate ||
        track->enc->rc_min_rate == 0)
310
        avio_wb32(pb, 0); // vbr
Baptiste Coudurier's avatar
Baptiste Coudurier committed
311
    else
312
        avio_wb32(pb, track->enc->rc_max_rate); // avg bitrate
Baptiste Coudurier's avatar
Baptiste Coudurier committed
313

314
    if (track->vos_len) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
315
        // DecoderSpecific info descriptor
316 317
        put_descr(pb, 0x05, track->vos_len);
        avio_write(pb, track->vos_data, track->vos_len);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
318 319 320
    }

    // SL descriptor
321
    put_descr(pb, 0x06, 1);
322
    avio_w8(pb, 0x02);
323
    return update_size(pb, pos);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
324 325
}

326
static int mov_write_ms_tag(AVIOContext *pb, MOVTrack *track)
327
{
328
    int64_t pos = avio_tell(pb);
329 330
    avio_wb32(pb, 0);
    avio_wl32(pb, track->tag); // store it byteswapped
331
    track->enc->codec_tag = av_bswap16(track->tag >> 16);
332
    ff_put_wav_header(pb, track->enc);
333
    return update_size(pb, pos);
334 335
}

336 337 338 339 340 341 342 343 344
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);
}

345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366
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

367
    return update_size(pb, pos);
368 369
}

370
static int mov_write_wave_tag(AVIOContext *pb, MOVTrack *track)
371
{
372
    int64_t pos = avio_tell(pb);
373

374
    avio_wb32(pb, 0);     /* size */
375
    ffio_wfourcc(pb, "wave");
376

377
    avio_wb32(pb, 12);    /* size */
378
    ffio_wfourcc(pb, "frma");
379
    avio_wl32(pb, track->tag);
380

381
    if (track->enc->codec_id == AV_CODEC_ID_AAC) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
382
        /* useless atom needed by mplayer, ipod, not needed by quicktime */
383
        avio_wb32(pb, 12); /* size */
384
        ffio_wfourcc(pb, "mp4a");
385
        avio_wb32(pb, 0);
386
        mov_write_esds_tag(pb, track);
387
    } else if (track->enc->codec_id == AV_CODEC_ID_AMR_NB) {
388
        mov_write_amr_tag(pb, track);
389
    } else if (track->enc->codec_id == AV_CODEC_ID_AC3) {
390
        mov_write_ac3_tag(pb, track);
391
    } else if (track->enc->codec_id == AV_CODEC_ID_ALAC) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
392
        mov_write_extradata_tag(pb, track);
393 394
    } else if (track->enc->codec_id == AV_CODEC_ID_ADPCM_MS ||
               track->enc->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) {
395
        mov_write_ms_tag(pb, track);
396
    }
397

398 399
    avio_wb32(pb, 8);     /* size */
    avio_wb32(pb, 0);     /* null tag */
400

401
    return update_size(pb, pos);
402 403
}

Martin Storsjö's avatar
Martin Storsjö committed
404 405 406 407 408 409 410 411 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
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;
}

496
static int mov_write_glbl_tag(AVIOContext *pb, MOVTrack *track)
497
{
498
    avio_wb32(pb, track->vos_len + 8);
499
    ffio_wfourcc(pb, "glbl");
500 501
    avio_write(pb, track->vos_data, track->vos_len);
    return 8 + track->vos_len;
502 503
}

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

533 534 535 536 537 538 539 540 541 542 543 544 545 546 547
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;
}

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

567
static int mov_write_audio_tag(AVIOContext *pb, MOVTrack *track)
568
{
569
    int64_t pos = avio_tell(pb);
570 571 572 573
    int version = 0;
    uint32_t tag = track->tag;

    if (track->mode == MODE_MOV) {
574 575 576
        if (mov_get_lpcm_flags(track->enc->codec_id))
            tag = AV_RL32("lpcm");
        version = 2;
577
    }
578

579 580 581 582 583
    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 */
584

585
    /* SoundDescription */
586 587 588
    avio_wb16(pb, version); /* Version */
    avio_wb16(pb, 0); /* Revision level */
    avio_wb32(pb, 0); /* Reserved */
589

590
    if (version == 2) {
591 592 593 594 595 596
        avio_wb16(pb, 3);
        avio_wb16(pb, 16);
        avio_wb16(pb, 0xfffe);
        avio_wb16(pb, 0);
        avio_wb32(pb, 0x00010000);
        avio_wb32(pb, 72);
597
        avio_wb64(pb, av_double2int(track->enc->sample_rate));
598 599 600 601
        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));
602
        avio_wb32(pb, track->sample_size);
603
        avio_wb32(pb, get_samples_per_packet(track));
604
    } else {
605 606 607 608
        /* reserved for mp4/3gp */
        avio_wb16(pb, 2);
        avio_wb16(pb, 16);
        avio_wb16(pb, 0);
609

610
        avio_wb16(pb, 0); /* packet size (= 0) */
611 612
        avio_wb16(pb, track->enc->sample_rate <= UINT16_MAX ?
                      track->enc->sample_rate : 0);
613
        avio_wb16(pb, 0); /* Reserved */
614
    }
615

616 617 618 619 620 621 622
    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))
623
        mov_write_wave_tag(pb, track);
624
    else if (track->tag == MKTAG('m','p','4','a'))
Baptiste Coudurier's avatar
Baptiste Coudurier committed
625
        mov_write_esds_tag(pb, track);
626
    else if (track->enc->codec_id == AV_CODEC_ID_AMR_NB)
627
        mov_write_amr_tag(pb, track);
628
    else if (track->enc->codec_id == AV_CODEC_ID_AC3)
629
        mov_write_ac3_tag(pb, track);
630
    else if (track->enc->codec_id == AV_CODEC_ID_ALAC)
631
        mov_write_extradata_tag(pb, track);
632
    else if (track->enc->codec_id == AV_CODEC_ID_WMAPRO)
633
        mov_write_wfex_tag(pb, track);
634
    else if (track->vos_len > 0)
635
        mov_write_glbl_tag(pb, track);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
636

637 638 639
    if (track->mode == MODE_MOV && track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
        mov_write_chan_tag(pb, track);

640
    return update_size(pb, pos);
641 642
}

643
static int mov_write_d263_tag(AVIOContext *pb)
644
{
645
    avio_wb32(pb, 0xf); /* size */
646 647
    ffio_wfourcc(pb, "d263");
    ffio_wfourcc(pb, "FFMP");
648
    avio_w8(pb, 0); /* decoder version */
649
    /* FIXME use AVCodecContext level/profile, when encoder will set values */
650 651
    avio_w8(pb, 0xa); /* level */
    avio_w8(pb, 0); /* profile */
652 653 654
    return 0xf;
}

655
/* TODO: No idea about these values */
656
static int mov_write_svq3_tag(AVIOContext *pb)
657
{
658
    avio_wb32(pb, 0x15);
659 660
    ffio_wfourcc(pb, "SMI ");
    ffio_wfourcc(pb, "SEQH");
661 662 663 664
    avio_wb32(pb, 0x5);
    avio_wb32(pb, 0xe2c0211d);
    avio_wb32(pb, 0xc0000000);
    avio_w8(pb, 0);
665
    return 0x15;
666 667
}

668
static int mov_write_avcc_tag(AVIOContext *pb, MOVTrack *track)
669
{
670
    int64_t pos = avio_tell(pb);
671

672
    avio_wb32(pb, 0);
673
    ffio_wfourcc(pb, "avcC");
674 675
    ff_isom_write_avcc(pb, track->vos_data, track->vos_len);
    return update_size(pb, pos);
676 677
}

678
/* also used by all avid codecs (dv, imx, meridien) and their variants */
679
static int mov_write_avid_tag(AVIOContext *pb, MOVTrack *track)
680 681
{
    int i;
682
    avio_wb32(pb, 24); /* size */
683 684 685
    ffio_wfourcc(pb, "ACLR");
    ffio_wfourcc(pb, "ACLR");
    ffio_wfourcc(pb, "0001");
686
    avio_wb32(pb, 2); /* yuv range: full 1 / normal 2 */
687
    avio_wb32(pb, 0); /* unknown */
688

689
    avio_wb32(pb, 24); /* size */
690 691 692
    ffio_wfourcc(pb, "APRG");
    ffio_wfourcc(pb, "APRG");
    ffio_wfourcc(pb, "0001");
693 694
    avio_wb32(pb, 1); /* unknown */
    avio_wb32(pb, 0); /* unknown */
695

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

    /* extra padding for stsd needed */
722
    avio_wb32(pb, 0);
723 724 725
    return 0;
}

726
static int mp4_get_codec_tag(AVFormatContext *s, MOVTrack *track)
727
{
Baptiste Coudurier's avatar
Baptiste Coudurier committed
728
    int tag = track->enc->codec_tag;
729

730
    if (!ff_codec_get_tag(ff_mp4_obj_type, track->enc->codec_id))
731 732
        return 0;

733 734 735 736 737
    if      (track->enc->codec_id == AV_CODEC_ID_H264)      tag = MKTAG('a','v','c','1');
    else if (track->enc->codec_id == AV_CODEC_ID_AC3)       tag = MKTAG('a','c','-','3');
    else if (track->enc->codec_id == AV_CODEC_ID_DIRAC)     tag = MKTAG('d','r','a','c');
    else if (track->enc->codec_id == AV_CODEC_ID_MOV_TEXT)  tag = MKTAG('t','x','3','g');
    else if (track->enc->codec_id == AV_CODEC_ID_VC1)       tag = MKTAG('v','c','-','1');
738 739
    else if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO)  tag = MKTAG('m','p','4','v');
    else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO)  tag = MKTAG('m','p','4','a');
740