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

Generated by: LCOV version 1.13