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 48
    { "movflags", "MOV muxer flags", offsetof(MOVMuxContext, flags), AV_OPT_TYPE_FLAGS, {.dbl = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
    { "rtphint", "Add RTP hint tracks", 0, AV_OPT_TYPE_CONST, {.dbl = FF_MOV_FLAG_RTP_HINT}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
49 50 51
    { "empty_moov", "Make the initial moov atom empty (not supported by QuickTime)", 0, AV_OPT_TYPE_CONST, {.dbl = 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, {.dbl = 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, {.dbl = FF_MOV_FLAG_SEPARATE_MOOF}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
52
    { "frag_custom", "Flush fragments on caller requests", 0, AV_OPT_TYPE_CONST, {.dbl = FF_MOV_FLAG_FRAG_CUSTOM}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
53
    { "isml", "Create a live smooth streaming feed (for pushing to a publishing point)", 0, AV_OPT_TYPE_CONST, {.dbl = 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
    { "skip_iods", "Skip writing iods atom.", offsetof(MOVMuxContext, iods_skip), AV_OPT_TYPE_INT, {.dbl = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
    { "iods_audio_profile", "iods audio profile atom.", offsetof(MOVMuxContext, iods_audio_profile), AV_OPT_TYPE_INT, {.dbl = -1}, -1, 255, AV_OPT_FLAG_ENCODING_PARAM},
    { "iods_video_profile", "iods video profile atom.", offsetof(MOVMuxContext, iods_video_profile), AV_OPT_TYPE_INT, {.dbl = -1}, -1, 255, AV_OPT_FLAG_ENCODING_PARAM},
58
    { "frag_duration", "Maximum fragment duration", offsetof(MOVMuxContext, max_fragment_duration), AV_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
59
    { "min_frag_duration", "Minimum fragment duration", offsetof(MOVMuxContext, min_fragment_duration), AV_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
60
    { "frag_size", "Maximum fragment size", offsetof(MOVMuxContext, max_fragment_size), AV_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
61
    { "ism_lookahead", "Number of lookahead entries for ISM files", offsetof(MOVMuxContext, ism_lookahead), AV_OPT_TYPE_INT, {.dbl = 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 == CODEC_ID_MP2 ||
         track->enc->codec_id == 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 == 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);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
390
    } else if (track->enc->codec_id == CODEC_ID_AMR_NB) {
391
        mov_write_amr_tag(pb, track);
392
    } else if (track->enc->codec_id == CODEC_ID_AC3) {
393
        mov_write_chan_tag(pb, track);
394
        mov_write_ac3_tag(pb, track);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
395 396
    } else if (track->enc->codec_id == CODEC_ID_ALAC) {
        mov_write_extradata_tag(pb, track);
397 398 399
    } else if (track->enc->codec_id == CODEC_ID_ADPCM_MS ||
               track->enc->codec_id == CODEC_ID_ADPCM_IMA_WAV) {
        mov_write_ms_tag(pb, track);
400
    }
401

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

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

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

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

508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536
/**
 * Compute flags for 'lpcm' tag.
 * See CoreAudioTypes and AudioStreamBasicDescription at Apple.
 */
static int mov_get_lpcm_flags(enum CodecID codec_id)
{
    switch (codec_id) {
    case CODEC_ID_PCM_F32BE:
    case CODEC_ID_PCM_F64BE:
        return 11;
    case CODEC_ID_PCM_F32LE:
    case CODEC_ID_PCM_F64LE:
        return 9;
    case CODEC_ID_PCM_U8:
        return 10;
    case CODEC_ID_PCM_S16BE:
    case CODEC_ID_PCM_S24BE:
    case CODEC_ID_PCM_S32BE:
        return 14;
    case CODEC_ID_PCM_S8:
    case CODEC_ID_PCM_S16LE:
    case CODEC_ID_PCM_S24LE:
    case CODEC_ID_PCM_S32LE:
        return 12;
    default:
        return 0;
    }
}

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

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

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

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

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

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

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

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

620 621
    if(track->mode == MODE_MOV &&
       (track->enc->codec_id == CODEC_ID_AAC ||
622
        track->enc->codec_id == CODEC_ID_AC3 ||
623
        track->enc->codec_id == CODEC_ID_AMR_NB ||
624
        track->enc->codec_id == CODEC_ID_ALAC ||
625
        track->enc->codec_id == CODEC_ID_ADPCM_MS ||
626
        track->enc->codec_id == CODEC_ID_ADPCM_IMA_WAV))
627
        mov_write_wave_tag(pb, track);
628
    else if(track->tag == MKTAG('m','p','4','a'))
Baptiste Coudurier's avatar
Baptiste Coudurier committed
629 630
        mov_write_esds_tag(pb, track);
    else if(track->enc->codec_id == CODEC_ID_AMR_NB)
631
        mov_write_amr_tag(pb, track);
632 633
    else if(track->enc->codec_id == CODEC_ID_AC3)
        mov_write_ac3_tag(pb, track);
634
    else if(track->enc->codec_id == CODEC_ID_ALAC)
635
        mov_write_extradata_tag(pb, track);
636 637
    else if (track->enc->codec_id == CODEC_ID_WMAPRO)
        mov_write_wfex_tag(pb, track);
638
    else if (track->vos_len > 0)
639
        mov_write_glbl_tag(pb, track);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
640

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

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

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

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

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

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

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

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

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

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

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

    if      (track->enc->codec_id == CODEC_ID_H264)      tag = MKTAG('a','v','c','1');
    else if (track->enc->codec_id == CODEC_ID_AC3)       tag = MKTAG('a','c','-','3');
    else if (track->enc->codec_id == CODEC_ID_DIRAC)     tag = MKTAG('d','r','a','c');
    else if (track->enc->codec_id == CODEC_ID_MOV_TEXT)  tag = MKTAG('t','x','3','g');
Martin Storsjö's avatar
Martin Storsjö committed
738
    else if (track->enc->codec_id == CODEC_ID_VC1)       tag = MKTAG('v','c','-','1');
739 740
    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');
741 742 743 744

    return tag;
}

745