LCOV - code coverage report
Current view: top level - libavformat - movenc.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 2653 4205 63.1 %
Date: 2018-05-20 11:54:08 Functions: 130 173 75.1 %

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

Generated by: LCOV version 1.13