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 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 int mov_write_enda_tag(AVIOContext *pb)
268
{
269
    avio_wb32(pb, 10);
270
    ffio_wfourcc(pb, "enda");
271
    avio_wb16(pb, 1); /* little endian */
272 273 274
    return 10;
}

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

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

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

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

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

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

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

316 317
    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
318

319
    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
320
    if(track->enc->rc_max_rate != track->enc->rc_min_rate || track->enc->rc_min_rate==0)
321
        avio_wb32(pb, 0); // vbr
Baptiste Coudurier's avatar
Baptiste Coudurier committed
322
    else
323
        avio_wb32(pb, track->enc->rc_max_rate); // avg bitrate
Baptiste Coudurier's avatar
Baptiste Coudurier committed
324

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

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

337 338 339 340 341 342 343 344
static int mov_pcm_le_gt16(enum CodecID codec_id)
{
    return codec_id == CODEC_ID_PCM_S24LE ||
           codec_id == CODEC_ID_PCM_S32LE ||
           codec_id == CODEC_ID_PCM_F32LE ||
           codec_id == CODEC_ID_PCM_F64LE;
}

345
static int mov_write_ms_tag(AVIOContext *pb, MOVTrack *track)
346
{
347
    int64_t pos = avio_tell(pb);
348 349
    avio_wb32(pb, 0);
    avio_wl32(pb, track->tag); // store it byteswapped
350
    track->enc->codec_tag = av_bswap16(track->tag >> 16);
351
    ff_put_wav_header(pb, track->enc);
352
    return update_size(pb, pos);
353 354
}

355 356 357 358 359 360 361 362 363
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);
}

364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385
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

386
    return update_size(pb, pos);
387 388
}

389
static int mov_write_wave_tag(AVIOContext *pb, MOVTrack *track)
390
{
391
    int64_t pos = avio_tell(pb);
392

393
    avio_wb32(pb, 0);     /* size */
394
    ffio_wfourcc(pb, "wave");
395

396
    avio_wb32(pb, 12);    /* size */
397
    ffio_wfourcc(pb, "frma");
398
    avio_wl32(pb, track->tag);
399

400
    if (track->enc->codec_id == CODEC_ID_AAC) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
401
        /* useless atom needed by mplayer, ipod, not needed by quicktime */
402
        avio_wb32(pb, 12); /* size */
403
        ffio_wfourcc(pb, "mp4a");
404
        avio_wb32(pb, 0);
405
        mov_write_esds_tag(pb, track);
406
    } else if (mov_pcm_le_gt16(track->enc->codec_id)) {
407
        mov_write_enda_tag(pb);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
408
    } else if (track->enc->codec_id == CODEC_ID_AMR_NB) {
409
        mov_write_amr_tag(pb, track);
410
    } else if (track->enc->codec_id == CODEC_ID_AC3) {
411
        mov_write_chan_tag(pb, track);
412
        mov_write_ac3_tag(pb, track);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
413 414
    } else if (track->enc->codec_id == CODEC_ID_ALAC) {
        mov_write_extradata_tag(pb, track);
415 416 417
    } 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);
418
    }
419

420 421
    avio_wb32(pb, 8);     /* size */
    avio_wb32(pb, 0);     /* null tag */
422

423
    return update_size(pb, pos);
424 425
}

Martin Storsjö's avatar
Martin Storsjö committed
426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517
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;
}

518
static int mov_write_glbl_tag(AVIOContext *pb, MOVTrack *track)
519
{
520
    avio_wb32(pb, track->vos_len + 8);
521
    ffio_wfourcc(pb, "glbl");
522 523
    avio_write(pb, track->vos_data, track->vos_len);
    return 8 + track->vos_len;
524 525
}

526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554
/**
 * 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;
    }
}

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

570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588
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;
}

589
static int mov_write_audio_tag(AVIOContext *pb, MOVTrack *track)
590
{
591
    int64_t pos = avio_tell(pb);
592 593 594 595
    int version = 0;
    uint32_t tag = track->tag;

    if (track->mode == MODE_MOV) {
596 597 598
        if (mov_get_lpcm_flags(track->enc->codec_id))
            tag = AV_RL32("lpcm");
        version = 2;
599
    }
600

601 602 603 604 605
    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 */
606

607
    /* SoundDescription */
608 609 610
    avio_wb16(pb, version); /* Version */
    avio_wb16(pb, 0); /* Revision level */
    avio_wb32(pb, 0); /* Reserved */
611

612
    if (version == 2) {
613 614 615 616 617 618
        avio_wb16(pb, 3);
        avio_wb16(pb, 16);
        avio_wb16(pb, 0xfffe);
        avio_wb16(pb, 0);
        avio_wb32(pb, 0x00010000);
        avio_wb32(pb, 72);
619
        avio_wb64(pb, av_double2int(track->enc->sample_rate));
620 621 622 623
        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));
624
        avio_wb32(pb, track->sample_size);
625
        avio_wb32(pb, get_samples_per_packet(track));
626
    } else {
627 628 629 630
        /* reserved for mp4/3gp */
        avio_wb16(pb, 2);
        avio_wb16(pb, 16);
        avio_wb16(pb, 0);
631

632
        avio_wb16(pb, 0); /* packet size (= 0) */
633
        avio_wb16(pb, track->enc->sample_rate);
634
        avio_wb16(pb, 0); /* Reserved */
635
    }
636

637 638
    if(track->mode == MODE_MOV &&
       (track->enc->codec_id == CODEC_ID_AAC ||
639
        track->enc->codec_id == CODEC_ID_AC3 ||
640
        track->enc->codec_id == CODEC_ID_AMR_NB ||
641
        track->enc->codec_id == CODEC_ID_ALAC ||
642 643
        track->enc->codec_id == CODEC_ID_ADPCM_MS ||
        track->enc->codec_id == CODEC_ID_ADPCM_IMA_WAV ||
644
        mov_pcm_le_gt16(track->enc->codec_id)))
645
        mov_write_wave_tag(pb, track);
646
    else if(track->tag == MKTAG('m','p','4','a'))
Baptiste Coudurier's avatar
Baptiste Coudurier committed
647 648
        mov_write_esds_tag(pb, track);
    else if(track->enc->codec_id == CODEC_ID_AMR_NB)
649
        mov_write_amr_tag(pb, track);
650 651
    else if(track->enc->codec_id == CODEC_ID_AC3)
        mov_write_ac3_tag(pb, track);
652
    else if(track->enc->codec_id == CODEC_ID_ALAC)
653
        mov_write_extradata_tag(pb, track);
654 655
    else if (track->enc->codec_id == CODEC_ID_WMAPRO)
        mov_write_wfex_tag(pb, track);
656
    else if (track->vos_len > 0)
657
        mov_write_glbl_tag(pb, track);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
658

659
    return update_size(pb, pos);
660 661
}

662
static int mov_write_d263_tag(AVIOContext *pb)
663
{
664
    avio_wb32(pb, 0xf); /* size */
665 666
    ffio_wfourcc(pb, "d263");
    ffio_wfourcc(pb, "FFMP");
667
    avio_w8(pb, 0); /* decoder version */
668
    /* FIXME use AVCodecContext level/profile, when encoder will set values */
669 670
    avio_w8(pb, 0xa); /* level */
    avio_w8(pb, 0); /* profile */
671 672 673
    return 0xf;
}

674
/* TODO: No idea about these values */
675
static int mov_write_svq3_tag(AVIOContext *pb)
676
{
677
    avio_wb32(pb, 0x15);
678 679
    ffio_wfourcc(pb, "SMI ");
    ffio_wfourcc(pb, "SEQH");
680 681 682 683
    avio_wb32(pb, 0x5);
    avio_wb32(pb, 0xe2c0211d);
    avio_wb32(pb, 0xc0000000);
    avio_w8(pb, 0);
684
    return 0x15;
685 686
}

687
static int mov_write_avcc_tag(AVIOContext *pb, MOVTrack *track)
688
{
689
    int64_t pos = avio_tell(pb);
690

691
    avio_wb32(pb, 0);
692
    ffio_wfourcc(pb, "avcC");
693 694
    ff_isom_write_avcc(pb, track->vos_data, track->vos_len);
    return update_size(pb, pos);
695 696
}

697
/* also used by all avid codecs (dv, imx, meridien) and their variants */
698
static int mov_write_avid_tag(AVIOContext *pb, MOVTrack *track)
699 700
{
    int i;
701
    avio_wb32(pb, 24); /* size */
702 703 704
    ffio_wfourcc(pb, "ACLR");
    ffio_wfourcc(pb, "ACLR");
    ffio_wfourcc(pb, "0001");
705
    avio_wb32(pb, 2); /* yuv range: full 1 / normal 2 */
706
    avio_wb32(pb, 0); /* unknown */
707

708
    avio_wb32(pb, 24); /* size */
709 710 711
    ffio_wfourcc(pb, "APRG");
    ffio_wfourcc(pb, "APRG");
    ffio_wfourcc(pb, "0001");
712 713
    avio_wb32(pb, 1); /* unknown */
    avio_wb32(pb, 0); /* unknown */
714

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

    /* extra padding for stsd needed */
741
    avio_wb32(pb, 0);
742 743 744
    return 0;
}

745
static int mp4_get_codec_tag(AVFormatContext *s, MOVTrack *track)
746
{
Baptiste Coudurier's avatar
Baptiste Coudurier committed