movenc.c 132 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 <stdint.h>
25
#include <inttypes.h>
26

27
#include "movenc.h"
28
#include "avformat.h"
29
#include "avio_internal.h"
30
#include "riff.h"
31
#include "avio.h"
32
#include "isom.h"
33
#include "avc.h"
34
#include "libavcodec/get_bits.h"
35
#include "libavcodec/put_bits.h"
36
#include "libavcodec/vc1.h"
37 38
#include "internal.h"
#include "libavutil/avstring.h"
39
#include "libavutil/intfloat.h"
40
#include "libavutil/mathematics.h"
41
#include "libavutil/opt.h"
42
#include "libavutil/dict.h"
43
#include "hevc.h"
44
#include "rtpenc.h"
45
#include "mov_chan.h"
46

47 48 49
#undef NDEBUG
#include <assert.h>

50
static const AVOption options[] = {
51
    { "movflags", "MOV muxer flags", offsetof(MOVMuxContext, flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
52 53 54 55 56 57
    { "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" },
58
    { "faststart", "Run a second pass to put the index (moov atom) at the beginning of the file", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_FASTSTART}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
59
    { "omit_tfhd_offset", "Omit the base data offset in tfhd atoms", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_OMIT_TFHD_OFFSET}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
60
    FF_RTP_FLAG_OPTS(MOVMuxContext, rtp_flags),
61 62 63 64 65 66 67
    { "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},
68
    { "brand",    "Override major brand", offsetof(MOVMuxContext, major_brand),   AV_OPT_TYPE_STRING, {.str = NULL}, .flags = AV_OPT_FLAG_ENCODING_PARAM },
69 70 71
    { NULL },
};

72 73 74 75 76 77
#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,\
78 79
};

Diego Biurrun's avatar
Diego Biurrun committed
80
//FIXME support 64 bit variant with wide placeholders
81
static int64_t update_size(AVIOContext *pb, int64_t pos)
82
{
83
    int64_t curpos = avio_tell(pb);
84
    avio_seek(pb, pos, SEEK_SET);
85
    avio_wb32(pb, curpos - pos); /* rewrite size */
86
    avio_seek(pb, curpos, SEEK_SET);
87 88

    return curpos - pos;
89 90
}

91 92 93 94 95 96 97
static int co64_required(const MOVTrack *track)
{
    if (track->entry > 0 && track->cluster[track->entry - 1].pos + track->data_offset > UINT32_MAX)
        return 1;
    return 0;
}

98
/* Chunk offset atom */
99
static int mov_write_stco_tag(AVIOContext *pb, MOVTrack *track)
100 101
{
    int i;
102
    int mode64 = co64_required(track); // use 32 bit size variant if possible
103
    int64_t pos = avio_tell(pb);
104
    avio_wb32(pb, 0); /* size */
105
    if (mode64) {
106
        ffio_wfourcc(pb, "co64");
107
    } else
108
        ffio_wfourcc(pb, "stco");
109 110
    avio_wb32(pb, 0); /* version & flags */
    avio_wb32(pb, track->entry); /* entry count */
111 112
    for (i = 0; i < track->entry; i++) {
        if (mode64 == 1)
113
            avio_wb64(pb, track->cluster[i].pos + track->data_offset);
114
        else
115
            avio_wb32(pb, track->cluster[i].pos + track->data_offset);
116
    }
117
    return update_size(pb, pos);
118 119
}

120
/* Sample size atom */
121
static int mov_write_stsz_tag(AVIOContext *pb, MOVTrack *track)
122
{
123
    int equalChunks = 1;
124
    int i, j, entries = 0, tst = -1, oldtst = -1;
125

126
    int64_t pos = avio_tell(pb);
127
    avio_wb32(pb, 0); /* size */
128
    ffio_wfourcc(pb, "stsz");
129
    avio_wb32(pb, 0); /* version & flags */
130

131 132 133
    for (i = 0; i < track->entry; i++) {
        tst = track->cluster[i].size / track->cluster[i].entries;
        if (oldtst != -1 && tst != oldtst)
134
            equalChunks = 0;
135
        oldtst = tst;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
136
        entries += track->cluster[i].entries;
137
    }
138
    if (equalChunks && track->entry) {
139
        int sSize = track->entry ? track->cluster[0].size / track->cluster[0].entries : 0;
140
        sSize = FFMAX(1, sSize); // adpcm mono case could make sSize == 0
141 142
        avio_wb32(pb, sSize); // sample size
        avio_wb32(pb, entries); // sample count
143
    } else {
144 145
        avio_wb32(pb, 0); // sample size
        avio_wb32(pb, entries); // sample count
146 147
        for (i = 0; i < track->entry; i++) {
            for (j = 0; j < track->cluster[i].entries; j++) {
148
                avio_wb32(pb, track->cluster[i].size /
149
                          track->cluster[i].entries);
150
            }
151 152
        }
    }
153
    return update_size(pb, pos);
154 155
}

156
/* Sample to chunk atom */
157
static int mov_write_stsc_tag(AVIOContext *pb, MOVTrack *track)
158
{
159
    int index = 0, oldval = -1, i;
160
    int64_t entryPos, curpos;
161

162
    int64_t pos = avio_tell(pb);
163
    avio_wb32(pb, 0); /* size */
164
    ffio_wfourcc(pb, "stsc");
165
    avio_wb32(pb, 0); // version & flags
166
    entryPos = avio_tell(pb);
167
    avio_wb32(pb, track->entry); // entry count
168 169 170
    for (i = 0; i < track->entry; i++) {
        if (oldval != track->cluster[i].samples_in_chunk) {
            avio_wb32(pb, i + 1); // first chunk
171
            avio_wb32(pb, track->cluster[i].samples_in_chunk); // samples per chunk
172
            avio_wb32(pb, 0x1); // sample description index
173
            oldval = track->cluster[i].samples_in_chunk;
174
            index++;
175 176
        }
    }
177
    curpos = avio_tell(pb);
178
    avio_seek(pb, entryPos, SEEK_SET);
179
    avio_wb32(pb, index); // rewrite size
180
    avio_seek(pb, curpos, SEEK_SET);
181

182
    return update_size(pb, pos);
183 184
}

185
/* Sync sample atom */
186
static int mov_write_stss_tag(AVIOContext *pb, MOVTrack *track, uint32_t flag)
187
{
188
    int64_t curpos, entryPos;
189
    int i, index = 0;
190
    int64_t pos = avio_tell(pb);
191
    avio_wb32(pb, 0); // size
192
    ffio_wfourcc(pb, flag == MOV_SYNC_SAMPLE ? "stss" : "stps");
193
    avio_wb32(pb, 0); // version & flags
194
    entryPos = avio_tell(pb);
195
    avio_wb32(pb, track->entry); // entry count
196
    for (i = 0; i < track->entry; i++) {
197
        if (track->cluster[i].flags & flag) {
198
            avio_wb32(pb, i + 1);
199 200 201
            index++;
        }
    }
202
    curpos = avio_tell(pb);
203
    avio_seek(pb, entryPos, SEEK_SET);
204
    avio_wb32(pb, index); // rewrite size
205
    avio_seek(pb, curpos, SEEK_SET);
206
    return update_size(pb, pos);
207 208
}

209
static int mov_write_amr_tag(AVIOContext *pb, MOVTrack *track)
210
{
211
    avio_wb32(pb, 0x11); /* size */
212 213 214
    if (track->mode == MODE_MOV) ffio_wfourcc(pb, "samr");
    else                         ffio_wfourcc(pb, "damr");
    ffio_wfourcc(pb, "FFMP");
215
    avio_w8(pb, 0); /* decoder version */
216

217 218 219
    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 */
220 221 222
    return 0x11;
}

223
static int mov_write_ac3_tag(AVIOContext *pb, MOVTrack *track)
224 225 226 227 228 229
{
    GetBitContext gbc;
    PutBitContext pbc;
    uint8_t buf[3];
    int fscod, bsid, bsmod, acmod, lfeon, frmsizecod;

230
    if (track->vos_len < 7)
231 232
        return -1;

233
    avio_wb32(pb, 11);
234
    ffio_wfourcc(pb, "dac3");
235

236
    init_get_bits(&gbc, track->vos_data + 4, (track->vos_len - 4) * 8);
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
    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);
258
    put_bits(&pbc, 5, frmsizecod >> 1); // bit_rate_code
259 260 261
    put_bits(&pbc, 5, 0); // reserved

    flush_put_bits(&pbc);
262
    avio_write(pb, buf, sizeof(buf));
263 264 265 266

    return 11;
}

267 268
/**
 * This function writes extradata "as is".
269
 * Extradata must be formatted like a valid atom (with size and tag).
270
 */
271
static int mov_write_extradata_tag(AVIOContext *pb, MOVTrack *track)
272
{
273
    avio_write(pb, track->enc->extradata, track->enc->extradata_size);
274 275 276
    return track->enc->extradata_size;
}

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

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

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

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

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

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

    // 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)
313 314 315
    if (track->enc->codec_id == AV_CODEC_ID_DVD_SUBTITLE)
        avio_w8(pb, (0x38 << 2) | 1); // flags (= NeroSubpicStream)
    else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
316
        avio_w8(pb, 0x15); // flags (= Audiostream)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
317
    else
318
        avio_w8(pb, 0x11); // flags (= Visualstream)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
319

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

322
    avio_wb32(pb, FFMAX(track->enc->bit_rate, track->enc->rc_max_rate)); // maxbitrate (FIXME should be max rate in any 1 sec window)
323 324
    if (track->enc->rc_max_rate != track->enc->rc_min_rate ||
        track->enc->rc_min_rate == 0)
325
        avio_wb32(pb, 0); // vbr
Baptiste Coudurier's avatar
Baptiste Coudurier committed
326
    else
327
        avio_wb32(pb, track->enc->rc_max_rate); // avg bitrate
Baptiste Coudurier's avatar
Baptiste Coudurier committed
328

329
    if (track->vos_len) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
330
        // DecoderSpecific info descriptor
331 332
        put_descr(pb, 0x05, track->vos_len);
        avio_write(pb, track->vos_data, track->vos_len);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
333 334 335
    }

    // SL descriptor
336
    put_descr(pb, 0x06, 1);
337
    avio_w8(pb, 0x02);
338
    return update_size(pb, pos);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
339 340
}

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

351 352 353 354 355 356 357 358 359
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);
}

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

382
    return update_size(pb, pos);
383 384
}

385
static int mov_write_wave_tag(AVIOContext *pb, MOVTrack *track)
386
{
387
    int64_t pos = avio_tell(pb);
388

389
    avio_wb32(pb, 0);     /* size */
390
    ffio_wfourcc(pb, "wave");
391

392
    avio_wb32(pb, 12);    /* size */
393
    ffio_wfourcc(pb, "frma");
394
    avio_wl32(pb, track->tag);
395

396
    if (track->enc->codec_id == AV_CODEC_ID_AAC) {
397
        /* useless atom needed by mplayer, ipod, not needed by quicktime */
398
        avio_wb32(pb, 12); /* size */
399
        ffio_wfourcc(pb, "mp4a");
400
        avio_wb32(pb, 0);
401
        mov_write_esds_tag(pb, track);
402
    } else if (track->enc->codec_id == AV_CODEC_ID_AMR_NB) {
403
        mov_write_amr_tag(pb, track);
404
    } else if (track->enc->codec_id == AV_CODEC_ID_AC3) {
405
        mov_write_ac3_tag(pb, track);
406
    } else if (track->enc->codec_id == AV_CODEC_ID_ALAC) {
407
        mov_write_extradata_tag(pb, track);
408 409
    } else if (track->enc->codec_id == AV_CODEC_ID_ADPCM_MS ||
               track->enc->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) {
410
        mov_write_ms_tag(pb, track);
411
    }
412

413 414
    avio_wb32(pb, 8);     /* size */
    avio_wb32(pb, 0);     /* null tag */
415

416
    return update_size(pb, pos);
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
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 */
486 487 488 489 490 491 492

    /* framerate */
    if (track->st->avg_frame_rate.num > 0 && track->st->avg_frame_rate.den > 0)
        put_bits32(&pbc, track->st->avg_frame_rate.num / track->st->avg_frame_rate.den);
    else
        put_bits32(&pbc, 0xffffffff);

493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516
    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
/**
 * Compute flags for 'lpcm' tag.
 * See CoreAudioTypes and AudioStreamBasicDescription at Apple.
 */
529
static int mov_get_lpcm_flags(enum AVCodecID codec_id)
530 531
{
    switch (codec_id) {
532 533
    case AV_CODEC_ID_PCM_F32BE:
    case AV_CODEC_ID_PCM_F64BE:
534
        return 11;
535 536
    case AV_CODEC_ID_PCM_F32LE:
    case AV_CODEC_ID_PCM_F64LE:
537
        return 9;
538
    case AV_CODEC_ID_PCM_U8:
539
        return 10;
540 541 542
    case AV_CODEC_ID_PCM_S16BE:
    case AV_CODEC_ID_PCM_S24BE:
    case AV_CODEC_ID_PCM_S32BE:
543
        return 14;
544 545 546 547
    case AV_CODEC_ID_PCM_S8:
    case AV_CODEC_ID_PCM_S16LE:
    case AV_CODEC_ID_PCM_S24LE:
    case AV_CODEC_ID_PCM_S32LE:
548 549 550 551 552 553
        return 12;
    default:
        return 0;
    }
}

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

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

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

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

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

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

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

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

637 638 639 640 641 642 643
    if (track->mode == MODE_MOV &&
        (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))
644
        mov_write_wave_tag(pb, track);
645
    else if (track->tag == MKTAG('m','p','4','a'))
646
        mov_write_esds_tag(pb, track);
647
    else if (track->enc->codec_id == AV_CODEC_ID_AMR_NB)
648
        mov_write_amr_tag(pb, track);
649
    else if (track->enc->codec_id == AV_CODEC_ID_AC3)
650
        mov_write_ac3_tag(pb, track);
651
    else if (track->enc->codec_id == AV_CODEC_ID_ALAC)
652
        mov_write_extradata_tag(pb, track);
653
    else if (track->enc->codec_id == AV_CODEC_ID_WMAPRO)
654
        mov_write_wfex_tag(pb, track);
655
    else if (track->vos_len > 0)
656
        mov_write_glbl_tag(pb, track);
657

658 659 660
    if (track->mode == MODE_MOV && track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
        mov_write_chan_tag(pb, track);

661
    return update_size(pb, pos);
662 663
}

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

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

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

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

699 700 701 702 703 704 705 706 707 708
static int mov_write_hvcc_tag(AVIOContext *pb, MOVTrack *track)
{
    int64_t pos = avio_tell(pb);

    avio_wb32(pb, 0);
    ffio_wfourcc(pb, "hvcC");
    ff_isom_write_hvcc(pb, track->vos_data, track->vos_len, 0);
    return update_size(pb, pos);
}

709
/* also used by all avid codecs (dv, imx, meridien) and their variants */
710
static int mov_write_avid_tag(AVIOContext *pb, MOVTrack *track)
711 712
{
    int i;
713
    avio_wb32(pb, 24); /* size */
714 715 716
    ffio_wfourcc(pb, "ACLR");
    ffio_wfourcc(pb, "ACLR");
    ffio_wfourcc(pb, "0001");
717
    avio_wb32(pb, 2); /* yuv range: full 1 / normal 2 */
718
    avio_wb32(pb, 0); /* unknown */
719

720
    avio_wb32(pb, 24); /* size */
721 722 723
    ffio_wfourcc(pb, "APRG");
    ffio_wfourcc(pb, "APRG");
    ffio_wfourcc(pb, "0001");
724 725
    avio_wb32(pb, 1); /* unknown */
    avio_wb32(pb, 0); /* unknown */
726

727
    avio_wb32(pb, 120); /* size */
728 729 730
    ffio_wfourcc(pb, "ARES");
    ffio_wfourcc(pb, "ARES");
    ffio_wfourcc(pb, "0001");
731
    avio_wb32(pb, AV_RB32(track->vos_data + 0x28)); /* dnxhd cid, some id ? */
732
    avio_wb32(pb, track->enc->width);
733
    /* values below are based on samples created with quicktime and avid codecs */
734
    if (track->vos_data[5] & 2) { // interlaced
735
        avio_wb32(pb, track->enc->height / 2);
736 737 738
        avio_wb32(pb, 2); /* unknown */
        avio_wb32(pb, 0); /* unknown */
        avio_wb32(pb, 4); /* unknown */
739
    } else {
740 741 742
        avio_wb32(pb, track->enc->height);
        avio_wb32(pb, 1); /* unknown */
        avio_wb32(pb, 0); /* unknown */
743
        if (track->enc->height == 1080)
744
            avio_wb32(pb, 5); /* unknown */
745
        else
746
            avio_wb32(pb, 6); /* unknown */
747 748 749
    }
    /* padding */
    for (i = 0; i < 10; i++)
750
        avio_wb64(pb, 0);
751 752

    /* extra padding for stsd needed */
753
    avio_wb32(pb, 0);
754 755 756
    return 0;
}

757
static int mp4_get_codec_tag(AVFormatContext *s, MOVTrack *track)
758
{
Baptiste Coudurier's avatar
Baptiste Coudurier committed
759
    int tag = track->enc->codec_tag;
760

761
    if (!ff_codec_get_tag(ff_mp4_obj_type, track->enc->codec_id))
762 763
        return 0;

764
    if      (track->enc->codec_id == AV_CODEC_ID_H264)      tag = MKTAG('a','v','c','1');
765
    else if (track->enc->codec_id == AV_CODEC_ID_HEVC)      tag = MKTAG('h','e','v','1');
766 767 768 769
    else if (track->enc->codec_id == AV_CODEC_ID_AC3)       tag = MKTAG('a','c','-','3');
    else if (track->enc->codec_id == AV_CODEC_ID_DIRAC)     tag = MKTAG('d','r','a','c');
    else if (track->enc->codec_id == AV_CODEC_ID_MOV_TEXT)  tag = MKTAG('t','x','3','g');
    else if (track->enc->codec_id == AV_CODEC_ID_VC1)       tag = MKTAG('v','c','-','1');
770 771
    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');
772
    else if (track->enc->codec_id == AV_CODEC_ID_DVD_SUBTITLE)  tag = MKTAG('m','p','4','s');
773 774 775 776

    return tag;
}

777
static const AVCodecTag codec_ipod_tags[] = {
778 779 780 781 782
    { AV_CODEC_ID_H264,     MKTAG('a','v','c','1') },
    { AV_CODEC_ID_MPEG4,    MKTAG('m','p','4','v') },
    { AV_CODEC_ID_AAC,      MKTAG('m','p','4','a') },
    { AV_CODEC_ID_ALAC,     MKTAG('a','l','a','c') },
    { AV_CODEC_ID_AC3,      MKTAG('a','c','-','3') },
783 784 785
    { AV_CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') },
    { AV_CODEC_ID_MOV_TEXT, MKTAG('t','e','x','t') },
    { AV_CODEC_ID_NONE, 0 },
786 787
};

788 789 790 791
static int ipod_get_codec_tag(AVFormatContext *s, MOVTrack *track)
{
    int tag = track->enc->codec_tag;

792
    // keep original tag for subs, ipod supports both formats
793
    if (!(track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE &&
794 795
          (tag == MKTAG('t', 'x', '3', 'g') ||
           tag == MKTAG('t', 'e', 'x', 't'))))
796
        tag = ff_codec_get_tag(codec_ipod_tags, track->enc->codec_id);
797

798
    if (!av_match_ext(s->filename, "m4a") && !av_match_ext(s->filename, "m4v"))
799 800
        av_log(s, AV_LOG_WARNING, "Warning, extension is not .m4a nor .m4v "
               "Quicktime/Ipod might not play the file\n");
801 802 803 804 805 806 807 808

    return tag;
}

static int mov_get_dv_codec_tag(AVFormatContext *s, MOVTrack *track)
{
    int tag;

809 810
    if (track->enc->width == 720) /* SD */
        if (track->enc->height == 480) /* NTSC */
811
            if  (track->enc->pix_fmt == AV_PIX_FMT_YUV422P) tag = MKTAG('d','v','5','n');
812
            else                                            tag = MKTAG('d','v','c',' ');
813 814
        else if (track->enc->pix_fmt == AV_PIX_FMT_YUV422P) tag = MKTAG('d','v','5','p');
        else if (track->enc->pix_fmt == AV_PIX_FMT_YUV420P) tag = MKTAG('d','v','c','p');
815
        else                                                tag = MKTAG('d','v','p','p');
816
    else if (track->enc->height == 720) /* HD 720 line */
817
        if  (track->st->time_base.den == 50)                tag = MKTAG('d','v','h','q');
818
        else                                                tag = MKTAG('d','v','h','p');
819
    else if (track->enc->height == 1080) /* HD 1080 line */
820
        if  (track->st->time_base.den == 25)                tag = MKTAG('d','v','h','5');
821
        else                                                tag = MKTAG('d','v','h','6');
822 823 824 825
    else {
        av_log(s, AV_LOG_ERROR, "unsupported height for dv codec\n");
        return 0;
    }
826 827 828 829

    return tag;
}

830
static const struct {
831
    enum AVPixelFormat pix_fmt;
832 833 834
    uint32_t tag;
    unsigned bps;
} mov_pix_fmt_tags[] = {
835 836 837 838 839 840 841 842 843 844 845 846 847 848
    { AV_PIX_FMT_YUYV422, MKTAG('y','u','v','s'),  0 },
    { AV_PIX_FMT_UYVY422, MKTAG('2','v','u','y'),  0 },
    { AV_PIX_FMT_RGB555BE,MKTAG('r','a','w',' '), 16 },
    { AV_PIX_FMT_RGB555LE,MKTAG('L','5','5','5'), 16 },
    { AV_PIX_FMT_RGB565LE,MKTAG('L','5','6','5'), 16 },
    { AV_PIX_FMT_RGB565BE,MKTAG('B','5','6','5'), 16 },
    { AV_PIX_FMT_GRAY16BE,MKTAG('b','1','6','g'), 16 },
    { AV_PIX_FMT_RGB24,   MKTAG('r','a','w',' '), 24 },
    { AV_PIX_FMT_BGR24,   MKTAG('2','4','B','G'), 24 },
    { AV_PIX_FMT_ARGB,    MKTAG('r','a','w',' '), 32 },
    { AV_PIX_FMT_BGRA,    MKTAG('B','G','R','A'), 32 },
    { AV_PIX_FMT_RGBA,    MKTAG('R','G','B','A'), 32 },
    { AV_PIX_FMT_ABGR,    MKTAG('A','B','G','R'), 32 },
    { AV_PIX_FMT_RGB48BE, MKTAG('b','4','8','r'), 48 },
849 850
};

851 852 853
static int mov_get_rawvideo_codec_tag(AVFormatContext *s, MOVTrack *track)
{
    int tag = track->enc->codec_tag;
854 855 856 857 858 859 860 861 862
    int i;

    for (i = 0; i < FF_ARRAY_ELEMS(mov_pix_fmt_tags); i++) {
        if (track->enc->pix_fmt == mov_pix_fmt_tags[i].pix_fmt) {
            tag = mov_pix_fmt_tags[i].tag;
            track->enc->bits_per_coded_sample = mov_pix_fmt_tags[i].bps;
            break;
        }
    }
863 864 865 866 867 868 869 870 871

    return tag;
}

static int mov_get_codec_tag(AVFormatContext *s, MOVTrack *track)
{
    int tag = track->enc->codec_tag;

    if (!tag || (track->enc->strict_std_compliance >= FF_COMPLIANCE_NORMAL &&
872 873 874
                 (track->enc->codec_id == AV_CODEC_ID_DVVIDEO ||
                  track->enc->codec_id == AV_CODEC_ID_RAWVIDEO ||
                  track->enc->codec_id == AV_CODEC_ID_H263 ||
875
                  av_get_bits_per_sample(track->enc->codec_id)))) { // pcm audio
876
        if (track->enc->codec_id == AV_CODEC_ID_DVVIDEO)
877
            tag = mov_get_dv_codec_tag(s, track);
878
        else if (track->enc->codec_id == AV_CODEC_ID_RAWVIDEO)
879
            tag = mov_get_rawvideo_codec_tag(s, track);
880
        else if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) {
881
            tag = ff_codec_get_tag(ff_codec_movvideo_tags, track->enc->codec_id);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
882
            if (!tag) { // if no mac fcc found, try with Microsoft tags
883
                tag = ff_codec_get_tag(ff_codec_bmp_tags, track->enc->codec_id);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
884
                if (tag)
885
                    av_log(s, AV_LOG_WARNING, "Using MS style video codec tag, "
Baptiste Coudurier's avatar
Baptiste Coudurier committed
886 887
                           "the file may be unplayable!\n");
            }
888
        } else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) {
889
            tag = ff_codec_get_tag(ff_codec_movaudio_tags, track->enc->codec_id);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
890
            if (!tag) { // if no mac fcc found, try with Microsoft tags
891
                int ms_tag = ff_codec_get_tag(ff_codec_wav_tags, track->enc->codec_id);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
892 893
                if (ms_tag) {
                    tag = MKTAG('m', 's', ((ms_tag >> 8) & 0xff), (ms_tag & 0xff));
894
                    av_log(s, AV_LOG_WARNING, "Using MS style audio codec tag, "
Baptiste Coudurier's avatar
Baptiste Coudurier committed
895
                           "the file may be unplayable!\n");
Baptiste Coudurier's avatar
Baptiste Coudurier committed
896
                }
Baptiste Coudurier's avatar
Baptiste Coudurier committed
897
            }
898
        } else if (track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE)
899
            tag = ff_codec_get_tag(ff_codec_movsubtitle_tags, track->enc->codec_id);
900
    }
901

902 903 904
    return tag;
}

905
static const AVCodecTag codec_3gp_tags[] = {
906 907 908 909 910 911
    { AV_CODEC_ID_H263,     MKTAG('s','2','6','3') },
    { AV_CODEC_ID_H264,     MKTAG('a','v','c','1') },
    { AV_CODEC_ID_MPEG4,    MKTAG('m','p','4','v') },
    { AV_CODEC_ID_AAC,      MKTAG('m','p','4','a') },
    { AV_CODEC_ID_AMR_NB,   MKTAG('s','a','m','r') },
    { AV_CODEC_ID_AMR_WB,   MKTAG('s','a','w','b') },
912 913
    { AV_CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') },
    { AV_CODEC_ID_NONE, 0 },
914 915
};

916 917 918 919 920 921 922 923 924
static const AVCodecTag codec_f4v_tags[] = {
    { AV_CODEC_ID_MP3,    MKTAG('.','m','p','3') },
    { AV_CODEC_ID_AAC,    MKTAG('m','p','4','a') },
    { AV_CODEC_ID_H264,   MKTAG('a','v','c','1') },
    { AV_CODEC_ID_VP6A,   MKTAG('V','P','6','A') },
    { AV_CODEC_ID_VP6F,   MKTAG('V','P','6','F') },
    { AV_CODEC_ID_NONE, 0 },
};

925 926
static int mov_find_codec_tag(AVFormatContext *s, MOVTrack *track)
{
927
    int tag;
928

929 930 931
    if (track->mode == MODE_MP4 || track->mode == MODE_PSP)
        tag = mp4_get_codec_tag(s, track);
    else if (track->mode == MODE_ISM) {
932
        tag = mp4_get_codec_tag(s, track);
933
        if (!tag && track->enc->codec_id == AV_CODEC_ID_WMAPRO)
934 935
            tag = MKTAG('w', 'm', 'a', ' ');
    } else if (track->mode == MODE_IPOD)
936 937
        tag = ipod_get_codec_tag(s, track);
    else if (track->mode & MODE_3GP)
938
        tag = ff_codec_get_tag(codec_3gp_tags, track->enc->codec_id);
939 940
    else if (track->mode == MODE_F4V)
        tag = ff_codec_get_tag(codec_f4v_tags, track->enc->codec_id);
941 942 943 944 945 946
    else
        tag = mov_get_codec_tag(s, track);

    return tag;
}

947 948 949 950
/** Write uuid atom.
 * Needed to make file play in iPods running newest firmware
 * goes after avcC atom in moov.trak.mdia.minf.stbl.stsd.avc1
 */
951
static int mov_write_uuid_tag_ipod(AVIOContext *pb)
952
{
953
    avio_wb32(pb, 28);
954
    ffio_wfourcc(pb, "uuid");
955 956 957 958 959
    avio_wb32(pb, 0x6b6840f2);
    avio_wb32(pb, 0x5f244fc5);
    avio_wb32(pb, 0xba39a51b);
    avio_wb32(pb, 0xcf0323f3);
    avio_wb32(pb, 0x0);
960 961 962
    return 28;
}

963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979
static const uint16_t fiel_data[] = {
    0x0000, 0x0100, 0x0201, 0x0206, 0x0209, 0x020e
};

static int mov_write_fiel_tag(AVIOContext *pb, MOVTrack *track)
{
    unsigned mov_field_order = 0;
    if (track->enc->field_order < FF_ARRAY_ELEMS(fiel_data))
        mov_field_order = fiel_data[track->enc->field_order];
    else
        return 0;
    avio_wb32(pb, 10);
    ffio_wfourcc(pb, "fiel");
    avio_wb16(pb, mov_field_order);
    return 10;
}

980
static int mov_write_subtitle_tag(AVIOContext *pb, MOVTrack *track)
981
{
982
    int64_t pos = avio_tell(pb);
983 984 985 986 987
    avio_wb32(pb, 0);    /* size */
    avio_wl32(pb, track->tag); // store it byteswapped
    avio_wb32(pb, 0);    /* Reserved */
    avio_wb16(pb, 0);    /* Reserved */
    avio_wb16(pb, 1);    /* Data-reference index */
988

989 990 991
    if (track->enc->codec_id == AV_CODEC_ID_DVD_SUBTITLE)
        mov_write_esds_tag(pb, track);
    else if (track->enc->extradata_size)
992
        avio_write(pb, track->enc->extradata, track->enc->extradata_size);
993

994
    return update_size(pb, pos);
995 996
}

997
static int mov_write_pasp_tag(AVIOContext *pb, MOVTrack *track)
998 999 1000 1001 1002
{
    AVRational sar;
    av_reduce(&sar.num, &sar.den, track->enc->sample_aspect_ratio.num,
              track->enc->sample_aspect_ratio.den, INT_MAX);

1003
    avio_wb32(pb, 16);
1004
    ffio_wfourcc(pb, "pasp");
1005 1006
    avio_wb32(pb, sar.num);
    avio_wb32(pb, sar.den);
1007 1008 1009
    return 16;
}

1010
static int mov_write_video_tag(AVIOContext *pb, MOVTrack *track)
1011
{
1012
    AVDictionaryEntry *encoder;
1013
    int64_t pos = avio_tell(pb);
1014
    char compressor_name[32] = { 0 };
1015

1016 1017 1018 1019 1020
    avio_wb32(pb, 0); /* size */
    avio_wl32(pb, track->tag); // store it byteswapped
    avio_wb32(pb, 0); /* Reserved */
    avio_wb16(pb, 0); /* Reserved */
    avio_wb16(pb, 1); /* Data-reference index */
1021

1022 1023
    avio_wb16(pb, 0); /* Codec stream version */
    avio_wb16(pb, 0); /* Codec stream revision (=0) */
1024
    if (track->mode == MODE_MOV) {
1025
        ffio_wfourcc(pb, "FFMP"); /* Vendor */
1026
        if (track->enc->codec_id == AV_CODEC_ID_RAWVIDEO) {
1027 1028
            avio_wb32(pb, 0); /* Temporal Quality */
            avio_wb32(pb, 0x400); /* Spatial Quality = lossless*/
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1029
        } else {
1030 1031
            avio_wb32(pb, 0x200); /* Temporal Quality = normal */
            avio_wb32(pb, 0x200); /* Spatial Quality = normal */
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1032
        }
1033
    } else {
1034 1035 1036
        avio_wb32(pb, 0); /* Reserved */
        avio_wb32(pb, 0); /* Reserved */
        avio_wb32(pb, 0); /* Reserved */
1037
    }
1038 1039 1040 1041 1042 1043
    avio_wb16(pb, track->enc->width); /* Video width */
    avio_wb16(pb, track->height); /* Video height */
    avio_wb32(pb, 0x00480000); /* Horizontal resolution 72dpi */
    avio_wb32(pb, 0x00480000); /* Vertical resolution 72dpi */
    avio_wb32(pb, 0); /* Data size (= 0) */
    avio_wb16(pb, 1); /* Frame count (= 1) */
1044

1045
    /* FIXME not sure, ISO 14496-1 draft where it shall be set to 0 */
1046 1047 1048
    if (track->mode == MODE_MOV &&
        (encoder = av_dict_get(track->st->metadata, "encoder", NULL, 0)))
        av_strlcpy(compressor_name, encoder->value, 32);
1049 1050
    avio_w8(pb, strlen(compressor_name));
    avio_write(pb, compressor_name, 31);
1051

1052
    if (track->mode == MODE_MOV && track->enc->bits_per_coded_sample)
1053
        avio_wb16(pb, track->enc->bits_per_coded_sample);
1054
    else
1055 1056
        avio_wb16(pb, 0x18); /* Reserved */
    avio_wb16(pb, 0xffff); /* Reserved */
1057
    if (track->tag == MKTAG('m','p','4','v'))
1058
        mov_write_esds_tag(pb, track);
1059
    else if (track->enc->codec_id == AV_CODEC_ID_H263)
1060
        mov_write_d263_tag(pb);
1061
    else if (track->enc->codec_id == AV_CODEC_ID_SVQ3)
1062
        mov_write_svq3_tag(pb);
1063
    else if (track->enc->codec_id == AV_CODEC_ID_DNXHD)
1064
        mov_write_avid_tag(pb, track);
1065 1066
    else if (track->enc->codec_id == AV_CODEC_ID_HEVC)
        mov_write_hvcc_tag(pb, track);
1067
    else if (track->enc->codec_id == AV_CODEC_ID_H264) {
1068
        mov_write_avcc_tag(pb, track);
1069
        if (track->mode == MODE_IPOD)
1070
            mov_write_uuid_tag_ipod(pb);
1071 1072
    } else if (track->enc->field_order != AV_FIELD_UNKNOWN)
        mov_write_fiel_tag(pb, track);
1073
    else if (track->enc->codec_id == AV_CODEC_ID_VC1 && track->vos_len > 0)
1074
        mov_write_dvc1_tag(pb, track);
1075 1076 1077 1078 1079
    else if (track->enc->codec_id == AV_CODEC_ID_VP6F ||
             track->enc->codec_id == AV_CODEC_ID_VP6A) {
        /* Don't write any potential extradata here - the cropping
         * is signalled via the normal width/height fields. */
    } else if (track->vos_len > 0)
1080
        mov_write_glbl_tag(pb, track);
1081

1082
    if (track->enc->sample_aspect_ratio.den && track->enc->sample_aspect_ratio.num &&
1083 1084 1085 1086
        track->enc->sample_aspect_ratio.den != track->enc->sample_aspect_ratio.num) {
        mov_write_pasp_tag(pb, track);
    }

1087
    return update_size(pb, pos);
1088 1089
}

1090
static int mov_write_rtp_tag(AVIOContext *pb, MOVTrack *track)
1091
{
1092
    int64_t pos = avio_tell(pb);
1093
    avio_wb32(pb, 0); /* size */
1094
    ffio_wfourcc(pb, "rtp ");
1095 1096 1097
    avio_wb32(pb, 0); /* Reserved */
    avio_wb16(pb, 0); /* Reserved */
    avio_wb16(pb, 1); /* Data-reference index */
1098

1099 1100 1101
    avio_wb16(pb, 1); /* Hint track version */
    avio_wb16(pb, 1); /* Highest compatible version */
    avio_wb32(pb, track->max_packet_size); /* Max packet size */
1102

1103
    avio_wb32(pb, 12); /* size */
1104
    ffio_wfourcc(pb, "tims");
1105
    avio_wb32(pb, track->timescale);
1106

1107
    return update_size(pb, pos);
1108 1109
}

Luca Barbato's avatar
Luca Barbato committed
1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122
static int mov_write_tmcd_tag(AVIOContext *pb, MOVTrack *track)
{
    int64_t pos = avio_tell(pb);

    avio_wb32(pb, 0); /* size */
    ffio_wfourcc(pb, "tmcd");               /* Data format */
    avio_wb32(pb, 0);                       /* Reserved */
    avio_wb32(pb, 1);                       /* Data reference index */
    if (track->enc->extradata_size)
        avio_write(pb, track->enc->extradata, track->enc->extradata_size);
    return update_size(pb, pos);
}

1123
static int mov_write_stsd_tag(AVIOContext *pb, MOVTrack *track)
1124
{
1125
    int64_t pos = avio_tell(pb);
1126
    avio_wb32(pb, 0); /* size */
1127
    ffio_wfourcc(pb, "stsd");
1128 1129
    avio_wb32(pb, 0); /* version & flags */
    avio_wb32(pb, 1); /* entry count */
1130
    if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO)
1131
        mov_write_video_tag(pb, track);
1132
    else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
1133
        mov_write_audio_tag(pb, track);
1134
    else if (track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE)
1135
        mov_write_subtitle_tag(pb, track);
1136 1137
    else if (track->enc->codec_tag == MKTAG('r','t','p',' '))
        mov_write_rtp_tag(pb, track);
Luca Barbato's avatar
Luca Barbato committed
1138 1139
    else if (track->enc->codec_tag == MKTAG('t','m','c','d'))
        mov_write_tmcd_tag(pb, track);
1140
    return update_size(pb, pos);
1141 1142
}

1143
static int mov_write_ctts_tag(AVIOContext *pb, MOVTrack *track)
1144
{
1145
    MOVStts *ctts_entries;
1146 1147 1148 1149 1150 1151
    uint32_t entries = 0;
    uint32_t atom_size;
    int i;

    ctts_entries = av_malloc((track->entry + 1) * sizeof(*ctts_entries)); /* worst case */
    ctts_entries[0].count = 1;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1152
    ctts_entries[0].duration = track->cluster[0].cts;
1153
    for (i = 1; i < track->entry; i++) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1154
        if (track->cluster[i].cts == ctts_entries[entries].duration) {
1155 1156 1157
            ctts_entries[entries].count++; /* compress */
        } else {
            entries++;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1158
            ctts_entries[entries].duration = track->cluster[i].cts;
1159 1160 1161 1162 1163
            ctts_entries[entries].count = 1;
        }
    }
    entries++; /* last one */
    atom_size = 16 + (entries * 8);
1164
    avio_wb32(pb, atom_size); /* size */
1165
    ffio_wfourcc(pb, "ctts");
1166 1167
    avio_wb32(pb, 0); /* version & flags */
    avio_wb32(pb, entries); /* entry count */
1168
    for (i = 0; i < entries; i++) {
1169 1170
        avio_wb32(pb, ctts_entries[i].count);
        avio_wb32(pb, ctts_entries[i].duration);
1171 1172 1173 1174 1175
    }
    av_free(ctts_entries);
    return atom_size;
}

1176
/* Time to sample atom */
1177
static int mov_write_stts_tag(AVIOContext *pb, MOVTrack *track)
1178
{
1179
    MOVStts *stts_entries;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1180 1181 1182 1183
    uint32_t entries = -1;
    uint32_t atom_size;
    int i;

1184
    if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO && !track->audio_vbr) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1185
        stts_entries = av_malloc(sizeof(*stts_entries)); /* one entry */
1186
        stts_entries[0].count = track->sample_count;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1187 1188 1189
        stts_entries[0].duration = 1;
        entries = 1;
    } else {
1190 1191 1192
        stts_entries = track->entry ?
                       av_malloc(track->entry * sizeof(*stts_entries)) : /* worst case */
                       NULL;
1193
        for (i = 0; i < track->entry; i++) {
1194
            int duration = get_cluster_duration(track, i);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205
            if (i && duration == stts_entries[entries].duration) {
                stts_entries[entries].count++; /* compress */
            } else {
                entries++;
                stts_entries[entries].duration = duration;
                stts_entries[entries].count = 1;
            }
        }
        entries++; /* last one */
    }
    atom_size = 16 + (entries * 8);
1206
    avio_wb32(pb, atom_size); /* size */
1207
    ffio_wfourcc(pb, "stts");
1208 1209
    avio_wb32(pb, 0); /* version & flags */
    avio_wb32(pb, entries); /* entry count */
1210
    for (i = 0; i < entries; i++) {
1211 1212
        avio_wb32(pb, stts_entries[i].count);
        avio_wb32(pb, stts_entries[i].duration);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1213 1214 1215
    }
    av_free(stts_entries);
    return atom_size;
1216 1217
}

1218
static int mov_write_dref_tag(AVIOContext *pb)
1219
{
1220
    avio_wb32(pb, 28); /* size */
1221
    ffio_wfourcc(pb, "dref");
1222 1223
    avio_wb32(pb, 0); /* version & flags */
    avio_wb32(pb, 1); /* entry count */
1224

1225
    avio_wb32(pb, 0xc); /* size */
1226
    ffio_wfourcc(pb, "url ");
1227
    avio_wb32(pb, 1); /* version & flags */
1228 1229 1230 1231

    return 28;
}

1232
static int mov_write_stbl_tag(AVIOContext *pb, MOVTrack *track)
1233
{
1234
    int64_t pos = avio_tell(pb);
1235
    avio_wb32(pb, 0); /* size */
1236
    ffio_wfourcc(pb, "stbl");
1237 1238
    mov_write_stsd_tag(pb, track);
    mov_write_stts_tag(pb, track);
1239 1240
    if ((track->enc->codec_type == AVMEDIA_TYPE_VIDEO ||
         track->enc->codec_tag == MKTAG('r','t','p',' ')) &&
1241
        track->has_keyframes && track->has_keyframes < track->entry)
1242 1243 1244
        mov_write_stss_tag(pb, track, MOV_SYNC_SAMPLE);
    if (track->mode == MODE_MOV && track->flags & MOV_TRACK_STPS)
        mov_write_stss_tag(pb, track, MOV_PARTIAL_SYNC_SAMPLE);
1245
    if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO &&
1246
        track->flags & MOV_TRACK_CTTS)
1247
        mov_write_ctts_tag(pb, track);
1248 1249 1250
    mov_write_stsc_tag(pb, track);
    mov_write_stsz_tag(pb, track);
    mov_write_stco_tag(pb, track);
1251
    return update_size(pb, pos);
1252 1253
}

1254
static int mov_write_dinf_tag(AVIOContext *pb)
1255
{
1256
    int64_t pos = avio_tell(pb);
1257
    avio_wb32(pb, 0); /* size */
1258
    ffio_wfourcc(pb, "dinf");
1259
    mov_write_dref_tag(pb);
1260
    return update_size(pb, pos);
1261 1262
}

1263
static int mov_write_nmhd_tag(AVIOContext *pb)
1264
{
1265
    avio_wb32(pb, 12);
1266
    ffio_wfourcc(pb, "nmhd");
1267
    avio_wb32(pb, 0);
1268 1269 1270
    return 12;
}

1271
static int mov_write_gmhd_tag(AVIOContext *pb)
1272
{
1273
    avio_wb32(pb, 0x20);   /* size */
1274
    ffio_wfourcc(pb, "gmhd");
1275
    avio_wb32(pb, 0x18);   /* gmin size */
1276
    ffio_wfourcc(pb, "gmin");/* generic media info */
1277 1278 1279 1280 1281 1282 1283
    avio_wb32(pb, 0);      /* version & flags */
    avio_wb16(pb, 0x40);   /* graphics mode = */
    avio_wb16(pb, 0x8000); /* opColor (r?) */
    avio_wb16(pb, 0x8000); /* opColor (g?) */
    avio_wb16(pb, 0x8000); /* opColor (b?) */
    avio_wb16(pb, 0);      /* balance */
    avio_wb16(pb, 0);      /* reserved */
1284 1285 1286
    return 0x20;
}

1287
static int mov_write_smhd_tag(AVIOContext *pb)
1288
{
1289
    avio_wb32(pb, 16); /* size */
1290
    ffio_wfourcc(pb, "smhd");
1291 1292 1293
    avio_wb32(pb, 0); /* version & flags */
    avio_wb16(pb, 0); /* reserved (balance, normally = 0) */
    avio_wb16(pb, 0); /* reserved */
1294 1295 1296
    return 16;
}

1297
static int mov_write_vmhd_tag(AVIOContext *pb)
1298
{
1299
    avio_wb32(pb, 0x14); /* size (always 0x14) */
1300
    ffio_wfourcc(pb, "vmhd");
1301 1302
    avio_wb32(pb, 0x01); /* version & flags */
    avio_wb64(pb, 0); /* reserved (graphics mode = copy) */
1303 1304 1305
    return 0x14;
}

1306 1307 1308 1309 1310 1311
static int is_clcp_track(MOVTrack *track)
{
    return track->tag == MKTAG('c','7','0','8') ||
           track->tag == MKTAG('c','6','0','8');
}

1312
static int mov_write_hdlr_tag(AVIOContext *pb, MOVTrack *track)
1313
{
1314
    const char *hdlr, *descr = NULL, *hdlr_type = NULL;
1315
    int64_t pos = avio_tell(pb);
1316

1317 1318 1319 1320 1321
    hdlr      = "dhlr";
    hdlr_type = "url ";
    descr     = "DataHandler";

    if (track) {
1322
        hdlr = (track->mode == MODE_MOV) ? "mhlr" : "\0\0\0\0";
1323
        if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) {
1324
            hdlr_type = "vide";
1325
            descr     = "VideoHandler";
1326
        } else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) {
1327
            hdlr_type = "soun";
1328
            descr     = "SoundHandler";
1329
        } else if (track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE) {
1330 1331 1332 1333
            if (track->tag == MKTAG('t','x','3','g')) {
                hdlr_type = "sbtl";
            } else if (track->tag == MKTAG('m','p','4','s')) {
                hdlr_type = "subp";
1334 1335
            } else if (is_clcp_track(track)) {
                hdlr_type = "clcp";
1336 1337 1338
            } else {
                hdlr_type = "text";
            }
1339
            descr = "SubtitleHandler";
1340 1341
        } else if (track->enc->codec_tag == MKTAG('r','t','p',' ')) {
            hdlr_type = "hint";
1342
            descr     = "HintHandler";
1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353
        } else if (track->enc->codec_tag == MKTAG('t','m','c','d')) {
            hdlr_type = "tmcd";
            descr = "TimeCodeHandler";
        } else {
            char tag_buf[32];
            av_get_codec_tag_string(tag_buf, sizeof(tag_buf),
                                    track->enc->codec_tag);

            av_log(track->enc, AV_LOG_WARNING,
                   "Unknown hldr_type for %s / 0x%04X, writing dummy values\n",
                   tag_buf, track->enc->codec_tag);
1354
        }
1355
    }
1356

1357
    avio_wb32(pb, 0); /* size */
1358
    ffio_wfourcc(pb, "hdlr");
1359 1360
    avio_wb32(pb, 0); /* Version & flags */
    avio_write(pb, hdlr, 4); /* handler */
1361
    ffio_wfourcc(pb, hdlr_type); /* handler type */
1362 1363 1364
    avio_wb32(pb, 0); /* reserved */
    avio_wb32(pb, 0); /* reserved */
    avio_wb32(pb, 0); /* reserved */
1365
    if (!track || track->mode == MODE_MOV)
1366 1367
        avio_w8(pb, strlen(descr)); /* pascal string */
    avio_write(pb, descr, strlen(descr)); /* handler description */
1368
    if (track && track->mode != MODE_MOV)
1369
        avio_w8(pb, 0); /* c string */
1370
    return update_size(pb, pos);
1371 1372
}

1373
static int mov_write_hmhd_tag(AVIOContext *pb)
1374 1375 1376
{
    /* This atom must be present, but leaving the values at zero
     * seems harmless. */
1377
    avio_wb32(pb, 28); /* size */
1378
    ffio_wfourcc(pb, "hmhd");
1379 1380 1381 1382 1383 1384
    avio_wb32(pb, 0); /* version, flags */
    avio_wb16(pb, 0); /* maxPDUsize */
    avio_wb16(pb, 0); /* avgPDUsize */
    avio_wb32(pb, 0); /* maxbitrate */
    avio_wb32(pb, 0); /* avgbitrate */
    avio_wb32(pb, 0); /* reserved */
1385 1386 1387
    return 28;
}

1388
static int mov_write_minf_tag(AVIOContext *pb, MOVTrack *track)
1389
{
1390
    int64_t pos = avio_tell(pb);
1391
    avio_wb32(pb, 0); /* size */
1392
    ffio_wfourcc(pb, "minf");
1393
    if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO)
1394
        mov_write_vmhd_tag(pb);
1395
    else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
1396
        mov_write_smhd_tag(pb);
1397
    else if (track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE) {
1398 1399 1400 1401 1402
        if (track->tag == MKTAG('t','e','x','t') || is_clcp_track(track)) {
            mov_write_gmhd_tag(pb);
        } else {
            mov_write_nmhd_tag(pb);
        }
1403 1404
    } else if (track->tag == MKTAG('r','t','p',' ')) {
        mov_write_hmhd_tag(pb);
Luca Barbato's avatar
Luca Barbato committed
1405 1406
    } else if (track->tag == MKTAG('t','m','c','d')) {
        mov_write_gmhd_tag(pb);
1407
    }
1408 1409 1410 1411
    if (track->mode == MODE_MOV) /* FIXME: Why do it for MODE_MOV only ? */
        mov_write_hdlr_tag(pb, NULL);
    mov_write_dinf_tag(pb);
    mov_write_stbl_tag(pb, track);
1412
    return update_size(pb, pos);
1413 1414
}

1415
static int mov_write_mdhd_tag(AVIOContext *pb, MOVTrack *track)
1416
{
1417
    int version = track->track_duration < INT32_MAX ? 0 : 1;
1418

1419 1420 1421
    if (track->mode == MODE_ISM)
        version = 1;

1422
    (version == 1) ? avio_wb32(pb, 44) : avio_wb32(pb, 32); /* size */
1423
    ffio_wfourcc(pb, "mdhd");
1424 1425
    avio_w8(pb, version);
    avio_wb24(pb, 0); /* flags */
1426
    if (version == 1) {
1427 1428
        avio_wb64(pb, track->time);
        avio_wb64(pb, track->time);
1429
    } else {
1430 1431
        avio_wb32(pb, track->time); /* creation time */
        avio_wb32(pb, track->time); /* modification time */
1432
    }
1433
    avio_wb32(pb, track->timescale); /* time scale (sample rate for audio) */
1434 1435 1436 1437
    if (!track->entry)
        (version == 1) ? avio_wb64(pb, UINT64_C(0xffffffffffffffff)) : avio_wb32(pb, 0xffffffff);
    else
        (version == 1) ? avio_wb64(pb, track->track_duration) : avio_wb32(pb, track->track_duration); /* duration */
1438 1439
    avio_wb16(pb, track->language); /* language */
    avio_wb16(pb, 0); /* reserved (quality) */
1440

1441
    if (version != 0 && track->mode == MODE_MOV) {
1442
        av_log(NULL, AV_LOG_ERROR,
1443 1444 1445
               "FATAL error, file duration too long for timebase, this file will not be\n"
               "playable with quicktime. Choose a different timebase or a different\n"
               "container format\n");
1446 1447
    }

1448 1449 1450
    return 32;
}

1451
static int mov_write_mdia_tag(AVIOContext *pb, MOVTrack *track)
1452
{
1453
    int64_t pos = avio_tell(pb);
1454
    avio_wb32(pb, 0); /* size */
1455
    ffio_wfourcc(pb, "mdia");
1456 1457 1458
    mov_write_mdhd_tag(pb, track);
    mov_write_hdlr_tag(pb, track);
    mov_write_minf_tag(pb, track);
1459
    return update_size(pb, pos);
1460 1461
}

1462
static int mov_write_tkhd_tag(AVIOContext *pb, MOVTrack *track, AVStream *st)
1463
{
1464
    int64_t duration = av_rescale_rnd(track->track_duration, MOV_TIMESCALE,
1465
                                      track->timescale, AV_ROUND_UP);
1466 1467
    int version = duration < INT32_MAX ? 0 : 1;

1468 1469 1470
    if (track->mode == MODE_ISM)
        version = 1;

1471
    (version == 1) ? avio_wb32(pb, 104) : avio_wb32(pb, 92); /* size */
1472
    ffio_wfourcc(pb, "tkhd");
1473
    avio_w8(pb, version);
1474 1475 1476
    avio_wb24(pb, (track->flags & MOV_TRACK_ENABLED) ?
                  MOV_TKHD_FLAG_ENABLED | MOV_TKHD_FLAG_IN_MOVIE :
                  MOV_TKHD_FLAG_IN_MOVIE);
1477
    if (version == 1) {
1478 1479
        avio_wb64(pb, track->time);
        avio_wb64(pb, track->time);
1480
    } else {
1481 1482
        avio_wb32(pb, track->time); /* creation time */
        avio_wb32(pb, track->time); /* modification time */
1483
    }
1484
    avio_wb32(pb, track->track_id); /* track-id */
1485
    avio_wb32(pb, 0); /* reserved */
1486 1487 1488 1489
    if (!track->entry)
        (version == 1) ? avio_wb64(pb, UINT64_C(0xffffffffffffffff)) : avio_wb32(pb, 0xffffffff);
    else
        (version == 1) ? avio_wb64(pb, duration) : avio_wb32(pb, duration);
1490

1491 1492
    avio_wb32(pb, 0); /* reserved */
    avio_wb32(pb, 0); /* reserved */
1493
    avio_wb16(pb, 0); /* layer */
1494
    avio_wb16(pb, st ? st->codec->codec_type : 0); /* alternate group) */
1495
    /* Volume, only for audio */
1496
    if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
1497
        avio_wb16(pb, 0x0100);
1498
    else
1499 1500
        avio_wb16(pb, 0);
    avio_wb16(pb, 0); /* reserved */
1501 1502

    /* Matrix structure */
1503 1504 1505 1506 1507 1508 1509 1510 1511
    avio_wb32(pb, 0x00010000); /* reserved */
    avio_wb32(pb, 0x0); /* reserved */
    avio_wb32(pb, 0x0); /* reserved */
    avio_wb32(pb, 0x0); /* reserved */
    avio_wb32(pb, 0x00010000); /* reserved */
    avio_wb32(pb, 0x0); /* reserved */
    avio_wb32(pb, 0x0); /* reserved */
    avio_wb32(pb, 0x0); /* reserved */
    avio_wb32(pb, 0x40000000); /* reserved */
1512 1513

    /* Track width and height, for visual only */
1514 1515 1516
    if (st && (track->enc->codec_type == AVMEDIA_TYPE_VIDEO ||
               track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE)) {
        if (track->mode == MODE_MOV) {
1517
            avio_wb32(pb, track->enc->width << 16);
1518
            avio_wb32(pb, track->height << 16);
1519
        } else {
1520
            double sample_aspect_ratio = av_q2d(st->sample_aspect_ratio);
1521
            if (!sample_aspect_ratio || track->height != track->enc->height)
1522
                sample_aspect_ratio = 1;
1523 1524
            avio_wb32(pb, sample_aspect_ratio * track->enc->width * 0x10000);
            avio_wb32(pb, track->height * 0x10000);
1525
        }
1526
    } else {
1527 1528
        avio_wb32(pb, 0);
        avio_wb32(pb, 0);
1529 1530 1531 1532
    }
    return 0x5c;
}

1533
static int mov_write_tapt_tag(AVIOContext *pb, MOVTrack *track)
1534 1535 1536 1537
{
    int32_t width = av_rescale(track->enc->sample_aspect_ratio.num, track->enc->width,
                               track->enc->sample_aspect_ratio.den);

1538
    int64_t pos = avio_tell(pb);
1539 1540

    avio_wb32(pb, 0); /* size */
1541
    ffio_wfourcc(pb, "tapt");
1542 1543

    avio_wb32(pb, 20);
1544
    ffio_wfourcc(pb, "clef");
1545 1546 1547
    avio_wb32(pb, 0);
    avio_wb32(pb, width << 16);
    avio_wb32(pb, track->enc->height << 16);
1548 1549 1550 1551 1552 1553

    avio_wb32(pb, 20);
    ffio_wfourcc(pb, "prof");
    avio_wb32(pb, 0);
    avio_wb32(pb, width << 16);
    avio_wb32(pb, track->enc->height << 16);
1554 1555

    avio_wb32(pb, 20);
1556
    ffio_wfourcc(pb, "enof");
1557 1558 1559 1560
    avio_wb32(pb, 0);
    avio_wb32(pb, track->enc->width << 16);
    avio_wb32(pb, track->enc->height << 16);

1561
    return update_size(pb, pos);
1562
}
1563

1564
// This box seems important for the psp playback ... without it the movie seems to hang
1565
static int mov_write_edts_tag(AVIOContext *pb, MOVTrack *track)
1566
{
1567
    int64_t duration = av_rescale_rnd(track->track_duration, MOV_TIMESCALE,
1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581
                                      track->timescale, AV_ROUND_UP);
    int version = duration < INT32_MAX ? 0 : 1;
    int entry_size, entry_count, size;
    int64_t delay, start_ct = track->cluster[0].cts;
    delay = av_rescale_rnd(track->cluster[0].dts + start_ct, MOV_TIMESCALE,
                           track->timescale, AV_ROUND_DOWN);
    version |= delay < INT32_MAX ? 0 : 1;

    entry_size = (version == 1) ? 20 : 12;
    entry_count = 1 + (delay > 0);
    size = 24 + entry_count * entry_size;

    /* write the atom data */
    avio_wb32(pb, size);
1582
    ffio_wfourcc(pb, "edts");
1583
    avio_wb32(pb, size - 8);
1584
    ffio_wfourcc(pb, "elst");
1585 1586
    avio_w8(pb, version);
    avio_wb24(pb, 0); /* flags */
1587

1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598
    avio_wb32(pb, entry_count);
    if (delay > 0) { /* add an empty edit to delay presentation */
        if (version == 1) {
            avio_wb64(pb, delay);
            avio_wb64(pb, -1);
        } else {
            avio_wb32(pb, delay);
            avio_wb32(pb, -1);
        }
        avio_wb32(pb, 0x00010000);
    }
1599

1600 1601 1602 1603 1604 1605 1606 1607
    /* duration */
    if (version == 1) {
        avio_wb64(pb, duration);
        avio_wb64(pb, start_ct);
    } else {
        avio_wb32(pb, duration);
        avio_wb32(pb, start_ct);
    }
1608
    avio_wb32(pb, 0x00010000);
1609
    return size;
1610 1611
}

1612
static int mov_write_tref_tag(AVIOContext *pb, MOVTrack *track)
1613
{
1614
    avio_wb32(pb, 20);   // size
1615
    ffio_wfourcc(pb, "tref");
1616 1617 1618
    avio_wb32(pb, 12);   // size (subatom)
    avio_wl32(pb, track->tref_tag);
    avio_wb32(pb, track->tref_id);
1619 1620 1621
    return 20;
}

1622
// goes at the end of each track!  ... Critical for PSP playback ("Incompatible data" without it)
1623
static int mov_write_uuid_tag_psp(AVIOContext *pb, MOVTrack *mov)
1624
{
1625
    avio_wb32(pb, 0x34); /* size ... reports as 28 in mp4box! */
1626 1627
    ffio_wfourcc(pb, "uuid");
    ffio_wfourcc(pb, "USMT");
1628 1629 1630 1631
    avio_wb32(pb, 0x21d24fce);
    avio_wb32(pb, 0xbb88695c);
    avio_wb32(pb, 0xfac9c740);
    avio_wb32(pb, 0x1c);     // another size here!
1632
    ffio_wfourcc(pb, "MTDT");
1633 1634 1635 1636 1637
    avio_wb32(pb, 0x00010012);
    avio_wb32(pb, 0x0a);
    avio_wb32(pb, 0x55c40000);
    avio_wb32(pb, 0x1);
    avio_wb32(pb, 0x0);
1638 1639 1640
    return 0x34;
}

1641
static int mov_write_udta_sdp(AVIOContext *pb, MOVTrack *track)
1642
{
1643
    AVFormatContext *ctx = track->rtp_ctx;
1644 1645 1646
    char buf[1000] = "";
    int len;

1647 1648 1649
    ff_sdp_write_media(buf, sizeof(buf), ctx->streams[0], track->src_track,
                       NULL, NULL, 0, 0, ctx);
    av_strlcatf(buf, sizeof(buf), "a=control:streamid=%d\r\n", track->track_id);
1650 1651
    len = strlen(buf);

1652
    avio_wb32(pb, len + 24);
1653
    ffio_wfourcc(pb, "udta");
1654
    avio_wb32(pb, len + 16);
1655
    ffio_wfourcc(pb, "hnti");
1656
    avio_wb32(pb, len + 8);
1657
    ffio_wfourcc(pb, "sdp ");
1658
    avio_write(pb, buf, len);
1659 1660 1661
    return len + 24;
}

1662 1663
static int mov_write_trak_tag(AVIOContext *pb, MOVMuxContext *mov,
                              MOVTrack *track, AVStream *st)
1664
{
1665
    int64_t pos = avio_tell(pb);
1666
    avio_wb32(pb, 0); /* size */
1667
    ffio_wfourcc(pb, "trak");
1668
    mov_write_tkhd_tag(pb, track, st);
1669
    if (track->mode == MODE_PSP || track->flags & MOV_TRACK_CTTS ||
1670 1671
        (track->entry && track->cluster[0].dts) ||
        is_clcp_track(track)) {
1672 1673 1674
        if (!(mov->flags & FF_MOV_FLAG_FRAGMENT))
            mov_write_edts_tag(pb, track);  // PSP Movies require edts box
    }
1675 1676
    if (track->tref_tag)
        mov_write_tref_tag(pb, track);
1677
    mov_write_mdia_tag(pb, track);
1678
    if (track->mode == MODE_PSP)
1679
        mov_write_uuid_tag_psp(pb, track); // PSP Movies require this uuid box
1680
    if (track->tag == MKTAG('r','t','p',' '))
1681
        mov_write_udta_sdp(pb, track);
1682 1683 1684 1685 1686 1687 1688 1689
    if (track->mode == MODE_MOV) {
        if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) {
            double sample_aspect_ratio = av_q2d(st->sample_aspect_ratio);
            if ((0.0 != sample_aspect_ratio && 1.0 != sample_aspect_ratio)) {
                mov_write_tapt_tag(pb, track);
            }
        }
        if (is_clcp_track(track)) {
1690
            mov_write_tapt_tag(pb, track);
1691
        }
1692
    }
1693
    return update_size(pb, pos);
1694 1695
}

1696
static int mov_write_iods_tag(AVIOContext *pb, MOVMuxContext *mov)
1697
{
1698 1699 1700 1701 1702
    int i, has_audio = 0, has_video = 0;
    int64_t pos = avio_tell(pb);
    int audio_profile = mov->iods_audio_profile;
    int video_profile = mov->iods_video_profile;
    for (i = 0; i < mov->nb_streams; i++) {
1703
        if (mov->tracks[i].entry > 0) {
1704 1705 1706 1707 1708 1709 1710 1711 1712
            has_audio |= mov->tracks[i].enc->codec_type == AVMEDIA_TYPE_AUDIO;
            has_video |= mov->tracks[i].enc->codec_type == AVMEDIA_TYPE_VIDEO;
        }
    }
    if (audio_profile < 0)
        audio_profile = 0xFF - has_audio;
    if (video_profile < 0)
        video_profile = 0xFF - has_video;
    avio_wb32(pb, 0x0); /* size */
1713
    ffio_wfourcc(pb, "iods");
1714
    avio_wb32(pb, 0);    /* version & flags */
1715
    put_descr(pb, 0x10, 7);
1716 1717 1718 1719 1720 1721
    avio_wb16(pb, 0x004f);
    avio_w8(pb, 0xff);
    avio_w8(pb, 0xff);
    avio_w8(pb, audio_profile);
    avio_w8(pb, video_profile);
    avio_w8(pb, 0xff);
1722
    return update_size(pb, pos);
1723 1724
}

1725 1726 1727 1728 1729
static int mov_write_trex_tag(AVIOContext *pb, MOVTrack *track)
{
    avio_wb32(pb, 0x20); /* size */
    ffio_wfourcc(pb, "trex");
    avio_wb32(pb, 0);   /* version & flags */
1730
    avio_wb32(pb, track->track_id); /* track ID */
1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745
    avio_wb32(pb, 1);   /* default sample description index */
    avio_wb32(pb, 0);   /* default sample duration */
    avio_wb32(pb, 0);   /* default sample size */
    avio_wb32(pb, 0);   /* default sample flags */
    return 0;
}

static int mov_write_mvex_tag(AVIOContext *pb, MOVMuxContext *mov)
{
    int64_t pos = avio_tell(pb);
    int i;
    avio_wb32(pb, 0x0); /* size */
    ffio_wfourcc(pb, "mvex");
    for (i = 0; i < mov->nb_streams; i++)
        mov_write_trex_tag(pb, &mov->tracks[i]);
1746
    return update_size(pb, pos);
1747 1748
}

1749
static int mov_write_mvhd_tag(AVIOContext *pb, MOVMuxContext *mov)
1750
{
1751 1752
    int max_track_id = 1, i;
    int64_t max_track_len_temp, max_track_len = 0;
1753
    int version;
1754

1755
    for (i = 0; i < mov->nb_streams; i++) {
1756
        if (mov->tracks[i].entry > 0 && mov->tracks[i].timescale) {
1757 1758 1759 1760 1761 1762 1763 1764
            max_track_len_temp = av_rescale_rnd(mov->tracks[i].track_duration,
                                                MOV_TIMESCALE,
                                                mov->tracks[i].timescale,
                                                AV_ROUND_UP);
            if (max_track_len < max_track_len_temp)
                max_track_len = max_track_len_temp;
            if (max_track_id < mov->tracks[i].track_id)
                max_track_id = mov->tracks[i].track_id;
1765 1766
        }
    }
1767

1768
    version = max_track_len < UINT32_MAX ? 0 : 1;
1769
    (version == 1) ? avio_wb32(pb, 120) : avio_wb32(pb, 108); /* size */
1770
    ffio_wfourcc(pb, "mvhd");
1771 1772
    avio_w8(pb, version);
    avio_wb24(pb, 0); /* flags */
1773
    if (version == 1) {
1774 1775
        avio_wb64(pb, mov->time);
        avio_wb64(pb, mov->time);
1776
    } else {
1777 1778
        avio_wb32(pb, mov->time); /* creation time */
        avio_wb32(pb, mov->time); /* modification time */
1779
    }
1780
    avio_wb32(pb, MOV_TIMESCALE);
1781
    (version == 1) ? avio_wb64(pb, max_track_len) : avio_wb32(pb, max_track_len); /* duration of longest track */
1782

1783 1784 1785 1786 1787
    avio_wb32(pb, 0x00010000); /* reserved (preferred rate) 1.0 = normal */
    avio_wb16(pb, 0x0100); /* reserved (preferred volume) 1.0 = normal */
    avio_wb16(pb, 0); /* reserved */
    avio_wb32(pb, 0); /* reserved */
    avio_wb32(pb, 0); /* reserved */
1788 1789

    /* Matrix structure */
1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805
    avio_wb32(pb, 0x00010000); /* reserved */
    avio_wb32(pb, 0x0); /* reserved */
    avio_wb32(pb, 0x0); /* reserved */
    avio_wb32(pb, 0x0); /* reserved */
    avio_wb32(pb, 0x00010000); /* reserved */
    avio_wb32(pb, 0x0); /* reserved */
    avio_wb32(pb, 0x0); /* reserved */
    avio_wb32(pb, 0x0); /* reserved */
    avio_wb32(pb, 0x40000000); /* reserved */

    avio_wb32(pb, 0); /* reserved (preview time) */
    avio_wb32(pb, 0); /* reserved (preview duration) */
    avio_wb32(pb, 0); /* reserved (poster time) */
    avio_wb32(pb, 0); /* reserved (selection time) */
    avio_wb32(pb, 0); /* reserved (selection duration) */
    avio_wb32(pb, 0); /* reserved (current time) */
1806
    avio_wb32(pb, max_track_id + 1); /* Next track id */
1807 1808 1809
    return 0x6c;
}

1810
static int mov_write_itunes_hdlr_tag(AVIOContext *pb, MOVMuxContext *mov,
1811 1812
                                     AVFormatContext *s)
{
1813
    avio_wb32(pb, 33); /* size */
1814
    ffio_wfourcc(pb, "hdlr");
1815 1816
    avio_wb32(pb, 0);
    avio_wb32(pb, 0);
1817 1818
    ffio_wfourcc(pb, "mdir");
    ffio_wfourcc(pb, "appl");
1819 1820 1821
    avio_wb32(pb, 0);
    avio_wb32(pb, 0);
    avio_w8(pb, 0);
1822
    return 33;
1823 1824 1825
}

/* helper function to write a data tag with the specified string as data */
1826
static int mov_write_string_data_tag(AVIOContext *pb, const char *data, int lang, int long_style)
1827
{
1828
    if (long_style) {
1829
        int size = 16 + strlen(data);
1830
        avio_wb32(pb, size); /* size */
1831
        ffio_wfourcc(pb, "data");
1832 1833 1834
        avio_wb32(pb, 1);
        avio_wb32(pb, 0);
        avio_write(pb, data, strlen(data));
1835
        return size;
1836
    } else {
1837 1838
        if (!lang)
            lang = ff_mov_iso639_to_lang("und", 1);
1839 1840 1841
        avio_wb16(pb, strlen(data)); /* string length */
        avio_wb16(pb, lang);
        avio_write(pb, data, strlen(data));
1842
        return strlen(data) + 4;
1843 1844 1845
    }
}

1846 1847 1848
static int mov_write_string_tag(AVIOContext *pb, const char *name,
                                const char *value, int lang, int long_style)
{
1849
    int size = 0;
1850
    if (value && value[0]) {
1851
        int64_t pos = avio_tell(pb);
1852
        avio_wb32(pb, 0); /* size */
1853
        ffio_wfourcc(pb, name);
1854
        mov_write_string_data_tag(pb, value, lang, long_style);
1855
        size = update_size(pb, pos);
1856 1857 1858 1859
    }
    return size;
}

1860
static int mov_write_string_metadata(AVFormatContext *s, AVIOContext *pb,
1861 1862
                                     const char *name, const char *tag,
                                     int long_style)
1863
{
1864
    int l, lang = 0, len, len2;
1865
    AVDictionaryEntry *t, *t2 = NULL;
1866
    char tag2[16];
1867

1868
    if (!(t = av_dict_get(s->metadata, tag, NULL, 0)))
1869
        return 0;
1870

1871 1872
    len = strlen(t->key);
    snprintf(tag2, sizeof(tag2), "%s-", tag);
1873
    while ((t2 = av_dict_get(s->metadata, tag2, t2, AV_DICT_IGNORE_SUFFIX))) {
1874
        len2 = strlen(t2->key);
1875 1876
        if (len2 == len + 4 && !strcmp(t->value, t2->value)
            && (l = ff_mov_iso639_to_lang(&t2->key[len2 - 3], 1)) >= 0) {
1877 1878 1879 1880 1881
            lang = l;
            break;
        }
    }
    return mov_write_string_tag(pb, name, t->value, lang, long_style);
1882 1883 1884
}

/* iTunes track number */
1885
static int mov_write_trkn_tag(AVIOContext *pb, MOVMuxContext *mov,
1886 1887
                              AVFormatContext *s)
{
1888
    AVDictionaryEntry *t = av_dict_get(s->metadata, "track", NULL, 0);
1889 1890
    int size = 0, track = t ? atoi(t->value) : 0;
    if (track) {
1891
        avio_wb32(pb, 32); /* size */
1892
        ffio_wfourcc(pb, "trkn");
1893 1894 1895 1896 1897 1898 1899 1900
        avio_wb32(pb, 24); /* size */
        ffio_wfourcc(pb, "data");
        avio_wb32(pb, 0);        // 8 bytes empty
        avio_wb32(pb, 0);
        avio_wb16(pb, 0);        // empty
        avio_wb16(pb, track);    // track number
        avio_wb16(pb, 0);        // total track number
        avio_wb16(pb, 0);        // empty
1901
        size = 32;
1902 1903 1904 1905 1906
    }
    return size;
}

/* iTunes meta data list */
1907
static int mov_write_ilst_tag(AVIOContext *pb, MOVMuxContext *mov,
1908 1909
                              AVFormatContext *s)
{
1910
    int64_t pos = avio_tell(pb);
1911
    avio_wb32(pb, 0); /* size */
1912
    ffio_wfourcc(pb, "ilst");
1913
    mov_write_string_metadata(s, pb, "\251nam", "title"    , 1);
1914
    mov_write_string_metadata(s, pb, "\251ART", "artist"   , 1);
1915
    mov_write_string_metadata(s, pb, "aART", "album_artist", 1);
1916
    mov_write_string_metadata(s, pb, "\251wrt", "composer" , 1);
1917
    mov_write_string_metadata(s, pb, "\251alb", "album"    , 1);
1918
    mov_write_string_metadata(s, pb, "\251day", "date"     , 1);
1919 1920
    if (!mov_write_string_metadata(s, pb, "\251too", "encoding_tool", 1))
        mov_write_string_tag(pb, "\251too", LIBAVFORMAT_IDENT, 0, 1);
1921 1922 1923
    mov_write_string_metadata(s, pb, "\251cmt", "comment"  , 1);
    mov_write_string_metadata(s, pb, "\251gen", "genre"    , 1);
    mov_write_string_metadata(s, pb, "\251cpy", "copyright", 1);
1924 1925
    mov_write_string_metadata(s, pb, "\251grp", "grouping" , 1);
    mov_write_string_metadata(s, pb, "\251lyr", "lyrics"   , 1);
1926 1927 1928 1929 1930
    mov_write_string_metadata(s, pb, "desc",    "description",1);
    mov_write_string_metadata(s, pb, "ldes",    "synopsis" , 1);
    mov_write_string_metadata(s, pb, "tvsh",    "show"     , 1);
    mov_write_string_metadata(s, pb, "tven",    "episode_id",1);
    mov_write_string_metadata(s, pb, "tvnn",    "network"  , 1);
1931
    mov_write_trkn_tag(pb, mov, s);
1932
    return update_size(pb, pos);
1933 1934 1935
}

/* iTunes meta data tag */
1936
static int mov_write_meta_tag(AVIOContext *pb, MOVMuxContext *mov,
1937 1938 1939
                              AVFormatContext *s)
{
    int size = 0;
1940
    int64_t pos = avio_tell(pb);
1941
    avio_wb32(pb, 0); /* size */
1942
    ffio_wfourcc(pb, "meta");
1943
    avio_wb32(pb, 0);
Aurelien Jacobs's avatar
Aurelien Jacobs committed
1944 1945
    mov_write_itunes_hdlr_tag(pb, mov, s);
    mov_write_ilst_tag(pb, mov, s);
1946
    size = update_size(pb, pos);
1947 1948
    return size;
}
1949

1950 1951
static int utf8len(const uint8_t *b)
{
1952
    int len = 0;
1953
    int val;
1954
    while (*b) {
1955 1956 1957 1958 1959 1960
        GET_UTF8(val, *b++, return -1;)
        len++;
    }
    return len;
}

1961
static int ascii_to_wc(AVIOContext *pb, const uint8_t *b)
1962 1963
{
    int val;
1964
    while (*b) {
1965
        GET_UTF8(val, *b++, return -1;)
1966
        avio_wb16(pb, val);
1967
    }
1968
    avio_wb16(pb, 0x00);
1969 1970 1971 1972 1973
    return 0;
}

static uint16_t language_code(const char *str)
{
1974 1975 1976
    return (((str[0] - 0x60) & 0x1F) << 10) +
           (((str[1] - 0x60) & 0x1F) <<  5) +
           (( str[2] - 0x60) & 0x1F);
1977 1978
}

1979
static int mov_write_3gp_udta_tag(AVIOContext *pb, AVFormatContext *s,
1980 1981
                                  const char *tag, const char *str)
{
1982
    int64_t pos = avio_tell(pb);
1983
    AVDictionaryEntry *t = av_dict_get(s->metadata, str, NULL, 0);
1984
    if (!t || !utf8len(t->value))
1985
        return 0;
1986
    avio_wb32(pb, 0);   /* size */
1987
    ffio_wfourcc(pb, tag); /* type */
1988
    avio_wb32(pb, 0);   /* version + flags */
1989
    if (!strcmp(tag, "yrrc"))
1990
        avio_wb16(pb, atoi(t->value));
1991
    else {
1992
        avio_wb16(pb, language_code("eng")); /* language */
1993
        avio_write(pb, t->value, strlen(t->value) + 1); /* UTF8 string value */
1994
        if (!strcmp(tag, "albm") &&
1995
            (t = av_dict_get(s->metadata, "track", NULL, 0)))
1996
            avio_w8(pb, atoi(t->value));
1997
    }
1998
    return update_size(pb, pos);
1999 2000
}

2001
static int mov_write_chpl_tag(AVIOContext *pb, AVFormatContext *s)
2002
{
2003
    int64_t pos = avio_tell(pb);
2004 2005
    int i, nb_chapters = FFMIN(s->nb_chapters, 255);

2006
    avio_wb32(pb, 0);            // size
2007
    ffio_wfourcc(pb, "chpl");
2008 2009 2010
    avio_wb32(pb, 0x01000000);   // version + flags
    avio_wb32(pb, 0);            // unknown
    avio_w8(pb, nb_chapters);
2011 2012 2013

    for (i = 0; i < nb_chapters; i++) {
        AVChapter *c = s->chapters[i];
2014
        AVDictionaryEntry *t;
2015
        avio_wb64(pb, av_rescale_q(c->start, c->time_base, (AVRational){1,10000000}));
2016

2017
        if ((t = av_dict_get(c->metadata, "title", NULL, 0))) {
2018
            int len = FFMIN(strlen(t->value), 255);
2019 2020
            avio_w8(pb, len);
            avio_write(pb, t->value, len);
2021
        } else
2022
            avio_w8(pb, 0);
2023
    }
2024
    return update_size(pb, pos);
2025 2026
}

2027
static int mov_write_udta_tag(AVIOContext *pb, MOVMuxContext *mov,
2028 2029
                              AVFormatContext *s)
{
2030
    AVIOContext *pb_buf;
2031 2032
    int i, ret, size;
    uint8_t *buf;
2033

2034
    for (i = 0; i < s->nb_streams; i++)
2035
        if (s->flags & AVFMT_FLAG_BITEXACT) {
2036
            return 0;
2037 2038
        }

2039
    ret = avio_open_dyn_buf(&pb_buf);
2040
    if (ret < 0)
2041
        return ret;
2042

2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065
    if (mov->mode & MODE_3GP) {
        mov_write_3gp_udta_tag(pb_buf, s, "perf", "artist");
        mov_write_3gp_udta_tag(pb_buf, s, "titl", "title");
        mov_write_3gp_udta_tag(pb_buf, s, "auth", "author");
        mov_write_3gp_udta_tag(pb_buf, s, "gnre", "genre");
        mov_write_3gp_udta_tag(pb_buf, s, "dscp", "comment");
        mov_write_3gp_udta_tag(pb_buf, s, "albm", "album");
        mov_write_3gp_udta_tag(pb_buf, s, "cprt", "copyright");
        mov_write_3gp_udta_tag(pb_buf, s, "yrrc", "date");
    } else if (mov->mode == MODE_MOV) { // the title field breaks gtkpod with mp4 and my suspicion is that stuff is not valid in mp4
        mov_write_string_metadata(s, pb_buf, "\251ART", "artist",      0);
        mov_write_string_metadata(s, pb_buf, "\251nam", "title",       0);
        mov_write_string_metadata(s, pb_buf, "\251aut", "author",      0);
        mov_write_string_metadata(s, pb_buf, "\251alb", "album",       0);
        mov_write_string_metadata(s, pb_buf, "\251day", "date",        0);
        mov_write_string_metadata(s, pb_buf, "\251swr", "encoder",     0);
        mov_write_string_metadata(s, pb_buf, "\251des", "comment",     0);
        mov_write_string_metadata(s, pb_buf, "\251gen", "genre",       0);
        mov_write_string_metadata(s, pb_buf, "\251cpy", "copyright",   0);
    } else {
        /* iTunes meta data */
        mov_write_meta_tag(pb_buf, mov, s);
    }
2066

2067 2068
    if (s->nb_chapters)
        mov_write_chpl_tag(pb_buf, s);
2069

2070
    if ((size = avio_close_dyn_buf(pb_buf, &buf)) > 0) {
2071
        avio_wb32(pb, size + 8);
2072
        ffio_wfourcc(pb, "udta");
2073
        avio_write(pb, buf, size);
2074
    }
2075
    av_free(buf);
2076 2077

    return 0;
2078 2079
}

2080
static void mov_write_psp_udta_tag(AVIOContext *pb,
2081
                                   const char *str, const char *lang, int type)
2082
{
2083 2084
    int len = utf8len(str) + 1;
    if (len <= 0)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2085
        return;
2086
    avio_wb16(pb, len * 2 + 10);        /* size */
2087 2088 2089
    avio_wb32(pb, type);                /* type */
    avio_wb16(pb, language_code(lang)); /* language */
    avio_wb16(pb, 0x01);                /* ? */
2090 2091 2092
    ascii_to_wc(pb, str);
}

2093
static int mov_write_uuidusmt_tag(AVIOContext *pb, AVFormatContext *s)
2094
{
2095
    AVDictionaryEntry *title = av_dict_get(s->metadata, "title", NULL, 0);
2096
    int64_t pos, pos2;
2097

2098
    if (title) {
2099
        pos = avio_tell(pb);
2100
        avio_wb32(pb, 0); /* size placeholder*/
2101 2102
        ffio_wfourcc(pb, "uuid");
        ffio_wfourcc(pb, "USMT");
2103 2104 2105
        avio_wb32(pb, 0x21d24fce); /* 96 bit UUID */
        avio_wb32(pb, 0xbb88695c);
        avio_wb32(pb, 0xfac9c740);
2106

2107
        pos2 = avio_tell(pb);
2108
        avio_wb32(pb, 0); /* size placeholder*/
2109
        ffio_wfourcc(pb, "MTDT");
2110
        avio_wb16(pb, 4);
2111

2112
        // ?
2113 2114 2115 2116 2117
        avio_wb16(pb, 0x0C);                 /* size */
        avio_wb32(pb, 0x0B);                 /* type */
        avio_wb16(pb, language_code("und")); /* language */
        avio_wb16(pb, 0x0);                  /* ? */
        avio_wb16(pb, 0x021C);               /* data */
2118

Baptiste Coudurier's avatar
Baptiste Coudurier committed
2119
        mov_write_psp_udta_tag(pb, LIBAVCODEC_IDENT,      "eng", 0x04);
2120
        mov_write_psp_udta_tag(pb, title->value,          "eng", 0x01);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2121 2122
        mov_write_psp_udta_tag(pb, "2006/04/01 11:11:11", "und", 0x03);

2123 2124
        update_size(pb, pos2);
        return update_size(pb, pos);
2125 2126
    }

Baptiste Coudurier's avatar
Baptiste Coudurier committed
2127
    return 0;
2128 2129
}

2130
static int mov_write_moov_tag(AVIOContext *pb, MOVMuxContext *mov,
2131
                              AVFormatContext *s)
2132
{
2133
    int i;
2134
    int64_t pos = avio_tell(pb);
2135
    avio_wb32(pb, 0); /* size placeholder*/
2136
    ffio_wfourcc(pb, "moov");
2137

2138
    for (i = 0; i < mov->nb_streams; i++) {
2139 2140
        if (mov->tracks[i].entry <= 0 && !(mov->flags & FF_MOV_FLAG_FRAGMENT))
            continue;
2141

2142 2143
        mov->tracks[i].time     = mov->time;
        mov->tracks[i].track_id = i + 1;
2144 2145
    }

2146
    if (mov->chapter_track)
2147
        for (i = 0; i < s->nb_streams; i++) {
2148
            mov->tracks[i].tref_tag = MKTAG('c','h','a','p');
2149
            mov->tracks[i].tref_id  = mov->tracks[mov->chapter_track].track_id;
2150
        }
2151 2152 2153 2154
    for (i = 0; i < mov->nb_streams; i++) {
        if (mov->tracks[i].tag == MKTAG('r','t','p',' ')) {
            mov->tracks[i].tref_tag = MKTAG('h','i','n','t');
            mov->tracks[i].tref_id =
2155
                mov->tracks[mov->tracks[i].src_track].track_id;
2156 2157
        }
    }
2158

2159
    mov_write_mvhd_tag(pb, mov);
2160 2161
    if (mov->mode != MODE_MOV && !mov->iods_skip)
        mov_write_iods_tag(pb, mov);
2162
    for (i = 0; i < mov->nb_streams; i++) {
2163 2164
        if (mov->tracks[i].entry > 0 || mov->flags & FF_MOV_FLAG_FRAGMENT) {
            mov_write_trak_tag(pb, mov, &(mov->tracks[i]), i < s->nb_streams ? s->streams[i] : NULL);
2165 2166
        }
    }
2167 2168
    if (mov->flags & FF_MOV_FLAG_FRAGMENT)
        mov_write_mvex_tag(pb, mov); /* QuickTime requires trak to precede this */
2169

2170 2171
    if (mov->mode == MODE_PSP)
        mov_write_uuidusmt_tag(pb, s);
2172
    else
2173
        mov_write_udta_tag(pb, mov, s);
2174

2175
    return update_size(pb, pos);
2176 2177
}

2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190
static void param_write_int(AVIOContext *pb, const char *name, int value)
{
    avio_printf(pb, "<param name=\"%s\" value=\"%d\" valuetype=\"data\"/>\n", name, value);
}

static void param_write_string(AVIOContext *pb, const char *name, const char *value)
{
    avio_printf(pb, "<param name=\"%s\" value=\"%s\" valuetype=\"data\"/>\n", name, value);
}

static void param_write_hex(AVIOContext *pb, const char *name, const uint8_t *value, int len)
{
    char buf[150];
2191
    len = FFMIN(sizeof(buf) / 2 - 1, len);
2192
    ff_data_to_hex(buf, value, len, 0);
2193
    buf[2 * len] = '\0';
2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221
    avio_printf(pb, "<param name=\"%s\" value=\"%s\" valuetype=\"data\"/>\n", name, buf);
}

static int mov_write_isml_manifest(AVIOContext *pb, MOVMuxContext *mov)
{
    int64_t pos = avio_tell(pb);
    int i;
    const uint8_t uuid[] = {
        0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
        0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
    };

    avio_wb32(pb, 0);
    ffio_wfourcc(pb, "uuid");
    avio_write(pb, uuid, sizeof(uuid));
    avio_wb32(pb, 0);

    avio_printf(pb, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
    avio_printf(pb, "<smil xmlns=\"http://www.w3.org/2001/SMIL20/Language\">\n");
    avio_printf(pb, "<head>\n");
    avio_printf(pb, "<meta name=\"creator\" content=\"%s\" />\n",
                    LIBAVFORMAT_IDENT);
    avio_printf(pb, "</head>\n");
    avio_printf(pb, "<body>\n");
    avio_printf(pb, "<switch>\n");
    for (i = 0; i < mov->nb_streams; i++) {
        MOVTrack *track = &mov->tracks[i];
        const char *type;
2222
        /* track->track_id is initialized in write_moov, and thus isn't known
2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237
         * here yet */
        int track_id = i + 1;

        if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) {
            type = "video";
        } else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) {
            type = "audio";
        } else {
            continue;
        }
        avio_printf(pb, "<%s systemBitrate=\"%d\">\n", type,
                                                       track->enc->bit_rate);
        param_write_int(pb, "systemBitrate", track->enc->bit_rate);
        param_write_int(pb, "trackID", track_id);
        if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) {
2238
            if (track->enc->codec_id == AV_CODEC_ID_H264) {
2239 2240 2241 2242 2243 2244 2245 2246 2247
                uint8_t *ptr;
                int size = track->enc->extradata_size;
                if (!ff_avc_write_annexb_extradata(track->enc->extradata, &ptr,
                                                   &size)) {
                    param_write_hex(pb, "CodecPrivateData",
                                    ptr ? ptr : track->enc->extradata,
                                    size);
                    av_free(ptr);
                }
2248
                param_write_string(pb, "FourCC", "H264");
2249
            } else if (track->enc->codec_id == AV_CODEC_ID_VC1) {
2250
                param_write_string(pb, "FourCC", "WVC1");
2251 2252
                param_write_hex(pb, "CodecPrivateData", track->enc->extradata,
                                track->enc->extradata_size);
2253 2254 2255 2256 2257 2258
            }
            param_write_int(pb, "MaxWidth", track->enc->width);
            param_write_int(pb, "MaxHeight", track->enc->height);
            param_write_int(pb, "DisplayWidth", track->enc->width);
            param_write_int(pb, "DisplayHeight", track->enc->height);
        } else {
2259
            if (track->enc->codec_id == AV_CODEC_ID_AAC) {
2260
                param_write_string(pb, "FourCC", "AACL");
2261
            } else if (track->enc->codec_id == AV_CODEC_ID_WMAPRO) {
2262 2263 2264 2265 2266
                param_write_string(pb, "FourCC", "WMAP");
            }
            param_write_hex(pb, "CodecPrivateData", track->enc->extradata,
                            track->enc->extradata_size);
            param_write_int(pb, "AudioTag", ff_codec_get_tag(ff_codec_wav_tags,
2267
                                                             track->enc->codec_id));
2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279
            param_write_int(pb, "Channels", track->enc->channels);
            param_write_int(pb, "SamplingRate", track->enc->sample_rate);
            param_write_int(pb, "BitsPerSample", 16);
            param_write_int(pb, "PacketSize", track->enc->block_align ?
                                              track->enc->block_align : 4);
        }
        avio_printf(pb, "</%s>\n", type);
    }
    avio_printf(pb, "</switch>\n");
    avio_printf(pb, "</body>\n");
    avio_printf(pb, "</smil>\n");

2280
    return update_size(pb, pos);
2281 2282
}

2283 2284 2285 2286 2287 2288 2289 2290 2291
static int mov_write_mfhd_tag(AVIOContext *pb, MOVMuxContext *mov)
{
    avio_wb32(pb, 16);
    ffio_wfourcc(pb, "mfhd");
    avio_wb32(pb, 0);
    avio_wb32(pb, mov->fragments);
    return 0;
}

2292 2293
static int mov_write_tfhd_tag(AVIOContext *pb, MOVMuxContext *mov,
                              MOVTrack *track, int64_t moof_offset)
2294 2295
{
    int64_t pos = avio_tell(pb);
2296 2297
    uint32_t flags = MOV_TFHD_DEFAULT_SIZE | MOV_TFHD_DEFAULT_DURATION |
                     MOV_TFHD_BASE_DATA_OFFSET;
2298
    if (!track->entry) {
2299
        flags |= MOV_TFHD_DURATION_IS_EMPTY;
2300
    } else {
2301
        flags |= MOV_TFHD_DEFAULT_FLAGS;
2302
    }
2303 2304
    if (mov->flags & FF_MOV_FLAG_OMIT_TFHD_OFFSET)
        flags &= ~MOV_TFHD_BASE_DATA_OFFSET;
2305

2306 2307
    /* Don't set a default sample size, the silverlight player refuses
     * to play files with that set. Don't set a default sample duration,
2308 2309
     * WMP freaks out if it is set. Don't set a base data offset, PIFF
     * file format says it MUST NOT be set. */
2310
    if (track->mode == MODE_ISM)
2311 2312
        flags &= ~(MOV_TFHD_DEFAULT_SIZE | MOV_TFHD_DEFAULT_DURATION |
                   MOV_TFHD_BASE_DATA_OFFSET);
2313

2314 2315 2316 2317 2318
    avio_wb32(pb, 0); /* size placeholder */
    ffio_wfourcc(pb, "tfhd");
    avio_w8(pb, 0); /* version */
    avio_wb24(pb, flags);

2319
    avio_wb32(pb, track->track_id); /* track-id */
2320
    if (flags & MOV_TFHD_BASE_DATA_OFFSET)
2321
        avio_wb64(pb, moof_offset);
2322
    if (flags & MOV_TFHD_DEFAULT_DURATION) {
2323
        track->default_duration = get_cluster_duration(track, 0);
2324 2325
        avio_wb32(pb, track->default_duration);
    }
2326
    if (flags & MOV_TFHD_DEFAULT_SIZE) {
2327 2328 2329 2330 2331
        track->default_size = track->entry ? track->cluster[0].size : 1;
        avio_wb32(pb, track->default_size);
    } else
        track->default_size = -1;

2332
    if (flags & MOV_TFHD_DEFAULT_FLAGS) {
2333 2334
        track->default_sample_flags =
            track->enc->codec_type == AVMEDIA_TYPE_VIDEO ?
2335 2336
            (MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES | MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC) :
            MOV_FRAG_SAMPLE_FLAG_DEPENDS_NO;
2337 2338 2339
        avio_wb32(pb, track->default_sample_flags);
    }

2340
    return update_size(pb, pos);
2341 2342 2343 2344
}

static uint32_t get_sample_flags(MOVTrack *track, MOVIentry *entry)
{
2345 2346
    return entry->flags & MOV_SYNC_SAMPLE ? MOV_FRAG_SAMPLE_FLAG_DEPENDS_NO :
           (MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES | MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC);
2347 2348
}

2349 2350
static int mov_write_trun_tag(AVIOContext *pb, MOVMuxContext *mov,
                              MOVTrack *track, int moof_size)
2351 2352
{
    int64_t pos = avio_tell(pb);
2353
    uint32_t flags = MOV_TRUN_DATA_OFFSET;
2354 2355 2356
    int i;

    for (i = 0; i < track->entry; i++) {
2357
        if (get_cluster_duration(track, i) != track->default_duration)
2358
            flags |= MOV_TRUN_SAMPLE_DURATION;
2359
        if (track->cluster[i].size != track->default_size)
2360
            flags |= MOV_TRUN_SAMPLE_SIZE;
2361
        if (i > 0 && get_sample_flags(track, &track->cluster[i]) != track->default_sample_flags)
2362
            flags |= MOV_TRUN_SAMPLE_FLAGS;
2363
    }
2364 2365
    if (!(flags & MOV_TRUN_SAMPLE_FLAGS))
        flags |= MOV_TRUN_FIRST_SAMPLE_FLAGS;
2366
    if (track->flags & MOV_TRACK_CTTS)
2367
        flags |= MOV_TRUN_SAMPLE_CTS;
2368 2369 2370 2371 2372 2373 2374

    avio_wb32(pb, 0); /* size placeholder */
    ffio_wfourcc(pb, "trun");
    avio_w8(pb, 0); /* version */
    avio_wb24(pb, flags);

    avio_wb32(pb, track->entry); /* sample count */
2375 2376 2377 2378 2379 2380 2381
    if (mov->flags & FF_MOV_FLAG_OMIT_TFHD_OFFSET &&
        !(mov->flags & FF_MOV_FLAG_SEPARATE_MOOF) &&
        track->track_id != 1)
        avio_wb32(pb, 0); /* Later tracks follow immediately after the previous one */
    else
        avio_wb32(pb, moof_size + 8 + track->data_offset +
                      track->cluster[0].pos); /* data offset */
2382
    if (flags & MOV_TRUN_FIRST_SAMPLE_FLAGS)
2383 2384 2385
        avio_wb32(pb, get_sample_flags(track, &track->cluster[0]));

    for (i = 0; i < track->entry; i++) {
2386
        if (flags & MOV_TRUN_SAMPLE_DURATION)
2387
            avio_wb32(pb, get_cluster_duration(track, i));
2388
        if (flags & MOV_TRUN_SAMPLE_SIZE)
2389
            avio_wb32(pb, track->cluster[i].size);
2390
        if (flags & MOV_TRUN_SAMPLE_FLAGS)
2391
            avio_wb32(pb, get_sample_flags(track, &track->cluster[i]));
2392
        if (flags & MOV_TRUN_SAMPLE_CTS)
2393 2394 2395
            avio_wb32(pb, track->cluster[i].cts);
    }

2396
    return update_size(pb, pos);
2397 2398
}

2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412
static int mov_write_tfxd_tag(AVIOContext *pb, MOVTrack *track)
{
    int64_t pos = avio_tell(pb);
    const uint8_t uuid[] = {
        0x6d, 0x1d, 0x9b, 0x05, 0x42, 0xd5, 0x44, 0xe6,
        0x80, 0xe2, 0x14, 0x1d, 0xaf, 0xf7, 0x57, 0xb2
    };

    avio_wb32(pb, 0); /* size placeholder */
    ffio_wfourcc(pb, "uuid");
    avio_write(pb, uuid, sizeof(uuid));
    avio_w8(pb, 1);
    avio_wb24(pb, 0);
    avio_wb64(pb, track->frag_start);
2413
    avio_wb64(pb, track->start_dts + track->track_duration -
2414 2415
                  track->cluster[0].dts);

2416
    return update_size(pb, pos);
2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444
}

static int mov_write_tfrf_tag(AVIOContext *pb, MOVMuxContext *mov,
                              MOVTrack *track, int entry)
{
    int n = track->nb_frag_info - 1 - entry, i;
    int size = 8 + 16 + 4 + 1 + 16*n;
    const uint8_t uuid[] = {
        0xd4, 0x80, 0x7e, 0xf2, 0xca, 0x39, 0x46, 0x95,
        0x8e, 0x54, 0x26, 0xcb, 0x9e, 0x46, 0xa7, 0x9f
    };

    if (entry < 0)
        return 0;

    avio_seek(pb, track->frag_info[entry].tfrf_offset, SEEK_SET);
    avio_wb32(pb, size);
    ffio_wfourcc(pb, "uuid");
    avio_write(pb, uuid, sizeof(uuid));
    avio_w8(pb, 1);
    avio_wb24(pb, 0);
    avio_w8(pb, n);
    for (i = 0; i < n; i++) {
        int index = entry + 1 + i;
        avio_wb64(pb, track->frag_info[index].time);
        avio_wb64(pb, track->frag_info[index].duration);
    }
    if (n < mov->ism_lookahead) {
2445
        int free_size = 16 * (mov->ism_lookahead - n);
2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469
        avio_wb32(pb, free_size);
        ffio_wfourcc(pb, "free");
        for (i = 0; i < free_size - 8; i++)
            avio_w8(pb, 0);
    }

    return 0;
}

static int mov_write_tfrf_tags(AVIOContext *pb, MOVMuxContext *mov,
                               MOVTrack *track)
{
    int64_t pos = avio_tell(pb);
    int i;
    for (i = 0; i < mov->ism_lookahead; i++) {
        /* Update the tfrf tag for the last ism_lookahead fragments,
         * nb_frag_info - 1 is the next fragment to be written. */
        mov_write_tfrf_tag(pb, mov, track, track->nb_frag_info - 2 - i);
    }
    avio_seek(pb, pos, SEEK_SET);
    return 0;
}

static int mov_write_traf_tag(AVIOContext *pb, MOVMuxContext *mov,
2470 2471
                              MOVTrack *track, int64_t moof_offset,
                              int moof_size)
2472 2473 2474 2475 2476
{
    int64_t pos = avio_tell(pb);
    avio_wb32(pb, 0); /* size placeholder */
    ffio_wfourcc(pb, "traf");

2477 2478
    mov_write_tfhd_tag(pb, mov, track, moof_offset);
    mov_write_trun_tag(pb, mov, track, moof_size);
2479 2480 2481 2482
    if (mov->mode == MODE_ISM) {
        mov_write_tfxd_tag(pb, track);

        if (mov->ism_lookahead) {
2483
            int i, size = 16 + 4 + 1 + 16 * mov->ism_lookahead;
2484 2485 2486 2487 2488 2489 2490 2491

            track->tfrf_offset = avio_tell(pb);
            avio_wb32(pb, 8 + size);
            ffio_wfourcc(pb, "free");
            for (i = 0; i < size; i++)
                avio_w8(pb, 0);
        }
    }
2492

2493
    return update_size(pb, pos);
2494 2495
}

2496 2497
static int mov_write_moof_tag_internal(AVIOContext *pb, MOVMuxContext *mov,
                                       int tracks, int moof_size)
2498
{
2499 2500
    int64_t pos = avio_tell(pb);
    int i;
2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511

    avio_wb32(pb, 0); /* size placeholder */
    ffio_wfourcc(pb, "moof");

    mov_write_mfhd_tag(pb, mov);
    for (i = 0; i < mov->nb_streams; i++) {
        MOVTrack *track = &mov->tracks[i];
        if (tracks >= 0 && i != tracks)
            continue;
        if (!track->entry)
            continue;
2512
        mov_write_traf_tag(pb, mov, track, pos, moof_size);
2513 2514
    }

2515
    return update_size(pb, pos);
2516 2517
}

2518 2519 2520 2521 2522
static int mov_write_moof_tag(AVIOContext *pb, MOVMuxContext *mov, int tracks)
{
    AVIOContext *avio_buf;
    int ret, moof_size;

2523
    if ((ret = ffio_open_null_buf(&avio_buf)) < 0)
2524 2525
        return ret;
    mov_write_moof_tag_internal(avio_buf, mov, tracks, 0);
2526
    moof_size = ffio_close_null_buf(avio_buf);
2527 2528 2529
    return mov_write_moof_tag_internal(pb, mov, tracks, moof_size);
}

2530 2531 2532 2533 2534 2535 2536 2537 2538 2539
static int mov_write_tfra_tag(AVIOContext *pb, MOVTrack *track)
{
    int64_t pos = avio_tell(pb);
    int i;

    avio_wb32(pb, 0); /* size placeholder */
    ffio_wfourcc(pb, "tfra");
    avio_w8(pb, 1); /* version */
    avio_wb24(pb, 0);

2540
    avio_wb32(pb, track->track_id);
2541 2542 2543 2544 2545 2546 2547 2548 2549 2550
    avio_wb32(pb, 0); /* length of traf/trun/sample num */
    avio_wb32(pb, track->nb_frag_info);
    for (i = 0; i < track->nb_frag_info; i++) {
        avio_wb64(pb, track->frag_info[i].time);
        avio_wb64(pb, track->frag_info[i].offset);
        avio_w8(pb, 1); /* traf number */
        avio_w8(pb, 1); /* trun number */
        avio_w8(pb, 1); /* sample number */
    }

2551
    return update_size(pb, pos);
2552 2553 2554 2555 2556 2557 2558 2559 2560
}

static int mov_write_mfra_tag(AVIOContext *pb, MOVMuxContext *mov)
{
    int64_t pos = avio_tell(pb);
    int i;

    avio_wb32(pb, 0); /* size placeholder */
    ffio_wfourcc(pb, "mfra");
2561 2562 2563
    /* An empty mfra atom is enough to indicate to the publishing point that
     * the stream has ended. */
    if (mov->flags & FF_MOV_FLAG_ISML)
2564
        return update_size(pb, pos);
2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576

    for (i = 0; i < mov->nb_streams; i++) {
        MOVTrack *track = &mov->tracks[i];
        if (track->nb_frag_info)
            mov_write_tfra_tag(pb, track);
    }

    avio_wb32(pb, 16);
    ffio_wfourcc(pb, "mfro");
    avio_wb32(pb, 0); /* version + flags */
    avio_wb32(pb, avio_tell(pb) + 4 - pos);

2577
    return update_size(pb, pos);
2578 2579
}

2580
static int mov_write_mdat_tag(AVIOContext *pb, MOVMuxContext *mov)
2581
{
2582
    avio_wb32(pb, 8);    // placeholder for extended size field (64 bit)
2583
    ffio_wfourcc(pb, mov->mode == MODE_MOV ? "wide" : "free");
2584

2585
    mov->mdat_pos = avio_tell(pb);
2586
    avio_wb32(pb, 0); /* size placeholder*/
2587
    ffio_wfourcc(pb, "mdat");
2588 2589 2590 2591
    return 0;
}

/* TODO: This needs to be more general */
2592
static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s)
2593
{
2594
    MOVMuxContext *mov = s->priv_data;
2595
    int64_t pos = avio_tell(pb);
2596
    int has_h264 = 0, has_video = 0;
2597
    int minor = 0x200;
2598
    int i;
2599

2600 2601
    for (i = 0; i < s->nb_streams; i++) {
        AVStream *st = s->streams[i];
2602
        if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
2603
            has_video = 1;
2604
        if (st->codec->codec_id == AV_CODEC_ID_H264)
2605 2606 2607
            has_h264 = 1;
    }

2608
    avio_wb32(pb, 0); /* size */
2609
    ffio_wfourcc(pb, "ftyp");
2610

2611 2612 2613
    if (mov->major_brand && strlen(mov->major_brand) >= 4)
        ffio_wfourcc(pb, mov->major_brand);
    else if (mov->mode == MODE_3GP) {
2614
        ffio_wfourcc(pb, has_h264 ? "3gp6"  : "3gp4");
2615 2616
        minor =     has_h264 ?   0x100 :   0x200;
    } else if (mov->mode & MODE_3G2) {
2617
        ffio_wfourcc(pb, has_h264 ? "3g2b"  : "3g2a");
2618
        minor =     has_h264 ? 0x20000 : 0x10000;
2619
    } else if (mov->mode == MODE_PSP)
2620
        ffio_wfourcc(pb, "MSNV");
2621
    else if (mov->mode == MODE_MP4)
2622
        ffio_wfourcc(pb, "isom");
2623
    else if (mov->mode == MODE_IPOD)
2624
        ffio_wfourcc(pb, has_video ? "M4V ":"M4A ");
2625 2626
    else if (mov->mode == MODE_ISM)
        ffio_wfourcc(pb, "isml");
2627 2628
    else if (mov->mode == MODE_F4V)
        ffio_wfourcc(pb, "f4v ");
2629
    else
2630
        ffio_wfourcc(pb, "qt  ");
2631

2632
    avio_wb32(pb, minor);
2633

2634
    if (mov->mode == MODE_MOV)
2635
        ffio_wfourcc(pb, "qt  ");
2636 2637 2638 2639
    else if (mov->mode == MODE_ISM) {
        ffio_wfourcc(pb, "piff");
        ffio_wfourcc(pb, "iso2");
    } else {
2640 2641
        ffio_wfourcc(pb, "isom");
        ffio_wfourcc(pb, "iso2");
2642
        if (has_h264)
2643
            ffio_wfourcc(pb, "avc1");
2644
    }
2645

2646
    if (mov->mode == MODE_3GP)
2647
        ffio_wfourcc(pb, has_h264 ? "3gp6":"3gp4");
Michael Niedermayer's avatar
Michael Niedermayer committed
2648
    else if (mov->mode & MODE_3G2)
2649
        ffio_wfourcc(pb, has_h264 ? "3g2b":"3g2a");
2650
    else if (mov->mode == MODE_PSP)
2651
        ffio_wfourcc(pb, "MSNV");
2652
    else if (mov->mode == MODE_MP4)
2653
        ffio_wfourcc(pb, "mp41");
2654
    return update_size(pb, pos);
2655 2656
}

2657
static void mov_write_uuidprof_tag(AVIOContext *pb, AVFormatContext *s)
2658
{
2659
    AVStream       *video_st    = s->streams[0];
2660 2661 2662
    AVCodecContext *video_codec = s->streams[0]->codec;
    AVCodecContext *audio_codec = s->streams[1]->codec;
    int audio_rate = audio_codec->sample_rate;
2663 2664
    // TODO: should be avg_frame_rate
    int frame_rate = ((video_st->time_base.den) * (0x10000)) / (video_st->time_base.num);
2665 2666
    int audio_kbitrate = audio_codec->bit_rate / 1000;
    int video_kbitrate = FFMIN(video_codec->bit_rate / 1000, 800 - audio_kbitrate);
2667

2668
    avio_wb32(pb, 0x94); /* size */
2669 2670
    ffio_wfourcc(pb, "uuid");
    ffio_wfourcc(pb, "PROF");
2671

2672 2673 2674
    avio_wb32(pb, 0x21d24fce); /* 96 bit UUID */
    avio_wb32(pb, 0xbb88695c);
    avio_wb32(pb, 0xfac9c740);
2675

2676 2677
    avio_wb32(pb, 0x0);  /* ? */
    avio_wb32(pb, 0x3);  /* 3 sections ? */
2678

2679
    avio_wb32(pb, 0x14); /* size */
2680
    ffio_wfourcc(pb, "FPRF");
2681 2682 2683
    avio_wb32(pb, 0x0);  /* ? */
    avio_wb32(pb, 0x0);  /* ? */
    avio_wb32(pb, 0x0);  /* ? */
2684

2685
    avio_wb32(pb, 0x2c);  /* size */
2686
    ffio_wfourcc(pb, "APRF"); /* audio */
2687 2688
    avio_wb32(pb, 0x0);
    avio_wb32(pb, 0x2);   /* TrackID */
2689
    ffio_wfourcc(pb, "mp4a");
2690 2691 2692 2693
    avio_wb32(pb, 0x20f);
    avio_wb32(pb, 0x0);
    avio_wb32(pb, audio_kbitrate);
    avio_wb32(pb, audio_kbitrate);
2694 2695
    avio_wb32(pb, audio_rate);
    avio_wb32(pb, audio_codec->channels);
2696 2697

    avio_wb32(pb, 0x34);  /* size */
2698
    ffio_wfourcc(pb, "VPRF");   /* video */
2699 2700
    avio_wb32(pb, 0x0);
    avio_wb32(pb, 0x1);    /* TrackID */
2701
    if (video_codec->codec_id == AV_CODEC_ID_H264) {
2702
        ffio_wfourcc(pb, "avc1");
2703 2704
        avio_wb16(pb, 0x014D);
        avio_wb16(pb, 0x0015);
2705
    } else {
2706
        ffio_wfourcc(pb, "mp4v");
2707 2708
        avio_wb16(pb, 0x0000);
        avio_wb16(pb, 0x0103);
2709
    }
2710 2711 2712
    avio_wb32(pb, 0x0);
    avio_wb32(pb, video_kbitrate);
    avio_wb32(pb, video_kbitrate);
2713 2714 2715 2716
    avio_wb32(pb, frame_rate);
    avio_wb32(pb, frame_rate);
    avio_wb16(pb, video_codec->width);
    avio_wb16(pb, video_codec->height);
2717
    avio_wb32(pb, 0x010001); /* ? */
2718 2719
}

2720 2721 2722 2723 2724 2725
static int mov_parse_mpeg2_frame(AVPacket *pkt, uint32_t *flags)
{
    uint32_t c = -1;
    int i, closed_gop = 0;

    for (i = 0; i < pkt->size - 4; i++) {
2726
        c = (c << 8) + pkt->data[i];
2727
        if (c == 0x1b8) { // gop
2728
            closed_gop = pkt->data[i + 4] >> 6 & 0x01;
2729
        } else if (c == 0x100) { // pic
2730
            int temp_ref = (pkt->data[i + 1] << 2) | (pkt->data[i + 2] >> 6);
2731 2732 2733 2734 2735 2736 2737 2738 2739 2740
            if (!temp_ref || closed_gop) // I picture is not reordered
                *flags = MOV_SYNC_SAMPLE;
            else
                *flags = MOV_PARTIAL_SYNC_SAMPLE;
            break;
        }
    }
    return 0;
}

2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797
static void mov_parse_vc1_frame(AVPacket *pkt, MOVTrack *trk, int fragment)
{
    const uint8_t *start, *next, *end = pkt->data + pkt->size;
    int seq = 0, entry = 0;
    int key = pkt->flags & AV_PKT_FLAG_KEY;
    start = find_next_marker(pkt->data, end);
    for (next = start; next < end; start = next) {
        next = find_next_marker(start + 4, end);
        switch (AV_RB32(start)) {
        case VC1_CODE_SEQHDR:
            seq = 1;
            break;
        case VC1_CODE_ENTRYPOINT:
            entry = 1;
            break;
        case VC1_CODE_SLICE:
            trk->vc1_info.slices = 1;
            break;
        }
    }
    if (!trk->entry && !fragment) {
        /* First packet in first fragment */
        trk->vc1_info.first_packet_seq   = seq;
        trk->vc1_info.first_packet_entry = entry;
    } else if ((seq && !trk->vc1_info.packet_seq) ||
               (entry && !trk->vc1_info.packet_entry)) {
        int i;
        for (i = 0; i < trk->entry; i++)
            trk->cluster[i].flags &= ~MOV_SYNC_SAMPLE;
        trk->has_keyframes = 0;
        if (seq)
            trk->vc1_info.packet_seq = 1;
        if (entry)
            trk->vc1_info.packet_entry = 1;
        if (!fragment) {
            /* First fragment */
            if ((!seq   || trk->vc1_info.first_packet_seq) &&
                (!entry || trk->vc1_info.first_packet_entry)) {
                /* First packet had the same headers as this one, readd the
                 * sync sample flag. */
                trk->cluster[0].flags |= MOV_SYNC_SAMPLE;
                trk->has_keyframes = 1;
            }
        }
    }
    if (trk->vc1_info.packet_seq && trk->vc1_info.packet_entry)
        key = seq && entry;
    else if (trk->vc1_info.packet_seq)
        key = seq;
    else if (trk->vc1_info.packet_entry)
        key = entry;
    if (key) {
        trk->cluster[trk->entry].flags |= MOV_SYNC_SAMPLE;
        trk->has_keyframes++;
    }
}

2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808
static int mov_flush_fragment(AVFormatContext *s)
{
    MOVMuxContext *mov = s->priv_data;
    int i, first_track = -1;
    int64_t mdat_size = 0;

    if (!(mov->flags & FF_MOV_FLAG_FRAGMENT))
        return 0;

    if (!(mov->flags & FF_MOV_FLAG_EMPTY_MOOV) && mov->fragments == 0) {
        int64_t pos = avio_tell(s->pb);
2809 2810 2811 2812
        int ret;
        AVIOContext *moov_buf;
        uint8_t *buf;
        int buf_size;
2813 2814 2815 2816 2817 2818 2819

        for (i = 0; i < mov->nb_streams; i++)
            if (!mov->tracks[i].entry)
                break;
        /* Don't write the initial moov unless all tracks have data */
        if (i < mov->nb_streams)
            return 0;
2820

2821
        if ((ret = ffio_open_null_buf(&moov_buf)) < 0)
2822 2823
            return ret;
        mov_write_moov_tag(moov_buf, mov, s);
2824
        buf_size = ffio_close_null_buf(moov_buf);
2825 2826 2827
        for (i = 0; i < mov->nb_streams; i++)
            mov->tracks[i].data_offset = pos + buf_size + 8;

2828
        mov_write_moov_tag(s->pb, mov, s);
2829 2830 2831 2832 2833 2834 2835 2836

        buf_size = avio_close_dyn_buf(mov->mdat_buf, &buf);
        mov->mdat_buf = NULL;
        avio_wb32(s->pb, buf_size + 8);
        ffio_wfourcc(s->pb, "mdat");
        avio_write(s->pb, buf, buf_size);
        av_free(buf);

2837 2838 2839 2840 2841
        mov->fragments++;
        mov->mdat_size = 0;
        for (i = 0; i < mov->nb_streams; i++) {
            if (mov->tracks[i].entry)
                mov->tracks[i].frag_start += mov->tracks[i].start_dts +
2842
                                             mov->tracks[i].track_duration -
2843 2844 2845
                                             mov->tracks[i].cluster[0].dts;
            mov->tracks[i].entry = 0;
        }
2846
        avio_flush(s->pb);
2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872
        return 0;
    }

    for (i = 0; i < mov->nb_streams; i++) {
        MOVTrack *track = &mov->tracks[i];
        if (mov->flags & FF_MOV_FLAG_SEPARATE_MOOF)
            track->data_offset = 0;
        else
            track->data_offset = mdat_size;
        if (!track->mdat_buf)
            continue;
        mdat_size += avio_tell(track->mdat_buf);
        if (first_track < 0)
            first_track = i;
    }

    if (!mdat_size)
        return 0;

    for (i = 0; i < mov->nb_streams; i++) {
        MOVTrack *track = &mov->tracks[i];
        int buf_size, write_moof = 1, moof_tracks = -1;
        uint8_t *buf;
        int64_t duration = 0;

        if (track->entry)
2873
            duration = track->start_dts + track->track_duration -
2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885
                       track->cluster[0].dts;
        if (mov->flags & FF_MOV_FLAG_SEPARATE_MOOF) {
            if (!track->mdat_buf)
                continue;
            mdat_size = avio_tell(track->mdat_buf);
            moof_tracks = i;
        } else {
            write_moof = i == first_track;
        }

        if (write_moof) {
            MOVFragmentInfo *info;
2886
            avio_flush(s->pb);
2887
            track->nb_frag_info++;
2888 2889 2890 2891 2892 2893 2894 2895
            if (track->nb_frag_info >= track->frag_info_capacity) {
                unsigned new_capacity = track->nb_frag_info + MOV_FRAG_INFO_ALLOC_INCREMENT;
                if (av_reallocp_array(&track->frag_info,
                                      new_capacity,
                                      sizeof(*track->frag_info)))
                    return AVERROR(ENOMEM);
                track->frag_info_capacity = new_capacity;
            }
2896 2897 2898
            info = &track->frag_info[track->nb_frag_info - 1];
            info->offset   = avio_tell(s->pb);
            info->time     = mov->tracks[i].frag_start;
2899 2900
            info->duration = duration;
            mov_write_tfrf_tags(s->pb, mov, track);
2901 2902

            mov_write_moof_tag(s->pb, mov, moof_tracks);
2903
            info->tfrf_offset = track->tfrf_offset;
2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923
            mov->fragments++;

            avio_wb32(s->pb, mdat_size + 8);
            ffio_wfourcc(s->pb, "mdat");
        }

        if (track->entry)
            track->frag_start += duration;
        track->entry = 0;
        if (!track->mdat_buf)
            continue;
        buf_size = avio_close_dyn_buf(track->mdat_buf, &buf);
        track->mdat_buf = NULL;

        avio_write(s->pb, buf, buf_size);
        av_free(buf);
    }

    mov->mdat_size = 0;

2924
    avio_flush(s->pb);
2925 2926 2927
    return 0;
}

2928
int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
2929
{
2930
    MOVMuxContext *mov = s->priv_data;
2931
    AVIOContext *pb = s->pb;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2932 2933
    MOVTrack *trk = &mov->tracks[pkt->stream_index];
    AVCodecContext *enc = trk->enc;
2934
    unsigned int samples_in_chunk = 0;
2935
    int size = pkt->size;
2936
    uint8_t *reformatted_data = NULL;
2937

2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951
    if (mov->flags & FF_MOV_FLAG_FRAGMENT) {
        int ret;
        if (mov->fragments > 0) {
            if (!trk->mdat_buf) {
                if ((ret = avio_open_dyn_buf(&trk->mdat_buf)) < 0)
                    return ret;
            }
            pb = trk->mdat_buf;
        } else {
            if (!mov->mdat_buf) {
                if ((ret = avio_open_dyn_buf(&mov->mdat_buf)) < 0)
                    return ret;
            }
            pb = mov->mdat_buf;
2952 2953 2954
        }
    }

2955
    if (enc->codec_id == AV_CODEC_ID_AMR_NB) {
2956 2957
        /* We must find out how many AMR blocks there are in one packet */
        static uint16_t packed_size[16] =
2958
            {13, 14, 16, 18, 20, 21, 27, 32, 6, 0, 0, 0, 0, 0, 0, 1};
2959 2960
        int len = 0;

2961
        while (len < size && samples_in_chunk < 100) {
2962
            len += packed_size[(pkt->data[len] >> 3) & 0x0F];
2963
            samples_in_chunk++;
2964
        }
2965
        if (samples_in_chunk > 1) {
Ramiro Polla's avatar
Ramiro Polla committed
2966
            av_log(s, AV_LOG_ERROR, "fatal error, input is not a single packet, implement a AVParser for it\n");
2967 2968
            return -1;
        }
2969 2970
    } else if (trk->sample_size)
        samples_in_chunk = size / trk->sample_size;
2971
    else
2972
        samples_in_chunk = 1;
2973

2974
    /* copy extradata if it exists */
2975
    if (trk->vos_len == 0 && enc->extradata_size > 0) {
2976
        trk->vos_len  = enc->extradata_size;
2977 2978
        trk->vos_data = av_malloc(trk->vos_len);
        memcpy(trk->vos_data, enc->extradata, trk->vos_len);
2979 2980
    }

2981
    if (enc->codec_id == AV_CODEC_ID_H264 && trk->vos_len > 0 && *(uint8_t *)trk->vos_data != 1) {
2982 2983
        /* from x264 or from bytestream h264 */
        /* nal reformating needed */
2984 2985 2986 2987 2988 2989 2990
        if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams) {
            ff_avc_parse_nal_units_buf(pkt->data, &reformatted_data,
                                       &size);
            avio_write(pb, reformatted_data, size);
        } else {
            size = ff_avc_parse_nal_units(pb, pkt->data, pkt->size);
        }
2991 2992 2993 2994 2995 2996 2997 2998 2999
    } else if (enc->codec_id == AV_CODEC_ID_HEVC && trk->vos_len > 6 &&
               (AV_RB24(trk->vos_data) == 1 || AV_RB32(trk->vos_data) == 1)) {
        /* extradata is Annex B, assume the bitstream is too and convert it */
        if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams) {
            ff_hevc_annexb2mp4_buf(pkt->data, &reformatted_data, &size, 0, NULL);
            avio_write(pb, reformatted_data, size);
        } else {
            size = ff_hevc_annexb2mp4(pb, pkt->data, pkt->size, 0, NULL);
        }
3000
    } else {
3001
        avio_write(pb, pkt->data, size);
3002 3003
    }

3004 3005
    if ((enc->codec_id == AV_CODEC_ID_DNXHD ||
         enc->codec_id == AV_CODEC_ID_AC3) && !trk->vos_len) {
3006
        /* copy frame to create needed atoms */
3007
        trk->vos_len  = size;
3008 3009
        trk->vos_data = av_malloc(size);
        if (!trk->vos_data)
3010
            return AVERROR(ENOMEM);
3011
        memcpy(trk->vos_data, pkt->data, size);
3012 3013
    }

3014
    if (trk->entry >= trk->cluster_capacity) {
3015
        unsigned new_capacity = 2 * (trk->entry + MOV_INDEX_CLUSTER_SIZE);
3016 3017 3018 3019
        if (av_reallocp_array(&trk->cluster, new_capacity,
                              sizeof(*trk->cluster)))
            return AVERROR(ENOMEM);
        trk->cluster_capacity = new_capacity;
3020 3021
    }

3022
    trk->cluster[trk->entry].pos              = avio_tell(pb) - size;
3023
    trk->cluster[trk->entry].samples_in_chunk = samples_in_chunk;
3024 3025 3026
    trk->cluster[trk->entry].size             = size;
    trk->cluster[trk->entry].entries          = samples_in_chunk;
    trk->cluster[trk->entry].dts              = pkt->dts;
3027 3028
    if (!trk->entry && trk->start_dts != AV_NOPTS_VALUE) {
        /* First packet of a new fragment. We already wrote the duration
3029
         * of the last packet of the previous fragment based on track_duration,
3030 3031
         * which might not exactly match our dts. Therefore adjust the dts
         * of this packet to be what the previous packets duration implies. */
3032
        trk->cluster[trk->entry].dts = trk->start_dts + trk->track_duration;
3033
    }
3034 3035
    if (trk->start_dts == AV_NOPTS_VALUE)
        trk->start_dts = pkt->dts;
3036
    trk->track_duration = pkt->dts - trk->start_dts + pkt->duration;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
3037

3038 3039 3040 3041
    if (pkt->pts == AV_NOPTS_VALUE) {
        av_log(s, AV_LOG_WARNING, "pts has no value\n");
        pkt->pts = pkt->dts;
    }
Baptiste Coudurier's avatar
Baptiste Coudurier committed
3042
    if (pkt->dts != pkt->pts)
3043
        trk->flags |= MOV_TRACK_CTTS;
3044
    trk->cluster[trk->entry].cts   = pkt->pts - pkt->dts;
3045
    trk->cluster[trk->entry].flags = 0;
3046
    if (enc->codec_id == AV_CODEC_ID_VC1) {
3047 3048
        mov_parse_vc1_frame(pkt, trk, mov->fragments);
    } else if (pkt->flags & AV_PKT_FLAG_KEY) {
3049
        if (mov->mode == MODE_MOV && enc->codec_id == AV_CODEC_ID_MPEG2VIDEO &&
3050
            trk->entry > 0) { // force sync sample for the first key frame
3051 3052 3053 3054 3055 3056 3057
            mov_parse_mpeg2_frame(pkt, &trk->cluster[trk->entry].flags);
            if (trk->cluster[trk->entry].flags & MOV_PARTIAL_SYNC_SAMPLE)
                trk->flags |= MOV_TRACK_STPS;
        } else {
            trk->cluster[trk->entry].flags = MOV_SYNC_SAMPLE;
        }
        if (trk->cluster[trk->entry].flags & MOV_SYNC_SAMPLE)
3058
            trk->has_keyframes++;
3059
    }
3060
    trk->entry++;
3061
    trk->sample_count += samples_in_chunk;
3062
    mov->mdat_size    += size;
3063

3064
    if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams)
3065 3066 3067
        ff_mov_add_hinted_packet(s, pkt, trk->hint_track, trk->entry,
                                 reformatted_data, size);
    av_free(reformatted_data);
3068 3069 3070
    return 0;
}

3071
static int mov_write_packet(AVFormatContext *s, AVPacket *pkt)
3072 3073 3074 3075 3076
{
    if (!pkt) {
        mov_flush_fragment(s);
        return 1;
    } else {
3077 3078 3079 3080 3081 3082
        MOVMuxContext *mov = s->priv_data;
        MOVTrack *trk = &mov->tracks[pkt->stream_index];
        AVCodecContext *enc = trk->enc;
        int64_t frag_duration = 0;
        int size = pkt->size;

3083 3084
        if (!pkt->size)
            return 0;             /* Discard 0 sized packets */
3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100

        if (trk->entry)
            frag_duration = av_rescale_q(pkt->dts - trk->cluster[0].dts,
                                         s->streams[pkt->stream_index]->time_base,
                                         AV_TIME_BASE_Q);
        if ((mov->max_fragment_duration &&
             frag_duration >= mov->max_fragment_duration) ||
             (mov->max_fragment_size && mov->mdat_size + size >= mov->max_fragment_size) ||
             (mov->flags & FF_MOV_FLAG_FRAG_KEYFRAME &&
              enc->codec_type == AVMEDIA_TYPE_VIDEO &&
              trk->entry && pkt->flags & AV_PKT_FLAG_KEY)) {
            if (frag_duration >= mov->min_fragment_duration)
                mov_flush_fragment(s);
        }

        return ff_mov_write_packet(s, pkt);
3101 3102 3103
    }
}

3104 3105
// QuickTime chapters involve an additional text track with the chapter names
// as samples, and a tref pointing from the other tracks to the chapter one.
3106
static int mov_create_chapter_track(AVFormatContext *s, int tracknum)
3107 3108 3109 3110 3111
{
    MOVMuxContext *mov = s->priv_data;
    MOVTrack *track = &mov->tracks[tracknum];
    AVPacket pkt = { .stream_index = tracknum, .flags = AV_PKT_FLAG_KEY };
    int i, len;
3112 3113
    // These properties are required to make QT recognize the chapter track
    uint8_t chapter_properties[43] = { 0, 0, 0, 0, 0, 0, 0, 1, };
3114 3115 3116 3117

    track->mode = mov->mode;
    track->tag = MKTAG('t','e','x','t');
    track->timescale = MOV_TIMESCALE;
3118
    track->enc = avcodec_alloc_context3(NULL);
3119 3120
    if (!track->enc)
        return AVERROR(ENOMEM);
3121
    track->enc->codec_type = AVMEDIA_TYPE_SUBTITLE;
3122 3123 3124 3125 3126
    track->enc->extradata = av_malloc(sizeof(chapter_properties));
    if (track->enc->extradata == NULL)
        return AVERROR(ENOMEM);
    track->enc->extradata_size = sizeof(chapter_properties);
    memcpy(track->enc->extradata, chapter_properties, sizeof(chapter_properties));
3127 3128 3129

    for (i = 0; i < s->nb_chapters; i++) {
        AVChapter *c = s->chapters[i];
3130
        AVDictionaryEntry *t;
3131 3132 3133 3134 3135

        int64_t end = av_rescale_q(c->end, c->time_base, (AVRational){1,MOV_TIMESCALE});
        pkt.pts = pkt.dts = av_rescale_q(c->start, c->time_base, (AVRational){1,MOV_TIMESCALE});
        pkt.duration = end - pkt.dts;

3136
        if ((t = av_dict_get(c->metadata, "title", NULL, 0))) {
3137 3138
            len      = strlen(t->value);
            pkt.size = len + 2;
3139
            pkt.data = av_malloc(pkt.size);
3140 3141
            if (!pkt.data)
                return AVERROR(ENOMEM);
3142
            AV_WB16(pkt.data, len);
3143
            memcpy(pkt.data + 2, t->value, len);
3144
            ff_mov_write_packet(s, &pkt);
3145 3146 3147
            av_freep(&pkt.data);
        }
    }
3148 3149

    return 0;
3150 3151
}

3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201
/*
 * st->disposition controls the "enabled" flag in the tkhd tag.
 * QuickTime will not play a track if it is not enabled.  So make sure
 * that one track of each type (audio, video, subtitle) is enabled.
 *
 * Subtitles are special.  For audio and video, setting "enabled" also
 * makes the track "default" (i.e. it is rendered when played). For
 * subtitles, an "enabled" subtitle is not rendered by default, but
 * if no subtitle is enabled, the subtitle menu in QuickTime will be
 * empty!
 */
static void enable_tracks(AVFormatContext *s)
{
    MOVMuxContext *mov = s->priv_data;
    int i;
    uint8_t enabled[AVMEDIA_TYPE_NB];
    int first[AVMEDIA_TYPE_NB];

    for (i = 0; i < AVMEDIA_TYPE_NB; i++) {
        enabled[i] = 0;
        first[i] = -1;
    }

    for (i = 0; i < s->nb_streams; i++) {
        AVStream *st = s->streams[i];

        if (st->codec->codec_type <= AVMEDIA_TYPE_UNKNOWN ||
            st->codec->codec_type >= AVMEDIA_TYPE_NB)
            continue;

        if (first[st->codec->codec_type] < 0)
            first[st->codec->codec_type] = i;
        if (st->disposition & AV_DISPOSITION_DEFAULT) {
            mov->tracks[i].flags |= MOV_TRACK_ENABLED;
            enabled[st->codec->codec_type] = 1;
        }
    }

    for (i = 0; i < AVMEDIA_TYPE_NB; i++) {
        switch (i) {
        case AVMEDIA_TYPE_VIDEO:
        case AVMEDIA_TYPE_AUDIO:
        case AVMEDIA_TYPE_SUBTITLE:
            if (!enabled[i] && first[i] >= 0)
                mov->tracks[first[i]].flags |= MOV_TRACK_ENABLED;
            break;
        }
    }
}

3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225
static void mov_free(AVFormatContext *s)
{
    MOVMuxContext *mov = s->priv_data;
    int i;

    if (mov->chapter_track) {
        if (mov->tracks[mov->chapter_track].enc)
            av_free(mov->tracks[mov->chapter_track].enc->extradata);
        av_freep(&mov->tracks[mov->chapter_track].enc);
    }

    for (i = 0; i < mov->nb_streams; i++) {
        if (mov->tracks[i].tag == MKTAG('r','t','p',' '))
            ff_mov_close_hinting(&mov->tracks[i]);
        av_freep(&mov->tracks[i].cluster);
        av_freep(&mov->tracks[i].frag_info);

        if (mov->tracks[i].vos_len)
            av_free(mov->tracks[i].vos_data);
    }

    av_freep(&mov->tracks);
}

3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253
static uint32_t rgb_to_yuv(uint32_t rgb)
{
    uint8_t r, g, b;
    int y, cb, cr;

    r = (rgb >> 16) & 0xFF;
    g = (rgb >>  8) & 0xFF;
    b = (rgb      ) & 0xFF;

    y  = av_clip_uint8( 16. +  0.257 * r + 0.504 * g + 0.098 * b);
    cb = av_clip_uint8(128. -  0.148 * r - 0.291 * g + 0.439 * b);
    cr = av_clip_uint8(128. +  0.439 * r - 0.368 * g - 0.071 * b);

    return (y << 16) | (cr << 8) | cb;
}

static int mov_create_dvd_sub_decoder_specific_info(MOVTrack *track,
                                                    AVStream *st)
{
    int i, width = 720, height = 480;
    int have_palette = 0, have_size = 0;
    uint32_t palette[16];
    char *cur = st->codec->extradata;

    while (cur && *cur) {
        if (strncmp("palette:", cur, 8) == 0) {
            int i, count;
            count = sscanf(cur + 8,
3254 3255 3256 3257
                "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32", "
                "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32", "
                "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32", "
                "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32"",
3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290
                &palette[ 0], &palette[ 1], &palette[ 2], &palette[ 3],
                &palette[ 4], &palette[ 5], &palette[ 6], &palette[ 7],
                &palette[ 8], &palette[ 9], &palette[10], &palette[11],
                &palette[12], &palette[13], &palette[14], &palette[15]);

            for (i = 0; i < count; i++) {
                palette[i] = rgb_to_yuv(palette[i]);
            }
            have_palette = 1;
        } else if (!strncmp("size:", cur, 5)) {
            sscanf(cur + 5, "%dx%d", &width, &height);
            have_size = 1;
        }
        if (have_palette && have_size)
            break;
        cur += strcspn(cur, "\n\r");
        cur += strspn(cur, "\n\r");
    }
    if (have_palette) {
        track->vos_data = av_malloc(16*4);
        if (!track->vos_data)
            return AVERROR(ENOMEM);
        for (i = 0; i < 16; i++) {
            AV_WB32(track->vos_data + i * 4, palette[i]);
        }
        track->vos_len = 16 * 4;
    }
    st->codec->width = width;
    st->codec->height = track->height = height;

    return 0;
}

3291 3292
static int mov_write_header(AVFormatContext *s)
{
3293
    AVIOContext *pb = s->pb;
3294
    MOVMuxContext *mov = s->priv_data;
3295
    AVDictionaryEntry *t;
3296
    int i, hint_track = 0;
3297

3298 3299 3300 3301 3302 3303 3304 3305 3306 3307
    /* Default mode == MP4 */
    mov->mode = MODE_MP4;

    if (s->oformat != NULL) {
        if (!strcmp("3gp", s->oformat->name)) mov->mode = MODE_3GP;
        else if (!strcmp("3g2", s->oformat->name)) mov->mode = MODE_3GP|MODE_3G2;
        else if (!strcmp("mov", s->oformat->name)) mov->mode = MODE_MOV;
        else if (!strcmp("psp", s->oformat->name)) mov->mode = MODE_PSP;
        else if (!strcmp("ipod",s->oformat->name)) mov->mode = MODE_IPOD;
        else if (!strcmp("ismv",s->oformat->name)) mov->mode = MODE_ISM;
3308
        else if (!strcmp("f4v", s->oformat->name)) mov->mode = MODE_F4V;
3309 3310
    }

3311 3312 3313 3314 3315 3316 3317 3318
    /* Set the FRAGMENT flag if any of the fragmentation methods are
     * enabled. */
    if (mov->max_fragment_duration || mov->max_fragment_size ||
        mov->flags & (FF_MOV_FLAG_EMPTY_MOOV |
                      FF_MOV_FLAG_FRAG_KEYFRAME |
                      FF_MOV_FLAG_FRAG_CUSTOM))
        mov->flags |= FF_MOV_FLAG_FRAGMENT;

3319 3320 3321 3322 3323
    /* Set other implicit flags immediately */
    if (mov->mode == MODE_ISM)
        mov->flags |= FF_MOV_FLAG_EMPTY_MOOV | FF_MOV_FLAG_SEPARATE_MOOF |
                      FF_MOV_FLAG_FRAGMENT;

3324 3325 3326
    /* faststart: moov at the beginning of the file, if supported */
    if (mov->flags & FF_MOV_FLAG_FASTSTART) {
        if ((mov->flags & FF_MOV_FLAG_FRAGMENT) ||
3327 3328 3329
            (s->flags & AVFMT_FLAG_CUSTOM_IO)) {
            av_log(s, AV_LOG_WARNING, "The faststart flag is incompatible "
                   "with fragmentation and custom IO, disabling faststart\n");
3330
            mov->flags &= ~FF_MOV_FLAG_FASTSTART;
3331
        }
3332 3333
    }

3334
    /* Non-seekable output is ok if using fragmentation. If ism_lookahead
3335 3336
     * is enabled, we don't support non-seekable output at all. */
    if (!s->pb->seekable &&
3337
        (!(mov->flags & FF_MOV_FLAG_FRAGMENT) || mov->ism_lookahead)) {
3338
        av_log(s, AV_LOG_ERROR, "muxer does not support non seekable output\n");
3339
        return AVERROR(EINVAL);
3340 3341 3342
    }


3343 3344 3345 3346
    mov_write_ftyp_tag(pb,s);
    if (mov->mode == MODE_PSP) {
        if (s->nb_streams != 2) {
            av_log(s, AV_LOG_ERROR, "PSP mode need one video and one audio stream\n");
3347
            return AVERROR(EINVAL);
3348
        }
3349
        mov_write_uuidprof_tag(pb, s);
3350 3351
    }

3352
    mov->nb_streams = s->nb_streams;
3353
    if (mov->mode & (MODE_MP4|MODE_MOV|MODE_IPOD) && s->nb_chapters)
3354 3355
        mov->chapter_track = mov->nb_streams++;

3356
    if (mov->flags & FF_MOV_FLAG_RTP_HINT) {
3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367
        /* Add hint tracks for each audio and video stream */
        hint_track = mov->nb_streams;
        for (i = 0; i < s->nb_streams; i++) {
            AVStream *st = s->streams[i];
            if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO ||
                st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
                mov->nb_streams++;
            }
        }
    }

3368 3369 3370
    // Reserve an extra stream for chapters for the case where chapters
    // are written in the trailer
    mov->tracks = av_mallocz((mov->nb_streams + 1) * sizeof(*mov->tracks));
3371 3372 3373
    if (!mov->tracks)
        return AVERROR(ENOMEM);

3374
    for (i = 0; i < s->nb_streams; i++) {
3375 3376
        AVStream *st= s->streams[i];
        MOVTrack *track= &mov->tracks[i];
3377
        AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL,0);
3378

3379
        track->st  = st;
3380 3381 3382 3383 3384
        track->enc = st->codec;
        track->language = ff_mov_iso639_to_lang(lang?lang->value:"und", mov->mode!=MODE_MOV);
        if (track->language < 0)
            track->language = 0;
        track->mode = mov->mode;
3385
        track->tag  = mov_find_codec_tag(s, track);
3386 3387 3388 3389 3390
        if (!track->tag) {
            av_log(s, AV_LOG_ERROR, "track %d: could not find tag, "
                   "codec not currently supported in container\n", i);
            goto error;
        }
3391 3392 3393
        /* If hinting of this track is enabled by a later hint track,
         * this is updated. */
        track->hint_track = -1;
3394 3395
        track->start_dts  = AV_NOPTS_VALUE;
        if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
3396 3397 3398 3399 3400 3401 3402
            if (track->tag == MKTAG('m','x','3','p') || track->tag == MKTAG('m','x','3','n') ||
                track->tag == MKTAG('m','x','4','p') || track->tag == MKTAG('m','x','4','n') ||
                track->tag == MKTAG('m','x','5','p') || track->tag == MKTAG('m','x','5','n')) {
                if (st->codec->width != 720 || (st->codec->height != 608 && st->codec->height != 512)) {
                    av_log(s, AV_LOG_ERROR, "D-10/IMX must use 720x608 or 720x512 video resolution\n");
                    goto error;
                }
3403
                track->height = track->tag >> 24 == 'n' ? 486 : 576;
3404
            }
3405
            track->timescale = st->time_base.den;
3406 3407 3408 3409 3410
            if (track->mode == MODE_MOV && track->timescale > 100000)
                av_log(s, AV_LOG_WARNING,
                       "WARNING codec timebase is very high. If duration is too long,\n"
                       "file may not be playable by quicktime. Specify a shorter timebase\n"
                       "or choose different container.\n");
3411
        } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
3412
            track->timescale = st->codec->sample_rate;
3413
            /* set sample_size for PCM and ADPCM */
3414
            if (av_get_bits_per_sample(st->codec->codec_id) ||
3415
                st->codec->codec_id == AV_CODEC_ID_ILBC) {
3416
                if (!st->codec->block_align) {
3417
                    av_log(s, AV_LOG_ERROR, "track %d: codec block align is not set\n", i);
3418 3419
                    goto error;
                }
3420
                track->sample_size = st->codec->block_align;
3421 3422 3423
            }
            /* set audio_vbr for compressed audio */
            if (av_get_bits_per_sample(st->codec->codec_id) < 8) {
3424 3425
                track->audio_vbr = 1;
            }
3426
            if (track->mode != MODE_MOV &&
3427
                track->enc->codec_id == AV_CODEC_ID_MP3 && track->timescale < 16000) {
3428 3429 3430
                av_log(s, AV_LOG_ERROR, "track %d: muxing mp3 at %dhz is not supported\n",
                       i, track->enc->sample_rate);
                goto error;
3431
            }
3432
        } else if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
3433
            track->timescale = st->time_base.den;
3434
        } else if (st->codec->codec_type == AVMEDIA_TYPE_DATA) {
3435
            track->timescale = st->time_base.den;
3436 3437 3438
        }
        if (!track->height)
            track->height = st->codec->height;
3439 3440 3441 3442
        /* The ism specific timescale isn't mandatory, but is assumed by
         * some tools, such as mp4split. */
        if (mov->mode == MODE_ISM)
            track->timescale = 10000000;
3443

3444
        avpriv_set_pts_info(st, 64, 1, track->timescale);
3445 3446 3447

        /* copy extradata if it exists */
        if (st->codec->extradata_size) {
3448 3449 3450 3451 3452 3453 3454
            if (st->codec->codec_id == AV_CODEC_ID_DVD_SUBTITLE)
                mov_create_dvd_sub_decoder_specific_info(track, st);
            else {
                track->vos_len  = st->codec->extradata_size;
                track->vos_data = av_malloc(track->vos_len);
                memcpy(track->vos_data, st->codec->extradata, track->vos_len);
            }
3455
        }
3456 3457
    }

3458 3459
    enable_tracks(s);

3460
    if (mov->flags & FF_MOV_FLAG_FRAGMENT) {
3461 3462 3463 3464
        /* If no fragmentation options have been set, set a default. */
        if (!(mov->flags & (FF_MOV_FLAG_FRAG_KEYFRAME |
                            FF_MOV_FLAG_FRAG_CUSTOM)) &&
            !mov->max_fragment_duration && !mov->max_fragment_size)
3465
            mov->flags |= FF_MOV_FLAG_FRAG_KEYFRAME;
3466
    } else {
3467 3468
        if (mov->flags & FF_MOV_FLAG_FASTSTART)
            mov->reserved_moov_pos = avio_tell(pb);
3469
        mov_write_mdat_tag(pb, mov);
3470
    }
3471

3472 3473
    if (t = av_dict_get(s->metadata, "creation_time", NULL, 0))
        mov->time = ff_iso8601_to_unix_time(t->value);
3474 3475
    if (mov->time)
        mov->time += 0x7C25B080; // 1970 based -> 1904 based
3476 3477

    if (mov->chapter_track)
3478 3479
        if (mov_create_chapter_track(s, mov->chapter_track) < 0)
            goto error;
3480

3481
    if (mov->flags & FF_MOV_FLAG_RTP_HINT) {
3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492
        /* Initialize the hint tracks for each audio and video stream */
        for (i = 0; i < s->nb_streams; i++) {
            AVStream *st = s->streams[i];
            if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO ||
                st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
                ff_mov_init_hinting(s, hint_track, i);
                hint_track++;
            }
        }
    }

3493
    avio_flush(pb);
3494

3495 3496 3497
    if (mov->flags & FF_MOV_FLAG_ISML)
        mov_write_isml_manifest(pb, mov);

3498 3499 3500 3501 3502
    if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV) {
        mov_write_moov_tag(pb, mov, s);
        mov->fragments++;
    }

3503 3504
    return 0;
 error:
3505
    mov_free(s);
3506 3507 3508
    return -1;
}

3509 3510 3511 3512 3513 3514
static int get_moov_size(AVFormatContext *s)
{
    int ret;
    AVIOContext *moov_buf;
    MOVMuxContext *mov = s->priv_data;

3515
    if ((ret = ffio_open_null_buf(&moov_buf)) < 0)
3516 3517
        return ret;
    mov_write_moov_tag(moov_buf, mov, s);
3518
    return ffio_close_null_buf(moov_buf);
3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614
}

/*
 * This function gets the moov size if moved to the top of the file: the chunk
 * offset table can switch between stco (32-bit entries) to co64 (64-bit
 * entries) when the moov is moved to the beginning, so the size of the moov
 * would change. It also updates the chunk offset tables.
 */
static int compute_moov_size(AVFormatContext *s)
{
    int i, moov_size, moov_size2;
    MOVMuxContext *mov = s->priv_data;

    moov_size = get_moov_size(s);
    if (moov_size < 0)
        return moov_size;

    for (i = 0; i < mov->nb_streams; i++)
        mov->tracks[i].data_offset += moov_size;

    moov_size2 = get_moov_size(s);
    if (moov_size2 < 0)
        return moov_size2;

    /* if the size changed, we just switched from stco to co64 and need to
     * update the offsets */
    if (moov_size2 != moov_size)
        for (i = 0; i < mov->nb_streams; i++)
            mov->tracks[i].data_offset += moov_size2 - moov_size;

    return moov_size2;
}

static int shift_data(AVFormatContext *s)
{
    int ret = 0, moov_size;
    MOVMuxContext *mov = s->priv_data;
    int64_t pos, pos_end = avio_tell(s->pb);
    uint8_t *buf, *read_buf[2];
    int read_buf_id = 0;
    int read_size[2];
    AVIOContext *read_pb;

    moov_size = compute_moov_size(s);
    if (moov_size < 0)
        return moov_size;

    buf = av_malloc(moov_size * 2);
    if (!buf)
        return AVERROR(ENOMEM);
    read_buf[0] = buf;
    read_buf[1] = buf + moov_size;

    /* Shift the data: the AVIO context of the output can only be used for
     * writing, so we re-open the same output, but for reading. It also avoids
     * a read/seek/write/seek back and forth. */
    avio_flush(s->pb);
    ret = avio_open(&read_pb, s->filename, AVIO_FLAG_READ);
    if (ret < 0) {
        av_log(s, AV_LOG_ERROR, "Unable to re-open %s output file for "
               "the second pass (faststart)\n", s->filename);
        goto end;
    }

    /* mark the end of the shift to up to the last data we wrote, and get ready
     * for writing */
    pos_end = avio_tell(s->pb);
    avio_seek(s->pb, mov->reserved_moov_pos + moov_size, SEEK_SET);

    /* start reading at where the new moov will be placed */
    avio_seek(read_pb, mov->reserved_moov_pos, SEEK_SET);
    pos = avio_tell(read_pb);

#define READ_BLOCK do {                                                             \
    read_size[read_buf_id] = avio_read(read_pb, read_buf[read_buf_id], moov_size);  \
    read_buf_id ^= 1;                                                               \
} while (0)

    /* shift data by chunk of at most moov_size */
    READ_BLOCK;
    do {
        int n;
        READ_BLOCK;
        n = read_size[read_buf_id];
        if (n <= 0)
            break;
        avio_write(s->pb, read_buf[read_buf_id], n);
        pos += n;
    } while (pos < pos_end);
    avio_close(read_pb);

end:
    av_free(buf);
    return ret;
}

3615 3616
static int mov_write_trailer(AVFormatContext *s)
{
3617
    MOVMuxContext *mov = s->priv_data;
3618
    AVIOContext *pb = s->pb;
3619
    int res = 0;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
3620
    int i;
3621 3622 3623 3624 3625 3626 3627 3628
    int64_t moov_pos;

    // If there were no chapters when the header was written, but there
    // are chapters now, write them in the trailer.  This only works
    // when we are not doing fragments.
    if (!mov->chapter_track && !(mov->flags & FF_MOV_FLAG_FRAGMENT)) {
        if (mov->mode & (MODE_MP4|MODE_MOV|MODE_IPOD) && s->nb_chapters) {
            mov->chapter_track = mov->nb_streams++;
3629 3630
            if ((res = mov_create_chapter_track(s, mov->chapter_track)) < 0)
                goto error;
3631 3632
        }
    }
3633

3634
    if (!(mov->flags & FF_MOV_FLAG_FRAGMENT)) {
3635 3636
        moov_pos = avio_tell(pb);

3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650
        /* Write size of mdat tag */
        if (mov->mdat_size + 8 <= UINT32_MAX) {
            avio_seek(pb, mov->mdat_pos, SEEK_SET);
            avio_wb32(pb, mov->mdat_size + 8);
        } else {
            /* overwrite 'wide' placeholder atom */
            avio_seek(pb, mov->mdat_pos - 8, SEEK_SET);
            /* special value: real atom size will be 64 bit value after
             * tag field */
            avio_wb32(pb, 1);
            ffio_wfourcc(pb, "mdat");
            avio_wb64(pb, mov->mdat_size + 16);
        }
        avio_seek(pb, moov_pos, SEEK_SET);
3651

3652 3653 3654 3655 3656 3657 3658 3659 3660 3661
        if (mov->flags & FF_MOV_FLAG_FASTSTART) {
            av_log(s, AV_LOG_INFO, "Starting second pass: moving the moov atom to the beginning of the file\n");
            res = shift_data(s);
            if (res == 0) {
                avio_seek(s->pb, mov->reserved_moov_pos, SEEK_SET);
                mov_write_moov_tag(pb, mov, s);
            }
        } else {
            mov_write_moov_tag(pb, mov, s);
        }
3662 3663 3664 3665
    } else {
        mov_flush_fragment(s);
        mov_write_mfra_tag(pb, mov);
    }
3666

3667
    for (i = 0; i < mov->nb_streams; i++) {
3668 3669 3670 3671 3672 3673 3674 3675 3676 3677
        if (mov->flags & FF_MOV_FLAG_FRAGMENT &&
            mov->tracks[i].vc1_info.struct_offset && s->pb->seekable) {
            int64_t off = avio_tell(pb);
            uint8_t buf[7];
            if (mov_write_dvc1_structs(&mov->tracks[i], buf) >= 0) {
                avio_seek(pb, mov->tracks[i].vc1_info.struct_offset, SEEK_SET);
                avio_write(pb, buf, 7);
                avio_seek(pb, off, SEEK_SET);
            }
        }
3678
    }
3679

3680
error:
3681
    mov_free(s);
3682

3683 3684 3685
    return res;
}

3686
#if CONFIG_MOV_MUXER
3687
MOV_CLASS(mov)
3688
AVOutputFormat ff_mov_muxer = {
3689
    .name              = "mov",
3690
    .long_name         = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
3691 3692
    .extensions        = "mov",
    .priv_data_size    = sizeof(MOVMuxContext),
3693
    .audio_codec       = AV_CODEC_ID_AAC,
3694
    .video_codec       = CONFIG_LIBX264_ENCODER ?
3695
                         AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4,
3696
    .write_header      = mov_write_header,
3697
    .write_packet      = mov_write_packet,
3698
    .write_trailer     = mov_write_trailer,
3699
    .flags             = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
3700 3701 3702 3703
    .codec_tag         = (const AVCodecTag* const []){
        ff_codec_movvideo_tags, ff_codec_movaudio_tags, 0
    },
    .priv_class        = &mov_muxer_class,
3704
};
3705
#endif
3706
#if CONFIG_TGP_MUXER
3707
MOV_CLASS(tgp)
3708
AVOutputFormat ff_tgp_muxer = {
3709
    .name              = "3gp",
3710
    .long_name         = NULL_IF_CONFIG_SMALL("3GP (3GPP file format)"),
3711 3712
    .extensions        = "3gp",
    .priv_data_size    = sizeof(MOVMuxContext),
3713 3714
    .audio_codec       = AV_CODEC_ID_AMR_NB,
    .video_codec       = AV_CODEC_ID_H263,
3715
    .write_header      = mov_write_header,
3716
    .write_packet      = mov_write_packet,
3717
    .write_trailer     = mov_write_trailer,
3718
    .flags             = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
3719 3720
    .codec_tag         = (const AVCodecTag* const []){ codec_3gp_tags, 0 },
    .priv_class        = &tgp_muxer_class,
3721
};
3722
#endif
3723
#if CONFIG_MP4_MUXER
3724
MOV_CLASS(mp4)
3725
AVOutputFormat ff_mp4_muxer = {
3726
    .name              = "mp4",
3727
    .long_name         = NULL_IF_CONFIG_SMALL("MP4 (MPEG-4 Part 14)"),
3728 3729 3730
    .mime_type         = "application/mp4",
    .extensions        = "mp4",
    .priv_data_size    = sizeof(MOVMuxContext),
3731
    .audio_codec       = AV_CODEC_ID_AAC,
3732
    .video_codec       = CONFIG_LIBX264_ENCODER ?
3733
                         AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4,
3734
    .write_header      = mov_write_header,
3735
    .write_packet      = mov_write_packet,
3736
    .write_trailer     = mov_write_trailer,
3737
    .flags             = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
3738 3739
    .codec_tag         = (const AVCodecTag* const []){ ff_mp4_obj_type, 0 },
    .priv_class        = &mp4_muxer_class,
3740
};
3741
#endif
3742
#if CONFIG_PSP_MUXER
3743
MOV_CLASS(psp)
3744
AVOutputFormat ff_psp_muxer = {
3745
    .name              = "psp",
3746
    .long_name         = NULL_IF_CONFIG_SMALL("PSP MP4 (MPEG-4 Part 14)"),
3747 3748
    .extensions        = "mp4,psp",
    .priv_data_size    = sizeof(MOVMuxContext),
3749
    .audio_codec       = AV_CODEC_ID_AAC,
3750
    .video_codec       = CONFIG_LIBX264_ENCODER ?
3751
                         AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4,
3752
    .write_header      = mov_write_header,
3753
    .write_packet      = mov_write_packet,
3754
    .write_trailer     = mov_write_trailer,
3755
    .flags             = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
3756 3757
    .codec_tag         = (const AVCodecTag* const []){ ff_mp4_obj_type, 0 },
    .priv_class        = &psp_muxer_class,
3758
};
3759
#endif
3760
#if CONFIG_TG2_MUXER
3761
MOV_CLASS(tg2)
3762
AVOutputFormat ff_tg2_muxer = {
3763
    .name              = "3g2",
3764
    .long_name         = NULL_IF_CONFIG_SMALL("3GP2 (3GPP2 file format)"),
3765 3766
    .extensions        = "3g2",
    .priv_data_size    = sizeof(MOVMuxContext),
3767 3768
    .audio_codec       = AV_CODEC_ID_AMR_NB,
    .video_codec       = AV_CODEC_ID_H263,
3769
    .write_header      = mov_write_header,
3770
    .write_packet      = mov_write_packet,
3771
    .write_trailer     = mov_write_trailer,
3772
    .flags             = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
3773 3774
    .codec_tag         = (const AVCodecTag* const []){ codec_3gp_tags, 0 },
    .priv_class        = &tg2_muxer_class,
3775
};
3776
#endif
3777
#if CONFIG_IPOD_MUXER
3778
MOV_CLASS(ipod)
3779
AVOutputFormat ff_ipod_muxer = {
3780
    .name              = "ipod",
3781
    .long_name         = NULL_IF_CONFIG_SMALL("iPod H.264 MP4 (MPEG-4 Part 14)"),
3782 3783 3784
    .mime_type         = "application/mp4",
    .extensions        = "m4v,m4a",
    .priv_data_size    = sizeof(MOVMuxContext),
3785 3786
    .audio_codec       = AV_CODEC_ID_AAC,
    .video_codec       = AV_CODEC_ID_H264,
3787
    .write_header      = mov_write_header,
3788
    .write_packet      = mov_write_packet,
3789
    .write_trailer     = mov_write_trailer,
3790
    .flags             = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
3791 3792
    .codec_tag         = (const AVCodecTag* const []){ codec_ipod_tags, 0 },
    .priv_class        = &ipod_muxer_class,
3793 3794
};
#endif
3795 3796 3797 3798
#if CONFIG_ISMV_MUXER
MOV_CLASS(ismv)
AVOutputFormat ff_ismv_muxer = {
    .name              = "ismv",
3799
    .long_name         = NULL_IF_CONFIG_SMALL("ISMV/ISMA (Smooth Streaming)"),
3800 3801 3802
    .mime_type         = "application/mp4",
    .extensions        = "ismv,isma",
    .priv_data_size    = sizeof(MOVMuxContext),
3803 3804
    .audio_codec       = AV_CODEC_ID_AAC,
    .video_codec       = AV_CODEC_ID_H264,
3805
    .write_header      = mov_write_header,
3806
    .write_packet      = mov_write_packet,
3807
    .write_trailer     = mov_write_trailer,
3808
    .flags             = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
3809
    .codec_tag         = (const AVCodecTag* const []){ ff_mp4_obj_type, 0 },
3810 3811 3812
    .priv_class        = &ismv_muxer_class,
};
#endif
3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830
#if CONFIG_F4V_MUXER
MOV_CLASS(f4v)
AVOutputFormat ff_f4v_muxer = {
    .name              = "f4v",
    .long_name         = NULL_IF_CONFIG_SMALL("F4V Adobe Flash Video"),
    .mime_type         = "application/f4v",
    .extensions        = "f4v",
    .priv_data_size    = sizeof(MOVMuxContext),
    .audio_codec       = AV_CODEC_ID_AAC,
    .video_codec       = AV_CODEC_ID_H264,
    .write_header      = mov_write_header,
    .write_packet      = mov_write_packet,
    .write_trailer     = mov_write_trailer,
    .flags             = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
    .codec_tag         = (const AVCodecTag* const []){ codec_f4v_tags, 0 },
    .priv_class        = &f4v_muxer_class,
};
#endif