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

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

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

172
    return update_size(pb, pos);
173 174
}

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

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

207 208 209
    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
210 211 212
    return 0x11;
}

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

220
    if (track->vos_len < 7)
221 222
        return -1;

223
    avio_wb32(pb, 11);
224
    ffio_wfourcc(pb, "dac3");
225

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

    flush_put_bits(&pbc);
252
    avio_write(pb, buf, sizeof(buf));
253 254 255 256

    return 11;
}

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

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

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

281
    avio_wb32(pb, 0); // size
282
    ffio_wfourcc(pb, "esds");
283
    avio_wb32(pb, 0); // Version
Baptiste Coudurier's avatar
Baptiste Coudurier committed
284 285

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

    // DecoderConfig descriptor
291
    put_descr(pb, 0x04, 13 + decoder_specific_info_len);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
292 293

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

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

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

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

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

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

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

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

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

369
    return update_size(pb, pos);
370 371
}

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

376
    avio_wb32(pb, 0);     /* size */
377
    ffio_wfourcc(pb, "wave");
378

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

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

400 401
    avio_wb32(pb, 8);     /* size */
    avio_wb32(pb, 0);     /* null tag */
402

403
    return update_size(pb, pos);
404 405
}

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

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

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

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

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

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

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

581 582 583 584 585
    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 */
586

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

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

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

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

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

642
    return update_size(pb, pos);
643 644
}

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

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

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

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

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

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

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

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

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

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

735 736 737 738 739
    if      (track->enc->codec_id == AV_CODEC_ID_H264)      tag = MKTAG('a','v','c','1');
    else if (track->enc->codec_id == AV_CODEC