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 59
    { "frag_duration", "Maximum fragment duration", offsetof(MOVMuxContext, max_fragment_duration), AV_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
    { "frag_size", "Maximum fragment size", offsetof(MOVMuxContext, max_fragment_size), AV_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
60
    { "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},
61 62 63
    { NULL },
};

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

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

    return curpos - pos;
81 82
}

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

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

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

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

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

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

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

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

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

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

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

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

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

225
    init_get_bits(&gbc, track->vos_data + 4, (track->vos_len - 4) * 8);
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
    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);
251
    avio_write(pb, buf, sizeof(buf));
252 253 254 255

    return 11;
}

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

266
static int mov_write_enda_tag(AVIOContext *pb)
267
{
268
    avio_wb32(pb, 10);
269
    ffio_wfourcc(pb, "enda");
270
    avio_wb16(pb, 1); /* little endian */
271 272 273
    return 10;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Martin Storsjö's avatar
Martin Storsjö committed
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 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516
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;
}

517
static int mov_write_glbl_tag(AVIOContext *pb, MOVTrack *track)
518
{
519
    avio_wb32(pb, track->vos_len + 8);
520
    ffio_wfourcc(pb, "glbl");
521 522
    avio_write(pb, track->vos_data, track->vos_len);
    return 8 + track->vos_len;
523 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
/**
 * 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;
    }
}

554
static int mov_write_audio_tag(AVIOContext *pb, MOVTrack *track)
555
{
556
    int64_t pos = avio_tell(pb);
557 558 559 560
    int version = 0;
    uint32_t tag = track->tag;

    if (track->mode == MODE_MOV) {
561 562 563
        if (mov_get_lpcm_flags(track->enc->codec_id))
            tag = AV_RL32("lpcm");
        version = 2;
564
    }
565

566 567 568 569 570
    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 */
571

572
    /* SoundDescription */
573 574 575
    avio_wb16(pb, version); /* Version */
    avio_wb16(pb, 0); /* Revision level */
    avio_wb32(pb, 0); /* Reserved */
576

577
    if (version == 2) {
578 579 580 581 582 583
        avio_wb16(pb, 3);
        avio_wb16(pb, 16);
        avio_wb16(pb, 0xfffe);
        avio_wb16(pb, 0);
        avio_wb32(pb, 0x00010000);
        avio_wb32(pb, 72);
584
        avio_wb64(pb, av_double2int(track->enc->sample_rate));
585 586 587 588
        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));
589
        avio_wb32(pb, track->sample_size);
590
        avio_wb32(pb, track->audio_vbr ? track->enc->frame_size : 1);
591
    } else {
592 593 594 595
        /* reserved for mp4/3gp */
        avio_wb16(pb, 2);
        avio_wb16(pb, 16);
        avio_wb16(pb, 0);
596

597
        avio_wb16(pb, 0); /* packet size (= 0) */
598
        avio_wb16(pb, track->enc->sample_rate);
599
        avio_wb16(pb, 0); /* Reserved */
600
    }
601

602 603
    if(track->mode == MODE_MOV &&
       (track->enc->codec_id == CODEC_ID_AAC ||
604
        track->enc->codec_id == CODEC_ID_AC3 ||
605
        track->enc->codec_id == CODEC_ID_AMR_NB ||
606
        track->enc->codec_id == CODEC_ID_ALAC ||
607 608
        track->enc->codec_id == CODEC_ID_ADPCM_MS ||
        track->enc->codec_id == CODEC_ID_ADPCM_IMA_WAV ||
609
        mov_pcm_le_gt16(track->enc->codec_id)))
610
        mov_write_wave_tag(pb, track);
611
    else if(track->tag == MKTAG('m','p','4','a'))
Baptiste Coudurier's avatar
Baptiste Coudurier committed
612 613
        mov_write_esds_tag(pb, track);
    else if(track->enc->codec_id == CODEC_ID_AMR_NB)
614
        mov_write_amr_tag(pb, track);
615 616
    else if(track->enc->codec_id == CODEC_ID_AC3)
        mov_write_ac3_tag(pb, track);
617
    else if(track->enc->codec_id == CODEC_ID_ALAC)
618
        mov_write_extradata_tag(pb, track);
619 620
    else if (track->enc->codec_id == CODEC_ID_WMAPRO)
        mov_write_wfex_tag(pb, track);
621
    else if (track->vos_len > 0)
622
        mov_write_glbl_tag(pb, track);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
623

624
    return update_size(pb, pos);
625 626
}

627
static int mov_write_d263_tag(AVIOContext *pb)
628
{
629
    avio_wb32(pb, 0xf); /* size */
630 631
    ffio_wfourcc(pb, "d263");
    ffio_wfourcc(pb, "FFMP");
632
    avio_w8(pb, 0); /* decoder version */
633
    /* FIXME use AVCodecContext level/profile, when encoder will set values */
634 635
    avio_w8(pb, 0xa); /* level */
    avio_w8(pb, 0); /* profile */
636 637 638
    return 0xf;
}

639
/* TODO: No idea about these values */
640
static int mov_write_svq3_tag(AVIOContext *pb)
641
{
642
    avio_wb32(pb, 0x15);
643 644
    ffio_wfourcc(pb, "SMI ");
    ffio_wfourcc(pb, "SEQH");
645 646 647 648
    avio_wb32(pb, 0x5);
    avio_wb32(pb, 0xe2c0211d);
    avio_wb32(pb, 0xc0000000);
    avio_w8(pb, 0);
649
    return 0x15;
650 651
}

652
static int mov_write_avcc_tag(AVIOContext *pb, MOVTrack *track)
653
{
654
    int64_t pos = avio_tell(pb);
655

656
    avio_wb32(pb, 0);
657
    ffio_wfourcc(pb, "avcC");
658 659
    ff_isom_write_avcc(pb, track->vos_data, track->vos_len);
    return update_size(pb, pos);
660 661
}

662
/* also used by all avid codecs (dv, imx, meridien) and their variants */
663
static int mov_write_avid_tag(AVIOContext *pb, MOVTrack *track)
664 665
{
    int i;
666
    avio_wb32(pb, 24); /* size */
667 668 669
    ffio_wfourcc(pb, "ACLR");
    ffio_wfourcc(pb, "ACLR");
    ffio_wfourcc(pb, "0001");
670
    avio_wb32(pb, 2); /* yuv range: full 1 / normal 2 */
671
    avio_wb32(pb, 0); /* unknown */
672

673
    avio_wb32(pb, 24); /* size */
674 675 676
    ffio_wfourcc(pb, "APRG");
    ffio_wfourcc(pb, "APRG");
    ffio_wfourcc(pb, "0001");
677 678
    avio_wb32(pb, 1); /* unknown */
    avio_wb32(pb, 0); /* unknown */
679

680
    avio_wb32(pb, 120); /* size */
681 682 683
    ffio_wfourcc(pb, "ARES");
    ffio_wfourcc(pb, "ARES");
    ffio_wfourcc(pb, "0001");
684
    avio_wb32(pb, AV_RB32(track->vos_data + 0x28)); /* dnxhd cid, some id ? */
685
    avio_wb32(pb, track->enc->width);
686
    /* values below are based on samples created with quicktime and avid codecs */
687
    if (track->vos_data[5] & 2) { // interlaced
688 689 690 691
        avio_wb32(pb, track->enc->height/2);
        avio_wb32(pb, 2); /* unknown */
        avio_wb32(pb, 0); /* unknown */
        avio_wb32(pb, 4); /* unknown */
692
    } else {
693 694 695
        avio_wb32(pb, track->enc->height);
        avio_wb32(pb, 1); /* unknown */
        avio_wb32(pb, 0); /* unknown */
696
        if (track->enc->height == 1080)
697
            avio_wb32(pb, 5); /* unknown */
698
        else
699
            avio_wb32(pb, 6); /* unknown */
700 701 702
    }
    /* padding */
    for (i = 0; i < 10; i++)
703
        avio_wb64(pb, 0);
704 705

    /* extra padding for stsd needed */
706
    avio_wb32(pb, 0);
707 708 709
    return 0;
}

710
static int mp4_get_codec_tag(AVFormatContext *s, MOVTrack *track)
711
{
Baptiste Coudurier's avatar
Baptiste Coudurier committed
712
    int tag = track->enc->codec_tag;
713

714
    if (!ff_codec_get_tag(ff_mp4_obj_type, track->enc->codec_id))
715 716 717 718 719 720
        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
721
    else if (track->enc->codec_id == CODEC_ID_VC1)       tag = MKTAG('v','c','-','1');
722 723
    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');
724 725 726 727

    return tag;
}

728 729 730 731 732 733