LCOV - code coverage report
Current view: top level - libavformat - movenc.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 2638 4154 63.5 %
Date: 2018-02-25 01:33:35 Functions: 128 171 74.9 %

          Line data    Source code
       1             : /*
       2             :  * MOV, 3GP, MP4 muxer
       3             :  * Copyright (c) 2003 Thomas Raivio
       4             :  * 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 FFmpeg.
       8             :  *
       9             :  * FFmpeg is free software; you can redistribute it and/or
      10             :  * modify it under the terms of the GNU Lesser General Public
      11             :  * 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             :  * FFmpeg is distributed in the hope that it will be useful,
      15             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      17             :  * Lesser General Public License for more details.
      18             :  *
      19             :  * You should have received a copy of the GNU Lesser General Public
      20             :  * License along with FFmpeg; if not, write to the Free Software
      21             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      22             :  */
      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/ac3_parser_internal.h"
      35             : #include "libavcodec/dnxhddata.h"
      36             : #include "libavcodec/flac.h"
      37             : #include "libavcodec/get_bits.h"
      38             : 
      39             : #include "libavcodec/internal.h"
      40             : #include "libavcodec/put_bits.h"
      41             : #include "libavcodec/vc1_common.h"
      42             : #include "libavcodec/raw.h"
      43             : #include "internal.h"
      44             : #include "libavutil/avstring.h"
      45             : #include "libavutil/intfloat.h"
      46             : #include "libavutil/mathematics.h"
      47             : #include "libavutil/libm.h"
      48             : #include "libavutil/opt.h"
      49             : #include "libavutil/dict.h"
      50             : #include "libavutil/pixdesc.h"
      51             : #include "libavutil/stereo3d.h"
      52             : #include "libavutil/timecode.h"
      53             : #include "libavutil/color_utils.h"
      54             : #include "hevc.h"
      55             : #include "rtpenc.h"
      56             : #include "mov_chan.h"
      57             : #include "vpcc.h"
      58             : 
      59             : static const AVOption options[] = {
      60             :     { "movflags", "MOV muxer flags", offsetof(MOVMuxContext, flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
      61             :     { "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" },
      62             :     { "moov_size", "maximum moov size so it can be placed at the begin", offsetof(MOVMuxContext, reserved_moov_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, 0 },
      63             :     { "empty_moov", "Make the initial moov atom empty", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_EMPTY_MOOV}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
      64             :     { "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" },
      65             :     { "frag_every_frame", "Fragment at every frame", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_FRAG_EVERY_FRAME}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
      66             :     { "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" },
      67             :     { "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" },
      68             :     { "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" },
      69             :     { "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" },
      70             :     { "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" },
      71             :     { "disable_chpl", "Disable Nero chapter atom", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_DISABLE_CHPL}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
      72             :     { "default_base_moof", "Set the default-base-is-moof flag in tfhd atoms", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_DEFAULT_BASE_MOOF}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
      73             :     { "dash", "Write DASH compatible fragmented MP4", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_DASH}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
      74             :     { "frag_discont", "Signal that the next fragment is discontinuous from earlier ones", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_FRAG_DISCONT}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
      75             :     { "delay_moov", "Delay writing the initial moov until the first fragment is cut, or until the first fragment flush", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_DELAY_MOOV}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
      76             :     { "global_sidx", "Write a global sidx index at the start of the file", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_GLOBAL_SIDX}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
      77             :     { "write_colr", "Write colr atom (Experimental, may be renamed or changed, do not use from scripts)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_WRITE_COLR}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
      78             :     { "write_gama", "Write deprecated gama atom", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_WRITE_GAMA}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
      79             :     { "use_metadata_tags", "Use mdta atom for metadata.", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_USE_MDTA}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
      80             :     { "skip_trailer", "Skip writing the mfra/tfra/mfro trailer for fragmented files", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_SKIP_TRAILER}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
      81             :     { "negative_cts_offsets", "Use negative CTS offsets (reducing the need for edit lists)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
      82             :     FF_RTP_FLAG_OPTS(MOVMuxContext, rtp_flags),
      83             :     { "skip_iods", "Skip writing iods atom.", offsetof(MOVMuxContext, iods_skip), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
      84             :     { "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},
      85             :     { "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},
      86             :     { "frag_duration", "Maximum fragment duration", offsetof(MOVMuxContext, max_fragment_duration), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
      87             :     { "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},
      88             :     { "frag_size", "Maximum fragment size", offsetof(MOVMuxContext, max_fragment_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
      89             :     { "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},
      90             :     { "video_track_timescale", "set timescale of all video tracks", offsetof(MOVMuxContext, video_track_timescale), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
      91             :     { "brand",    "Override major brand", offsetof(MOVMuxContext, major_brand),   AV_OPT_TYPE_STRING, {.str = NULL}, .flags = AV_OPT_FLAG_ENCODING_PARAM },
      92             :     { "use_editlist", "use edit list", offsetof(MOVMuxContext, use_editlist), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM},
      93             :     { "fragment_index", "Fragment number of the next fragment", offsetof(MOVMuxContext, fragments), AV_OPT_TYPE_INT, {.i64 = 1}, 1, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
      94             :     { "mov_gamma", "gamma value for gama atom", offsetof(MOVMuxContext, gamma), AV_OPT_TYPE_FLOAT, {.dbl = 0.0 }, 0.0, 10, AV_OPT_FLAG_ENCODING_PARAM},
      95             :     { "frag_interleave", "Interleave samples within fragments (max number of consecutive samples, lower is tighter interleaving, but with more overhead)", offsetof(MOVMuxContext, frag_interleave), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
      96             :     { "encryption_scheme",    "Configures the encryption scheme, allowed values are none, cenc-aes-ctr", offsetof(MOVMuxContext, encryption_scheme_str),   AV_OPT_TYPE_STRING, {.str = NULL}, .flags = AV_OPT_FLAG_ENCODING_PARAM },
      97             :     { "encryption_key", "The media encryption key (hex)", offsetof(MOVMuxContext, encryption_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_ENCODING_PARAM },
      98             :     { "encryption_kid", "The media encryption key identifier (hex)", offsetof(MOVMuxContext, encryption_kid), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_ENCODING_PARAM },
      99             :     { "use_stream_ids_as_track_ids", "use stream ids as track ids", offsetof(MOVMuxContext, use_stream_ids_as_track_ids), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
     100             :     { "write_tmcd", "force or disable writing tmcd", offsetof(MOVMuxContext, write_tmcd), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM},
     101             :     { NULL },
     102             : };
     103             : 
     104             : #define MOV_CLASS(flavor)\
     105             : static const AVClass flavor ## _muxer_class = {\
     106             :     .class_name = #flavor " muxer",\
     107             :     .item_name  = av_default_item_name,\
     108             :     .option     = options,\
     109             :     .version    = LIBAVUTIL_VERSION_INT,\
     110             : };
     111             : 
     112             : static int get_moov_size(AVFormatContext *s);
     113             : 
     114           2 : static int utf8len(const uint8_t *b)
     115             : {
     116           2 :     int len = 0;
     117             :     int val;
     118          14 :     while (*b) {
     119          10 :         GET_UTF8(val, *b++, return -1;)
     120          10 :         len++;
     121             :     }
     122           2 :     return len;
     123             : }
     124             : 
     125             : //FIXME support 64 bit variant with wide placeholders
     126        4713 : static int64_t update_size(AVIOContext *pb, int64_t pos)
     127             : {
     128        4713 :     int64_t curpos = avio_tell(pb);
     129        4713 :     avio_seek(pb, pos, SEEK_SET);
     130        4713 :     avio_wb32(pb, curpos - pos); /* rewrite size */
     131        4713 :     avio_seek(pb, curpos, SEEK_SET);
     132             : 
     133        4713 :     return curpos - pos;
     134             : }
     135             : 
     136         248 : static int co64_required(const MOVTrack *track)
     137             : {
     138         248 :     if (track->entry > 0 && track->cluster[track->entry - 1].pos + track->data_offset > UINT32_MAX)
     139           0 :         return 1;
     140         248 :     return 0;
     141             : }
     142             : 
     143             : /* Chunk offset atom */
     144         248 : static int mov_write_stco_tag(AVIOContext *pb, MOVTrack *track)
     145             : {
     146             :     int i;
     147         248 :     int mode64 = co64_required(track); // use 32 bit size variant if possible
     148         248 :     int64_t pos = avio_tell(pb);
     149         248 :     avio_wb32(pb, 0); /* size */
     150         248 :     if (mode64)
     151           0 :         ffio_wfourcc(pb, "co64");
     152             :     else
     153         248 :         ffio_wfourcc(pb, "stco");
     154         248 :     avio_wb32(pb, 0); /* version & flags */
     155         248 :     avio_wb32(pb, track->chunkCount); /* entry count */
     156        9406 :     for (i = 0; i < track->entry; i++) {
     157        9158 :         if (!track->cluster[i].chunkNum)
     158        7069 :             continue;
     159        2089 :         if (mode64 == 1)
     160           0 :             avio_wb64(pb, track->cluster[i].pos + track->data_offset);
     161             :         else
     162        2089 :             avio_wb32(pb, track->cluster[i].pos + track->data_offset);
     163             :     }
     164         248 :     return update_size(pb, pos);
     165             : }
     166             : 
     167             : /* Sample size atom */
     168         248 : static int mov_write_stsz_tag(AVIOContext *pb, MOVTrack *track)
     169             : {
     170         248 :     int equalChunks = 1;
     171         248 :     int i, j, entries = 0, tst = -1, oldtst = -1;
     172             : 
     173         248 :     int64_t pos = avio_tell(pb);
     174         248 :     avio_wb32(pb, 0); /* size */
     175         248 :     ffio_wfourcc(pb, "stsz");
     176         248 :     avio_wb32(pb, 0); /* version & flags */
     177             : 
     178        9406 :     for (i = 0; i < track->entry; i++) {
     179        9158 :         tst = track->cluster[i].size / track->cluster[i].entries;
     180        9158 :         if (oldtst != -1 && tst != oldtst)
     181        4721 :             equalChunks = 0;
     182        9158 :         oldtst = tst;
     183        9158 :         entries += track->cluster[i].entries;
     184             :     }
     185         327 :     if (equalChunks && track->entry) {
     186          79 :         int sSize = track->entry ? track->cluster[0].size / track->cluster[0].entries : 0;
     187          79 :         sSize = FFMAX(1, sSize); // adpcm mono case could make sSize == 0
     188          79 :         avio_wb32(pb, sSize); // sample size
     189          79 :         avio_wb32(pb, entries); // sample count
     190             :     } else {
     191         169 :         avio_wb32(pb, 0); // sample size
     192         169 :         avio_wb32(pb, entries); // sample count
     193        5828 :         for (i = 0; i < track->entry; i++) {
     194       11318 :             for (j = 0; j < track->cluster[i].entries; j++) {
     195       11318 :                 avio_wb32(pb, track->cluster[i].size /
     196        5659 :                           track->cluster[i].entries);
     197             :             }
     198             :         }
     199             :     }
     200         248 :     return update_size(pb, pos);
     201             : }
     202             : 
     203             : /* Sample to chunk atom */
     204         248 : static int mov_write_stsc_tag(AVIOContext *pb, MOVTrack *track)
     205             : {
     206         248 :     int index = 0, oldval = -1, i;
     207             :     int64_t entryPos, curpos;
     208             : 
     209         248 :     int64_t pos = avio_tell(pb);
     210         248 :     avio_wb32(pb, 0); /* size */
     211         248 :     ffio_wfourcc(pb, "stsc");
     212         248 :     avio_wb32(pb, 0); // version & flags
     213         248 :     entryPos = avio_tell(pb);
     214         248 :     avio_wb32(pb, track->chunkCount); // entry count
     215        9406 :     for (i = 0; i < track->entry; i++) {
     216        9158 :         if (oldval != track->cluster[i].samples_in_chunk && track->cluster[i].chunkNum) {
     217         739 :             avio_wb32(pb, track->cluster[i].chunkNum); // first chunk
     218         739 :             avio_wb32(pb, track->cluster[i].samples_in_chunk); // samples per chunk
     219         739 :             avio_wb32(pb, 0x1); // sample description index
     220         739 :             oldval = track->cluster[i].samples_in_chunk;
     221         739 :             index++;
     222             :         }
     223             :     }
     224         248 :     curpos = avio_tell(pb);
     225         248 :     avio_seek(pb, entryPos, SEEK_SET);
     226         248 :     avio_wb32(pb, index); // rewrite size
     227         248 :     avio_seek(pb, curpos, SEEK_SET);
     228             : 
     229         248 :     return update_size(pb, pos);
     230             : }
     231             : 
     232             : /* Sync sample atom */
     233          40 : static int mov_write_stss_tag(AVIOContext *pb, MOVTrack *track, uint32_t flag)
     234             : {
     235             :     int64_t curpos, entryPos;
     236          40 :     int i, index = 0;
     237          40 :     int64_t pos = avio_tell(pb);
     238          40 :     avio_wb32(pb, 0); // size
     239          40 :     ffio_wfourcc(pb, flag == MOV_SYNC_SAMPLE ? "stss" : "stps");
     240          40 :     avio_wb32(pb, 0); // version & flags
     241          40 :     entryPos = avio_tell(pb);
     242          40 :     avio_wb32(pb, track->entry); // entry count
     243        1902 :     for (i = 0; i < track->entry; i++) {
     244        1862 :         if (track->cluster[i].flags & flag) {
     245         149 :             avio_wb32(pb, i + 1);
     246         149 :             index++;
     247             :         }
     248             :     }
     249          40 :     curpos = avio_tell(pb);
     250          40 :     avio_seek(pb, entryPos, SEEK_SET);
     251          40 :     avio_wb32(pb, index); // rewrite size
     252          40 :     avio_seek(pb, curpos, SEEK_SET);
     253          40 :     return update_size(pb, pos);
     254             : }
     255             : 
     256             : /* Sample dependency atom */
     257           0 : static int mov_write_sdtp_tag(AVIOContext *pb, MOVTrack *track)
     258             : {
     259             :     int i;
     260             :     uint8_t leading, dependent, reference, redundancy;
     261           0 :     int64_t pos = avio_tell(pb);
     262           0 :     avio_wb32(pb, 0); // size
     263           0 :     ffio_wfourcc(pb, "sdtp");
     264           0 :     avio_wb32(pb, 0); // version & flags
     265           0 :     for (i = 0; i < track->entry; i++) {
     266           0 :         dependent = MOV_SAMPLE_DEPENDENCY_YES;
     267           0 :         leading = reference = redundancy = MOV_SAMPLE_DEPENDENCY_UNKNOWN;
     268           0 :         if (track->cluster[i].flags & MOV_DISPOSABLE_SAMPLE) {
     269           0 :             reference = MOV_SAMPLE_DEPENDENCY_NO;
     270             :         }
     271           0 :         if (track->cluster[i].flags & MOV_SYNC_SAMPLE) {
     272           0 :             dependent = MOV_SAMPLE_DEPENDENCY_NO;
     273             :         }
     274           0 :         avio_w8(pb, (leading << 6)   | (dependent << 4) |
     275           0 :                     (reference << 2) | redundancy);
     276             :     }
     277           0 :     return update_size(pb, pos);
     278             : }
     279             : 
     280           0 : static int mov_write_amr_tag(AVIOContext *pb, MOVTrack *track)
     281             : {
     282           0 :     avio_wb32(pb, 0x11); /* size */
     283           0 :     if (track->mode == MODE_MOV) ffio_wfourcc(pb, "samr");
     284           0 :     else                         ffio_wfourcc(pb, "damr");
     285           0 :     ffio_wfourcc(pb, "FFMP");
     286           0 :     avio_w8(pb, 0); /* decoder version */
     287             : 
     288           0 :     avio_wb16(pb, 0x81FF); /* Mode set (all modes for AMR_NB) */
     289           0 :     avio_w8(pb, 0x00); /* Mode change period (no restriction) */
     290           0 :     avio_w8(pb, 0x01); /* Frames per sample */
     291           0 :     return 0x11;
     292             : }
     293             : 
     294           0 : static int mov_write_ac3_tag(AVIOContext *pb, MOVTrack *track)
     295             : {
     296             :     GetBitContext gbc;
     297             :     PutBitContext pbc;
     298             :     uint8_t buf[3];
     299             :     int fscod, bsid, bsmod, acmod, lfeon, frmsizecod;
     300             : 
     301           0 :     if (track->vos_len < 7)
     302           0 :         return -1;
     303             : 
     304           0 :     avio_wb32(pb, 11);
     305           0 :     ffio_wfourcc(pb, "dac3");
     306             : 
     307           0 :     init_get_bits(&gbc, track->vos_data + 4, (track->vos_len - 4) * 8);
     308           0 :     fscod      = get_bits(&gbc, 2);
     309           0 :     frmsizecod = get_bits(&gbc, 6);
     310           0 :     bsid       = get_bits(&gbc, 5);
     311           0 :     bsmod      = get_bits(&gbc, 3);
     312           0 :     acmod      = get_bits(&gbc, 3);
     313           0 :     if (acmod == 2) {
     314           0 :         skip_bits(&gbc, 2); // dsurmod
     315             :     } else {
     316           0 :         if ((acmod & 1) && acmod != 1)
     317           0 :             skip_bits(&gbc, 2); // cmixlev
     318           0 :         if (acmod & 4)
     319           0 :             skip_bits(&gbc, 2); // surmixlev
     320             :     }
     321           0 :     lfeon = get_bits1(&gbc);
     322             : 
     323           0 :     init_put_bits(&pbc, buf, sizeof(buf));
     324           0 :     put_bits(&pbc, 2, fscod);
     325           0 :     put_bits(&pbc, 5, bsid);
     326           0 :     put_bits(&pbc, 3, bsmod);
     327           0 :     put_bits(&pbc, 3, acmod);
     328           0 :     put_bits(&pbc, 1, lfeon);
     329           0 :     put_bits(&pbc, 5, frmsizecod >> 1); // bit_rate_code
     330           0 :     put_bits(&pbc, 5, 0); // reserved
     331             : 
     332           0 :     flush_put_bits(&pbc);
     333           0 :     avio_write(pb, buf, sizeof(buf));
     334             : 
     335           0 :     return 11;
     336             : }
     337             : 
     338             : struct eac3_info {
     339             :     AVPacket pkt;
     340             :     uint8_t ec3_done;
     341             :     uint8_t num_blocks;
     342             : 
     343             :     /* Layout of the EC3SpecificBox */
     344             :     /* maximum bitrate */
     345             :     uint16_t data_rate;
     346             :     /* number of independent substreams */
     347             :     uint8_t  num_ind_sub;
     348             :     struct {
     349             :         /* sample rate code (see ff_ac3_sample_rate_tab) 2 bits */
     350             :         uint8_t fscod;
     351             :         /* bit stream identification 5 bits */
     352             :         uint8_t bsid;
     353             :         /* one bit reserved */
     354             :         /* audio service mixing (not supported yet) 1 bit */
     355             :         /* bit stream mode 3 bits */
     356             :         uint8_t bsmod;
     357             :         /* audio coding mode 3 bits */
     358             :         uint8_t acmod;
     359             :         /* sub woofer on 1 bit */
     360             :         uint8_t lfeon;
     361             :         /* 3 bits reserved */
     362             :         /* number of dependent substreams associated with this substream 4 bits */
     363             :         uint8_t num_dep_sub;
     364             :         /* channel locations of the dependent substream(s), if any, 9 bits */
     365             :         uint16_t chan_loc;
     366             :         /* if there is no dependent substream, then one bit reserved instead */
     367             :     } substream[1]; /* TODO: support 8 independent substreams */
     368             : };
     369             : 
     370             : #if CONFIG_AC3_PARSER
     371         652 : static int handle_eac3(MOVMuxContext *mov, AVPacket *pkt, MOVTrack *track)
     372             : {
     373         652 :     AC3HeaderInfo *hdr = NULL;
     374             :     struct eac3_info *info;
     375             :     int num_blocks, ret;
     376             : 
     377         652 :     if (!track->eac3_priv && !(track->eac3_priv = av_mallocz(sizeof(*info))))
     378           0 :         return AVERROR(ENOMEM);
     379         652 :     info = track->eac3_priv;
     380             : 
     381         652 :     if (avpriv_ac3_parse_header(&hdr, pkt->data, pkt->size) < 0) {
     382             :         /* drop the packets until we see a good one */
     383           1 :         if (!track->entry) {
     384           1 :             av_log(mov, AV_LOG_WARNING, "Dropping invalid packet from start of the stream\n");
     385           1 :             ret = 0;
     386             :         } else
     387           0 :             ret = AVERROR_INVALIDDATA;
     388           1 :         goto end;
     389             :     }
     390             : 
     391         651 :     info->data_rate = FFMAX(info->data_rate, hdr->bit_rate / 1000);
     392         651 :     num_blocks = hdr->num_blocks;
     393             : 
     394         651 :     if (!info->ec3_done) {
     395             :         /* AC-3 substream must be the first one */
     396           2 :         if (hdr->bitstream_id <= 10 && hdr->substreamid != 0) {
     397           0 :             ret = AVERROR(EINVAL);
     398           0 :             goto end;
     399             :         }
     400             : 
     401             :         /* this should always be the case, given that our AC-3 parser
     402             :          * concatenates dependent frames to their independent parent */
     403           2 :         if (hdr->frame_type == EAC3_FRAME_TYPE_INDEPENDENT) {
     404             :             /* substream ids must be incremental */
     405           2 :             if (hdr->substreamid > info->num_ind_sub + 1) {
     406           0 :                 ret = AVERROR(EINVAL);
     407           0 :                 goto end;
     408             :             }
     409             : 
     410           2 :             if (hdr->substreamid == info->num_ind_sub + 1) {
     411             :                 //info->num_ind_sub++;
     412           0 :                 avpriv_request_sample(track->par, "Multiple independent substreams");
     413           0 :                 ret = AVERROR_PATCHWELCOME;
     414           0 :                 goto end;
     415           4 :             } else if (hdr->substreamid < info->num_ind_sub ||
     416           4 :                        hdr->substreamid == 0 && info->substream[0].bsid) {
     417           1 :                 info->ec3_done = 1;
     418           1 :                 goto concatenate;
     419             :             }
     420             :         }
     421             : 
     422             :         /* fill the info needed for the "dec3" atom */
     423           1 :         info->substream[hdr->substreamid].fscod = hdr->sr_code;
     424           1 :         info->substream[hdr->substreamid].bsid  = hdr->bitstream_id;
     425           1 :         info->substream[hdr->substreamid].bsmod = hdr->bitstream_mode;
     426           1 :         info->substream[hdr->substreamid].acmod = hdr->channel_mode;
     427           1 :         info->substream[hdr->substreamid].lfeon = hdr->lfe_on;
     428             : 
     429             :         /* Parse dependent substream(s), if any */
     430           1 :         if (pkt->size != hdr->frame_size) {
     431           0 :             int cumul_size = hdr->frame_size;
     432           0 :             int parent = hdr->substreamid;
     433             : 
     434           0 :             while (cumul_size != pkt->size) {
     435             :                 GetBitContext gbc;
     436             :                 int i;
     437           0 :                 ret = avpriv_ac3_parse_header(&hdr, pkt->data + cumul_size, pkt->size - cumul_size);
     438           0 :                 if (ret < 0)
     439           0 :                     goto end;
     440           0 :                 if (hdr->frame_type != EAC3_FRAME_TYPE_DEPENDENT) {
     441           0 :                     ret = AVERROR(EINVAL);
     442           0 :                     goto end;
     443             :                 }
     444           0 :                 info->substream[parent].num_dep_sub++;
     445           0 :                 ret /= 8;
     446             : 
     447             :                 /* header is parsed up to lfeon, but custom channel map may be needed */
     448           0 :                 init_get_bits8(&gbc, pkt->data + cumul_size + ret, pkt->size - cumul_size - ret);
     449             :                 /* skip bsid */
     450           0 :                 skip_bits(&gbc, 5);
     451             :                 /* skip volume control params */
     452           0 :                 for (i = 0; i < (hdr->channel_mode ? 1 : 2); i++) {
     453           0 :                     skip_bits(&gbc, 5); // skip dialog normalization
     454           0 :                     if (get_bits1(&gbc)) {
     455           0 :                         skip_bits(&gbc, 8); // skip compression gain word
     456             :                     }
     457             :                 }
     458             :                 /* get the dependent stream channel map, if exists */
     459           0 :                 if (get_bits1(&gbc))
     460           0 :                     info->substream[parent].chan_loc |= (get_bits(&gbc, 16) >> 5) & 0x1f;
     461             :                 else
     462           0 :                     info->substream[parent].chan_loc |= hdr->channel_mode;
     463           0 :                 cumul_size += hdr->frame_size;
     464             :             }
     465             :         }
     466             :     }
     467             : 
     468         650 : concatenate:
     469         651 :     if (!info->num_blocks && num_blocks == 6) {
     470         651 :         ret = pkt->size;
     471         651 :         goto end;
     472             :     }
     473           0 :     else if (info->num_blocks + num_blocks > 6) {
     474           0 :         ret = AVERROR_INVALIDDATA;
     475           0 :         goto end;
     476             :     }
     477             : 
     478           0 :     if (!info->num_blocks) {
     479           0 :         ret = av_packet_ref(&info->pkt, pkt);
     480           0 :         if (!ret)
     481           0 :             info->num_blocks = num_blocks;
     482           0 :         goto end;
     483             :     } else {
     484           0 :         if ((ret = av_grow_packet(&info->pkt, pkt->size)) < 0)
     485           0 :             goto end;
     486           0 :         memcpy(info->pkt.data + info->pkt.size - pkt->size, pkt->data, pkt->size);
     487           0 :         info->num_blocks += num_blocks;
     488           0 :         info->pkt.duration += pkt->duration;
     489           0 :         if ((ret = av_copy_packet_side_data(&info->pkt, pkt)) < 0)
     490           0 :             goto end;
     491           0 :         if (info->num_blocks != 6)
     492           0 :             goto end;
     493           0 :         av_packet_unref(pkt);
     494           0 :         ret = av_packet_ref(pkt, &info->pkt);
     495           0 :         if (ret < 0)
     496           0 :             goto end;
     497           0 :         av_packet_unref(&info->pkt);
     498           0 :         info->num_blocks = 0;
     499             :     }
     500           0 :     ret = pkt->size;
     501             : 
     502         652 : end:
     503         652 :     av_free(hdr);
     504             : 
     505         652 :     return ret;
     506             : }
     507             : #endif
     508             : 
     509           1 : static int mov_write_eac3_tag(AVIOContext *pb, MOVTrack *track)
     510             : {
     511             :     PutBitContext pbc;
     512             :     uint8_t *buf;
     513             :     struct eac3_info *info;
     514             :     int size, i;
     515             : 
     516           1 :     if (!track->eac3_priv)
     517           0 :         return AVERROR(EINVAL);
     518             : 
     519           1 :     info = track->eac3_priv;
     520           1 :     size = 2 + 4 * (info->num_ind_sub + 1);
     521           1 :     buf = av_malloc(size);
     522           1 :     if (!buf) {
     523           0 :         size = AVERROR(ENOMEM);
     524           0 :         goto end;
     525             :     }
     526             : 
     527           1 :     init_put_bits(&pbc, buf, size);
     528           1 :     put_bits(&pbc, 13, info->data_rate);
     529           1 :     put_bits(&pbc,  3, info->num_ind_sub);
     530           2 :     for (i = 0; i <= info->num_ind_sub; i++) {
     531           1 :         put_bits(&pbc, 2, info->substream[i].fscod);
     532           1 :         put_bits(&pbc, 5, info->substream[i].bsid);
     533           1 :         put_bits(&pbc, 1, 0); /* reserved */
     534           1 :         put_bits(&pbc, 1, 0); /* asvc */
     535           1 :         put_bits(&pbc, 3, info->substream[i].bsmod);
     536           1 :         put_bits(&pbc, 3, info->substream[i].acmod);
     537           1 :         put_bits(&pbc, 1, info->substream[i].lfeon);
     538           1 :         put_bits(&pbc, 5, 0); /* reserved */
     539           1 :         put_bits(&pbc, 4, info->substream[i].num_dep_sub);
     540           1 :         if (!info->substream[i].num_dep_sub) {
     541           1 :             put_bits(&pbc, 1, 0); /* reserved */
     542           1 :             size--;
     543             :         } else {
     544           0 :             put_bits(&pbc, 9, info->substream[i].chan_loc);
     545             :         }
     546             :     }
     547           1 :     flush_put_bits(&pbc);
     548             : 
     549           1 :     avio_wb32(pb, size + 8);
     550           1 :     ffio_wfourcc(pb, "dec3");
     551           1 :     avio_write(pb, buf, size);
     552             : 
     553           1 :     av_free(buf);
     554             : 
     555           1 : end:
     556           1 :     av_packet_unref(&info->pkt);
     557           1 :     av_freep(&track->eac3_priv);
     558             : 
     559           1 :     return size;
     560             : }
     561             : 
     562             : /**
     563             :  * This function writes extradata "as is".
     564             :  * Extradata must be formatted like a valid atom (with size and tag).
     565             :  */
     566          12 : static int mov_write_extradata_tag(AVIOContext *pb, MOVTrack *track)
     567             : {
     568          12 :     avio_write(pb, track->par->extradata, track->par->extradata_size);
     569          12 :     return track->par->extradata_size;
     570             : }
     571             : 
     572           0 : static int mov_write_enda_tag(AVIOContext *pb)
     573             : {
     574           0 :     avio_wb32(pb, 10);
     575           0 :     ffio_wfourcc(pb, "enda");
     576           0 :     avio_wb16(pb, 1); /* little endian */
     577           0 :     return 10;
     578             : }
     579             : 
     580           2 : static int mov_write_enda_tag_be(AVIOContext *pb)
     581             : {
     582           2 :   avio_wb32(pb, 10);
     583           2 :   ffio_wfourcc(pb, "enda");
     584           2 :   avio_wb16(pb, 0); /* big endian */
     585           2 :   return 10;
     586             : }
     587             : 
     588         284 : static void put_descr(AVIOContext *pb, int tag, unsigned int size)
     589             : {
     590         284 :     int i = 3;
     591         284 :     avio_w8(pb, tag);
     592        1136 :     for (; i > 0; i--)
     593         852 :         avio_w8(pb, (size >> (7 * i)) | 0x80);
     594         284 :     avio_w8(pb, size & 0x7F);
     595         284 : }
     596             : 
     597          71 : static unsigned compute_avg_bitrate(MOVTrack *track)
     598             : {
     599          71 :     uint64_t size = 0;
     600             :     int i;
     601          71 :     if (!track->track_duration)
     602          15 :         return 0;
     603        1871 :     for (i = 0; i < track->entry; i++)
     604        1815 :         size += track->cluster[i].size;
     605          56 :     return size * 8 * track->timescale / track->track_duration;
     606             : }
     607             : 
     608          71 : static int mov_write_esds_tag(AVIOContext *pb, MOVTrack *track) // Basic
     609             : {
     610             :     AVCPBProperties *props;
     611          71 :     int64_t pos = avio_tell(pb);
     612          71 :     int decoder_specific_info_len = track->vos_len ? 5 + track->vos_len : 0;
     613             :     unsigned avg_bitrate;
     614             : 
     615          71 :     avio_wb32(pb, 0); // size
     616          71 :     ffio_wfourcc(pb, "esds");
     617          71 :     avio_wb32(pb, 0); // Version
     618             : 
     619             :     // ES descriptor
     620          71 :     put_descr(pb, 0x03, 3 + 5+13 + decoder_specific_info_len + 5+1);
     621          71 :     avio_wb16(pb, track->track_id);
     622          71 :     avio_w8(pb, 0x00); // flags (= no flags)
     623             : 
     624             :     // DecoderConfig descriptor
     625          71 :     put_descr(pb, 0x04, 13 + decoder_specific_info_len);
     626             : 
     627             :     // Object type indication
     628         142 :     if ((track->par->codec_id == AV_CODEC_ID_MP2 ||
     629          71 :          track->par->codec_id == AV_CODEC_ID_MP3) &&
     630           0 :         track->par->sample_rate > 24000)
     631           0 :         avio_w8(pb, 0x6B); // 11172-3
     632             :     else
     633          71 :         avio_w8(pb, ff_codec_get_tag(ff_mp4_obj_type, track->par->codec_id));
     634             : 
     635             :     // the following fields is made of 6 bits to identify the streamtype (4 for video, 5 for audio)
     636             :     // plus 1 bit to indicate upstream and 1 bit set to 1 (reserved)
     637          71 :     if (track->par->codec_id == AV_CODEC_ID_DVD_SUBTITLE)
     638           0 :         avio_w8(pb, (0x38 << 2) | 1); // flags (= NeroSubpicStream)
     639          71 :     else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO)
     640          51 :         avio_w8(pb, 0x15); // flags (= Audiostream)
     641             :     else
     642          20 :         avio_w8(pb, 0x11); // flags (= Visualstream)
     643             : 
     644          71 :     props = (AVCPBProperties*)av_stream_get_side_data(track->st, AV_PKT_DATA_CPB_PROPERTIES,
     645             :                                                       NULL);
     646             : 
     647          71 :     avio_wb24(pb, props ? props->buffer_size / 8 : 0); // Buffersize DB
     648             : 
     649          71 :     avg_bitrate = compute_avg_bitrate(track);
     650          71 :     avio_wb32(pb, props ? FFMAX3(props->max_bitrate, props->avg_bitrate, avg_bitrate) : FFMAX(track->par->bit_rate, avg_bitrate)); // maxbitrate (FIXME should be max rate in any 1 sec window)
     651          71 :     avio_wb32(pb, avg_bitrate);
     652             : 
     653          71 :     if (track->vos_len) {
     654             :         // DecoderSpecific info descriptor
     655          71 :         put_descr(pb, 0x05, track->vos_len);
     656          71 :         avio_write(pb, track->vos_data, track->vos_len);
     657             :     }
     658             : 
     659             :     // SL descriptor
     660          71 :     put_descr(pb, 0x06, 1);
     661          71 :     avio_w8(pb, 0x02);
     662          71 :     return update_size(pb, pos);
     663             : }
     664             : 
     665          53 : static int mov_pcm_le_gt16(enum AVCodecID codec_id)
     666             : {
     667          53 :     return codec_id == AV_CODEC_ID_PCM_S24LE ||
     668          53 :            codec_id == AV_CODEC_ID_PCM_S32LE ||
     669         106 :            codec_id == AV_CODEC_ID_PCM_F32LE ||
     670             :            codec_id == AV_CODEC_ID_PCM_F64LE;
     671             : }
     672             : 
     673          53 : static int mov_pcm_be_gt16(enum AVCodecID codec_id)
     674             : {
     675          49 :     return codec_id == AV_CODEC_ID_PCM_S24BE ||
     676          45 :            codec_id == AV_CODEC_ID_PCM_S32BE ||
     677          98 :            codec_id == AV_CODEC_ID_PCM_F32BE ||
     678             :            codec_id == AV_CODEC_ID_PCM_F64BE;
     679             : }
     680             : 
     681           0 : static int mov_write_ms_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
     682             : {
     683             :     int ret;
     684           0 :     int64_t pos = avio_tell(pb);
     685           0 :     avio_wb32(pb, 0);
     686           0 :     avio_wl32(pb, track->tag); // store it byteswapped
     687           0 :     track->par->codec_tag = av_bswap16(track->tag >> 16);
     688           0 :     if ((ret = ff_put_wav_header(s, pb, track->par, 0)) < 0)
     689           0 :         return ret;
     690           0 :     return update_size(pb, pos);
     691             : }
     692             : 
     693           0 : static int mov_write_wfex_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
     694             : {
     695             :     int ret;
     696           0 :     int64_t pos = avio_tell(pb);
     697           0 :     avio_wb32(pb, 0);
     698           0 :     ffio_wfourcc(pb, "wfex");
     699           0 :     if ((ret = ff_put_wav_header(s, pb, track->st->codecpar, FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX)) < 0)
     700           0 :         return ret;
     701           0 :     return update_size(pb, pos);
     702             : }
     703             : 
     704           0 : static int mov_write_dfla_tag(AVIOContext *pb, MOVTrack *track)
     705             : {
     706           0 :     int64_t pos = avio_tell(pb);
     707           0 :     avio_wb32(pb, 0);
     708           0 :     ffio_wfourcc(pb, "dfLa");
     709           0 :     avio_w8(pb, 0); /* version */
     710           0 :     avio_wb24(pb, 0); /* flags */
     711             : 
     712             :     /* Expect the encoder to pass a METADATA_BLOCK_TYPE_STREAMINFO. */
     713           0 :     if (track->par->extradata_size != FLAC_STREAMINFO_SIZE)
     714           0 :         return AVERROR_INVALIDDATA;
     715             : 
     716             :     /* TODO: Write other METADATA_BLOCK_TYPEs if the encoder makes them available. */
     717           0 :     avio_w8(pb, 1 << 7 | FLAC_METADATA_TYPE_STREAMINFO); /* LastMetadataBlockFlag << 7 | BlockType */
     718           0 :     avio_wb24(pb, track->par->extradata_size); /* Length */
     719           0 :     avio_write(pb, track->par->extradata, track->par->extradata_size); /* BlockData[Length] */
     720             : 
     721           0 :     return update_size(pb, pos);
     722             : }
     723             : 
     724           0 : static int mov_write_dops_tag(AVIOContext *pb, MOVTrack *track)
     725             : {
     726           0 :     int64_t pos = avio_tell(pb);
     727           0 :     avio_wb32(pb, 0);
     728           0 :     ffio_wfourcc(pb, "dOps");
     729           0 :     avio_w8(pb, 0); /* Version */
     730           0 :     if (track->par->extradata_size < 19) {
     731           0 :         av_log(pb, AV_LOG_ERROR, "invalid extradata size\n");
     732           0 :         return AVERROR_INVALIDDATA;
     733             :     }
     734             :     /* extradata contains an Ogg OpusHead, other than byte-ordering and
     735             :        OpusHead's preceeding magic/version, OpusSpecificBox is currently
     736             :        identical. */
     737           0 :     avio_w8(pb, AV_RB8(track->par->extradata + 9)); /* OuputChannelCount */
     738           0 :     avio_wb16(pb, AV_RL16(track->par->extradata + 10)); /* PreSkip */
     739           0 :     avio_wb32(pb, AV_RL32(track->par->extradata + 12)); /* InputSampleRate */
     740           0 :     avio_wb16(pb, AV_RL16(track->par->extradata + 16)); /* OutputGain */
     741             :     /* Write the rest of the header out without byte-swapping. */
     742           0 :     avio_write(pb, track->par->extradata + 18, track->par->extradata_size - 18);
     743             : 
     744           0 :     return update_size(pb, pos);
     745             : }
     746             : 
     747          28 : static int mov_write_chan_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
     748             : {
     749             :     uint32_t layout_tag, bitmap;
     750          28 :     int64_t pos = avio_tell(pb);
     751             : 
     752          28 :     layout_tag = ff_mov_get_channel_layout_tag(track->par->codec_id,
     753          28 :                                                track->par->channel_layout,
     754             :                                                &bitmap);
     755          28 :     if (!layout_tag) {
     756           0 :         av_log(s, AV_LOG_WARNING, "not writing 'chan' tag due to "
     757             :                "lack of channel information\n");
     758           0 :         return 0;
     759             :     }
     760             : 
     761          28 :     if (track->multichannel_as_mono)
     762           0 :         return 0;
     763             : 
     764          28 :     avio_wb32(pb, 0);           // Size
     765          28 :     ffio_wfourcc(pb, "chan");   // Type
     766          28 :     avio_w8(pb, 0);             // Version
     767          28 :     avio_wb24(pb, 0);           // Flags
     768          28 :     avio_wb32(pb, layout_tag);  // mChannelLayoutTag
     769          28 :     avio_wb32(pb, bitmap);      // mChannelBitmap
     770          28 :     avio_wb32(pb, 0);           // mNumberChannelDescriptions
     771             : 
     772          28 :     return update_size(pb, pos);
     773             : }
     774             : 
     775          14 : static int mov_write_wave_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
     776             : {
     777          14 :     int64_t pos = avio_tell(pb);
     778             : 
     779          14 :     avio_wb32(pb, 0);     /* size */
     780          14 :     ffio_wfourcc(pb, "wave");
     781             : 
     782          14 :     if (track->par->codec_id != AV_CODEC_ID_QDM2) {
     783          14 :     avio_wb32(pb, 12);    /* size */
     784          14 :     ffio_wfourcc(pb, "frma");
     785          14 :     avio_wl32(pb, track->tag);
     786             :     }
     787             : 
     788          14 :     if (track->par->codec_id == AV_CODEC_ID_AAC) {
     789             :         /* useless atom needed by mplayer, ipod, not needed by quicktime */
     790           3 :         avio_wb32(pb, 12); /* size */
     791           3 :         ffio_wfourcc(pb, "mp4a");
     792           3 :         avio_wb32(pb, 0);
     793           3 :         mov_write_esds_tag(pb, track);
     794          11 :     } else if (mov_pcm_le_gt16(track->par->codec_id))  {
     795           0 :       mov_write_enda_tag(pb);
     796          11 :     } else if (mov_pcm_be_gt16(track->par->codec_id))  {
     797           2 :       mov_write_enda_tag_be(pb);
     798           9 :     } else if (track->par->codec_id == AV_CODEC_ID_AMR_NB) {
     799           0 :         mov_write_amr_tag(pb, track);
     800           9 :     } else if (track->par->codec_id == AV_CODEC_ID_AC3) {
     801           0 :         mov_write_ac3_tag(pb, track);
     802           9 :     } else if (track->par->codec_id == AV_CODEC_ID_EAC3) {
     803           0 :         mov_write_eac3_tag(pb, track);
     804           9 :     } else if (track->par->codec_id == AV_CODEC_ID_ALAC ||
     805           0 :                track->par->codec_id == AV_CODEC_ID_QDM2) {
     806           9 :         mov_write_extradata_tag(pb, track);
     807           0 :     } else if (track->par->codec_id == AV_CODEC_ID_ADPCM_MS ||
     808           0 :                track->par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) {
     809           0 :         mov_write_ms_tag(s, pb, track);
     810             :     }
     811             : 
     812          14 :     avio_wb32(pb, 8);     /* size */
     813          14 :     avio_wb32(pb, 0);     /* null tag */
     814             : 
     815          14 :     return update_size(pb, pos);
     816             : }
     817             : 
     818           0 : static int mov_write_dvc1_structs(MOVTrack *track, uint8_t *buf)
     819             : {
     820             :     uint8_t *unescaped;
     821           0 :     const uint8_t *start, *next, *end = track->vos_data + track->vos_len;
     822           0 :     int unescaped_size, seq_found = 0;
     823           0 :     int level = 0, interlace = 0;
     824           0 :     int packet_seq   = track->vc1_info.packet_seq;
     825           0 :     int packet_entry = track->vc1_info.packet_entry;
     826           0 :     int slices       = track->vc1_info.slices;
     827             :     PutBitContext pbc;
     828             : 
     829           0 :     if (track->start_dts == AV_NOPTS_VALUE) {
     830             :         /* No packets written yet, vc1_info isn't authoritative yet. */
     831             :         /* Assume inline sequence and entry headers. */
     832           0 :         packet_seq = packet_entry = 1;
     833           0 :         av_log(NULL, AV_LOG_WARNING,
     834             :                "moov atom written before any packets, unable to write correct "
     835             :                "dvc1 atom. Set the delay_moov flag to fix this.\n");
     836             :     }
     837             : 
     838           0 :     unescaped = av_mallocz(track->vos_len + AV_INPUT_BUFFER_PADDING_SIZE);
     839           0 :     if (!unescaped)
     840           0 :         return AVERROR(ENOMEM);
     841           0 :     start = find_next_marker(track->vos_data, end);
     842           0 :     for (next = start; next < end; start = next) {
     843             :         GetBitContext gb;
     844             :         int size;
     845           0 :         next = find_next_marker(start + 4, end);
     846           0 :         size = next - start - 4;
     847           0 :         if (size <= 0)
     848           0 :             continue;
     849           0 :         unescaped_size = vc1_unescape_buffer(start + 4, size, unescaped);
     850           0 :         init_get_bits(&gb, unescaped, 8 * unescaped_size);
     851           0 :         if (AV_RB32(start) == VC1_CODE_SEQHDR) {
     852           0 :             int profile = get_bits(&gb, 2);
     853           0 :             if (profile != PROFILE_ADVANCED) {
     854           0 :                 av_free(unescaped);
     855           0 :                 return AVERROR(ENOSYS);
     856             :             }
     857           0 :             seq_found = 1;
     858           0 :             level = get_bits(&gb, 3);
     859             :             /* chromaformat, frmrtq_postproc, bitrtq_postproc, postprocflag,
     860             :              * width, height */
     861           0 :             skip_bits_long(&gb, 2 + 3 + 5 + 1 + 2*12);
     862           0 :             skip_bits(&gb, 1); /* broadcast */
     863           0 :             interlace = get_bits1(&gb);
     864           0 :             skip_bits(&gb, 4); /* tfcntrflag, finterpflag, reserved, psf */
     865             :         }
     866             :     }
     867           0 :     if (!seq_found) {
     868           0 :         av_free(unescaped);
     869           0 :         return AVERROR(ENOSYS);
     870             :     }
     871             : 
     872           0 :     init_put_bits(&pbc, buf, 7);
     873             :     /* VC1DecSpecStruc */
     874           0 :     put_bits(&pbc, 4, 12); /* profile - advanced */
     875           0 :     put_bits(&pbc, 3, level);
     876           0 :     put_bits(&pbc, 1, 0); /* reserved */
     877             :     /* VC1AdvDecSpecStruc */
     878           0 :     put_bits(&pbc, 3, level);
     879           0 :     put_bits(&pbc, 1, 0); /* cbr */
     880           0 :     put_bits(&pbc, 6, 0); /* reserved */
     881           0 :     put_bits(&pbc, 1, !interlace); /* no interlace */
     882           0 :     put_bits(&pbc, 1, !packet_seq); /* no multiple seq */
     883           0 :     put_bits(&pbc, 1, !packet_entry); /* no multiple entry */
     884           0 :     put_bits(&pbc, 1, !slices); /* no slice code */
     885           0 :     put_bits(&pbc, 1, 0); /* no bframe */
     886           0 :     put_bits(&pbc, 1, 0); /* reserved */
     887             : 
     888             :     /* framerate */
     889           0 :     if (track->st->avg_frame_rate.num > 0 && track->st->avg_frame_rate.den > 0)
     890           0 :         put_bits32(&pbc, track->st->avg_frame_rate.num / track->st->avg_frame_rate.den);
     891             :     else
     892           0 :         put_bits32(&pbc, 0xffffffff);
     893             : 
     894           0 :     flush_put_bits(&pbc);
     895             : 
     896           0 :     av_free(unescaped);
     897             : 
     898           0 :     return 0;
     899             : }
     900             : 
     901           0 : static int mov_write_dvc1_tag(AVIOContext *pb, MOVTrack *track)
     902             : {
     903           0 :     uint8_t buf[7] = { 0 };
     904             :     int ret;
     905             : 
     906           0 :     if ((ret = mov_write_dvc1_structs(track, buf)) < 0)
     907           0 :         return ret;
     908             : 
     909           0 :     avio_wb32(pb, track->vos_len + 8 + sizeof(buf));
     910           0 :     ffio_wfourcc(pb, "dvc1");
     911           0 :     avio_write(pb, buf, sizeof(buf));
     912           0 :     avio_write(pb, track->vos_data, track->vos_len);
     913             : 
     914           0 :     return 0;
     915             : }
     916             : 
     917           0 : static int mov_write_glbl_tag(AVIOContext *pb, MOVTrack *track)
     918             : {
     919           0 :     avio_wb32(pb, track->vos_len + 8);
     920           0 :     ffio_wfourcc(pb, "glbl");
     921           0 :     avio_write(pb, track->vos_data, track->vos_len);
     922           0 :     return 8 + track->vos_len;
     923             : }
     924             : 
     925             : /**
     926             :  * Compute flags for 'lpcm' tag.
     927             :  * See CoreAudioTypes and AudioStreamBasicDescription at Apple.
     928             :  */
     929           8 : static int mov_get_lpcm_flags(enum AVCodecID codec_id)
     930             : {
     931           8 :     switch (codec_id) {
     932           0 :     case AV_CODEC_ID_PCM_F32BE:
     933             :     case AV_CODEC_ID_PCM_F64BE:
     934           0 :         return 11;
     935           0 :     case AV_CODEC_ID_PCM_F32LE:
     936             :     case AV_CODEC_ID_PCM_F64LE:
     937           0 :         return 9;
     938           0 :     case AV_CODEC_ID_PCM_U8:
     939           0 :         return 10;
     940           0 :     case AV_CODEC_ID_PCM_S16BE:
     941             :     case AV_CODEC_ID_PCM_S24BE:
     942             :     case AV_CODEC_ID_PCM_S32BE:
     943           0 :         return 14;
     944           0 :     case AV_CODEC_ID_PCM_S8:
     945             :     case AV_CODEC_ID_PCM_S16LE:
     946             :     case AV_CODEC_ID_PCM_S24LE:
     947             :     case AV_CODEC_ID_PCM_S32LE:
     948           0 :         return 12;
     949           8 :     default:
     950           8 :         return 0;
     951             :     }
     952             : }
     953             : 
     954       19596 : static int get_cluster_duration(MOVTrack *track, int cluster_idx)
     955             : {
     956             :     int64_t next_dts;
     957             : 
     958       19596 :     if (cluster_idx >= track->entry)
     959           0 :         return 0;
     960             : 
     961       19596 :     if (cluster_idx + 1 == track->entry)
     962         540 :         next_dts = track->track_duration + track->start_dts;
     963             :     else
     964       19056 :         next_dts = track->cluster[cluster_idx + 1].dts;
     965             : 
     966       19596 :     next_dts -= track->cluster[cluster_idx].dts;
     967             : 
     968       19596 :     av_assert0(next_dts >= 0);
     969       19596 :     av_assert0(next_dts <= INT_MAX);
     970             : 
     971       19596 :     return next_dts;
     972             : }
     973             : 
     974           4 : static int get_samples_per_packet(MOVTrack *track)
     975             : {
     976             :     int i, first_duration;
     977             : 
     978             : // return track->par->frame_size;
     979             : 
     980             :     /* use 1 for raw PCM */
     981           4 :     if (!track->audio_vbr)
     982           0 :         return 1;
     983             : 
     984             :     /* check to see if duration is constant for all clusters */
     985           4 :     if (!track->entry)
     986           0 :         return 0;
     987           4 :     first_duration = get_cluster_duration(track, 0);
     988        1872 :     for (i = 1; i < track->entry; i++) {
     989        1872 :         if (get_cluster_duration(track, i) != first_duration)
     990           4 :             return 0;
     991             :     }
     992           0 :     return first_duration;
     993             : }
     994             : 
     995          77 : static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
     996             : {
     997          77 :     int64_t pos = avio_tell(pb);
     998          77 :     int version = 0;
     999          77 :     uint32_t tag = track->tag;
    1000             : 
    1001          77 :     if (track->mode == MODE_MOV) {
    1002          28 :         if (track->timescale > UINT16_MAX) {
    1003           4 :             if (mov_get_lpcm_flags(track->par->codec_id))
    1004           0 :                 tag = AV_RL32("lpcm");
    1005           4 :             version = 2;
    1006          39 :         } else if (track->audio_vbr || mov_pcm_le_gt16(track->par->codec_id) ||
    1007          28 :                    mov_pcm_be_gt16(track->par->codec_id) ||
    1008          26 :                    track->par->codec_id == AV_CODEC_ID_ADPCM_MS ||
    1009          26 :                    track->par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV ||
    1010          13 :                    track->par->codec_id == AV_CODEC_ID_QDM2) {
    1011          11 :             version = 1;
    1012             :         }
    1013             :     }
    1014             : 
    1015          77 :     avio_wb32(pb, 0); /* size */
    1016          77 :     if (mov->encryption_scheme != MOV_ENC_NONE) {
    1017           0 :         ffio_wfourcc(pb, "enca");
    1018             :     } else {
    1019          77 :         avio_wl32(pb, tag); // store it byteswapped
    1020             :     }
    1021          77 :     avio_wb32(pb, 0); /* Reserved */
    1022          77 :     avio_wb16(pb, 0); /* Reserved */
    1023          77 :     avio_wb16(pb, 1); /* Data-reference index, XXX  == 1 */
    1024             : 
    1025             :     /* SoundDescription */
    1026          77 :     avio_wb16(pb, version); /* Version */
    1027          77 :     avio_wb16(pb, 0); /* Revision level */
    1028          77 :     avio_wb32(pb, 0); /* Reserved */
    1029             : 
    1030          77 :     if (version == 2) {
    1031           4 :         avio_wb16(pb, 3);
    1032           4 :         avio_wb16(pb, 16);
    1033           4 :         avio_wb16(pb, 0xfffe);
    1034           4 :         avio_wb16(pb, 0);
    1035           4 :         avio_wb32(pb, 0x00010000);
    1036           4 :         avio_wb32(pb, 72);
    1037           4 :         avio_wb64(pb, av_double2int(track->par->sample_rate));
    1038           4 :         avio_wb32(pb, track->par->channels);
    1039           4 :         avio_wb32(pb, 0x7F000000);
    1040           4 :         avio_wb32(pb, av_get_bits_per_sample(track->par->codec_id));
    1041           4 :         avio_wb32(pb, mov_get_lpcm_flags(track->par->codec_id));
    1042           4 :         avio_wb32(pb, track->sample_size);
    1043           4 :         avio_wb32(pb, get_samples_per_packet(track));
    1044             :     } else {
    1045          73 :         if (track->mode == MODE_MOV) {
    1046          24 :             avio_wb16(pb, track->par->channels);
    1047          48 :             if (track->par->codec_id == AV_CODEC_ID_PCM_U8 ||
    1048          24 :                 track->par->codec_id == AV_CODEC_ID_PCM_S8)
    1049           1 :                 avio_wb16(pb, 8); /* bits per sample */
    1050          23 :             else if (track->par->codec_id == AV_CODEC_ID_ADPCM_G726)
    1051           0 :                 avio_wb16(pb, track->par->bits_per_coded_sample);
    1052             :             else
    1053          23 :                 avio_wb16(pb, 16);
    1054          24 :             avio_wb16(pb, track->audio_vbr ? -2 : 0); /* compression ID */
    1055             :         } else { /* reserved for mp4/3gp */
    1056          98 :             if (track->par->codec_id == AV_CODEC_ID_FLAC ||
    1057          49 :                 track->par->codec_id == AV_CODEC_ID_OPUS) {
    1058           0 :                 avio_wb16(pb, track->par->channels);
    1059             :             } else {
    1060          49 :                 avio_wb16(pb, 2);
    1061             :             }
    1062          49 :             if (track->par->codec_id == AV_CODEC_ID_FLAC) {
    1063           0 :                 avio_wb16(pb, track->par->bits_per_raw_sample);
    1064             :             } else {
    1065          49 :                 avio_wb16(pb, 16);
    1066             :             }
    1067          49 :             avio_wb16(pb, 0);
    1068             :         }
    1069             : 
    1070          73 :         avio_wb16(pb, 0); /* packet size (= 0) */
    1071          73 :         if (track->par->codec_id == AV_CODEC_ID_OPUS)
    1072           0 :             avio_wb16(pb, 48000);
    1073             :         else
    1074         146 :             avio_wb16(pb, track->par->sample_rate <= UINT16_MAX ?
    1075          73 :                           track->par->sample_rate : 0);
    1076          73 :         avio_wb16(pb, 0); /* Reserved */
    1077             :     }
    1078             : 
    1079          77 :     if (version == 1) { /* SoundDescription V1 extended info */
    1080          22 :         if (mov_pcm_le_gt16(track->par->codec_id) ||
    1081          11 :             mov_pcm_be_gt16(track->par->codec_id))
    1082           2 :             avio_wb32(pb, 1); /*  must be 1 for  uncompressed formats */
    1083             :         else
    1084           9 :             avio_wb32(pb, track->par->frame_size); /* Samples per packet */
    1085          11 :         avio_wb32(pb, track->sample_size / track->par->channels); /* Bytes per packet */
    1086          11 :         avio_wb32(pb, track->sample_size); /* Bytes per frame */
    1087          11 :         avio_wb32(pb, 2); /* Bytes per sample */
    1088             :     }
    1089             : 
    1090         105 :     if (track->mode == MODE_MOV &&
    1091          53 :         (track->par->codec_id == AV_CODEC_ID_AAC           ||
    1092          50 :          track->par->codec_id == AV_CODEC_ID_AC3           ||
    1093          50 :          track->par->codec_id == AV_CODEC_ID_EAC3          ||
    1094          50 :          track->par->codec_id == AV_CODEC_ID_AMR_NB        ||
    1095          41 :          track->par->codec_id == AV_CODEC_ID_ALAC          ||
    1096          32 :          track->par->codec_id == AV_CODEC_ID_ADPCM_MS      ||
    1097          32 :          track->par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV ||
    1098          32 :          track->par->codec_id == AV_CODEC_ID_QDM2          ||
    1099          32 :          (mov_pcm_le_gt16(track->par->codec_id) && version==1) ||
    1100          18 :          (mov_pcm_be_gt16(track->par->codec_id) && version==1)))
    1101          14 :         mov_write_wave_tag(s, pb, track);
    1102          63 :     else if (track->tag == MKTAG('m','p','4','a'))
    1103          48 :         mov_write_esds_tag(pb, track);
    1104          15 :     else if (track->par->codec_id == AV_CODEC_ID_AMR_NB)
    1105           0 :         mov_write_amr_tag(pb, track);
    1106          15 :     else if (track->par->codec_id == AV_CODEC_ID_AC3)
    1107           0 :         mov_write_ac3_tag(pb, track);
    1108          15 :     else if (track->par->codec_id == AV_CODEC_ID_EAC3)
    1109           1 :         mov_write_eac3_tag(pb, track);
    1110          14 :     else if (track->par->codec_id == AV_CODEC_ID_ALAC)
    1111           0 :         mov_write_extradata_tag(pb, track);
    1112          14 :     else if (track->par->codec_id == AV_CODEC_ID_WMAPRO)
    1113           0 :         mov_write_wfex_tag(s, pb, track);
    1114          14 :     else if (track->par->codec_id == AV_CODEC_ID_FLAC)
    1115           0 :         mov_write_dfla_tag(pb, track);
    1116          14 :     else if (track->par->codec_id == AV_CODEC_ID_OPUS)
    1117           0 :         mov_write_dops_tag(pb, track);
    1118          14 :     else if (track->vos_len > 0)
    1119           0 :         mov_write_glbl_tag(pb, track);
    1120             : 
    1121          77 :     if (track->mode == MODE_MOV && track->par->codec_type == AVMEDIA_TYPE_AUDIO)
    1122          28 :         mov_write_chan_tag(s, pb, track);
    1123             : 
    1124          77 :     if (mov->encryption_scheme != MOV_ENC_NONE) {
    1125           0 :         ff_mov_cenc_write_sinf_tag(track, pb, mov->encryption_kid);
    1126             :     }
    1127             : 
    1128          77 :     return update_size(pb, pos);
    1129             : }
    1130             : 
    1131           0 : static int mov_write_d263_tag(AVIOContext *pb)
    1132             : {
    1133           0 :     avio_wb32(pb, 0xf); /* size */
    1134           0 :     ffio_wfourcc(pb, "d263");
    1135           0 :     ffio_wfourcc(pb, "FFMP");
    1136           0 :     avio_w8(pb, 0); /* decoder version */
    1137             :     /* FIXME use AVCodecContext level/profile, when encoder will set values */
    1138           0 :     avio_w8(pb, 0xa); /* level */
    1139           0 :     avio_w8(pb, 0); /* profile */
    1140           0 :     return 0xf;
    1141             : }
    1142             : 
    1143          49 : static int mov_write_avcc_tag(AVIOContext *pb, MOVTrack *track)
    1144             : {
    1145          49 :     int64_t pos = avio_tell(pb);
    1146             : 
    1147          49 :     avio_wb32(pb, 0);
    1148          49 :     ffio_wfourcc(pb, "avcC");
    1149          49 :     ff_isom_write_avcc(pb, track->vos_data, track->vos_len);
    1150          49 :     return update_size(pb, pos);
    1151             : }
    1152             : 
    1153           0 : static int mov_write_vpcc_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
    1154             : {
    1155           0 :     int64_t pos = avio_tell(pb);
    1156             : 
    1157           0 :     avio_wb32(pb, 0);
    1158           0 :     ffio_wfourcc(pb, "vpcC");
    1159           0 :     avio_w8(pb, 1); /* version */
    1160           0 :     avio_wb24(pb, 0); /* flags */
    1161           0 :     ff_isom_write_vpcc(s, pb, track->par);
    1162           0 :     return update_size(pb, pos);
    1163             : }
    1164             : 
    1165           1 : static int mov_write_hvcc_tag(AVIOContext *pb, MOVTrack *track)
    1166             : {
    1167           1 :     int64_t pos = avio_tell(pb);
    1168             : 
    1169           1 :     avio_wb32(pb, 0);
    1170           1 :     ffio_wfourcc(pb, "hvcC");
    1171           1 :     if (track->tag == MKTAG('h','v','c','1'))
    1172           0 :         ff_isom_write_hvcc(pb, track->vos_data, track->vos_len, 1);
    1173             :     else
    1174           1 :         ff_isom_write_hvcc(pb, track->vos_data, track->vos_len, 0);
    1175           1 :     return update_size(pb, pos);
    1176             : }
    1177             : 
    1178             : /* also used by all avid codecs (dv, imx, meridien) and their variants */
    1179          23 : static int mov_write_avid_tag(AVIOContext *pb, MOVTrack *track)
    1180             : {
    1181             :     int i;
    1182             :     int interlaced;
    1183             :     int cid;
    1184          23 :     int display_width = track->par->width;
    1185             : 
    1186          23 :     if (track->vos_data && track->vos_len > 0x29) {
    1187          46 :         if (ff_dnxhd_parse_header_prefix(track->vos_data) != 0) {
    1188             :             /* looks like a DNxHD bit stream */
    1189          23 :             interlaced = (track->vos_data[5] & 2);
    1190          23 :             cid = AV_RB32(track->vos_data + 0x28);
    1191             :         } else {
    1192           0 :             av_log(NULL, AV_LOG_WARNING, "Could not locate DNxHD bit stream in vos_data\n");
    1193           0 :             return 0;
    1194             :         }
    1195             :     } else {
    1196           0 :         av_log(NULL, AV_LOG_WARNING, "Could not locate DNxHD bit stream, vos_data too small\n");
    1197           0 :         return 0;
    1198             :     }
    1199             : 
    1200          23 :     avio_wb32(pb, 24); /* size */
    1201          23 :     ffio_wfourcc(pb, "ACLR");
    1202          23 :     ffio_wfourcc(pb, "ACLR");
    1203          23 :     ffio_wfourcc(pb, "0001");
    1204          46 :     if (track->par->color_range == AVCOL_RANGE_MPEG || /* Legal range (16-235) */
    1205          23 :         track->par->color_range == AVCOL_RANGE_UNSPECIFIED) {
    1206          23 :         avio_wb32(pb, 1); /* Corresponds to 709 in official encoder */
    1207             :     } else { /* Full range (0-255) */
    1208           0 :         avio_wb32(pb, 2); /* Corresponds to RGB in official encoder */
    1209             :     }
    1210          23 :     avio_wb32(pb, 0); /* unknown */
    1211             : 
    1212          23 :     if (track->tag == MKTAG('A','V','d','h')) {
    1213          12 :         avio_wb32(pb, 32);
    1214          12 :         ffio_wfourcc(pb, "ADHR");
    1215          12 :         ffio_wfourcc(pb, "0001");
    1216          12 :         avio_wb32(pb, cid);
    1217          12 :         avio_wb32(pb, 0); /* unknown */
    1218          12 :         avio_wb32(pb, 1); /* unknown */
    1219          12 :         avio_wb32(pb, 0); /* unknown */
    1220          12 :         avio_wb32(pb, 0); /* unknown */
    1221          12 :         return 0;
    1222             :     }
    1223             : 
    1224          11 :     avio_wb32(pb, 24); /* size */
    1225          11 :     ffio_wfourcc(pb, "APRG");
    1226          11 :     ffio_wfourcc(pb, "APRG");
    1227          11 :     ffio_wfourcc(pb, "0001");
    1228          11 :     avio_wb32(pb, 1); /* unknown */
    1229          11 :     avio_wb32(pb, 0); /* unknown */
    1230             : 
    1231          11 :     avio_wb32(pb, 120); /* size */
    1232          11 :     ffio_wfourcc(pb, "ARES");
    1233          11 :     ffio_wfourcc(pb, "ARES");
    1234          11 :     ffio_wfourcc(pb, "0001");
    1235          11 :     avio_wb32(pb, cid); /* dnxhd cid, some id ? */
    1236          11 :     if (   track->par->sample_aspect_ratio.num > 0
    1237           0 :         && track->par->sample_aspect_ratio.den > 0)
    1238           0 :         display_width = display_width * track->par->sample_aspect_ratio.num / track->par->sample_aspect_ratio.den;
    1239          11 :     avio_wb32(pb, display_width);
    1240             :     /* values below are based on samples created with quicktime and avid codecs */
    1241          11 :     if (interlaced) {
    1242          11 :         avio_wb32(pb, track->par->height / 2);
    1243          11 :         avio_wb32(pb, 2); /* unknown */
    1244          11 :         avio_wb32(pb, 0); /* unknown */
    1245          11 :         avio_wb32(pb, 4); /* unknown */
    1246             :     } else {
    1247           0 :         avio_wb32(pb, track->par->height);
    1248           0 :         avio_wb32(pb, 1); /* unknown */
    1249           0 :         avio_wb32(pb, 0); /* unknown */
    1250           0 :         if (track->par->height == 1080)
    1251           0 :             avio_wb32(pb, 5); /* unknown */
    1252             :         else
    1253           0 :             avio_wb32(pb, 6); /* unknown */
    1254             :     }
    1255             :     /* padding */
    1256         121 :     for (i = 0; i < 10; i++)
    1257         110 :         avio_wb64(pb, 0);
    1258             : 
    1259          11 :     return 0;
    1260             : }
    1261             : 
    1262           0 : static int mov_write_dpxe_tag(AVIOContext *pb, MOVTrack *track)
    1263             : {
    1264           0 :     avio_wb32(pb, 12);
    1265           0 :     ffio_wfourcc(pb, "DpxE");
    1266           0 :     if (track->par->extradata_size >= 12 &&
    1267           0 :         !memcmp(&track->par->extradata[4], "DpxE", 4)) {
    1268           0 :         avio_wb32(pb, track->par->extradata[11]);
    1269             :     } else {
    1270           0 :         avio_wb32(pb, 1);
    1271             :     }
    1272           0 :     return 0;
    1273             : }
    1274             : 
    1275           1 : static int mov_get_dv_codec_tag(AVFormatContext *s, MOVTrack *track)
    1276             : {
    1277             :     int tag;
    1278             : 
    1279           1 :     if (track->par->width == 720) { /* SD */
    1280           1 :         if (track->par->height == 480) { /* NTSC */
    1281           1 :             if  (track->par->format == AV_PIX_FMT_YUV422P) tag = MKTAG('d','v','5','n');
    1282           1 :             else                                            tag = MKTAG('d','v','c',' ');
    1283           0 :        }else if (track->par->format == AV_PIX_FMT_YUV422P) tag = MKTAG('d','v','5','p');
    1284           0 :         else if (track->par->format == AV_PIX_FMT_YUV420P) tag = MKTAG('d','v','c','p');
    1285           0 :         else                                                tag = MKTAG('d','v','p','p');
    1286           0 :     } else if (track->par->height == 720) { /* HD 720 line */
    1287           0 :         if  (track->st->time_base.den == 50)                tag = MKTAG('d','v','h','q');
    1288           0 :         else                                                tag = MKTAG('d','v','h','p');
    1289           0 :     } else if (track->par->height == 1080) { /* HD 1080 line */
    1290           0 :         if  (track->st->time_base.den == 25)                tag = MKTAG('d','v','h','5');
    1291           0 :         else                                                tag = MKTAG('d','v','h','6');
    1292             :     } else {
    1293           0 :         av_log(s, AV_LOG_ERROR, "unsupported height for dv codec\n");
    1294           0 :         return 0;
    1295             :     }
    1296             : 
    1297           1 :     return tag;
    1298             : }
    1299             : 
    1300          14 : static AVRational find_fps(AVFormatContext *s, AVStream *st)
    1301             : {
    1302          14 :     AVRational rate = st->avg_frame_rate;
    1303             : 
    1304             : #if FF_API_LAVF_AVCTX
    1305             :     FF_DISABLE_DEPRECATION_WARNINGS
    1306          14 :     rate = av_inv_q(st->codec->time_base);
    1307          14 :     if (av_timecode_check_frame_rate(rate) < 0) {
    1308           2 :         av_log(s, AV_LOG_DEBUG, "timecode: tbc=%d/%d invalid, fallback on %d/%d\n",
    1309             :                rate.num, rate.den, st->avg_frame_rate.num, st->avg_frame_rate.den);
    1310           2 :         rate = st->avg_frame_rate;
    1311             :     }
    1312             :     FF_ENABLE_DEPRECATION_WARNINGS
    1313             : #endif
    1314             : 
    1315          14 :     return rate;
    1316             : }
    1317             : 
    1318           1 : static int defined_frame_rate(AVFormatContext *s, AVStream *st)
    1319             : {
    1320           1 :     AVRational rational_framerate = find_fps(s, st);
    1321           1 :     int rate = 0;
    1322           1 :     if (rational_framerate.den != 0)
    1323           1 :         rate = av_q2d(rational_framerate);
    1324           1 :     return rate;
    1325             : }
    1326             : 
    1327           0 : static int mov_get_mpeg2_xdcam_codec_tag(AVFormatContext *s, MOVTrack *track)
    1328             : {
    1329           0 :     int tag = track->par->codec_tag;
    1330           0 :     int interlaced = track->par->field_order > AV_FIELD_PROGRESSIVE;
    1331           0 :     AVStream *st = track->st;
    1332           0 :     int rate = defined_frame_rate(s, st);
    1333             : 
    1334           0 :     if (!tag)
    1335           0 :         tag = MKTAG('m', '2', 'v', '1'); //fallback tag
    1336             : 
    1337           0 :     if (track->par->format == AV_PIX_FMT_YUV420P) {
    1338           0 :         if (track->par->width == 1280 && track->par->height == 720) {
    1339           0 :             if (!interlaced) {
    1340           0 :                 if      (rate == 24) tag = MKTAG('x','d','v','4');
    1341           0 :                 else if (rate == 25) tag = MKTAG('x','d','v','5');
    1342           0 :                 else if (rate == 30) tag = MKTAG('x','d','v','1');
    1343           0 :                 else if (rate == 50) tag = MKTAG('x','d','v','a');
    1344           0 :                 else if (rate == 60) tag = MKTAG('x','d','v','9');
    1345             :             }
    1346           0 :         } else if (track->par->width == 1440 && track->par->height == 1080) {
    1347           0 :             if (!interlaced) {
    1348           0 :                 if      (rate == 24) tag = MKTAG('x','d','v','6');
    1349           0 :                 else if (rate == 25) tag = MKTAG('x','d','v','7');
    1350           0 :                 else if (rate == 30) tag = MKTAG('x','d','v','8');
    1351             :             } else {
    1352           0 :                 if      (rate == 25) tag = MKTAG('x','d','v','3');
    1353           0 :                 else if (rate == 30) tag = MKTAG('x','d','v','2');
    1354             :             }
    1355           0 :         } else if (track->par->width == 1920 && track->par->height == 1080) {
    1356           0 :             if (!interlaced) {
    1357           0 :                 if      (rate == 24) tag = MKTAG('x','d','v','d');
    1358           0 :                 else if (rate == 25) tag = MKTAG('x','d','v','e');
    1359           0 :                 else if (rate == 30) tag = MKTAG('x','d','v','f');
    1360             :             } else {
    1361           0 :                 if      (rate == 25) tag = MKTAG('x','d','v','c');
    1362           0 :                 else if (rate == 30) tag = MKTAG('x','d','v','b');
    1363             :             }
    1364             :         }
    1365           0 :     } else if (track->par->format == AV_PIX_FMT_YUV422P) {
    1366           0 :         if (track->par->width == 1280 && track->par->height == 720) {
    1367           0 :             if (!interlaced) {
    1368           0 :                 if      (rate == 24) tag = MKTAG('x','d','5','4');
    1369           0 :                 else if (rate == 25) tag = MKTAG('x','d','5','5');
    1370           0 :                 else if (rate == 30) tag = MKTAG('x','d','5','1');
    1371           0 :                 else if (rate == 50) tag = MKTAG('x','d','5','a');
    1372           0 :                 else if (rate == 60) tag = MKTAG('x','d','5','9');
    1373             :             }
    1374           0 :         } else if (track->par->width == 1920 && track->par->height == 1080) {
    1375           0 :             if (!interlaced) {
    1376           0 :                 if      (rate == 24) tag = MKTAG('x','d','5','d');
    1377           0 :                 else if (rate == 25) tag = MKTAG('x','d','5','e');
    1378           0 :                 else if (rate == 30) tag = MKTAG('x','d','5','f');
    1379             :             } else {
    1380           0 :                 if      (rate == 25) tag = MKTAG('x','d','5','c');
    1381           0 :                 else if (rate == 30) tag = MKTAG('x','d','5','b');
    1382             :             }
    1383             :         }
    1384             :     }
    1385             : 
    1386           0 :     return tag;
    1387             : }
    1388             : 
    1389           1 : static int mov_get_h264_codec_tag(AVFormatContext *s, MOVTrack *track)
    1390             : {
    1391           1 :     int tag = track->par->codec_tag;
    1392           1 :     int interlaced = track->par->field_order > AV_FIELD_PROGRESSIVE;
    1393           1 :     AVStream *st = track->st;
    1394           1 :     int rate = defined_frame_rate(s, st);
    1395             : 
    1396           1 :     if (!tag)
    1397           0 :         tag = MKTAG('a', 'v', 'c', 'i'); //fallback tag
    1398             : 
    1399           1 :     if (track->par->format == AV_PIX_FMT_YUV420P10) {
    1400           0 :         if (track->par->width == 960 && track->par->height == 720) {
    1401           0 :             if (!interlaced) {
    1402           0 :                 if      (rate == 24) tag = MKTAG('a','i','5','p');
    1403           0 :                 else if (rate == 25) tag = MKTAG('a','i','5','q');
    1404           0 :                 else if (rate == 30) tag = MKTAG('a','i','5','p');
    1405           0 :                 else if (rate == 50) tag = MKTAG('a','i','5','q');
    1406           0 :                 else if (rate == 60) tag = MKTAG('a','i','5','p');
    1407             :             }
    1408           0 :         } else if (track->par->width == 1440 && track->par->height == 1080) {
    1409           0 :             if (!interlaced) {
    1410           0 :                 if      (rate == 24) tag = MKTAG('a','i','5','3');
    1411           0 :                 else if (rate == 25) tag = MKTAG('a','i','5','2');
    1412           0 :                 else if (rate == 30) tag = MKTAG('a','i','5','3');
    1413             :             } else {
    1414           0 :                 if      (rate == 50) tag = MKTAG('a','i','5','5');
    1415           0 :                 else if (rate == 60) tag = MKTAG('a','i','5','6');
    1416             :             }
    1417             :         }
    1418           1 :     } else if (track->par->format == AV_PIX_FMT_YUV422P10) {
    1419           0 :         if (track->par->width == 1280 && track->par->height == 720) {
    1420           0 :             if (!interlaced) {
    1421           0 :                 if      (rate == 24) tag = MKTAG('a','i','1','p');
    1422           0 :                 else if (rate == 25) tag = MKTAG('a','i','1','q');
    1423           0 :                 else if (rate == 30) tag = MKTAG('a','i','1','p');
    1424           0 :                 else if (rate == 50) tag = MKTAG('a','i','1','q');
    1425           0 :                 else if (rate == 60) tag = MKTAG('a','i','1','p');
    1426             :             }
    1427           0 :         } else if (track->par->width == 1920 && track->par->height == 1080) {
    1428           0 :             if (!interlaced) {
    1429           0 :                 if      (rate == 24) tag = MKTAG('a','i','1','3');
    1430           0 :                 else if (rate == 25) tag = MKTAG('a','i','1','2');
    1431           0 :                 else if (rate == 30) tag = MKTAG('a','i','1','3');
    1432             :             } else {
    1433           0 :                 if      (rate == 25) tag = MKTAG('a','i','1','5');
    1434           0 :                 else if (rate == 50) tag = MKTAG('a','i','1','5');
    1435           0 :                 else if (rate == 60) tag = MKTAG('a','i','1','6');
    1436             :             }
    1437           0 :         } else if (   track->par->width == 4096 && track->par->height == 2160
    1438           0 :                    || track->par->width == 3840 && track->par->height == 2160
    1439           0 :                    || track->par->width == 2048 && track->par->height == 1080) {
    1440           0 :             tag = MKTAG('a','i','v','x');
    1441             :         }
    1442             :     }
    1443             : 
    1444           1 :     return tag;
    1445             : }
    1446             : 
    1447             : static const struct {
    1448             :     enum AVPixelFormat pix_fmt;
    1449             :     uint32_t tag;
    1450             :     unsigned bps;
    1451             : } mov_pix_fmt_tags[] = {
    1452             :     { AV_PIX_FMT_YUYV422, MKTAG('y','u','v','2'),  0 },
    1453             :     { AV_PIX_FMT_YUYV422, MKTAG('y','u','v','s'),  0 },
    1454             :     { AV_PIX_FMT_UYVY422, MKTAG('2','v','u','y'),  0 },
    1455             :     { AV_PIX_FMT_RGB555BE,MKTAG('r','a','w',' '), 16 },
    1456             :     { AV_PIX_FMT_RGB555LE,MKTAG('L','5','5','5'), 16 },
    1457             :     { AV_PIX_FMT_RGB565LE,MKTAG('L','5','6','5'), 16 },
    1458             :     { AV_PIX_FMT_RGB565BE,MKTAG('B','5','6','5'), 16 },
    1459             :     { AV_PIX_FMT_GRAY16BE,MKTAG('b','1','6','g'), 16 },
    1460             :     { AV_PIX_FMT_RGB24,   MKTAG('r','a','w',' '), 24 },
    1461             :     { AV_PIX_FMT_BGR24,   MKTAG('2','4','B','G'), 24 },
    1462             :     { AV_PIX_FMT_ARGB,    MKTAG('r','a','w',' '), 32 },
    1463             :     { AV_PIX_FMT_BGRA,    MKTAG('B','G','R','A'), 32 },
    1464             :     { AV_PIX_FMT_RGBA,    MKTAG('R','G','B','A'), 32 },
    1465             :     { AV_PIX_FMT_ABGR,    MKTAG('A','B','G','R'), 32 },
    1466             :     { AV_PIX_FMT_RGB48BE, MKTAG('b','4','8','r'), 48 },
    1467             : };
    1468             : 
    1469          23 : static int mov_get_dnxhd_codec_tag(AVFormatContext *s, MOVTrack *track)
    1470             : {
    1471          23 :   int tag = MKTAG('A','V','d','n');
    1472          46 :   if (track->par->profile != FF_PROFILE_UNKNOWN &&
    1473          23 :       track->par->profile != FF_PROFILE_DNXHD)
    1474          12 :       tag = MKTAG('A','V','d','h');
    1475          23 :   return tag;
    1476             : }
    1477             : 
    1478          12 : static int mov_get_rawvideo_codec_tag(AVFormatContext *s, MOVTrack *track)
    1479             : {
    1480          12 :     int tag = track->par->codec_tag;
    1481             :     int i;
    1482             :     enum AVPixelFormat pix_fmt;
    1483             : 
    1484         192 :     for (i = 0; i < FF_ARRAY_ELEMS(mov_pix_fmt_tags); i++) {
    1485         180 :         if (track->par->format == mov_pix_fmt_tags[i].pix_fmt) {
    1486          12 :             tag = mov_pix_fmt_tags[i].tag;
    1487          12 :             track->par->bits_per_coded_sample = mov_pix_fmt_tags[i].bps;
    1488          12 :             if (track->par->codec_tag == mov_pix_fmt_tags[i].tag)
    1489           0 :                 break;
    1490             :         }
    1491             :     }
    1492             : 
    1493          12 :     pix_fmt = avpriv_find_pix_fmt(avpriv_pix_fmt_bps_mov,
    1494          12 :                                   track->par->bits_per_coded_sample);
    1495          12 :     if (tag == MKTAG('r','a','w',' ') &&
    1496           0 :         track->par->format != pix_fmt &&
    1497           0 :         track->par->format != AV_PIX_FMT_GRAY8 &&
    1498           0 :         track->par->format != AV_PIX_FMT_NONE)
    1499           0 :         av_log(s, AV_LOG_ERROR, "%s rawvideo cannot be written to mov, output file will be unreadable\n",
    1500           0 :                av_get_pix_fmt_name(track->par->format));
    1501          12 :     return tag;
    1502             : }
    1503             : 
    1504         117 : static int mov_get_codec_tag(AVFormatContext *s, MOVTrack *track)
    1505             : {
    1506         117 :     int tag = track->par->codec_tag;
    1507             : 
    1508         204 :     if (!tag || (s->strict_std_compliance >= FF_COMPLIANCE_NORMAL &&
    1509         173 :                  (track->par->codec_id == AV_CODEC_ID_DVVIDEO ||
    1510         160 :                   track->par->codec_id == AV_CODEC_ID_RAWVIDEO ||
    1511         148 :                   track->par->codec_id == AV_CODEC_ID_H263 ||
    1512         147 :                   track->par->codec_id == AV_CODEC_ID_H264 ||
    1513         123 :                   track->par->codec_id == AV_CODEC_ID_DNXHD ||
    1514         100 :                   track->par->codec_id == AV_CODEC_ID_MPEG2VIDEO ||
    1515          50 :                   av_get_bits_per_sample(track->par->codec_id)))) { // pcm audio
    1516          46 :         if (track->par->codec_id == AV_CODEC_ID_DVVIDEO)
    1517           1 :             tag = mov_get_dv_codec_tag(s, track);
    1518          45 :         else if (track->par->codec_id == AV_CODEC_ID_RAWVIDEO)
    1519          12 :             tag = mov_get_rawvideo_codec_tag(s, track);
    1520          33 :         else if (track->par->codec_id == AV_CODEC_ID_MPEG2VIDEO)
    1521           0 :             tag = mov_get_mpeg2_xdcam_codec_tag(s, track);
    1522          33 :         else if (track->par->codec_id == AV_CODEC_ID_H264)
    1523           1 :             tag = mov_get_h264_codec_tag(s, track);
    1524          32 :         else if (track->par->codec_id == AV_CODEC_ID_DNXHD)
    1525          23 :             tag = mov_get_dnxhd_codec_tag(s, track);
    1526           9 :         else if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
    1527           0 :             tag = ff_codec_get_tag(ff_codec_movvideo_tags, track->par->codec_id);
    1528           0 :             if (!tag) { // if no mac fcc found, try with Microsoft tags
    1529           0 :                 tag = ff_codec_get_tag(ff_codec_bmp_tags, track->par->codec_id);
    1530           0 :                 if (tag)
    1531           0 :                     av_log(s, AV_LOG_WARNING, "Using MS style video codec tag, "
    1532             :                            "the file may be unplayable!\n");
    1533             :             }
    1534           9 :         } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) {
    1535           9 :             tag = ff_codec_get_tag(ff_codec_movaudio_tags, track->par->codec_id);
    1536           9 :             if (!tag) { // if no mac fcc found, try with Microsoft tags
    1537           0 :                 int ms_tag = ff_codec_get_tag(ff_codec_wav_tags, track->par->codec_id);
    1538           0 :                 if (ms_tag) {
    1539           0 :                     tag = MKTAG('m', 's', ((ms_tag >> 8) & 0xff), (ms_tag & 0xff));
    1540           0 :                     av_log(s, AV_LOG_WARNING, "Using MS style audio codec tag, "
    1541             :                            "the file may be unplayable!\n");
    1542             :                 }
    1543             :             }
    1544           0 :         } else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE)
    1545           0 :             tag = ff_codec_get_tag(ff_codec_movsubtitle_tags, track->par->codec_id);
    1546             :     }
    1547             : 
    1548         117 :     return tag;
    1549             : }
    1550             : 
    1551         188 : static int mov_find_codec_tag(AVFormatContext *s, MOVTrack *track)
    1552             : {
    1553             :     int tag;
    1554             : 
    1555         188 :     if (track->mode == MODE_MP4 || track->mode == MODE_PSP)
    1556          65 :         tag = track->par->codec_tag;
    1557         123 :     else if (track->mode == MODE_ISM)
    1558           5 :         tag = track->par->codec_tag;
    1559         118 :     else if (track->mode == MODE_IPOD) {
    1560           2 :         if (!av_match_ext(s->url, "m4a") &&
    1561           2 :             !av_match_ext(s->url, "m4v") &&
    1562           1 :             !av_match_ext(s->url, "m4b"))
    1563           1 :             av_log(s, AV_LOG_WARNING, "Warning, extension is not .m4a nor .m4v "
    1564             :                    "Quicktime/Ipod might not play the file\n");
    1565           1 :         tag = track->par->codec_tag;
    1566         117 :     } else if (track->mode & MODE_3GP)
    1567           0 :         tag = track->par->codec_tag;
    1568         117 :     else if (track->mode == MODE_F4V)
    1569           0 :         tag = track->par->codec_tag;
    1570             :     else
    1571         117 :         tag = mov_get_codec_tag(s, track);
    1572             : 
    1573         188 :     return tag;
    1574             : }
    1575             : 
    1576             : /** Write uuid atom.
    1577             :  * Needed to make file play in iPods running newest firmware
    1578             :  * goes after avcC atom in moov.trak.mdia.minf.stbl.stsd.avc1
    1579             :  */
    1580           0 : static int mov_write_uuid_tag_ipod(AVIOContext *pb)
    1581             : {
    1582           0 :     avio_wb32(pb, 28);
    1583           0 :     ffio_wfourcc(pb, "uuid");
    1584           0 :     avio_wb32(pb, 0x6b6840f2);
    1585           0 :     avio_wb32(pb, 0x5f244fc5);
    1586           0 :     avio_wb32(pb, 0xba39a51b);
    1587           0 :     avio_wb32(pb, 0xcf0323f3);
    1588           0 :     avio_wb32(pb, 0x0);
    1589           0 :     return 28;
    1590             : }
    1591             : 
    1592             : static const uint16_t fiel_data[] = {
    1593             :     0x0000, 0x0100, 0x0201, 0x0206, 0x0209, 0x020e
    1594             : };
    1595             : 
    1596          62 : static int mov_write_fiel_tag(AVIOContext *pb, MOVTrack *track, int field_order)
    1597             : {
    1598          62 :     unsigned mov_field_order = 0;
    1599          62 :     if (field_order < FF_ARRAY_ELEMS(fiel_data))
    1600          62 :         mov_field_order = fiel_data[field_order];
    1601             :     else
    1602           0 :         return 0;
    1603          62 :     avio_wb32(pb, 10);
    1604          62 :     ffio_wfourcc(pb, "fiel");
    1605          62 :     avio_wb16(pb, mov_field_order);
    1606          62 :     return 10;
    1607             : }
    1608             : 
    1609           1 : static int mov_write_subtitle_tag(AVIOContext *pb, MOVTrack *track)
    1610             : {
    1611           1 :     int64_t pos = avio_tell(pb);
    1612           1 :     avio_wb32(pb, 0);    /* size */
    1613           1 :     avio_wl32(pb, track->tag); // store it byteswapped
    1614           1 :     avio_wb32(pb, 0);    /* Reserved */
    1615           1 :     avio_wb16(pb, 0);    /* Reserved */
    1616           1 :     avio_wb16(pb, 1);    /* Data-reference index */
    1617             : 
    1618           1 :     if (track->par->codec_id == AV_CODEC_ID_DVD_SUBTITLE)
    1619           0 :         mov_write_esds_tag(pb, track);
    1620           1 :     else if (track->par->extradata_size)
    1621           1 :         avio_write(pb, track->par->extradata, track->par->extradata_size);
    1622             : 
    1623           1 :     return update_size(pb, pos);
    1624             : }
    1625             : 
    1626           0 : static int mov_write_st3d_tag(AVIOContext *pb, AVStereo3D *stereo_3d)
    1627             : {
    1628             :     int8_t stereo_mode;
    1629             : 
    1630           0 :     if (stereo_3d->flags != 0) {
    1631           0 :         av_log(pb, AV_LOG_WARNING, "Unsupported stereo_3d flags %x. st3d not written.\n", stereo_3d->flags);
    1632           0 :         return 0;
    1633             :     }
    1634             : 
    1635           0 :     switch (stereo_3d->type) {
    1636           0 :     case AV_STEREO3D_2D:
    1637           0 :         stereo_mode = 0;
    1638           0 :         break;
    1639           0 :     case AV_STEREO3D_TOPBOTTOM:
    1640           0 :         stereo_mode = 1;
    1641           0 :         break;
    1642           0 :     case AV_STEREO3D_SIDEBYSIDE:
    1643           0 :         stereo_mode = 2;
    1644           0 :         break;
    1645           0 :     default:
    1646           0 :         av_log(pb, AV_LOG_WARNING, "Unsupported stereo_3d type %s. st3d not written.\n", av_stereo3d_type_name(stereo_3d->type));
    1647           0 :         return 0;
    1648             :     }
    1649           0 :     avio_wb32(pb, 13); /* size */
    1650           0 :     ffio_wfourcc(pb, "st3d");
    1651           0 :     avio_wb32(pb, 0); /* version = 0 & flags = 0 */
    1652           0 :     avio_w8(pb, stereo_mode);
    1653           0 :     return 13;
    1654             : }
    1655             : 
    1656           0 : static int mov_write_sv3d_tag(AVFormatContext *s, AVIOContext *pb, AVSphericalMapping *spherical_mapping)
    1657             : {
    1658             :     int64_t sv3d_pos, svhd_pos, proj_pos;
    1659           0 :     const char* metadata_source = s->flags & AVFMT_FLAG_BITEXACT ? "Lavf" : LIBAVFORMAT_IDENT;
    1660             : 
    1661           0 :     if (spherical_mapping->projection != AV_SPHERICAL_EQUIRECTANGULAR &&
    1662           0 :         spherical_mapping->projection != AV_SPHERICAL_EQUIRECTANGULAR_TILE &&
    1663           0 :         spherical_mapping->projection != AV_SPHERICAL_CUBEMAP) {
    1664           0 :         av_log(pb, AV_LOG_WARNING, "Unsupported projection %d. sv3d not written.\n", spherical_mapping->projection);
    1665           0 :         return 0;
    1666             :     }
    1667             : 
    1668           0 :     sv3d_pos = avio_tell(pb);
    1669           0 :     avio_wb32(pb, 0);  /* size */
    1670           0 :     ffio_wfourcc(pb, "sv3d");
    1671             : 
    1672           0 :     svhd_pos = avio_tell(pb);
    1673           0 :     avio_wb32(pb, 0);  /* size */
    1674           0 :     ffio_wfourcc(pb, "svhd");
    1675           0 :     avio_wb32(pb, 0); /* version = 0 & flags = 0 */
    1676           0 :     avio_put_str(pb, metadata_source);
    1677           0 :     update_size(pb, svhd_pos);
    1678             : 
    1679           0 :     proj_pos = avio_tell(pb);
    1680           0 :     avio_wb32(pb, 0); /* size */
    1681           0 :     ffio_wfourcc(pb, "proj");
    1682             : 
    1683           0 :     avio_wb32(pb, 24); /* size */
    1684           0 :     ffio_wfourcc(pb, "prhd");
    1685           0 :     avio_wb32(pb, 0); /* version = 0 & flags = 0 */
    1686           0 :     avio_wb32(pb, spherical_mapping->yaw);
    1687           0 :     avio_wb32(pb, spherical_mapping->pitch);
    1688           0 :     avio_wb32(pb, spherical_mapping->roll);
    1689             : 
    1690           0 :     switch (spherical_mapping->projection) {
    1691           0 :     case AV_SPHERICAL_EQUIRECTANGULAR:
    1692             :     case AV_SPHERICAL_EQUIRECTANGULAR_TILE:
    1693           0 :         avio_wb32(pb, 28);    /* size */
    1694           0 :         ffio_wfourcc(pb, "equi");
    1695           0 :         avio_wb32(pb, 0); /* version = 0 & flags = 0 */
    1696           0 :         avio_wb32(pb, spherical_mapping->bound_top);
    1697           0 :         avio_wb32(pb, spherical_mapping->bound_bottom);
    1698           0 :         avio_wb32(pb, spherical_mapping->bound_left);
    1699           0 :         avio_wb32(pb, spherical_mapping->bound_right);
    1700           0 :         break;
    1701           0 :     case AV_SPHERICAL_CUBEMAP:
    1702           0 :         avio_wb32(pb, 20);    /* size */
    1703           0 :         ffio_wfourcc(pb, "cbmp");
    1704           0 :         avio_wb32(pb, 0); /* version = 0 & flags = 0 */
    1705           0 :         avio_wb32(pb, 0); /* layout */
    1706           0 :         avio_wb32(pb, spherical_mapping->padding); /* padding */
    1707           0 :         break;
    1708             :     }
    1709           0 :     update_size(pb, proj_pos);
    1710             : 
    1711           0 :     return update_size(pb, sv3d_pos);
    1712             : }
    1713             : 
    1714           0 : static int mov_write_clap_tag(AVIOContext *pb, MOVTrack *track)
    1715             : {
    1716           0 :     avio_wb32(pb, 40);
    1717           0 :     ffio_wfourcc(pb, "clap");
    1718           0 :     avio_wb32(pb, track->par->width); /* apertureWidth_N */
    1719           0 :     avio_wb32(pb, 1); /* apertureWidth_D (= 1) */
    1720           0 :     avio_wb32(pb, track->height); /* apertureHeight_N */
    1721           0 :     avio_wb32(pb, 1); /* apertureHeight_D (= 1) */
    1722           0 :     avio_wb32(pb, 0); /* horizOff_N (= 0) */
    1723           0 :     avio_wb32(pb, 1); /* horizOff_D (= 1) */
    1724           0 :     avio_wb32(pb, 0); /* vertOff_N (= 0) */
    1725           0 :     avio_wb32(pb, 1); /* vertOff_D (= 1) */
    1726           0 :     return 40;
    1727             : }
    1728             : 
    1729           3 : static int mov_write_pasp_tag(AVIOContext *pb, MOVTrack *track)
    1730             : {
    1731             :     AVRational sar;
    1732           3 :     av_reduce(&sar.num, &sar.den, track->par->sample_aspect_ratio.num,
    1733           3 :               track->par->sample_aspect_ratio.den, INT_MAX);
    1734             : 
    1735           3 :     avio_wb32(pb, 16);
    1736           3 :     ffio_wfourcc(pb, "pasp");
    1737           3 :     avio_wb32(pb, sar.num);
    1738           3 :     avio_wb32(pb, sar.den);
    1739           3 :     return 16;
    1740             : }
    1741             : 
    1742           0 : static int mov_write_gama_tag(AVIOContext *pb, MOVTrack *track, double gamma)
    1743             : {
    1744           0 :     uint32_t gama = 0;
    1745           0 :     if (gamma <= 0.0)
    1746             :     {
    1747           0 :         gamma = avpriv_get_gamma_from_trc(track->par->color_trc);
    1748             :     }
    1749           0 :     av_log(pb, AV_LOG_DEBUG, "gamma value %g\n", gamma);
    1750             : 
    1751           0 :     if (gamma > 1e-6) {
    1752           0 :         gama = (uint32_t)lrint((double)(1<<16) * gamma);
    1753           0 :         av_log(pb, AV_LOG_DEBUG, "writing gama value %"PRId32"\n", gama);
    1754             : 
    1755           0 :         av_assert0(track->mode == MODE_MOV);
    1756           0 :         avio_wb32(pb, 12);
    1757           0 :         ffio_wfourcc(pb, "gama");
    1758           0 :         avio_wb32(pb, gama);
    1759           0 :         return 12;
    1760             :     }
    1761             :     else {
    1762           0 :         av_log(pb, AV_LOG_WARNING, "gamma value unknown, unable to write gama atom\n");
    1763             :     }
    1764           0 :     return 0;
    1765             : }
    1766             : 
    1767           4 : static int mov_write_colr_tag(AVIOContext *pb, MOVTrack *track)
    1768             : {
    1769             :     // Ref (MOV): https://developer.apple.com/library/mac/technotes/tn2162/_index.html#//apple_ref/doc/uid/DTS40013070-CH1-TNTAG9
    1770             :     // Ref (MP4): ISO/IEC 14496-12:2012
    1771             : 
    1772           8 :     if (track->par->color_primaries == AVCOL_PRI_UNSPECIFIED &&
    1773           8 :         track->par->color_trc == AVCOL_TRC_UNSPECIFIED &&
    1774           4 :         track->par->color_space == AVCOL_SPC_UNSPECIFIED) {
    1775           4 :         if ((track->par->width >= 1920 && track->par->height >= 1080)
    1776           0 :           || (track->par->width == 1280 && track->par->height == 720)) {
    1777           4 :             av_log(NULL, AV_LOG_WARNING, "color primaries unspecified, assuming bt709\n");
    1778           4 :             track->par->color_primaries = AVCOL_PRI_BT709;
    1779           0 :         } else if (track->par->width == 720 && track->height == 576) {
    1780           0 :             av_log(NULL, AV_LOG_WARNING, "color primaries unspecified, assuming bt470bg\n");
    1781           0 :             track->par->color_primaries = AVCOL_PRI_BT470BG;
    1782           0 :         } else if (track->par->width == 720 &&
    1783           0 :                    (track->height == 486 || track->height == 480)) {
    1784           0 :             av_log(NULL, AV_LOG_WARNING, "color primaries unspecified, assuming smpte170\n");
    1785           0 :             track->par->color_primaries = AVCOL_PRI_SMPTE170M;
    1786             :         } else {
    1787           0 :             av_log(NULL, AV_LOG_WARNING, "color primaries unspecified, unable to assume anything\n");
    1788             :         }
    1789           4 :         switch (track->par->color_primaries) {
    1790           4 :         case AVCOL_PRI_BT709:
    1791           4 :             track->par->color_trc = AVCOL_TRC_BT709;
    1792           4 :             track->par->color_space = AVCOL_SPC_BT709;
    1793           4 :             break;
    1794           0 :         case AVCOL_PRI_SMPTE170M:
    1795             :         case AVCOL_PRI_BT470BG:
    1796           0 :             track->par->color_trc = AVCOL_TRC_BT709;
    1797           0 :             track->par->color_space = AVCOL_SPC_SMPTE170M;
    1798           0 :             break;
    1799             :         }
    1800             :     }
    1801             : 
    1802             :     /* We should only ever be called by MOV or MP4. */
    1803           4 :     av_assert0(track->mode == MODE_MOV || track->mode == MODE_MP4);
    1804             : 
    1805           4 :     avio_wb32(pb, 18 + (track->mode == MODE_MP4));
    1806           4 :     ffio_wfourcc(pb, "colr");
    1807           4 :     if (track->mode == MODE_MP4)
    1808           0 :         ffio_wfourcc(pb, "nclx");
    1809             :     else
    1810           4 :         ffio_wfourcc(pb, "nclc");
    1811           4 :     switch (track->par->color_primaries) {
    1812           4 :     case AVCOL_PRI_BT709:     avio_wb16(pb, 1); break;
    1813           0 :     case AVCOL_PRI_BT470BG:   avio_wb16(pb, 5); break;
    1814           0 :     case AVCOL_PRI_SMPTE170M:
    1815           0 :     case AVCOL_PRI_SMPTE240M: avio_wb16(pb, 6); break;
    1816           0 :     case AVCOL_PRI_BT2020:    avio_wb16(pb, 9); break;
    1817           0 :     case AVCOL_PRI_SMPTE431:  avio_wb16(pb, 11); break;
    1818           0 :     case AVCOL_PRI_SMPTE432:  avio_wb16(pb, 12); break;
    1819           0 :     default:                  avio_wb16(pb, 2);
    1820             :     }
    1821           4 :     switch (track->par->color_trc) {
    1822           4 :     case AVCOL_TRC_BT709:        avio_wb16(pb, 1); break;
    1823           0 :     case AVCOL_TRC_SMPTE170M:    avio_wb16(pb, 1); break; // remapped
    1824           0 :     case AVCOL_TRC_SMPTE240M:    avio_wb16(pb, 7); break;
    1825           0 :     case AVCOL_TRC_SMPTEST2084:  avio_wb16(pb, 16); break;
    1826           0 :     case AVCOL_TRC_SMPTE428:     avio_wb16(pb, 17); break;
    1827           0 :     case AVCOL_TRC_ARIB_STD_B67: avio_wb16(pb, 18); break;
    1828           0 :     default:                     avio_wb16(pb, 2);
    1829             :     }
    1830           4 :     switch (track->par->color_space) {
    1831           4 :     case AVCOL_SPC_BT709:      avio_wb16(pb, 1); break;
    1832           0 :     case AVCOL_SPC_BT470BG:
    1833           0 :     case AVCOL_SPC_SMPTE170M:  avio_wb16(pb, 6); break;
    1834           0 :     case AVCOL_SPC_SMPTE240M:  avio_wb16(pb, 7); break;
    1835           0 :     case AVCOL_SPC_BT2020_NCL: avio_wb16(pb, 9); break;
    1836           0 :     default:                   avio_wb16(pb, 2);
    1837             :     }
    1838             : 
    1839           4 :     if (track->mode == MODE_MP4) {
    1840           0 :         int full_range = track->par->color_range == AVCOL_RANGE_JPEG;
    1841           0 :         avio_w8(pb, full_range << 7);
    1842           0 :         return 19;
    1843             :     } else {
    1844           4 :         return 18;
    1845             :     }
    1846             : }
    1847             : 
    1848         156 : static void find_compressor(char * compressor_name, int len, MOVTrack *track)
    1849             : {
    1850             :     AVDictionaryEntry *encoder;
    1851         313 :     int xdcam_res =  (track->par->width == 1280 && track->par->height == 720)
    1852         155 :                   || (track->par->width == 1440 && track->par->height == 1080)
    1853         311 :                   || (track->par->width == 1920 && track->par->height == 1080);
    1854             : 
    1855         254 :     if (track->mode == MODE_MOV &&
    1856          98 :         (encoder = av_dict_get(track->st->metadata, "encoder", NULL, 0))) {
    1857          97 :         av_strlcpy(compressor_name, encoder->value, 32);
    1858          59 :     } else if (track->par->codec_id == AV_CODEC_ID_MPEG2VIDEO && xdcam_res) {
    1859           0 :         int interlaced = track->par->field_order > AV_FIELD_PROGRESSIVE;
    1860           0 :         AVStream *st = track->st;
    1861           0 :         int rate = defined_frame_rate(NULL, st);
    1862           0 :         av_strlcatf(compressor_name, len, "XDCAM");
    1863           0 :         if (track->par->format == AV_PIX_FMT_YUV422P) {
    1864           0 :             av_strlcatf(compressor_name, len, " HD422");
    1865           0 :         } else if(track->par->width == 1440) {
    1866           0 :             av_strlcatf(compressor_name, len, " HD");
    1867             :         } else
    1868           0 :             av_strlcatf(compressor_name, len, " EX");
    1869             : 
    1870           0 :         av_strlcatf(compressor_name, len, " %d%c", track->par->height, interlaced ? 'i' : 'p');
    1871             : 
    1872           0 :         av_strlcatf(compressor_name, len, "%d", rate * (interlaced + 1));
    1873             :     }
    1874         156 : }
    1875             : 
    1876         156 : static int mov_write_video_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
    1877             : {
    1878         156 :     int64_t pos = avio_tell(pb);
    1879         156 :     char compressor_name[32] = { 0 };
    1880         156 :     int avid = 0;
    1881             : 
    1882         324 :     int uncompressed_ycbcr = ((track->par->codec_id == AV_CODEC_ID_RAWVIDEO && track->par->format == AV_PIX_FMT_UYVY422)
    1883         156 :                            || (track->par->codec_id == AV_CODEC_ID_RAWVIDEO && track->par->format == AV_PIX_FMT_YUYV422)
    1884         156 :                            ||  track->par->codec_id == AV_CODEC_ID_V308
    1885         156 :                            ||  track->par->codec_id == AV_CODEC_ID_V408
    1886         156 :                            ||  track->par->codec_id == AV_CODEC_ID_V410
    1887         312 :                            ||  track->par->codec_id == AV_CODEC_ID_V210);
    1888             : 
    1889         156 :     avio_wb32(pb, 0); /* size */
    1890         156 :     if (mov->encryption_scheme != MOV_ENC_NONE) {
    1891           0 :         ffio_wfourcc(pb, "encv");
    1892             :     } else {
    1893         156 :         avio_wl32(pb, track->tag); // store it byteswapped
    1894             :     }
    1895         156 :     avio_wb32(pb, 0); /* Reserved */
    1896         156 :     avio_wb16(pb, 0); /* Reserved */
    1897         156 :     avio_wb16(pb, 1); /* Data-reference index */
    1898             : 
    1899         156 :     if (uncompressed_ycbcr) {
    1900           0 :         avio_wb16(pb, 2); /* Codec stream version */
    1901             :     } else {
    1902         156 :         avio_wb16(pb, 0); /* Codec stream version */
    1903             :     }
    1904         156 :     avio_wb16(pb, 0); /* Codec stream revision (=0) */
    1905         156 :     if (track->mode == MODE_MOV) {
    1906          98 :         ffio_wfourcc(pb, "FFMP"); /* Vendor */
    1907          98 :         if (track->par->codec_id == AV_CODEC_ID_RAWVIDEO || uncompressed_ycbcr) {
    1908          12 :             avio_wb32(pb, 0); /* Temporal Quality */
    1909          12 :             avio_wb32(pb, 0x400); /* Spatial Quality = lossless*/
    1910             :         } else {
    1911          86 :             avio_wb32(pb, 0x200); /* Temporal Quality = normal */
    1912          86 :             avio_wb32(pb, 0x200); /* Spatial Quality = normal */
    1913             :         }
    1914             :     } else {
    1915          58 :         avio_wb32(pb, 0); /* Reserved */
    1916          58 :         avio_wb32(pb, 0); /* Reserved */
    1917          58 :         avio_wb32(pb, 0); /* Reserved */
    1918             :     }
    1919         156 :     avio_wb16(pb, track->par->width); /* Video width */
    1920         156 :     avio_wb16(pb, track->height); /* Video height */
    1921         156 :     avio_wb32(pb, 0x00480000); /* Horizontal resolution 72dpi */
    1922         156 :     avio_wb32(pb, 0x00480000); /* Vertical resolution 72dpi */
    1923         156 :     avio_wb32(pb, 0); /* Data size (= 0) */
    1924         156 :     avio_wb16(pb, 1); /* Frame count (= 1) */
    1925             : 
    1926             :     /* FIXME not sure, ISO 14496-1 draft where it shall be set to 0 */
    1927         156 :     find_compressor(compressor_name, 32, track);
    1928         156 :     avio_w8(pb, strlen(compressor_name));
    1929         156 :     avio_write(pb, compressor_name, 31);
    1930             : 
    1931         254 :     if (track->mode == MODE_MOV &&
    1932         196 :        (track->par->codec_id == AV_CODEC_ID_V410 || track->par->codec_id == AV_CODEC_ID_V210))
    1933           0 :         avio_wb16(pb, 0x18);
    1934         156 :     else if (track->mode == MODE_MOV && track->par->bits_per_coded_sample)
    1935          44 :         avio_wb16(pb, track->par->bits_per_coded_sample |
    1936          22 :                   (track->par->format == AV_PIX_FMT_GRAY8 ? 0x20 : 0));
    1937             :     else
    1938         134 :         avio_wb16(pb, 0x18); /* Reserved */
    1939             : 
    1940         157 :     if (track->mode == MODE_MOV && track->par->format == AV_PIX_FMT_PAL8) {
    1941           1 :         int pal_size = 1 << track->par->bits_per_coded_sample;
    1942             :         int i;
    1943           1 :         avio_wb16(pb, 0);             /* Color table ID */
    1944           1 :         avio_wb32(pb, 0);             /* Color table seed */
    1945           1 :         avio_wb16(pb, 0x8000);        /* Color table flags */
    1946           1 :         avio_wb16(pb, pal_size - 1);  /* Color table size (zero-relative) */
    1947          17 :         for (i = 0; i < pal_size; i++) {
    1948          16 :             uint32_t rgb = track->palette[i];
    1949          16 :             uint16_t r = (rgb >> 16) & 0xff;
    1950          16 :             uint16_t g = (rgb >> 8)  & 0xff;
    1951          16 :             uint16_t b = rgb         & 0xff;
    1952          16 :             avio_wb16(pb, 0);
    1953          16 :             avio_wb16(pb, (r << 8) | r);
    1954          16 :             avio_wb16(pb, (g << 8) | g);
    1955          16 :             avio_wb16(pb, (b << 8) | b);
    1956             :         }
    1957             :     } else
    1958         155 :         avio_wb16(pb, 0xffff); /* Reserved */
    1959             : 
    1960         156 :     if (track->tag == MKTAG('m','p','4','v'))
    1961          20 :         mov_write_esds_tag(pb, track);
    1962         136 :     else if (track->par->codec_id == AV_CODEC_ID_H263)
    1963           0 :         mov_write_d263_tag(pb);
    1964         269 :     else if (track->par->codec_id == AV_CODEC_ID_AVUI ||
    1965         133 :             track->par->codec_id == AV_CODEC_ID_SVQ3) {
    1966           3 :         mov_write_extradata_tag(pb, track);
    1967           3 :         avio_wb32(pb, 0);
    1968         133 :     } else if (track->par->codec_id == AV_CODEC_ID_DNXHD) {
    1969          23 :         mov_write_avid_tag(pb, track);
    1970          23 :         avid = 1;
    1971         110 :     } else if (track->par->codec_id == AV_CODEC_ID_HEVC)
    1972           1 :         mov_write_hvcc_tag(pb, track);
    1973         109 :     else if (track->par->codec_id == AV_CODEC_ID_H264 && !TAG_IS_AVCI(track->tag)) {
    1974          49 :         mov_write_avcc_tag(pb, track);
    1975          98 :         if (track->mode == MODE_IPOD)
    1976           0 :             mov_write_uuid_tag_ipod(pb);
    1977          60 :     } else if (track->par->codec_id == AV_CODEC_ID_VP9) {
    1978           0 :         mov_write_vpcc_tag(mov->fc, pb, track);
    1979          60 :     } else if (track->par->codec_id == AV_CODEC_ID_VC1 && track->vos_len > 0)
    1980           0 :         mov_write_dvc1_tag(pb, track);
    1981         120 :     else if (track->par->codec_id == AV_CODEC_ID_VP6F ||
    1982          60 :              track->par->codec_id == AV_CODEC_ID_VP6A) {
    1983             :         /* Don't write any potential extradata here - the cropping
    1984             :          * is signalled via the normal width/height fields. */
    1985          60 :     } else if (track->par->codec_id == AV_CODEC_ID_R10K) {
    1986           0 :         if (track->par->codec_tag == MKTAG('R','1','0','k'))
    1987           0 :             mov_write_dpxe_tag(pb, track);
    1988          60 :     } else if (track->vos_len > 0)
    1989           0 :         mov_write_glbl_tag(pb, track);
    1990             : 
    1991         263 :     if (track->par->codec_id != AV_CODEC_ID_H264 &&
    1992         194 :         track->par->codec_id != AV_CODEC_ID_MPEG4 &&
    1993          87 :         track->par->codec_id != AV_CODEC_ID_DNXHD) {
    1994          64 :         int field_order = track->par->field_order;
    1995             : 
    1996             : #if FF_API_LAVF_AVCTX
    1997             :     FF_DISABLE_DEPRECATION_WARNINGS
    1998          64 :     if (field_order != track->st->codec->field_order && track->st->codec->field_order != AV_FIELD_UNKNOWN)
    1999           0 :         field_order = track->st->codec->field_order;
    2000             :     FF_ENABLE_DEPRECATION_WARNINGS
    2001             : #endif
    2002             : 
    2003          64 :         if (field_order != AV_FIELD_UNKNOWN)
    2004          62 :             mov_write_fiel_tag(pb, track, field_order);
    2005             :     }
    2006             : 
    2007         156 :     if (mov->flags & FF_MOV_FLAG_WRITE_GAMA) {
    2008           0 :         if (track->mode == MODE_MOV)
    2009           0 :             mov_write_gama_tag(pb, track, mov->gamma);
    2010             :         else
    2011           0 :             av_log(mov->fc, AV_LOG_WARNING, "Not writing 'gama' atom. Format is not MOV.\n");
    2012             :     }
    2013         156 :     if (mov->flags & FF_MOV_FLAG_WRITE_COLR) {
    2014           4 :         if (track->mode == MODE_MOV || track->mode == MODE_MP4)
    2015           4 :             mov_write_colr_tag(pb, track);
    2016             :         else
    2017           0 :             av_log(mov->fc, AV_LOG_WARNING, "Not writing 'colr' atom. Format is not MOV or MP4.\n");
    2018             :     }
    2019             : 
    2020         156 :     if (track->mode == MODE_MP4 && mov->fc->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL) {
    2021           0 :         AVStereo3D* stereo_3d = (AVStereo3D*) av_stream_get_side_data(track->st, AV_PKT_DATA_STEREO3D, NULL);
    2022           0 :         AVSphericalMapping* spherical_mapping = (AVSphericalMapping*)av_stream_get_side_data(track->st, AV_PKT_DATA_SPHERICAL, NULL);
    2023             : 
    2024           0 :         if (stereo_3d)
    2025           0 :             mov_write_st3d_tag(pb, stereo_3d);
    2026           0 :         if (spherical_mapping)
    2027           0 :             mov_write_sv3d_tag(mov->fc, pb, spherical_mapping);
    2028             :     }
    2029             : 
    2030         156 :     if (track->par->sample_aspect_ratio.den && track->par->sample_aspect_ratio.num) {
    2031           3 :         mov_write_pasp_tag(pb, track);
    2032             :     }
    2033             : 
    2034         156 :     if (uncompressed_ycbcr){
    2035           0 :         mov_write_clap_tag(pb, track);
    2036             :     }
    2037             : 
    2038         156 :     if (mov->encryption_scheme != MOV_ENC_NONE) {
    2039           0 :         ff_mov_cenc_write_sinf_tag(track, pb, mov->encryption_kid);
    2040             :     }
    2041             : 
    2042             :     /* extra padding for avid stsd */
    2043             :     /* https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/QTFFChap2/qtff2.html#//apple_ref/doc/uid/TP40000939-CH204-61112 */
    2044         156 :     if (avid)
    2045          23 :         avio_wb32(pb, 0);
    2046             : 
    2047         156 :     return update_size(pb, pos);
    2048             : }
    2049             : 
    2050           2 : static int mov_write_rtp_tag(AVIOContext *pb, MOVTrack *track)
    2051             : {
    2052           2 :     int64_t pos = avio_tell(pb);
    2053           2 :     avio_wb32(pb, 0); /* size */
    2054           2 :     ffio_wfourcc(pb, "rtp ");
    2055           2 :     avio_wb32(pb, 0); /* Reserved */
    2056           2 :     avio_wb16(pb, 0); /* Reserved */
    2057           2 :     avio_wb16(pb, 1); /* Data-reference index */
    2058             : 
    2059           2 :     avio_wb16(pb, 1); /* Hint track version */
    2060           2 :     avio_wb16(pb, 1); /* Highest compatible version */
    2061           2 :     avio_wb32(pb, track->max_packet_size); /* Max packet size */
    2062             : 
    2063           2 :     avio_wb32(pb, 12); /* size */
    2064           2 :     ffio_wfourcc(pb, "tims");
    2065           2 :     avio_wb32(pb, track->timescale);
    2066             : 
    2067           2 :     return update_size(pb, pos);
    2068             : }
    2069             : 
    2070           2 : static int mov_write_source_reference_tag(AVIOContext *pb, MOVTrack *track, const char *reel_name)
    2071             : {
    2072           2 :     uint64_t str_size =strlen(reel_name);
    2073           2 :     int64_t pos = avio_tell(pb);
    2074             : 
    2075           2 :     if (str_size >= UINT16_MAX){
    2076           0 :         av_log(NULL, AV_LOG_ERROR, "reel_name length %"PRIu64" is too large\n", str_size);
    2077           0 :         avio_wb16(pb, 0);
    2078           0 :         return AVERROR(EINVAL);
    2079             :     }
    2080             : 
    2081           2 :     avio_wb32(pb, 0);                              /* size */
    2082           2 :     ffio_wfourcc(pb, "name");                      /* Data format */
    2083           2 :     avio_wb16(pb, str_size);                       /* string size */
    2084           2 :     avio_wb16(pb, track->language);                /* langcode */
    2085           2 :     avio_write(pb, reel_name, str_size);           /* reel name */
    2086           2 :     return update_size(pb,pos);
    2087             : }
    2088             : 
    2089          11 : static int mov_write_tmcd_tag(AVIOContext *pb, MOVTrack *track)
    2090             : {
    2091          11 :     int64_t pos = avio_tell(pb);
    2092             : #if 1
    2093             :     int frame_duration;
    2094             :     int nb_frames;
    2095          11 :     AVDictionaryEntry *t = NULL;
    2096             : 
    2097          11 :     if (!track->st->avg_frame_rate.num || !track->st->avg_frame_rate.den) {
    2098             : #if FF_API_LAVF_AVCTX
    2099             :     FF_DISABLE_DEPRECATION_WARNINGS
    2100           3 :         frame_duration = av_rescale(track->timescale, track->st->codec->time_base.num, track->st->codec->time_base.den);
    2101           3 :         nb_frames      = ROUNDED_DIV(track->st->codec->time_base.den, track->st->codec->time_base.num);
    2102             :     FF_ENABLE_DEPRECATION_WARNINGS
    2103             : #else
    2104             :         av_log(NULL, AV_LOG_ERROR, "avg_frame_rate not set for tmcd track.\n");
    2105             :         return AVERROR(EINVAL);
    2106             : #endif
    2107             :     } else {
    2108           8 :         frame_duration = av_rescale(track->timescale, track->st->avg_frame_rate.num, track->st->avg_frame_rate.den);
    2109           8 :         nb_frames      = ROUNDED_DIV(track->st->avg_frame_rate.den, track->st->avg_frame_rate.num);
    2110             :     }
    2111             : 
    2112          11 :     if (nb_frames > 255) {
    2113           0 :         av_log(NULL, AV_LOG_ERROR, "fps %d is too large\n", nb_frames);
    2114           0 :         return AVERROR(EINVAL);
    2115             :     }
    2116             : 
    2117          11 :     avio_wb32(pb, 0); /* size */
    2118          11 :     ffio_wfourcc(pb, "tmcd");               /* Data format */
    2119          11 :     avio_wb32(pb, 0);                       /* Reserved */
    2120          11 :     avio_wb32(pb, 1);                       /* Data reference index */
    2121          11 :     avio_wb32(pb, 0);                       /* Flags */
    2122          11 :     avio_wb32(pb, track->timecode_flags);   /* Flags (timecode) */
    2123          11 :     avio_wb32(pb, track->timescale);        /* Timescale */
    2124          11 :     avio_wb32(pb, frame_duration);          /* Frame duration */
    2125          11 :     avio_w8(pb, nb_frames);                 /* Number of frames */
    2126          11 :     avio_w8(pb, 0);                         /* Reserved */
    2127             : 
    2128          11 :     t = av_dict_get(track->st->metadata, "reel_name", NULL, 0);
    2129          11 :     if (t && utf8len(t->value) && track->mode != MODE_MP4)
    2130           2 :         mov_write_source_reference_tag(pb, track, t->value);
    2131             :     else
    2132           9 :         avio_wb16(pb, 0); /* zero size */
    2133             : #else
    2134             : 
    2135             :     avio_wb32(pb, 0); /* size */
    2136             :     ffio_wfourcc(pb, "tmcd");               /* Data format */
    2137             :     avio_wb32(pb, 0);                       /* Reserved */
    2138             :     avio_wb32(pb, 1);                       /* Data reference index */
    2139             :     if (track->par->extradata_size)
    2140             :         avio_write(pb, track->par->extradata, track->par->extradata_size);
    2141             : #endif
    2142          11 :     return update_size(pb, pos);
    2143             : }
    2144             : 
    2145           1 : static int mov_write_gpmd_tag(AVIOContext *pb, const MOVTrack *track)
    2146             : {
    2147           1 :     int64_t pos = avio_tell(pb);
    2148           1 :     avio_wb32(pb, 0); /* size */
    2149           1 :     ffio_wfourcc(pb, "gpmd");
    2150           1 :     avio_wb32(pb, 0); /* Reserved */
    2151           1 :     avio_wb16(pb, 0); /* Reserved */
    2152           1 :     avio_wb16(pb, 1); /* Data-reference index */
    2153           1 :     avio_wb32(pb, 0); /* Reserved */
    2154           1 :     return update_size(pb, pos);
    2155             : }
    2156             : 
    2157         248 : static int mov_write_stsd_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
    2158             : {
    2159         248 :     int64_t pos = avio_tell(pb);
    2160         248 :     avio_wb32(pb, 0); /* size */
    2161         248 :     ffio_wfourcc(pb, "stsd");
    2162         248 :     avio_wb32(pb, 0); /* version & flags */
    2163         248 :     avio_wb32(pb, 1); /* entry count */
    2164         248 :     if (track->par->codec_type == AVMEDIA_TYPE_VIDEO)
    2165         156 :         mov_write_video_tag(pb, mov, track);
    2166          92 :     else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO)
    2167          77 :         mov_write_audio_tag(s, pb, mov, track);
    2168          15 :     else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE)
    2169           1 :         mov_write_subtitle_tag(pb, track);
    2170          14 :     else if (track->par->codec_tag == MKTAG('r','t','p',' '))
    2171           2 :         mov_write_rtp_tag(pb, track);
    2172          12 :     else if (track->par->codec_tag == MKTAG('t','m','c','d'))
    2173          11 :         mov_write_tmcd_tag(pb, track);
    2174           1 :     else if (track->par->codec_tag == MKTAG('g','p','m','d'))
    2175           1 :         mov_write_gpmd_tag(pb, track);
    2176         248 :     return update_size(pb, pos);
    2177             : }
    2178             : 
    2179           5 : static int mov_write_ctts_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
    2180             : {
    2181           5 :     MOVMuxContext *mov = s->priv_data;
    2182             :     MOVStts *ctts_entries;
    2183           5 :     uint32_t entries = 0;
    2184             :     uint32_t atom_size;
    2185             :     int i;
    2186             : 
    2187           5 :     ctts_entries = av_malloc_array((track->entry + 1), sizeof(*ctts_entries)); /* worst case */
    2188           5 :     if (!ctts_entries)
    2189           0 :         return AVERROR(ENOMEM);
    2190           5 :     ctts_entries[0].count = 1;
    2191           5 :     ctts_entries[0].duration = track->cluster[0].cts;
    2192         370 :     for (i = 1; i < track->entry; i++) {
    2193         365 :         if (track->cluster[i].cts == ctts_entries[entries].duration) {
    2194           0 :             ctts_entries[entries].count++; /* compress */
    2195             :         } else {
    2196         365 :             entries++;
    2197         365 :             ctts_entries[entries].duration = track->cluster[i].cts;
    2198         365 :             ctts_entries[entries].count = 1;
    2199             :         }
    2200             :     }
    2201           5 :     entries++; /* last one */
    2202           5 :     atom_size = 16 + (entries * 8);
    2203           5 :     avio_wb32(pb, atom_size); /* size */
    2204           5 :     ffio_wfourcc(pb, "ctts");
    2205           5 :     if (mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS)
    2206           0 :         avio_w8(pb, 1); /* version */
    2207             :     else
    2208           5 :         avio_w8(pb, 0); /* version */
    2209           5 :     avio_wb24(pb, 0); /* flags */
    2210           5 :     avio_wb32(pb, entries); /* entry count */
    2211         375 :     for (i = 0; i < entries; i++) {
    2212         370 :         avio_wb32(pb, ctts_entries[i].count);
    2213         370 :         avio_wb32(pb, ctts_entries[i].duration);
    2214             :     }
    2215           5 :     av_free(ctts_entries);
    2216           5 :     return atom_size;
    2217             : }
    2218             : 
    2219             : /* Time to sample atom */
    2220         248 : static int mov_write_stts_tag(AVIOContext *pb, MOVTrack *track)
    2221             : {
    2222         248 :     MOVStts *stts_entries = NULL;
    2223         248 :     uint32_t entries = -1;
    2224             :     uint32_t atom_size;
    2225             :     int i;
    2226             : 
    2227         248 :     if (track->par->codec_type == AVMEDIA_TYPE_AUDIO && !track->audio_vbr) {
    2228          15 :         stts_entries = av_malloc(sizeof(*stts_entries)); /* one entry */
    2229          15 :         if (!stts_entries)
    2230           0 :             return AVERROR(ENOMEM);
    2231          15 :         stts_entries[0].count = track->sample_count;
    2232          15 :         stts_entries[0].duration = 1;
    2233          15 :         entries = 1;
    2234             :     } else {
    2235         233 :         if (track->entry) {
    2236         149 :             stts_entries = av_malloc_array(track->entry, sizeof(*stts_entries)); /* worst case */
    2237         149 :             if (!stts_entries)
    2238           0 :                 return AVERROR(ENOMEM);
    2239             :         }
    2240        7908 :         for (i = 0; i < track->entry; i++) {
    2241        7675 :             int duration = get_cluster_duration(track, i);
    2242        7675 :             if (i && duration == stts_entries[entries].duration) {
    2243        7352 :                 stts_entries[entries].count++; /* compress */
    2244             :             } else {
    2245         323 :                 entries++;
    2246         323 :                 stts_entries[entries].duration = duration;
    2247         323 :                 stts_entries[entries].count = 1;
    2248             :             }
    2249             :         }
    2250         233 :         entries++; /* last one */
    2251             :     }
    2252         248 :     atom_size = 16 + (entries * 8);
    2253         248 :     avio_wb32(pb, atom_size); /* size */
    2254         248 :     ffio_wfourcc(pb, "stts");
    2255         248 :     avio_wb32(pb, 0); /* version & flags */
    2256         248 :     avio_wb32(pb, entries); /* entry count */
    2257         586 :     for (i = 0; i < entries; i++) {
    2258         338 :         avio_wb32(pb, stts_entries[i].count);
    2259         338 :         avio_wb32(pb, stts_entries[i].duration);
    2260             :     }
    2261         248 :     av_free(stts_entries);
    2262         248 :     return atom_size;
    2263             : }
    2264             : 
    2265         248 : static int mov_write_dref_tag(AVIOContext *pb)
    2266             : {
    2267         248 :     avio_wb32(pb, 28); /* size */
    2268         248 :     ffio_wfourcc(pb, "dref");
    2269         248 :     avio_wb32(pb, 0); /* version & flags */
    2270         248 :     avio_wb32(pb, 1); /* entry count */
    2271             : 
    2272         248 :     avio_wb32(pb, 0xc); /* size */
    2273             :     //FIXME add the alis and rsrc atom
    2274         248 :     ffio_wfourcc(pb, "url ");
    2275         248 :     avio_wb32(pb, 1); /* version & flags */
    2276             : 
    2277         248 :     return 28;
    2278             : }
    2279             : 
    2280          51 : static int mov_preroll_write_stbl_atoms(AVIOContext *pb, MOVTrack *track)
    2281             : {
    2282             :     struct sgpd_entry {
    2283             :         int count;
    2284             :         int16_t roll_distance;
    2285             :         int group_description_index;
    2286             :     };
    2287             : 
    2288          51 :     struct sgpd_entry *sgpd_entries = NULL;
    2289          51 :     int entries = -1;
    2290          51 :     int group = 0;
    2291             :     int i, j;
    2292             : 
    2293          51 :     const int OPUS_SEEK_PREROLL_MS = 80;
    2294          51 :     int roll_samples = av_rescale_q(OPUS_SEEK_PREROLL_MS,
    2295          51 :                                     (AVRational){1, 1000},
    2296          51 :                                     (AVRational){1, 48000});
    2297             : 
    2298          51 :     if (!track->entry)
    2299          40 :         return 0;
    2300             : 
    2301          11 :     sgpd_entries = av_malloc_array(track->entry, sizeof(*sgpd_entries));
    2302          11 :     if (!sgpd_entries)
    2303           0 :         return AVERROR(ENOMEM);
    2304             : 
    2305          11 :     av_assert0(track->par->codec_id == AV_CODEC_ID_OPUS || track->par->codec_id == AV_CODEC_ID_AAC);
    2306             : 
    2307          11 :     if (track->par->codec_id == AV_CODEC_ID_OPUS) {
    2308           0 :         for (i = 0; i < track->entry; i++) {
    2309           0 :             int roll_samples_remaining = roll_samples;
    2310           0 :             int distance = 0;
    2311           0 :             for (j = i - 1; j >= 0; j--) {
    2312           0 :                 roll_samples_remaining -= get_cluster_duration(track, j);
    2313           0 :                 distance++;
    2314           0 :                 if (roll_samples_remaining <= 0)
    2315           0 :                     break;
    2316             :             }
    2317             :             /* We don't have enough preceeding samples to compute a valid
    2318             :                roll_distance here, so this sample can't be independently
    2319             :                decoded. */
    2320           0 :             if (roll_samples_remaining > 0)
    2321           0 :                 distance = 0;
    2322             :             /* Verify distance is a minimum of 2 (60ms) packets and a maximum of
    2323             :                32 (2.5ms) packets. */
    2324           0 :             av_assert0(distance == 0 || (distance >= 2 && distance <= 32));
    2325           0 :             if (i && distance == sgpd_entries[entries].roll_distance) {
    2326           0 :                 sgpd_entries[entries].count++;
    2327             :             } else {
    2328           0 :                 entries++;
    2329           0 :                 sgpd_entries[entries].count = 1;
    2330           0 :                 sgpd_entries[entries].roll_distance = distance;
    2331           0 :                 sgpd_entries[entries].group_description_index = distance ? ++group : 0;
    2332             :             }
    2333             :         }
    2334             :     } else {
    2335          11 :         entries++;
    2336          11 :         sgpd_entries[entries].count = track->sample_count;
    2337          11 :         sgpd_entries[entries].roll_distance = 1;
    2338          11 :         sgpd_entries[entries].group_description_index = ++group;
    2339             :     }
    2340          11 :     entries++;
    2341             : 
    2342          11 :     if (!group) {
    2343           0 :         av_free(sgpd_entries);
    2344           0 :         return 0;
    2345             :     }
    2346             : 
    2347             :     /* Write sgpd tag */
    2348          11 :     avio_wb32(pb, 24 + (group * 2)); /* size */
    2349          11 :     ffio_wfourcc(pb, "sgpd");
    2350          11 :     avio_wb32(pb, 1 << 24); /* fullbox */
    2351          11 :     ffio_wfourcc(pb, "roll");
    2352          11 :     avio_wb32(pb, 2); /* default_length */
    2353          11 :     avio_wb32(pb, group); /* entry_count */
    2354          22 :     for (i = 0; i < entries; i++) {
    2355          11 :         if (sgpd_entries[i].group_description_index) {
    2356          11 :             avio_wb16(pb, -sgpd_entries[i].roll_distance); /* roll_distance */
    2357             :         }
    2358             :     }
    2359             : 
    2360             :     /* Write sbgp tag */
    2361          11 :     avio_wb32(pb, 20 + (entries * 8)); /* size */
    2362          11 :     ffio_wfourcc(pb, "sbgp");
    2363          11 :     avio_wb32(pb, 0); /* fullbox */
    2364          11 :     ffio_wfourcc(pb, "roll");
    2365          11 :     avio_wb32(pb, entries); /* entry_count */
    2366          22 :     for (i = 0; i < entries; i++) {
    2367          11 :         avio_wb32(pb, sgpd_entries[i].count); /* sample_count */
    2368          11 :         avio_wb32(pb, sgpd_entries[i].group_description_index); /* group_description_index */
    2369             :     }
    2370             : 
    2371          11 :     av_free(sgpd_entries);
    2372          11 :     return 0;
    2373             : }
    2374             : 
    2375         248 : static int mov_write_stbl_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
    2376             : {
    2377         248 :     int64_t pos = avio_tell(pb);
    2378             :     int ret;
    2379             : 
    2380         248 :     avio_wb32(pb, 0); /* size */
    2381         248 :     ffio_wfourcc(pb, "stbl");
    2382         248 :     mov_write_stsd_tag(s, pb, mov, track);
    2383         248 :     mov_write_stts_tag(pb, track);
    2384         340 :     if ((track->par->codec_type == AVMEDIA_TYPE_VIDEO ||
    2385         250 :          track->par->codec_tag == MKTAG('r','t','p',' ')) &&
    2386         278 :         track->has_keyframes && track->has_keyframes < track->entry)
    2387          40 :         mov_write_stss_tag(pb, track, MOV_SYNC_SAMPLE);
    2388         248 :     if (track->par->codec_type == AVMEDIA_TYPE_VIDEO && track->has_disposable)
    2389           0 :         mov_write_sdtp_tag(pb, track);
    2390         248 :     if (track->mode == MODE_MOV && track->flags & MOV_TRACK_STPS)
    2391           0 :         mov_write_stss_tag(pb, track, MOV_PARTIAL_SYNC_SAMPLE);
    2392         404 :     if (track->par->codec_type == AVMEDIA_TYPE_VIDEO &&
    2393         183 :         track->flags & MOV_TRACK_CTTS && track->entry) {
    2394             : 
    2395           5 :         if ((ret = mov_write_ctts_tag(s, pb, track)) < 0)
    2396           0 :             return ret;
    2397             :     }
    2398         248 :     mov_write_stsc_tag(pb, track);
    2399         248 :     mov_write_stsz_tag(pb, track);
    2400         248 :     mov_write_stco_tag(pb, track);
    2401         248 :     if (track->cenc.aes_ctr) {
    2402           0 :         ff_mov_cenc_write_stbl_atoms(&track->cenc, pb);
    2403             :     }
    2404         248 :     if (track->par->codec_id == AV_CODEC_ID_OPUS || track->par->codec_id == AV_CODEC_ID_AAC) {
    2405          51 :         mov_preroll_write_stbl_atoms(pb, track);
    2406             :     }
    2407         248 :     return update_size(pb, pos);
    2408             : }
    2409             : 
    2410         248 : static int mov_write_dinf_tag(AVIOContext *pb)
    2411             : {
    2412         248 :     int64_t pos = avio_tell(pb);
    2413         248 :     avio_wb32(pb, 0); /* size */
    2414         248 :     ffio_wfourcc(pb, "dinf");
    2415         248 :     mov_write_dref_tag(pb);
    2416         248 :     return update_size(pb, pos);
    2417             : }
    2418             : 
    2419           3 : static int mov_write_nmhd_tag(AVIOContext *pb)
    2420             : {
    2421           3 :     avio_wb32(pb, 12);
    2422           3 :     ffio_wfourcc(pb, "nmhd");
    2423           3 :     avio_wb32(pb, 0);
    2424           3 :     return 12;
    2425             : }
    2426             : 
    2427           9 : static int mov_write_tcmi_tag(AVIOContext *pb, MOVTrack *track)
    2428             : {
    2429           9 :     int64_t pos = avio_tell(pb);
    2430           9 :     const char *font = "Lucida Grande";
    2431           9 :     avio_wb32(pb, 0);                   /* size */
    2432           9 :     ffio_wfourcc(pb, "tcmi");           /* timecode media information atom */
    2433           9 :     avio_wb32(pb, 0);                   /* version & flags */
    2434           9 :     avio_wb16(pb, 0);                   /* text font */
    2435           9 :     avio_wb16(pb, 0);                   /* text face */
    2436           9 :     avio_wb16(pb, 12);                  /* text size */
    2437           9 :     avio_wb16(pb, 0);                   /* (unknown, not in the QT specs...) */
    2438           9 :     avio_wb16(pb, 0x0000);              /* text color (red) */
    2439           9 :     avio_wb16(pb, 0x0000);              /* text color (green) */
    2440           9 :     avio_wb16(pb, 0x0000);              /* text color (blue) */
    2441           9 :     avio_wb16(pb, 0xffff);              /* background color (red) */
    2442           9 :     avio_wb16(pb, 0xffff);              /* background color (green) */
    2443           9 :     avio_wb16(pb, 0xffff);              /* background color (blue) */
    2444           9 :     avio_w8(pb, strlen(font));          /* font len (part of the pascal string) */
    2445           9 :     avio_write(pb, font, strlen(font)); /* font name */
    2446           9 :     return update_size(pb, pos);
    2447             : }
    2448             : 
    2449          10 : static int mov_write_gmhd_tag(AVIOContext *pb, MOVTrack *track)
    2450             : {
    2451          10 :     int64_t pos = avio_tell(pb);
    2452          10 :     avio_wb32(pb, 0);      /* size */
    2453          10 :     ffio_wfourcc(pb, "gmhd");
    2454          10 :     avio_wb32(pb, 0x18);   /* gmin size */
    2455          10 :     ffio_wfourcc(pb, "gmin");/* generic media info */
    2456          10 :     avio_wb32(pb, 0);      /* version & flags */
    2457          10 :     avio_wb16(pb, 0x40);   /* graphics mode = */
    2458          10 :     avio_wb16(pb, 0x8000); /* opColor (r?) */
    2459          10 :     avio_wb16(pb, 0x8000); /* opColor (g?) */
    2460          10 :     avio_wb16(pb, 0x8000); /* opColor (b?) */
    2461          10 :     avio_wb16(pb, 0);      /* balance */
    2462          10 :     avio_wb16(pb, 0);      /* reserved */
    2463             : 
    2464             :     /*
    2465             :      * This special text atom is required for
    2466             :      * Apple Quicktime chapters. The contents
    2467             :      * don't appear to be documented, so the
    2468             :      * bytes are copied verbatim.
    2469             :      */
    2470          10 :     if (track->tag != MKTAG('c','6','0','8')) {
    2471          10 :     avio_wb32(pb, 0x2C);   /* size */
    2472          10 :     ffio_wfourcc(pb, "text");
    2473          10 :     avio_wb16(pb, 0x01);
    2474          10 :     avio_wb32(pb, 0x00);
    2475          10 :     avio_wb32(pb, 0x00);
    2476          10 :     avio_wb32(pb, 0x00);
    2477          10 :     avio_wb32(pb, 0x01);
    2478          10 :     avio_wb32(pb, 0x00);
    2479          10 :     avio_wb32(pb, 0x00);
    2480          10 :     avio_wb32(pb, 0x00);
    2481          10 :     avio_wb32(pb, 0x00004000);
    2482          10 :     avio_wb16(pb, 0x0000);
    2483             :     }
    2484             : 
    2485          10 :     if (track->par->codec_tag == MKTAG('t','m','c','d')) {
    2486           9 :         int64_t tmcd_pos = avio_tell(pb);
    2487           9 :         avio_wb32(pb, 0); /* size */
    2488           9 :         ffio_wfourcc(pb, "tmcd");
    2489           9 :         mov_write_tcmi_tag(pb, track);
    2490           9 :         update_size(pb, tmcd_pos);
    2491           1 :     } else if (track->par->codec_tag == MKTAG('g','p','m','d')) {
    2492           1 :         int64_t gpmd_pos = avio_tell(pb);
    2493           1 :         avio_wb32(pb, 0); /* size */
    2494           1 :         ffio_wfourcc(pb, "gpmd");
    2495           1 :         avio_wb32(pb, 0); /* version */
    2496           1 :         update_size(pb, gpmd_pos);
    2497             :     }
    2498          10 :     return update_size(pb, pos);
    2499             : }
    2500             : 
    2501          77 : static int mov_write_smhd_tag(AVIOContext *pb)
    2502             : {
    2503          77 :     avio_wb32(pb, 16); /* size */
    2504          77 :     ffio_wfourcc(pb, "smhd");
    2505          77 :     avio_wb32(pb, 0); /* version & flags */
    2506          77 :     avio_wb16(pb, 0); /* reserved (balance, normally = 0) */
    2507          77 :     avio_wb16(pb, 0); /* reserved */
    2508          77 :     return 16;
    2509             : }
    2510             : 
    2511         156 : static int mov_write_vmhd_tag(AVIOContext *pb)
    2512             : {
    2513         156 :     avio_wb32(pb, 0x14); /* size (always 0x14) */
    2514         156 :     ffio_wfourcc(pb, "vmhd");
    2515         156 :     avio_wb32(pb, 0x01); /* version & flags */
    2516         156 :     avio_wb64(pb, 0); /* reserved (graphics mode = copy) */
    2517         156 :     return 0x14;
    2518             : }
    2519             : 
    2520         153 : static int is_clcp_track(MOVTrack *track)
    2521             : {
    2522         306 :     return track->tag == MKTAG('c','7','0','8') ||
    2523         153 :            track->tag == MKTAG('c','6','0','8');
    2524             : }
    2525             : 
    2526         383 : static int mov_write_hdlr_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
    2527             : {
    2528         383 :     const char *hdlr, *descr = NULL, *hdlr_type = NULL;
    2529         383 :     int64_t pos = avio_tell(pb);
    2530             : 
    2531         383 :     hdlr      = "dhlr";
    2532         383 :     hdlr_type = "url ";
    2533         383 :     descr     = "DataHandler";
    2534             : 
    2535         383 :     if (track) {
    2536         248 :         hdlr = (track->mode == MODE_MOV) ? "mhlr" : "\0\0\0\0";
    2537         248 :         if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
    2538         156 :             hdlr_type = "vide";
    2539         156 :             descr     = "VideoHandler";
    2540          92 :         } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) {
    2541          77 :             hdlr_type = "soun";
    2542          77 :             descr     = "SoundHandler";
    2543          15 :         } else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE) {
    2544           1 :             if (is_clcp_track(track)) {
    2545           0 :                 hdlr_type = "clcp";
    2546           0 :                 descr = "ClosedCaptionHandler";
    2547             :             } else {
    2548           1 :                 if (track->tag == MKTAG('t','x','3','g')) {
    2549           1 :                     hdlr_type = "sbtl";
    2550           0 :                 } else if (track->tag == MKTAG('m','p','4','s')) {
    2551           0 :                     hdlr_type = "subp";
    2552             :                 } else {
    2553           0 :                     hdlr_type = "text";
    2554             :                 }
    2555           1 :             descr = "SubtitleHandler";
    2556             :             }
    2557          14 :         } else if (track->par->codec_tag == MKTAG('r','t','p',' ')) {
    2558           2 :             hdlr_type = "hint";
    2559           2 :             descr     = "HintHandler";
    2560          12 :         } else if (track->par->codec_tag == MKTAG('t','m','c','d')) {
    2561          11 :             hdlr_type = "tmcd";
    2562          11 :             descr = "TimeCodeHandler";
    2563           1 :         } else if (track->par->codec_tag == MKTAG('g','p','m','d')) {
    2564           1 :             hdlr_type = "meta";
    2565           1 :             descr = "GoPro MET"; // GoPro Metadata
    2566             :         } else {
    2567           0 :             av_log(s, AV_LOG_WARNING,
    2568             :                    "Unknown hldr_type for %s, writing dummy values\n",
    2569           0 :                    av_fourcc2str(track->par->codec_tag));
    2570             :         }
    2571         248 :         if (track->st) {
    2572             :             // hdlr.name is used by some players to identify the content title
    2573             :             // of the track. So if an alternate handler description is
    2574             :             // specified, use it.
    2575             :             AVDictionaryEntry *t;
    2576         246 :             t = av_dict_get(track->st->metadata, "handler", NULL, 0);
    2577         246 :             if (t && utf8len(t->value))
    2578           0 :                 descr = t->value;
    2579             :         }
    2580             :     }
    2581             : 
    2582         383 :     avio_wb32(pb, 0); /* size */
    2583         383 :     ffio_wfourcc(pb, "hdlr");
    2584         383 :     avio_wb32(pb, 0); /* Version & flags */
    2585         383 :     avio_write(pb, hdlr, 4); /* handler */
    2586         383 :     ffio_wfourcc(pb, hdlr_type); /* handler type */
    2587         383 :     avio_wb32(pb, 0); /* reserved */
    2588         383 :     avio_wb32(pb, 0); /* reserved */
    2589         383 :     avio_wb32(pb, 0); /* reserved */
    2590         383 :     if (!track || track->mode == MODE_MOV)
    2591         270 :         avio_w8(pb, strlen(descr)); /* pascal string */
    2592         383 :     avio_write(pb, descr, strlen(descr)); /* handler description */
    2593         383 :     if (track && track->mode != MODE_MOV)
    2594         113 :         avio_w8(pb, 0); /* c string */
    2595         383 :     return update_size(pb, pos);
    2596             : }
    2597             : 
    2598           2 : static int mov_write_hmhd_tag(AVIOContext *pb)
    2599             : {
    2600             :     /* This atom must be present, but leaving the values at zero
    2601             :      * seems harmless. */
    2602           2 :     avio_wb32(pb, 28); /* size */
    2603           2 :     ffio_wfourcc(pb, "hmhd");
    2604           2 :     avio_wb32(pb, 0); /* version, flags */
    2605           2 :     avio_wb16(pb, 0); /* maxPDUsize */
    2606           2 :     avio_wb16(pb, 0); /* avgPDUsize */
    2607           2 :     avio_wb32(pb, 0); /* maxbitrate */
    2608           2 :     avio_wb32(pb, 0); /* avgbitrate */
    2609           2 :     avio_wb32(pb, 0); /* reserved */
    2610           2 :     return 28;
    2611             : }
    2612             : 
    2613         248 : static int mov_write_minf_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
    2614             : {
    2615         248 :     int64_t pos = avio_tell(pb);
    2616             :     int ret;
    2617             : 
    2618         248 :     avio_wb32(pb, 0); /* size */
    2619         248 :     ffio_wfourcc(pb, "minf");
    2620         248 :     if (track->par->codec_type == AVMEDIA_TYPE_VIDEO)
    2621         156 :         mov_write_vmhd_tag(pb);
    2622          92 :     else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO)
    2623          77 :         mov_write_smhd_tag(pb);
    2624          15 :     else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE) {
    2625           1 :         if (track->tag == MKTAG('t','e','x','t') || is_clcp_track(track)) {
    2626           0 :             mov_write_gmhd_tag(pb, track);
    2627             :         } else {
    2628           1 :             mov_write_nmhd_tag(pb);
    2629             :         }
    2630          14 :     } else if (track->tag == MKTAG('r','t','p',' ')) {
    2631           2 :         mov_write_hmhd_tag(pb);
    2632          12 :     } else if (track->tag == MKTAG('t','m','c','d')) {
    2633          11 :         if (track->mode != MODE_MOV)
    2634           2 :             mov_write_nmhd_tag(pb);
    2635             :         else
    2636           9 :             mov_write_gmhd_tag(pb, track);
    2637           1 :     } else if (track->tag == MKTAG('g','p','m','d')) {
    2638           1 :         mov_write_gmhd_tag(pb, track);
    2639             :     }
    2640         248 :     if (track->mode == MODE_MOV) /* FIXME: Why do it for MODE_MOV only ? */
    2641         135 :         mov_write_hdlr_tag(s, pb, NULL);
    2642         248 :     mov_write_dinf_tag(pb);
    2643         248 :     if ((ret = mov_write_stbl_tag(s, pb, mov, track)) < 0)
    2644           0 :         return ret;
    2645         248 :     return update_size(pb, pos);
    2646             : }
    2647             : 
    2648         248 : static int mov_write_mdhd_tag(AVIOContext *pb, MOVMuxContext *mov,
    2649             :                               MOVTrack *track)
    2650             : {
    2651         248 :     int version = track->track_duration < INT32_MAX ? 0 : 1;
    2652             : 
    2653         248 :     if (track->mode == MODE_ISM)
    2654           5 :         version = 1;
    2655             : 
    2656         248 :     (version == 1) ? avio_wb32(pb, 44) : avio_wb32(pb, 32); /* size */
    2657         248 :     ffio_wfourcc(pb, "mdhd");
    2658         248 :     avio_w8(pb, version);
    2659         248 :     avio_wb24(pb, 0); /* flags */
    2660         248 :     if (version == 1) {
    2661           9 :         avio_wb64(pb, track->time);
    2662           9 :         avio_wb64(pb, track->time);
    2663             :     } else {
    2664         239 :         avio_wb32(pb, track->time); /* creation time */
    2665         239 :         avio_wb32(pb, track->time); /* modification time */
    2666             :     }
    2667         248 :     avio_wb32(pb, track->timescale); /* time scale (sample rate for audio) */
    2668         248 :     if (!track->entry && mov->mode == MODE_ISM)
    2669           5 :         (version == 1) ? avio_wb64(pb, UINT64_C(0xffffffffffffffff)) : avio_wb32(pb, 0xffffffff);
    2670         243 :     else if (!track->entry)
    2671          79 :         (version == 1) ? avio_wb64(pb, 0) : avio_wb32(pb, 0);
    2672             :     else
    2673         164 :         (version == 1) ? avio_wb64(pb, track->track_duration) : avio_wb32(pb, track->track_duration); /* duration */
    2674         248 :     avio_wb16(pb, track->language); /* language */
    2675         248 :     avio_wb16(pb, 0); /* reserved (quality) */
    2676             : 
    2677         248 :     if (version != 0 && track->mode == MODE_MOV) {
    2678           0 :         av_log(NULL, AV_LOG_ERROR,
    2679             :                "FATAL error, file duration too long for timebase, this file will not be\n"
    2680             :                "playable with quicktime. Choose a different timebase or a different\n"
    2681             :                "container format\n");
    2682             :     }
    2683             : 
    2684         248 :     return 32;
    2685             : }
    2686             : 
    2687         248 : static int mov_write_mdia_tag(AVFormatContext *s, AVIOContext *pb,
    2688             :                               MOVMuxContext *mov, MOVTrack *track)
    2689             : {
    2690         248 :     int64_t pos = avio_tell(pb);
    2691             :     int ret;
    2692             : 
    2693         248 :     avio_wb32(pb, 0); /* size */
    2694         248 :     ffio_wfourcc(pb, "mdia");
    2695         248 :     mov_write_mdhd_tag(pb, mov, track);
    2696         248 :     mov_write_hdlr_tag(s, pb, track);
    2697         248 :     if ((ret = mov_write_minf_tag(s, pb, mov, track)) < 0)
    2698           0 :         return ret;
    2699         248 :     return update_size(pb, pos);
    2700             : }
    2701             : 
    2702             : /* transformation matrix
    2703             :      |a  b  u|
    2704             :      |c  d  v|
    2705             :      |tx ty w| */
    2706         421 : static void write_matrix(AVIOContext *pb, int16_t a, int16_t b, int16_t c,
    2707             :                          int16_t d, int16_t tx, int16_t ty)
    2708             : {
    2709         421 :     avio_wb32(pb, a << 16);  /* 16.16 format */
    2710         421 :     avio_wb32(pb, b << 16);  /* 16.16 format */
    2711         421 :     avio_wb32(pb, 0);        /* u in 2.30 format */
    2712         421 :     avio_wb32(pb, c << 16);  /* 16.16 format */
    2713         421 :     avio_wb32(pb, d << 16);  /* 16.16 format */
    2714         421 :     avio_wb32(pb, 0);        /* v in 2.30 format */
    2715         421 :     avio_wb32(pb, tx << 16); /* 16.16 format */
    2716         421 :     avio_wb32(pb, ty << 16); /* 16.16 format */
    2717         421 :     avio_wb32(pb, 1 << 30);  /* w in 2.30 format */
    2718         421 : }
    2719             : 
    2720         248 : static int mov_write_tkhd_tag(AVIOContext *pb, MOVMuxContext *mov,
    2721             :                               MOVTrack *track, AVStream *st)
    2722             : {
    2723         248 :     int64_t duration = av_rescale_rnd(track->track_duration, MOV_TIMESCALE,
    2724         248 :                                       track->timescale, AV_ROUND_UP);
    2725         248 :     int version = duration < INT32_MAX ? 0 : 1;
    2726         248 :     int flags   = MOV_TKHD_FLAG_IN_MOVIE;
    2727         248 :     int rotation = 0;
    2728         248 :     int group   = 0;
    2729             : 
    2730         248 :     uint32_t *display_matrix = NULL;
    2731             :     int      display_matrix_size, i;
    2732             : 
    2733         248 :     if (st) {
    2734         238 :         if (mov->per_stream_grouping)
    2735           0 :             group = st->index;
    2736             :         else
    2737         238 :             group = st->codecpar->codec_type;
    2738             : 
    2739         238 :         display_matrix = (uint32_t*)av_stream_get_side_data(st, AV_PKT_DATA_DISPLAYMATRIX,
    2740             :                                                             &display_matrix_size);
    2741         238 :         if (display_matrix && display_matrix_size < 9 * sizeof(*display_matrix))
    2742           0 :             display_matrix = NULL;
    2743             :     }
    2744             : 
    2745         248 :     if (track->flags & MOV_TRACK_ENABLED)
    2746         238 :         flags |= MOV_TKHD_FLAG_ENABLED;
    2747             : 
    2748         248 :     if (track->mode == MODE_ISM)
    2749           5 :         version = 1;
    2750             : 
    2751         248 :     (version == 1) ? avio_wb32(pb, 104) : avio_wb32(pb, 92); /* size */
    2752         248 :     ffio_wfourcc(pb, "tkhd");
    2753         248 :     avio_w8(pb, version);
    2754         248 :     avio_wb24(pb, flags);
    2755         248 :     if (version == 1) {
    2756           5 :         avio_wb64(pb, track->time);
    2757           5 :         avio_wb64(pb, track->time);
    2758             :     } else {
    2759         243 :         avio_wb32(pb, track->time); /* creation time */
    2760         243 :         avio_wb32(pb, track->time); /* modification time */
    2761             :     }
    2762         248 :     avio_wb32(pb, track->track_id); /* track-id */
    2763         248 :     avio_wb32(pb, 0); /* reserved */
    2764         248 :     if (!track->entry && mov->mode == MODE_ISM)
    2765           5 :         (version == 1) ? avio_wb64(pb, UINT64_C(0xffffffffffffffff)) : avio_wb32(pb, 0xffffffff);
    2766         243 :     else if (!track->entry)
    2767          79 :         (version == 1) ? avio_wb64(pb, 0) : avio_wb32(pb, 0);
    2768             :     else
    2769         164 :         (version == 1) ? avio_wb64(pb, duration) : avio_wb32(pb, duration);
    2770             : 
    2771         248 :     avio_wb32(pb, 0); /* reserved */
    2772         248 :     avio_wb32(pb, 0); /* reserved */
    2773         248 :     avio_wb16(pb, 0); /* layer */
    2774         248 :     avio_wb16(pb, group); /* alternate group) */
    2775             :     /* Volume, only for audio */
    2776         248 :     if (track->par->codec_type == AVMEDIA_TYPE_AUDIO)
    2777          77 :         avio_wb16(pb, 0x0100);
    2778             :     else
    2779         171 :         avio_wb16(pb, 0);
    2780         248 :     avio_wb16(pb, 0); /* reserved */
    2781             : 
    2782             :     /* Matrix structure */
    2783             : #if FF_API_OLD_ROTATE_API
    2784         248 :     if (st && st->metadata) {
    2785         143 :         AVDictionaryEntry *rot = av_dict_get(st->metadata, "rotate", NULL, 0);
    2786         143 :         rotation = (rot && rot->value) ? atoi(rot->value) : 0;
    2787             :     }
    2788             : #endif
    2789         248 :     if (display_matrix) {
    2790          10 :         for (i = 0; i < 9; i++)
    2791           9 :             avio_wb32(pb, display_matrix[i]);
    2792             : #if FF_API_OLD_ROTATE_API
    2793         247 :     } else if (rotation == 90) {
    2794           0 :         write_matrix(pb,  0,  1, -1,  0, track->par->height, 0);
    2795         247 :     } else if (rotation == 180) {
    2796           0 :         write_matrix(pb, -1,  0,  0, -1, track->par->width, track->par->height);
    2797         247 :     } else if (rotation == 270) {
    2798           0 :         write_matrix(pb,  0, -1,  1,  0, 0, track->par->width);
    2799             : #endif
    2800             :     } else {
    2801         247 :         write_matrix(pb,  1,  0,  0,  1, 0, 0);
    2802             :     }
    2803             :     /* Track width and height, for visual only */
    2804         330 :     if (st && (track->par->codec_type == AVMEDIA_TYPE_VIDEO ||
    2805         239 :                track->par->codec_type == AVMEDIA_TYPE_SUBTITLE)) {
    2806             :         int64_t track_width_1616;
    2807         157 :         if (track->mode == MODE_MOV) {
    2808          98 :             track_width_1616 = track->par->width * 0x10000ULL;
    2809             :         } else {
    2810         118 :             track_width_1616 = av_rescale(st->sample_aspect_ratio.num,
    2811          59 :                                                   track->par->width * 0x10000LL,
    2812          59 :                                                   st->sample_aspect_ratio.den);
    2813          61 :             if (!track_width_1616 ||
    2814           4 :                 track->height != track->par->height ||
    2815             :                 track_width_1616 > UINT32_MAX)
    2816          57 :                 track_width_1616 = track->par->width * 0x10000ULL;
    2817             :         }
    2818         157 :         if (track_width_1616 > UINT32_MAX) {
    2819           0 :             av_log(mov->fc, AV_LOG_WARNING, "track width is too large\n");
    2820           0 :             track_width_1616 = 0;
    2821             :         }
    2822         157 :         avio_wb32(pb, track_width_1616);
    2823         157 :         if (track->height > 0xFFFF) {
    2824           0 :             av_log(mov->fc, AV_LOG_WARNING, "track height is too large\n");
    2825           0 :             avio_wb32(pb, 0);
    2826             :         } else
    2827         157 :             avio_wb32(pb, track->height * 0x10000U);
    2828             :     } else {
    2829          91 :         avio_wb32(pb, 0);
    2830          91 :         avio_wb32(pb, 0);
    2831             :     }
    2832         248 :     return 0x5c;
    2833             : }
    2834             : 
    2835           1 : static int mov_write_tapt_tag(AVIOContext *pb, MOVTrack *track)
    2836             : {
    2837           1 :     int32_t width = av_rescale(track->par->sample_aspect_ratio.num, track->par->width,
    2838           1 :                                track->par->sample_aspect_ratio.den);
    2839             : 
    2840           1 :     int64_t pos = avio_tell(pb);
    2841             : 
    2842           1 :     avio_wb32(pb, 0); /* size */
    2843           1 :     ffio_wfourcc(pb, "tapt");
    2844             : 
    2845           1 :     avio_wb32(pb, 20);
    2846           1 :     ffio_wfourcc(pb, "clef");
    2847           1 :     avio_wb32(pb, 0);
    2848           1 :     avio_wb32(pb, width << 16);
    2849           1 :     avio_wb32(pb, track->par->height << 16);
    2850             : 
    2851           1 :     avio_wb32(pb, 20);
    2852           1 :     ffio_wfourcc(pb, "prof");
    2853           1 :     avio_wb32(pb, 0);
    2854           1 :     avio_wb32(pb, width << 16);
    2855           1 :     avio_wb32(pb, track->par->height << 16);
    2856             : 
    2857           1 :     avio_wb32(pb, 20);
    2858           1 :     ffio_wfourcc(pb, "enof");
    2859           1 :     avio_wb32(pb, 0);
    2860           1 :     avio_wb32(pb, track->par->width << 16);
    2861           1 :     avio_wb32(pb, track->par->height << 16);
    2862             : 
    2863           1 :     return update_size(pb, pos);
    2864             : }
    2865             : 
    2866             : // This box seems important for the psp playback ... without it the movie seems to hang
    2867         208 : static int mov_write_edts_tag(AVIOContext *pb, MOVMuxContext *mov,
    2868             :                               MOVTrack *track)
    2869             : {
    2870         208 :     int64_t duration = av_rescale_rnd(track->track_duration, MOV_TIMESCALE,
    2871         208 :                                       track->timescale, AV_ROUND_UP);
    2872         208 :     int version = duration < INT32_MAX ? 0 : 1;
    2873             :     int entry_size, entry_count, size;
    2874         208 :     int64_t delay, start_ct = track->start_cts;
    2875         208 :     int64_t start_dts = track->start_dts;
    2876             : 
    2877         208 :     if (track->entry) {
    2878         156 :         if (start_dts != track->cluster[0].dts || start_ct != track->cluster[0].cts) {
    2879             : 
    2880           0 :             av_log(mov->fc, AV_LOG_DEBUG,
    2881             :                    "EDTS using dts:%"PRId64" cts:%d instead of dts:%"PRId64" cts:%"PRId64" tid:%d\n",
    2882           0 :                    track->cluster[0].dts, track->cluster[0].cts,
    2883             :                    start_dts, start_ct, track->track_id);
    2884           0 :             start_dts = track->cluster[0].dts;
    2885           0 :             start_ct  = track->cluster[0].cts;
    2886             :         }
    2887             :     }
    2888             : 
    2889         208 :     delay = av_rescale_rnd(start_dts + start_ct, MOV_TIMESCALE,
    2890         208 :                            track->timescale, AV_ROUND_DOWN);
    2891         208 :     version |= delay < INT32_MAX ? 0 : 1;
    2892             : 
    2893         208 :     entry_size = (version == 1) ? 20 : 12;
    2894         208 :     entry_count = 1 + (delay > 0);
    2895         208 :     size = 24 + entry_count * entry_size;
    2896             : 
    2897             :     /* write the atom data */
    2898         208 :     avio_wb32(pb, size);
    2899         208 :     ffio_wfourcc(pb, "edts");
    2900         208 :     avio_wb32(pb, size - 8);
    2901         208 :     ffio_wfourcc(pb, "elst");
    2902         208 :     avio_w8(pb, version);
    2903         208 :     avio_wb24(pb, 0); /* flags */
    2904             : 
    2905         208 :     avio_wb32(pb, entry_count);
    2906         208 :     if (delay > 0) { /* add an empty edit to delay presentation */
    2907             :         /* In the positive delay case, the delay includes the cts
    2908             :          * offset, and the second edit list entry below trims out
    2909             :          * the same amount from the actual content. This makes sure
    2910             :          * that the offset last sample is included in the edit
    2911             :          * list duration as well. */
    2912           1 :         if (version == 1) {
    2913           0 :             avio_wb64(pb, delay);
    2914           0 :             avio_wb64(pb, -1);
    2915             :         } else {
    2916           1 :             avio_wb32(pb, delay);
    2917           1 :             avio_wb32(pb, -1);
    2918             :         }
    2919           1 :         avio_wb32(pb, 0x00010000);
    2920             :     } else {
    2921             :         /* Avoid accidentally ending up with start_ct = -1 which has got a
    2922             :          * special meaning. Normally start_ct should end up positive or zero
    2923             :          * here, but use FFMIN in case dts is a small positive integer
    2924             :          * rounded to 0 when represented in MOV_TIMESCALE units. */
    2925         207 :         av_assert0(av_rescale_rnd(start_dts, MOV_TIMESCALE, track->timescale, AV_ROUND_DOWN) <= 0);
    2926         207 :         start_ct  = -FFMIN(start_dts, 0);
    2927             :         /* Note, this delay is calculated from the pts of the first sample,
    2928             :          * ensuring that we don't reduce the duration for cases with
    2929             :          * dts<0 pts=0. */
    2930         207 :         duration += delay;
    2931             :     }
    2932             : 
    2933             :     /* For fragmented files, we don't know the full length yet. Setting
    2934             :      * duration to 0 allows us to only specify the offset, including
    2935             :      * the rest of the content (from all future fragments) without specifying
    2936             :      * an explicit duration. */
    2937         208 :     if (mov->flags & FF_MOV_FLAG_FRAGMENT)
    2938          56 :         duration = 0;
    2939             : 
    2940             :     /* duration */
    2941         208 :     if (version == 1) {
    2942           0 :         avio_wb64(pb, duration);
    2943           0 :         avio_wb64(pb, start_ct);
    2944             :     } else {
    2945         208 :         avio_wb32(pb, duration);
    2946         208 :         avio_wb32(pb, start_ct);
    2947             :     }
    2948         208 :     avio_wb32(pb, 0x00010000);
    2949         208 :     return size;
    2950             : }
    2951             : 
    2952          11 : static int mov_write_tref_tag(AVIOContext *pb, MOVTrack *track)
    2953             : {
    2954          11 :     avio_wb32(pb, 20);   // size
    2955          11 :     ffio_wfourcc(pb, "tref");
    2956          11 :     avio_wb32(pb, 12);   // size (subatom)
    2957          11 :     avio_wl32(pb, track->tref_tag);
    2958          11 :     avio_wb32(pb, track->tref_id);
    2959          11 :     return 20;
    2960             : }
    2961             : 
    2962             : // goes at the end of each track!  ... Critical for PSP playback ("Incompatible data" without it)
    2963           2 : static int mov_write_uuid_tag_psp(AVIOContext *pb, MOVTrack *mov)
    2964             : {
    2965           2 :     avio_wb32(pb, 0x34); /* size ... reports as 28 in mp4box! */
    2966           2 :     ffio_wfourcc(pb, "uuid");
    2967           2 :     ffio_wfourcc(pb, "USMT");
    2968           2 :     avio_wb32(pb, 0x21d24fce);
    2969           2 :     avio_wb32(pb, 0xbb88695c);
    2970           2 :     avio_wb32(pb, 0xfac9c740);
    2971           2 :     avio_wb32(pb, 0x1c);     // another size here!
    2972           2 :     ffio_wfourcc(pb, "MTDT");
    2973           2 :     avio_wb32(pb, 0x00010012);
    2974           2 :     avio_wb32(pb, 0x0a);
    2975           2 :     avio_wb32(pb, 0x55c40000);
    2976           2 :     avio_wb32(pb, 0x1);
    2977           2 :     avio_wb32(pb, 0x0);
    2978           2 :     return 0x34;
    2979             : }
    2980             : 
    2981           2 : static int mov_write_udta_sdp(AVIOContext *pb, MOVTrack *track)
    2982             : {
    2983           2 :     AVFormatContext *ctx = track->rtp_ctx;
    2984           2 :     char buf[1000] = "";
    2985             :     int len;
    2986             : 
    2987           2 :     ff_sdp_write_media(buf, sizeof(buf), ctx->streams[0], track->src_track,
    2988             :                        NULL, NULL, 0, 0, ctx);
    2989           2 :     av_strlcatf(buf, sizeof(buf), "a=control:streamid=%d\r\n", track->track_id);
    2990           2 :     len = strlen(buf);
    2991             : 
    2992           2 :     avio_wb32(pb, len + 24);
    2993           2 :     ffio_wfourcc(pb, "udta");
    2994           2 :     avio_wb32(pb, len + 16);
    2995           2 :     ffio_wfourcc(pb, "hnti");
    2996           2 :     avio_wb32(pb, len + 8);
    2997           2 :     ffio_wfourcc(pb, "sdp ");
    2998           2 :     avio_write(pb, buf, len);
    2999           2 :     return len + 24;
    3000             : }
    3001             : 
    3002         101 : static int mov_write_track_metadata(AVIOContext *pb, AVStream *st,
    3003             :                                     const char *tag, const char *str)
    3004             : {
    3005         101 :     int64_t pos = avio_tell(pb);
    3006         101 :     AVDictionaryEntry *t = av_dict_get(st->metadata, str, NULL, 0);
    3007         101 :     if (!t || !utf8len(t->value))
    3008         101 :         return 0;
    3009             : 
    3010           0 :     avio_wb32(pb, 0);   /* size */
    3011           0 :     ffio_wfourcc(pb, tag); /* type */
    3012           0 :     avio_write(pb, t->value, strlen(t->value)); /* UTF8 string value */
    3013           0 :     return update_size(pb, pos);
    3014             : }
    3015             : 
    3016         248 : static int mov_write_track_udta_tag(AVIOContext *pb, MOVMuxContext *mov,
    3017             :                                     AVStream *st)
    3018             : {
    3019             :     AVIOContext *pb_buf;
    3020             :     int ret, size;
    3021             :     uint8_t *buf;
    3022             : 
    3023         248 :     if (!st)
    3024          10 :         return 0;
    3025             : 
    3026         238 :     ret = avio_open_dyn_buf(&pb_buf);
    3027         238 :     if (ret < 0)
    3028           0 :         return ret;
    3029             : 
    3030         238 :     if (mov->mode & MODE_MP4)
    3031         101 :         mov_write_track_metadata(pb_buf, st, "name", "title");
    3032             : 
    3033         238 :     if ((size = avio_close_dyn_buf(pb_buf, &buf)) > 0) {
    3034           0 :         avio_wb32(pb, size + 8);
    3035           0 :         ffio_wfourcc(pb, "udta");
    3036           0 :         avio_write(pb, buf, size);
    3037             :     }
    3038         238 :     av_free(buf);
    3039             : 
    3040         238 :     return 0;
    3041             : }
    3042             : 
    3043         248 : static int mov_write_trak_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov,
    3044             :                               MOVTrack *track, AVStream *st)
    3045             : {
    3046         248 :     int64_t pos = avio_tell(pb);
    3047         248 :     int entry_backup = track->entry;
    3048         248 :     int chunk_backup = track->chunkCount;
    3049             :     int ret;
    3050             : 
    3051             :     /* If we want to have an empty moov, but some samples already have been
    3052             :      * buffered (delay_moov), pretend that no samples have been written yet. */
    3053         248 :     if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV)
    3054          84 :         track->chunkCount = track->entry = 0;
    3055             : 
    3056         248 :     avio_wb32(pb, 0); /* size */
    3057         248 :     ffio_wfourcc(pb, "trak");
    3058         248 :     mov_write_tkhd_tag(pb, mov, track, st);
    3059             : 
    3060             :     av_assert2(mov->use_editlist >= 0);
    3061             : 
    3062         248 :     if (track->start_dts != AV_NOPTS_VALUE) {
    3063         224 :         if (mov->use_editlist)
    3064         208 :             mov_write_edts_tag(pb, mov, track);  // PSP Movies and several other cases require edts box
    3065          16 :         else if ((track->entry && track->cluster[0].dts) || track->mode == MODE_PSP || is_clcp_track(track))
    3066           0 :             av_log(mov->fc, AV_LOG_WARNING,
    3067             :                    "Not writing any edit list even though one would have been required\n");
    3068             :     }
    3069             : 
    3070         248 :     if (track->tref_tag)
    3071          11 :         mov_write_tref_tag(pb, track);
    3072             : 
    3073         248 :     if ((ret = mov_write_mdia_tag(s, pb, mov, track)) < 0)
    3074           0 :         return ret;
    3075         248 :     if (track->mode == MODE_PSP)
    3076           2 :         mov_write_uuid_tag_psp(pb, track); // PSP Movies require this uuid box
    3077         248 :     if (track->tag == MKTAG('r','t','p',' '))
    3078           2 :         mov_write_udta_sdp(pb, track);
    3079         248 :     if (track->mode == MODE_MOV) {
    3080         135 :         if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
    3081          98 :             double sample_aspect_ratio = av_q2d(st->sample_aspect_ratio);
    3082          98 :             if (st->sample_aspect_ratio.num && 1.0 != sample_aspect_ratio) {
    3083           1 :                 mov_write_tapt_tag(pb, track);
    3084             :             }
    3085             :         }
    3086         135 :         if (is_clcp_track(track) && st->sample_aspect_ratio.num) {
    3087           0 :             mov_write_tapt_tag(pb, track);
    3088             :         }
    3089             :     }
    3090         248 :     mov_write_track_udta_tag(pb, mov, st);
    3091         248 :     track->entry = entry_backup;
    3092         248 :     track->chunkCount = chunk_backup;
    3093         248 :     return update_size(pb, pos);
    3094             : }
    3095             : 
    3096           0 : static int mov_write_iods_tag(AVIOContext *pb, MOVMuxContext *mov)
    3097             : {
    3098           0 :     int i, has_audio = 0, has_video = 0;
    3099           0 :     int64_t pos = avio_tell(pb);
    3100           0 :     int audio_profile = mov->iods_audio_profile;
    3101           0 :     int video_profile = mov->iods_video_profile;
    3102           0 :     for (i = 0; i < mov->nb_streams; i++) {
    3103           0 :         if (mov->tracks[i].entry > 0 || mov->flags & FF_MOV_FLAG_EMPTY_MOOV) {
    3104           0 :             has_audio |= mov->tracks[i].par->codec_type == AVMEDIA_TYPE_AUDIO;
    3105           0 :             has_video |= mov->tracks[i].par->codec_type == AVMEDIA_TYPE_VIDEO;
    3106             :         }
    3107             :     }
    3108           0 :     if (audio_profile < 0)
    3109           0 :         audio_profile = 0xFF - has_audio;
    3110           0 :     if (video_profile < 0)
    3111           0 :         video_profile = 0xFF - has_video;
    3112           0 :     avio_wb32(pb, 0x0); /* size */
    3113           0 :     ffio_wfourcc(pb, "iods");
    3114           0 :     avio_wb32(pb, 0);    /* version & flags */
    3115           0 :     put_descr(pb, 0x10, 7);
    3116           0 :     avio_wb16(pb, 0x004f);
    3117           0 :     avio_w8(pb, 0xff);
    3118           0 :     avio_w8(pb, 0xff);
    3119           0 :     avio_w8(pb, audio_profile);
    3120           0 :     avio_w8(pb, video_profile);
    3121           0 :     avio_w8(pb, 0xff);
    3122           0 :     return update_size(pb, pos);
    3123             : }
    3124             : 
    3125          96 : static int mov_write_trex_tag(AVIOContext *pb, MOVTrack *track)
    3126             : {
    3127          96 :     avio_wb32(pb, 0x20); /* size */
    3128          96 :     ffio_wfourcc(pb, "trex");
    3129          96 :     avio_wb32(pb, 0);   /* version & flags */
    3130          96 :     avio_wb32(pb, track->track_id); /* track ID */
    3131          96 :     avio_wb32(pb, 1);   /* default sample description index */
    3132          96 :     avio_wb32(pb, 0);   /* default sample duration */
    3133          96 :     avio_wb32(pb, 0);   /* default sample size */
    3134          96 :     avio_wb32(pb, 0);   /* default sample flags */
    3135          96 :     return 0;
    3136             : }
    3137             : 
    3138          50 : static int mov_write_mvex_tag(AVIOContext *pb, MOVMuxContext *mov)
    3139             : {
    3140          50 :     int64_t pos = avio_tell(pb);
    3141             :     int i;
    3142          50 :     avio_wb32(pb, 0x0); /* size */
    3143          50 :     ffio_wfourcc(pb, "mvex");
    3144         146 :     for (i = 0; i < mov->nb_streams; i++)
    3145          96 :         mov_write_trex_tag(pb, &mov->tracks[i]);
    3146          50 :     return update_size(pb, pos);
    3147             : }
    3148             : 
    3149         174 : static int mov_write_mvhd_tag(AVIOContext *pb, MOVMuxContext *mov)
    3150             : {
    3151         174 :     int max_track_id = 1, i;
    3152         174 :     int64_t max_track_len = 0;
    3153             :     int version;
    3154             : 
    3155         422 :     for (i = 0; i < mov->nb_streams; i++) {
    3156         248 :         if (mov->tracks[i].entry > 0 && mov->tracks[i].timescale) {
    3157         224 :             int64_t max_track_len_temp = av_rescale_rnd(mov->tracks[i].track_duration,
    3158             :                                                 MOV_TIMESCALE,
    3159         224 :                                                 mov->tracks[i].timescale,
    3160             :                                                 AV_ROUND_UP);
    3161         224 :             if (max_track_len < max_track_len_temp)
    3162         182 :                 max_track_len = max_track_len_temp;
    3163         224 :             if (max_track_id < mov->tracks[i].track_id)
    3164          62 :                 max_track_id = mov->tracks[i].track_id;
    3165             :         }
    3166             :     }
    3167             :     /* If using delay_moov, make sure the output is the same as if no
    3168             :      * samples had been written yet. */
    3169         174 :     if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV) {
    3170          44 :         max_track_len = 0;
    3171          44 :         max_track_id  = 1;
    3172             :     }
    3173             : 
    3174         174 :     version = max_track_len < UINT32_MAX ? 0 : 1;
    3175         174 :     avio_wb32(pb, version == 1 ? 120 : 108); /* size */
    3176             : 
    3177         174 :     ffio_wfourcc(pb, "mvhd");
    3178         174 :     avio_w8(pb, version);
    3179         174 :     avio_wb24(pb, 0); /* flags */
    3180         174 :     if (version == 1) {
    3181           0 :         avio_wb64(pb, mov->time);
    3182           0 :         avio_wb64(pb, mov->time);
    3183             :     } else {
    3184         174 :         avio_wb32(pb, mov->time); /* creation time */
    3185         174 :         avio_wb32(pb, mov->time); /* modification time */
    3186             :     }
    3187         174 :     avio_wb32(pb, MOV_TIMESCALE);
    3188         174 :     (version == 1) ? avio_wb64(pb, max_track_len) : avio_wb32(pb, max_track_len); /* duration of longest track */
    3189             : 
    3190         174 :     avio_wb32(pb, 0x00010000); /* reserved (preferred rate) 1.0 = normal */
    3191         174 :     avio_wb16(pb, 0x0100); /* reserved (preferred volume) 1.0 = normal */
    3192         174 :     avio_wb16(pb, 0); /* reserved */
    3193         174 :     avio_wb32(pb, 0); /* reserved */
    3194         174 :     avio_wb32(pb, 0); /* reserved */
    3195             : 
    3196             :     /* Matrix structure */
    3197         174 :     write_matrix(pb, 1, 0, 0, 1, 0, 0);
    3198             : 
    3199         174 :     avio_wb32(pb, 0); /* reserved (preview time) */
    3200         174 :     avio_wb32(pb, 0); /* reserved (preview duration) */
    3201         174 :     avio_wb32(pb, 0); /* reserved (poster time) */
    3202         174 :     avio_wb32(pb, 0); /* reserved (selection time) */
    3203         174 :     avio_wb32(pb, 0); /* reserved (selection duration) */
    3204         174 :     avio_wb32(pb, 0); /* reserved (current time) */
    3205         174 :     avio_wb32(pb, max_track_id + 1); /* Next track id */
    3206         174 :     return 0x6c;
    3207             : }
    3208             : 
    3209          60 : static int mov_write_itunes_hdlr_tag(AVIOContext *pb, MOVMuxContext *mov,
    3210             :                                      AVFormatContext *s)
    3211             : {
    3212          60 :     avio_wb32(pb, 33); /* size */
    3213          60 :     ffio_wfourcc(pb, "hdlr");
    3214          60 :     avio_wb32(pb, 0);
    3215          60 :     avio_wb32(pb, 0);
    3216          60 :     ffio_wfourcc(pb, "mdir");
    3217          60 :     ffio_wfourcc(pb, "appl");
    3218          60 :     avio_wb32(pb, 0);
    3219          60 :     avio_wb32(pb, 0);
    3220          60 :     avio_w8(pb, 0);
    3221          60 :     return 33;
    3222             : }
    3223             : 
    3224             : /* helper function to write a data tag with the specified string as data */
    3225          31 : static int mov_write_string_data_tag(AVIOContext *pb, const char *data, int lang, int long_style)
    3226             : {
    3227          31 :     if (long_style) {
    3228           6 :         int size = 16 + strlen(data);
    3229           6 :         avio_wb32(pb, size); /* size */
    3230           6 :         ffio_wfourcc(pb, "data");
    3231           6 :         avio_wb32(pb, 1);
    3232           6 :         avio_wb32(pb, 0);
    3233           6 :         avio_write(pb, data, strlen(data));
    3234           6 :         return size;
    3235             :     } else {
    3236          25 :         if (!lang)
    3237          21 :             lang = ff_mov_iso639_to_lang("und", 1);
    3238          25 :         avio_wb16(pb, strlen(data)); /* string length */
    3239          25 :         avio_wb16(pb, lang);
    3240          25 :         avio_write(pb, data, strlen(data));
    3241          25 :         return strlen(data) + 4;
    3242             :     }
    3243             : }
    3244             : 
    3245          31 : static int mov_write_string_tag(AVIOContext *pb, const char *name,
    3246             :                                 const char *value, int lang, int long_style)
    3247             : {
    3248          31 :     int size = 0;
    3249          31 :     if (value && value[0]) {
    3250          31 :         int64_t pos = avio_tell(pb);
    3251          31 :         avio_wb32(pb, 0); /* size */
    3252          31 :         ffio_wfourcc(pb, name);
    3253          31 :         mov_write_string_data_tag(pb, value, lang, long_style);
    3254          31 :         size = update_size(pb, pos);
    3255             :     }
    3256          31 :     return size;
    3257             : }
    3258             : 
    3259        2722 : static AVDictionaryEntry *get_metadata_lang(AVFormatContext *s,
    3260             :                                             const char *tag, int *lang)
    3261             : {
    3262             :     int l, len, len2;
    3263        2722 :     AVDictionaryEntry *t, *t2 = NULL;
    3264             :     char tag2[16];
    3265             : 
    3266        2722 :     *lang = 0;
    3267             : 
    3268        2722 :     if (!(t = av_dict_get(s->metadata, tag, NULL, 0)))
    3269        2691 :         return NULL;
    3270             : 
    3271          31 :     len = strlen(t->key);
    3272          31 :     snprintf(tag2, sizeof(tag2), "%s-", tag);
    3273          62 :     while ((t2 = av_dict_get(s->metadata, tag2, t2, AV_DICT_IGNORE_SUFFIX))) {
    3274           4 :         len2 = strlen(t2->key);
    3275           4 :         if (len2 == len + 4 && !strcmp(t->value, t2->value)
    3276           4 :             && (l = ff_mov_iso639_to_lang(&t2->key[len2 - 3], 1)) >= 0) {
    3277           4 :             *lang = l;
    3278           4 :             return t;
    3279             :         }
    3280             :     }
    3281          27 :     return t;
    3282             : }
    3283             : 
    3284        2662 : static int mov_write_string_metadata(AVFormatContext *s, AVIOContext *pb,
    3285             :                                      const char *name, const char *tag,
    3286             :                                      int long_style)
    3287             : {
    3288             :     int lang;
    3289        2662 :     AVDictionaryEntry *t = get_metadata_lang(s, tag, &lang);
    3290        2662 :     if (!t)
    3291        2631 :         return 0;
    3292          31 :     return mov_write_string_tag(pb, name, t->value, lang, long_style);
    3293             : }
    3294             : 
    3295             : /* iTunes bpm number */
    3296          60 : static int mov_write_tmpo_tag(AVIOContext *pb, AVFormatContext *s)
    3297             : {
    3298          60 :     AVDictionaryEntry *t = av_dict_get(s->metadata, "tmpo", NULL, 0);
    3299          60 :     int size = 0, tmpo = t ? atoi(t->value) : 0;
    3300          60 :     if (tmpo) {
    3301           0 :         size = 26;
    3302           0 :         avio_wb32(pb, size);
    3303           0 :         ffio_wfourcc(pb, "tmpo");
    3304           0 :         avio_wb32(pb, size-8); /* size */
    3305           0 :         ffio_wfourcc(pb, "data");
    3306           0 :         avio_wb32(pb, 0x15);  //type specifier
    3307           0 :         avio_wb32(pb, 0);
    3308           0 :         avio_wb16(pb, tmpo);        // data
    3309             :     }
    3310          60 :     return size;
    3311             : }
    3312             : 
    3313             : /* 3GPP TS 26.244 */
    3314          60 : static int mov_write_loci_tag(AVFormatContext *s, AVIOContext *pb)
    3315             : {
    3316             :     int lang;
    3317          60 :     int64_t pos = avio_tell(pb);
    3318             :     double latitude, longitude, altitude;
    3319             :     int32_t latitude_fix, longitude_fix, altitude_fix;
    3320          60 :     AVDictionaryEntry *t = get_metadata_lang(s, "location", &lang);
    3321          60 :     const char *ptr, *place = "";
    3322             :     char *end;
    3323             :     static const char *astronomical_body = "earth";
    3324          60 :     if (!t)
    3325          60 :         return 0;
    3326             : 
    3327           0 :     ptr = t->value;
    3328           0 :     longitude = strtod(ptr, &end);
    3329           0 :     if (end == ptr) {
    3330           0 :         av_log(s, AV_LOG_WARNING, "malformed location metadata\n");
    3331           0 :         return 0;
    3332             :     }
    3333           0 :     ptr = end;
    3334           0 :     latitude = strtod(ptr, &end);
    3335           0 :     if (end == ptr) {
    3336           0 :         av_log(s, AV_LOG_WARNING, "malformed location metadata\n");
    3337           0 :         return 0;
    3338             :     }
    3339           0 :     ptr = end;
    3340           0 :     altitude = strtod(ptr, &end);
    3341             :     /* If no altitude was present, the default 0 should be fine */
    3342           0 :     if (*end == '/')
    3343           0 :         place = end + 1;
    3344             : 
    3345           0 :     latitude_fix  = (int32_t) ((1 << 16) * latitude);
    3346           0 :     longitude_fix = (int32_t) ((1 << 16) * longitude);
    3347           0 :     altitude_fix  = (int32_t) ((1 << 16) * altitude);
    3348             : 
    3349           0 :     avio_wb32(pb, 0);         /* size */
    3350           0 :     ffio_wfourcc(pb, "loci"); /* type */
    3351           0 :     avio_wb32(pb, 0);         /* version + flags */
    3352           0 :     avio_wb16(pb, lang);
    3353           0 :     avio_write(pb, place, strlen(place) + 1);
    3354           0 :     avio_w8(pb, 0);           /* role of place (0 == shooting location, 1 == real location, 2 == fictional location) */
    3355           0 :     avio_wb32(pb, latitude_fix);
    3356           0 :     avio_wb32(pb, longitude_fix);
    3357           0 :     avio_wb32(pb, altitude_fix);
    3358           0 :     avio_write(pb, astronomical_body, strlen(astronomical_body) + 1);
    3359           0 :     avio_w8(pb, 0);           /* additional notes, null terminated string */
    3360             : 
    3361           0 :     return update_size(pb, pos);
    3362             : }
    3363             : 
    3364             : /* iTunes track or disc number */
    3365         120 : static int mov_write_trkn_tag(AVIOContext *pb, MOVMuxContext *mov,
    3366             :                               AVFormatContext *s, int disc)
    3367             : {
    3368         120 :     AVDictionaryEntry *t = av_dict_get(s->metadata,
    3369             :                                        disc ? "disc" : "track",
    3370             :                                        NULL, 0);
    3371         120 :     int size = 0, track = t ? atoi(t->value) : 0;
    3372         120 :     if (track) {
    3373           0 :         int tracks = 0;
    3374           0 :         char *slash = strchr(t->value, '/');
    3375           0 :         if (slash)
    3376           0 :             tracks = atoi(slash + 1);
    3377           0 :         avio_wb32(pb, 32); /* size */
    3378           0 :         ffio_wfourcc(pb, disc ? "disk" : "trkn");
    3379           0 :         avio_wb32(pb, 24); /* size */
    3380           0 :         ffio_wfourcc(pb, "data");
    3381           0 :         avio_wb32(pb, 0);        // 8 bytes empty
    3382           0 :         avio_wb32(pb, 0);
    3383           0 :         avio_wb16(pb, 0);        // empty
    3384           0 :         avio_wb16(pb, track);    // track / disc number
    3385           0 :         avio_wb16(pb, tracks);   // total track / disc number
    3386           0 :         avio_wb16(pb, 0);        // empty
    3387           0 :         size = 32;
    3388             :     }
    3389         120 :     return size;
    3390             : }
    3391             : 
    3392         360 : static int mov_write_int8_metadata(AVFormatContext *s, AVIOContext *pb,
    3393             :                                    const char *name, const char *tag,
    3394             :                                    int len)
    3395             : {
    3396         360 :     AVDictionaryEntry *t = NULL;
    3397             :     uint8_t num;
    3398         360 :     int size = 24 + len;
    3399             : 
    3400         360 :     if (len != 1 && len != 4)
    3401           0 :         return -1;
    3402             : 
    3403         360 :     if (!(t = av_dict_get(s->metadata, tag, NULL, 0)))
    3404         360 :         return 0;
    3405           0 :     num = atoi(t->value);
    3406             : 
    3407           0 :     avio_wb32(pb, size);
    3408           0 :     ffio_wfourcc(pb, name);
    3409           0 :     avio_wb32(pb, size - 8);
    3410           0 :     ffio_wfourcc(pb, "data");
    3411           0 :     avio_wb32(pb, 0x15);
    3412           0 :     avio_wb32(pb, 0);
    3413           0 :     if (len==4) avio_wb32(pb, num);
    3414           0 :     else        avio_w8 (pb, num);
    3415             : 
    3416           0 :     return size;
    3417             : }
    3418             : 
    3419             : /* iTunes meta data list */
    3420          60 : static int mov_write_ilst_tag(AVIOContext *pb, MOVMuxContext *mov,
    3421             :                               AVFormatContext *s)
    3422             : {
    3423          60 :     int64_t pos = avio_tell(pb);
    3424          60 :     avio_wb32(pb, 0); /* size */
    3425          60 :     ffio_wfourcc(pb, "ilst");
    3426          60 :     mov_write_string_metadata(s, pb, "\251nam", "title"    , 1);
    3427          60 :     mov_write_string_metadata(s, pb, "\251ART", "artist"   , 1);
    3428          60 :     mov_write_string_metadata(s, pb, "aART", "album_artist", 1);
    3429          60 :     mov_write_string_metadata(s, pb, "\251wrt", "composer" , 1);
    3430          60 :     mov_write_string_metadata(s, pb, "\251alb", "album"    , 1);
    3431          60 :     mov_write_string_metadata(s, pb, "\251day", "date"     , 1);
    3432          60 :     if (!mov_write_string_metadata(s, pb, "\251too", "encoding_tool", 1)) {
    3433          60 :         if (!(s->flags & AVFMT_FLAG_BITEXACT))
    3434           0 :             mov_write_string_tag(pb, "\251too", LIBAVFORMAT_IDENT, 0, 1);
    3435             :     }
    3436          60 :     mov_write_string_metadata(s, pb, "\251cmt", "comment"  , 1);
    3437          60 :     mov_write_string_metadata(s, pb, "\251gen", "genre"    , 1);
    3438          60 :     mov_write_string_metadata(s, pb, "\251cpy", "copyright", 1);
    3439          60 :     mov_write_string_metadata(s, pb, "\251grp", "grouping" , 1);
    3440          60 :     mov_write_string_metadata(s, pb, "\251lyr", "lyrics"   , 1);
    3441          60 :     mov_write_string_metadata(s, pb, "desc",    "description",1);
    3442          60 :     mov_write_string_metadata(s, pb, "ldes",    "synopsis" , 1);
    3443          60 :     mov_write_string_metadata(s, pb, "tvsh",    "show"     , 1);
    3444          60 :     mov_write_string_metadata(s, pb, "tven",    "episode_id",1);
    3445          60 :     mov_write_string_metadata(s, pb, "tvnn",    "network"  , 1);
    3446          60 :     mov_write_string_metadata(s, pb, "keyw",    "keywords"  , 1);
    3447          60 :     mov_write_int8_metadata  (s, pb, "tves",    "episode_sort",4);
    3448          60 :     mov_write_int8_metadata  (s, pb, "tvsn",    "season_number",4);
    3449          60 :     mov_write_int8_metadata  (s, pb, "stik",    "media_type",1);
    3450          60 :     mov_write_int8_metadata  (s, pb, "hdvd",    "hd_video",  1);
    3451          60 :     mov_write_int8_metadata  (s, pb, "pgap",    "gapless_playback",1);
    3452          60 :     mov_write_int8_metadata  (s, pb, "cpil",    "compilation", 1);
    3453          60 :     mov_write_trkn_tag(pb, mov, s, 0); // track number
    3454          60 :     mov_write_trkn_tag(pb, mov, s, 1); // disc number
    3455          60 :     mov_write_tmpo_tag(pb, s);
    3456          60 :     return update_size(pb, pos);
    3457             : }
    3458             : 
    3459           0 : static int mov_write_mdta_hdlr_tag(AVIOContext *pb, MOVMuxContext *mov,
    3460             :                                    AVFormatContext *s)
    3461             : {
    3462           0 :     avio_wb32(pb, 33); /* size */
    3463           0 :     ffio_wfourcc(pb, "hdlr");
    3464           0 :     avio_wb32(pb, 0);
    3465           0 :     avio_wb32(pb, 0);
    3466           0 :     ffio_wfourcc(pb, "mdta");
    3467           0 :     avio_wb32(pb, 0);
    3468           0 :     avio_wb32(pb, 0);
    3469           0 :     avio_wb32(pb, 0);
    3470           0 :     avio_w8(pb, 0);
    3471           0 :     return 33;
    3472             : }
    3473             : 
    3474           0 : static int mov_write_mdta_keys_tag(AVIOContext *pb, MOVMuxContext *mov,
    3475             :                                    AVFormatContext *s)
    3476             : {
    3477           0 :     AVDictionaryEntry *t = NULL;
    3478           0 :     int64_t pos = avio_tell(pb);
    3479             :     int64_t curpos, entry_pos;
    3480           0 :     int count = 0;
    3481             : 
    3482           0 :     avio_wb32(pb, 0); /* size */
    3483           0 :     ffio_wfourcc(pb, "keys");
    3484           0 :     avio_wb32(pb, 0);
    3485           0 :     entry_pos = avio_tell(pb);
    3486           0 :     avio_wb32(pb, 0); /* entry count */
    3487             : 
    3488           0 :     while (t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX)) {
    3489           0 :         avio_wb32(pb, strlen(t->key) + 8);
    3490           0 :         ffio_wfourcc(pb, "mdta");
    3491           0 :         avio_write(pb, t->key, strlen(t->key));
    3492           0 :         count += 1;
    3493             :     }
    3494           0 :     curpos = avio_tell(pb);
    3495           0 :     avio_seek(pb, entry_pos, SEEK_SET);
    3496           0 :     avio_wb32(pb, count); // rewrite entry count
    3497           0 :     avio_seek(pb, curpos, SEEK_SET);
    3498             : 
    3499           0 :     return update_size(pb, pos);
    3500             : }
    3501             : 
    3502           0 : static int mov_write_mdta_ilst_tag(AVIOContext *pb, MOVMuxContext *mov,
    3503             :                                    AVFormatContext *s)
    3504             : {
    3505           0 :     AVDictionaryEntry *t = NULL;
    3506           0 :     int64_t pos = avio_tell(pb);
    3507           0 :     int count = 1; /* keys are 1-index based */
    3508             : 
    3509           0 :     avio_wb32(pb, 0); /* size */
    3510           0 :     ffio_wfourcc(pb, "ilst");
    3511             : 
    3512           0 :     while (t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX)) {
    3513           0 :         int64_t entry_pos = avio_tell(pb);
    3514           0 :         avio_wb32(pb, 0); /* size */
    3515           0 :         avio_wb32(pb, count); /* key */
    3516           0 :         mov_write_string_data_tag(pb, t->value, 0, 1);
    3517           0 :         update_size(pb, entry_pos);
    3518           0 :         count += 1;
    3519             :     }
    3520           0 :     return update_size(pb, pos);
    3521             : }
    3522             : 
    3523             : /* meta data tags */
    3524          60 : static int mov_write_meta_tag(AVIOContext *pb, MOVMuxContext *mov,
    3525             :                               AVFormatContext *s)
    3526             : {
    3527          60 :     int size = 0;
    3528          60 :     int64_t pos = avio_tell(pb);
    3529          60 :     avio_wb32(pb, 0); /* size */
    3530          60 :     ffio_wfourcc(pb, "meta");
    3531          60 :     avio_wb32(pb, 0);
    3532          60 :     if (mov->flags & FF_MOV_FLAG_USE_MDTA) {
    3533           0 :         mov_write_mdta_hdlr_tag(pb, mov, s);
    3534           0 :         mov_write_mdta_keys_tag(pb, mov, s);
    3535           0 :         mov_write_mdta_ilst_tag(pb, mov, s);
    3536             :     }
    3537             :     else {
    3538             :         /* iTunes metadata tag */
    3539          60 :         mov_write_itunes_hdlr_tag(pb, mov, s);
    3540          60 :         mov_write_ilst_tag(pb, mov, s);
    3541             :     }
    3542          60 :     size = update_size(pb, pos);
    3543          60 :     return size;
    3544             : }
    3545             : 
    3546         113 : static int mov_write_raw_metadata_tag(AVFormatContext *s, AVIOContext *pb,
    3547             :                                       const char *name, const char *key)
    3548             : {
    3549             :     int len;
    3550             :     AVDictionaryEntry *t;
    3551             : 
    3552         113 :     if (!(t = av_dict_get(s->metadata, key, NULL, 0)))
    3553         113 :         return 0;
    3554             : 
    3555           0 :     len = strlen(t->value);
    3556           0 :     if (len > 0) {
    3557           0 :         int size = len + 8;
    3558           0 :         avio_wb32(pb, size);
    3559           0 :         ffio_wfourcc(pb, name);
    3560           0 :         avio_write(pb, t->value, len);
    3561           0 :         return size;
    3562             :     }
    3563           0 :     return 0;
    3564             : }
    3565             : 
    3566           0 : static int ascii_to_wc(AVIOContext *pb, const uint8_t *b)
    3567             : {
    3568             :     int val;
    3569           0 :     while (*b) {
    3570           0 :         GET_UTF8(val, *b++, return -1;)
    3571           0 :         avio_wb16(pb, val);
    3572             :     }
    3573           0 :     avio_wb16(pb, 0x00);
    3574           0 :     return 0;
    3575             : }
    3576             : 
    3577           0 : static uint16_t language_code(const char *str)
    3578             : {
    3579           0 :     return (((str[0] - 0x60) & 0x1F) << 10) +
    3580           0 :            (((str[1] - 0x60) & 0x1F) <<  5) +
    3581           0 :            (( str[2] - 0x60) & 0x1F);
    3582             : }
    3583             : 
    3584           0 : static int mov_write_3gp_udta_tag(AVIOContext *pb, AVFormatContext *s,
    3585             :                                   const char *tag, const char *str)
    3586             : {
    3587           0 :     int64_t pos = avio_tell(pb);
    3588           0 :     AVDictionaryEntry *t = av_dict_get(s->metadata, str, NULL, 0);
    3589           0 :     if (!t || !utf8len(t->value))
    3590           0 :         return 0;
    3591           0 :     avio_wb32(pb, 0);   /* size */
    3592           0 :     ffio_wfourcc(pb, tag); /* type */
    3593           0 :     avio_wb32(pb, 0);   /* version + flags */
    3594           0 :     if (!strcmp(tag, "yrrc"))
    3595           0 :         avio_wb16(pb, atoi(t->value));
    3596             :     else {
    3597           0 :         avio_wb16(pb, language_code("eng")); /* language */
    3598           0 :         avio_write(pb, t->value, strlen(t->value) + 1); /* UTF8 string value */
    3599           0 :         if (!strcmp(tag, "albm") &&
    3600           0 :             (t = av_dict_get(s->metadata, "track", NULL, 0)))
    3601           0 :             avio_w8(pb, atoi(t->value));
    3602             :     }
    3603           0 :     return update_size(pb, pos);
    3604             : }
    3605             : 
    3606           0 : static int mov_write_chpl_tag(AVIOContext *pb, AVFormatContext *s)
    3607             : {
    3608           0 :     int64_t pos = avio_tell(pb);
    3609           0 :     int i, nb_chapters = FFMIN(s->nb_chapters, 255);
    3610             : 
    3611           0 :     avio_wb32(pb, 0);            // size
    3612           0 :     ffio_wfourcc(pb, "chpl");
    3613           0 :     avio_wb32(pb, 0x01000000);   // version + flags
    3614           0 :     avio_wb32(pb, 0);            // unknown
    3615           0 :     avio_w8(pb, nb_chapters);
    3616             : 
    3617           0 :     for (i = 0; i < nb_chapters; i++) {
    3618           0 :         AVChapter *c = s->chapters[i];
    3619             :         AVDictionaryEntry *t;
    3620           0 :         avio_wb64(pb, av_rescale_q(c->start, c->time_base, (AVRational){1,10000000}));
    3621             : 
    3622           0 :         if ((t = av_dict_get(c->metadata, "title", NULL, 0))) {
    3623           0 :             int len = FFMIN(strlen(t->value), 255);
    3624           0 :             avio_w8(pb, len);
    3625           0 :             avio_write(pb, t->value, len);
    3626             :         } else
    3627           0 :             avio_w8(pb, 0);
    3628             :     }
    3629           0 :     return update_size(pb, pos);
    3630             : }
    3631             : 
    3632         173 : static int mov_write_udta_tag(AVIOContext *pb, MOVMuxContext *mov,
    3633             :                               AVFormatContext *s)
    3634             : {
    3635             :     AVIOContext *pb_buf;
    3636             :     int ret, size;
    3637             :     uint8_t *buf;
    3638             : 
    3639         173 :     ret = avio_open_dyn_buf(&pb_buf);
    3640         173 :     if (ret < 0)
    3641           0 :         return ret;
    3642             : 
    3643         173 :     if (mov->mode & MODE_3GP) {
    3644           0 :         mov_write_3gp_udta_tag(pb_buf, s, "perf", "artist");
    3645           0 :         mov_write_3gp_udta_tag(pb_buf, s, "titl", "title");
    3646           0 :         mov_write_3gp_udta_tag(pb_buf, s, "auth", "author");
    3647           0 :         mov_write_3gp_udta_tag(pb_buf, s, "gnre", "genre");
    3648           0 :         mov_write_3gp_udta_tag(pb_buf, s, "dscp", "comment");
    3649           0 :         mov_write_3gp_udta_tag(pb_buf, s, "albm", "album");
    3650           0 :         mov_write_3gp_udta_tag(pb_buf, s, "cprt", "copyright");
    3651           0 :         mov_write_3gp_udta_tag(pb_buf, s, "yrrc", "date");
    3652           0 :         mov_write_loci_tag(s, pb_buf);
    3653         173 :     } else if (mov->mode == MODE_MOV && !(mov->flags & FF_MOV_FLAG_USE_MDTA)) { // the title field breaks gtkpod with mp4 and my suspicion is that stuff is not valid in mp4
    3654         113 :         mov_write_string_metadata(s, pb_buf, "\251ART", "artist",      0);
    3655         113 :         mov_write_string_metadata(s, pb_buf, "\251nam", "title",       0);
    3656         113 :         mov_write_string_metadata(s, pb_buf, "\251aut", "author",      0);
    3657         113 :         mov_write_string_metadata(s, pb_buf, "\251alb", "album",       0);
    3658         113 :         mov_write_string_metadata(s, pb_buf, "\251day", "date",        0);
    3659         113 :         mov_write_string_metadata(s, pb_buf, "\251swr", "encoder",     0);
    3660             :         // currently ignored by mov.c
    3661         113 :         mov_write_string_metadata(s, pb_buf, "\251des", "comment",     0);
    3662             :         // add support for libquicktime, this atom is also actually read by mov.c
    3663         113 :         mov_write_string_metadata(s, pb_buf, "\251cmt", "comment",     0);
    3664         113 :         mov_write_string_metadata(s, pb_buf, "\251gen", "genre",       0);
    3665         113 :         mov_write_string_metadata(s, pb_buf, "\251cpy", "copyright",   0);
    3666         113 :         mov_write_string_metadata(s, pb_buf, "\251mak", "make",        0);
    3667         113 :         mov_write_string_metadata(s, pb_buf, "\251mod", "model",       0);
    3668         113 :         mov_write_string_metadata(s, pb_buf, "\251xyz", "location",    0);
    3669         113 :         mov_write_string_metadata(s, pb_buf, "\251key", "keywords",    0);
    3670         113 :         mov_write_raw_metadata_tag(s, pb_buf, "XMP_", "xmp");
    3671             :     } else {
    3672             :         /* iTunes meta data */
    3673          60 :         mov_write_meta_tag(pb_buf, mov, s);
    3674          60 :         mov_write_loci_tag(s, pb_buf);
    3675             :     }
    3676             : 
    3677         173 :     if (s->nb_chapters && !(mov->flags & FF_MOV_FLAG_DISABLE_CHPL))
    3678           0 :         mov_write_chpl_tag(pb_buf, s);
    3679             : 
    3680         173 :     if ((size = avio_close_dyn_buf(pb_buf, &buf)) > 0) {
    3681          81 :         avio_wb32(pb, size + 8);
    3682          81 :         ffio_wfourcc(pb, "udta");
    3683          81 :         avio_write(pb, buf, size);
    3684             :     }
    3685         173 :     av_free(buf);
    3686             : 
    3687         173 :     return 0;
    3688             : }
    3689             : 
    3690           0 : static void mov_write_psp_udta_tag(AVIOContext *pb,
    3691             :                                    const char *str, const char *lang, int type)
    3692             : {
    3693           0 :     int len = utf8len(str) + 1;
    3694           0 :     if (len <= 0)
    3695           0 :         return;
    3696           0 :     avio_wb16(pb, len * 2 + 10);        /* size */
    3697           0 :     avio_wb32(pb, type);                /* type */
    3698           0 :     avio_wb16(pb, language_code(lang)); /* language */
    3699           0 :     avio_wb16(pb, 0x01);                /* ? */
    3700           0 :     ascii_to_wc(pb, str);
    3701             : }
    3702             : 
    3703           1 : static int mov_write_uuidusmt_tag(AVIOContext *pb, AVFormatContext *s)
    3704             : {
    3705           1 :     AVDictionaryEntry *title = av_dict_get(s->metadata, "title", NULL, 0);
    3706             :     int64_t pos, pos2;
    3707             : 
    3708           1 :     if (title) {
    3709           0 :         pos = avio_tell(pb);
    3710           0 :         avio_wb32(pb, 0); /* size placeholder*/
    3711           0 :         ffio_wfourcc(pb, "uuid");
    3712           0 :         ffio_wfourcc(pb, "USMT");
    3713           0 :         avio_wb32(pb, 0x21d24fce); /* 96 bit UUID */
    3714           0 :         avio_wb32(pb, 0xbb88695c);
    3715           0 :         avio_wb32(pb, 0xfac9c740);
    3716             : 
    3717           0 :         pos2 = avio_tell(pb);
    3718           0 :         avio_wb32(pb, 0); /* size placeholder*/
    3719           0 :         ffio_wfourcc(pb, "MTDT");
    3720           0 :         avio_wb16(pb, 4);
    3721             : 
    3722             :         // ?
    3723           0 :         avio_wb16(pb, 0x0C);                 /* size */
    3724           0 :         avio_wb32(pb, 0x0B);                 /* type */
    3725           0 :         avio_wb16(pb, language_code("und")); /* language */
    3726           0 :         avio_wb16(pb, 0x0);                  /* ? */
    3727           0 :         avio_wb16(pb, 0x021C);               /* data */
    3728             : 
    3729           0 :         if (!(s->flags & AVFMT_FLAG_BITEXACT))
    3730           0 :             mov_write_psp_udta_tag(pb, LIBAVCODEC_IDENT,      "eng", 0x04);
    3731           0 :         mov_write_psp_udta_tag(pb, title->value,          "eng", 0x01);
    3732           0 :         mov_write_psp_udta_tag(pb, "2006/04/01 11:11:11", "und", 0x03);
    3733             : 
    3734           0 :         update_size(pb, pos2);
    3735           0 :         return update_size(pb, pos);
    3736             :     }
    3737             : 
    3738           1 :     return 0;
    3739             : }
    3740             : 
    3741         224 : static void build_chunks(MOVTrack *trk)
    3742             : {
    3743             :     int i;
    3744         224 :     MOVIentry *chunk = &trk->cluster[0];
    3745         224 :     uint64_t chunkSize = chunk->size;
    3746         224 :     chunk->chunkNum = 1;
    3747         224 :     if (trk->chunkCount)
    3748          52 :         return;
    3749         172 :     trk->chunkCount = 1;
    3750       10337 :     for (i = 1; i<trk->entry; i++){
    3751       19365 :         if (chunk->pos + chunkSize == trk->cluster[i].pos &&
    3752        9200 :             chunkSize + trk->cluster[i].size < (1<<20)){
    3753        8721 :             chunkSize             += trk->cluster[i].size;
    3754        8721 :             chunk->samples_in_chunk += trk->cluster[i].entries;
    3755             :         } else {
    3756        1444 :             trk->cluster[i].chunkNum = chunk->chunkNum+1;
    3757        1444 :             chunk=&trk->cluster[i];
    3758        1444 :             chunkSize = chunk->size;
    3759        1444 :             trk->chunkCount++;
    3760             :         }
    3761             :     }
    3762             : }
    3763             : 
    3764             : /**
    3765             :  * Assign track ids. If option "use_stream_ids_as_track_ids" is set,
    3766             :  * the stream ids are used as track ids.
    3767             :  *
    3768             :  * This assumes mov->tracks and s->streams are in the same order and
    3769             :  * there are no gaps in either of them (so mov->tracks[n] refers to
    3770             :  * s->streams[n]).
    3771             :  *
    3772             :  * As an exception, there can be more entries in
    3773             :  * s->streams than in mov->tracks, in which case new track ids are
    3774             :  * generated (starting after the largest found stream id).
    3775             :  */
    3776         174 : static int mov_setup_track_ids(MOVMuxContext *mov, AVFormatContext *s)
    3777             : {
    3778             :     int i;
    3779             : 
    3780         174 :     if (mov->track_ids_ok)
    3781          25 :         return 0;
    3782             : 
    3783         149 :     if (mov->use_stream_ids_as_track_ids) {
    3784           0 :         int next_generated_track_id = 0;
    3785           0 :         for (i = 0; i < s->nb_streams; i++) {
    3786           0 :             if (s->streams[i]->id > next_generated_track_id)
    3787           0 :                 next_generated_track_id = s->streams[i]->id;
    3788             :         }
    3789             : 
    3790           0 :         for (i = 0; i < mov->nb_streams; i++) {
    3791           0 :             if (mov->tracks[i].entry <= 0 && !(mov->flags & FF_MOV_FLAG_FRAGMENT))
    3792           0 :                 continue;
    3793             : 
    3794           0 :             mov->tracks[i].track_id = i >= s->nb_streams ? ++next_generated_track_id : s->streams[i]->id;
    3795             :         }
    3796             :     } else {
    3797         343 :         for (i = 0; i < mov->nb_streams; i++) {
    3798         194 :             if (mov->tracks[i].entry <= 0 && !(mov->flags & FF_MOV_FLAG_FRAGMENT))
    3799           0 :                 continue;
    3800             : 
    3801         194 :             mov->tracks[i].track_id = i + 1;
    3802             :         }
    3803             :     }
    3804             : 
    3805         149 :     mov->track_ids_ok = 1;
    3806             : 
    3807         149 :     return 0;
    3808             : }
    3809             : 
    3810         174 : static int mov_write_moov_tag(AVIOContext *pb, MOVMuxContext *mov,
    3811             :                               AVFormatContext *s)
    3812             : {
    3813             :     int i;
    3814         174 :     int64_t pos = avio_tell(pb);
    3815         174 :     avio_wb32(pb, 0); /* size placeholder*/
    3816         174 :     ffio_wfourcc(pb, "moov");
    3817             : 
    3818         174 :     mov_setup_track_ids(mov, s);
    3819             : 
    3820         422 :     for (i = 0; i < mov->nb_streams; i++) {
    3821         248 :         if (mov->tracks[i].entry <= 0 && !(mov->flags & FF_MOV_FLAG_FRAGMENT))
    3822           0 :             continue;
    3823             : 
    3824         248 :         mov->tracks[i].time     = mov->time;
    3825             : 
    3826         248 :         if (mov->tracks[i].entry)
    3827         224 :             build_chunks(&mov->tracks[i]);
    3828             :     }
    3829             : 
    3830         174 :     if (mov->chapter_track)
    3831           0 :         for (i = 0; i < s->nb_streams; i++) {
    3832           0 :             mov->tracks[i].tref_tag = MKTAG('c','h','a','p');
    3833           0 :             mov->tracks[i].tref_id  = mov->tracks[mov->chapter_track].track_id;
    3834             :         }
    3835         422 :     for (i = 0; i < mov->nb_streams; i++) {
    3836         248 :         MOVTrack *track = &mov->tracks[i];
    3837         248 :         if (track->tag == MKTAG('r','t','p',' ')) {
    3838           2 :             track->tref_tag = MKTAG('h','i','n','t');
    3839           2 :             track->tref_id = mov->tracks[track->src_track].track_id;
    3840         246 :         } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) {
    3841             :             int * fallback, size;
    3842          77 :             fallback = (int*)av_stream_get_side_data(track->st,
    3843             :                                                      AV_PKT_DATA_FALLBACK_TRACK,
    3844             :                                                      &size);
    3845          77 :             if (fallback != NULL && size == sizeof(int)) {
    3846           0 :                 if (*fallback >= 0 && *fallback < mov->nb_streams) {
    3847           0 :                     track->tref_tag = MKTAG('f','a','l','l');
    3848           0 :                     track->tref_id = mov->tracks[*fallback].track_id;
    3849             :                 }
    3850             :             }
    3851             :         }
    3852             :     }
    3853         422 :     for (i = 0; i < mov->nb_streams; i++) {
    3854         248 :         if (mov->tracks[i].tag == MKTAG('t','m','c','d')) {
    3855          11 :             int src_trk = mov->tracks[i].src_track;
    3856          11 :             mov->tracks[src_trk].tref_tag = mov->tracks[i].tag;
    3857          11 :             mov->tracks[src_trk].tref_id  = mov->tracks[i].track_id;
    3858             :             //src_trk may have a different timescale than the tmcd track
    3859          22 :             mov->tracks[i].track_duration = av_rescale(mov->tracks[src_trk].track_duration,
    3860          11 :                                                        mov->tracks[i].timescale,
    3861          11 :                                                        mov->tracks[src_trk].timescale);
    3862             :         }
    3863             :     }
    3864             : 
    3865         174 :     mov_write_mvhd_tag(pb, mov);
    3866         174 :     if (mov->mode != MODE_MOV && !mov->iods_skip)
    3867           0 :         mov_write_iods_tag(pb, mov);
    3868         422 :     for (i = 0; i < mov->nb_streams; i++) {
    3869         248 :         if (mov->tracks[i].entry > 0 || mov->flags & FF_MOV_FLAG_FRAGMENT) {
    3870         248 :             int ret = mov_write_trak_tag(s, pb, mov, &(mov->tracks[i]), i < s->nb_streams ? s->streams[i] : NULL);
    3871         248 :             if (ret < 0)
    3872           0 :                 return ret;
    3873             :         }
    3874             :     }
    3875         174 :     if (mov->flags & FF_MOV_FLAG_FRAGMENT)
    3876          50 :         mov_write_mvex_tag(pb, mov); /* QuickTime requires trak to precede this */
    3877             : 
    3878         174 :     if (mov->mode == MODE_PSP)
    3879           1 :         mov_write_uuidusmt_tag(pb, s);
    3880             :     else
    3881         173 :         mov_write_udta_tag(pb, mov, s);
    3882             : 
    3883         174 :     return update_size(pb, pos);
    3884             : }
    3885             : 
    3886           0 : static void param_write_int(AVIOContext *pb, const char *name, int value)
    3887             : {
    3888           0 :     avio_printf(pb, "<param name=\"%s\" value=\"%d\" valuetype=\"data\"/>\n", name, value);
    3889           0 : }
    3890             : 
    3891           0 : static void param_write_string(AVIOContext *pb, const char *name, const char *value)
    3892             : {
    3893           0 :     avio_printf(pb, "<param name=\"%s\" value=\"%s\" valuetype=\"data\"/>\n", name, value);
    3894           0 : }
    3895             : 
    3896           0 : static void param_write_hex(AVIOContext *pb, const char *name, const uint8_t *value, int len)
    3897             : {
    3898             :     char buf[150];
    3899           0 :     len = FFMIN(sizeof(buf) / 2 - 1, len);
    3900           0 :     ff_data_to_hex(buf, value, len, 0);
    3901           0 :     buf[2 * len] = '\0';
    3902           0 :     avio_printf(pb, "<param name=\"%s\" value=\"%s\" valuetype=\"data\"/>\n", name, buf);
    3903           0 : }
    3904             : 
    3905           0 : static int mov_write_isml_manifest(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
    3906             : {
    3907           0 :     int64_t pos = avio_tell(pb);
    3908             :     int i;
    3909           0 :     int64_t manifest_bit_rate = 0;
    3910           0 :     AVCPBProperties *props = NULL;
    3911             : 
    3912             :     static const uint8_t uuid[] = {
    3913             :         0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
    3914             :         0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
    3915             :     };
    3916             : 
    3917           0 :     avio_wb32(pb, 0);
    3918           0 :     ffio_wfourcc(pb, "uuid");
    3919           0 :     avio_write(pb, uuid, sizeof(uuid));
    3920           0 :     avio_wb32(pb, 0);
    3921             : 
    3922           0 :     avio_printf(pb, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
    3923           0 :     avio_printf(pb, "<smil xmlns=\"http://www.w3.org/2001/SMIL20/Language\">\n");
    3924           0 :     avio_printf(pb, "<head>\n");
    3925           0 :     if (!(mov->fc->flags & AVFMT_FLAG_BITEXACT))
    3926           0 :         avio_printf(pb, "<meta name=\"creator\" content=\"%s\" />\n",
    3927             :                     LIBAVFORMAT_IDENT);
    3928           0 :     avio_printf(pb, "</head>\n");
    3929           0 :     avio_printf(pb, "<body>\n");
    3930           0 :     avio_printf(pb, "<switch>\n");
    3931             : 
    3932           0 :     mov_setup_track_ids(mov, s);
    3933             : 
    3934           0 :     for (i = 0; i < mov->nb_streams; i++) {
    3935           0 :         MOVTrack *track = &mov->tracks[i];
    3936             :         const char *type;
    3937           0 :         int track_id = track->track_id;
    3938           0 :         char track_name_buf[32] = { 0 };
    3939             : 
    3940           0 :         AVStream *st = track->st;
    3941           0 :         AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL,0);
    3942             : 
    3943           0 :         if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
    3944           0 :             type = "video";
    3945           0 :         } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) {
    3946           0 :             type = "audio";
    3947             :         } else {
    3948           0 :             continue;
    3949             :         }
    3950             : 
    3951           0 :         props = (AVCPBProperties*)av_stream_get_side_data(track->st, AV_PKT_DATA_CPB_PROPERTIES, NULL);
    3952             : 
    3953           0 :         if (track->par->bit_rate) {
    3954           0 :             manifest_bit_rate = track->par->bit_rate;
    3955           0 :         } else if (props) {
    3956           0 :             manifest_bit_rate = props->max_bitrate;
    3957             :         }
    3958             : 
    3959           0 :         avio_printf(pb, "<%s systemBitrate=\"%"PRId64"\">\n", type,
    3960             :                     manifest_bit_rate);
    3961           0 :         param_write_int(pb, "systemBitrate", manifest_bit_rate);
    3962           0 :         param_write_int(pb, "trackID", track_id);
    3963           0 :         param_write_string(pb, "systemLanguage", lang ? lang->value : "und");
    3964             : 
    3965             :         /* Build track name piece by piece: */
    3966             :         /* 1. track type */
    3967           0 :         av_strlcat(track_name_buf, type, sizeof(track_name_buf));
    3968             :         /* 2. track language, if available */
    3969           0 :         if (lang)
    3970           0 :             av_strlcatf(track_name_buf, sizeof(track_name_buf),
    3971             :                         "_%s", lang->value);
    3972             :         /* 3. special type suffix */
    3973             :         /* "_cc" = closed captions, "_ad" = audio_description */
    3974           0 :         if (st->disposition & AV_DISPOSITION_HEARING_IMPAIRED)
    3975           0 :             av_strlcat(track_name_buf, "_cc", sizeof(track_name_buf));
    3976           0 :         else if (st->disposition & AV_DISPOSITION_VISUAL_IMPAIRED)
    3977           0 :             av_strlcat(track_name_buf, "_ad", sizeof(track_name_buf));
    3978             : 
    3979           0 :         param_write_string(pb, "trackName", track_name_buf);
    3980             : 
    3981           0 :         if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
    3982           0 :             if (track->par->codec_id == AV_CODEC_ID_H264) {
    3983             :                 uint8_t *ptr;
    3984           0 :                 int size = track->par->extradata_size;
    3985           0 :                 if (!ff_avc_write_annexb_extradata(track->par->extradata, &ptr,
    3986             :                                                    &size)) {
    3987           0 :                     param_write_hex(pb, "CodecPrivateData",
    3988           0 :                                     ptr ? ptr : track->par->extradata,
    3989             :                                     size);
    3990           0 :                     av_free(ptr);
    3991             :                 }
    3992           0 :                 param_write_string(pb, "FourCC", "H264");
    3993           0 :             } else if (track->par->codec_id == AV_CODEC_ID_VC1) {
    3994           0 :                 param_write_string(pb, "FourCC", "WVC1");
    3995           0 :                 param_write_hex(pb, "CodecPrivateData", track->par->extradata,
    3996           0 :                                 track->par->extradata_size);
    3997             :             }
    3998           0 :             param_write_int(pb, "MaxWidth", track->par->width);
    3999           0 :             param_write_int(pb, "MaxHeight", track->par->height);
    4000           0 :             param_write_int(pb, "DisplayWidth", track->par->width);
    4001           0 :             param_write_int(pb, "DisplayHeight", track->par->height);
    4002             :         } else {
    4003           0 :             if (track->par->codec_id == AV_CODEC_ID_AAC) {
    4004           0 :                 switch (track->par->profile)
    4005             :                 {
    4006           0 :                     case FF_PROFILE_AAC_HE_V2:
    4007           0 :                         param_write_string(pb, "FourCC", "AACP");
    4008           0 :                         break;
    4009           0 :                     case FF_PROFILE_AAC_HE:
    4010           0 :                         param_write_string(pb, "FourCC", "AACH");
    4011           0 :                         break;
    4012           0 :                     default:
    4013           0 :                         param_write_string(pb, "FourCC", "AACL");
    4014             :                 }
    4015           0 :             } else if (track->par->codec_id == AV_CODEC_ID_WMAPRO) {
    4016           0 :                 param_write_string(pb, "FourCC", "WMAP");
    4017             :             }
    4018           0 :             param_write_hex(pb, "CodecPrivateData", track->par->extradata,
    4019           0 :                             track->par->extradata_size);
    4020           0 :             param_write_int(pb, "AudioTag", ff_codec_get_tag(ff_codec_wav_tags,
    4021           0 :                                                              track->par->codec_id));
    4022           0 :             param_write_int(pb, "Channels", track->par->channels);
    4023           0 :             param_write_int(pb, "SamplingRate", track->par->sample_rate);
    4024           0 :             param_write_int(pb, "BitsPerSample", 16);
    4025           0 :             param_write_int(pb, "PacketSize", track->par->block_align ?
    4026           0 :                                               track->par->block_align : 4);
    4027             :         }
    4028           0 :         avio_printf(pb, "</%s>\n", type);
    4029             :     }
    4030           0 :     avio_printf(pb, "</switch>\n");
    4031           0 :     avio_printf(pb, "</body>\n");
    4032           0 :     avio_printf(pb, "</smil>\n");
    4033             : 
    4034           0 :     return update_size(pb, pos);
    4035             : }
    4036             : 
    4037         120 : static int mov_write_mfhd_tag(AVIOContext *pb, MOVMuxContext *mov)
    4038             : {
    4039         120 :     avio_wb32(pb, 16);
    4040         120 :     ffio_wfourcc(pb, "mfhd");
    4041         120 :     avio_wb32(pb, 0);
    4042         120 :     avio_wb32(pb, mov->fragments);
    4043         120 :     return 0;
    4044             : }
    4045             : 
    4046        9288 : static uint32_t get_sample_flags(MOVTrack *track, MOVIentry *entry)
    4047             : {
    4048        9288 :     return entry->flags & MOV_SYNC_SAMPLE ? MOV_FRAG_SAMPLE_FLAG_DEPENDS_NO :
    4049             :            (MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES | MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC);
    4050             : }
    4051             : 
    4052         206 : static int mov_write_tfhd_tag(AVIOContext *pb, MOVMuxContext *mov,
    4053             :                               MOVTrack *track, int64_t moof_offset)
    4054             : {
    4055         206 :     int64_t pos = avio_tell(pb);
    4056         206 :     uint32_t flags = MOV_TFHD_DEFAULT_SIZE | MOV_TFHD_DEFAULT_DURATION |
    4057             :                      MOV_TFHD_BASE_DATA_OFFSET;
    4058         206 :     if (!track->entry) {
    4059           0 :         flags |= MOV_TFHD_DURATION_IS_EMPTY;
    4060             :     } else {
    4061         206 :         flags |= MOV_TFHD_DEFAULT_FLAGS;
    4062             :     }
    4063         206 :     if (mov->flags & FF_MOV_FLAG_OMIT_TFHD_OFFSET)
    4064           0 :         flags &= ~MOV_TFHD_BASE_DATA_OFFSET;
    4065         206 :     if (mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF) {
    4066          60 :         flags &= ~MOV_TFHD_BASE_DATA_OFFSET;
    4067          60 :         flags |= MOV_TFHD_DEFAULT_BASE_IS_MOOF;
    4068             :     }
    4069             : 
    4070             :     /* Don't set a default sample size, the silverlight player refuses
    4071             :      * to play files with that set. Don't set a default sample duration,
    4072             :      * WMP freaks out if it is set. Don't set a base data offset, PIFF
    4073             :      * file format says it MUST NOT be set. */
    4074         206 :     if (track->mode == MODE_ISM)
    4075          26 :         flags &= ~(MOV_TFHD_DEFAULT_SIZE | MOV_TFHD_DEFAULT_DURATION |
    4076             :                    MOV_TFHD_BASE_DATA_OFFSET);
    4077             : 
    4078         206 :     avio_wb32(pb, 0); /* size placeholder */
    4079         206 :     ffio_wfourcc(pb, "tfhd");
    4080         206 :     avio_w8(pb, 0); /* version */
    4081         206 :     avio_wb24(pb, flags);
    4082             : 
    4083         206 :     avio_wb32(pb, track->track_id); /* track-id */
    4084         206 :     if (flags & MOV_TFHD_BASE_DATA_OFFSET)
    4085         120 :         avio_wb64(pb, moof_offset);
    4086         206 :     if (flags & MOV_TFHD_DEFAULT_DURATION) {
    4087         180 :         track->default_duration = get_cluster_duration(track, 0);
    4088         180 :         avio_wb32(pb, track->default_duration);
    4089             :     }
    4090         206 :     if (flags & MOV_TFHD_DEFAULT_SIZE) {
    4091         180 :         track->default_size = track->entry ? track->cluster[0].size : 1;
    4092         180 :         avio_wb32(pb, track->default_size);
    4093             :     } else
    4094          26 :         track->default_size = -1;
    4095             : 
    4096         206 :     if (flags & MOV_TFHD_DEFAULT_FLAGS) {
    4097             :         /* Set the default flags based on the second sample, if available.
    4098             :          * If the first sample is different, that can be signaled via a separate field. */
    4099         206 :         if (track->entry > 1)
    4100         202 :             track->default_sample_flags = get_sample_flags(track, &track->cluster[1]);
    4101             :         else
    4102           4 :             track->default_sample_flags =
    4103           4 :                 track->par->codec_type == AVMEDIA_TYPE_VIDEO ?
    4104           4 :                 (MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES | MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC) :
    4105             :                 MOV_FRAG_SAMPLE_FLAG_DEPENDS_NO;
    4106         206 :         avio_wb32(pb, track->default_sample_flags);
    4107             :     }
    4108             : 
    4109         206 :     return update_size(pb, pos);
    4110             : }
    4111             : 
    4112         206 : static int mov_write_trun_tag(AVIOContext *pb, MOVMuxContext *mov,
    4113             :                               MOVTrack *track, int moof_size,
    4114             :                               int first, int end)
    4115             : {
    4116         206 :     int64_t pos = avio_tell(pb);
    4117         206 :     uint32_t flags = MOV_TRUN_DATA_OFFSET;
    4118             :     int i;
    4119             : 
    4120        9068 :     for (i = first; i < end; i++) {
    4121        8862 :         if (get_cluster_duration(track, i) != track->default_duration)
    4122         756 :             flags |= MOV_TRUN_SAMPLE_DURATION;
    4123        8862 :         if (track->cluster[i].size != track->default_size)
    4124         462 :             flags |= MOV_TRUN_SAMPLE_SIZE;
    4125        8862 :         if (i > first && get_sample_flags(track, &track->cluster[i]) != track->default_sample_flags)
    4126           2 :             flags |= MOV_TRUN_SAMPLE_FLAGS;
    4127             :     }
    4128         410 :     if (!(flags & MOV_TRUN_SAMPLE_FLAGS) && track->entry > 0 &&
    4129         204 :          get_sample_flags(track, &track->cluster[0]) != track->default_sample_flags)
    4130         106 :         flags |= MOV_TRUN_FIRST_SAMPLE_FLAGS;
    4131         206 :     if (track->flags & MOV_TRACK_CTTS)
    4132          64 :         flags |= MOV_TRUN_SAMPLE_CTS;
    4133             : 
    4134         206 :     avio_wb32(pb, 0); /* size placeholder */
    4135         206 :     ffio_wfourcc(pb, "trun");
    4136         206 :     if (mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS)
    4137          16 :         avio_w8(pb, 1); /* version */
    4138             :     else
    4139         190 :         avio_w8(pb, 0); /* version */
    4140         206 :     avio_wb24(pb, flags);
    4141             : 
    4142         206 :     avio_wb32(pb, end - first); /* sample count */
    4143         206 :     if (mov->flags & FF_MOV_FLAG_OMIT_TFHD_OFFSET &&
    4144           0 :         !(mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF) &&
    4145           0 :         !mov->first_trun)
    4146           0 :         avio_wb32(pb, 0); /* Later tracks follow immediately after the previous one */
    4147             :     else
    4148         412 :         avio_wb32(pb, moof_size + 8 + track->data_offset +
    4149         206 :                       track->cluster[first].pos); /* data offset */
    4150         206 :     if (flags & MOV_TRUN_FIRST_SAMPLE_FLAGS)
    4151         106 :         avio_wb32(pb, get_sample_flags(track, &track->cluster[first]));
    4152             : 
    4153        9068 :     for (i = first; i < end; i++) {
    4154        8862 :         if (flags & MOV_TRUN_SAMPLE_DURATION)
    4155         856 :             avio_wb32(pb, get_cluster_duration(track, i));
    4156        8862 :         if (flags & MOV_TRUN_SAMPLE_SIZE)
    4157         466 :             avio_wb32(pb, track->cluster[i].size);
    4158        8862 :         if (flags & MOV_TRUN_SAMPLE_FLAGS)
    4159         120 :             avio_wb32(pb, get_sample_flags(track, &track->cluster[i]));
    4160        8862 :         if (flags & MOV_TRUN_SAMPLE_CTS)
    4161        1740 :             avio_wb32(pb, track->cluster[i].cts);
    4162             :     }
    4163             : 
    4164         206 :     mov->first_trun = 0;
    4165         206 :     return update_size(pb, pos);
    4166             : }
    4167             : 
    4168          26 : static int mov_write_tfxd_tag(AVIOContext *pb, MOVTrack *track)
    4169             : {
    4170          26 :     int64_t pos = avio_tell(pb);
    4171             :     static const uint8_t uuid[] = {
    4172             :         0x6d, 0x1d, 0x9b, 0x05, 0x42, 0xd5, 0x44, 0xe6,
    4173             :         0x80, 0xe2, 0x14, 0x1d, 0xaf, 0xf7, 0x57, 0xb2
    4174             :     };
    4175             : 
    4176          26 :     avio_wb32(pb, 0); /* size placeholder */
    4177          26 :     ffio_wfourcc(pb, "uuid");
    4178          26 :     avio_write(pb, uuid, sizeof(uuid));
    4179          26 :     avio_w8(pb, 1);
    4180          26 :     avio_wb24(pb, 0);
    4181          52 :     avio_wb64(pb, track->start_dts + track->frag_start +
    4182          26 :                   track->cluster[0].cts);
    4183          52 :     avio_wb64(pb, track->end_pts -
    4184          26 :                   (track->cluster[0].dts + track->cluster[0].cts));
    4185             : 
    4186          26 :     return update_size(pb, pos);
    4187             : }
    4188             : 
    4189           0 : static int mov_write_tfrf_tag(AVIOContext *pb, MOVMuxContext *mov,
    4190             :                               MOVTrack *track, int entry)
    4191             : {
    4192           0 :     int n = track->nb_frag_info - 1 - entry, i;
    4193           0 :     int size = 8 + 16 + 4 + 1 + 16*n;
    4194             :     static const uint8_t uuid[] = {
    4195             :         0xd4, 0x80, 0x7e, 0xf2, 0xca, 0x39, 0x46, 0x95,
    4196             :         0x8e, 0x54, 0x26, 0xcb, 0x9e, 0x46, 0xa7, 0x9f
    4197             :     };
    4198             : 
    4199           0 :     if (entry < 0)
    4200           0 :         return 0;
    4201             : 
    4202           0 :     avio_seek(pb, track->frag_info[entry].tfrf_offset, SEEK_SET);
    4203           0 :     avio_wb32(pb, size);
    4204           0 :     ffio_wfourcc(pb, "uuid");
    4205           0 :     avio_write(pb, uuid, sizeof(uuid));
    4206           0 :     avio_w8(pb, 1);
    4207           0 :     avio_wb24(pb, 0);
    4208           0 :     avio_w8(pb, n);
    4209           0 :     for (i = 0; i < n; i++) {
    4210           0 :         int index = entry + 1 + i;
    4211           0 :         avio_wb64(pb, track->frag_info[index].time);
    4212           0 :         avio_wb64(pb, track->frag_info[index].duration);
    4213             :     }
    4214           0 :     if (n < mov->ism_lookahead) {
    4215           0 :         int free_size = 16 * (mov->ism_lookahead - n);
    4216           0 :         avio_wb32(pb, free_size);
    4217           0 :         ffio_wfourcc(pb, "free");
    4218           0 :         ffio_fill(pb, 0, free_size - 8);
    4219             :     }
    4220             : 
    4221           0 :     return 0;
    4222             : }
    4223             : 
    4224         103 : static int mov_write_tfrf_tags(AVIOContext *pb, MOVMuxContext *mov,
    4225             :                                MOVTrack *track)
    4226             : {
    4227         103 :     int64_t pos = avio_tell(pb);
    4228             :     int i;
    4229         103 :     for (i = 0; i < mov->ism_lookahead; i++) {
    4230             :         /* Update the tfrf tag for the last ism_lookahead fragments,
    4231             :          * nb_frag_info - 1 is the next fragment to be written. */
    4232           0 :         mov_write_tfrf_tag(pb, mov, track, track->nb_frag_info - 2 - i);
    4233             :     }
    4234         103 :     avio_seek(pb, pos, SEEK_SET);
    4235         103 :     return 0;
    4236             : }
    4237             : 
    4238          60 : static int mov_add_tfra_entries(AVIOContext *pb, MOVMuxContext *mov, int tracks,
    4239             :                                 int size)
    4240             : {
    4241             :     int i;
    4242         170 :     for (i = 0; i < mov->nb_streams; i++) {
    4243         110 :         MOVTrack *track = &mov->tracks[i];
    4244             :         MOVFragmentInfo *info;
    4245         110 :         if ((tracks >= 0 && i != tracks) || !track->entry)
    4246           7 :             continue;
    4247         103 :         track->nb_frag_info++;
    4248         103 :         if (track->nb_frag_info >= track->frag_info_capacity) {
    4249          56 :             unsigned new_capacity = track->nb_frag_info + MOV_FRAG_INFO_ALLOC_INCREMENT;
    4250          56 :             if (av_reallocp_array(&track->frag_info,
    4251             :                                   new_capacity,
    4252             :                                   sizeof(*track->frag_info)))
    4253           0 :                 return AVERROR(ENOMEM);
    4254          56 :             track->frag_info_capacity = new_capacity;
    4255             :         }
    4256         103 :         info = &track->frag_info[track->nb_frag_info - 1];
    4257         103 :         info->offset   = avio_tell(pb);
    4258         103 :         info->size     = size;
    4259             :         // Try to recreate the original pts for the first packet
    4260             :         // from the fields we have stored
    4261         206 :         info->time     = track->start_dts + track->frag_start +
    4262         103 :                          track->cluster[0].cts;
    4263         206 :         info->duration = track->end_pts -
    4264         103 :                          (track->cluster[0].dts + track->cluster[0].cts);
    4265             :         // If the pts is less than zero, we will have trimmed
    4266             :         // away parts of the media track using an edit list,
    4267             :         // and the corresponding start presentation time is zero.
    4268         103 :         if (info->time < 0) {
    4269           7 :             info->duration += info->time;
    4270           7 :             info->time = 0;
    4271             :         }
    4272         103 :         info->tfrf_offset = 0;
    4273         103 :         mov_write_tfrf_tags(pb, mov, track);
    4274             :     }
    4275          60 :     return 0;
    4276             : }
    4277             : 
    4278           0 : static void mov_prune_frag_info(MOVMuxContext *mov, int tracks, int max)
    4279             : {
    4280             :     int i;
    4281           0 :     for (i = 0; i < mov->nb_streams; i++) {
    4282           0 :         MOVTrack *track = &mov->tracks[i];
    4283           0 :         if ((tracks >= 0 && i != tracks) || !track->entry)
    4284           0 :             continue;
    4285           0 :         if (track->nb_frag_info > max) {
    4286           0 :             memmove(track->frag_info, track->frag_info + (track->nb_frag_info - max), max * sizeof(*track->frag_info));
    4287           0 :             track->nb_frag_info = max;
    4288             :         }
    4289             :     }
    4290           0 : }
    4291             : 
    4292         180 : static int mov_write_tfdt_tag(AVIOContext *pb, MOVTrack *track)
    4293             : {
    4294         180 :     int64_t pos = avio_tell(pb);
    4295             : 
    4296         180 :     avio_wb32(pb, 0); /* size */
    4297         180 :     ffio_wfourcc(pb, "tfdt");
    4298         180 :     avio_w8(pb, 1); /* version */
    4299         180 :     avio_wb24(pb, 0);
    4300         180 :     avio_wb64(pb, track->frag_start);
    4301         180 :     return update_size(pb, pos);
    4302             : }
    4303             : 
    4304         206 : static int mov_write_traf_tag(AVIOContext *pb, MOVMuxContext *mov,
    4305             :                               MOVTrack *track, int64_t moof_offset,
    4306             :                               int moof_size)
    4307             : {
    4308         206 :     int64_t pos = avio_tell(pb);
    4309         206 :     int i, start = 0;
    4310         206 :     avio_wb32(pb, 0); /* size placeholder */
    4311         206 :     ffio_wfourcc(pb, "traf");
    4312             : 
    4313         206 :     mov_write_tfhd_tag(pb, mov, track, moof_offset);
    4314         206 :     if (mov->mode != MODE_ISM)
    4315         180 :         mov_write_tfdt_tag(pb, track);
    4316        8862 :     for (i = 1; i < track->entry; i++) {
    4317        8656 :         if (track->cluster[i].pos != track->cluster[i - 1].pos + track->cluster[i - 1].size) {
    4318           0 :             mov_write_trun_tag(pb, mov, track, moof_size, start, i);
    4319           0 :             start = i;
    4320             :         }
    4321             :     }
    4322         206 :     mov_write_trun_tag(pb, mov, track, moof_size, start, track->entry);
    4323         206 :     if (mov->mode == MODE_ISM) {
    4324          26 :         mov_write_tfxd_tag(pb, track);
    4325             : 
    4326          26 :         if (mov->ism_lookahead) {
    4327           0 :             int i, size = 16 + 4 + 1 + 16 * mov->ism_lookahead;
    4328             : 
    4329           0 :             if (track->nb_frag_info > 0) {
    4330           0 :                 MOVFragmentInfo *info = &track->frag_info[track->nb_frag_info - 1];
    4331           0 :                 if (!info->tfrf_offset)
    4332           0 :                     info->tfrf_offset = avio_tell(pb);
    4333             :             }
    4334           0 :             avio_wb32(pb, 8 + size);
    4335           0 :             ffio_wfourcc(pb, "free");
    4336           0 :             for (i = 0; i < size; i++)
    4337           0 :                 avio_w8(pb, 0);
    4338             :         }
    4339             :     }
    4340             : 
    4341         206 :     return update_size(pb, pos);
    4342             : }
    4343             : 
    4344         120 : static int mov_write_moof_tag_internal(AVIOContext *pb, MOVMuxContext *mov,
    4345             :                                        int tracks, int moof_size)
    4346             : {
    4347         120 :     int64_t pos = avio_tell(pb);
    4348             :     int i;
    4349             : 
    4350         120 :     avio_wb32(pb, 0); /* size placeholder */
    4351         120 :     ffio_wfourcc(pb, "moof");
    4352         120 :     mov->first_trun = 1;
    4353             : 
    4354         120 :     mov_write_mfhd_tag(pb, mov);
    4355         340 :     for (i = 0; i < mov->nb_streams; i++) {
    4356         220 :         MOVTrack *track = &mov->tracks[i];
    4357         220 :         if (tracks >= 0 && i != tracks)
    4358           8 :             continue;
    4359         212 :         if (!track->entry)
    4360           6 :             continue;
    4361         206 :         mov_write_traf_tag(pb, mov, track, pos, moof_size);
    4362             :     }
    4363             : 
    4364         120 :     return update_size(pb, pos);
    4365             : }
    4366             : 
    4367          60 : static int mov_write_sidx_tag(AVIOContext *pb,
    4368             :                               MOVTrack *track, int ref_size, int total_sidx_size)
    4369             : {
    4370          60 :     int64_t pos = avio_tell(pb), offset_pos, end_pos;
    4371             :     int64_t presentation_time, duration, offset;
    4372             :     int starts_with_SAP, i, entries;
    4373             : 
    4374          60 :     if (track->entry) {
    4375          60 :         entries = 1;
    4376         120 :         presentation_time = track->start_dts + track->frag_start +
    4377          60 :                             track->cluster[0].cts;
    4378         120 :         duration = track->end_pts -
    4379          60 :                    (track->cluster[0].dts + track->cluster[0].cts);
    4380          60 :         starts_with_SAP = track->cluster[0].flags & MOV_SYNC_SAMPLE;
    4381             : 
    4382             :         // pts<0 should be cut away using edts
    4383          60 :         if (presentation_time < 0) {
    4384           6 :             duration += presentation_time;
    4385           6 :             presentation_time = 0;
    4386             :         }
    4387             :     } else {
    4388           0 :         entries = track->nb_frag_info;
    4389           0 :         if (entries <= 0)
    4390           0 :             return 0;
    4391           0 :         presentation_time = track->frag_info[0].time;
    4392             :     }
    4393             : 
    4394          60 :     avio_wb32(pb, 0); /* size */
    4395          60 :     ffio_wfourcc(pb, "sidx");
    4396          60 :     avio_w8(pb, 1); /* version */
    4397          60 :     avio_wb24(pb, 0);
    4398          60 :     avio_wb32(pb, track->track_id); /* reference_ID */
    4399          60 :     avio_wb32(pb, track->timescale); /* timescale */
    4400          60 :     avio_wb64(pb, presentation_time); /* earliest_presentation_time */
    4401          60 :     offset_pos = avio_tell(pb);
    4402          60 :     avio_wb64(pb, 0); /* first_offset (offset to referenced moof) */
    4403          60 :     avio_wb16(pb, 0); /* reserved */
    4404             : 
    4405          60 :     avio_wb16(pb, entries); /* reference_count */
    4406         120 :     for (i = 0; i < entries; i++) {
    4407          60 :         if (!track->entry) {
    4408           0 :             if (i > 1 && track->frag_info[i].offset != track->frag_info[i - 1].offset + track->frag_info[i - 1].size) {
    4409           0 :                av_log(NULL, AV_LOG_ERROR, "Non-consecutive fragments, writing incorrect sidx\n");
    4410             :             }
    4411           0 :             duration = track->frag_info[i].duration;
    4412           0 :             ref_size = track->frag_info[i].size;
    4413           0 :             starts_with_SAP = 1;
    4414             :         }
    4415          60 :         avio_wb32(pb, (0 << 31) | (ref_size & 0x7fffffff)); /* reference_type (0 = media) | referenced_size */
    4416          60 :         avio_wb32(pb, duration); /* subsegment_duration */
    4417          60 :         avio_wb32(pb, (starts_with_SAP << 31) | (0 << 28) | 0); /* starts_with_SAP | SAP_type | SAP_delta_time */
    4418             :     }
    4419             : 
    4420          60 :     end_pos = avio_tell(pb);
    4421          60 :     offset = pos + total_sidx_size - end_pos;
    4422          60 :     avio_seek(pb, offset_pos, SEEK_SET);
    4423          60 :     avio_wb64(pb, offset);
    4424          60 :     avio_seek(pb, end_pos, SEEK_SET);
    4425          60 :     return update_size(pb, pos);
    4426             : }
    4427             : 
    4428          15 : static int mov_write_sidx_tags(AVIOContext *pb, MOVMuxContext *mov,
    4429             :                                int tracks, int ref_size)
    4430             : {
    4431             :     int i, round, ret;
    4432             :     AVIOContext *avio_buf;
    4433          15 :     int total_size = 0;
    4434          45 :     for (round = 0; round < 2; round++) {
    4435             :         // First run one round to calculate the total size of all
    4436             :         // sidx atoms.
    4437             :         // This would be much simpler if we'd only write one sidx
    4438             :         // atom, for the first track in the moof.
    4439          30 :         if (round == 0) {
    4440          15 :             if ((ret = ffio_open_null_buf(&avio_buf)) < 0)
    4441           0 :                 return ret;
    4442             :         } else {
    4443          15 :             avio_buf = pb;
    4444             :         }
    4445          90 :         for (i = 0; i < mov->nb_streams; i++) {
    4446          60 :             MOVTrack *track = &mov->tracks[i];
    4447          60 :             if (tracks >= 0 && i != tracks)
    4448           0 :                 continue;
    4449             :             // When writing a sidx for the full file, entry is 0, but
    4450             :             // we want to include all tracks. ref_size is 0 in this case,
    4451             :             // since we read it from frag_info instead.
    4452          60 :             if (!track->entry && ref_size > 0)
    4453           0 :                 continue;
    4454          60 :             total_size -= mov_write_sidx_tag(avio_buf, track, ref_size,
    4455             :                                              total_size);
    4456             :         }
    4457          30 :         if (round == 0)
    4458          15 :             total_size = ffio_close_null_buf(avio_buf);
    4459             :     }
    4460          15 :     return 0;
    4461             : }
    4462             : 
    4463          60 : static int mov_write_moof_tag(AVIOContext *pb, MOVMuxContext *mov, int tracks,
    4464             :                               int64_t mdat_size)
    4465             : {
    4466             :     AVIOContext *avio_buf;
    4467             :     int ret, moof_size;
    4468             : 
    4469          60 :     if ((ret = ffio_open_null_buf(&avio_buf)) < 0)
    4470           0 :         return ret;
    4471          60 :     mov_write_moof_tag_internal(avio_buf, mov, tracks, 0);
    4472          60 :     moof_size = ffio_close_null_buf(avio_buf);
    4473             : 
    4474          60 :     if (mov->flags & FF_MOV_FLAG_DASH && !(mov->flags & FF_MOV_FLAG_GLOBAL_SIDX))
    4475          15 :         mov_write_sidx_tags(pb, mov, tracks, moof_size + 8 + mdat_size);
    4476             : 
    4477         120 :     if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX ||
    4478          60 :         !(mov->flags & FF_MOV_FLAG_SKIP_TRAILER) ||
    4479           0 :         mov->ism_lookahead) {
    4480          60 :         if ((ret = mov_add_tfra_entries(pb, mov, tracks, moof_size + 8 + mdat_size)) < 0)
    4481           0 :             return ret;
    4482         120 :         if (!(mov->flags & FF_MOV_FLAG_GLOBAL_SIDX) &&
    4483          60 :             mov->flags & FF_MOV_FLAG_SKIP_TRAILER) {
    4484           0 :             mov_prune_frag_info(mov, tracks, mov->ism_lookahead + 1);
    4485             :         }
    4486             :     }
    4487             : 
    4488          60 :     return mov_write_moof_tag_internal(pb, mov, tracks, moof_size);
    4489             : }
    4490             : 
    4491          56 : static int mov_write_tfra_tag(AVIOContext *pb, MOVTrack *track)
    4492             : {
    4493          56 :     int64_t pos = avio_tell(pb);
    4494             :     int i;
    4495             : 
    4496          56 :     avio_wb32(pb, 0); /* size placeholder */
    4497          56 :     ffio_wfourcc(pb, "tfra");
    4498          56 :     avio_w8(pb, 1); /* version */
    4499          56 :     avio_wb24(pb, 0);
    4500             : 
    4501          56 :     avio_wb32(pb, track->track_id);
    4502          56 :     avio_wb32(pb, 0); /* length of traf/trun/sample num */
    4503          56 :     avio_wb32(pb, track->nb_frag_info);
    4504         159 :     for (i = 0; i < track->nb_frag_info; i++) {
    4505         103 :         avio_wb64(pb, track->frag_info[i].time);
    4506         103 :         avio_wb64(pb, track->frag_info[i].offset + track->data_offset);
    4507         103 :         avio_w8(pb, 1); /* traf number */
    4508         103 :         avio_w8(pb, 1); /* trun number */
    4509         103 :         avio_w8(pb, 1); /* sample number */
    4510             :     }
    4511             : 
    4512          56 :     return update_size(pb, pos);
    4513             : }
    4514             : 
    4515          31 : static int mov_write_mfra_tag(AVIOContext *pb, MOVMuxContext *mov)
    4516             : {
    4517          31 :     int64_t pos = avio_tell(pb);
    4518             :     int i;
    4519             : 
    4520          31 :     avio_wb32(pb, 0); /* size placeholder */
    4521          31 :     ffio_wfourcc(pb, "mfra");
    4522             :     /* An empty mfra atom is enough to indicate to the publishing point that
    4523             :      * the stream has ended. */
    4524          31 :     if (mov->flags & FF_MOV_FLAG_ISML)
    4525           0 :         return update_size(pb, pos);
    4526             : 
    4527          89 :     for (i = 0; i < mov->nb_streams; i++) {
    4528          58 :         MOVTrack *track = &mov->tracks[i];
    4529          58 :         if (track->nb_frag_info)
    4530          56 :             mov_write_tfra_tag(pb, track);
    4531             :     }
    4532             : 
    4533          31 :     avio_wb32(pb, 16);
    4534          31 :     ffio_wfourcc(pb, "mfro");
    4535          31 :     avio_wb32(pb, 0); /* version + flags */
    4536          31 :     avio_wb32(pb, avio_tell(pb) + 4 - pos);
    4537             : 
    4538          31 :     return update_size(pb, pos);
    4539             : }
    4540             : 
    4541         118 : static int mov_write_mdat_tag(AVIOContext *pb, MOVMuxContext *mov)
    4542             : {
    4543         118 :     avio_wb32(pb, 8);    // placeholder for extended size field (64 bit)
    4544         118 :     ffio_wfourcc(pb, mov->mode == MODE_MOV ? "wide" : "free");
    4545             : 
    4546         118 :     mov->mdat_pos = avio_tell(pb);
    4547         118 :     avio_wb32(pb, 0); /* size placeholder*/
    4548         118 :     ffio_wfourcc(pb, "mdat");
    4549         118 :     return 0;
    4550             : }
    4551             : 
    4552             : /* TODO: This needs to be more general */
    4553         149 : static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s)
    4554             : {
    4555         149 :     MOVMuxContext *mov = s->priv_data;
    4556         149 :     int64_t pos = avio_tell(pb);
    4557         149 :     int has_h264 = 0, has_video = 0;
    4558         149 :     int minor = 0x200;
    4559             :     int i;
    4560             : 
    4561         337 :     for (i = 0; i < s->nb_streams; i++) {
    4562         188 :         AVStream *st = s->streams[i];
    4563         188 :         if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
    4564         131 :             has_video = 1;
    4565         188 :         if (st->codecpar->codec_id == AV_CODEC_ID_H264)
    4566          30 :             has_h264 = 1;
    4567             :     }
    4568             : 
    4569         149 :     avio_wb32(pb, 0); /* size */
    4570         149 :     ffio_wfourcc(pb, "ftyp");
    4571             : 
    4572         149 :     if (mov->major_brand && strlen(mov->major_brand) >= 4)
    4573           0 :         ffio_wfourcc(pb, mov->major_brand);
    4574         149 :     else if (mov->mode == MODE_3GP) {
    4575           0 :         ffio_wfourcc(pb, has_h264 ? "3gp6"  : "3gp4");
    4576           0 :         minor =     has_h264 ?   0x100 :   0x200;
    4577         149 :     } else if (mov->mode & MODE_3G2) {
    4578           0 :         ffio_wfourcc(pb, has_h264 ? "3g2b"  : "3g2a");
    4579           0 :         minor =     has_h264 ? 0x20000 : 0x10000;
    4580         149 :     } else if (mov->mode == MODE_PSP)
    4581           1 :         ffio_wfourcc(pb, "MSNV");
    4582         148 :     else if (mov->mode == MODE_MP4 && mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF)
    4583          10 :         ffio_wfourcc(pb, "iso5"); // Required when using default-base-is-moof
    4584         138 :     else if (mov->mode == MODE_MP4 && mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS)
    4585           2 :         ffio_wfourcc(pb, "iso4");
    4586         136 :     else if (mov->mode == MODE_MP4)
    4587          24 :         ffio_wfourcc(pb, "isom");
    4588         112 :     else if (mov->mode == MODE_IPOD)
    4589           1 :         ffio_wfourcc(pb, has_video ? "M4V ":"M4A ");
    4590         111 :     else if (mov->mode == MODE_ISM)
    4591           4 :         ffio_wfourcc(pb, "isml");
    4592         107 :     else if (mov->mode == MODE_F4V)
    4593           0 :         ffio_wfourcc(pb, "f4v ");
    4594             :     else
    4595         107 :         ffio_wfourcc(pb, "qt  ");
    4596             : 
    4597         149 :     avio_wb32(pb, minor);
    4598             : 
    4599         149 :     if (mov->mode == MODE_MOV)
    4600         107 :         ffio_wfourcc(pb, "qt  ");
    4601          42 :     else if (mov->mode == MODE_ISM) {
    4602           4 :         ffio_wfourcc(pb, "piff");
    4603          38 :     } else if (!(mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF)) {
    4604          28 :         ffio_wfourcc(pb, "isom");
    4605          28 :         ffio_wfourcc(pb, "iso2");
    4606          28 :         if (has_h264)
    4607          18 :             ffio_wfourcc(pb, "avc1");
    4608             :     }
    4609             : 
    4610             :     // We add tfdt atoms when fragmenting, signal this with the iso6 compatible
    4611             :     // brand. This is compatible with users that don't understand tfdt.
    4612         149 :     if (mov->flags & FF_MOV_FLAG_FRAGMENT && mov->mode != MODE_ISM)
    4613          27 :         ffio_wfourcc(pb, "iso6");
    4614             : 
    4615         149 :     if (mov->mode == MODE_3GP)
    4616           0 :         ffio_wfourcc(pb, has_h264 ? "3gp6":"3gp4");
    4617         149 :     else if (mov->mode & MODE_3G2)
    4618           0 :         ffio_wfourcc(pb, has_h264 ? "3g2b":"3g2a");
    4619         149 :     else if (mov->mode == MODE_PSP)
    4620           1 :         ffio_wfourcc(pb, "MSNV");
    4621         148 :     else if (mov->mode == MODE_MP4)
    4622          36 :         ffio_wfourcc(pb, "mp41");
    4623             : 
    4624         149 :     if (mov->flags & FF_MOV_FLAG_DASH && mov->flags & FF_MOV_FLAG_GLOBAL_SIDX)
    4625           0 :         ffio_wfourcc(pb, "dash");
    4626             : 
    4627         149 :     return update_size(pb, pos);
    4628             : }
    4629             : 
    4630           1 : static int mov_write_uuidprof_tag(AVIOContext *pb, AVFormatContext *s)
    4631             : {
    4632           1 :     AVStream       *video_st    = s->streams[0];
    4633           1 :     AVCodecParameters *video_par = s->streams[0]->codecpar;
    4634           1 :     AVCodecParameters *audio_par = s->streams[1]->codecpar;
    4635           1 :     int audio_rate = audio_par->sample_rate;
    4636           2 :     int64_t frame_rate = video_st->avg_frame_rate.den ?
    4637           1 :                         (video_st->avg_frame_rate.num * 0x10000LL) / video_st->avg_frame_rate.den :
    4638             :                         0;
    4639           1 :     int audio_kbitrate = audio_par->bit_rate / 1000;
    4640           1 :     int video_kbitrate = FFMIN(video_par->bit_rate / 1000, 800 - audio_kbitrate);
    4641             : 
    4642           1 :     if (frame_rate < 0 || frame_rate > INT32_MAX) {
    4643           0 :         av_log(s, AV_LOG_ERROR, "Frame rate %f outside supported range\n", frame_rate / (double)0x10000);
    4644           0 :         return AVERROR(EINVAL);
    4645             :     }
    4646             : 
    4647           1 :     avio_wb32(pb, 0x94); /* size */
    4648           1 :     ffio_wfourcc(pb, "uuid");
    4649           1 :     ffio_wfourcc(pb, "PROF");
    4650             : 
    4651           1 :     avio_wb32(pb, 0x21d24fce); /* 96 bit UUID */
    4652           1 :     avio_wb32(pb, 0xbb88695c);
    4653           1 :     avio_wb32(pb, 0xfac9c740);
    4654             : 
    4655           1 :     avio_wb32(pb, 0x0);  /* ? */
    4656           1 :     avio_wb32(pb, 0x3);  /* 3 sections ? */
    4657             : 
    4658           1 :     avio_wb32(pb, 0x14); /* size */
    4659           1 :     ffio_wfourcc(pb, "FPRF");
    4660           1 :     avio_wb32(pb, 0x0);  /* ? */
    4661           1 :     avio_wb32(pb, 0x0);  /* ? */
    4662           1 :     avio_wb32(pb, 0x0);  /* ? */
    4663             : 
    4664           1 :     avio_wb32(pb, 0x2c);  /* size */
    4665           1 :     ffio_wfourcc(pb, "APRF"); /* audio */
    4666           1 :     avio_wb32(pb, 0x0);
    4667           1 :     avio_wb32(pb, 0x2);   /* TrackID */
    4668           1 :     ffio_wfourcc(pb, "mp4a");
    4669           1 :     avio_wb32(pb, 0x20f);
    4670           1 :     avio_wb32(pb, 0x0);
    4671           1 :     avio_wb32(pb, audio_kbitrate);
    4672           1 :     avio_wb32(pb, audio_kbitrate);
    4673           1 :     avio_wb32(pb, audio_rate);
    4674           1 :     avio_wb32(pb, audio_par->channels);
    4675             : 
    4676           1 :     avio_wb32(pb, 0x34);  /* size */
    4677           1 :     ffio_wfourcc(pb, "VPRF");   /* video */
    4678           1 :     avio_wb32(pb, 0x0);
    4679           1 :     avio_wb32(pb, 0x1);    /* TrackID */
    4680           1 :     if (video_par->codec_id == AV_CODEC_ID_H264) {
    4681           1 :         ffio_wfourcc(pb, "avc1");
    4682           1 :         avio_wb16(pb, 0x014D);
    4683           1 :         avio_wb16(pb, 0x0015);
    4684             :     } else {
    4685           0 :         ffio_wfourcc(pb, "mp4v");
    4686           0 :         avio_wb16(pb, 0x0000);
    4687           0 :         avio_wb16(pb, 0x0103);
    4688             :     }
    4689           1 :     avio_wb32(pb, 0x0);
    4690           1 :     avio_wb32(pb, video_kbitrate);
    4691           1 :     avio_wb32(pb, video_kbitrate);
    4692           1 :     avio_wb32(pb, frame_rate);
    4693           1 :     avio_wb32(pb, frame_rate);
    4694           1 :     avio_wb16(pb, video_par->width);
    4695           1 :     avio_wb16(pb, video_par->height);
    4696           1 :     avio_wb32(pb, 0x010001); /* ? */
    4697             : 
    4698           1 :     return 0;
    4699             : }
    4700             : 
    4701         149 : static int mov_write_identification(AVIOContext *pb, AVFormatContext *s)
    4702             : {
    4703         149 :     MOVMuxContext *mov = s->priv_data;
    4704             :     int i;
    4705             : 
    4706         149 :     mov_write_ftyp_tag(pb,s);
    4707         149 :     if (mov->mode == MODE_PSP) {
    4708           1 :         int video_streams_nb = 0, audio_streams_nb = 0, other_streams_nb = 0;
    4709           3 :         for (i = 0; i < s->nb_streams; i++) {
    4710           2 :             AVStream *st = s->streams[i];
    4711           2 :             if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
    4712           1 :                 video_streams_nb++;
    4713           1 :             else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
    4714           1 :                 audio_streams_nb++;
    4715             :             else
    4716           0 :                 other_streams_nb++;
    4717             :             }
    4718             : 
    4719           1 :         if (video_streams_nb != 1 || audio_streams_nb != 1 || other_streams_nb) {
    4720           0 :             av_log(s, AV_LOG_ERROR, "PSP mode need one video and one audio stream\n");
    4721           0 :             return AVERROR(EINVAL);
    4722             :         }
    4723           1 :         return mov_write_uuidprof_tag(pb, s);
    4724             :     }
    4725         148 :     return 0;
    4726             : }
    4727             : 
    4728           0 : static int mov_parse_mpeg2_frame(AVPacket *pkt, uint32_t *flags)
    4729             : {
    4730           0 :     uint32_t c = -1;
    4731           0 :     int i, closed_gop = 0;
    4732             : 
    4733           0 :     for (i = 0; i < pkt->size - 4; i++) {
    4734           0 :         c = (c << 8) + pkt->data[i];
    4735           0 :         if (c == 0x1b8) { // gop
    4736           0 :             closed_gop = pkt->data[i + 4] >> 6 & 0x01;
    4737           0 :         } else if (c == 0x100) { // pic
    4738           0 :             int temp_ref = (pkt->data[i + 1] << 2) | (pkt->data[i + 2] >> 6);
    4739           0 :             if (!temp_ref || closed_gop) // I picture is not reordered
    4740           0 :                 *flags = MOV_SYNC_SAMPLE;
    4741             :             else
    4742           0 :                 *flags = MOV_PARTIAL_SYNC_SAMPLE;
    4743           0 :             break;
    4744             :         }
    4745             :     }
    4746           0 :     return 0;
    4747             : }
    4748             : 
    4749           0 : static void mov_parse_vc1_frame(AVPacket *pkt, MOVTrack *trk)
    4750             : {
    4751           0 :     const uint8_t *start, *next, *end = pkt->data + pkt->size;
    4752           0 :     int seq = 0, entry = 0;
    4753           0 :     int key = pkt->flags & AV_PKT_FLAG_KEY;
    4754           0 :     start = find_next_marker(pkt->data, end);
    4755           0 :     for (next = start; next < end; start = next) {
    4756           0 :         next = find_next_marker(start + 4, end);
    4757           0 :         switch (AV_RB32(start)) {
    4758           0 :         case VC1_CODE_SEQHDR:
    4759           0 :             seq = 1;
    4760           0 :             break;
    4761           0 :         case VC1_CODE_ENTRYPOINT:
    4762           0 :             entry = 1;
    4763           0 :             break;
    4764           0 :         case VC1_CODE_SLICE:
    4765           0 :             trk->vc1_info.slices = 1;
    4766           0 :             break;
    4767             :         }
    4768             :     }
    4769           0 :     if (!trk->entry && trk->vc1_info.first_packet_seen)
    4770           0 :         trk->vc1_info.first_frag_written = 1;
    4771           0 :     if (!trk->entry && !trk->vc1_info.first_frag_written) {
    4772             :         /* First packet in first fragment */
    4773           0 :         trk->vc1_info.first_packet_seq   = seq;
    4774           0 :         trk->vc1_info.first_packet_entry = entry;
    4775           0 :         trk->vc1_info.first_packet_seen  = 1;
    4776           0 :     } else if ((seq && !trk->vc1_info.packet_seq) ||
    4777           0 :                (entry && !trk->vc1_info.packet_entry)) {
    4778             :         int i;
    4779           0 :         for (i = 0; i < trk->entry; i++)
    4780           0 :             trk->cluster[i].flags &= ~MOV_SYNC_SAMPLE;
    4781           0 :         trk->has_keyframes = 0;
    4782           0 :         if (seq)
    4783           0 :             trk->vc1_info.packet_seq = 1;
    4784           0 :         if (entry)
    4785           0 :             trk->vc1_info.packet_entry = 1;
    4786           0 :         if (!trk->vc1_info.first_frag_written) {
    4787             :             /* First fragment */
    4788           0 :             if ((!seq   || trk->vc1_info.first_packet_seq) &&
    4789           0 :                 (!entry || trk->vc1_info.first_packet_entry)) {
    4790             :                 /* First packet had the same headers as this one, readd the
    4791             :                  * sync sample flag. */
    4792           0 :                 trk->cluster[0].flags |= MOV_SYNC_SAMPLE;
    4793           0 :                 trk->has_keyframes = 1;
    4794             :             }
    4795             :         }
    4796             :     }
    4797           0 :     if (trk->vc1_info.packet_seq && trk->vc1_info.packet_entry)
    4798           0 :         key = seq && entry;
    4799           0 :     else if (trk->vc1_info.packet_seq)
    4800           0 :         key = seq;
    4801           0 :     else if (trk->vc1_info.packet_entry)
    4802           0 :         key = entry;
    4803           0 :     if (key) {
    4804           0 :         trk->cluster[trk->entry].flags |= MOV_SYNC_SAMPLE;
    4805           0 :         trk->has_keyframes++;
    4806             :     }
    4807           0 : }
    4808             : 
    4809           0 : static int mov_flush_fragment_interleaving(AVFormatContext *s, MOVTrack *track)
    4810             : {
    4811           0 :     MOVMuxContext *mov = s->priv_data;
    4812             :     int ret, buf_size;
    4813             :     uint8_t *buf;
    4814             :     int i, offset;
    4815             : 
    4816           0 :     if (!track->mdat_buf)
    4817           0 :         return 0;
    4818           0 :     if (!mov->mdat_buf) {
    4819           0 :         if ((ret = avio_open_dyn_buf(&mov->mdat_buf)) < 0)
    4820           0 :             return ret;
    4821             :     }
    4822           0 :     buf_size = avio_close_dyn_buf(track->mdat_buf, &buf);
    4823           0 :     track->mdat_buf = NULL;
    4824             : 
    4825           0 :     offset = avio_tell(mov->mdat_buf);
    4826           0 :     avio_write(mov->mdat_buf, buf, buf_size);
    4827           0 :     av_free(buf);
    4828             : 
    4829           0 :     for (i = track->entries_flushed; i < track->entry; i++)
    4830           0 :         track->cluster[i].pos += offset;
    4831           0 :     track->entries_flushed = track->entry;
    4832           0 :     return 0;
    4833             : }
    4834             : 
    4835          91 : static int mov_flush_fragment(AVFormatContext *s, int force)
    4836             : {
    4837          91 :     MOVMuxContext *mov = s->priv_data;
    4838          91 :     int i, first_track = -1;
    4839          91 :     int64_t mdat_size = 0;
    4840             :     int ret;
    4841          91 :     int has_video = 0, starts_with_key = 0, first_video_track = 1;
    4842             : 
    4843          91 :     if (!(mov->flags & FF_MOV_FLAG_FRAGMENT))
    4844           0 :         return 0;
    4845             : 
    4846             :     // Try to fill in the duration of the last packet in each stream
    4847             :     // from queued packets in the interleave queues. If the flushing
    4848             :     // of fragments was triggered automatically by an AVPacket, we
    4849             :     // already have reliable info for the end of that track, but other
    4850             :     // tracks may need to be filled in.
    4851         263 :     for (i = 0; i < s->nb_streams; i++) {
    4852         172 :         MOVTrack *track = &mov->tracks[i];
    4853         172 :         if (!track->end_reliable) {
    4854             :             AVPacket pkt;
    4855         136 :             if (!ff_interleaved_peek(s, i, &pkt, 1)) {
    4856           5 :                 if (track->dts_shift != AV_NOPTS_VALUE)
    4857           0 :                     pkt.dts += track->dts_shift;
    4858           5 :                 track->track_duration = pkt.dts - track->start_dts;
    4859           5 :                 if (pkt.pts != AV_NOPTS_VALUE)
    4860           5 :                     track->end_pts = pkt.pts;
    4861             :                 else
    4862           0 :                     track->end_pts = pkt.dts;
    4863             :             }
    4864             :         }
    4865             :     }
    4866             : 
    4867         263 :     for (i = 0; i < mov->nb_streams; i++) {
    4868         172 :         MOVTrack *track = &mov->tracks[i];
    4869         172 :         if (track->entry <= 1)
    4870          33 :             continue;
    4871             :         // Sample durations are calculated as the diff of dts values,
    4872             :         // but for the last sample in a fragment, we don't know the dts
    4873             :         // of the first sample in the next fragment, so we have to rely
    4874             :         // on what was set as duration in the AVPacket. Not all callers
    4875             :         // set this though, so we might want to replace it with an
    4876             :         // estimate if it currently is zero.
    4877         139 :         if (get_cluster_duration(track, track->entry - 1) != 0)
    4878         135 :             continue;
    4879             :         // Use the duration (i.e. dts diff) of the second last sample for
    4880             :         // the last one. This is a wild guess (and fatal if it turns out
    4881             :         // to be too long), but probably the best we can do - having a zero
    4882             :         // duration is bad as well.
    4883           4 :         track->track_duration += get_cluster_duration(track, track->entry - 2);
    4884           4 :         track->end_pts        += get_cluster_duration(track, track->entry - 2);
    4885           4 :         if (!mov->missing_duration_warned) {
    4886           2 :             av_log(s, AV_LOG_WARNING,
    4887             :                    "Estimating the duration of the last packet in a "
    4888             :                    "fragment, consider setting the duration field in "
    4889             :                    "AVPacket instead.\n");
    4890           2 :             mov->missing_duration_warned = 1;
    4891             :         }
    4892             :     }
    4893             : 
    4894          91 :     if (!mov->moov_written) {
    4895          21 :         int64_t pos = avio_tell(s->pb);
    4896             :         uint8_t *buf;
    4897             :         int buf_size, moov_size;
    4898             : 
    4899          59 :         for (i = 0; i < mov->nb_streams; i++)
    4900          42 :             if (!mov->tracks[i].entry)
    4901           4 :                 break;
    4902             :         /* Don't write the initial moov unless all tracks have data */
    4903          21 :         if (i < mov->nb_streams && !force)
    4904           2 :             return 0;
    4905             : 
    4906          19 :         moov_size = get_moov_size(s);
    4907          57 :         for (i = 0; i < mov->nb_streams; i++)
    4908          38 :             mov->tracks[i].data_offset = pos + moov_size + 8;
    4909             : 
    4910          19 :         avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_HEADER);
    4911          19 :         if (mov->flags & FF_MOV_FLAG_DELAY_MOOV)
    4912          16 :             mov_write_identification(s->pb, s);
    4913          19 :         if ((ret = mov_write_moov_tag(s->pb, mov, s)) < 0)
    4914           0 :             return ret;
    4915             : 
    4916          19 :         if (mov->flags & FF_MOV_FLAG_DELAY_MOOV) {
    4917          16 :             if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX)
    4918           0 :                 mov->reserved_header_pos = avio_tell(s->pb);
    4919          16 :             avio_flush(s->pb);
    4920          16 :             mov->moov_written = 1;
    4921          16 :             return 0;
    4922             :         }
    4923             : 
    4924           3 :         buf_size = avio_close_dyn_buf(mov->mdat_buf, &buf);
    4925           3 :         mov->mdat_buf = NULL;
    4926           3 :         avio_wb32(s->pb, buf_size + 8);
    4927           3 :         ffio_wfourcc(s->pb, "mdat");
    4928           3 :         avio_write(s->pb, buf, buf_size);
    4929           3 :         av_free(buf);
    4930             : 
    4931           3 :         if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX)
    4932           0 :             mov->reserved_header_pos = avio_tell(s->pb);
    4933             : 
    4934           3 :         mov->moov_written = 1;
    4935           3 :         mov->mdat_size = 0;
    4936           9 :         for (i = 0; i < mov->nb_streams; i++) {
    4937           6 :             if (mov->tracks[i].entry)
    4938          18 :                 mov->tracks[i].frag_start += mov->tracks[i].start_dts +
    4939          12 :                                              mov->tracks[i].track_duration -
    4940           6 :                                              mov->tracks[i].cluster[0].dts;
    4941           6 :             mov->tracks[i].entry = 0;
    4942           6 :             mov->tracks[i].end_reliable = 0;
    4943             :         }
    4944           3 :         avio_flush(s->pb);
    4945           3 :         return 0;
    4946             :     }
    4947             : 
    4948          70 :     if (mov->frag_interleave) {
    4949           0 :         for (i = 0; i < mov->nb_streams; i++) {
    4950           0 :             MOVTrack *track = &mov->tracks[i];
    4951             :             int ret;
    4952           0 :             if ((ret = mov_flush_fragment_interleaving(s, track)) < 0)
    4953           0 :                 return ret;
    4954             :         }
    4955             : 
    4956           0 :         if (!mov->mdat_buf)
    4957           0 :             return 0;
    4958           0 :         mdat_size = avio_tell(mov->mdat_buf);
    4959             :     }
    4960             : 
    4961         200 :     for (i = 0; i < mov->nb_streams; i++) {
    4962         130 :         MOVTrack *track = &mov->tracks[i];
    4963         130 :         if (mov->flags & FF_MOV_FLAG_SEPARATE_MOOF || mov->frag_interleave)
    4964          13 :             track->data_offset = 0;
    4965             :         else
    4966         117 :             track->data_offset = mdat_size;
    4967         130 :         if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
    4968          69 :             has_video = 1;
    4969          69 :             if (first_video_track) {
    4970          69 :                 if (track->entry)
    4971          57 :                     starts_with_key = track->cluster[0].flags & MOV_SYNC_SAMPLE;
    4972          69 :                 first_video_track = 0;
    4973             :             }
    4974             :         }
    4975         130 :         if (!track->entry)
    4976          27 :             continue;
    4977         103 :         if (track->mdat_buf)
    4978         103 :             mdat_size += avio_tell(track->mdat_buf);
    4979         103 :         if (first_track < 0)
    4980          58 :             first_track = i;
    4981             :     }
    4982             : 
    4983          70 :     if (!mdat_size)
    4984          12 :         return 0;
    4985             : 
    4986         174 :     avio_write_marker(s->pb,
    4987         116 :                       av_rescale(mov->tracks[first_track].cluster[0].dts, AV_TIME_BASE, mov->tracks[first_track].timescale),
    4988          58 :                       (has_video ? starts_with_key : mov->tracks[first_track].cluster[0].flags & MOV_SYNC_SAMPLE) ? AVIO_DATA_MARKER_SYNC_POINT : AVIO_DATA_MARKER_BOUNDARY_POINT);
    4989             : 
    4990         164 :     for (i = 0; i < mov->nb_streams; i++) {
    4991         106 :         MOVTrack *track = &mov->tracks[i];
    4992         106 :         int buf_size, write_moof = 1, moof_tracks = -1;
    4993             :         uint8_t *buf;
    4994         106 :         int64_t duration = 0;
    4995             : 
    4996         106 :         if (track->entry)
    4997         206 :             duration = track->start_dts + track->track_duration -
    4998         103 :                        track->cluster[0].dts;
    4999         106 :         if (mov->flags & FF_MOV_FLAG_SEPARATE_MOOF) {
    5000          13 :             if (!track->mdat_buf)
    5001           3 :                 continue;
    5002          13 :             mdat_size = avio_tell(track->mdat_buf);
    5003          13 :             moof_tracks = i;
    5004             :         } else {
    5005          93 :             write_moof = i == first_track;
    5006             :         }
    5007             : 
    5008         106 :         if (write_moof) {
    5009          60 :             avio_flush(s->pb);
    5010             : 
    5011          60 :             mov_write_moof_tag(s->pb, mov, moof_tracks, mdat_size);
    5012          60 :             mov->fragments++;
    5013             : 
    5014          60 :             avio_wb32(s->pb, mdat_size + 8);
    5015          60 :             ffio_wfourcc(s->pb, "mdat");
    5016             :         }
    5017             : 
    5018         106 :         if (track->entry)
    5019         103 :             track->frag_start += duration;
    5020         106 :         track->entry = 0;
    5021         106 :         track->entries_flushed = 0;
    5022         106 :         track->end_reliable = 0;
    5023         106 :         if (!mov->frag_interleave) {
    5024         106 :             if (!track->mdat_buf)
    5025           3 :                 continue;
    5026         103 :             buf_size = avio_close_dyn_buf(track->mdat_buf, &buf);
    5027         103 :             track->mdat_buf = NULL;
    5028             :         } else {
    5029           0 :             if (!mov->mdat_buf)
    5030           0 :                 continue;
    5031           0 :             buf_size = avio_close_dyn_buf(mov->mdat_buf, &buf);
    5032           0 :             mov->mdat_buf = NULL;
    5033             :         }
    5034             : 
    5035         103 :         avio_write(s->pb, buf, buf_size);
    5036         103 :         av_free(buf);
    5037             :     }
    5038             : 
    5039          58 :     mov->mdat_size = 0;
    5040             : 
    5041          58 :     avio_flush(s->pb);
    5042          58 :     return 0;
    5043             : }
    5044             : 
    5045          57 : static int mov_auto_flush_fragment(AVFormatContext *s, int force)
    5046             : {
    5047          57 :     MOVMuxContext *mov = s->priv_data;
    5048          57 :     int had_moov = mov->moov_written;
    5049          57 :     int ret = mov_flush_fragment(s, force);
    5050          57 :     if (ret < 0)
    5051           0 :         return ret;
    5052             :     // If using delay_moov, the first flush only wrote the moov,
    5053             :     // not the actual moof+mdat pair, thus flush once again.
    5054          57 :     if (!had_moov && mov->flags & FF_MOV_FLAG_DELAY_MOOV)
    5055           9 :         ret = mov_flush_fragment(s, force);
    5056          57 :     return ret;
    5057             : }
    5058             : 
    5059       25815 : static int check_pkt(AVFormatContext *s, AVPacket *pkt)
    5060             : {
    5061       25815 :     MOVMuxContext *mov = s->priv_data;
    5062       25815 :     MOVTrack *trk = &mov->tracks[pkt->stream_index];
    5063             :     int64_t ref;
    5064             :     uint64_t duration;
    5065             : 
    5066       25815 :     if (trk->entry) {
    5067       25350 :         ref = trk->cluster[trk->entry - 1].dts;
    5068         465 :     } else if (   trk->start_dts != AV_NOPTS_VALUE
    5069          95 :                && !trk->frag_discont) {
    5070          87 :         ref = trk->start_dts + trk->track_duration;
    5071             :     } else
    5072         378 :         ref = pkt->dts; // Skip tests for the first packet
    5073             : 
    5074       25815 :     if (trk->dts_shift != AV_NOPTS_VALUE) {
    5075             :         /* With negative CTS offsets we have set an offset to the DTS,
    5076             :          * reverse this for the check. */
    5077         653 :         ref -= trk->dts_shift;
    5078             :     }
    5079             : 
    5080       25815 :     duration = pkt->dts - ref;
    5081       25815 :     if (pkt->dts < ref || duration >= INT_MAX) {
    5082           0 :         av_log(s, AV_LOG_ERROR, "Application provided duration: %"PRId64" / timestamp: %"PRId64" is out of range for mov/mp4 format\n",
    5083             :             duration, pkt->dts
    5084             :         );
    5085             : 
    5086           0 :         pkt->dts = ref + 1;
    5087           0 :         pkt->pts = AV_NOPTS_VALUE;
    5088             :     }
    5089             : 
    5090       25815 :     if (pkt->duration < 0 || pkt->duration > INT_MAX) {
    5091           0 :         av_log(s, AV_LOG_ERROR, "Application provided duration: %"PRId64" is invalid\n", pkt->duration);
    5092           0 :         return AVERROR(EINVAL);
    5093             :     }
    5094       25815 :     return 0;
    5095             : }
    5096             : 
    5097       12942 : int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
    5098             : {
    5099       12942 :     MOVMuxContext *mov = s->priv_data;
    5100       12942 :     AVIOContext *pb = s->pb;
    5101       12942 :     MOVTrack *trk = &mov->tracks[pkt->stream_index];
    5102       12942 :     AVCodecParameters *par = trk->par;
    5103       12942 :     unsigned int samples_in_chunk = 0;
    5104       12942 :     int size = pkt->size, ret = 0;
    5105       12942 :     uint8_t *reformatted_data = NULL;
    5106             : 
    5107       12942 :     ret = check_pkt(s, pkt);
    5108       12942 :     if (ret < 0)
    5109           0 :         return ret;
    5110             : 
    5111       12942 :     if (mov->flags & FF_MOV_FLAG_FRAGMENT) {
    5112             :         int ret;
    5113        4651 :         if (mov->moov_written || mov->flags & FF_MOV_FLAG_EMPTY_MOOV) {
    5114        4431 :             if (mov->frag_interleave && mov->fragments > 0) {
    5115           0 :                 if (trk->entry - trk->entries_flushed >= mov->frag_interleave) {
    5116           0 :                     if ((ret = mov_flush_fragment_interleaving(s, trk)) < 0)
    5117           0 :                         return ret;
    5118             :                 }
    5119             :             }
    5120             : 
    5121        4431 :             if (!trk->mdat_buf) {
    5122         103 :                 if ((ret = avio_open_dyn_buf(&trk->mdat_buf)) < 0)
    5123           0 :                     return ret;
    5124             :             }
    5125        4431 :             pb = trk->mdat_buf;
    5126             :         } else {
    5127         220 :             if (!mov->mdat_buf) {
    5128           3 :                 if ((ret = avio_open_dyn_buf(&mov->mdat_buf)) < 0)
    5129           0 :                     return ret;
    5130             :             }
    5131         220 :             pb = mov->mdat_buf;
    5132             :         }
    5133             :     }
    5134             : 
    5135       12942 :     if (par->codec_id == AV_CODEC_ID_AMR_NB) {
    5136             :         /* We must find out how many AMR blocks there are in one packet */
    5137             :         static const uint16_t packed_size[16] =
    5138             :             {13, 14, 16, 18, 20, 21, 27, 32, 6, 0, 0, 0, 0, 0, 0, 1};
    5139           0 :         int len = 0;
    5140             : 
    5141           0 :         while (len < size && samples_in_chunk < 100) {
    5142           0 :             len += packed_size[(pkt->data[len] >> 3) & 0x0F];
    5143           0 :             samples_in_chunk++;
    5144             :         }
    5145           0 :         if (samples_in_chunk > 1) {
    5146           0 :             av_log(s, AV_LOG_ERROR, "fatal error, input is not a single packet, implement a AVParser for it\n");
    5147           0 :             return -1;
    5148             :         }
    5149       25884 :     } else if (par->codec_id == AV_CODEC_ID_ADPCM_MS ||
    5150       12942 :                par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) {
    5151           0 :         samples_in_chunk = trk->par->frame_size;
    5152       12942 :     } else if (trk->sample_size)
    5153        1219 :         samples_in_chunk = size / trk->sample_size;
    5154             :     else
    5155       11723 :         samples_in_chunk = 1;
    5156             : 
    5157             :     /* copy extradata if it exists */
    5158       12943 :     if (trk->vos_len == 0 && par->extradata_size > 0 &&
    5159           3 :         !TAG_IS_AVCI(trk->tag) &&
    5160           1 :         (par->codec_id != AV_CODEC_ID_DNXHD)) {
    5161           1 :         trk->vos_len  = par->extradata_size;
    5162           1 :         trk->vos_data = av_malloc(trk->vos_len);
    5163           1 :         if (!trk->vos_data) {
    5164           0 :             ret = AVERROR(ENOMEM);
    5165           0 :             goto err;
    5166             :         }
    5167           1 :         memcpy(trk->vos_data, par->extradata, trk->vos_len);
    5168             :     }
    5169             : 
    5170       17047 :     if (par->codec_id == AV_CODEC_ID_AAC && pkt->size > 2 &&
    5171        4105 :         (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) {
    5172           0 :         if (!s->streams[pkt->stream_index]->nb_frames) {
    5173           0 :             av_log(s, AV_LOG_ERROR, "Malformed AAC bitstream detected: "
    5174             :                    "use the audio bitstream filter 'aac_adtstoasc' to fix it "
    5175             :                    "('-bsf:a aac_adtstoasc' option with ffmpeg)\n");
    5176           0 :             return -1;
    5177             :         }
    5178           0 :         av_log(s, AV_LOG_WARNING, "aac bitstream error\n");
    5179             :     }
    5180       12942 :     if (par->codec_id == AV_CODEC_ID_H264 && trk->vos_len > 0 && *(uint8_t *)trk->vos_data != 1 && !TAG_IS_AVCI(trk->tag)) {
    5181             :         /* from x264 or from bytestream H.264 */
    5182             :         /* NAL reformatting needed */
    5183           0 :         if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams) {
    5184           0 :             ff_avc_parse_nal_units_buf(pkt->data, &reformatted_data,
    5185             :                                        &size);
    5186           0 :             avio_write(pb, reformatted_data, size);
    5187             :         } else {
    5188           0 :             if (trk->cenc.aes_ctr) {
    5189           0 :                 size = ff_mov_cenc_avc_parse_nal_units(&trk->cenc, pb, pkt->data, size);
    5190           0 :                 if (size < 0) {
    5191           0 :                     ret = size;
    5192           0 :                     goto err;
    5193             :                 }
    5194             :             } else {
    5195           0 :                 size = ff_avc_parse_nal_units(pb, pkt->data, pkt->size);
    5196             :             }
    5197             :         }
    5198       12990 :     } else if (par->codec_id == AV_CODEC_ID_HEVC && trk->vos_len > 6 &&
    5199          48 :                (AV_RB24(trk->vos_data) == 1 || AV_RB32(trk->vos_data) == 1)) {
    5200             :         /* extradata is Annex B, assume the bitstream is too and convert it */
    5201          96 :         if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams) {
    5202           0 :             ff_hevc_annexb2mp4_buf(pkt->data, &reformatted_data, &size, 0, NULL);
    5203           0 :             avio_write(pb, reformatted_data, size);
    5204             :         } else {
    5205          48 :             size = ff_hevc_annexb2mp4(pb, pkt->data, pkt->size, 0, NULL);
    5206             :         }
    5207             : #if CONFIG_AC3_PARSER
    5208       12894 :     } else if (par->codec_id == AV_CODEC_ID_EAC3) {
    5209         652 :         size = handle_eac3(mov, pkt, trk);
    5210         652 :         if (size < 0)
    5211           0 :             return size;
    5212         652 :         else if (!size)
    5213           1 :             goto end;
    5214         651 :         avio_write(pb, pkt->data, size);
    5215             : #endif
    5216             :     } else {
    5217       12242 :         if (trk->cenc.aes_ctr) {
    5218           0 :             if (par->codec_id == AV_CODEC_ID_H264 && par->extradata_size > 4) {
    5219           0 :                 int nal_size_length = (par->extradata[4] & 0x3) + 1;
    5220           0 :                 ret = ff_mov_cenc_avc_write_nal_units(s, &trk->cenc, nal_size_length, pb, pkt->data, size);
    5221             :             } else {
    5222           0 :                 ret = ff_mov_cenc_write_packet(&trk->cenc, pb, pkt->data, size);
    5223             :             }
    5224             : 
    5225           0 :             if (ret) {
    5226           0 :                 goto err;
    5227             :             }
    5228             :         } else {
    5229       12242 :             avio_write(pb, pkt->data, size);
    5230             :         }
    5231             :     }
    5232             : 
    5233       25767 :     if ((par->codec_id == AV_CODEC_ID_DNXHD ||
    5234       12941 :          par->codec_id == AV_CODEC_ID_AC3) && !trk->vos_len) {
    5235             :         /* copy frame to create needed atoms */
    5236          23 :         trk->vos_len  = size;
    5237          23 :         trk->vos_data = av_malloc(size);
    5238          23 :         if (!trk->vos_data) {
    5239           0 :             ret = AVERROR(ENOMEM);
    5240           0 :             goto err;
    5241             :         }
    5242          23 :         memcpy(trk->vos_data, pkt->data, size);
    5243             :     }
    5244             : 
    5245       12941 :     if (trk->entry >= trk->cluster_capacity) {
    5246         192 :         unsigned new_capacity = 2 * (trk->entry + MOV_INDEX_CLUSTER_SIZE);
    5247         192 :         if (av_reallocp_array(&trk->cluster, new_capacity,
    5248             :                               sizeof(*trk->cluster))) {
    5249           0 :             ret = AVERROR(ENOMEM);
    5250           0 :             goto err;
    5251             :         }
    5252         192 :         trk->cluster_capacity = new_capacity;
    5253             :     }
    5254             : 
    5255       12941 :     trk->cluster[trk->entry].pos              = avio_tell(pb) - size;
    5256       12941 :     trk->cluster[trk->entry].samples_in_chunk = samples_in_chunk;
    5257       12941 :     trk->cluster[trk->entry].chunkNum         = 0;
    5258       12941 :     trk->cluster[trk->entry].size             = size;
    5259       12941 :     trk->cluster[trk->entry].entries          = samples_in_chunk;
    5260       12941 :     trk->cluster[trk->entry].dts              = pkt->dts;
    5261       12941 :     if (!trk->entry && trk->start_dts != AV_NOPTS_VALUE) {
    5262          63 :         if (!trk->frag_discont) {
    5263             :             /* First packet of a new fragment. We already wrote the duration
    5264             :              * of the last packet of the previous fragment based on track_duration,
    5265             :              * which might not exactly match our dts. Therefore adjust the dts
    5266             :              * of this packet to be what the previous packets duration implies. */
    5267          59 :             trk->cluster[trk->entry].dts = trk->start_dts + trk->track_duration;
    5268             :             /* We also may have written the pts and the corresponding duration
    5269             :              * in sidx/tfrf/tfxd tags; make sure the sidx pts and duration match up with
    5270             :              * the next fragment. This means the cts of the first sample must
    5271             :              * be the same in all fragments, unless end_pts was updated by
    5272             :              * the packet causing the fragment to be written. */
    5273         108 :             if ((mov->flags & FF_MOV_FLAG_DASH && !(mov->flags & FF_MOV_FLAG_GLOBAL_SIDX)) ||
    5274          49 :                 mov->mode == MODE_ISM)
    5275          18 :                 pkt->pts = pkt->dts + trk->end_pts - trk->cluster[trk->entry].dts;
    5276             :         } else {
    5277             :             /* New fragment, but discontinuous from previous fragments.
    5278             :              * Pretend the duration sum of the earlier fragments is
    5279             :              * pkt->dts - trk->start_dts. */
    5280           4 :             trk->frag_start = pkt->dts - trk->start_dts;
    5281           4 :             trk->end_pts = AV_NOPTS_VALUE;
    5282           4 :             trk->frag_discont = 0;
    5283             :         }
    5284             :     }
    5285             : 
    5286       12967 :     if (!trk->entry && trk->start_dts == AV_NOPTS_VALUE && !mov->use_editlist &&
    5287          26 :         s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO) {
    5288             :         /* Not using edit lists and shifting the first track to start from zero.
    5289             :          * If the other streams start from a later timestamp, we won't be able
    5290             :          * to signal the difference in starting time without an edit list.
    5291             :          * Thus move the timestamp for this first sample to 0, increasing
    5292             :          * its duration instead. */
    5293          24 :         trk->cluster[trk->entry].dts = trk->start_dts = 0;
    5294             :     }
    5295       12941 :     if (trk->start_dts == AV_NOPTS_VALUE) {
    5296         158 :         trk->start_dts = pkt->dts;
    5297         158 :         if (trk->frag_discont) {
    5298           6 :             if (mov->use_editlist) {
    5299             :                 /* Pretend the whole stream started at pts=0, with earlier fragments
    5300             :                  * already written. If the stream started at pts=0, the duration sum
    5301             :                  * of earlier fragments would have been pkt->pts. */
    5302           4 :                 trk->frag_start = pkt->pts;
    5303           4 :                 trk->start_dts  = pkt->dts - pkt->pts;
    5304             :             } else {
    5305             :                 /* Pretend the whole stream started at dts=0, with earlier fragments
    5306             :                  * already written, with a duration summing up to pkt->dts. */
    5307           2 :                 trk->frag_start = pkt->dts;
    5308           2 :                 trk->start_dts  = 0;
    5309             :             }
    5310           6 :             trk->frag_discont = 0;
    5311         152 :         } else if (pkt->dts && mov->moov_written)
    5312           1 :             av_log(s, AV_LOG_WARNING,
    5313             :                    "Track %d starts with a nonzero dts %"PRId64", while the moov "
    5314             :                    "already has been written. Set the delay_moov flag to handle "
    5315             :                    "this case.\n",
    5316             :                    pkt->stream_index, pkt->dts);
    5317             :     }
    5318       12941 :     trk->track_duration = pkt->dts - trk->start_dts + pkt->duration;
    5319       12941 :     trk->last_sample_is_subtitle_end = 0;
    5320             : 
    5321       12941 :     if (pkt->pts == AV_NOPTS_VALUE) {
    5322          48 :         av_log(s, AV_LOG_WARNING, "pts has no value\n");
    5323          48 :         pkt->pts = pkt->dts;
    5324             :     }
    5325       12941 :     if (pkt->dts != pkt->pts)
    5326         732 :         trk->flags |= MOV_TRACK_CTTS;
    5327       12941 :     trk->cluster[trk->entry].cts   = pkt->pts - pkt->dts;
    5328       12941 :     trk->cluster[trk->entry].flags = 0;
    5329       12941 :     if (trk->start_cts == AV_NOPTS_VALUE)
    5330         182 :         trk->start_cts = pkt->pts - pkt->dts;
    5331       12941 :     if (trk->end_pts == AV_NOPTS_VALUE)
    5332         558 :         trk->end_pts = trk->cluster[trk->entry].dts +
    5333         372 :                        trk->cluster[trk->entry].cts + pkt->duration;
    5334             :     else
    5335       12755 :         trk->end_pts = FFMAX(trk->end_pts, trk->cluster[trk->entry].dts +
    5336             :                                            trk->cluster[trk->entry].cts +
    5337             :                                            pkt->duration);
    5338             : 
    5339       12941 :     if (par->codec_id == AV_CODEC_ID_VC1) {
    5340           0 :         mov_parse_vc1_frame(pkt, trk);
    5341       12941 :     } else if (pkt->flags & AV_PKT_FLAG_KEY) {
    5342        6816 :         if (mov->mode == MODE_MOV && par->codec_id == AV_CODEC_ID_MPEG2VIDEO &&
    5343           0 :             trk->entry > 0) { // force sync sample for the first key frame
    5344           0 :             mov_parse_mpeg2_frame(pkt, &trk->cluster[trk->entry].flags);
    5345           0 :             if (trk->cluster[trk->entry].flags & MOV_PARTIAL_SYNC_SAMPLE)
    5346           0 :                 trk->flags |= MOV_TRACK_STPS;
    5347             :         } else {
    5348        6816 :             trk->cluster[trk->entry].flags = MOV_SYNC_SAMPLE;
    5349             :         }
    5350        6816 :         if (trk->cluster[trk->entry].flags & MOV_SYNC_SAMPLE)
    5351        6816 :             trk->has_keyframes++;
    5352             :     }
    5353       12941 :     if (pkt->flags & AV_PKT_FLAG_DISPOSABLE) {
    5354           0 :         trk->cluster[trk->entry].flags |= MOV_DISPOSABLE_SAMPLE;
    5355           0 :         trk->has_disposable++;
    5356             :     }
    5357       12941 :     trk->entry++;
    5358       12941 :     trk->sample_count += samples_in_chunk;
    5359       12941 :     mov->mdat_size    += size;
    5360             : 
    5361       13083 :     if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams)
    5362         142 :         ff_mov_add_hinted_packet(s, pkt, trk->hint_track, trk->entry,
    5363             :                                  reformatted_data, size);
    5364             : 
    5365       25741 : end:
    5366       12942 : err:
    5367             : 
    5368       12942 :     av_free(reformatted_data);
    5369       12942 :     return ret;
    5370             : }
    5371             : 
    5372       12873 : static int mov_write_single_packet(AVFormatContext *s, AVPacket *pkt)
    5373             : {
    5374       12873 :         MOVMuxContext *mov = s->priv_data;
    5375       12873 :         MOVTrack *trk = &mov->tracks[pkt->stream_index];
    5376       12873 :         AVCodecParameters *par = trk->par;
    5377       12873 :         int64_t frag_duration = 0;
    5378       12873 :         int size = pkt->size;
    5379             : 
    5380       12873 :         int ret = check_pkt(s, pkt);
    5381       12873 :         if (ret < 0)
    5382           0 :             return ret;
    5383             : 
    5384       12873 :         if (mov->flags & FF_MOV_FLAG_FRAG_DISCONT) {
    5385             :             int i;
    5386          15 :             for (i = 0; i < s->nb_streams; i++)
    5387          10 :                 mov->tracks[i].frag_discont = 1;
    5388           5 :             mov->flags &= ~FF_MOV_FLAG_FRAG_DISCONT;
    5389             :         }
    5390             : 
    5391       12873 :         if (mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS) {
    5392         292 :             if (trk->dts_shift == AV_NOPTS_VALUE)
    5393           4 :                 trk->dts_shift = pkt->pts - pkt->dts;
    5394         292 :             pkt->dts += trk->dts_shift;
    5395             :         }
    5396             : 
    5397       25746 :         if (trk->par->codec_id == AV_CODEC_ID_MP4ALS ||
    5398       21639 :             trk->par->codec_id == AV_CODEC_ID_AAC ||
    5399        8766 :             trk->par->codec_id == AV_CODEC_ID_FLAC) {
    5400        4107 :             int side_size = 0;
    5401        4107 :             uint8_t *side = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size);
    5402        4107 :             if (side && side_size > 0 && (side_size != par->extradata_size || memcmp(side, par->extradata, side_size))) {
    5403           1 :                 void *newextra = av_mallocz(side_size + AV_INPUT_BUFFER_PADDING_SIZE);
    5404           1 :                 if (!newextra)
    5405           0 :                     return AVERROR(ENOMEM);
    5406           1 :                 av_free(par->extradata);
    5407           1 :                 par->extradata = newextra;
    5408           1 :                 memcpy(par->extradata, side, side_size);
    5409           1 :                 par->extradata_size = side_size;
    5410           1 :                 if (!pkt->size) // Flush packet
    5411           0 :                     mov->need_rewrite_extradata = 1;
    5412             :             }
    5413             :         }
    5414             : 
    5415       12873 :         if (!pkt->size) {
    5416           4 :             if (trk->start_dts == AV_NOPTS_VALUE && trk->frag_discont) {
    5417           4 :                 trk->start_dts = pkt->dts;
    5418           4 :                 if (pkt->pts != AV_NOPTS_VALUE)
    5419           4 :                     trk->start_cts = pkt->pts - pkt->dts;
    5420             :                 else
    5421           0 :                     trk->start_cts = 0;
    5422             :             }
    5423             : 
    5424           4 :             return 0;             /* Discard 0 sized packets */
    5425             :         }
    5426             : 
    5427       12869 :         if (trk->entry && pkt->stream_index < s->nb_streams)
    5428       12654 :             frag_duration = av_rescale_q(pkt->dts - trk->cluster[0].dts,
    5429       12654 :                                          s->streams[pkt->stream_index]->time_base,
    5430       12654 :                                          AV_TIME_BASE_Q);
    5431       13042 :         if ((mov->max_fragment_duration &&
    5432       13039 :              frag_duration >= mov->max_fragment_duration) ||
    5433       25732 :              (mov->max_fragment_size && mov->mdat_size + size >= mov->max_fragment_size) ||
    5434       16503 :              (mov->flags & FF_MOV_FLAG_FRAG_KEYFRAME &&
    5435        4737 :               par->codec_type == AVMEDIA_TYPE_VIDEO &&
    5436       15020 :               trk->entry && pkt->flags & AV_PKT_FLAG_KEY) ||
    5437       12843 :               (mov->flags & FF_MOV_FLAG_FRAG_EVERY_FRAME)) {
    5438          26 :             if (frag_duration >= mov->min_fragment_duration) {
    5439             :                 // Set the duration of this track to line up with the next
    5440             :                 // sample in this track. This avoids relying on AVPacket
    5441             :                 // duration, but only helps for this particular track, not
    5442             :                 // for the other ones that are flushed at the same time.
    5443          26 :                 trk->track_duration = pkt->dts - trk->start_dts;
    5444          26 :                 if (pkt->pts != AV_NOPTS_VALUE)
    5445          26 :                     trk->end_pts = pkt->pts;
    5446             :                 else
    5447           0 :                     trk->end_pts = pkt->dts;
    5448          26 :                 trk->end_reliable = 1;
    5449          26 :                 mov_auto_flush_fragment(s, 0);
    5450             :             }
    5451             :         }
    5452             : 
    5453       12869 :         return ff_mov_write_packet(s, pkt);
    5454             : }
    5455             : 
    5456           3 : static int mov_write_subtitle_end_packet(AVFormatContext *s,
    5457             :                                          int stream_index,
    5458             :                                          int64_t dts) {
    5459             :     AVPacket end;
    5460           3 :     uint8_t data[2] = {0};
    5461             :     int ret;
    5462             : 
    5463           3 :     av_init_packet(&end);
    5464           3 :     end.size = sizeof(data);
    5465           3 :     end.data = data;
    5466           3 :     end.pts = dts;
    5467           3 :     end.dts = dts;
    5468           3 :     end.duration = 0;
    5469           3 :     end.stream_index = stream_index;
    5470             : 
    5471           3 :     ret = mov_write_single_packet(s, &end);
    5472           3 :     av_packet_unref(&end);
    5473             : 
    5474           3 :     return ret;
    5475             : }
    5476             : 
    5477       12895 : static int mov_write_packet(AVFormatContext *s, AVPacket *pkt)
    5478             : {
    5479       12895 :     if (!pkt) {
    5480          25 :         mov_flush_fragment(s, 1);
    5481          25 :         return 1;
    5482             :     } else {
    5483             :         int i;
    5484       12870 :         MOVMuxContext *mov = s->priv_data;
    5485       12870 :         MOVTrack *trk = &mov->tracks[pkt->stream_index];
    5486             : 
    5487       12870 :         if (!pkt->size)
    5488           4 :             return mov_write_single_packet(s, pkt); /* Passthrough. */
    5489             : 
    5490             :         /*
    5491             :          * Subtitles require special handling.
    5492             :          *
    5493             :          * 1) For full complaince, every track must have a sample at
    5494             :          * dts == 0, which is rarely true for subtitles. So, as soon
    5495             :          * as we see any packet with dts > 0, write an empty subtitle
    5496             :          * at dts == 0 for any subtitle track with no samples in it.
    5497             :          *
    5498             :          * 2) For each subtitle track, check if the current packet's
    5499             :          * dts is past the duration of the last subtitle sample. If
    5500             :          * so, we now need to write an end sample for that subtitle.
    5501             :          *
    5502             :          * This must be done conditionally to allow for subtitles that
    5503             :          * immediately replace each other, in which case an end sample
    5504             :          * is not needed, and is, in fact, actively harmful.
    5505             :          *
    5506             :          * 3) See mov_write_trailer for how the final end sample is
    5507             :          * handled.
    5508             :          */
    5509       31871 :         for (i = 0; i < mov->nb_streams; i++) {
    5510       19005 :             MOVTrack *trk = &mov->tracks[i];
    5511             :             int ret;
    5512             : 
    5513       19008 :             if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT &&
    5514           5 :                 trk->track_duration < pkt->dts &&
    5515           4 :                 (trk->entry == 0 || !trk->last_sample_is_subtitle_end)) {
    5516           2 :                 ret = mov_write_subtitle_end_packet(s, i, trk->track_duration);
    5517           2 :                 if (ret < 0) return ret;
    5518           2 :                 trk->last_sample_is_subtitle_end = 1;
    5519             :             }
    5520             :         }
    5521             : 
    5522       12866 :         if (trk->mode == MODE_MOV && trk->par->codec_type == AVMEDIA_TYPE_VIDEO) {
    5523        2252 :             AVPacket *opkt = pkt;
    5524             :             int reshuffle_ret, ret;
    5525        2252 :             if (trk->is_unaligned_qt_rgb) {
    5526           0 :                 int64_t bpc = trk->par->bits_per_coded_sample != 15 ? trk->par->bits_per_coded_sample : 16;
    5527           0 :                 int expected_stride = ((trk->par->width * bpc + 15) >> 4)*2;
    5528           0 :                 reshuffle_ret = ff_reshuffle_raw_rgb(s, &pkt, trk->par, expected_stride);
    5529           0 :                 if (reshuffle_ret < 0)
    5530           0 :                     return reshuffle_ret;
    5531             :             } else
    5532        2252 :                 reshuffle_ret = 0;
    5533        2252 :             if (trk->par->format == AV_PIX_FMT_PAL8 && !trk->pal_done) {
    5534           1 :                 ret = ff_get_packet_palette(s, opkt, reshuffle_ret, trk->palette);
    5535           1 :                 if (ret < 0)
    5536           0 :                     goto fail;
    5537           2 :                 if (ret)
    5538           1 :                     trk->pal_done++;
    5539        2851 :             } else if (trk->par->codec_id == AV_CODEC_ID_RAWVIDEO &&
    5540        1200 :                        (trk->par->format == AV_PIX_FMT_GRAY8 ||
    5541         600 :                        trk->par->format == AV_PIX_FMT_MONOBLACK)) {
    5542           0 :                 for (i = 0; i < pkt->size; i++)
    5543           0 :                     pkt->data[i] = ~pkt->data[i];
    5544             :             }
    5545        2252 :             if (reshuffle_ret) {
    5546           0 :                 ret = mov_write_single_packet(s, pkt);
    5547           0 : fail:
    5548           0 :                 if (reshuffle_ret)
    5549           0 :                     av_packet_free(&pkt);
    5550           0 :                 return ret;
    5551             :             }
    5552             :         }
    5553             : 
    5554       12866 :         return mov_write_single_packet(s, pkt);
    5555             :     }
    5556             : }
    5557             : 
    5558             : // QuickTime chapters involve an additional text track with the chapter names
    5559             : // as samples, and a tref pointing from the other tracks to the chapter one.
    5560           0 : static int mov_create_chapter_track(AVFormatContext *s, int tracknum)
    5561             : {
    5562             :     AVIOContext *pb;
    5563             : 
    5564           0 :     MOVMuxContext *mov = s->priv_data;
    5565           0 :     MOVTrack *track = &mov->tracks[tracknum];
    5566           0 :     AVPacket pkt = { .stream_index = tracknum, .flags = AV_PKT_FLAG_KEY };
    5567             :     int i, len;
    5568             : 
    5569           0 :     track->mode = mov->mode;
    5570           0 :     track->tag = MKTAG('t','e','x','t');
    5571           0 :     track->timescale = MOV_TIMESCALE;
    5572           0 :     track->par = avcodec_parameters_alloc();
    5573           0 :     if (!track->par)
    5574           0 :         return AVERROR(ENOMEM);
    5575           0 :     track->par->codec_type = AVMEDIA_TYPE_SUBTITLE;
    5576             : #if 0
    5577             :     // These properties are required to make QT recognize the chapter track
    5578             :     uint8_t chapter_properties[43] = { 0, 0, 0, 0, 0, 0, 0, 1, };
    5579             :     if (ff_alloc_extradata(track->par, sizeof(chapter_properties)))
    5580             :         return AVERROR(ENOMEM);
    5581             :     memcpy(track->par->extradata, chapter_properties, sizeof(chapter_properties));
    5582             : #else
    5583           0 :     if (avio_open_dyn_buf(&pb) >= 0) {
    5584             :         int size;
    5585             :         uint8_t *buf;
    5586             : 
    5587             :         /* Stub header (usually for Quicktime chapter track) */
    5588             :         // TextSampleEntry
    5589           0 :         avio_wb32(pb, 0x01); // displayFlags
    5590           0 :         avio_w8(pb, 0x00);   // horizontal justification
    5591           0 :         avio_w8(pb, 0x00);   // vertical justification
    5592           0 :         avio_w8(pb, 0x00);   // bgColourRed
    5593           0 :         avio_w8(pb, 0x00);   // bgColourGreen
    5594           0 :         avio_w8(pb, 0x00);   // bgColourBlue
    5595           0 :         avio_w8(pb, 0x00);   // bgColourAlpha
    5596             :         // BoxRecord
    5597           0 :         avio_wb16(pb, 0x00); // defTextBoxTop
    5598           0 :         avio_wb16(pb, 0x00); // defTextBoxLeft
    5599           0 :         avio_wb16(pb, 0x00); // defTextBoxBottom
    5600           0 :         avio_wb16(pb, 0x00); // defTextBoxRight
    5601             :         // StyleRecord
    5602           0 :         avio_wb16(pb, 0x00); // startChar
    5603           0 :         avio_wb16(pb, 0x00); // endChar
    5604           0 :         avio_wb16(pb, 0x01); // fontID
    5605           0 :         avio_w8(pb, 0x00);   // fontStyleFlags
    5606           0 :         avio_w8(pb, 0x00);   // fontSize
    5607           0 :         avio_w8(pb, 0x00);   // fgColourRed
    5608           0 :         avio_w8(pb, 0x00);   // fgColourGreen
    5609           0 :         avio_w8(pb, 0x00);   // fgColourBlue
    5610           0 :         avio_w8(pb, 0x00);   // fgColourAlpha
    5611             :         // FontTableBox
    5612           0 :         avio_wb32(pb, 0x0D); // box size
    5613           0 :         ffio_wfourcc(pb, "ftab"); // box atom name
    5614           0 :         avio_wb16(pb, 0x01); // entry count
    5615             :         // FontRecord
    5616           0 :         avio_wb16(pb, 0x01); // font ID
    5617           0 :         avio_w8(pb, 0x00);   // font name length
    5618             : 
    5619           0 :         if ((size = avio_close_dyn_buf(pb, &buf)) > 0) {
    5620           0 :             track->par->extradata = buf;
    5621           0 :             track->par->extradata_size = size;
    5622             :         } else {
    5623           0 :             av_freep(&buf);
    5624             :         }
    5625             :     }
    5626             : #endif
    5627             : 
    5628           0 :     for (i = 0; i < s->nb_chapters; i++) {
    5629           0 :         AVChapter *c = s->chapters[i];
    5630             :         AVDictionaryEntry *t;
    5631             : 
    5632           0 :         int64_t end = av_rescale_q(c->end, c->time_base, (AVRational){1,MOV_TIMESCALE});
    5633           0 :         pkt.pts = pkt.dts = av_rescale_q(c->start, c->time_base, (AVRational){1,MOV_TIMESCALE});
    5634           0 :         pkt.duration = end - pkt.dts;
    5635             : 
    5636           0 :         if ((t = av_dict_get(c->metadata, "title", NULL, 0))) {
    5637             :             static const char encd[12] = {
    5638             :                 0x00, 0x00, 0x00, 0x0C,
    5639             :                 'e',  'n',  'c',  'd',
    5640             :                 0x00, 0x00, 0x01, 0x00 };
    5641           0 :             len      = strlen(t->value);
    5642           0 :             pkt.size = len + 2 + 12;
    5643           0 :             pkt.data = av_malloc(pkt.size);
    5644           0 :             if (!pkt.data)
    5645           0 :                 return AVERROR(ENOMEM);
    5646           0 :             AV_WB16(pkt.data, len);
    5647           0 :             memcpy(pkt.data + 2, t->value, len);
    5648           0 :             memcpy(pkt.data + len + 2, encd, sizeof(encd));
    5649           0 :             ff_mov_write_packet(s, &pkt);
    5650           0 :             av_freep(&pkt.data);
    5651             :         }
    5652             :     }
    5653             : 
    5654           0 :     return 0;
    5655             : }
    5656             : 
    5657             : 
    5658           9 : static int mov_check_timecode_track(AVFormatContext *s, AVTimecode *tc, int src_index, const char *tcstr)
    5659             : {
    5660             :     int ret;
    5661             : 
    5662             :     /* compute the frame number */
    5663           9 :     ret = av_timecode_init_from_string(tc, find_fps(s,  s->streams[src_index]), tcstr, s);
    5664           9 :     return ret;
    5665             : }
    5666             : 
    5667           4 : static int mov_create_timecode_track(AVFormatContext *s, int index, int src_index, AVTimecode tc)
    5668             : {
    5669             :     int ret;
    5670           4 :     MOVMuxContext *mov  = s->priv_data;
    5671           4 :     MOVTrack *track     = &mov->tracks[index];
    5672           4 :     AVStream *src_st    = s->streams[src_index];
    5673           4 :     AVPacket pkt    = {.stream_index = index, .flags = AV_PKT_FLAG_KEY, .size = 4};
    5674           4 :     AVRational rate = find_fps(s, src_st);
    5675             : 
    5676             :     /* tmcd track based on video stream */
    5677           4 :     track->mode      = mov->mode;
    5678           4 :     track->tag       = MKTAG('t','m','c','d');
    5679           4 :     track->src_track = src_index;
    5680           4 :     track->timescale = mov->tracks[src_index].timescale;
    5681           4 :     if (tc.flags & AV_TIMECODE_FLAG_DROPFRAME)
    5682           2 :         track->timecode_flags |= MOV_TIMECODE_FLAG_DROPFRAME;
    5683             : 
    5684             :     /* set st to src_st for metadata access*/
    5685           4 :     track->st = src_st;
    5686             : 
    5687             :     /* encode context: tmcd data stream */
    5688           4 :     track->par = avcodec_parameters_alloc();
    5689           4 :     if (!track->par)
    5690           0 :         return AVERROR(ENOMEM);
    5691           4 :     track->par->codec_type = AVMEDIA_TYPE_DATA;
    5692           4 :     track->par->codec_tag  = track->tag;
    5693           4 :     track->st->avg_frame_rate = av_inv_q(rate);
    5694             : 
    5695             :     /* the tmcd track just contains one packet with the frame number */
    5696           4 :     pkt.data = av_malloc(pkt.size);
    5697           4 :     if (!pkt.data)
    5698           0 :         return AVERROR(ENOMEM);
    5699           4 :     AV_WB32(pkt.data, tc.start);
    5700           4 :     ret = ff_mov_write_packet(s, &pkt);
    5701           4 :     av_free(pkt.data);
    5702           4 :     return ret;
    5703             : }
    5704             : 
    5705             : /*
    5706             :  * st->disposition controls the "enabled" flag in the tkhd tag.
    5707             :  * QuickTime will not play a track if it is not enabled.  So make sure
    5708             :  * that one track of each type (audio, video, subtitle) is enabled.
    5709             :  *
    5710             :  * Subtitles are special.  For audio and video, setting "enabled" also
    5711             :  * makes the track "default" (i.e. it is rendered when played). For
    5712             :  * subtitles, an "enabled" subtitle is not rendered by default, but
    5713             :  * if no subtitle is enabled, the subtitle menu in QuickTime will be
    5714             :  * empty!
    5715             :  */
    5716         149 : static void enable_tracks(AVFormatContext *s)
    5717             : {
    5718         149 :     MOVMuxContext *mov = s->priv_data;
    5719             :     int i;
    5720             :     int enabled[AVMEDIA_TYPE_NB];
    5721             :     int first[AVMEDIA_TYPE_NB];
    5722             : 
    5723         894 :     for (i = 0; i < AVMEDIA_TYPE_NB; i++) {
    5724         745 :         enabled[i] = 0;
    5725         745 :         first[i] = -1;
    5726             :     }
    5727             : 
    5728         337 :     for (i = 0; i < s->nb_streams; i++) {
    5729         188 :         AVStream *st = s->streams[i];
    5730             : 
    5731         376 :         if (st->codecpar->codec_type <= AVMEDIA_TYPE_UNKNOWN ||
    5732         188 :             st->codecpar->codec_type >= AVMEDIA_TYPE_NB)
    5733           0 :             continue;
    5734             : 
    5735         188 :         if (first[st->codecpar->codec_type] < 0)
    5736         186 :             first[st->codecpar->codec_type] = i;
    5737         188 :         if (st->disposition & AV_DISPOSITION_DEFAULT) {
    5738          15 :             mov->tracks[i].flags |= MOV_TRACK_ENABLED;
    5739          15 :             enabled[st->codecpar->codec_type]++;
    5740             :         }
    5741             :     }
    5742             : 
    5743         894 :     for (i = 0; i < AVMEDIA_TYPE_NB; i++) {
    5744         745 :         switch (i) {
    5745         447 :         case AVMEDIA_TYPE_VIDEO:
    5746             :         case AVMEDIA_TYPE_AUDIO:
    5747             :         case AVMEDIA_TYPE_SUBTITLE:
    5748         447 :             if (enabled[i] > 1)
    5749           0 :                 mov->per_stream_grouping = 1;
    5750         447 :             if (!enabled[i] && first[i] >= 0)
    5751         173 :                 mov->tracks[first[i]].flags |= MOV_TRACK_ENABLED;
    5752         447 :             break;
    5753             :         }
    5754             :     }
    5755         149 : }
    5756             : 
    5757         149 : static void mov_free(AVFormatContext *s)
    5758             : {
    5759         149 :     MOVMuxContext *mov = s->priv_data;
    5760             :     int i;
    5761             : 
    5762         149 :     if (mov->chapter_track) {
    5763           0 :         if (mov->tracks[mov->chapter_track].par)
    5764           0 :             av_freep(&mov->tracks[mov->chapter_track].par->extradata);
    5765           0 :         av_freep(&mov->tracks[mov->chapter_track].par);
    5766             :     }
    5767             : 
    5768         343 :     for (i = 0; i < mov->nb_streams; i++) {
    5769         194 :         if (mov->tracks[i].tag == MKTAG('r','t','p',' '))
    5770           2 :             ff_mov_close_hinting(&mov->tracks[i]);
    5771         192 :         else if (mov->tracks[i].tag == MKTAG('t','m','c','d') && mov->nb_meta_tmcd)
    5772           4 :             av_freep(&mov->tracks[i].par);
    5773         194 :         av_freep(&mov->tracks[i].cluster);
    5774         194 :         av_freep(&mov->tracks[i].frag_info);
    5775             : 
    5776         194 :         if (mov->tracks[i].vos_len)
    5777         116 :             av_freep(&mov->tracks[i].vos_data);
    5778             : 
    5779         194 :         ff_mov_cenc_free(&mov->tracks[i].cenc);
    5780             :     }
    5781             : 
    5782         149 :     av_freep(&mov->tracks);
    5783         149 : }
    5784             : 
    5785           0 : static uint32_t rgb_to_yuv(uint32_t rgb)
    5786             : {
    5787             :     uint8_t r, g, b;
    5788             :     int y, cb, cr;
    5789             : 
    5790           0 :     r = (rgb >> 16) & 0xFF;
    5791           0 :     g = (rgb >>  8) & 0xFF;
    5792           0 :     b = (rgb      ) & 0xFF;
    5793             : 
    5794           0 :     y  = av_clip_uint8(( 16000 +  257 * r + 504 * g +  98 * b)/1000);
    5795           0 :     cb = av_clip_uint8((128000 -  148 * r - 291 * g + 439 * b)/1000);
    5796           0 :     cr = av_clip_uint8((128000 +  439 * r - 368 * g -  71 * b)/1000);
    5797             : 
    5798           0 :     return (y << 16) | (cr << 8) | cb;
    5799             : }
    5800             : 
    5801           0 : static int mov_create_dvd_sub_decoder_specific_info(MOVTrack *track,
    5802             :                                                     AVStream *st)
    5803             : {
    5804           0 :     int i, width = 720, height = 480;
    5805           0 :     int have_palette = 0, have_size = 0;
    5806             :     uint32_t palette[16];
    5807           0 :     char *cur = st->codecpar->extradata;
    5808             : 
    5809           0 :     while (cur && *cur) {
    5810           0 :         if (strncmp("palette:", cur, 8) == 0) {
    5811             :             int i, count;
    5812           0 :             count = sscanf(cur + 8,
    5813             :                 "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32", "
    5814             :                 "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32", "
    5815             :                 "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32", "
    5816             :                 "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32"",
    5817             :                 &palette[ 0], &palette[ 1], &palette[ 2], &palette[ 3],
    5818             :                 &palette[ 4], &palette[ 5], &palette[ 6], &palette[ 7],
    5819             :                 &palette[ 8], &palette[ 9], &palette[10], &palette[11],
    5820             :                 &palette[12], &palette[13], &palette[14], &palette[15]);
    5821             : 
    5822           0 :             for (i = 0; i < count; i++) {
    5823           0 :                 palette[i] = rgb_to_yuv(palette[i]);
    5824             :             }
    5825           0 :             have_palette = 1;
    5826           0 :         } else if (!strncmp("size:", cur, 5)) {
    5827           0 :             sscanf(cur + 5, "%dx%d", &width, &height);
    5828           0 :             have_size = 1;
    5829             :         }
    5830           0 :         if (have_palette && have_size)
    5831           0 :             break;
    5832           0 :         cur += strcspn(cur, "\n\r");
    5833           0 :         cur += strspn(cur, "\n\r");
    5834             :     }
    5835           0 :     if (have_palette) {
    5836           0 :         track->vos_data = av_malloc(16*4);
    5837           0 :         if (!track->vos_data)
    5838           0 :             return AVERROR(ENOMEM);
    5839           0 :         for (i = 0; i < 16; i++) {
    5840           0 :             AV_WB32(track->vos_data + i * 4, palette[i]);
    5841             :         }
    5842           0 :         track->vos_len = 16 * 4;
    5843             :     }
    5844           0 :     st->codecpar->width = width;
    5845           0 :     st->codecpar->height = track->height = height;
    5846             : 
    5847           0 :     return 0;
    5848             : }
    5849             : 
    5850         149 : static int mov_init(AVFormatContext *s)
    5851             : {
    5852         149 :     MOVMuxContext *mov = s->priv_data;
    5853         149 :     AVDictionaryEntry *global_tcr = av_dict_get(s->metadata, "timecode", NULL, 0);
    5854             :     int i, ret;
    5855             : 
    5856         149 :     mov->fc = s;
    5857             : 
    5858             :     /* Default mode == MP4 */
    5859         149 :     mov->mode = MODE_MP4;
    5860             : 
    5861         149 :     if (s->oformat) {
    5862         149 :         if (!strcmp("3gp", s->oformat->name)) mov->mode = MODE_3GP;
    5863         149 :         else if (!strcmp("3g2", s->oformat->name)) mov->mode = MODE_3GP|MODE_3G2;
    5864         149 :         else if (!strcmp("mov", s->oformat->name)) mov->mode = MODE_MOV;
    5865          42 :         else if (!strcmp("psp", s->oformat->name)) mov->mode = MODE_PSP;
    5866          41 :         else if (!strcmp("ipod",s->oformat->name)) mov->mode = MODE_IPOD;
    5867          40 :         else if (!strcmp("ismv",s->oformat->name)) mov->mode = MODE_ISM;
    5868          36 :         else if (!strcmp("f4v", s->oformat->name)) mov->mode = MODE_F4V;
    5869             :     }
    5870             : 
    5871         149 :     if (mov->flags & FF_MOV_FLAG_DELAY_MOOV)
    5872          16 :         mov->flags |= FF_MOV_FLAG_EMPTY_MOOV;
    5873             : 
    5874             :     /* Set the FRAGMENT flag if any of the fragmentation methods are
    5875             :      * enabled. */
    5876         297 :     if (mov->max_fragment_duration || mov->max_fragment_size ||
    5877         148 :         mov->flags & (FF_MOV_FLAG_EMPTY_MOOV |
    5878             :                       FF_MOV_FLAG_FRAG_KEYFRAME |
    5879             :                       FF_MOV_FLAG_FRAG_CUSTOM |
    5880             :                       FF_MOV_FLAG_FRAG_EVERY_FRAME))
    5881          28 :         mov->flags |= FF_MOV_FLAG_FRAGMENT;
    5882             : 
    5883             :     /* Set other implicit flags immediately */
    5884         149 :     if (mov->mode == MODE_ISM)
    5885           4 :         mov->flags |= FF_MOV_FLAG_EMPTY_MOOV | FF_MOV_FLAG_SEPARATE_MOOF |
    5886             :                       FF_MOV_FLAG_FRAGMENT;
    5887         149 :     if (mov->flags & FF_MOV_FLAG_DASH)
    5888          10 :         mov->flags |= FF_MOV_FLAG_FRAGMENT | FF_MOV_FLAG_EMPTY_MOOV |
    5889             :                       FF_MOV_FLAG_DEFAULT_BASE_MOOF;
    5890             : 
    5891         149 :     if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV && s->flags & AVFMT_FLAG_AUTO_BSF) {
    5892          28 :         av_log(s, AV_LOG_VERBOSE, "Empty MOOV enabled; disabling automatic bitstream filtering\n");
    5893          28 :         s->flags &= ~AVFMT_FLAG_AUTO_BSF;
    5894             :     }
    5895             : 
    5896         149 :     if (mov->flags & FF_MOV_FLAG_FASTSTART) {
    5897           3 :         mov->reserved_moov_size = -1;
    5898             :     }
    5899             : 
    5900         149 :     if (mov->use_editlist < 0) {
    5901         142 :         mov->use_editlist = 1;
    5902         166 :         if (mov->flags & FF_MOV_FLAG_FRAGMENT &&
    5903          24 :             !(mov->flags & FF_MOV_FLAG_DELAY_MOOV)) {
    5904             :             // If we can avoid needing an edit list by shifting the
    5905             :             // tracks, prefer that over (trying to) write edit lists
    5906             :             // in fragmented output.
    5907          11 :             if (s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO ||
    5908           1 :                 s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO)
    5909           9 :                 mov->use_editlist = 0;
    5910             :         }
    5911             :     }
    5912         177 :     if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV &&
    5913          40 :         !(mov->flags & FF_MOV_FLAG_DELAY_MOOV) && mov->use_editlist)
    5914           1 :         av_log(s, AV_LOG_WARNING, "No meaningful edit list will be written when using empty_moov without delay_moov\n");
    5915             : 
    5916         149 :     if (!mov->use_editlist && s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO)
    5917          14 :         s->avoid_negative_ts = AVFMT_AVOID_NEG_TS_MAKE_ZERO;
    5918             : 
    5919             :     /* Clear the omit_tfhd_offset flag if default_base_moof is set;
    5920             :      * if the latter is set that's enough and omit_tfhd_offset doesn't
    5921             :      * add anything extra on top of that. */
    5922         149 :     if (mov->flags & FF_MOV_FLAG_OMIT_TFHD_OFFSET &&
    5923           0 :         mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF)
    5924           0 :         mov->flags &= ~FF_MOV_FLAG_OMIT_TFHD_OFFSET;
    5925             : 
    5926         149 :     if (mov->frag_interleave &&
    5927           0 :         mov->flags & (FF_MOV_FLAG_OMIT_TFHD_OFFSET | FF_MOV_FLAG_SEPARATE_MOOF)) {
    5928           0 :         av_log(s, AV_LOG_ERROR,
    5929             :                "Sample interleaving in fragments is mutually exclusive with "
    5930             :                "omit_tfhd_offset and separate_moof\n");
    5931           0 :         return AVERROR(EINVAL);
    5932             :     }
    5933             : 
    5934             :     /* Non-seekable output is ok if using fragmentation. If ism_lookahead
    5935             :      * is enabled, we don't support non-seekable output at all. */
    5936         176 :     if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL) &&
    5937          54 :         (!(mov->flags & FF_MOV_FLAG_FRAGMENT) || mov->ism_lookahead)) {
    5938           0 :         av_log(s, AV_LOG_ERROR, "muxer does not support non seekable output\n");
    5939           0 :         return AVERROR(EINVAL);
    5940             :     }
    5941             : 
    5942         149 :     mov->nb_streams = s->nb_streams;
    5943         149 :     if (mov->mode & (MODE_MP4|MODE_MOV|MODE_IPOD) && s->nb_chapters)
    5944           0 :         mov->chapter_track = mov->nb_streams++;
    5945             : 
    5946         149 :     if (mov->flags & FF_MOV_FLAG_RTP_HINT) {
    5947             :         /* Add hint tracks for each audio and video stream */
    5948           3 :         for (i = 0; i < s->nb_streams; i++) {
    5949           2 :             AVStream *st = s->streams[i];
    5950           3 :             if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ||
    5951           1 :                 st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
    5952           2 :                 mov->nb_streams++;
    5953             :             }
    5954             :         }
    5955             :     }
    5956             : 
    5957         149 :     if (   mov->write_tmcd == -1 && (mov->mode == MODE_MOV || mov->mode == MODE_MP4)
    5958           6 :         || mov->write_tmcd == 1) {
    5959             :         /* +1 tmcd track for each video stream with a timecode */
    5960         323 :         for (i = 0; i < s->nb_streams; i++) {
    5961         180 :             AVStream *st = s->streams[i];
    5962         180 :             AVDictionaryEntry *t = global_tcr;
    5963         180 :             if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
    5964         121 :                 (t || (t=av_dict_get(st->metadata, "timecode", NULL, 0)))) {
    5965             :                 AVTimecode tc;
    5966           5 :                 ret = mov_check_timecode_track(s, &tc, i, t->value);
    5967           5 :                 if (ret >= 0)
    5968           5 :                     mov->nb_meta_tmcd++;
    5969             :             }
    5970             :         }
    5971             : 
    5972             :         /* check if there is already a tmcd track to remux */
    5973         143 :         if (mov->nb_meta_tmcd) {
    5974          16 :             for (i = 0; i < s->nb_streams; i++) {
    5975          11 :                 AVStream *st = s->streams[i];
    5976          11 :                 if (st->codecpar->codec_tag == MKTAG('t','m','c','d')) {
    5977           3 :                     av_log(s, AV_LOG_WARNING, "You requested a copy of the original timecode track "
    5978             :                            "so timecode metadata are now ignored\n");
    5979           3 :                     mov->nb_meta_tmcd = 0;
    5980             :                 }
    5981             :             }
    5982             :         }
    5983             : 
    5984         143 :         mov->nb_streams += mov->nb_meta_tmcd;
    5985             :     }
    5986             : 
    5987             :     // Reserve an extra stream for chapters for the case where chapters
    5988             :     // are written in the trailer
    5989         149 :     mov->tracks = av_mallocz_array((mov->nb_streams + 1), sizeof(*mov->tracks));
    5990         149 :     if (!mov->tracks)
    5991           0 :         return AVERROR(ENOMEM);
    5992             : 
    5993         149 :     if (mov->encryption_scheme_str != NULL && strcmp(mov->encryption_scheme_str, "none") != 0) {
    5994           0 :         if (strcmp(mov->encryption_scheme_str, "cenc-aes-ctr") == 0) {
    5995           0 :             mov->encryption_scheme = MOV_ENC_CENC_AES_CTR;
    5996             : 
    5997           0 :             if (mov->encryption_key_len != AES_CTR_KEY_SIZE) {
    5998           0 :                 av_log(s, AV_LOG_ERROR, "Invalid encryption key len %d expected %d\n",
    5999             :                     mov->encryption_key_len, AES_CTR_KEY_SIZE);
    6000           0 :                 return AVERROR(EINVAL);
    6001             :             }
    6002             : 
    6003           0 :             if (mov->encryption_kid_len != CENC_KID_SIZE) {
    6004           0 :                 av_log(s, AV_LOG_ERROR, "Invalid encryption kid len %d expected %d\n",
    6005             :                     mov->encryption_kid_len, CENC_KID_SIZE);
    6006           0 :                 return AVERROR(EINVAL);
    6007             :             }
    6008             :         } else {
    6009           0 :             av_log(s, AV_LOG_ERROR, "unsupported encryption scheme %s\n",
    6010             :                 mov->encryption_scheme_str);
    6011           0 :             return AVERROR(EINVAL);
    6012             :         }
    6013             :     }
    6014             : 
    6015         337 :     for (i = 0; i < s->nb_streams; i++) {
    6016         188 :         AVStream *st= s->streams[i];
    6017         188 :         MOVTrack *track= &mov->tracks[i];
    6018         188 :         AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL,0);
    6019             : 
    6020         188 :         track->st  = st;
    6021         188 :         track->par = st->codecpar;
    6022         188 :         track->language = ff_mov_iso639_to_lang(lang?lang->value:"und", mov->mode!=MODE_MOV);
    6023         188 :         if (track->language < 0)
    6024         110 :             track->language = 0;
    6025         188 :         track->mode = mov->mode;
    6026         188 :         track->tag  = mov_find_codec_tag(s, track);
    6027         188 :         if (!track->tag) {
    6028           0 :             av_log(s, AV_LOG_ERROR, "Could not find tag for codec %s in stream #%d, "
    6029             :                    "codec not currently supported in container\n",
    6030           0 :                    avcodec_get_name(st->codecpar->codec_id), i);
    6031           0 :             return AVERROR(EINVAL);
    6032             :         }
    6033             :         /* If hinting of this track is enabled by a later hint track,
    6034             :          * this is updated. */
    6035         188 :         track->hint_track = -1;
    6036         188 :         track->start_dts  = AV_NOPTS_VALUE;
    6037         188 :         track->start_cts  = AV_NOPTS_VALUE;
    6038         188 :         track->end_pts    = AV_NOPTS_VALUE;
    6039         188 :         track->dts_shift  = AV_NOPTS_VALUE;
    6040         188 :         if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
    6041         262 :             if (track->tag == MKTAG('m','x','3','p') || track->tag == MKTAG('m','x','3','n') ||
    6042         393 :                 track->tag == MKTAG('m','x','4','p') || track->tag == MKTAG('m','x','4','n') ||
    6043         262 :                 track->tag == MKTAG('m','x','5','p') || track->tag == MKTAG('m','x','5','n')) {
    6044           0 :                 if (st->codecpar->width != 720 || (st->codecpar->height != 608 && st->codecpar->height != 512)) {
    6045           0 :                     av_log(s, AV_LOG_ERROR, "D-10/IMX must use 720x608 or 720x512 video resolution\n");
    6046           0 :                     return AVERROR(EINVAL);
    6047             :                 }
    6048           0 :                 track->height = track->tag >> 24 == 'n' ? 486 : 576;
    6049             :             }
    6050         131 :             if (mov->video_track_timescale) {
    6051           0 :                 track->timescale = mov->video_track_timescale;
    6052             :             } else {
    6053         131 :                 track->timescale = st->time_base.den;
    6054        1371 :                 while(track->timescale < 10000)
    6055        1109 :                     track->timescale *= 2;
    6056             :             }
    6057         131 :             if (st->codecpar->width > 65535 || st->codecpar->height > 65535) {
    6058           0 :                 av_log(s, AV_LOG_ERROR, "Resolution %dx%d too large for mov/mp4\n", st->codecpar->width, st->codecpar->height);
    6059           0 :                 return AVERROR(EINVAL);
    6060             :             }
    6061         131 :             if (track->mode == MODE_MOV && track->timescale > 100000)
    6062           1 :                 av_log(s, AV_LOG_WARNING,
    6063             :                        "WARNING codec timebase is very high. If duration is too long,\n"
    6064             :                        "file may not be playable by quicktime. Specify a shorter timebase\n"
    6065             :                        "or choose different container.\n");
    6066         223 :             if (track->mode == MODE_MOV &&
    6067         104 :                 track->par->codec_id == AV_CODEC_ID_RAWVIDEO &&
    6068          12 :                 track->tag == MKTAG('r','a','w',' ')) {
    6069           0 :                 enum AVPixelFormat pix_fmt = track->par->format;
    6070           0 :                 if (pix_fmt == AV_PIX_FMT_NONE && track->par->bits_per_coded_sample == 1)
    6071           0 :                     pix_fmt = AV_PIX_FMT_MONOWHITE;
    6072           0 :                 track->is_unaligned_qt_rgb =
    6073           0 :                         pix_fmt == AV_PIX_FMT_RGB24 ||
    6074           0 :                         pix_fmt == AV_PIX_FMT_BGR24 ||
    6075           0 :                         pix_fmt == AV_PIX_FMT_PAL8 ||
    6076           0 :                         pix_fmt == AV_PIX_FMT_GRAY8 ||
    6077           0 :                         pix_fmt == AV_PIX_FMT_MONOWHITE ||
    6078             :                         pix_fmt == AV_PIX_FMT_MONOBLACK;
    6079             :             }
    6080         131 :             if (track->par->codec_id == AV_CODEC_ID_VP9) {
    6081           0 :                 if (track->mode != MODE_MP4) {
    6082           0 :                     av_log(s, AV_LOG_ERROR, "VP9 only supported in MP4.\n");
    6083           0 :                     return AVERROR(EINVAL);
    6084             :                 }
    6085         131 :             } else if (track->par->codec_id == AV_CODEC_ID_VP8) {
    6086             :                 /* altref frames handling is not defined in the spec as of version v1.0,
    6087             :                  * so just forbid muxing VP8 streams altogether until a new version does */
    6088           0 :                 av_log(s, AV_LOG_ERROR, "VP8 muxing is currently not supported.\n");
    6089           0 :                 return AVERROR_PATCHWELCOME;
    6090             :             }
    6091          57 :         } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
    6092          52 :             track->timescale = st->codecpar->sample_rate;
    6093          52 :             if (!st->codecpar->frame_size && !av_get_bits_per_sample(st->codecpar->codec_id)) {
    6094          29 :                 av_log(s, AV_LOG_WARNING, "track %d: codec frame size is not set\n", i);
    6095          29 :                 track->audio_vbr = 1;
    6096          46 :             }else if (st->codecpar->codec_id == AV_CODEC_ID_ADPCM_MS ||
    6097          46 :                      st->codecpar->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV ||
    6098          23 :                      st->codecpar->codec_id == AV_CODEC_ID_ILBC){
    6099           0 :                 if (!st->codecpar->block_align) {
    6100           0 :                     av_log(s, AV_LOG_ERROR, "track %d: codec block align is not set for adpcm\n", i);
    6101           0 :                     return AVERROR(EINVAL);
    6102             :                 }
    6103           0 :                 track->sample_size = st->codecpar->block_align;
    6104          23 :             }else if (st->codecpar->frame_size > 1){ /* assume compressed audio */
    6105          14 :                 track->audio_vbr = 1;
    6106             :             }else{
    6107           9 :                 track->sample_size = (av_get_bits_per_sample(st->codecpar->codec_id) >> 3) * st->codecpar->channels;
    6108             :             }
    6109         104 :             if (st->codecpar->codec_id == AV_CODEC_ID_ILBC ||
    6110          52 :                 st->codecpar->codec_id == AV_CODEC_ID_ADPCM_IMA_QT) {
    6111           0 :                 track->audio_vbr = 1;
    6112             :             }
    6113          82 :             if (track->mode != MODE_MOV &&
    6114          30 :                 track->par->codec_id == AV_CODEC_ID_MP3 && track->timescale < 16000) {
    6115           0 :                 if (s->strict_std_compliance >= FF_COMPLIANCE_NORMAL) {
    6116           0 :                     av_log(s, AV_LOG_ERROR, "track %d: muxing mp3 at %dhz is not standard, to mux anyway set strict to -1\n",
    6117           0 :                         i, track->par->sample_rate);
    6118           0 :                     return AVERROR(EINVAL);
    6119             :                 } else {
    6120           0 :                     av_log(s, AV_LOG_WARNING, "track %d: muxing mp3 at %dhz is not standard in MP4\n",
    6121           0 :                            i, track->par->sample_rate);
    6122             :                 }
    6123             :             }
    6124         104 :             if (track->par->codec_id == AV_CODEC_ID_FLAC ||
    6125          52 :                 track->par->codec_id == AV_CODEC_ID_OPUS) {
    6126           0 :                 if (track->mode != MODE_MP4) {
    6127           0 :                     av_log(s, AV_LOG_ERROR, "%s only supported in MP4.\n", avcodec_get_name(track->par->codec_id));
    6128           0 :                     return AVERROR(EINVAL);
    6129             :                 }
    6130           0 :                 if (s->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) {
    6131           0 :                     av_log(s, AV_LOG_ERROR,
    6132             :                            "%s in MP4 support is experimental, add "
    6133             :                            "'-strict %d' if you want to use it.\n",
    6134           0 :                            avcodec_get_name(track->par->codec_id), FF_COMPLIANCE_EXPERIMENTAL);
    6135           0 :                     return AVERROR_EXPERIMENTAL;
    6136             :                 }
    6137             :             }
    6138           5 :         } else if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
    6139           1 :             track->timescale = st->time_base.den;
    6140           4 :         } else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA) {
    6141           4 :             track->timescale = st->time_base.den;
    6142             :         } else {
    6143           0 :             track->timescale = MOV_TIMESCALE;
    6144             :         }
    6145         188 :         if (!track->height)
    6146         188 :             track->height = st->codecpar->height;
    6147             :         /* The ism specific timescale isn't mandatory, but is assumed by
    6148             :          * some tools, such as mp4split. */
    6149         188 :         if (mov->mode == MODE_ISM)
    6150           5 :             track->timescale = 10000000;
    6151             : 
    6152         188 :         avpriv_set_pts_info(st, 64, 1, track->timescale);
    6153             : 
    6154         188 :         if (mov->encryption_scheme == MOV_ENC_CENC_AES_CTR) {
    6155           0 :             ret = ff_mov_cenc_init(&track->cenc, mov->encryption_key,
    6156           0 :                 track->par->codec_id == AV_CODEC_ID_H264, s->flags & AVFMT_FLAG_BITEXACT);
    6157           0 :             if (ret)
    6158           0 :                 return ret;
    6159             :         }
    6160             :     }
    6161             : 
    6162         149 :     enable_tracks(s);
    6163         149 :     return 0;
    6164             : }
    6165             : 
    6166         149 : static int mov_write_header(AVFormatContext *s)
    6167             : {
    6168         149 :     AVIOContext *pb = s->pb;
    6169         149 :     MOVMuxContext *mov = s->priv_data;
    6170         149 :     AVDictionaryEntry *t, *global_tcr = av_dict_get(s->metadata, "timecode", NULL, 0);
    6171         149 :     int i, ret, hint_track = 0, tmcd_track = 0, nb_tracks = s->nb_streams;
    6172             : 
    6173         149 :     if (mov->mode & (MODE_MP4|MODE_MOV|MODE_IPOD) && s->nb_chapters)
    6174           0 :         nb_tracks++;
    6175             : 
    6176         149 :     if (mov->flags & FF_MOV_FLAG_RTP_HINT) {
    6177             :         /* Add hint tracks for each audio and video stream */
    6178           1 :         hint_track = nb_tracks;
    6179           3 :         for (i = 0; i < s->nb_streams; i++) {
    6180           2 :             AVStream *st = s->streams[i];
    6181           3 :             if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ||
    6182           1 :                 st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
    6183           2 :                 nb_tracks++;
    6184             :             }
    6185             :         }
    6186             :     }
    6187             : 
    6188         149 :     if (mov->mode == MODE_MOV || mov->mode == MODE_MP4)
    6189         143 :         tmcd_track = nb_tracks;
    6190             : 
    6191         337 :     for (i = 0; i < s->nb_streams; i++) {
    6192             :         int j;
    6193         188 :         AVStream *st= s->streams[i];
    6194         188 :         MOVTrack *track= &mov->tracks[i];
    6195             : 
    6196             :         /* copy extradata if it exists */
    6197         188 :         if (st->codecpar->extradata_size) {
    6198          92 :             if (st->codecpar->codec_id == AV_CODEC_ID_DVD_SUBTITLE)
    6199           0 :                 mov_create_dvd_sub_decoder_specific_info(track, st);
    6200          92 :             else if (!TAG_IS_AVCI(track->tag) && st->codecpar->codec_id != AV_CODEC_ID_DNXHD) {
    6201          92 :                 track->vos_len  = st->codecpar->extradata_size;
    6202          92 :                 track->vos_data = av_malloc(track->vos_len);
    6203          92 :                 if (!track->vos_data) {
    6204           0 :                     return AVERROR(ENOMEM);
    6205             :                 }
    6206          92 :                 memcpy(track->vos_data, st->codecpar->extradata, track->vos_len);
    6207             :             }
    6208             :         }
    6209             : 
    6210         240 :         if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO ||
    6211          52 :             track->par->channel_layout != AV_CH_LAYOUT_MONO)
    6212         181 :             continue;
    6213             : 
    6214          20 :         for (j = 0; j < s->nb_streams; j++) {
    6215          13 :             AVStream *stj= s->streams[j];
    6216          13 :             MOVTrack *trackj= &mov->tracks[j];
    6217          13 :             if (j == i)
    6218           7 :                 continue;
    6219             : 
    6220           6 :             if (stj->codecpar->codec_type != AVMEDIA_TYPE_AUDIO ||
    6221           0 :                 trackj->par->channel_layout != AV_CH_LAYOUT_MONO ||
    6222           0 :                 trackj->language != track->language ||
    6223           0 :                 trackj->tag != track->tag
    6224             :             )
    6225           6 :                 continue;
    6226           0 :             track->multichannel_as_mono++;
    6227             :         }
    6228             :     }
    6229             : 
    6230         149 :     if (!(mov->flags & FF_MOV_FLAG_DELAY_MOOV)) {
    6231         133 :         if ((ret = mov_write_identification(pb, s)) < 0)
    6232           0 :             return ret;
    6233             :     }
    6234             : 
    6235         149 :     if (mov->reserved_moov_size){
    6236           3 :         mov->reserved_header_pos = avio_tell(pb);
    6237           3 :         if (mov->reserved_moov_size > 0)
    6238           0 :             avio_skip(pb, mov->reserved_moov_size);
    6239             :     }
    6240             : 
    6241         149 :     if (mov->flags & FF_MOV_FLAG_FRAGMENT) {
    6242             :         /* If no fragmentation options have been set, set a default. */
    6243          31 :         if (!(mov->flags & (FF_MOV_FLAG_FRAG_KEYFRAME |
    6244             :                             FF_MOV_FLAG_FRAG_CUSTOM |
    6245           3 :                             FF_MOV_FLAG_FRAG_EVERY_FRAME)) &&
    6246           6 :             !mov->max_fragment_duration && !mov->max_fragment_size)
    6247           3 :             mov->flags |= FF_MOV_FLAG_FRAG_KEYFRAME;
    6248             :     } else {
    6249         118 :         if (mov->flags & FF_MOV_FLAG_FASTSTART)
    6250           3 :             mov->reserved_header_pos = avio_tell(pb);
    6251         118 :         mov_write_mdat_tag(pb, mov);
    6252             :     }
    6253             : 
    6254         149 :     ff_parse_creation_time_metadata(s, &mov->time, 1);
    6255         149 :     if (mov->time)
    6256           0 :         mov->time += 0x7C25B080; // 1970 based -> 1904 based
    6257             : 
    6258         149 :     if (mov->chapter_track)
    6259           0 :         if ((ret = mov_create_chapter_track(s, mov->chapter_track)) < 0)
    6260           0 :             return ret;
    6261             : 
    6262         149 :     if (mov->flags & FF_MOV_FLAG_RTP_HINT) {
    6263             :         /* Initialize the hint tracks for each audio and video stream */
    6264           3 :         for (i = 0; i < s->nb_streams; i++) {
    6265           2 :             AVStream *st = s->streams[i];
    6266           3 :             if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ||
    6267           1 :                 st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
    6268           2 :                 if ((ret = ff_mov_init_hinting(s, hint_track, i)) < 0)
    6269           0 :                     return ret;
    6270           2 :                 hint_track++;
    6271             :             }
    6272             :         }
    6273             :     }
    6274             : 
    6275         149 :     if (mov->nb_meta_tmcd) {
    6276             :         /* Initialize the tmcd tracks */
    6277          10 :         for (i = 0; i < s->nb_streams; i++) {
    6278           6 :             AVStream *st = s->streams[i];
    6279           6 :             t = global_tcr;
    6280             : 
    6281           6 :             if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
    6282             :                 AVTimecode tc;
    6283           4 :                 if (!t)
    6284           0 :                     t = av_dict_get(st->metadata, "timecode", NULL, 0);
    6285           4 :                 if (!t)
    6286           0 :                     continue;
    6287           4 :                 if (mov_check_timecode_track(s, &tc, i, t->value) < 0)
    6288           0 :                     continue;
    6289           4 :                 if ((ret = mov_create_timecode_track(s, tmcd_track, i, tc)) < 0)
    6290           0 :                     return ret;
    6291           4 :                 tmcd_track++;
    6292             :             }
    6293             :         }
    6294             :     }
    6295             : 
    6296         149 :     avio_flush(pb);
    6297             : 
    6298         149 :     if (mov->flags & FF_MOV_FLAG_ISML)
    6299           0 :         mov_write_isml_manifest(pb, mov, s);
    6300             : 
    6301         177 :     if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV &&
    6302          28 :         !(mov->flags & FF_MOV_FLAG_DELAY_MOOV)) {
    6303          12 :         if ((ret = mov_write_moov_tag(pb, mov, s)) < 0)
    6304           0 :             return ret;
    6305          12 :         avio_flush(pb);
    6306          12 :         mov->moov_written = 1;
    6307          12 :         if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX)
    6308           0 :             mov->reserved_header_pos = avio_tell(pb);
    6309             :     }
    6310             : 
    6311         149 :     return 0;
    6312             : }
    6313             : 
    6314          25 : static int get_moov_size(AVFormatContext *s)
    6315             : {
    6316             :     int ret;
    6317             :     AVIOContext *moov_buf;
    6318          25 :     MOVMuxContext *mov = s->priv_data;
    6319             : 
    6320          25 :     if ((ret = ffio_open_null_buf(&moov_buf)) < 0)
    6321           0 :         return ret;
    6322          25 :     if ((ret = mov_write_moov_tag(moov_buf, mov, s)) < 0)
    6323           0 :         return ret;
    6324          25 :     return ffio_close_null_buf(moov_buf);
    6325             : }
    6326             : 
    6327           0 : static int get_sidx_size(AVFormatContext *s)
    6328             : {
    6329             :     int ret;
    6330             :     AVIOContext *buf;
    6331           0 :     MOVMuxContext *mov = s->priv_data;
    6332             : 
    6333           0 :     if ((ret = ffio_open_null_buf(&buf)) < 0)
    6334           0 :         return ret;
    6335           0 :     mov_write_sidx_tags(buf, mov, -1, 0);
    6336           0 :     return ffio_close_null_buf(buf);
    6337             : }
    6338             : 
    6339             : /*
    6340             :  * This function gets the moov size if moved to the top of the file: the chunk
    6341             :  * offset table can switch between stco (32-bit entries) to co64 (64-bit
    6342             :  * entries) when the moov is moved to the beginning, so the size of the moov
    6343             :  * would change. It also updates the chunk offset tables.
    6344             :  */
    6345           3 : static int compute_moov_size(AVFormatContext *s)
    6346             : {
    6347             :     int i, moov_size, moov_size2;
    6348           3 :     MOVMuxContext *mov = s->priv_data;
    6349             : 
    6350           3 :     moov_size = get_moov_size(s);
    6351           3 :     if (moov_size < 0)
    6352           0 :         return moov_size;
    6353             : 
    6354          11 :     for (i = 0; i < mov->nb_streams; i++)
    6355           8 :         mov->tracks[i].data_offset += moov_size;
    6356             : 
    6357           3 :     moov_size2 = get_moov_size(s);
    6358           3 :     if (moov_size2 < 0)
    6359           0 :         return moov_size2;
    6360             : 
    6361             :     /* if the size changed, we just switched from stco to co64 and need to
    6362             :      * update the offsets */
    6363           3 :     if (moov_size2 != moov_size)
    6364           0 :         for (i = 0; i < mov->nb_streams; i++)
    6365           0 :             mov->tracks[i].data_offset += moov_size2 - moov_size;
    6366             : 
    6367           3 :     return moov_size2;
    6368             : }
    6369             : 
    6370           0 : static int compute_sidx_size(AVFormatContext *s)
    6371             : {
    6372             :     int i, sidx_size;
    6373           0 :     MOVMuxContext *mov = s->priv_data;
    6374             : 
    6375           0 :     sidx_size = get_sidx_size(s);
    6376           0 :     if (sidx_size < 0)
    6377           0 :         return sidx_size;
    6378             : 
    6379           0 :     for (i = 0; i < mov->nb_streams; i++)
    6380           0 :         mov->tracks[i].data_offset += sidx_size;
    6381             : 
    6382           0 :     return sidx_size;
    6383             : }
    6384             : 
    6385           3 : static int shift_data(AVFormatContext *s)
    6386             : {
    6387           3 :     int ret = 0, moov_size;
    6388           3 :     MOVMuxContext *mov = s->priv_data;
    6389           3 :     int64_t pos, pos_end = avio_tell(s->pb);
    6390             :     uint8_t *buf, *read_buf[2];
    6391           3 :     int read_buf_id = 0;
    6392             :     int read_size[2];
    6393             :     AVIOContext *read_pb;
    6394             : 
    6395           3 :     if (mov->flags & FF_MOV_FLAG_FRAGMENT)
    6396           0 :         moov_size = compute_sidx_size(s);
    6397             :     else
    6398           3 :         moov_size = compute_moov_size(s);
    6399           3 :     if (moov_size < 0)
    6400           0 :         return moov_size;
    6401             : 
    6402           3 :     buf = av_malloc(moov_size * 2);
    6403           3 :     if (!buf)
    6404           0 :         return AVERROR(ENOMEM);
    6405           3 :     read_buf[0] = buf;
    6406           3 :     read_buf[1] = buf + moov_size;
    6407             : 
    6408             :     /* Shift the data: the AVIO context of the output can only be used for
    6409             :      * writing, so we re-open the same output, but for reading. It also avoids
    6410             :      * a read/seek/write/seek back and forth. */
    6411           3 :     avio_flush(s->pb);
    6412           3 :     ret = s->io_open(s, &read_pb, s->url, AVIO_FLAG_READ, NULL);
    6413           3 :     if (ret < 0) {
    6414           0 :         av_log(s, AV_LOG_ERROR, "Unable to re-open %s output file for "
    6415             :                "the second pass (faststart)\n", s->url);
    6416           0 :         goto end;
    6417             :     }
    6418             : 
    6419             :     /* mark the end of the shift to up to the last data we wrote, and get ready
    6420             :      * for writing */
    6421           3 :     pos_end = avio_tell(s->pb);
    6422           3 :     avio_seek(s->pb, mov->reserved_header_pos + moov_size, SEEK_SET);
    6423             : 
    6424             :     /* start reading at where the new moov will be placed */
    6425           3 :     avio_seek(read_pb, mov->reserved_header_pos, SEEK_SET);
    6426           3 :     pos = avio_tell(read_pb);
    6427             : 
    6428             : #define READ_BLOCK do {                                                             \
    6429             :     read_size[read_buf_id] = avio_read(read_pb, read_buf[read_buf_id], moov_size);  \
    6430             :     read_buf_id ^= 1;                                                               \
    6431             : } while (0)
    6432             : 
    6433             :     /* shift data by chunk of at most moov_size */
    6434           3 :     READ_BLOCK;
    6435             :     do {
    6436             :         int n;
    6437         501 :         READ_BLOCK;
    6438         501 :         n = read_size[read_buf_id];
    6439         501 :         if (n <= 0)
    6440           0 :             break;
    6441         501 :         avio_write(s->pb, read_buf[read_buf_id], n);
    6442         501 :         pos += n;
    6443         501 :     } while (pos < pos_end);
    6444           3 :     ff_format_io_close(s, &read_pb);
    6445             : 
    6446           3 : end:
    6447           3 :     av_free(buf);
    6448           3 :     return ret;
    6449             : }
    6450             : 
    6451         149 : static int mov_write_trailer(AVFormatContext *s)
    6452             : {
    6453         149 :     MOVMuxContext *mov = s->priv_data;
    6454         149 :     AVIOContext *pb = s->pb;
    6455         149 :     int res = 0;
    6456             :     int i;
    6457             :     int64_t moov_pos;
    6458             : 
    6459         149 :     if (mov->need_rewrite_extradata) {
    6460           0 :         for (i = 0; i < s->nb_streams; i++) {
    6461           0 :             MOVTrack *track = &mov->tracks[i];
    6462           0 :             AVCodecParameters *par = track->par;
    6463             : 
    6464           0 :             track->vos_len  = par->extradata_size;
    6465           0 :             track->vos_data = av_malloc(track->vos_len);
    6466           0 :             if (!track->vos_data)
    6467           0 :                 return AVERROR(ENOMEM);
    6468           0 :             memcpy(track->vos_data, par->extradata, track->vos_len);
    6469             :         }
    6470           0 :         mov->need_rewrite_extradata = 0;
    6471             :     }
    6472             : 
    6473             :     /*
    6474             :      * Before actually writing the trailer, make sure that there are no
    6475             :      * dangling subtitles, that need a terminating sample.
    6476             :      */
    6477         343 :     for (i = 0; i < mov->nb_streams; i++) {
    6478         194 :         MOVTrack *trk = &mov->tracks[i];
    6479         195 :         if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT &&
    6480           1 :             !trk->last_sample_is_subtitle_end) {
    6481           1 :             mov_write_subtitle_end_packet(s, i, trk->track_duration);
    6482           1 :             trk->last_sample_is_subtitle_end = 1;
    6483             :         }
    6484             :     }
    6485             : 
    6486             :     // If there were no chapters when the header was written, but there
    6487             :     // are chapters now, write them in the trailer.  This only works
    6488             :     // when we are not doing fragments.
    6489         149 :     if (!mov->chapter_track && !(mov->flags & FF_MOV_FLAG_FRAGMENT)) {
    6490         118 :         if (mov->mode & (MODE_MP4|MODE_MOV|MODE_IPOD) && s->nb_chapters) {
    6491           0 :             mov->chapter_track = mov->nb_streams++;
    6492           0 :             if ((res = mov_create_chapter_track(s, mov->chapter_track)) < 0)
    6493           0 :                 return res;
    6494             :         }
    6495             :     }
    6496             : 
    6497         149 :     if (!(mov->flags & FF_MOV_FLAG_FRAGMENT)) {
    6498         118 :         moov_pos = avio_tell(pb);
    6499             : 
    6500             :         /* Write size of mdat tag */
    6501         118 :         if (mov->mdat_size + 8 <= UINT32_MAX) {
    6502         118 :             avio_seek(pb, mov->mdat_pos, SEEK_SET);
    6503         118 :             avio_wb32(pb, mov->mdat_size + 8);
    6504             :         } else {
    6505             :             /* overwrite 'wide' placeholder atom */
    6506           0 :             avio_seek(pb, mov->mdat_pos - 8, SEEK_SET);
    6507             :             /* special value: real atom size will be 64 bit value after
    6508             :              * tag field */
    6509           0 :             avio_wb32(pb, 1);
    6510           0 :             ffio_wfourcc(pb, "mdat");
    6511           0 :             avio_wb64(pb, mov->mdat_size + 16);
    6512             :         }
    6513         118 :         avio_seek(pb, mov->reserved_moov_size > 0 ? mov->reserved_header_pos : moov_pos, SEEK_SET);
    6514             : 
    6515         118 :         if (mov->flags & FF_MOV_FLAG_FASTSTART) {
    6516           3 :             av_log(s, AV_LOG_INFO, "Starting second pass: moving the moov atom to the beginning of the file\n");
    6517           3 :             res = shift_data(s);
    6518           3 :             if (res < 0)
    6519           0 :                 return res;
    6520           3 :             avio_seek(pb, mov->reserved_header_pos, SEEK_SET);
    6521           3 :             if ((res = mov_write_moov_tag(pb, mov, s)) < 0)
    6522           0 :                 return res;
    6523         115 :         } else if (mov->reserved_moov_size > 0) {
    6524             :             int64_t size;
    6525           0 :             if ((res = mov_write_moov_tag(pb, mov, s)) < 0)
    6526           0 :                 return res;
    6527           0 :             size = mov->reserved_moov_size - (avio_tell(pb) - mov->reserved_header_pos);
    6528           0 :             if (size < 8){
    6529           0 :                 av_log(s, AV_LOG_ERROR, "reserved_moov_size is too small, needed %"PRId64" additional\n", 8-size);
    6530           0 :                 return AVERROR(EINVAL);
    6531             :             }
    6532           0 :             avio_wb32(pb, size);
    6533           0 :             ffio_wfourcc(pb, "free");
    6534           0 :             ffio_fill(pb, 0, size - 8);
    6535           0 :             avio_seek(pb, moov_pos, SEEK_SET);
    6536             :         } else {
    6537         115 :             if ((res = mov_write_moov_tag(pb, mov, s)) < 0)
    6538           0 :                 return res;
    6539             :         }
    6540         118 :         res = 0;
    6541             :     } else {
    6542          31 :         mov_auto_flush_fragment(s, 1);
    6543          89 :         for (i = 0; i < mov->nb_streams; i++)
    6544          58 :            mov->tracks[i].data_offset = 0;
    6545          31 :         if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX) {
    6546             :             int64_t end;
    6547           0 :             av_log(s, AV_LOG_INFO, "Starting second pass: inserting sidx atoms\n");
    6548           0 :             res = shift_data(s);
    6549           0 :             if (res < 0)
    6550           0 :                 return res;
    6551           0 :             end = avio_tell(pb);
    6552           0 :             avio_seek(pb, mov->reserved_header_pos, SEEK_SET);
    6553           0 :             mov_write_sidx_tags(pb, mov, -1, 0);
    6554           0 :             avio_seek(pb, end, SEEK_SET);
    6555           0 :             avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_TRAILER);
    6556           0 :             mov_write_mfra_tag(pb, mov);
    6557          31 :         } else if (!(mov->flags & FF_MOV_FLAG_SKIP_TRAILER)) {
    6558          31 :             avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_TRAILER);
    6559          31 :             mov_write_mfra_tag(pb, mov);
    6560             :         }
    6561             :     }
    6562             : 
    6563         149 :     return res;
    6564             : }
    6565             : 
    6566         136 : static int mov_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt)
    6567             : {
    6568         136 :     int ret = 1;
    6569         136 :     AVStream *st = s->streams[pkt->stream_index];
    6570             : 
    6571         136 :     if (st->codecpar->codec_id == AV_CODEC_ID_AAC) {
    6572           8 :         if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0)
    6573           0 :             ret = ff_stream_add_bitstream_filter(st, "aac_adtstoasc", NULL);
    6574         128 :     } else if (st->codecpar->codec_id == AV_CODEC_ID_VP9) {
    6575           0 :         ret = ff_stream_add_bitstream_filter(st, "vp9_superframe", NULL);
    6576             :     }
    6577             : 
    6578         136 :     return ret;
    6579             : }
    6580             : 
    6581             : static const AVCodecTag codec_3gp_tags[] = {
    6582             :     { AV_CODEC_ID_H263,     MKTAG('s','2','6','3') },
    6583             :     { AV_CODEC_ID_H264,     MKTAG('a','v','c','1') },
    6584             :     { AV_CODEC_ID_MPEG4,    MKTAG('m','p','4','v') },
    6585             :     { AV_CODEC_ID_AAC,      MKTAG('m','p','4','a') },
    6586             :     { AV_CODEC_ID_AMR_NB,   MKTAG('s','a','m','r') },
    6587             :     { AV_CODEC_ID_AMR_WB,   MKTAG('s','a','w','b') },
    6588             :     { AV_CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') },
    6589             :     { AV_CODEC_ID_NONE, 0 },
    6590             : };
    6591             : 
    6592             : const AVCodecTag codec_mp4_tags[] = {
    6593             :     { AV_CODEC_ID_MPEG4       , MKTAG('m', 'p', '4', 'v') },
    6594             :     { AV_CODEC_ID_H264        , MKTAG('a', 'v', 'c', '1') },
    6595             :     { AV_CODEC_ID_H264        , MKTAG('a', 'v', 'c', '3') },
    6596             :     { AV_CODEC_ID_HEVC        , MKTAG('h', 'e', 'v', '1') },
    6597             :     { AV_CODEC_ID_HEVC        , MKTAG('h', 'v', 'c', '1') },
    6598             :     { AV_CODEC_ID_MPEG2VIDEO  , MKTAG('m', 'p', '4', 'v') },
    6599             :     { AV_CODEC_ID_MPEG1VIDEO  , MKTAG('m', 'p', '4', 'v') },
    6600             :     { AV_CODEC_ID_MJPEG       , MKTAG('m', 'p', '4', 'v') },
    6601             :     { AV_CODEC_ID_PNG         , MKTAG('m', 'p', '4', 'v') },
    6602             :     { AV_CODEC_ID_JPEG2000    , MKTAG('m', 'p', '4', 'v') },
    6603             :     { AV_CODEC_ID_VC1         , MKTAG('v', 'c', '-', '1') },
    6604             :     { AV_CODEC_ID_DIRAC       , MKTAG('d', 'r', 'a', 'c') },
    6605             :     { AV_CODEC_ID_TSCC2       , MKTAG('m', 'p', '4', 'v') },
    6606             :     { AV_CODEC_ID_VP9         , MKTAG('v', 'p', '0', '9') },
    6607             :     { AV_CODEC_ID_AAC         , MKTAG('m', 'p', '4', 'a') },
    6608             :     { AV_CODEC_ID_MP4ALS      , MKTAG('m', 'p', '4', 'a') },
    6609             :     { AV_CODEC_ID_MP3         , MKTAG('m', 'p', '4', 'a') },
    6610             :     { AV_CODEC_ID_MP2         , MKTAG('m', 'p', '4', 'a') },
    6611             :     { AV_CODEC_ID_AC3         , MKTAG('a', 'c', '-', '3') },
    6612             :     { AV_CODEC_ID_EAC3        , MKTAG('e', 'c', '-', '3') },
    6613             :     { AV_CODEC_ID_DTS         , MKTAG('m', 'p', '4', 'a') },
    6614             :     { AV_CODEC_ID_FLAC        , MKTAG('f', 'L', 'a', 'C') },
    6615             :     { AV_CODEC_ID_OPUS        , MKTAG('O', 'p', 'u', 's') },
    6616             :     { AV_CODEC_ID_VORBIS      , MKTAG('m', 'p', '4', 'a') },
    6617             :     { AV_CODEC_ID_QCELP       , MKTAG('m', 'p', '4', 'a') },
    6618             :     { AV_CODEC_ID_EVRC        , MKTAG('m', 'p', '4', 'a') },
    6619             :     { AV_CODEC_ID_DVD_SUBTITLE, MKTAG('m', 'p', '4', 's') },
    6620             :     { AV_CODEC_ID_MOV_TEXT    , MKTAG('t', 'x', '3', 'g') },
    6621             :     { AV_CODEC_ID_NONE        ,    0 },
    6622             : };
    6623             : 
    6624             : const AVCodecTag codec_ism_tags[] = {
    6625             :     { AV_CODEC_ID_WMAPRO      , MKTAG('w', 'm', 'a', ' ') },
    6626             :     { AV_CODEC_ID_NONE        ,    0 },
    6627             : };
    6628             : 
    6629             : static const AVCodecTag codec_ipod_tags[] = {
    6630             :     { AV_CODEC_ID_H264,     MKTAG('a','v','c','1') },
    6631             :     { AV_CODEC_ID_MPEG4,    MKTAG('m','p','4','v') },
    6632             :     { AV_CODEC_ID_AAC,      MKTAG('m','p','4','a') },
    6633             :     { AV_CODEC_ID_ALAC,     MKTAG('a','l','a','c') },
    6634             :     { AV_CODEC_ID_AC3,      MKTAG('a','c','-','3') },
    6635             :     { AV_CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') },
    6636             :     { AV_CODEC_ID_MOV_TEXT, MKTAG('t','e','x','t') },
    6637             :     { AV_CODEC_ID_NONE, 0 },
    6638             : };
    6639             : 
    6640             : static const AVCodecTag codec_f4v_tags[] = {
    6641             :     { AV_CODEC_ID_MP3,    MKTAG('.','m','p','3') },
    6642             :     { AV_CODEC_ID_AAC,    MKTAG('m','p','4','a') },
    6643             :     { AV_CODEC_ID_H264,   MKTAG('a','v','c','1') },
    6644             :     { AV_CODEC_ID_VP6A,   MKTAG('V','P','6','A') },
    6645             :     { AV_CODEC_ID_VP6F,   MKTAG('V','P','6','F') },
    6646             :     { AV_CODEC_ID_NONE, 0 },
    6647             : };
    6648             : 
    6649             : #if CONFIG_MOV_MUXER
    6650             : MOV_CLASS(mov)
    6651             : AVOutputFormat ff_mov_muxer = {
    6652             :     .name              = "mov",
    6653             :     .long_name         = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
    6654             :     .extensions        = "mov",
    6655             :     .priv_data_size    = sizeof(MOVMuxContext),
    6656             :     .audio_codec       = AV_CODEC_ID_AAC,
    6657             :     .video_codec       = CONFIG_LIBX264_ENCODER ?
    6658             :                          AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4,
    6659             :     .init              = mov_init,
    6660             :     .write_header      = mov_write_header,
    6661             :     .write_packet      = mov_write_packet,
    6662             :     .write_trailer     = mov_write_trailer,
    6663             :     .deinit            = mov_free,
    6664             :     .flags             = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
    6665             :     .codec_tag         = (const AVCodecTag* const []){
    6666             :         ff_codec_movvideo_tags, ff_codec_movaudio_tags, 0
    6667             :     },
    6668             :     .check_bitstream   = mov_check_bitstream,
    6669             :     .priv_class        = &mov_muxer_class,
    6670             : };
    6671             : #endif
    6672             : #if CONFIG_TGP_MUXER
    6673             : MOV_CLASS(tgp)
    6674             : AVOutputFormat ff_tgp_muxer = {
    6675             :     .name              = "3gp",
    6676             :     .long_name         = NULL_IF_CONFIG_SMALL("3GP (3GPP file format)"),
    6677             :     .extensions        = "3gp",
    6678             :     .priv_data_size    = sizeof(MOVMuxContext),
    6679             :     .audio_codec       = AV_CODEC_ID_AMR_NB,
    6680             :     .video_codec       = AV_CODEC_ID_H263,
    6681             :     .init              = mov_init,
    6682             :     .write_header      = mov_write_header,
    6683             :     .write_packet      = mov_write_packet,
    6684             :     .write_trailer     = mov_write_trailer,
    6685             :     .deinit            = mov_free,
    6686             :     .flags             = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
    6687             :     .codec_tag         = (const AVCodecTag* const []){ codec_3gp_tags, 0 },
    6688             :     .check_bitstream   = mov_check_bitstream,
    6689             :     .priv_class        = &tgp_muxer_class,
    6690             : };
    6691             : #endif
    6692             : #if CONFIG_MP4_MUXER
    6693             : MOV_CLASS(mp4)
    6694             : AVOutputFormat ff_mp4_muxer = {
    6695             :     .name              = "mp4",
    6696             :     .long_name         = NULL_IF_CONFIG_SMALL("MP4 (MPEG-4 Part 14)"),
    6697             :     .mime_type         = "video/mp4",
    6698             :     .extensions        = "mp4",
    6699             :     .priv_data_size    = sizeof(MOVMuxContext),
    6700             :     .audio_codec       = AV_CODEC_ID_AAC,
    6701             :     .video_codec       = CONFIG_LIBX264_ENCODER ?
    6702             :                          AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4,
    6703             :     .init              = mov_init,
    6704             :     .write_header      = mov_write_header,
    6705             :     .write_packet      = mov_write_packet,
    6706             :     .write_trailer     = mov_write_trailer,
    6707             :     .deinit            = mov_free,
    6708             :     .flags             = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
    6709             :     .codec_tag         = (const AVCodecTag* const []){ codec_mp4_tags, 0 },
    6710             :     .check_bitstream   = mov_check_bitstream,
    6711             :     .priv_class        = &mp4_muxer_class,
    6712             : };
    6713             : #endif
    6714             : #if CONFIG_PSP_MUXER
    6715             : MOV_CLASS(psp)
    6716             : AVOutputFormat ff_psp_muxer = {
    6717             :     .name              = "psp",
    6718             :     .long_name         = NULL_IF_CONFIG_SMALL("PSP MP4 (MPEG-4 Part 14)"),
    6719             :     .extensions        = "mp4,psp",
    6720             :     .priv_data_size    = sizeof(MOVMuxContext),
    6721             :     .audio_codec       = AV_CODEC_ID_AAC,
    6722             :     .video_codec       = CONFIG_LIBX264_ENCODER ?
    6723             :                          AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4,
    6724             :     .init              = mov_init,
    6725             :     .write_header      = mov_write_header,
    6726             :     .write_packet      = mov_write_packet,
    6727             :     .write_trailer     = mov_write_trailer,
    6728             :     .deinit            = mov_free,
    6729             :     .flags             = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
    6730             :     .codec_tag         = (const AVCodecTag* const []){ codec_mp4_tags, 0 },
    6731             :     .check_bitstream   = mov_check_bitstream,
    6732             :     .priv_class        = &psp_muxer_class,
    6733             : };
    6734             : #endif
    6735             : #if CONFIG_TG2_MUXER
    6736             : MOV_CLASS(tg2)
    6737             : AVOutputFormat ff_tg2_muxer = {
    6738             :     .name              = "3g2",
    6739             :     .long_name         = NULL_IF_CONFIG_SMALL("3GP2 (3GPP2 file format)"),
    6740             :     .extensions        = "3g2",
    6741             :     .priv_data_size    = sizeof(MOVMuxContext),
    6742             :     .audio_codec       = AV_CODEC_ID_AMR_NB,
    6743             :     .video_codec       = AV_CODEC_ID_H263,
    6744             :     .init              = mov_init,
    6745             :     .write_header      = mov_write_header,
    6746             :     .write_packet      = mov_write_packet,
    6747             :     .write_trailer     = mov_write_trailer,
    6748             :     .deinit            = mov_free,
    6749             :     .flags             = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
    6750             :     .codec_tag         = (const AVCodecTag* const []){ codec_3gp_tags, 0 },
    6751             :     .check_bitstream   = mov_check_bitstream,
    6752             :     .priv_class        = &tg2_muxer_class,
    6753             : };
    6754             : #endif
    6755             : #if CONFIG_IPOD_MUXER
    6756             : MOV_CLASS(ipod)
    6757             : AVOutputFormat ff_ipod_muxer = {
    6758             :     .name              = "ipod",
    6759             :     .long_name         = NULL_IF_CONFIG_SMALL("iPod H.264 MP4 (MPEG-4 Part 14)"),
    6760             :     .mime_type         = "video/mp4",
    6761             :     .extensions        = "m4v,m4a,m4b",
    6762             :     .priv_data_size    = sizeof(MOVMuxContext),
    6763             :     .audio_codec       = AV_CODEC_ID_AAC,
    6764             :     .video_codec       = AV_CODEC_ID_H264,
    6765             :     .init              = mov_init,
    6766             :     .write_header      = mov_write_header,
    6767             :     .write_packet      = mov_write_packet,
    6768             :     .write_trailer     = mov_write_trailer,
    6769             :     .deinit            = mov_free,
    6770             :     .flags             = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
    6771             :     .codec_tag         = (const AVCodecTag* const []){ codec_ipod_tags, 0 },
    6772             :     .check_bitstream   = mov_check_bitstream,
    6773             :     .priv_class        = &ipod_muxer_class,
    6774             : };
    6775             : #endif
    6776             : #if CONFIG_ISMV_MUXER
    6777             : MOV_CLASS(ismv)
    6778             : AVOutputFormat ff_ismv_muxer = {
    6779             :     .name              = "ismv",
    6780             :     .long_name         = NULL_IF_CONFIG_SMALL("ISMV/ISMA (Smooth Streaming)"),
    6781             :     .mime_type         = "video/mp4",
    6782             :     .extensions        = "ismv,isma",
    6783             :     .priv_data_size    = sizeof(MOVMuxContext),
    6784             :     .audio_codec       = AV_CODEC_ID_AAC,
    6785             :     .video_codec       = AV_CODEC_ID_H264,
    6786             :     .init              = mov_init,
    6787             :     .write_header      = mov_write_header,
    6788             :     .write_packet      = mov_write_packet,
    6789             :     .write_trailer     = mov_write_trailer,
    6790             :     .deinit            = mov_free,
    6791             :     .flags             = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
    6792             :     .codec_tag         = (const AVCodecTag* const []){
    6793             :         codec_mp4_tags, codec_ism_tags, 0 },
    6794             :     .check_bitstream   = mov_check_bitstream,
    6795             :     .priv_class        = &ismv_muxer_class,
    6796             : };
    6797             : #endif
    6798             : #if CONFIG_F4V_MUXER
    6799             : MOV_CLASS(f4v)
    6800             : AVOutputFormat ff_f4v_muxer = {
    6801             :     .name              = "f4v",
    6802             :     .long_name         = NULL_IF_CONFIG_SMALL("F4V Adobe Flash Video"),
    6803             :     .mime_type         = "application/f4v",
    6804             :     .extensions        = "f4v",
    6805             :     .priv_data_size    = sizeof(MOVMuxContext),
    6806             :     .audio_codec       = AV_CODEC_ID_AAC,
    6807             :     .video_codec       = AV_CODEC_ID_H264,
    6808             :     .init              = mov_init,
    6809             :     .write_header      = mov_write_header,
    6810             :     .write_packet      = mov_write_packet,
    6811             :     .write_trailer     = mov_write_trailer,
    6812             :     .deinit            = mov_free,
    6813             :     .flags             = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH,
    6814             :     .codec_tag         = (const AVCodecTag* const []){ codec_f4v_tags, 0 },
    6815             :     .check_bitstream   = mov_check_bitstream,
    6816             :     .priv_class        = &f4v_muxer_class,
    6817             : };
    6818             : #endif

Generated by: LCOV version 1.13