movenc.c 115 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 309
    avio_w8(pb,  track->enc->rc_buffer_size>>(3+16));      // Buffersize DB (24 bits)
    avio_wb16(pb, (track->enc->rc_buffer_size>>3)&0xFFFF); // Buffersize DB
Baptiste Coudurier's avatar
Baptiste Coudurier committed
310

311
    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
312
    if(track->enc->rc_max_rate != track->enc->rc_min_rate || track->enc->rc_min_rate==0)
313
        avio_wb32(pb, 0); // vbr
Baptiste Coudurier's avatar
Baptiste Coudurier committed
314
    else
315
        avio_wb32(pb, track->enc->rc_max_rate); // avg bitrate
Baptiste Coudurier's avatar
Baptiste Coudurier committed
316

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

736 737 738 739 740