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 "config_components.h"
25 
26 #include <stdint.h>
27 #include <inttypes.h>
28 
29 #include "movenc.h"
30 #include "avformat.h"
31 #include "avio_internal.h"
32 #include "dovi_isom.h"
33 #include "riff.h"
34 #include "avio.h"
35 #include "isom.h"
36 #include "av1.h"
37 #include "avc.h"
38 #include "libavcodec/ac3_parser_internal.h"
39 #include "libavcodec/dnxhddata.h"
40 #include "libavcodec/flac.h"
41 #include "libavcodec/get_bits.h"
42 
43 #include "libavcodec/internal.h"
44 #include "libavcodec/put_bits.h"
45 #include "libavcodec/vc1_common.h"
46 #include "libavcodec/raw.h"
47 #include "internal.h"
48 #include "libavutil/avstring.h"
49 #include "libavutil/channel_layout.h"
50 #include "libavutil/intfloat.h"
51 #include "libavutil/mathematics.h"
52 #include "libavutil/libm.h"
53 #include "libavutil/opt.h"
54 #include "libavutil/dict.h"
55 #include "libavutil/pixdesc.h"
56 #include "libavutil/stereo3d.h"
57 #include "libavutil/timecode.h"
58 #include "libavutil/dovi_meta.h"
59 #include "libavutil/color_utils.h"
60 #include "libavutil/uuid.h"
61 #include "hevc.h"
62 #include "rtpenc.h"
63 #include "mov_chan.h"
64 #include "movenc_ttml.h"
65 #include "mux.h"
66 #include "rawutils.h"
67 #include "ttmlenc.h"
68 #include "version.h"
69 #include "vpcc.h"
70 
71 static const AVOption options[] = {
72     { "movflags", "MOV muxer flags", offsetof(MOVMuxContext, flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
73     { "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" },
74     { "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 },
75     { "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" },
76     { "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" },
77     { "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" },
78     { "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" },
79     { "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" },
80     { "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" },
81     { "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" },
82     { "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" },
83     { "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" },
84     { "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" },
85     { "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" },
86     { "cmaf", "Write CMAF compatible fragmented MP4", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_CMAF}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
87     { "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" },
88     { "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" },
89     { "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" },
90     { "skip_sidx", "Skip writing of sidx atom", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_SKIP_SIDX}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
91     { "write_colr", "Write colr atom even if the color info is unspecified (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" },
92     { "prefer_icc", "If writing colr atom prioritise usage of ICC profile if it exists in stream packet side data", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_PREFER_ICC}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
93     { "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" },
94     { "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" },
95     { "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" },
96     { "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" },
97 #ifdef OHOS_TIMED_META_TRACK
98     { "use_timed_meta_track", "Use timed meta data track for linking metadata to another track", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_TIMED_METADATA}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
99 #endif
100     FF_RTP_FLAG_OPTS(MOVMuxContext, rtp_flags),
101     { "skip_iods", "Skip writing iods atom.", offsetof(MOVMuxContext, iods_skip), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
102     { "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},
103     { "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},
104     { "frag_duration", "Maximum fragment duration", offsetof(MOVMuxContext, max_fragment_duration), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
105     { "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},
106     { "frag_size", "Maximum fragment size", offsetof(MOVMuxContext, max_fragment_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
107     { "ism_lookahead", "Number of lookahead entries for ISM files", offsetof(MOVMuxContext, ism_lookahead), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 255, AV_OPT_FLAG_ENCODING_PARAM},
108     { "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},
109     { "brand",    "Override major brand", offsetof(MOVMuxContext, major_brand),   AV_OPT_TYPE_STRING, {.str = NULL}, .flags = AV_OPT_FLAG_ENCODING_PARAM },
110     { "use_editlist", "use edit list", offsetof(MOVMuxContext, use_editlist), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM},
111     { "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},
112     { "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},
113     { "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 },
114     { "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 },
115     { "encryption_key", "The media encryption key (hex)", offsetof(MOVMuxContext, encryption_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_ENCODING_PARAM },
116     { "encryption_kid", "The media encryption key identifier (hex)", offsetof(MOVMuxContext, encryption_kid), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_ENCODING_PARAM },
117     { "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},
118     { "write_btrt", "force or disable writing btrt", offsetof(MOVMuxContext, write_btrt), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM},
119     { "write_tmcd", "force or disable writing tmcd", offsetof(MOVMuxContext, write_tmcd), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM},
120     { "write_prft", "Write producer reference time box with specified time source", offsetof(MOVMuxContext, write_prft), AV_OPT_TYPE_INT, {.i64 = MOV_PRFT_NONE}, 0, MOV_PRFT_NB-1, AV_OPT_FLAG_ENCODING_PARAM, "prft"},
121     { "wallclock", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = MOV_PRFT_SRC_WALLCLOCK}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM, "prft"},
122     { "pts", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = MOV_PRFT_SRC_PTS}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM, "prft"},
123     { "empty_hdlr_name", "write zero-length name string in hdlr atoms within mdia and minf atoms", offsetof(MOVMuxContext, empty_hdlr_name), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
124     { "movie_timescale", "set movie timescale", offsetof(MOVMuxContext, movie_timescale), AV_OPT_TYPE_INT, {.i64 = MOV_TIMESCALE}, 1, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
125     { NULL },
126 };
127 
128 static const AVClass mov_isobmff_muxer_class = {
129     .class_name = "mov/mp4/tgp/psp/tg2/ipod/ismv/f4v muxer",
130     .item_name  = av_default_item_name,
131     .option     = options,
132     .version    = LIBAVUTIL_VERSION_INT,
133 };
134 
135 #ifdef OHOS_HDR_VIVID
136 typedef struct CuvaConfig {
137     int cuva_version_map;
138     int terminal_provide_code;
139     int terminal_provide_oriented_code;
140 } CuvaConfig;
141 #endif
142 
143 static int get_moov_size(AVFormatContext *s);
144 static int mov_write_single_packet(AVFormatContext *s, AVPacket *pkt);
145 
utf8len(const uint8_t *b)146 static int utf8len(const uint8_t *b)
147 {
148     int len = 0;
149     int val;
150     while (*b) {
151         GET_UTF8(val, *b++, return -1;)
152         len++;
153     }
154     return len;
155 }
156 
157 //FIXME support 64 bit variant with wide placeholders
update_size(AVIOContext *pb, int64_t pos)158 static int64_t update_size(AVIOContext *pb, int64_t pos)
159 {
160     int64_t curpos = avio_tell(pb);
161     avio_seek(pb, pos, SEEK_SET);
162     avio_wb32(pb, curpos - pos); /* rewrite size */
163     avio_seek(pb, curpos, SEEK_SET);
164 
165     return curpos - pos;
166 }
167 
co64_required(const MOVTrack *track)168 static int co64_required(const MOVTrack *track)
169 {
170     if (track->entry > 0 && track->cluster[track->entry - 1].pos + track->data_offset > UINT32_MAX)
171         return 1;
172     return 0;
173 }
174 
is_cover_image(const AVStream *st)175 static int is_cover_image(const AVStream *st)
176 {
177     /* Eg. AV_DISPOSITION_ATTACHED_PIC | AV_DISPOSITION_TIMED_THUMBNAILS
178      * is encoded as sparse video track */
179     return st && st->disposition == AV_DISPOSITION_ATTACHED_PIC;
180 }
181 
rtp_hinting_needed(const AVStream *st)182 static int rtp_hinting_needed(const AVStream *st)
183 {
184     /* Add hint tracks for each real audio and video stream */
185     if (is_cover_image(st))
186         return 0;
187     return st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ||
188            st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO;
189 }
190 
191 /* Chunk offset atom */
mov_write_stco_tag(AVIOContext *pb, MOVTrack *track)192 static int mov_write_stco_tag(AVIOContext *pb, MOVTrack *track)
193 {
194     int i;
195     int mode64 = co64_required(track); // use 32 bit size variant if possible
196     int64_t pos = avio_tell(pb);
197     avio_wb32(pb, 0); /* size */
198     if (mode64)
199         ffio_wfourcc(pb, "co64");
200     else
201         ffio_wfourcc(pb, "stco");
202     avio_wb32(pb, 0); /* version & flags */
203     avio_wb32(pb, track->chunkCount); /* entry count */
204     for (i = 0; i < track->entry; i++) {
205         if (!track->cluster[i].chunkNum)
206             continue;
207         if (mode64 == 1)
208             avio_wb64(pb, track->cluster[i].pos + track->data_offset);
209         else
210             avio_wb32(pb, track->cluster[i].pos + track->data_offset);
211     }
212     return update_size(pb, pos);
213 }
214 
215 /* Sample size atom */
mov_write_stsz_tag(AVIOContext *pb, MOVTrack *track)216 static int mov_write_stsz_tag(AVIOContext *pb, MOVTrack *track)
217 {
218     int equalChunks = 1;
219     int i, j, entries = 0, tst = -1, oldtst = -1;
220 
221     int64_t pos = avio_tell(pb);
222     avio_wb32(pb, 0); /* size */
223     ffio_wfourcc(pb, "stsz");
224     avio_wb32(pb, 0); /* version & flags */
225 
226     for (i = 0; i < track->entry; i++) {
227         tst = track->cluster[i].size / track->cluster[i].entries;
228         if (oldtst != -1 && tst != oldtst)
229             equalChunks = 0;
230         oldtst = tst;
231         entries += track->cluster[i].entries;
232     }
233     if (equalChunks && track->entry) {
234         int sSize = track->entry ? track->cluster[0].size / track->cluster[0].entries : 0;
235         sSize = FFMAX(1, sSize); // adpcm mono case could make sSize == 0
236         avio_wb32(pb, sSize); // sample size
237         avio_wb32(pb, entries); // sample count
238     } else {
239         avio_wb32(pb, 0); // sample size
240         avio_wb32(pb, entries); // sample count
241         for (i = 0; i < track->entry; i++) {
242             for (j = 0; j < track->cluster[i].entries; j++) {
243                 avio_wb32(pb, track->cluster[i].size /
244                           track->cluster[i].entries);
245             }
246         }
247     }
248     return update_size(pb, pos);
249 }
250 
251 /* Sample to chunk atom */
mov_write_stsc_tag(AVIOContext *pb, MOVTrack *track)252 static int mov_write_stsc_tag(AVIOContext *pb, MOVTrack *track)
253 {
254     int index = 0, oldval = -1, i;
255     int64_t entryPos, curpos;
256 
257     int64_t pos = avio_tell(pb);
258     avio_wb32(pb, 0); /* size */
259     ffio_wfourcc(pb, "stsc");
260     avio_wb32(pb, 0); // version & flags
261     entryPos = avio_tell(pb);
262     avio_wb32(pb, track->chunkCount); // entry count
263     for (i = 0; i < track->entry; i++) {
264         if (oldval != track->cluster[i].samples_in_chunk && track->cluster[i].chunkNum) {
265             avio_wb32(pb, track->cluster[i].chunkNum); // first chunk
266             avio_wb32(pb, track->cluster[i].samples_in_chunk); // samples per chunk
267             avio_wb32(pb, 0x1); // sample description index
268             oldval = track->cluster[i].samples_in_chunk;
269             index++;
270         }
271     }
272     curpos = avio_tell(pb);
273     avio_seek(pb, entryPos, SEEK_SET);
274     avio_wb32(pb, index); // rewrite size
275     avio_seek(pb, curpos, SEEK_SET);
276 
277     return update_size(pb, pos);
278 }
279 
280 /* Sync sample atom */
mov_write_stss_tag(AVIOContext *pb, MOVTrack *track, uint32_t flag)281 static int mov_write_stss_tag(AVIOContext *pb, MOVTrack *track, uint32_t flag)
282 {
283     int64_t curpos, entryPos;
284     int i, index = 0;
285     int64_t pos = avio_tell(pb);
286     avio_wb32(pb, 0); // size
287     ffio_wfourcc(pb, flag == MOV_SYNC_SAMPLE ? "stss" : "stps");
288     avio_wb32(pb, 0); // version & flags
289     entryPos = avio_tell(pb);
290     avio_wb32(pb, track->entry); // entry count
291     for (i = 0; i < track->entry; i++) {
292         if (track->cluster[i].flags & flag) {
293             avio_wb32(pb, i + 1);
294             index++;
295         }
296     }
297     curpos = avio_tell(pb);
298     avio_seek(pb, entryPos, SEEK_SET);
299     avio_wb32(pb, index); // rewrite size
300     avio_seek(pb, curpos, SEEK_SET);
301     return update_size(pb, pos);
302 }
303 
304 /* Sample dependency atom */
mov_write_sdtp_tag(AVIOContext *pb, MOVTrack *track)305 static int mov_write_sdtp_tag(AVIOContext *pb, MOVTrack *track)
306 {
307     int i;
308     uint8_t leading, dependent, reference, redundancy;
309     int64_t pos = avio_tell(pb);
310     avio_wb32(pb, 0); // size
311     ffio_wfourcc(pb, "sdtp");
312     avio_wb32(pb, 0); // version & flags
313     for (i = 0; i < track->entry; i++) {
314         dependent = MOV_SAMPLE_DEPENDENCY_YES;
315         leading = reference = redundancy = MOV_SAMPLE_DEPENDENCY_UNKNOWN;
316         if (track->cluster[i].flags & MOV_DISPOSABLE_SAMPLE) {
317             reference = MOV_SAMPLE_DEPENDENCY_NO;
318 #ifdef OHOS_SDTP_BOX_EXT
319         } else if (track->cluster[i].flags & MOV_DISPOSABLE_EXT_SAMPLE) {
320             reference = MOV_SAMPLE_DEPENDENCY_EXT;
321 #endif
322         }
323         if (track->cluster[i].flags & MOV_SYNC_SAMPLE) {
324             dependent = MOV_SAMPLE_DEPENDENCY_NO;
325         }
326         avio_w8(pb, (leading << 6)   | (dependent << 4) |
327                     (reference << 2) | redundancy);
328     }
329     return update_size(pb, pos);
330 }
331 
mov_write_amr_tag(AVIOContext *pb, MOVTrack *track)332 static int mov_write_amr_tag(AVIOContext *pb, MOVTrack *track)
333 {
334     avio_wb32(pb, 0x11); /* size */
335     if (track->mode == MODE_MOV) ffio_wfourcc(pb, "samr");
336     else                         ffio_wfourcc(pb, "damr");
337     ffio_wfourcc(pb, "FFMP");
338     avio_w8(pb, 0); /* decoder version */
339 
340     avio_wb16(pb, 0x81FF); /* Mode set (all modes for AMR_NB) */
341     avio_w8(pb, 0x00); /* Mode change period (no restriction) */
342     avio_w8(pb, 0x01); /* Frames per sample */
343     return 0x11;
344 }
345 
346 struct eac3_info {
347     AVPacket *pkt;
348     uint8_t ec3_done;
349     uint8_t num_blocks;
350 
351     /* Layout of the EC3SpecificBox */
352     /* maximum bitrate */
353     uint16_t data_rate;
354     int8_t   ac3_bit_rate_code;
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 
mov_write_ac3_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)379 static int mov_write_ac3_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
380 {
381     struct eac3_info *info = track->eac3_priv;
382     PutBitContext pbc;
383     uint8_t buf[3];
384 
385     if (!info || !info->ec3_done) {
386         av_log(s, AV_LOG_ERROR,
387                "Cannot write moov atom before AC3 packets."
388                " Set the delay_moov flag to fix this.\n");
389         return AVERROR(EINVAL);
390     }
391 
392     if (info->substream[0].bsid > 8) {
393         av_log(s, AV_LOG_ERROR,
394                "RealAudio AC-3/DolbyNet with bsid %d is not defined by the "
395                "ISOBMFF specification in ETSI TS 102 366!\n",
396                info->substream[0].bsid);
397         return AVERROR(EINVAL);
398     }
399 
400     if (info->ac3_bit_rate_code < 0) {
401         av_log(s, AV_LOG_ERROR,
402                "No valid AC3 bit rate code for data rate of %d!\n",
403                info->data_rate);
404         return AVERROR(EINVAL);
405     }
406 
407     avio_wb32(pb, 11);
408     ffio_wfourcc(pb, "dac3");
409 
410     init_put_bits(&pbc, buf, sizeof(buf));
411     put_bits(&pbc, 2, info->substream[0].fscod);
412     put_bits(&pbc, 5, info->substream[0].bsid);
413     put_bits(&pbc, 3, info->substream[0].bsmod);
414     put_bits(&pbc, 3, info->substream[0].acmod);
415     put_bits(&pbc, 1, info->substream[0].lfeon);
416     put_bits(&pbc, 5, info->ac3_bit_rate_code); // bit_rate_code
417     put_bits(&pbc, 5, 0); // reserved
418 
419     flush_put_bits(&pbc);
420     avio_write(pb, buf, sizeof(buf));
421 
422     return 11;
423 }
424 
handle_eac3(MOVMuxContext *mov, AVPacket *pkt, MOVTrack *track)425 static int handle_eac3(MOVMuxContext *mov, AVPacket *pkt, MOVTrack *track)
426 {
427     AC3HeaderInfo *hdr = NULL;
428     struct eac3_info *info;
429     int num_blocks, ret;
430 
431     if (!track->eac3_priv) {
432         if (!(track->eac3_priv = av_mallocz(sizeof(*info))))
433             return AVERROR(ENOMEM);
434 
435         ((struct eac3_info *)track->eac3_priv)->ac3_bit_rate_code = -1;
436     }
437     info = track->eac3_priv;
438 
439     if (!info->pkt && !(info->pkt = av_packet_alloc()))
440         return AVERROR(ENOMEM);
441 
442     if ((ret = avpriv_ac3_parse_header(&hdr, pkt->data, pkt->size)) < 0) {
443         if (ret == AVERROR(ENOMEM))
444             goto end;
445 
446         /* drop the packets until we see a good one */
447         if (!track->entry) {
448             av_log(mov->fc, AV_LOG_WARNING, "Dropping invalid packet from start of the stream\n");
449             ret = 0;
450         } else
451             ret = AVERROR_INVALIDDATA;
452         goto end;
453     }
454 
455     info->data_rate = FFMAX(info->data_rate, hdr->bit_rate / 1000);
456     info->ac3_bit_rate_code = FFMAX(info->ac3_bit_rate_code,
457                                     hdr->ac3_bit_rate_code);
458     num_blocks = hdr->num_blocks;
459 
460     if (!info->ec3_done) {
461         /* AC-3 substream must be the first one */
462         if (hdr->bitstream_id <= 10 && hdr->substreamid != 0) {
463             ret = AVERROR(EINVAL);
464             goto end;
465         }
466 
467         /* this should always be the case, given that our AC-3 parser
468          * concatenates dependent frames to their independent parent */
469         if (hdr->frame_type == EAC3_FRAME_TYPE_INDEPENDENT ||
470             hdr->frame_type == EAC3_FRAME_TYPE_AC3_CONVERT) {
471             /* substream ids must be incremental */
472             if (hdr->substreamid > info->num_ind_sub + 1) {
473                 ret = AVERROR(EINVAL);
474                 goto end;
475             }
476 
477             if (hdr->substreamid == info->num_ind_sub + 1) {
478                 //info->num_ind_sub++;
479                 avpriv_request_sample(mov->fc, "Multiple independent substreams");
480                 ret = AVERROR_PATCHWELCOME;
481                 goto end;
482             } else if (hdr->substreamid < info->num_ind_sub ||
483                        hdr->substreamid == 0 && info->substream[0].bsid) {
484                 info->ec3_done = 1;
485                 goto concatenate;
486             }
487         } else {
488             if (hdr->substreamid != 0) {
489                 avpriv_request_sample(mov->fc, "Multiple non EAC3 independent substreams");
490                 ret = AVERROR_PATCHWELCOME;
491                 goto end;
492             }
493         }
494 
495         /* fill the info needed for the "dec3" atom */
496         info->substream[hdr->substreamid].fscod = hdr->sr_code;
497         info->substream[hdr->substreamid].bsid  = hdr->bitstream_id;
498         info->substream[hdr->substreamid].bsmod = hdr->bitstream_mode;
499         info->substream[hdr->substreamid].acmod = hdr->channel_mode;
500         info->substream[hdr->substreamid].lfeon = hdr->lfe_on;
501 
502         if (track->par->codec_id == AV_CODEC_ID_AC3) {
503             // with AC-3 we only require the information of a single packet,
504             // so we can finish as soon as the basic values of the bit stream
505             // have been set to the track's informational structure.
506             info->ec3_done = 1;
507             goto concatenate;
508         }
509 
510         /* Parse dependent substream(s), if any */
511         if (pkt->size != hdr->frame_size) {
512             int cumul_size = hdr->frame_size;
513             int parent = hdr->substreamid;
514 
515             while (cumul_size != pkt->size) {
516                 GetBitContext gbc;
517                 int i;
518                 ret = avpriv_ac3_parse_header(&hdr, pkt->data + cumul_size, pkt->size - cumul_size);
519                 if (ret < 0)
520                     goto end;
521                 if (hdr->frame_type != EAC3_FRAME_TYPE_DEPENDENT) {
522                     ret = AVERROR(EINVAL);
523                     goto end;
524                 }
525                 info->substream[parent].num_dep_sub++;
526                 ret /= 8;
527 
528                 /* header is parsed up to lfeon, but custom channel map may be needed */
529                 init_get_bits8(&gbc, pkt->data + cumul_size + ret, pkt->size - cumul_size - ret);
530                 /* skip bsid */
531                 skip_bits(&gbc, 5);
532                 /* skip volume control params */
533                 for (i = 0; i < (hdr->channel_mode ? 1 : 2); i++) {
534                     skip_bits(&gbc, 5); // skip dialog normalization
535                     if (get_bits1(&gbc)) {
536                         skip_bits(&gbc, 8); // skip compression gain word
537                     }
538                 }
539                 /* get the dependent stream channel map, if exists */
540                 if (get_bits1(&gbc))
541                     info->substream[parent].chan_loc |= (get_bits(&gbc, 16) >> 5) & 0x1f;
542                 else
543                     info->substream[parent].chan_loc |= hdr->channel_mode;
544                 cumul_size += hdr->frame_size;
545             }
546         }
547     }
548 
549 concatenate:
550     if (!info->num_blocks && num_blocks == 6) {
551         ret = pkt->size;
552         goto end;
553     }
554     else if (info->num_blocks + num_blocks > 6) {
555         ret = AVERROR_INVALIDDATA;
556         goto end;
557     }
558 
559     if (!info->num_blocks) {
560         ret = av_packet_ref(info->pkt, pkt);
561         if (!ret)
562             info->num_blocks = num_blocks;
563         goto end;
564     } else {
565         if ((ret = av_grow_packet(info->pkt, pkt->size)) < 0)
566             goto end;
567         memcpy(info->pkt->data + info->pkt->size - pkt->size, pkt->data, pkt->size);
568         info->num_blocks += num_blocks;
569         info->pkt->duration += pkt->duration;
570         if (info->num_blocks != 6)
571             goto end;
572         av_packet_unref(pkt);
573         av_packet_move_ref(pkt, info->pkt);
574         info->num_blocks = 0;
575     }
576     ret = pkt->size;
577 
578 end:
579     av_free(hdr);
580 
581     return ret;
582 }
583 
mov_write_eac3_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)584 static int mov_write_eac3_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
585 {
586     PutBitContext pbc;
587     uint8_t *buf;
588     struct eac3_info *info;
589     int size, i;
590 
591     if (!track->eac3_priv) {
592         av_log(s, AV_LOG_ERROR,
593                "Cannot write moov atom before EAC3 packets parsed.\n");
594         return AVERROR(EINVAL);
595     }
596 
597     info = track->eac3_priv;
598     size = 2 + ((34 * (info->num_ind_sub + 1) + 7) >> 3);
599     buf = av_malloc(size);
600     if (!buf) {
601         return AVERROR(ENOMEM);
602     }
603 
604     init_put_bits(&pbc, buf, size);
605     put_bits(&pbc, 13, info->data_rate);
606     put_bits(&pbc,  3, info->num_ind_sub);
607     for (i = 0; i <= info->num_ind_sub; i++) {
608         put_bits(&pbc, 2, info->substream[i].fscod);
609         put_bits(&pbc, 5, info->substream[i].bsid);
610         put_bits(&pbc, 1, 0); /* reserved */
611         put_bits(&pbc, 1, 0); /* asvc */
612         put_bits(&pbc, 3, info->substream[i].bsmod);
613         put_bits(&pbc, 3, info->substream[i].acmod);
614         put_bits(&pbc, 1, info->substream[i].lfeon);
615         put_bits(&pbc, 5, 0); /* reserved */
616         put_bits(&pbc, 4, info->substream[i].num_dep_sub);
617         if (!info->substream[i].num_dep_sub) {
618             put_bits(&pbc, 1, 0); /* reserved */
619         } else {
620             put_bits(&pbc, 9, info->substream[i].chan_loc);
621         }
622     }
623     flush_put_bits(&pbc);
624     size = put_bytes_output(&pbc);
625 
626     avio_wb32(pb, size + 8);
627     ffio_wfourcc(pb, "dec3");
628     avio_write(pb, buf, size);
629 
630     av_free(buf);
631 
632     return size;
633 }
634 
635 /**
636  * This function writes extradata "as is".
637  * Extradata must be formatted like a valid atom (with size and tag).
638  */
mov_write_extradata_tag(AVIOContext *pb, MOVTrack *track)639 static int mov_write_extradata_tag(AVIOContext *pb, MOVTrack *track)
640 {
641     avio_write(pb, track->par->extradata, track->par->extradata_size);
642     return track->par->extradata_size;
643 }
644 
mov_write_enda_tag(AVIOContext *pb)645 static int mov_write_enda_tag(AVIOContext *pb)
646 {
647     avio_wb32(pb, 10);
648     ffio_wfourcc(pb, "enda");
649     avio_wb16(pb, 1); /* little endian */
650     return 10;
651 }
652 
mov_write_enda_tag_be(AVIOContext *pb)653 static int mov_write_enda_tag_be(AVIOContext *pb)
654 {
655   avio_wb32(pb, 10);
656   ffio_wfourcc(pb, "enda");
657   avio_wb16(pb, 0); /* big endian */
658   return 10;
659 }
660 
put_descr(AVIOContext *pb, int tag, unsigned int size)661 static void put_descr(AVIOContext *pb, int tag, unsigned int size)
662 {
663     int i = 3;
664     avio_w8(pb, tag);
665     for (; i > 0; i--)
666         avio_w8(pb, (size >> (7 * i)) | 0x80);
667     avio_w8(pb, size & 0x7F);
668 }
669 
compute_avg_bitrate(MOVTrack *track)670 static unsigned compute_avg_bitrate(MOVTrack *track)
671 {
672     uint64_t size = 0;
673     int i;
674     if (!track->track_duration)
675         return 0;
676     for (i = 0; i < track->entry; i++)
677         size += track->cluster[i].size;
678     return size * 8 * track->timescale / track->track_duration;
679 }
680 
681 struct mpeg4_bit_rate_values {
682     uint32_t buffer_size;  ///< Size of the decoding buffer for the elementary stream in bytes.
683     uint32_t max_bit_rate; ///< Maximum rate in bits/second over any window of one second.
684     uint32_t avg_bit_rate; ///< Average rate in bits/second over the entire presentation.
685 };
686 
calculate_mpeg4_bit_rates(MOVTrack *track)687 static struct mpeg4_bit_rate_values calculate_mpeg4_bit_rates(MOVTrack *track)
688 {
689     AVCPBProperties *props = track->st ?
690         (AVCPBProperties*)av_stream_get_side_data(track->st,
691                                                   AV_PKT_DATA_CPB_PROPERTIES,
692                                                   NULL) :
693         NULL;
694     struct mpeg4_bit_rate_values bit_rates = { 0 };
695 
696     bit_rates.avg_bit_rate = compute_avg_bitrate(track);
697     if (!bit_rates.avg_bit_rate) {
698         // if the average bit rate cannot be calculated at this point, such as
699         // in the case of fragmented MP4, utilize the following values as
700         // fall-back in priority order:
701         //
702         // 1. average bit rate property
703         // 2. bit rate (usually average over the whole clip)
704         // 3. maximum bit rate property
705 
706         if (props && props->avg_bitrate) {
707             bit_rates.avg_bit_rate = props->avg_bitrate;
708         } else if (track->par->bit_rate) {
709             bit_rates.avg_bit_rate = track->par->bit_rate;
710         } else if (props && props->max_bitrate) {
711             bit_rates.avg_bit_rate = props->max_bitrate;
712         }
713     }
714 
715     // (FIXME should be max rate in any 1 sec window)
716     bit_rates.max_bit_rate = FFMAX(track->par->bit_rate,
717                                    bit_rates.avg_bit_rate);
718 
719     // utilize values from properties if we have them available
720     if (props) {
721         bit_rates.max_bit_rate = FFMAX(bit_rates.max_bit_rate,
722                                        props->max_bitrate);
723         bit_rates.buffer_size = props->buffer_size / 8;
724     }
725 
726     return bit_rates;
727 }
728 
mov_write_esds_tag(AVIOContext *pb, MOVTrack *track)729 static int mov_write_esds_tag(AVIOContext *pb, MOVTrack *track) // Basic
730 {
731     struct mpeg4_bit_rate_values bit_rates = calculate_mpeg4_bit_rates(track);
732     int64_t pos = avio_tell(pb);
733     int decoder_specific_info_len = track->vos_len ? 5 + track->vos_len : 0;
734 
735     avio_wb32(pb, 0); // size
736     ffio_wfourcc(pb, "esds");
737     avio_wb32(pb, 0); // Version
738 
739     // ES descriptor
740     put_descr(pb, 0x03, 3 + 5+13 + decoder_specific_info_len + 5+1);
741     avio_wb16(pb, track->track_id);
742     avio_w8(pb, 0x00); // flags (= no flags)
743 
744     // DecoderConfig descriptor
745     put_descr(pb, 0x04, 13 + decoder_specific_info_len);
746 
747     // Object type indication
748     if ((track->par->codec_id == AV_CODEC_ID_MP2 ||
749          track->par->codec_id == AV_CODEC_ID_MP3) &&
750         track->par->sample_rate > 24000)
751         avio_w8(pb, 0x6B); // 11172-3
752     else
753         avio_w8(pb, ff_codec_get_tag(ff_mp4_obj_type, track->par->codec_id));
754 
755     // the following fields is made of 6 bits to identify the streamtype (4 for video, 5 for audio)
756     // plus 1 bit to indicate upstream and 1 bit set to 1 (reserved)
757     if (track->par->codec_id == AV_CODEC_ID_DVD_SUBTITLE)
758         avio_w8(pb, (0x38 << 2) | 1); // flags (= NeroSubpicStream)
759     else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO)
760         avio_w8(pb, 0x15); // flags (= Audiostream)
761     else
762         avio_w8(pb, 0x11); // flags (= Visualstream)
763 
764     avio_wb24(pb, bit_rates.buffer_size); // Buffersize DB
765     avio_wb32(pb, bit_rates.max_bit_rate); // maxbitrate
766     avio_wb32(pb, bit_rates.avg_bit_rate);
767 
768     if (track->vos_len) {
769         // DecoderSpecific info descriptor
770         put_descr(pb, 0x05, track->vos_len);
771         avio_write(pb, track->vos_data, track->vos_len);
772     }
773 
774     // SL descriptor
775     put_descr(pb, 0x06, 1);
776     avio_w8(pb, 0x02);
777     return update_size(pb, pos);
778 }
779 
mov_pcm_le_gt16(enum AVCodecID codec_id)780 static int mov_pcm_le_gt16(enum AVCodecID codec_id)
781 {
782     return codec_id == AV_CODEC_ID_PCM_S24LE ||
783            codec_id == AV_CODEC_ID_PCM_S32LE ||
784            codec_id == AV_CODEC_ID_PCM_F32LE ||
785            codec_id == AV_CODEC_ID_PCM_F64LE;
786 }
787 
mov_pcm_be_gt16(enum AVCodecID codec_id)788 static int mov_pcm_be_gt16(enum AVCodecID codec_id)
789 {
790     return codec_id == AV_CODEC_ID_PCM_S24BE ||
791            codec_id == AV_CODEC_ID_PCM_S32BE ||
792            codec_id == AV_CODEC_ID_PCM_F32BE ||
793            codec_id == AV_CODEC_ID_PCM_F64BE;
794 }
795 
mov_write_ms_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)796 static int mov_write_ms_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
797 {
798     int ret;
799     int64_t pos = avio_tell(pb);
800     avio_wb32(pb, 0);
801     avio_wl32(pb, track->tag); // store it byteswapped
802     track->par->codec_tag = av_bswap16(track->tag >> 16);
803     if ((ret = ff_put_wav_header(s, pb, track->par, 0)) < 0)
804         return ret;
805     return update_size(pb, pos);
806 }
807 
mov_write_wfex_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)808 static int mov_write_wfex_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
809 {
810     int ret;
811     int64_t pos = avio_tell(pb);
812     avio_wb32(pb, 0);
813     ffio_wfourcc(pb, "wfex");
814     if ((ret = ff_put_wav_header(s, pb, track->st->codecpar, FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX)) < 0)
815         return ret;
816     return update_size(pb, pos);
817 }
818 
mov_write_dfla_tag(AVIOContext *pb, MOVTrack *track)819 static int mov_write_dfla_tag(AVIOContext *pb, MOVTrack *track)
820 {
821     int64_t pos = avio_tell(pb);
822     avio_wb32(pb, 0);
823     ffio_wfourcc(pb, "dfLa");
824     avio_w8(pb, 0); /* version */
825     avio_wb24(pb, 0); /* flags */
826 
827     /* Expect the encoder to pass a METADATA_BLOCK_TYPE_STREAMINFO. */
828     if (track->par->extradata_size != FLAC_STREAMINFO_SIZE)
829         return AVERROR_INVALIDDATA;
830 
831     /* TODO: Write other METADATA_BLOCK_TYPEs if the encoder makes them available. */
832     avio_w8(pb, 1 << 7 | FLAC_METADATA_TYPE_STREAMINFO); /* LastMetadataBlockFlag << 7 | BlockType */
833     avio_wb24(pb, track->par->extradata_size); /* Length */
834     avio_write(pb, track->par->extradata, track->par->extradata_size); /* BlockData[Length] */
835 
836     return update_size(pb, pos);
837 }
838 
mov_write_dops_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)839 static int mov_write_dops_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
840 {
841     int64_t pos = avio_tell(pb);
842     int channels, channel_map;
843     avio_wb32(pb, 0);
844     ffio_wfourcc(pb, "dOps");
845     avio_w8(pb, 0); /* Version */
846     if (track->par->extradata_size < 19) {
847         av_log(s, AV_LOG_ERROR, "invalid extradata size\n");
848         return AVERROR_INVALIDDATA;
849     }
850     /* extradata contains an Ogg OpusHead, other than byte-ordering and
851        OpusHead's preceeding magic/version, OpusSpecificBox is currently
852        identical. */
853     channels = AV_RB8(track->par->extradata + 9);
854     channel_map = AV_RB8(track->par->extradata + 18);
855 
856     avio_w8(pb, channels); /* OuputChannelCount */
857     avio_wb16(pb, AV_RL16(track->par->extradata + 10)); /* PreSkip */
858     avio_wb32(pb, AV_RL32(track->par->extradata + 12)); /* InputSampleRate */
859     avio_wb16(pb, AV_RL16(track->par->extradata + 16)); /* OutputGain */
860     avio_w8(pb, channel_map); /* ChannelMappingFamily */
861     /* Write the rest of the header out without byte-swapping. */
862     if (channel_map) {
863         if (track->par->extradata_size < 21 + channels) {
864             av_log(s, AV_LOG_ERROR, "invalid extradata size\n");
865             return AVERROR_INVALIDDATA;
866         }
867         avio_write(pb, track->par->extradata + 19, 2 + channels); /* ChannelMappingTable */
868     }
869 
870     return update_size(pb, pos);
871 }
872 
mov_write_dmlp_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)873 static int mov_write_dmlp_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
874 {
875     int64_t pos = avio_tell(pb);
876     int length;
877     avio_wb32(pb, 0);
878     ffio_wfourcc(pb, "dmlp");
879 
880     if (track->vos_len < 20) {
881         av_log(s, AV_LOG_ERROR,
882                "Cannot write moov atom before TrueHD packets."
883                " Set the delay_moov flag to fix this.\n");
884         return AVERROR(EINVAL);
885     }
886 
887     length = (AV_RB16(track->vos_data) & 0xFFF) * 2;
888     if (length < 20 || length > track->vos_len)
889         return AVERROR_INVALIDDATA;
890 
891     // Only TrueHD is supported
892     if (AV_RB32(track->vos_data + 4) != 0xF8726FBA)
893         return AVERROR_INVALIDDATA;
894 
895     avio_wb32(pb, AV_RB32(track->vos_data + 8)); /* format_info */
896     avio_wb16(pb, AV_RB16(track->vos_data + 18) << 1); /* peak_data_rate */
897     avio_wb32(pb, 0); /* reserved */
898 
899     return update_size(pb, pos);
900 }
901 
mov_write_chan_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)902 static int mov_write_chan_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
903 {
904     uint32_t layout_tag, bitmap, *channel_desc;
905     int64_t pos = avio_tell(pb);
906     int num_desc, ret;
907 
908     if (track->multichannel_as_mono)
909         return 0;
910 
911     ret = ff_mov_get_channel_layout_tag(track->par, &layout_tag,
912                                         &bitmap, &channel_desc);
913 
914     if (ret < 0) {
915         if (ret == AVERROR(ENOSYS)) {
916             av_log(s, AV_LOG_WARNING, "not writing 'chan' tag due to "
917                                       "lack of channel information\n");
918             ret = 0;
919         }
920 
921         return ret;
922     }
923 
924     if (layout_tag == MOV_CH_LAYOUT_MONO && track->mono_as_fc > 0) {
925         av_assert0(!channel_desc);
926         channel_desc = av_malloc(sizeof(*channel_desc));
927         if (!channel_desc)
928             return AVERROR(ENOMEM);
929 
930         layout_tag = 0;
931         bitmap = 0;
932         *channel_desc = 3; // channel label "Center"
933     }
934 
935     num_desc = layout_tag ? 0 : track->par->ch_layout.nb_channels;
936 
937     avio_wb32(pb, 0);           // Size
938     ffio_wfourcc(pb, "chan");   // Type
939     avio_w8(pb, 0);             // Version
940     avio_wb24(pb, 0);           // Flags
941     avio_wb32(pb, layout_tag);  // mChannelLayoutTag
942     avio_wb32(pb, bitmap);      // mChannelBitmap
943     avio_wb32(pb, num_desc);    // mNumberChannelDescriptions
944 
945     for (int i = 0; i < num_desc; i++) {
946         avio_wb32(pb, channel_desc[i]); // mChannelLabel
947         avio_wb32(pb, 0);               // mChannelFlags
948         avio_wl32(pb, 0);               // mCoordinates[0]
949         avio_wl32(pb, 0);               // mCoordinates[1]
950         avio_wl32(pb, 0);               // mCoordinates[2]
951     }
952 
953     av_free(channel_desc);
954 
955     return update_size(pb, pos);
956 }
957 
mov_write_wave_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)958 static int mov_write_wave_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
959 {
960     int64_t pos = avio_tell(pb);
961 
962     avio_wb32(pb, 0);     /* size */
963     ffio_wfourcc(pb, "wave");
964 
965     if (track->par->codec_id != AV_CODEC_ID_QDM2) {
966     avio_wb32(pb, 12);    /* size */
967     ffio_wfourcc(pb, "frma");
968     avio_wl32(pb, track->tag);
969     }
970 
971     if (track->par->codec_id == AV_CODEC_ID_AAC) {
972         /* useless atom needed by mplayer, ipod, not needed by quicktime */
973         avio_wb32(pb, 12); /* size */
974         ffio_wfourcc(pb, "mp4a");
975         avio_wb32(pb, 0);
976         mov_write_esds_tag(pb, track);
977     } else if (mov_pcm_le_gt16(track->par->codec_id))  {
978       mov_write_enda_tag(pb);
979     } else if (mov_pcm_be_gt16(track->par->codec_id))  {
980       mov_write_enda_tag_be(pb);
981     } else if (track->par->codec_id == AV_CODEC_ID_AMR_NB) {
982         mov_write_amr_tag(pb, track);
983     } else if (track->par->codec_id == AV_CODEC_ID_AC3) {
984         mov_write_ac3_tag(s, pb, track);
985     } else if (track->par->codec_id == AV_CODEC_ID_EAC3) {
986         mov_write_eac3_tag(s, pb, track);
987     } else if (track->par->codec_id == AV_CODEC_ID_ALAC ||
988                track->par->codec_id == AV_CODEC_ID_QDM2) {
989         mov_write_extradata_tag(pb, track);
990     } else if (track->par->codec_id == AV_CODEC_ID_ADPCM_MS ||
991                track->par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) {
992         mov_write_ms_tag(s, pb, track);
993     }
994 
995     avio_wb32(pb, 8);     /* size */
996     avio_wb32(pb, 0);     /* null tag */
997 
998     return update_size(pb, pos);
999 }
1000 
mov_write_dvc1_structs(MOVTrack *track, uint8_t *buf)1001 static int mov_write_dvc1_structs(MOVTrack *track, uint8_t *buf)
1002 {
1003     uint8_t *unescaped;
1004     const uint8_t *start, *next, *end = track->vos_data + track->vos_len;
1005     int unescaped_size, seq_found = 0;
1006     int level = 0, interlace = 0;
1007     int packet_seq   = track->vc1_info.packet_seq;
1008     int packet_entry = track->vc1_info.packet_entry;
1009     int slices       = track->vc1_info.slices;
1010     PutBitContext pbc;
1011 
1012     if (track->start_dts == AV_NOPTS_VALUE) {
1013         /* No packets written yet, vc1_info isn't authoritative yet. */
1014         /* Assume inline sequence and entry headers. */
1015         packet_seq = packet_entry = 1;
1016         av_log(NULL, AV_LOG_WARNING,
1017                "moov atom written before any packets, unable to write correct "
1018                "dvc1 atom. Set the delay_moov flag to fix this.\n");
1019     }
1020 
1021     unescaped = av_mallocz(track->vos_len + AV_INPUT_BUFFER_PADDING_SIZE);
1022     if (!unescaped)
1023         return AVERROR(ENOMEM);
1024     start = find_next_marker(track->vos_data, end);
1025     for (next = start; next < end; start = next) {
1026         GetBitContext gb;
1027         int size;
1028         next = find_next_marker(start + 4, end);
1029         size = next - start - 4;
1030         if (size <= 0)
1031             continue;
1032         unescaped_size = vc1_unescape_buffer(start + 4, size, unescaped);
1033         init_get_bits(&gb, unescaped, 8 * unescaped_size);
1034         if (AV_RB32(start) == VC1_CODE_SEQHDR) {
1035             int profile = get_bits(&gb, 2);
1036             if (profile != PROFILE_ADVANCED) {
1037                 av_free(unescaped);
1038                 return AVERROR(ENOSYS);
1039             }
1040             seq_found = 1;
1041             level = get_bits(&gb, 3);
1042             /* chromaformat, frmrtq_postproc, bitrtq_postproc, postprocflag,
1043              * width, height */
1044             skip_bits_long(&gb, 2 + 3 + 5 + 1 + 2*12);
1045             skip_bits(&gb, 1); /* broadcast */
1046             interlace = get_bits1(&gb);
1047             skip_bits(&gb, 4); /* tfcntrflag, finterpflag, reserved, psf */
1048         }
1049     }
1050     if (!seq_found) {
1051         av_free(unescaped);
1052         return AVERROR(ENOSYS);
1053     }
1054 
1055     init_put_bits(&pbc, buf, 7);
1056     /* VC1DecSpecStruc */
1057     put_bits(&pbc, 4, 12); /* profile - advanced */
1058     put_bits(&pbc, 3, level);
1059     put_bits(&pbc, 1, 0); /* reserved */
1060     /* VC1AdvDecSpecStruc */
1061     put_bits(&pbc, 3, level);
1062     put_bits(&pbc, 1, 0); /* cbr */
1063     put_bits(&pbc, 6, 0); /* reserved */
1064     put_bits(&pbc, 1, !interlace); /* no interlace */
1065     put_bits(&pbc, 1, !packet_seq); /* no multiple seq */
1066     put_bits(&pbc, 1, !packet_entry); /* no multiple entry */
1067     put_bits(&pbc, 1, !slices); /* no slice code */
1068     put_bits(&pbc, 1, 0); /* no bframe */
1069     put_bits(&pbc, 1, 0); /* reserved */
1070 
1071     /* framerate */
1072     if (track->st->avg_frame_rate.num > 0 && track->st->avg_frame_rate.den > 0)
1073         put_bits32(&pbc, track->st->avg_frame_rate.num / track->st->avg_frame_rate.den);
1074     else
1075         put_bits32(&pbc, 0xffffffff);
1076 
1077     flush_put_bits(&pbc);
1078 
1079     av_free(unescaped);
1080 
1081     return 0;
1082 }
1083 
mov_write_dvc1_tag(AVIOContext *pb, MOVTrack *track)1084 static int mov_write_dvc1_tag(AVIOContext *pb, MOVTrack *track)
1085 {
1086     uint8_t buf[7] = { 0 };
1087     int ret;
1088 
1089     if ((ret = mov_write_dvc1_structs(track, buf)) < 0)
1090         return ret;
1091 
1092     avio_wb32(pb, track->vos_len + 8 + sizeof(buf));
1093     ffio_wfourcc(pb, "dvc1");
1094     avio_write(pb, buf, sizeof(buf));
1095     avio_write(pb, track->vos_data, track->vos_len);
1096 
1097     return 0;
1098 }
1099 
mov_write_glbl_tag(AVIOContext *pb, MOVTrack *track)1100 static int mov_write_glbl_tag(AVIOContext *pb, MOVTrack *track)
1101 {
1102     avio_wb32(pb, track->vos_len + 8);
1103     ffio_wfourcc(pb, "glbl");
1104     avio_write(pb, track->vos_data, track->vos_len);
1105     return 8 + track->vos_len;
1106 }
1107 
1108 /**
1109  * Compute flags for 'lpcm' tag.
1110  * See CoreAudioTypes and AudioStreamBasicDescription at Apple.
1111  */
mov_get_lpcm_flags(enum AVCodecID codec_id)1112 static int mov_get_lpcm_flags(enum AVCodecID codec_id)
1113 {
1114     switch (codec_id) {
1115     case AV_CODEC_ID_PCM_F32BE:
1116     case AV_CODEC_ID_PCM_F64BE:
1117         return 11;
1118     case AV_CODEC_ID_PCM_F32LE:
1119     case AV_CODEC_ID_PCM_F64LE:
1120         return 9;
1121     case AV_CODEC_ID_PCM_U8:
1122         return 10;
1123     case AV_CODEC_ID_PCM_S16BE:
1124     case AV_CODEC_ID_PCM_S24BE:
1125     case AV_CODEC_ID_PCM_S32BE:
1126         return 14;
1127     case AV_CODEC_ID_PCM_S8:
1128     case AV_CODEC_ID_PCM_S16LE:
1129     case AV_CODEC_ID_PCM_S24LE:
1130     case AV_CODEC_ID_PCM_S32LE:
1131         return 12;
1132     default:
1133         return 0;
1134     }
1135 }
1136 
get_cluster_duration(MOVTrack *track, int cluster_idx)1137 static int get_cluster_duration(MOVTrack *track, int cluster_idx)
1138 {
1139     int64_t next_dts;
1140 
1141     if (cluster_idx >= track->entry)
1142         return 0;
1143 
1144     if (cluster_idx + 1 == track->entry)
1145         next_dts = track->track_duration + track->start_dts;
1146     else
1147         next_dts = track->cluster[cluster_idx + 1].dts;
1148 
1149     next_dts -= track->cluster[cluster_idx].dts;
1150 
1151     av_assert0(next_dts >= 0);
1152     av_assert0(next_dts <= INT_MAX);
1153 
1154     return next_dts;
1155 }
1156 
get_samples_per_packet(MOVTrack *track)1157 static int get_samples_per_packet(MOVTrack *track)
1158 {
1159     int i, first_duration;
1160 
1161 // return track->par->frame_size;
1162 
1163     /* use 1 for raw PCM */
1164     if (!track->audio_vbr)
1165         return 1;
1166 
1167     /* check to see if duration is constant for all clusters */
1168     if (!track->entry)
1169         return 0;
1170     first_duration = get_cluster_duration(track, 0);
1171     for (i = 1; i < track->entry; i++) {
1172         if (get_cluster_duration(track, i) != first_duration)
1173             return 0;
1174     }
1175     return first_duration;
1176 }
1177 
mov_write_btrt_tag(AVIOContext *pb, MOVTrack *track)1178 static int mov_write_btrt_tag(AVIOContext *pb, MOVTrack *track)
1179 {
1180     int64_t pos = avio_tell(pb);
1181     struct mpeg4_bit_rate_values bit_rates = calculate_mpeg4_bit_rates(track);
1182     if (!bit_rates.max_bit_rate && !bit_rates.avg_bit_rate &&
1183         !bit_rates.buffer_size)
1184         // no useful data to be written, skip
1185         return 0;
1186 
1187     avio_wb32(pb, 0); /* size */
1188     ffio_wfourcc(pb, "btrt");
1189 
1190     avio_wb32(pb, bit_rates.buffer_size);
1191     avio_wb32(pb, bit_rates.max_bit_rate);
1192     avio_wb32(pb, bit_rates.avg_bit_rate);
1193 
1194     return update_size(pb, pos);
1195 }
1196 
mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)1197 static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
1198 {
1199     int64_t pos = avio_tell(pb);
1200     int version = 0;
1201     uint32_t tag = track->tag;
1202     int ret = 0;
1203 
1204     if (track->mode == MODE_MOV) {
1205         if (track->timescale > UINT16_MAX || !track->par->ch_layout.nb_channels) {
1206             if (mov_get_lpcm_flags(track->par->codec_id))
1207                 tag = AV_RL32("lpcm");
1208             version = 2;
1209         } else if (track->audio_vbr || mov_pcm_le_gt16(track->par->codec_id) ||
1210                    mov_pcm_be_gt16(track->par->codec_id) ||
1211                    track->par->codec_id == AV_CODEC_ID_ADPCM_MS ||
1212                    track->par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV ||
1213                    track->par->codec_id == AV_CODEC_ID_QDM2) {
1214             version = 1;
1215         }
1216     }
1217 
1218     avio_wb32(pb, 0); /* size */
1219     if (mov->encryption_scheme != MOV_ENC_NONE) {
1220         ffio_wfourcc(pb, "enca");
1221     } else {
1222         avio_wl32(pb, tag); // store it byteswapped
1223     }
1224     avio_wb32(pb, 0); /* Reserved */
1225     avio_wb16(pb, 0); /* Reserved */
1226     avio_wb16(pb, 1); /* Data-reference index, XXX  == 1 */
1227 
1228     /* SoundDescription */
1229     avio_wb16(pb, version); /* Version */
1230     avio_wb16(pb, 0); /* Revision level */
1231     avio_wb32(pb, 0); /* Reserved */
1232 
1233     if (version == 2) {
1234         avio_wb16(pb, 3);
1235         avio_wb16(pb, 16);
1236         avio_wb16(pb, 0xfffe);
1237         avio_wb16(pb, 0);
1238         avio_wb32(pb, 0x00010000);
1239         avio_wb32(pb, 72);
1240         avio_wb64(pb, av_double2int(track->par->sample_rate));
1241         avio_wb32(pb, track->par->ch_layout.nb_channels);
1242         avio_wb32(pb, 0x7F000000);
1243         avio_wb32(pb, av_get_bits_per_sample(track->par->codec_id));
1244         avio_wb32(pb, mov_get_lpcm_flags(track->par->codec_id));
1245         avio_wb32(pb, track->sample_size);
1246         avio_wb32(pb, get_samples_per_packet(track));
1247     } else {
1248         if (track->mode == MODE_MOV) {
1249             avio_wb16(pb, track->par->ch_layout.nb_channels);
1250             if (track->par->codec_id == AV_CODEC_ID_PCM_U8 ||
1251                 track->par->codec_id == AV_CODEC_ID_PCM_S8)
1252                 avio_wb16(pb, 8); /* bits per sample */
1253             else if (track->par->codec_id == AV_CODEC_ID_ADPCM_G726)
1254                 avio_wb16(pb, track->par->bits_per_coded_sample);
1255             else
1256                 avio_wb16(pb, 16);
1257             avio_wb16(pb, track->audio_vbr ? -2 : 0); /* compression ID */
1258         } else { /* reserved for mp4/3gp */
1259             if (track->par->codec_id == AV_CODEC_ID_FLAC ||
1260                 track->par->codec_id == AV_CODEC_ID_ALAC ||
1261                 track->par->codec_id == AV_CODEC_ID_OPUS) {
1262                 avio_wb16(pb, track->par->ch_layout.nb_channels);
1263             } else {
1264                 avio_wb16(pb, 2);
1265             }
1266             if (track->par->codec_id == AV_CODEC_ID_FLAC ||
1267                 track->par->codec_id == AV_CODEC_ID_ALAC) {
1268                 avio_wb16(pb, track->par->bits_per_raw_sample);
1269             } else {
1270                 avio_wb16(pb, 16);
1271             }
1272             avio_wb16(pb, 0);
1273         }
1274 
1275         avio_wb16(pb, 0); /* packet size (= 0) */
1276         if (track->par->codec_id == AV_CODEC_ID_OPUS)
1277             avio_wb16(pb, 48000);
1278         else if (track->par->codec_id == AV_CODEC_ID_TRUEHD)
1279             avio_wb32(pb, track->par->sample_rate);
1280         else
1281             avio_wb16(pb, track->par->sample_rate <= UINT16_MAX ?
1282                           track->par->sample_rate : 0);
1283 
1284         if (track->par->codec_id != AV_CODEC_ID_TRUEHD)
1285             avio_wb16(pb, 0); /* Reserved */
1286     }
1287 
1288     if (version == 1) { /* SoundDescription V1 extended info */
1289         if (mov_pcm_le_gt16(track->par->codec_id) ||
1290             mov_pcm_be_gt16(track->par->codec_id))
1291             avio_wb32(pb, 1); /*  must be 1 for  uncompressed formats */
1292         else
1293             avio_wb32(pb, track->par->frame_size); /* Samples per packet */
1294         avio_wb32(pb, track->sample_size / track->par->ch_layout.nb_channels); /* Bytes per packet */
1295         avio_wb32(pb, track->sample_size); /* Bytes per frame */
1296         avio_wb32(pb, 2); /* Bytes per sample */
1297     }
1298 
1299     if (track->mode == MODE_MOV &&
1300         (track->par->codec_id == AV_CODEC_ID_AAC           ||
1301          track->par->codec_id == AV_CODEC_ID_AC3           ||
1302          track->par->codec_id == AV_CODEC_ID_EAC3          ||
1303          track->par->codec_id == AV_CODEC_ID_AMR_NB        ||
1304          track->par->codec_id == AV_CODEC_ID_ALAC          ||
1305          track->par->codec_id == AV_CODEC_ID_ADPCM_MS      ||
1306          track->par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV ||
1307          track->par->codec_id == AV_CODEC_ID_QDM2          ||
1308          (mov_pcm_le_gt16(track->par->codec_id) && version==1) ||
1309          (mov_pcm_be_gt16(track->par->codec_id) && version==1)))
1310         ret = mov_write_wave_tag(s, pb, track);
1311     else if (track->tag == MKTAG('m','p','4','a'))
1312         ret = mov_write_esds_tag(pb, track);
1313     else if (track->par->codec_id == AV_CODEC_ID_AMR_NB)
1314         ret = mov_write_amr_tag(pb, track);
1315     else if (track->par->codec_id == AV_CODEC_ID_AC3)
1316         ret = mov_write_ac3_tag(s, pb, track);
1317     else if (track->par->codec_id == AV_CODEC_ID_EAC3)
1318         ret = mov_write_eac3_tag(s, pb, track);
1319     else if (track->par->codec_id == AV_CODEC_ID_ALAC)
1320         ret = mov_write_extradata_tag(pb, track);
1321     else if (track->par->codec_id == AV_CODEC_ID_WMAPRO)
1322         ret = mov_write_wfex_tag(s, pb, track);
1323     else if (track->par->codec_id == AV_CODEC_ID_FLAC)
1324         ret = mov_write_dfla_tag(pb, track);
1325     else if (track->par->codec_id == AV_CODEC_ID_OPUS)
1326         ret = mov_write_dops_tag(s, pb, track);
1327     else if (track->par->codec_id == AV_CODEC_ID_TRUEHD)
1328         ret = mov_write_dmlp_tag(s, pb, track);
1329     else if (track->vos_len > 0)
1330         ret = mov_write_glbl_tag(pb, track);
1331 
1332     if (ret < 0)
1333         return ret;
1334 
1335     if (track->mode == MODE_MOV && track->par->codec_type == AVMEDIA_TYPE_AUDIO
1336             && ((ret = mov_write_chan_tag(s, pb, track)) < 0)) {
1337         return ret;
1338     }
1339 
1340     if (mov->encryption_scheme != MOV_ENC_NONE
1341             && ((ret = ff_mov_cenc_write_sinf_tag(track, pb, mov->encryption_kid)) < 0)) {
1342         return ret;
1343     }
1344 
1345     if (mov->write_btrt &&
1346             ((ret = mov_write_btrt_tag(pb, track)) < 0))
1347         return ret;
1348 
1349     ret = update_size(pb, pos);
1350     return ret;
1351 }
1352 
mov_write_d263_tag(AVIOContext *pb)1353 static int mov_write_d263_tag(AVIOContext *pb)
1354 {
1355     avio_wb32(pb, 0xf); /* size */
1356     ffio_wfourcc(pb, "d263");
1357     ffio_wfourcc(pb, "FFMP");
1358     avio_w8(pb, 0); /* decoder version */
1359     /* FIXME use AVCodecContext level/profile, when encoder will set values */
1360     avio_w8(pb, 0xa); /* level */
1361     avio_w8(pb, 0); /* profile */
1362     return 0xf;
1363 }
1364 
mov_write_av1c_tag(AVIOContext *pb, MOVTrack *track)1365 static int mov_write_av1c_tag(AVIOContext *pb, MOVTrack *track)
1366 {
1367     int64_t pos = avio_tell(pb);
1368 
1369     avio_wb32(pb, 0);
1370     ffio_wfourcc(pb, "av1C");
1371     ff_isom_write_av1c(pb, track->vos_data, track->vos_len, track->mode != MODE_AVIF);
1372     return update_size(pb, pos);
1373 }
1374 
mov_write_avcc_tag(AVIOContext *pb, MOVTrack *track)1375 static int mov_write_avcc_tag(AVIOContext *pb, MOVTrack *track)
1376 {
1377     int64_t pos = avio_tell(pb);
1378 
1379     avio_wb32(pb, 0);
1380     ffio_wfourcc(pb, "avcC");
1381     ff_isom_write_avcc(pb, track->vos_data, track->vos_len);
1382     return update_size(pb, pos);
1383 }
1384 
mov_write_vpcc_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)1385 static int mov_write_vpcc_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
1386 {
1387     int64_t pos = avio_tell(pb);
1388 
1389     avio_wb32(pb, 0);
1390     ffio_wfourcc(pb, "vpcC");
1391     avio_w8(pb, 1); /* version */
1392     avio_wb24(pb, 0); /* flags */
1393     ff_isom_write_vpcc(s, pb, track->par);
1394     return update_size(pb, pos);
1395 }
1396 
mov_write_hvcc_tag(AVIOContext *pb, MOVTrack *track)1397 static int mov_write_hvcc_tag(AVIOContext *pb, MOVTrack *track)
1398 {
1399     int64_t pos = avio_tell(pb);
1400 
1401     avio_wb32(pb, 0);
1402     ffio_wfourcc(pb, "hvcC");
1403     if (track->tag == MKTAG('h','v','c','1'))
1404         ff_isom_write_hvcc(pb, track->vos_data, track->vos_len, 1);
1405     else
1406         ff_isom_write_hvcc(pb, track->vos_data, track->vos_len, 0);
1407     return update_size(pb, pos);
1408 }
1409 
1410 /* also used by all avid codecs (dv, imx, meridien) and their variants */
mov_write_avid_tag(AVIOContext *pb, MOVTrack *track)1411 static int mov_write_avid_tag(AVIOContext *pb, MOVTrack *track)
1412 {
1413     int interlaced;
1414     int cid;
1415     int display_width = track->par->width;
1416 
1417     if (track->vos_data && track->vos_len > 0x29) {
1418         if (ff_dnxhd_parse_header_prefix(track->vos_data) != 0) {
1419             /* looks like a DNxHD bit stream */
1420             interlaced = (track->vos_data[5] & 2);
1421             cid = AV_RB32(track->vos_data + 0x28);
1422         } else {
1423             av_log(NULL, AV_LOG_WARNING, "Could not locate DNxHD bit stream in vos_data\n");
1424             return 0;
1425         }
1426     } else {
1427         av_log(NULL, AV_LOG_WARNING, "Could not locate DNxHD bit stream, vos_data too small\n");
1428         return 0;
1429     }
1430 
1431     avio_wb32(pb, 24); /* size */
1432     ffio_wfourcc(pb, "ACLR");
1433     ffio_wfourcc(pb, "ACLR");
1434     ffio_wfourcc(pb, "0001");
1435     if (track->par->color_range == AVCOL_RANGE_MPEG || /* Legal range (16-235) */
1436         track->par->color_range == AVCOL_RANGE_UNSPECIFIED) {
1437         avio_wb32(pb, 1); /* Corresponds to 709 in official encoder */
1438     } else { /* Full range (0-255) */
1439         avio_wb32(pb, 2); /* Corresponds to RGB in official encoder */
1440     }
1441     avio_wb32(pb, 0); /* unknown */
1442 
1443     if (track->tag == MKTAG('A','V','d','h')) {
1444         avio_wb32(pb, 32);
1445         ffio_wfourcc(pb, "ADHR");
1446         ffio_wfourcc(pb, "0001");
1447         avio_wb32(pb, cid);
1448         avio_wb32(pb, 0); /* unknown */
1449         avio_wb32(pb, 1); /* unknown */
1450         avio_wb32(pb, 0); /* unknown */
1451         avio_wb32(pb, 0); /* unknown */
1452         return 0;
1453     }
1454 
1455     avio_wb32(pb, 24); /* size */
1456     ffio_wfourcc(pb, "APRG");
1457     ffio_wfourcc(pb, "APRG");
1458     ffio_wfourcc(pb, "0001");
1459     avio_wb32(pb, 1); /* unknown */
1460     avio_wb32(pb, 0); /* unknown */
1461 
1462     avio_wb32(pb, 120); /* size */
1463     ffio_wfourcc(pb, "ARES");
1464     ffio_wfourcc(pb, "ARES");
1465     ffio_wfourcc(pb, "0001");
1466     avio_wb32(pb, cid); /* dnxhd cid, some id ? */
1467     if (   track->par->sample_aspect_ratio.num > 0
1468         && track->par->sample_aspect_ratio.den > 0)
1469         display_width = display_width * track->par->sample_aspect_ratio.num / track->par->sample_aspect_ratio.den;
1470     avio_wb32(pb, display_width);
1471     /* values below are based on samples created with quicktime and avid codecs */
1472     if (interlaced) {
1473         avio_wb32(pb, track->par->height / 2);
1474         avio_wb32(pb, 2); /* unknown */
1475         avio_wb32(pb, 0); /* unknown */
1476         avio_wb32(pb, 4); /* unknown */
1477     } else {
1478         avio_wb32(pb, track->par->height);
1479         avio_wb32(pb, 1); /* unknown */
1480         avio_wb32(pb, 0); /* unknown */
1481         if (track->par->height == 1080)
1482             avio_wb32(pb, 5); /* unknown */
1483         else
1484             avio_wb32(pb, 6); /* unknown */
1485     }
1486     /* padding */
1487     ffio_fill(pb, 0, 10 * 8);
1488 
1489     return 0;
1490 }
1491 
mov_write_dpxe_tag(AVIOContext *pb, MOVTrack *track)1492 static int mov_write_dpxe_tag(AVIOContext *pb, MOVTrack *track)
1493 {
1494     avio_wb32(pb, 12);
1495     ffio_wfourcc(pb, "DpxE");
1496     if (track->par->extradata_size >= 12 &&
1497         !memcmp(&track->par->extradata[4], "DpxE", 4)) {
1498         avio_wb32(pb, track->par->extradata[11]);
1499     } else {
1500         avio_wb32(pb, 1);
1501     }
1502     return 0;
1503 }
1504 
mov_get_dv_codec_tag(AVFormatContext *s, MOVTrack *track)1505 static int mov_get_dv_codec_tag(AVFormatContext *s, MOVTrack *track)
1506 {
1507     int tag;
1508 
1509     if (track->par->width == 720) { /* SD */
1510         if (track->par->height == 480) { /* NTSC */
1511             if  (track->par->format == AV_PIX_FMT_YUV422P) tag = MKTAG('d','v','5','n');
1512             else                                            tag = MKTAG('d','v','c',' ');
1513        }else if (track->par->format == AV_PIX_FMT_YUV422P) tag = MKTAG('d','v','5','p');
1514         else if (track->par->format == AV_PIX_FMT_YUV420P) tag = MKTAG('d','v','c','p');
1515         else                                                tag = MKTAG('d','v','p','p');
1516     } else if (track->par->height == 720) { /* HD 720 line */
1517         if  (track->st->time_base.den == 50)                tag = MKTAG('d','v','h','q');
1518         else                                                tag = MKTAG('d','v','h','p');
1519     } else if (track->par->height == 1080) { /* HD 1080 line */
1520         if  (track->st->time_base.den == 25)                tag = MKTAG('d','v','h','5');
1521         else                                                tag = MKTAG('d','v','h','6');
1522     } else {
1523         av_log(s, AV_LOG_ERROR, "unsupported height for dv codec\n");
1524         return 0;
1525     }
1526 
1527     return tag;
1528 }
1529 
defined_frame_rate(AVFormatContext *s, AVStream *st)1530 static int defined_frame_rate(AVFormatContext *s, AVStream *st)
1531 {
1532     AVRational rational_framerate = st->avg_frame_rate;
1533     int rate = 0;
1534     if (rational_framerate.den != 0)
1535         rate = av_q2d(rational_framerate);
1536     return rate;
1537 }
1538 
mov_get_mpeg2_xdcam_codec_tag(AVFormatContext *s, MOVTrack *track)1539 static int mov_get_mpeg2_xdcam_codec_tag(AVFormatContext *s, MOVTrack *track)
1540 {
1541     int tag = track->par->codec_tag;
1542     int interlaced = track->par->field_order > AV_FIELD_PROGRESSIVE;
1543     AVStream *st = track->st;
1544     int rate = defined_frame_rate(s, st);
1545 
1546     if (!tag)
1547         tag = MKTAG('m', '2', 'v', '1'); //fallback tag
1548 
1549     if (track->par->format == AV_PIX_FMT_YUV420P) {
1550         if (track->par->width == 1280 && track->par->height == 720) {
1551             if (!interlaced) {
1552                 if      (rate == 24) tag = MKTAG('x','d','v','4');
1553                 else if (rate == 25) tag = MKTAG('x','d','v','5');
1554                 else if (rate == 30) tag = MKTAG('x','d','v','1');
1555                 else if (rate == 50) tag = MKTAG('x','d','v','a');
1556                 else if (rate == 60) tag = MKTAG('x','d','v','9');
1557             }
1558         } else if (track->par->width == 1440 && track->par->height == 1080) {
1559             if (!interlaced) {
1560                 if      (rate == 24) tag = MKTAG('x','d','v','6');
1561                 else if (rate == 25) tag = MKTAG('x','d','v','7');
1562                 else if (rate == 30) tag = MKTAG('x','d','v','8');
1563             } else {
1564                 if      (rate == 25) tag = MKTAG('x','d','v','3');
1565                 else if (rate == 30) tag = MKTAG('x','d','v','2');
1566             }
1567         } else if (track->par->width == 1920 && track->par->height == 1080) {
1568             if (!interlaced) {
1569                 if      (rate == 24) tag = MKTAG('x','d','v','d');
1570                 else if (rate == 25) tag = MKTAG('x','d','v','e');
1571                 else if (rate == 30) tag = MKTAG('x','d','v','f');
1572             } else {
1573                 if      (rate == 25) tag = MKTAG('x','d','v','c');
1574                 else if (rate == 30) tag = MKTAG('x','d','v','b');
1575             }
1576         }
1577     } else if (track->par->format == AV_PIX_FMT_YUV422P) {
1578         if (track->par->width == 1280 && track->par->height == 720) {
1579             if (!interlaced) {
1580                 if      (rate == 24) tag = MKTAG('x','d','5','4');
1581                 else if (rate == 25) tag = MKTAG('x','d','5','5');
1582                 else if (rate == 30) tag = MKTAG('x','d','5','1');
1583                 else if (rate == 50) tag = MKTAG('x','d','5','a');
1584                 else if (rate == 60) tag = MKTAG('x','d','5','9');
1585             }
1586         } else if (track->par->width == 1920 && track->par->height == 1080) {
1587             if (!interlaced) {
1588                 if      (rate == 24) tag = MKTAG('x','d','5','d');
1589                 else if (rate == 25) tag = MKTAG('x','d','5','e');
1590                 else if (rate == 30) tag = MKTAG('x','d','5','f');
1591             } else {
1592                 if      (rate == 25) tag = MKTAG('x','d','5','c');
1593                 else if (rate == 30) tag = MKTAG('x','d','5','b');
1594             }
1595         }
1596     }
1597 
1598     return tag;
1599 }
1600 
mov_get_h264_codec_tag(AVFormatContext *s, MOVTrack *track)1601 static int mov_get_h264_codec_tag(AVFormatContext *s, MOVTrack *track)
1602 {
1603     int tag = track->par->codec_tag;
1604     int interlaced = track->par->field_order > AV_FIELD_PROGRESSIVE;
1605     AVStream *st = track->st;
1606     int rate = defined_frame_rate(s, st);
1607 
1608     if (!tag)
1609         tag = MKTAG('a', 'v', 'c', 'i'); //fallback tag
1610 
1611     if (track->par->format == AV_PIX_FMT_YUV420P10) {
1612         if (track->par->width == 960 && track->par->height == 720) {
1613             if (!interlaced) {
1614                 if      (rate == 24) tag = MKTAG('a','i','5','p');
1615                 else if (rate == 25) tag = MKTAG('a','i','5','q');
1616                 else if (rate == 30) tag = MKTAG('a','i','5','p');
1617                 else if (rate == 50) tag = MKTAG('a','i','5','q');
1618                 else if (rate == 60) tag = MKTAG('a','i','5','p');
1619             }
1620         } else if (track->par->width == 1440 && track->par->height == 1080) {
1621             if (!interlaced) {
1622                 if      (rate == 24) tag = MKTAG('a','i','5','3');
1623                 else if (rate == 25) tag = MKTAG('a','i','5','2');
1624                 else if (rate == 30) tag = MKTAG('a','i','5','3');
1625             } else {
1626                 if      (rate == 50) tag = MKTAG('a','i','5','5');
1627                 else if (rate == 60) tag = MKTAG('a','i','5','6');
1628             }
1629         }
1630     } else if (track->par->format == AV_PIX_FMT_YUV422P10) {
1631         if (track->par->width == 1280 && track->par->height == 720) {
1632             if (!interlaced) {
1633                 if      (rate == 24) tag = MKTAG('a','i','1','p');
1634                 else if (rate == 25) tag = MKTAG('a','i','1','q');
1635                 else if (rate == 30) tag = MKTAG('a','i','1','p');
1636                 else if (rate == 50) tag = MKTAG('a','i','1','q');
1637                 else if (rate == 60) tag = MKTAG('a','i','1','p');
1638             }
1639         } else if (track->par->width == 1920 && track->par->height == 1080) {
1640             if (!interlaced) {
1641                 if      (rate == 24) tag = MKTAG('a','i','1','3');
1642                 else if (rate == 25) tag = MKTAG('a','i','1','2');
1643                 else if (rate == 30) tag = MKTAG('a','i','1','3');
1644             } else {
1645                 if      (rate == 25) tag = MKTAG('a','i','1','5');
1646                 else if (rate == 50) tag = MKTAG('a','i','1','5');
1647                 else if (rate == 60) tag = MKTAG('a','i','1','6');
1648             }
1649         } else if (   track->par->width == 4096 && track->par->height == 2160
1650                    || track->par->width == 3840 && track->par->height == 2160
1651                    || track->par->width == 2048 && track->par->height == 1080) {
1652             tag = MKTAG('a','i','v','x');
1653         }
1654     }
1655 
1656     return tag;
1657 }
1658 
1659 static const struct {
1660     enum AVPixelFormat pix_fmt;
1661     uint32_t tag;
1662     unsigned bps;
1663 } mov_pix_fmt_tags[] = {
1664     { AV_PIX_FMT_YUYV422, MKTAG('y','u','v','2'),  0 },
1665     { AV_PIX_FMT_YUYV422, MKTAG('y','u','v','s'),  0 },
1666     { AV_PIX_FMT_UYVY422, MKTAG('2','v','u','y'),  0 },
1667     { AV_PIX_FMT_RGB555BE,MKTAG('r','a','w',' '), 16 },
1668     { AV_PIX_FMT_RGB555LE,MKTAG('L','5','5','5'), 16 },
1669     { AV_PIX_FMT_RGB565LE,MKTAG('L','5','6','5'), 16 },
1670     { AV_PIX_FMT_RGB565BE,MKTAG('B','5','6','5'), 16 },
1671     { AV_PIX_FMT_GRAY16BE,MKTAG('b','1','6','g'), 16 },
1672     { AV_PIX_FMT_RGB24,   MKTAG('r','a','w',' '), 24 },
1673     { AV_PIX_FMT_BGR24,   MKTAG('2','4','B','G'), 24 },
1674     { AV_PIX_FMT_ARGB,    MKTAG('r','a','w',' '), 32 },
1675     { AV_PIX_FMT_BGRA,    MKTAG('B','G','R','A'), 32 },
1676     { AV_PIX_FMT_RGBA,    MKTAG('R','G','B','A'), 32 },
1677     { AV_PIX_FMT_ABGR,    MKTAG('A','B','G','R'), 32 },
1678     { AV_PIX_FMT_RGB48BE, MKTAG('b','4','8','r'), 48 },
1679 };
1680 
mov_get_dnxhd_codec_tag(AVFormatContext *s, MOVTrack *track)1681 static int mov_get_dnxhd_codec_tag(AVFormatContext *s, MOVTrack *track)
1682 {
1683   int tag = MKTAG('A','V','d','n');
1684   if (track->par->profile != FF_PROFILE_UNKNOWN &&
1685       track->par->profile != FF_PROFILE_DNXHD)
1686       tag = MKTAG('A','V','d','h');
1687   return tag;
1688 }
1689 
mov_get_rawvideo_codec_tag(AVFormatContext *s, MOVTrack *track)1690 static int mov_get_rawvideo_codec_tag(AVFormatContext *s, MOVTrack *track)
1691 {
1692     int tag = track->par->codec_tag;
1693     int i;
1694     enum AVPixelFormat pix_fmt;
1695 
1696     for (i = 0; i < FF_ARRAY_ELEMS(mov_pix_fmt_tags); i++) {
1697         if (track->par->format == mov_pix_fmt_tags[i].pix_fmt) {
1698             tag = mov_pix_fmt_tags[i].tag;
1699             track->par->bits_per_coded_sample = mov_pix_fmt_tags[i].bps;
1700             if (track->par->codec_tag == mov_pix_fmt_tags[i].tag)
1701                 break;
1702         }
1703     }
1704 
1705     pix_fmt = avpriv_pix_fmt_find(PIX_FMT_LIST_MOV,
1706                                   track->par->bits_per_coded_sample);
1707     if (tag == MKTAG('r','a','w',' ') &&
1708         track->par->format != pix_fmt &&
1709         track->par->format != AV_PIX_FMT_GRAY8 &&
1710         track->par->format != AV_PIX_FMT_NONE)
1711         av_log(s, AV_LOG_ERROR, "%s rawvideo cannot be written to mov, output file will be unreadable\n",
1712                av_get_pix_fmt_name(track->par->format));
1713     return tag;
1714 }
1715 
mov_get_codec_tag(AVFormatContext *s, MOVTrack *track)1716 static unsigned int mov_get_codec_tag(AVFormatContext *s, MOVTrack *track)
1717 {
1718     unsigned int tag = track->par->codec_tag;
1719 
1720     // "rtp " is used to distinguish internally created RTP-hint tracks
1721     // (with rtp_ctx) from other tracks.
1722     if (tag == MKTAG('r','t','p',' '))
1723         tag = 0;
1724     if (!tag || (s->strict_std_compliance >= FF_COMPLIANCE_NORMAL &&
1725                  (track->par->codec_id == AV_CODEC_ID_DVVIDEO ||
1726                   track->par->codec_id == AV_CODEC_ID_RAWVIDEO ||
1727                   track->par->codec_id == AV_CODEC_ID_H263 ||
1728                   track->par->codec_id == AV_CODEC_ID_H264 ||
1729                   track->par->codec_id == AV_CODEC_ID_DNXHD ||
1730                   track->par->codec_id == AV_CODEC_ID_MPEG2VIDEO ||
1731                   av_get_bits_per_sample(track->par->codec_id)))) { // pcm audio
1732         if (track->par->codec_id == AV_CODEC_ID_DVVIDEO)
1733             tag = mov_get_dv_codec_tag(s, track);
1734         else if (track->par->codec_id == AV_CODEC_ID_RAWVIDEO)
1735             tag = mov_get_rawvideo_codec_tag(s, track);
1736         else if (track->par->codec_id == AV_CODEC_ID_MPEG2VIDEO)
1737             tag = mov_get_mpeg2_xdcam_codec_tag(s, track);
1738         else if (track->par->codec_id == AV_CODEC_ID_H264)
1739             tag = mov_get_h264_codec_tag(s, track);
1740         else if (track->par->codec_id == AV_CODEC_ID_DNXHD)
1741             tag = mov_get_dnxhd_codec_tag(s, track);
1742         else if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
1743             tag = ff_codec_get_tag(ff_codec_movvideo_tags, track->par->codec_id);
1744             if (!tag) { // if no mac fcc found, try with Microsoft tags
1745                 tag = ff_codec_get_tag(ff_codec_bmp_tags, track->par->codec_id);
1746                 if (tag)
1747                     av_log(s, AV_LOG_WARNING, "Using MS style video codec tag, "
1748                            "the file may be unplayable!\n");
1749             }
1750         } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) {
1751             tag = ff_codec_get_tag(ff_codec_movaudio_tags, track->par->codec_id);
1752             if (!tag) { // if no mac fcc found, try with Microsoft tags
1753                 int ms_tag = ff_codec_get_tag(ff_codec_wav_tags, track->par->codec_id);
1754                 if (ms_tag) {
1755                     tag = MKTAG('m', 's', ((ms_tag >> 8) & 0xff), (ms_tag & 0xff));
1756                     av_log(s, AV_LOG_WARNING, "Using MS style audio codec tag, "
1757                            "the file may be unplayable!\n");
1758                 }
1759             }
1760         } else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE)
1761             tag = ff_codec_get_tag(ff_codec_movsubtitle_tags, track->par->codec_id);
1762     }
1763 
1764     return tag;
1765 }
1766 
1767 static const AVCodecTag codec_cover_image_tags[] = {
1768     { AV_CODEC_ID_MJPEG,  0xD },
1769     { AV_CODEC_ID_PNG,    0xE },
1770     { AV_CODEC_ID_BMP,    0x1B },
1771     { AV_CODEC_ID_NONE, 0 },
1772 };
1773 
validate_codec_tag(const AVCodecTag *const *tags, unsigned int tag, int codec_id)1774 static unsigned int validate_codec_tag(const AVCodecTag *const *tags,
1775                                        unsigned int tag, int codec_id)
1776 {
1777     int i;
1778 
1779     /**
1780      * Check that tag + id is in the table
1781      */
1782     for (i = 0; tags && tags[i]; i++) {
1783         const AVCodecTag *codec_tags = tags[i];
1784         while (codec_tags->id != AV_CODEC_ID_NONE) {
1785             if (ff_toupper4(codec_tags->tag) == ff_toupper4(tag) &&
1786                 codec_tags->id == codec_id)
1787                 return codec_tags->tag;
1788             codec_tags++;
1789         }
1790     }
1791     return 0;
1792 }
1793 
mov_find_codec_tag(AVFormatContext *s, MOVTrack *track)1794 static unsigned int mov_find_codec_tag(AVFormatContext *s, MOVTrack *track)
1795 {
1796     if (is_cover_image(track->st))
1797         return ff_codec_get_tag(codec_cover_image_tags, track->par->codec_id);
1798 
1799     if (track->mode == MODE_IPOD)
1800         if (!av_match_ext(s->url, "m4a") &&
1801             !av_match_ext(s->url, "m4v") &&
1802             !av_match_ext(s->url, "m4b"))
1803             av_log(s, AV_LOG_WARNING, "Warning, extension is not .m4a nor .m4v "
1804                    "Quicktime/Ipod might not play the file\n");
1805 
1806     if (track->mode == MODE_MOV) {
1807         return mov_get_codec_tag(s, track);
1808     } else
1809         return validate_codec_tag(s->oformat->codec_tag, track->par->codec_tag,
1810                                   track->par->codec_id);
1811 }
1812 
1813 /** Write uuid atom.
1814  * Needed to make file play in iPods running newest firmware
1815  * goes after avcC atom in moov.trak.mdia.minf.stbl.stsd.avc1
1816  */
mov_write_uuid_tag_ipod(AVIOContext *pb)1817 static int mov_write_uuid_tag_ipod(AVIOContext *pb)
1818 {
1819     avio_wb32(pb, 28);
1820     ffio_wfourcc(pb, "uuid");
1821     avio_wb32(pb, 0x6b6840f2);
1822     avio_wb32(pb, 0x5f244fc5);
1823     avio_wb32(pb, 0xba39a51b);
1824     avio_wb32(pb, 0xcf0323f3);
1825     avio_wb32(pb, 0x0);
1826     return 28;
1827 }
1828 
1829 static const uint16_t fiel_data[] = {
1830     0x0000, 0x0100, 0x0201, 0x0206, 0x0209, 0x020e
1831 };
1832 
mov_write_fiel_tag(AVIOContext *pb, MOVTrack *track, int field_order)1833 static int mov_write_fiel_tag(AVIOContext *pb, MOVTrack *track, int field_order)
1834 {
1835     unsigned mov_field_order = 0;
1836     if (field_order < FF_ARRAY_ELEMS(fiel_data))
1837         mov_field_order = fiel_data[field_order];
1838     else
1839         return 0;
1840     avio_wb32(pb, 10);
1841     ffio_wfourcc(pb, "fiel");
1842     avio_wb16(pb, mov_field_order);
1843     return 10;
1844 }
1845 
mov_write_subtitle_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)1846 static int mov_write_subtitle_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
1847 {
1848     MOVMuxContext *mov = s->priv_data;
1849     int ret = AVERROR_BUG;
1850     int64_t pos = avio_tell(pb);
1851     avio_wb32(pb, 0);    /* size */
1852     avio_wl32(pb, track->tag); // store it byteswapped
1853     avio_wb32(pb, 0);    /* Reserved */
1854     avio_wb16(pb, 0);    /* Reserved */
1855     avio_wb16(pb, 1);    /* Data-reference index */
1856 
1857     if (track->par->codec_id == AV_CODEC_ID_DVD_SUBTITLE)
1858         mov_write_esds_tag(pb, track);
1859     else if (track->par->codec_id == AV_CODEC_ID_TTML) {
1860         switch (track->par->codec_tag) {
1861         case MOV_ISMV_TTML_TAG:
1862             // ISMV dfxp requires no extradata.
1863             break;
1864         case MOV_MP4_TTML_TAG:
1865             // As specified in 14496-30, XMLSubtitleSampleEntry
1866             // Namespace
1867             avio_put_str(pb, "http://www.w3.org/ns/ttml");
1868             // Empty schema_location
1869             avio_w8(pb, 0);
1870             // Empty auxiliary_mime_types
1871             avio_w8(pb, 0);
1872             break;
1873         default:
1874             av_log(NULL, AV_LOG_ERROR,
1875                    "Unknown codec tag '%s' utilized for TTML stream with "
1876                    "index %d (track id %d)!\n",
1877                    av_fourcc2str(track->par->codec_tag), track->st->index,
1878                    track->track_id);
1879             return AVERROR(EINVAL);
1880         }
1881     } else if (track->par->extradata_size)
1882         avio_write(pb, track->par->extradata, track->par->extradata_size);
1883 
1884     if (mov->write_btrt &&
1885             ((ret = mov_write_btrt_tag(pb, track)) < 0))
1886         return ret;
1887 
1888     return update_size(pb, pos);
1889 }
1890 
mov_write_st3d_tag(AVFormatContext *s, AVIOContext *pb, AVStereo3D *stereo_3d)1891 static int mov_write_st3d_tag(AVFormatContext *s, AVIOContext *pb, AVStereo3D *stereo_3d)
1892 {
1893     int8_t stereo_mode;
1894 
1895     if (stereo_3d->flags != 0) {
1896         av_log(s, AV_LOG_WARNING, "Unsupported stereo_3d flags %x. st3d not written.\n", stereo_3d->flags);
1897         return 0;
1898     }
1899 
1900     switch (stereo_3d->type) {
1901     case AV_STEREO3D_2D:
1902         stereo_mode = 0;
1903         break;
1904     case AV_STEREO3D_TOPBOTTOM:
1905         stereo_mode = 1;
1906         break;
1907     case AV_STEREO3D_SIDEBYSIDE:
1908         stereo_mode = 2;
1909         break;
1910     default:
1911         av_log(s, AV_LOG_WARNING, "Unsupported stereo_3d type %s. st3d not written.\n", av_stereo3d_type_name(stereo_3d->type));
1912         return 0;
1913     }
1914     avio_wb32(pb, 13); /* size */
1915     ffio_wfourcc(pb, "st3d");
1916     avio_wb32(pb, 0); /* version = 0 & flags = 0 */
1917     avio_w8(pb, stereo_mode);
1918     return 13;
1919 }
1920 
mov_write_sv3d_tag(AVFormatContext *s, AVIOContext *pb, AVSphericalMapping *spherical_mapping)1921 static int mov_write_sv3d_tag(AVFormatContext *s, AVIOContext *pb, AVSphericalMapping *spherical_mapping)
1922 {
1923     int64_t sv3d_pos, svhd_pos, proj_pos;
1924     const char* metadata_source = s->flags & AVFMT_FLAG_BITEXACT ? "Lavf" : LIBAVFORMAT_IDENT;
1925 
1926     if (spherical_mapping->projection != AV_SPHERICAL_EQUIRECTANGULAR &&
1927         spherical_mapping->projection != AV_SPHERICAL_EQUIRECTANGULAR_TILE &&
1928         spherical_mapping->projection != AV_SPHERICAL_CUBEMAP) {
1929         av_log(s, AV_LOG_WARNING, "Unsupported projection %d. sv3d not written.\n", spherical_mapping->projection);
1930         return 0;
1931     }
1932 
1933     sv3d_pos = avio_tell(pb);
1934     avio_wb32(pb, 0);  /* size */
1935     ffio_wfourcc(pb, "sv3d");
1936 
1937     svhd_pos = avio_tell(pb);
1938     avio_wb32(pb, 0);  /* size */
1939     ffio_wfourcc(pb, "svhd");
1940     avio_wb32(pb, 0); /* version = 0 & flags = 0 */
1941     avio_put_str(pb, metadata_source);
1942     update_size(pb, svhd_pos);
1943 
1944     proj_pos = avio_tell(pb);
1945     avio_wb32(pb, 0); /* size */
1946     ffio_wfourcc(pb, "proj");
1947 
1948     avio_wb32(pb, 24); /* size */
1949     ffio_wfourcc(pb, "prhd");
1950     avio_wb32(pb, 0); /* version = 0 & flags = 0 */
1951     avio_wb32(pb, spherical_mapping->yaw);
1952     avio_wb32(pb, spherical_mapping->pitch);
1953     avio_wb32(pb, spherical_mapping->roll);
1954 
1955     switch (spherical_mapping->projection) {
1956     case AV_SPHERICAL_EQUIRECTANGULAR:
1957     case AV_SPHERICAL_EQUIRECTANGULAR_TILE:
1958         avio_wb32(pb, 28);    /* size */
1959         ffio_wfourcc(pb, "equi");
1960         avio_wb32(pb, 0); /* version = 0 & flags = 0 */
1961         avio_wb32(pb, spherical_mapping->bound_top);
1962         avio_wb32(pb, spherical_mapping->bound_bottom);
1963         avio_wb32(pb, spherical_mapping->bound_left);
1964         avio_wb32(pb, spherical_mapping->bound_right);
1965         break;
1966     case AV_SPHERICAL_CUBEMAP:
1967         avio_wb32(pb, 20);    /* size */
1968         ffio_wfourcc(pb, "cbmp");
1969         avio_wb32(pb, 0); /* version = 0 & flags = 0 */
1970         avio_wb32(pb, 0); /* layout */
1971         avio_wb32(pb, spherical_mapping->padding); /* padding */
1972         break;
1973     }
1974     update_size(pb, proj_pos);
1975 
1976     return update_size(pb, sv3d_pos);
1977 }
1978 
mov_write_dvcc_dvvc_tag(AVFormatContext *s, AVIOContext *pb, AVDOVIDecoderConfigurationRecord *dovi)1979 static int mov_write_dvcc_dvvc_tag(AVFormatContext *s, AVIOContext *pb, AVDOVIDecoderConfigurationRecord *dovi)
1980 {
1981     uint8_t buf[ISOM_DVCC_DVVC_SIZE];
1982 
1983     avio_wb32(pb, 32); /* size = 8 + 24 */
1984     if (dovi->dv_profile > 10)
1985         ffio_wfourcc(pb, "dvwC");
1986     else if (dovi->dv_profile > 7)
1987         ffio_wfourcc(pb, "dvvC");
1988     else
1989         ffio_wfourcc(pb, "dvcC");
1990 
1991     ff_isom_put_dvcc_dvvc(s, buf, dovi);
1992     avio_write(pb, buf, sizeof(buf));
1993 
1994     return 32; /* 8 + 24 */
1995 }
1996 
mov_write_clap_tag(AVIOContext *pb, MOVTrack *track)1997 static int mov_write_clap_tag(AVIOContext *pb, MOVTrack *track)
1998 {
1999     avio_wb32(pb, 40);
2000     ffio_wfourcc(pb, "clap");
2001     avio_wb32(pb, track->par->width); /* apertureWidth_N */
2002     avio_wb32(pb, 1); /* apertureWidth_D (= 1) */
2003     avio_wb32(pb, track->height); /* apertureHeight_N */
2004     avio_wb32(pb, 1); /* apertureHeight_D (= 1) */
2005     avio_wb32(pb, 0); /* horizOff_N (= 0) */
2006     avio_wb32(pb, 1); /* horizOff_D (= 1) */
2007     avio_wb32(pb, 0); /* vertOff_N (= 0) */
2008     avio_wb32(pb, 1); /* vertOff_D (= 1) */
2009     return 40;
2010 }
2011 
mov_write_pasp_tag(AVIOContext *pb, MOVTrack *track)2012 static int mov_write_pasp_tag(AVIOContext *pb, MOVTrack *track)
2013 {
2014     AVRational sar;
2015     av_reduce(&sar.num, &sar.den, track->par->sample_aspect_ratio.num,
2016               track->par->sample_aspect_ratio.den, INT_MAX);
2017 
2018     avio_wb32(pb, 16);
2019     ffio_wfourcc(pb, "pasp");
2020     avio_wb32(pb, sar.num);
2021     avio_wb32(pb, sar.den);
2022     return 16;
2023 }
2024 
mov_write_gama_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track, double gamma)2025 static int mov_write_gama_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track, double gamma)
2026 {
2027     uint32_t gama = 0;
2028     if (gamma <= 0.0) {
2029         gamma = avpriv_get_gamma_from_trc(track->par->color_trc);
2030     }
2031     av_log(s, AV_LOG_DEBUG, "gamma value %g\n", gamma);
2032 
2033     if (gamma > 1e-6) {
2034         gama = (uint32_t)lrint((double)(1<<16) * gamma);
2035         av_log(s, AV_LOG_DEBUG, "writing gama value %"PRId32"\n", gama);
2036 
2037         av_assert0(track->mode == MODE_MOV);
2038         avio_wb32(pb, 12);
2039         ffio_wfourcc(pb, "gama");
2040         avio_wb32(pb, gama);
2041         return 12;
2042     } else {
2043         av_log(s, AV_LOG_WARNING, "gamma value unknown, unable to write gama atom\n");
2044     }
2045     return 0;
2046 }
2047 
mov_write_colr_tag(AVIOContext *pb, MOVTrack *track, int prefer_icc)2048 static int mov_write_colr_tag(AVIOContext *pb, MOVTrack *track, int prefer_icc)
2049 {
2050     int64_t pos = avio_tell(pb);
2051 
2052     // Ref (MOV): https://developer.apple.com/library/mac/technotes/tn2162/_index.html#//apple_ref/doc/uid/DTS40013070-CH1-TNTAG9
2053     // Ref (MP4): ISO/IEC 14496-12:2012
2054 
2055     const uint8_t *icc_profile;
2056     size_t icc_profile_size;
2057 
2058     if (prefer_icc) {
2059         icc_profile = av_stream_get_side_data(track->st, AV_PKT_DATA_ICC_PROFILE, &icc_profile_size);
2060 
2061         if (icc_profile) {
2062             avio_wb32(pb, 12 + icc_profile_size);
2063             ffio_wfourcc(pb, "colr");
2064             ffio_wfourcc(pb, "prof");
2065             avio_write(pb, icc_profile, icc_profile_size);
2066             return 12 + icc_profile_size;
2067         }
2068         else {
2069             av_log(NULL, AV_LOG_INFO, "no ICC profile found, will write nclx/nclc colour info instead\n");
2070         }
2071     }
2072 
2073     /* We should only ever be called for MOV, MP4 and AVIF. */
2074     av_assert0(track->mode == MODE_MOV || track->mode == MODE_MP4 ||
2075                track->mode == MODE_AVIF);
2076 
2077     avio_wb32(pb, 0); /* size */
2078     ffio_wfourcc(pb, "colr");
2079     if (track->mode == MODE_MP4 || track->mode == MODE_AVIF)
2080         ffio_wfourcc(pb, "nclx");
2081     else
2082         ffio_wfourcc(pb, "nclc");
2083     // Do not try to guess the color info if it is AVCOL_PRI_UNSPECIFIED.
2084     // e.g., Dolby Vision for Apple devices should be set to AVCOL_PRI_UNSPECIFIED. See
2085     // https://developer.apple.com/av-foundation/High-Dynamic-Range-Metadata-for-Apple-Devices.pdf
2086     avio_wb16(pb, track->par->color_primaries);
2087     avio_wb16(pb, track->par->color_trc);
2088     avio_wb16(pb, track->par->color_space);
2089     if (track->mode == MODE_MP4 || track->mode == MODE_AVIF) {
2090         int full_range = track->par->color_range == AVCOL_RANGE_JPEG;
2091         avio_w8(pb, full_range << 7);
2092     }
2093 
2094     return update_size(pb, pos);
2095 }
2096 
2097 #ifdef OHOS_HDR_VIVID
mov_write_cuvv_tag(AVIOContext *pb, CuvaConfig *cuva)2098 static int mov_write_cuvv_tag(AVIOContext *pb, CuvaConfig *cuva)
2099 {
2100     int64_t pos = avio_tell(pb);
2101     avio_wb32(pb, 0); /* size */
2102     ffio_wfourcc(pb, "cuvv");
2103     avio_wb16(pb, cuva->cuva_version_map);
2104     avio_wb16(pb, cuva->terminal_provide_code);
2105     avio_wb16(pb, cuva->terminal_provide_oriented_code);
2106     avio_wb32(pb, 0); // reserved
2107     avio_wb32(pb, 0); // reserved
2108     avio_wb32(pb, 0); // reserved
2109     avio_wb32(pb, 0); // reserved
2110     return update_size(pb, pos);
2111 }
2112 #endif
2113 
mov_write_clli_tag(AVIOContext *pb, MOVTrack *track)2114 static int mov_write_clli_tag(AVIOContext *pb, MOVTrack *track)
2115 {
2116     const uint8_t *side_data;
2117     const AVContentLightMetadata *content_light_metadata;
2118 
2119     side_data = av_stream_get_side_data(track->st, AV_PKT_DATA_CONTENT_LIGHT_LEVEL, NULL);
2120     if (!side_data) {
2121         return 0;
2122     }
2123     content_light_metadata = (const AVContentLightMetadata*)side_data;
2124 
2125     avio_wb32(pb, 12); // size
2126     ffio_wfourcc(pb, "clli");
2127     avio_wb16(pb, content_light_metadata->MaxCLL);
2128     avio_wb16(pb, content_light_metadata->MaxFALL);
2129     return 12;
2130 }
2131 
rescale_mdcv(AVRational q, int b)2132 static inline int64_t rescale_mdcv(AVRational q, int b)
2133 {
2134     return av_rescale(q.num, b, q.den);
2135 }
2136 
mov_write_mdcv_tag(AVIOContext *pb, MOVTrack *track)2137 static int mov_write_mdcv_tag(AVIOContext *pb, MOVTrack *track)
2138 {
2139     const int chroma_den = 50000;
2140     const int luma_den = 10000;
2141     const uint8_t *side_data;
2142     const AVMasteringDisplayMetadata *metadata;
2143 
2144     side_data = av_stream_get_side_data(track->st, AV_PKT_DATA_MASTERING_DISPLAY_METADATA, NULL);
2145     metadata = (const AVMasteringDisplayMetadata*)side_data;
2146     if (!metadata || !metadata->has_primaries || !metadata->has_luminance) {
2147         return 0;
2148     }
2149 
2150     avio_wb32(pb, 32); // size
2151     ffio_wfourcc(pb, "mdcv");
2152     avio_wb16(pb, rescale_mdcv(metadata->display_primaries[1][0], chroma_den));
2153     avio_wb16(pb, rescale_mdcv(metadata->display_primaries[1][1], chroma_den));
2154     avio_wb16(pb, rescale_mdcv(metadata->display_primaries[2][0], chroma_den));
2155     avio_wb16(pb, rescale_mdcv(metadata->display_primaries[2][1], chroma_den));
2156     avio_wb16(pb, rescale_mdcv(metadata->display_primaries[0][0], chroma_den));
2157     avio_wb16(pb, rescale_mdcv(metadata->display_primaries[0][1], chroma_den));
2158     avio_wb16(pb, rescale_mdcv(metadata->white_point[0], chroma_den));
2159     avio_wb16(pb, rescale_mdcv(metadata->white_point[1], chroma_den));
2160     avio_wb32(pb, rescale_mdcv(metadata->max_luminance, luma_den));
2161     avio_wb32(pb, rescale_mdcv(metadata->min_luminance, luma_den));
2162     return 32;
2163 }
2164 
find_compressor(char * compressor_name, int len, MOVTrack *track)2165 static void find_compressor(char * compressor_name, int len, MOVTrack *track)
2166 {
2167     AVDictionaryEntry *encoder;
2168     int xdcam_res =  (track->par->width == 1280 && track->par->height == 720)
2169                   || (track->par->width == 1440 && track->par->height == 1080)
2170                   || (track->par->width == 1920 && track->par->height == 1080);
2171 
2172     if ((track->mode == MODE_AVIF ||
2173          track->mode == MODE_MOV ||
2174          track->mode == MODE_MP4) &&
2175         (encoder = av_dict_get(track->st->metadata, "encoder", NULL, 0))) {
2176         av_strlcpy(compressor_name, encoder->value, 32);
2177     } else if (track->par->codec_id == AV_CODEC_ID_MPEG2VIDEO && xdcam_res) {
2178         int interlaced = track->par->field_order > AV_FIELD_PROGRESSIVE;
2179         AVStream *st = track->st;
2180         int rate = defined_frame_rate(NULL, st);
2181         av_strlcatf(compressor_name, len, "XDCAM");
2182         if (track->par->format == AV_PIX_FMT_YUV422P) {
2183             av_strlcatf(compressor_name, len, " HD422");
2184         } else if(track->par->width == 1440) {
2185             av_strlcatf(compressor_name, len, " HD");
2186         } else
2187             av_strlcatf(compressor_name, len, " EX");
2188 
2189         av_strlcatf(compressor_name, len, " %d%c", track->par->height, interlaced ? 'i' : 'p');
2190 
2191         av_strlcatf(compressor_name, len, "%d", rate * (interlaced + 1));
2192     }
2193 }
2194 
mov_write_ccst_tag(AVIOContext *pb)2195 static int mov_write_ccst_tag(AVIOContext *pb)
2196 {
2197     int64_t pos = avio_tell(pb);
2198     // Write sane defaults:
2199     // all_ref_pics_intra = 0 : all samples can use any type of reference.
2200     // intra_pred_used = 1 : intra prediction may or may not be used.
2201     // max_ref_per_pic = 15 : reserved value to indicate that any number of
2202     //                        reference images can be used.
2203     uint8_t ccstValue = (0 << 7) |  /* all_ref_pics_intra */
2204                         (1 << 6) |  /* intra_pred_used */
2205                         (15 << 2);  /* max_ref_per_pic */
2206     avio_wb32(pb, 0); /* size */
2207     ffio_wfourcc(pb, "ccst");
2208     avio_wb32(pb, 0); /* Version & flags */
2209     avio_w8(pb, ccstValue);
2210     avio_wb24(pb, 0);  /* reserved */
2211     return update_size(pb, pos);
2212 }
2213 
2214 #ifdef OHOS_HDR_VIVID
mov_get_cuva_from_metadata(AVFormatContext *s, MOVMuxContext *mov, MOVTrack *track)2215 static CuvaConfig mov_get_cuva_from_metadata(AVFormatContext *s, MOVMuxContext *mov, MOVTrack *track)
2216 {
2217     CuvaConfig cuva;
2218     cuva.cuva_version_map = 0;
2219     cuva.terminal_provide_code = 0;
2220     cuva.terminal_provide_oriented_code = 0;
2221     if (s == NULL || mov == NULL || track == NULL) {
2222         av_log(mov->fc, AV_LOG_WARNING, "Not cuva info. Parameters is NULL!\n");
2223         return cuva;
2224     }
2225 
2226     int i = 0;
2227     for (i = 0; i < mov->nb_streams; ++i) {
2228         if (track == &mov->tracks[i]) {
2229             break;
2230         }
2231     }
2232     if (i == mov->nb_streams) {
2233         av_log(mov->fc, AV_LOG_WARNING, "Not cuva info. The track is not in the mov!\n");
2234         return cuva;
2235     }
2236     AVStream *st = i < s->nb_streams ? s->streams[i] : NULL;
2237     if (st && st->metadata) {
2238         AVDictionaryEntry *rot = av_dict_get(st->metadata, "hdr_type", NULL, 0);
2239         if (rot && rot->value && strcmp(rot->value, "hdr_vivid") == 0) {
2240             cuva.cuva_version_map = 1;
2241             cuva.terminal_provide_code = 4;
2242             cuva.terminal_provide_oriented_code = 5;
2243         }
2244     }
2245     return cuva;
2246 }
2247 #endif
2248 
2249 #ifdef OHOS_TIMED_META_TRACK
mov_write_metadata_setup_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)2250 static int mov_write_metadata_setup_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
2251 {
2252     int64_t pos = avio_tell(pb);
2253     avio_wb32(pb, 0); /* size */
2254     ffio_wfourcc(pb, "setu");
2255     AVDictionaryEntry* key_val = av_dict_get(track->st->metadata, "setup_key", NULL, 0);
2256     if (key_val) {
2257         size_t key_len = strlen(key_val->value);
2258         avio_write(pb, key_val->value, key_len);
2259     }
2260     return update_size(pb, pos);
2261 }
2262 
mov_write_metadata_locale_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)2263 static int mov_write_metadata_locale_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
2264 {
2265     int64_t pos = avio_tell(pb);
2266     avio_wb32(pb, 0); /* size */
2267     ffio_wfourcc(pb, "loca");
2268     AVDictionaryEntry* key_val = av_dict_get(track->st->metadata, "locale_key", NULL, 0);
2269     if (key_val) {
2270         size_t key_len = strlen(key_val->value);
2271         avio_write(pb, key_val->value, key_len);
2272     }
2273     return update_size(pb, pos);
2274 }
2275 
mov_write_metadata_keyd_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, const char *metadata)2276 static int mov_write_metadata_keyd_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, const char *metadata)
2277 {
2278     int64_t pos = avio_tell(pb);
2279     avio_wb32(pb, 0); /* size */
2280     ffio_wfourcc(pb, "keyd");
2281     size_t key_len = strlen(metadata);
2282     ffio_wfourcc(pb, "mdta");
2283     avio_write(pb, metadata, key_len);
2284     return update_size(pb, pos);
2285 }
2286 
mov_write_metadata_keys_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)2287 static int mov_write_metadata_keys_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
2288 {
2289     int ret = AVERROR_BUG;
2290     const AVDictionaryEntry *t = NULL;
2291     avio_wb32(pb, 0); /* Reserved */
2292     avio_wb16(pb, 0); /* Reserved */
2293     avio_wb16(pb, 1); /* Data-reference index */
2294     int64_t pos = avio_tell(pb);
2295     avio_wb32(pb, 0); /* size */
2296     ffio_wfourcc(pb, "keys");
2297     int count = 0;
2298 
2299     const char *key_tag = "com.openharmony.timed_metadata";
2300     size_t key_tag_len = strlen(key_tag);
2301     // key atoms table
2302     while (t = av_dict_get(track->st->metadata, "", t, AV_DICT_IGNORE_SUFFIX)) {
2303         size_t key_len = strlen(t->key);
2304         if (key_len > key_tag_len && strncmp(t->key, key_tag, key_tag_len) == 0) {
2305             int64_t entry_pos = avio_tell(pb);
2306             avio_wb32(pb, 0); /* size */
2307             avio_wb32(pb, count + 1); /* local key id, 0 and 0xFFFFFFFF reserved */
2308             ret = mov_write_metadata_keyd_tag(s, pb, mov, t->value);
2309             if (ret < 0)
2310                 return ret;
2311             update_size(pb, entry_pos);
2312             count += 1;
2313         }
2314     }
2315 
2316     return update_size(pb, pos);
2317 }
2318 
mov_write_mebx_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)2319 static int mov_write_mebx_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
2320 {
2321     int ret = AVERROR_BUG;
2322     int64_t pos = avio_tell(pb);
2323     avio_wb32(pb, 0); /* size */
2324     ffio_wfourcc(pb, "mebx");
2325     ret = mov_write_metadata_keys_tag(s, pb, mov, track);
2326     if (ret < 0)
2327         return ret;
2328 
2329     return update_size(pb, pos);
2330 }
2331 #endif
2332 
mov_write_video_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)2333 static int mov_write_video_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
2334 {
2335     int ret = AVERROR_BUG;
2336     int64_t pos = avio_tell(pb);
2337     char compressor_name[32] = { 0 };
2338     int avid = 0;
2339 
2340     int uncompressed_ycbcr = ((track->par->codec_id == AV_CODEC_ID_RAWVIDEO && track->par->format == AV_PIX_FMT_UYVY422)
2341                            || (track->par->codec_id == AV_CODEC_ID_RAWVIDEO && track->par->format == AV_PIX_FMT_YUYV422)
2342                            ||  track->par->codec_id == AV_CODEC_ID_V308
2343                            ||  track->par->codec_id == AV_CODEC_ID_V408
2344                            ||  track->par->codec_id == AV_CODEC_ID_V410
2345                            ||  track->par->codec_id == AV_CODEC_ID_V210);
2346 
2347     avio_wb32(pb, 0); /* size */
2348     if (mov->encryption_scheme != MOV_ENC_NONE) {
2349         ffio_wfourcc(pb, "encv");
2350     } else {
2351         avio_wl32(pb, track->tag); // store it byteswapped
2352     }
2353     avio_wb32(pb, 0); /* Reserved */
2354     avio_wb16(pb, 0); /* Reserved */
2355     avio_wb16(pb, 1); /* Data-reference index */
2356 
2357     if (uncompressed_ycbcr) {
2358         avio_wb16(pb, 2); /* Codec stream version */
2359     } else {
2360         avio_wb16(pb, 0); /* Codec stream version */
2361     }
2362     avio_wb16(pb, 0); /* Codec stream revision (=0) */
2363     if (track->mode == MODE_MOV) {
2364         ffio_wfourcc(pb, "FFMP"); /* Vendor */
2365         if (track->par->codec_id == AV_CODEC_ID_RAWVIDEO || uncompressed_ycbcr) {
2366             avio_wb32(pb, 0); /* Temporal Quality */
2367             avio_wb32(pb, 0x400); /* Spatial Quality = lossless*/
2368         } else {
2369             avio_wb32(pb, 0x200); /* Temporal Quality = normal */
2370             avio_wb32(pb, 0x200); /* Spatial Quality = normal */
2371         }
2372     } else {
2373         ffio_fill(pb, 0, 3 * 4); /* Reserved */
2374     }
2375     avio_wb16(pb, track->par->width); /* Video width */
2376     avio_wb16(pb, track->height); /* Video height */
2377     avio_wb32(pb, 0x00480000); /* Horizontal resolution 72dpi */
2378     avio_wb32(pb, 0x00480000); /* Vertical resolution 72dpi */
2379     avio_wb32(pb, 0); /* Data size (= 0) */
2380     avio_wb16(pb, 1); /* Frame count (= 1) */
2381 
2382     find_compressor(compressor_name, 32, track);
2383 #ifdef OHOS_HDR_VIVID
2384     CuvaConfig cuva = mov_get_cuva_from_metadata(s, mov, track);
2385     if (cuva.cuva_version_map > 0 && track->par->codec_id == AV_CODEC_ID_HEVC) {
2386         memset(compressor_name, 0, 32);
2387         memcpy(compressor_name, "CUVA HDR Video", 14);
2388     }
2389 #endif
2390     avio_w8(pb, strlen(compressor_name));
2391     avio_write(pb, compressor_name, 31);
2392 
2393     if (track->mode == MODE_MOV &&
2394        (track->par->codec_id == AV_CODEC_ID_V410 || track->par->codec_id == AV_CODEC_ID_V210))
2395         avio_wb16(pb, 0x18);
2396     else if (track->mode == MODE_MOV && track->par->bits_per_coded_sample)
2397         avio_wb16(pb, track->par->bits_per_coded_sample |
2398                   (track->par->format == AV_PIX_FMT_GRAY8 ? 0x20 : 0));
2399     else
2400         avio_wb16(pb, 0x18); /* Reserved */
2401 
2402     if (track->mode == MODE_MOV && track->par->format == AV_PIX_FMT_PAL8) {
2403         int pal_size, i;
2404         avio_wb16(pb, 0);             /* Color table ID */
2405         avio_wb32(pb, 0);             /* Color table seed */
2406         avio_wb16(pb, 0x8000);        /* Color table flags */
2407         if (track->par->bits_per_coded_sample < 0 || track->par->bits_per_coded_sample > 8)
2408             return AVERROR(EINVAL);
2409         pal_size = 1 << track->par->bits_per_coded_sample;
2410         avio_wb16(pb, pal_size - 1);  /* Color table size (zero-relative) */
2411         for (i = 0; i < pal_size; i++) {
2412             uint32_t rgb = track->palette[i];
2413             uint16_t r = (rgb >> 16) & 0xff;
2414             uint16_t g = (rgb >> 8)  & 0xff;
2415             uint16_t b = rgb         & 0xff;
2416             avio_wb16(pb, 0);
2417             avio_wb16(pb, (r << 8) | r);
2418             avio_wb16(pb, (g << 8) | g);
2419             avio_wb16(pb, (b << 8) | b);
2420         }
2421     } else
2422         avio_wb16(pb, 0xffff); /* Reserved */
2423 
2424     if (track->tag == MKTAG('m','p','4','v'))
2425         mov_write_esds_tag(pb, track);
2426     else if (track->par->codec_id == AV_CODEC_ID_H263)
2427         mov_write_d263_tag(pb);
2428     else if (track->par->codec_id == AV_CODEC_ID_AVUI ||
2429             track->par->codec_id == AV_CODEC_ID_SVQ3) {
2430         mov_write_extradata_tag(pb, track);
2431         avio_wb32(pb, 0);
2432     } else if (track->par->codec_id == AV_CODEC_ID_DNXHD) {
2433         mov_write_avid_tag(pb, track);
2434         avid = 1;
2435     } else if (track->par->codec_id == AV_CODEC_ID_HEVC)
2436         mov_write_hvcc_tag(pb, track);
2437     else if (track->par->codec_id == AV_CODEC_ID_H264 && !TAG_IS_AVCI(track->tag)) {
2438         mov_write_avcc_tag(pb, track);
2439         if (track->mode == MODE_IPOD)
2440             mov_write_uuid_tag_ipod(pb);
2441     } else if (track->par->codec_id == AV_CODEC_ID_VP9) {
2442         mov_write_vpcc_tag(mov->fc, pb, track);
2443     } else if (track->par->codec_id == AV_CODEC_ID_AV1) {
2444         mov_write_av1c_tag(pb, track);
2445     } else if (track->par->codec_id == AV_CODEC_ID_VC1 && track->vos_len > 0)
2446         mov_write_dvc1_tag(pb, track);
2447     else if (track->par->codec_id == AV_CODEC_ID_VP6F ||
2448              track->par->codec_id == AV_CODEC_ID_VP6A) {
2449         /* Don't write any potential extradata here - the cropping
2450          * is signalled via the normal width/height fields. */
2451     } else if (track->par->codec_id == AV_CODEC_ID_R10K) {
2452         if (track->par->codec_tag == MKTAG('R','1','0','k'))
2453             mov_write_dpxe_tag(pb, track);
2454     } else if (track->vos_len > 0)
2455         mov_write_glbl_tag(pb, track);
2456 
2457     if (track->par->codec_id != AV_CODEC_ID_H264 &&
2458         track->par->codec_id != AV_CODEC_ID_MPEG4 &&
2459         track->par->codec_id != AV_CODEC_ID_DNXHD) {
2460         int field_order = track->par->field_order;
2461 
2462         if (field_order != AV_FIELD_UNKNOWN)
2463             mov_write_fiel_tag(pb, track, field_order);
2464     }
2465 
2466     if (mov->flags & FF_MOV_FLAG_WRITE_GAMA) {
2467         if (track->mode == MODE_MOV)
2468             mov_write_gama_tag(s, pb, track, mov->gamma);
2469         else
2470             av_log(mov->fc, AV_LOG_WARNING, "Not writing 'gama' atom. Format is not MOV.\n");
2471     }
2472     if (track->mode == MODE_MOV || track->mode == MODE_MP4 || track->mode == MODE_AVIF) {
2473         int has_color_info = track->par->color_primaries != AVCOL_PRI_UNSPECIFIED &&
2474                              track->par->color_trc != AVCOL_TRC_UNSPECIFIED &&
2475                              track->par->color_space != AVCOL_SPC_UNSPECIFIED;
2476         if (has_color_info || mov->flags & FF_MOV_FLAG_WRITE_COLR ||
2477             av_stream_get_side_data(track->st, AV_PKT_DATA_ICC_PROFILE, NULL)) {
2478             int prefer_icc = mov->flags & FF_MOV_FLAG_PREFER_ICC || !has_color_info;
2479             mov_write_colr_tag(pb, track, prefer_icc);
2480         } else if (mov->flags & FF_MOV_FLAG_WRITE_COLR) {
2481              av_log(mov->fc, AV_LOG_WARNING, "Not writing 'colr' atom. Format is not MOV or MP4.\n");
2482         }
2483     }
2484     if (track->mode == MODE_MOV || track->mode == MODE_MP4) {
2485         mov_write_clli_tag(pb, track);
2486         mov_write_mdcv_tag(pb, track);
2487     }
2488 
2489     if (track->mode == MODE_MP4 && mov->fc->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL) {
2490         AVStereo3D* stereo_3d = (AVStereo3D*) av_stream_get_side_data(track->st, AV_PKT_DATA_STEREO3D, NULL);
2491         AVSphericalMapping* spherical_mapping = (AVSphericalMapping*)av_stream_get_side_data(track->st, AV_PKT_DATA_SPHERICAL, NULL);
2492         AVDOVIDecoderConfigurationRecord *dovi = (AVDOVIDecoderConfigurationRecord *)
2493                                                  av_stream_get_side_data(track->st, AV_PKT_DATA_DOVI_CONF, NULL);
2494 
2495         if (stereo_3d)
2496             mov_write_st3d_tag(s, pb, stereo_3d);
2497         if (spherical_mapping)
2498             mov_write_sv3d_tag(mov->fc, pb, spherical_mapping);
2499         if (dovi)
2500             mov_write_dvcc_dvvc_tag(s, pb, dovi);
2501     }
2502 
2503     if (track->par->sample_aspect_ratio.den && track->par->sample_aspect_ratio.num) {
2504         mov_write_pasp_tag(pb, track);
2505     }
2506 
2507     if (uncompressed_ycbcr){
2508         mov_write_clap_tag(pb, track);
2509     }
2510 
2511     if (mov->encryption_scheme != MOV_ENC_NONE) {
2512         ff_mov_cenc_write_sinf_tag(track, pb, mov->encryption_kid);
2513     }
2514 
2515 #ifdef OHOS_HDR_VIVID
2516     if (cuva.cuva_version_map > 0 && track->par->codec_id == AV_CODEC_ID_HEVC) {
2517         mov_write_cuvv_tag(pb, &cuva);
2518     }
2519 #endif
2520 
2521     if (mov->write_btrt &&
2522             ((ret = mov_write_btrt_tag(pb, track)) < 0))
2523         return ret;
2524 
2525     /* extra padding for avid stsd */
2526     /* https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/QTFFChap2/qtff2.html#//apple_ref/doc/uid/TP40000939-CH204-61112 */
2527     if (avid)
2528         avio_wb32(pb, 0);
2529 
2530     if (track->mode == MODE_AVIF)
2531         mov_write_ccst_tag(pb);
2532 
2533     return update_size(pb, pos);
2534 }
2535 
mov_write_rtp_tag(AVIOContext *pb, MOVTrack *track)2536 static int mov_write_rtp_tag(AVIOContext *pb, MOVTrack *track)
2537 {
2538     int64_t pos = avio_tell(pb);
2539     avio_wb32(pb, 0); /* size */
2540     ffio_wfourcc(pb, "rtp ");
2541     avio_wb32(pb, 0); /* Reserved */
2542     avio_wb16(pb, 0); /* Reserved */
2543     avio_wb16(pb, 1); /* Data-reference index */
2544 
2545     avio_wb16(pb, 1); /* Hint track version */
2546     avio_wb16(pb, 1); /* Highest compatible version */
2547     avio_wb32(pb, track->max_packet_size); /* Max packet size */
2548 
2549     avio_wb32(pb, 12); /* size */
2550     ffio_wfourcc(pb, "tims");
2551     avio_wb32(pb, track->timescale);
2552 
2553     return update_size(pb, pos);
2554 }
2555 
mov_write_source_reference_tag(AVIOContext *pb, MOVTrack *track, const char *reel_name)2556 static int mov_write_source_reference_tag(AVIOContext *pb, MOVTrack *track, const char *reel_name)
2557 {
2558     uint64_t str_size =strlen(reel_name);
2559     int64_t pos = avio_tell(pb);
2560 
2561     if (str_size >= UINT16_MAX){
2562         av_log(NULL, AV_LOG_ERROR, "reel_name length %"PRIu64" is too large\n", str_size);
2563         avio_wb16(pb, 0);
2564         return AVERROR(EINVAL);
2565     }
2566 
2567     avio_wb32(pb, 0);                              /* size */
2568     ffio_wfourcc(pb, "name");                      /* Data format */
2569     avio_wb16(pb, str_size);                       /* string size */
2570     avio_wb16(pb, track->language);                /* langcode */
2571     avio_write(pb, reel_name, str_size);           /* reel name */
2572     return update_size(pb,pos);
2573 }
2574 
mov_write_tmcd_tag(AVIOContext *pb, MOVTrack *track)2575 static int mov_write_tmcd_tag(AVIOContext *pb, MOVTrack *track)
2576 {
2577     int64_t pos = avio_tell(pb);
2578 #if 1
2579     int frame_duration;
2580     int nb_frames;
2581     AVDictionaryEntry *t = NULL;
2582 
2583     if (!track->st->avg_frame_rate.num || !track->st->avg_frame_rate.den) {
2584         av_log(NULL, AV_LOG_ERROR, "avg_frame_rate not set for tmcd track.\n");
2585         return AVERROR(EINVAL);
2586     } else {
2587         frame_duration = av_rescale(track->timescale, track->st->avg_frame_rate.den, track->st->avg_frame_rate.num);
2588         nb_frames      = ROUNDED_DIV(track->st->avg_frame_rate.num, track->st->avg_frame_rate.den);
2589     }
2590 
2591     if (nb_frames > 255) {
2592         av_log(NULL, AV_LOG_ERROR, "fps %d is too large\n", nb_frames);
2593         return AVERROR(EINVAL);
2594     }
2595 
2596     avio_wb32(pb, 0); /* size */
2597     ffio_wfourcc(pb, "tmcd");               /* Data format */
2598     avio_wb32(pb, 0);                       /* Reserved */
2599     avio_wb32(pb, 1);                       /* Data reference index */
2600     avio_wb32(pb, 0);                       /* Flags */
2601     avio_wb32(pb, track->timecode_flags);   /* Flags (timecode) */
2602     avio_wb32(pb, track->timescale);        /* Timescale */
2603     avio_wb32(pb, frame_duration);          /* Frame duration */
2604     avio_w8(pb, nb_frames);                 /* Number of frames */
2605     avio_w8(pb, 0);                         /* Reserved */
2606 
2607     t = av_dict_get(track->st->metadata, "reel_name", NULL, 0);
2608     if (t && utf8len(t->value) && track->mode != MODE_MP4)
2609         mov_write_source_reference_tag(pb, track, t->value);
2610     else
2611         avio_wb16(pb, 0); /* zero size */
2612 #else
2613 
2614     avio_wb32(pb, 0); /* size */
2615     ffio_wfourcc(pb, "tmcd");               /* Data format */
2616     avio_wb32(pb, 0);                       /* Reserved */
2617     avio_wb32(pb, 1);                       /* Data reference index */
2618     if (track->par->extradata_size)
2619         avio_write(pb, track->par->extradata, track->par->extradata_size);
2620 #endif
2621     return update_size(pb, pos);
2622 }
2623 
mov_write_gpmd_tag(AVIOContext *pb, const MOVTrack *track)2624 static int mov_write_gpmd_tag(AVIOContext *pb, const MOVTrack *track)
2625 {
2626     int64_t pos = avio_tell(pb);
2627     avio_wb32(pb, 0); /* size */
2628     ffio_wfourcc(pb, "gpmd");
2629     avio_wb32(pb, 0); /* Reserved */
2630     avio_wb16(pb, 0); /* Reserved */
2631     avio_wb16(pb, 1); /* Data-reference index */
2632     avio_wb32(pb, 0); /* Reserved */
2633     return update_size(pb, pos);
2634 }
2635 
mov_write_stsd_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)2636 static int mov_write_stsd_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
2637 {
2638     int64_t pos = avio_tell(pb);
2639     int ret = 0;
2640     avio_wb32(pb, 0); /* size */
2641     ffio_wfourcc(pb, "stsd");
2642     avio_wb32(pb, 0); /* version & flags */
2643     avio_wb32(pb, 1); /* entry count */
2644     if (track->par->codec_type == AVMEDIA_TYPE_VIDEO)
2645         ret = mov_write_video_tag(s, pb, mov, track);
2646     else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO)
2647         ret = mov_write_audio_tag(s, pb, mov, track);
2648     else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE)
2649         ret = mov_write_subtitle_tag(s, pb, track);
2650     else if (track->par->codec_tag == MKTAG('r','t','p',' '))
2651         ret = mov_write_rtp_tag(pb, track);
2652     else if (track->par->codec_tag == MKTAG('t','m','c','d'))
2653         ret = mov_write_tmcd_tag(pb, track);
2654     else if (track->par->codec_tag == MKTAG('g','p','m','d'))
2655         ret = mov_write_gpmd_tag(pb, track);
2656 #ifdef OHOS_TIMED_META_TRACK
2657     else if (track->par->codec_type == AVMEDIA_TYPE_TIMEDMETA)
2658         ret = mov_write_mebx_tag(s, pb, mov, track);
2659 #endif
2660 
2661     if (ret < 0)
2662         return ret;
2663 
2664     return update_size(pb, pos);
2665 }
2666 
mov_write_ctts_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)2667 static int mov_write_ctts_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
2668 {
2669     MOVMuxContext *mov = s->priv_data;
2670     MOVCtts *ctts_entries;
2671     uint32_t entries = 0;
2672     uint32_t atom_size;
2673     int i;
2674 
2675     ctts_entries = av_malloc_array((track->entry + 1), sizeof(*ctts_entries)); /* worst case */
2676     if (!ctts_entries)
2677         return AVERROR(ENOMEM);
2678     ctts_entries[0].count = 1;
2679     ctts_entries[0].duration = track->cluster[0].cts;
2680     for (i = 1; i < track->entry; i++) {
2681         if (track->cluster[i].cts == ctts_entries[entries].duration) {
2682             ctts_entries[entries].count++; /* compress */
2683         } else {
2684             entries++;
2685             ctts_entries[entries].duration = track->cluster[i].cts;
2686             ctts_entries[entries].count = 1;
2687         }
2688     }
2689     entries++; /* last one */
2690     atom_size = 16 + (entries * 8);
2691     avio_wb32(pb, atom_size); /* size */
2692     ffio_wfourcc(pb, "ctts");
2693     if (mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS)
2694         avio_w8(pb, 1); /* version */
2695     else
2696         avio_w8(pb, 0); /* version */
2697     avio_wb24(pb, 0); /* flags */
2698     avio_wb32(pb, entries); /* entry count */
2699     for (i = 0; i < entries; i++) {
2700         avio_wb32(pb, ctts_entries[i].count);
2701         avio_wb32(pb, ctts_entries[i].duration);
2702     }
2703     av_free(ctts_entries);
2704     return atom_size;
2705 }
2706 
2707 /* Time to sample atom */
mov_write_stts_tag(AVIOContext *pb, MOVTrack *track)2708 static int mov_write_stts_tag(AVIOContext *pb, MOVTrack *track)
2709 {
2710     MOVStts *stts_entries = NULL;
2711     uint32_t entries = -1;
2712     uint32_t atom_size;
2713     int i;
2714 
2715     if (track->par->codec_type == AVMEDIA_TYPE_AUDIO && !track->audio_vbr) {
2716         stts_entries = av_malloc(sizeof(*stts_entries)); /* one entry */
2717         if (!stts_entries)
2718             return AVERROR(ENOMEM);
2719         stts_entries[0].count = track->sample_count;
2720         stts_entries[0].duration = 1;
2721         entries = 1;
2722     } else {
2723         if (track->entry) {
2724             stts_entries = av_malloc_array(track->entry, sizeof(*stts_entries)); /* worst case */
2725             if (!stts_entries)
2726                 return AVERROR(ENOMEM);
2727         }
2728         for (i = 0; i < track->entry; i++) {
2729             int duration = get_cluster_duration(track, i);
2730             if (i && duration == stts_entries[entries].duration) {
2731                 stts_entries[entries].count++; /* compress */
2732             } else {
2733                 entries++;
2734                 stts_entries[entries].duration = duration;
2735                 stts_entries[entries].count = 1;
2736             }
2737         }
2738         entries++; /* last one */
2739     }
2740     atom_size = 16 + (entries * 8);
2741     avio_wb32(pb, atom_size); /* size */
2742     ffio_wfourcc(pb, "stts");
2743     avio_wb32(pb, 0); /* version & flags */
2744     avio_wb32(pb, entries); /* entry count */
2745     for (i = 0; i < entries; i++) {
2746         avio_wb32(pb, stts_entries[i].count);
2747         avio_wb32(pb, stts_entries[i].duration);
2748     }
2749     av_free(stts_entries);
2750     return atom_size;
2751 }
2752 
mov_write_dref_tag(AVIOContext *pb)2753 static int mov_write_dref_tag(AVIOContext *pb)
2754 {
2755     avio_wb32(pb, 28); /* size */
2756     ffio_wfourcc(pb, "dref");
2757     avio_wb32(pb, 0); /* version & flags */
2758     avio_wb32(pb, 1); /* entry count */
2759 
2760     avio_wb32(pb, 0xc); /* size */
2761     //FIXME add the alis and rsrc atom
2762     ffio_wfourcc(pb, "url ");
2763     avio_wb32(pb, 1); /* version & flags */
2764 
2765     return 28;
2766 }
2767 
mov_preroll_write_stbl_atoms(AVIOContext *pb, MOVTrack *track)2768 static int mov_preroll_write_stbl_atoms(AVIOContext *pb, MOVTrack *track)
2769 {
2770     struct sgpd_entry {
2771         int count;
2772         int16_t roll_distance;
2773         int group_description_index;
2774     };
2775 
2776     struct sgpd_entry *sgpd_entries = NULL;
2777     int entries = -1;
2778     int group = 0;
2779     int i, j;
2780 
2781     const int OPUS_SEEK_PREROLL_MS = 80;
2782     int roll_samples = av_rescale_q(OPUS_SEEK_PREROLL_MS,
2783                                     (AVRational){1, 1000},
2784                                     (AVRational){1, 48000});
2785 
2786     if (!track->entry)
2787         return 0;
2788 
2789     sgpd_entries = av_malloc_array(track->entry, sizeof(*sgpd_entries));
2790     if (!sgpd_entries)
2791         return AVERROR(ENOMEM);
2792 
2793     av_assert0(track->par->codec_id == AV_CODEC_ID_OPUS || track->par->codec_id == AV_CODEC_ID_AAC);
2794 
2795     if (track->par->codec_id == AV_CODEC_ID_OPUS) {
2796         for (i = 0; i < track->entry; i++) {
2797             int roll_samples_remaining = roll_samples;
2798             int distance = 0;
2799             for (j = i - 1; j >= 0; j--) {
2800                 roll_samples_remaining -= get_cluster_duration(track, j);
2801                 distance++;
2802                 if (roll_samples_remaining <= 0)
2803                     break;
2804             }
2805             /* We don't have enough preceeding samples to compute a valid
2806                roll_distance here, so this sample can't be independently
2807                decoded. */
2808             if (roll_samples_remaining > 0)
2809                 distance = 0;
2810             /* Verify distance is a maximum of 32 (2.5ms) packets. */
2811             if (distance > 32)
2812                 return AVERROR_INVALIDDATA;
2813             if (i && distance == sgpd_entries[entries].roll_distance) {
2814                 sgpd_entries[entries].count++;
2815             } else {
2816                 entries++;
2817                 sgpd_entries[entries].count = 1;
2818                 sgpd_entries[entries].roll_distance = distance;
2819                 sgpd_entries[entries].group_description_index = distance ? ++group : 0;
2820             }
2821         }
2822     } else {
2823         entries++;
2824         sgpd_entries[entries].count = track->sample_count;
2825         sgpd_entries[entries].roll_distance = 1;
2826         sgpd_entries[entries].group_description_index = ++group;
2827     }
2828     entries++;
2829 
2830     if (!group) {
2831         av_free(sgpd_entries);
2832         return 0;
2833     }
2834 
2835     /* Write sgpd tag */
2836     avio_wb32(pb, 24 + (group * 2)); /* size */
2837     ffio_wfourcc(pb, "sgpd");
2838     avio_wb32(pb, 1 << 24); /* fullbox */
2839     ffio_wfourcc(pb, "roll");
2840     avio_wb32(pb, 2); /* default_length */
2841     avio_wb32(pb, group); /* entry_count */
2842     for (i = 0; i < entries; i++) {
2843         if (sgpd_entries[i].group_description_index) {
2844             avio_wb16(pb, -sgpd_entries[i].roll_distance); /* roll_distance */
2845         }
2846     }
2847 
2848     /* Write sbgp tag */
2849     avio_wb32(pb, 20 + (entries * 8)); /* size */
2850     ffio_wfourcc(pb, "sbgp");
2851     avio_wb32(pb, 0); /* fullbox */
2852     ffio_wfourcc(pb, "roll");
2853     avio_wb32(pb, entries); /* entry_count */
2854     for (i = 0; i < entries; i++) {
2855         avio_wb32(pb, sgpd_entries[i].count); /* sample_count */
2856         avio_wb32(pb, sgpd_entries[i].group_description_index); /* group_description_index */
2857     }
2858 
2859     av_free(sgpd_entries);
2860     return 0;
2861 }
2862 
mov_write_stbl_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)2863 static int mov_write_stbl_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
2864 {
2865     int64_t pos = avio_tell(pb);
2866     int ret = 0;
2867 
2868     avio_wb32(pb, 0); /* size */
2869     ffio_wfourcc(pb, "stbl");
2870     if ((ret = mov_write_stsd_tag(s, pb, mov, track)) < 0)
2871         return ret;
2872     mov_write_stts_tag(pb, track);
2873     if ((track->par->codec_type == AVMEDIA_TYPE_VIDEO ||
2874          track->par->codec_id == AV_CODEC_ID_TRUEHD ||
2875          track->par->codec_id == AV_CODEC_ID_MPEGH_3D_AUDIO ||
2876 #ifdef OHOS_TIMED_META_TRACK
2877          track->par->codec_tag == MKTAG('r','t','p',' ') ||
2878          track->par->codec_type == AVMEDIA_TYPE_TIMEDMETA) &&
2879 #else
2880          track->par->codec_tag == MKTAG('r','t','p',' ')) &&
2881 #endif
2882         track->has_keyframes && track->has_keyframes < track->entry)
2883         mov_write_stss_tag(pb, track, MOV_SYNC_SAMPLE);
2884     if (track->par->codec_type == AVMEDIA_TYPE_VIDEO && track->has_disposable)
2885         mov_write_sdtp_tag(pb, track);
2886     if (track->mode == MODE_MOV && track->flags & MOV_TRACK_STPS)
2887         mov_write_stss_tag(pb, track, MOV_PARTIAL_SYNC_SAMPLE);
2888     if (track->par->codec_type == AVMEDIA_TYPE_VIDEO &&
2889         track->flags & MOV_TRACK_CTTS && track->entry) {
2890 
2891         if ((ret = mov_write_ctts_tag(s, pb, track)) < 0)
2892             return ret;
2893     }
2894     mov_write_stsc_tag(pb, track);
2895     mov_write_stsz_tag(pb, track);
2896     mov_write_stco_tag(pb, track);
2897     if (track->cenc.aes_ctr) {
2898         ff_mov_cenc_write_stbl_atoms(&track->cenc, pb);
2899     }
2900     if (track->par->codec_id == AV_CODEC_ID_OPUS || track->par->codec_id == AV_CODEC_ID_AAC) {
2901         mov_preroll_write_stbl_atoms(pb, track);
2902     }
2903     return update_size(pb, pos);
2904 }
2905 
mov_write_dinf_tag(AVIOContext *pb)2906 static int mov_write_dinf_tag(AVIOContext *pb)
2907 {
2908     int64_t pos = avio_tell(pb);
2909     avio_wb32(pb, 0); /* size */
2910     ffio_wfourcc(pb, "dinf");
2911     mov_write_dref_tag(pb);
2912     return update_size(pb, pos);
2913 }
2914 
mov_write_nmhd_tag(AVIOContext *pb)2915 static int mov_write_nmhd_tag(AVIOContext *pb)
2916 {
2917     avio_wb32(pb, 12);
2918     ffio_wfourcc(pb, "nmhd");
2919     avio_wb32(pb, 0);
2920     return 12;
2921 }
2922 
mov_write_sthd_tag(AVIOContext *pb)2923 static int mov_write_sthd_tag(AVIOContext *pb)
2924 {
2925     avio_wb32(pb, 12);
2926     ffio_wfourcc(pb, "sthd");
2927     avio_wb32(pb, 0);
2928     return 12;
2929 }
2930 
mov_write_tcmi_tag(AVIOContext *pb, MOVTrack *track)2931 static int mov_write_tcmi_tag(AVIOContext *pb, MOVTrack *track)
2932 {
2933     int64_t pos = avio_tell(pb);
2934     const char *font = "Lucida Grande";
2935     avio_wb32(pb, 0);                   /* size */
2936     ffio_wfourcc(pb, "tcmi");           /* timecode media information atom */
2937     avio_wb32(pb, 0);                   /* version & flags */
2938     avio_wb16(pb, 0);                   /* text font */
2939     avio_wb16(pb, 0);                   /* text face */
2940     avio_wb16(pb, 12);                  /* text size */
2941     avio_wb16(pb, 0);                   /* (unknown, not in the QT specs...) */
2942     avio_wb16(pb, 0x0000);              /* text color (red) */
2943     avio_wb16(pb, 0x0000);              /* text color (green) */
2944     avio_wb16(pb, 0x0000);              /* text color (blue) */
2945     avio_wb16(pb, 0xffff);              /* background color (red) */
2946     avio_wb16(pb, 0xffff);              /* background color (green) */
2947     avio_wb16(pb, 0xffff);              /* background color (blue) */
2948     avio_w8(pb, strlen(font));          /* font len (part of the pascal string) */
2949     avio_write(pb, font, strlen(font)); /* font name */
2950     return update_size(pb, pos);
2951 }
2952 
mov_write_gmhd_tag(AVIOContext *pb, MOVTrack *track)2953 static int mov_write_gmhd_tag(AVIOContext *pb, MOVTrack *track)
2954 {
2955     int64_t pos = avio_tell(pb);
2956     avio_wb32(pb, 0);      /* size */
2957     ffio_wfourcc(pb, "gmhd");
2958     avio_wb32(pb, 0x18);   /* gmin size */
2959     ffio_wfourcc(pb, "gmin");/* generic media info */
2960     avio_wb32(pb, 0);      /* version & flags */
2961     avio_wb16(pb, 0x40);   /* graphics mode = */
2962     avio_wb16(pb, 0x8000); /* opColor (r?) */
2963     avio_wb16(pb, 0x8000); /* opColor (g?) */
2964     avio_wb16(pb, 0x8000); /* opColor (b?) */
2965     avio_wb16(pb, 0);      /* balance */
2966     avio_wb16(pb, 0);      /* reserved */
2967 
2968     /*
2969      * This special text atom is required for
2970      * Apple Quicktime chapters. The contents
2971      * don't appear to be documented, so the
2972      * bytes are copied verbatim.
2973      */
2974     if (track->tag != MKTAG('c','6','0','8')) {
2975     avio_wb32(pb, 0x2C);   /* size */
2976     ffio_wfourcc(pb, "text");
2977     avio_wb16(pb, 0x01);
2978     avio_wb32(pb, 0x00);
2979     avio_wb32(pb, 0x00);
2980     avio_wb32(pb, 0x00);
2981     avio_wb32(pb, 0x01);
2982     avio_wb32(pb, 0x00);
2983     avio_wb32(pb, 0x00);
2984     avio_wb32(pb, 0x00);
2985     avio_wb32(pb, 0x00004000);
2986     avio_wb16(pb, 0x0000);
2987     }
2988 
2989     if (track->par->codec_tag == MKTAG('t','m','c','d')) {
2990         int64_t tmcd_pos = avio_tell(pb);
2991         avio_wb32(pb, 0); /* size */
2992         ffio_wfourcc(pb, "tmcd");
2993         mov_write_tcmi_tag(pb, track);
2994         update_size(pb, tmcd_pos);
2995     } else if (track->par->codec_tag == MKTAG('g','p','m','d')) {
2996         int64_t gpmd_pos = avio_tell(pb);
2997         avio_wb32(pb, 0); /* size */
2998         ffio_wfourcc(pb, "gpmd");
2999         avio_wb32(pb, 0); /* version */
3000         update_size(pb, gpmd_pos);
3001     }
3002     return update_size(pb, pos);
3003 }
3004 
mov_write_smhd_tag(AVIOContext *pb)3005 static int mov_write_smhd_tag(AVIOContext *pb)
3006 {
3007     avio_wb32(pb, 16); /* size */
3008     ffio_wfourcc(pb, "smhd");
3009     avio_wb32(pb, 0); /* version & flags */
3010     avio_wb16(pb, 0); /* reserved (balance, normally = 0) */
3011     avio_wb16(pb, 0); /* reserved */
3012     return 16;
3013 }
3014 
mov_write_vmhd_tag(AVIOContext *pb)3015 static int mov_write_vmhd_tag(AVIOContext *pb)
3016 {
3017     avio_wb32(pb, 0x14); /* size (always 0x14) */
3018     ffio_wfourcc(pb, "vmhd");
3019     avio_wb32(pb, 0x01); /* version & flags */
3020     avio_wb64(pb, 0); /* reserved (graphics mode = copy) */
3021     return 0x14;
3022 }
3023 
is_clcp_track(MOVTrack *track)3024 static int is_clcp_track(MOVTrack *track)
3025 {
3026     return track->tag == MKTAG('c','7','0','8') ||
3027            track->tag == MKTAG('c','6','0','8');
3028 }
3029 
mov_write_hdlr_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)3030 static int mov_write_hdlr_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
3031 {
3032     MOVMuxContext *mov = s->priv_data;
3033     const char *hdlr, *descr = NULL, *hdlr_type = NULL;
3034     int64_t pos = avio_tell(pb);
3035     size_t descr_len;
3036 
3037     hdlr      = "dhlr";
3038     hdlr_type = "url ";
3039     descr     = "DataHandler";
3040 
3041     if (track) {
3042         hdlr = (track->mode == MODE_MOV) ? "mhlr" : "\0\0\0\0";
3043         if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
3044             if (track->mode == MODE_AVIF) {
3045                 hdlr_type = (track == &mov->tracks[0]) ? "pict" : "auxv";
3046                 descr     = "PictureHandler";
3047             } else {
3048                 hdlr_type = "vide";
3049                 descr     = "VideoHandler";
3050             }
3051         } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) {
3052             hdlr_type = "soun";
3053             descr     = "SoundHandler";
3054         } else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE) {
3055             if (is_clcp_track(track)) {
3056                 hdlr_type = "clcp";
3057                 descr = "ClosedCaptionHandler";
3058             } else {
3059                 if (track->tag == MKTAG('t','x','3','g')) {
3060                     hdlr_type = "sbtl";
3061                 } else if (track->tag == MKTAG('m','p','4','s')) {
3062                     hdlr_type = "subp";
3063                 } else if (track->tag == MOV_MP4_TTML_TAG) {
3064                     hdlr_type = "subt";
3065                 } else {
3066                     hdlr_type = "text";
3067                 }
3068                 descr = "SubtitleHandler";
3069             }
3070         } else if (track->par->codec_tag == MKTAG('r','t','p',' ')) {
3071             hdlr_type = "hint";
3072             descr     = "HintHandler";
3073         } else if (track->par->codec_tag == MKTAG('t','m','c','d')) {
3074             hdlr_type = "tmcd";
3075             descr = "TimeCodeHandler";
3076         } else if (track->par->codec_tag == MKTAG('g','p','m','d')) {
3077             hdlr_type = "meta";
3078             descr = "GoPro MET"; // GoPro Metadata
3079 #ifdef OHOS_TIMED_META_TRACK
3080         } else if (track->par->codec_type == AVMEDIA_TYPE_TIMEDMETA) {
3081             hdlr_type = "meta";
3082 #endif
3083         } else {
3084             av_log(s, AV_LOG_WARNING,
3085                    "Unknown hdlr_type for %s, writing dummy values\n",
3086                    av_fourcc2str(track->par->codec_tag));
3087         }
3088         if (track->st) {
3089             // hdlr.name is used by some players to identify the content title
3090             // of the track. So if an alternate handler description is
3091             // specified, use it.
3092             AVDictionaryEntry *t;
3093             t = av_dict_get(track->st->metadata, "handler_name", NULL, 0);
3094             if (t && utf8len(t->value))
3095                 descr = t->value;
3096         }
3097     }
3098 
3099     if (mov->empty_hdlr_name) /* expressly allowed by QTFF and not prohibited in ISO 14496-12 8.4.3.3 */
3100         descr = "";
3101 
3102     avio_wb32(pb, 0); /* size */
3103     ffio_wfourcc(pb, "hdlr");
3104     avio_wb32(pb, 0); /* Version & flags */
3105     avio_write(pb, hdlr, 4); /* handler */
3106     ffio_wfourcc(pb, hdlr_type); /* handler type */
3107     avio_wb32(pb, 0); /* reserved */
3108     avio_wb32(pb, 0); /* reserved */
3109     avio_wb32(pb, 0); /* reserved */
3110     descr_len = strlen(descr);
3111     if (!track || track->mode == MODE_MOV)
3112         avio_w8(pb, descr_len); /* pascal string */
3113     avio_write(pb, descr, descr_len); /* handler description */
3114     if (track && track->mode != MODE_MOV)
3115         avio_w8(pb, 0); /* c string */
3116     return update_size(pb, pos);
3117 }
3118 
mov_write_pitm_tag(AVIOContext *pb, int item_id)3119 static int mov_write_pitm_tag(AVIOContext *pb, int item_id)
3120 {
3121     int64_t pos = avio_tell(pb);
3122     avio_wb32(pb, 0); /* size */
3123     ffio_wfourcc(pb, "pitm");
3124     avio_wb32(pb, 0); /* Version & flags */
3125     avio_wb16(pb, item_id); /* item_id */
3126     return update_size(pb, pos);
3127 }
3128 
mov_write_iloc_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)3129 static int mov_write_iloc_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
3130 {
3131     int64_t pos = avio_tell(pb);
3132     avio_wb32(pb, 0); /* size */
3133     ffio_wfourcc(pb, "iloc");
3134     avio_wb32(pb, 0); /* Version & flags */
3135     avio_w8(pb, (4 << 4) + 4); /* offset_size(4) and length_size(4) */
3136     avio_w8(pb, 0); /* base_offset_size(4) and reserved(4) */
3137     avio_wb16(pb, s->nb_streams); /* item_count */
3138 
3139     for (int i = 0; i < s->nb_streams; i++) {
3140         avio_wb16(pb, i + 1); /* item_id */
3141         avio_wb16(pb, 0); /* data_reference_index */
3142         avio_wb16(pb, 1); /* extent_count */
3143         mov->avif_extent_pos[i] = avio_tell(pb);
3144         avio_wb32(pb, 0); /* extent_offset (written later) */
3145         // For animated AVIF, we simply write the first packet's size.
3146         avio_wb32(pb, mov->avif_extent_length[i]); /* extent_length */
3147     }
3148 
3149     return update_size(pb, pos);
3150 }
3151 
mov_write_iinf_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)3152 static int mov_write_iinf_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
3153 {
3154     int64_t iinf_pos = avio_tell(pb);
3155     avio_wb32(pb, 0); /* size */
3156     ffio_wfourcc(pb, "iinf");
3157     avio_wb32(pb, 0); /* Version & flags */
3158     avio_wb16(pb, s->nb_streams); /* entry_count */
3159 
3160     for (int i = 0; i < s->nb_streams; i++) {
3161         int64_t infe_pos = avio_tell(pb);
3162         avio_wb32(pb, 0); /* size */
3163         ffio_wfourcc(pb, "infe");
3164         avio_w8(pb, 0x2); /* Version */
3165         avio_wb24(pb, 0); /* flags */
3166         avio_wb16(pb, i + 1); /* item_id */
3167         avio_wb16(pb, 0); /* item_protection_index */
3168         avio_write(pb, "av01", 4); /* item_type */
3169         avio_write(pb, !i ? "Color\0" : "Alpha\0", 6); /* item_name */
3170         update_size(pb, infe_pos);
3171     }
3172 
3173     return update_size(pb, iinf_pos);
3174 }
3175 
3176 
mov_write_iref_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)3177 static int mov_write_iref_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
3178 {
3179     int64_t auxl_pos;
3180     int64_t iref_pos = avio_tell(pb);
3181     avio_wb32(pb, 0); /* size */
3182     ffio_wfourcc(pb, "iref");
3183     avio_wb32(pb, 0); /* Version & flags */
3184 
3185     auxl_pos = avio_tell(pb);
3186     avio_wb32(pb, 0); /* size */
3187     ffio_wfourcc(pb, "auxl");
3188     avio_wb16(pb, 2); /* from_item_ID */
3189     avio_wb16(pb, 1); /* reference_count */
3190     avio_wb16(pb, 1); /* to_item_ID */
3191     update_size(pb, auxl_pos);
3192 
3193     return update_size(pb, iref_pos);
3194 }
3195 
mov_write_ispe_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s, int stream_index)3196 static int mov_write_ispe_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s,
3197                               int stream_index)
3198 {
3199     int64_t pos = avio_tell(pb);
3200     avio_wb32(pb, 0); /* size */
3201     ffio_wfourcc(pb, "ispe");
3202     avio_wb32(pb, 0); /* Version & flags */
3203     avio_wb32(pb, s->streams[stream_index]->codecpar->width); /* image_width */
3204     avio_wb32(pb, s->streams[stream_index]->codecpar->height); /* image_height */
3205     return update_size(pb, pos);
3206 }
3207 
mov_write_pixi_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s, int stream_index)3208 static int mov_write_pixi_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s,
3209                               int stream_index)
3210 {
3211     int64_t pos = avio_tell(pb);
3212     const AVPixFmtDescriptor *pixdesc =
3213         av_pix_fmt_desc_get(s->streams[stream_index]->codecpar->format);
3214     avio_wb32(pb, 0); /* size */
3215     ffio_wfourcc(pb, "pixi");
3216     avio_wb32(pb, 0); /* Version & flags */
3217     avio_w8(pb, pixdesc->nb_components); /* num_channels */
3218     for (int i = 0; i < pixdesc->nb_components; ++i) {
3219       avio_w8(pb, pixdesc->comp[i].depth); /* bits_per_channel */
3220     }
3221     return update_size(pb, pos);
3222 }
3223 
mov_write_auxC_tag(AVIOContext *pb)3224 static int mov_write_auxC_tag(AVIOContext *pb)
3225 {
3226     int64_t pos = avio_tell(pb);
3227     avio_wb32(pb, 0); /* size */
3228     ffio_wfourcc(pb, "auxC");
3229     avio_wb32(pb, 0); /* Version & flags */
3230     avio_write(pb, "urn:mpeg:mpegB:cicp:systems:auxiliary:alpha\0", 44);
3231     return update_size(pb, pos);
3232 }
3233 
mov_write_ipco_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)3234 static int mov_write_ipco_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
3235 {
3236     int64_t pos = avio_tell(pb);
3237     avio_wb32(pb, 0); /* size */
3238     ffio_wfourcc(pb, "ipco");
3239     for (int i = 0; i < s->nb_streams; i++) {
3240         mov_write_ispe_tag(pb, mov, s, i);
3241         mov_write_pixi_tag(pb, mov, s, i);
3242         mov_write_av1c_tag(pb, &mov->tracks[i]);
3243         if (!i)
3244             mov_write_colr_tag(pb, &mov->tracks[0], 0);
3245         else
3246             mov_write_auxC_tag(pb);
3247     }
3248     return update_size(pb, pos);
3249 }
3250 
mov_write_ipma_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)3251 static int mov_write_ipma_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
3252 {
3253     int64_t pos = avio_tell(pb);
3254     avio_wb32(pb, 0); /* size */
3255     ffio_wfourcc(pb, "ipma");
3256     avio_wb32(pb, 0); /* Version & flags */
3257     avio_wb32(pb, s->nb_streams); /* entry_count */
3258 
3259     for (int i = 0, index = 1; i < s->nb_streams; i++) {
3260         avio_wb16(pb, i + 1); /* item_ID */
3261         avio_w8(pb, 4); /* association_count */
3262 
3263         // ispe association.
3264         avio_w8(pb, index++); /* essential and property_index */
3265         // pixi association.
3266         avio_w8(pb, index++); /* essential and property_index */
3267         // av1C association.
3268         avio_w8(pb, 0x80 | index++); /* essential and property_index */
3269         // colr/auxC association.
3270         avio_w8(pb, index++); /* essential and property_index */
3271     }
3272     return update_size(pb, pos);
3273 }
3274 
mov_write_iprp_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)3275 static int mov_write_iprp_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
3276 {
3277     int64_t pos = avio_tell(pb);
3278     avio_wb32(pb, 0); /* size */
3279     ffio_wfourcc(pb, "iprp");
3280     mov_write_ipco_tag(pb, mov, s);
3281     mov_write_ipma_tag(pb, mov, s);
3282     return update_size(pb, pos);
3283 }
3284 
mov_write_hmhd_tag(AVIOContext *pb)3285 static int mov_write_hmhd_tag(AVIOContext *pb)
3286 {
3287     /* This atom must be present, but leaving the values at zero
3288      * seems harmless. */
3289     avio_wb32(pb, 28); /* size */
3290     ffio_wfourcc(pb, "hmhd");
3291     avio_wb32(pb, 0); /* version, flags */
3292     avio_wb16(pb, 0); /* maxPDUsize */
3293     avio_wb16(pb, 0); /* avgPDUsize */
3294     avio_wb32(pb, 0); /* maxbitrate */
3295     avio_wb32(pb, 0); /* avgbitrate */
3296     avio_wb32(pb, 0); /* reserved */
3297     return 28;
3298 }
3299 
mov_write_minf_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)3300 static int mov_write_minf_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
3301 {
3302     int64_t pos = avio_tell(pb);
3303     int ret;
3304 
3305     avio_wb32(pb, 0); /* size */
3306     ffio_wfourcc(pb, "minf");
3307     if (track->par->codec_type == AVMEDIA_TYPE_VIDEO)
3308         mov_write_vmhd_tag(pb);
3309     else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO)
3310         mov_write_smhd_tag(pb);
3311     else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE) {
3312         if (track->tag == MKTAG('t','e','x','t') || is_clcp_track(track)) {
3313             mov_write_gmhd_tag(pb, track);
3314         } else if (track->tag == MOV_MP4_TTML_TAG) {
3315             mov_write_sthd_tag(pb);
3316         } else {
3317             mov_write_nmhd_tag(pb);
3318         }
3319     } else if (track->tag == MKTAG('r','t','p',' ')) {
3320         mov_write_hmhd_tag(pb);
3321     } else if (track->tag == MKTAG('t','m','c','d')) {
3322         if (track->mode != MODE_MOV)
3323             mov_write_nmhd_tag(pb);
3324         else
3325             mov_write_gmhd_tag(pb, track);
3326     } else if (track->tag == MKTAG('g','p','m','d')) {
3327         mov_write_gmhd_tag(pb, track);
3328     }
3329     if (track->mode == MODE_MOV) /* ISO 14496-12 8.4.3.1 specifies hdlr only within mdia or meta boxes */
3330         mov_write_hdlr_tag(s, pb, NULL);
3331     mov_write_dinf_tag(pb);
3332     if ((ret = mov_write_stbl_tag(s, pb, mov, track)) < 0)
3333         return ret;
3334     return update_size(pb, pos);
3335 }
3336 
get_pts_range(MOVMuxContext *mov, MOVTrack *track, int64_t *start, int64_t *end)3337 static void get_pts_range(MOVMuxContext *mov, MOVTrack *track,
3338                           int64_t *start, int64_t *end)
3339 {
3340 #ifdef OHOS_TIMED_META_TRACK
3341     if ((track->tag == MKTAG('t','m','c','d') && mov->nb_meta_tmcd) ||
3342         (track->tag == MKTAG('c','d','s','c'))) {
3343 #else
3344     if (track->tag == MKTAG('t','m','c','d') && mov->nb_meta_tmcd) {
3345 #endif
3346         // tmcd tracks gets track_duration set in mov_write_moov_tag from
3347         // another track's duration, while the end_pts may be left at zero.
3348         // Calculate the pts duration for that track instead.
3349         get_pts_range(mov, &mov->tracks[track->src_track], start, end);
3350         *start = av_rescale(*start, track->timescale,
3351                             mov->tracks[track->src_track].timescale);
3352         *end   = av_rescale(*end, track->timescale,
3353                             mov->tracks[track->src_track].timescale);
3354         return;
3355     }
3356     if (track->end_pts != AV_NOPTS_VALUE &&
3357         track->start_dts != AV_NOPTS_VALUE &&
3358         track->start_cts != AV_NOPTS_VALUE) {
3359         *start = track->start_dts + track->start_cts;
3360         *end   = track->end_pts;
3361         return;
3362     }
3363     *start = 0;
3364     *end   = track->track_duration;
3365 }
3366 
3367 static int64_t calc_samples_pts_duration(MOVMuxContext *mov, MOVTrack *track)
3368 {
3369     int64_t start, end;
3370     get_pts_range(mov, track, &start, &end);
3371     return end - start;
3372 }
3373 
3374 // Calculate the actual duration of the track, after edits.
3375 // If it starts with a pts < 0, that is removed by the edit list.
3376 // If it starts with a pts > 0, the edit list adds a delay before that.
3377 // Thus, with edit lists enabled, the post-edit output of the file is
3378 // starting with pts=0.
3379 static int64_t calc_pts_duration(MOVMuxContext *mov, MOVTrack *track)
3380 {
3381     int64_t start, end;
3382     get_pts_range(mov, track, &start, &end);
3383     if (mov->use_editlist != 0)
3384         start = 0;
3385     return end - start;
3386 }
3387 
3388 static int mov_write_mdhd_tag(AVIOContext *pb, MOVMuxContext *mov,
3389                               MOVTrack *track)
3390 {
3391     int64_t duration = calc_samples_pts_duration(mov, track);
3392     int version = duration < INT32_MAX ? 0 : 1;
3393 
3394     if (track->mode == MODE_ISM)
3395         version = 1;
3396 
3397     (version == 1) ? avio_wb32(pb, 44) : avio_wb32(pb, 32); /* size */
3398     ffio_wfourcc(pb, "mdhd");
3399     avio_w8(pb, version);
3400     avio_wb24(pb, 0); /* flags */
3401     if (version == 1) {
3402         avio_wb64(pb, track->time);
3403         avio_wb64(pb, track->time);
3404     } else {
3405         avio_wb32(pb, track->time); /* creation time */
3406         avio_wb32(pb, track->time); /* modification time */
3407     }
3408     avio_wb32(pb, track->timescale); /* time scale (sample rate for audio) */
3409     if (!track->entry && mov->mode == MODE_ISM)
3410         (version == 1) ? avio_wb64(pb, UINT64_C(0xffffffffffffffff)) : avio_wb32(pb, 0xffffffff);
3411     else if (!track->entry)
3412         (version == 1) ? avio_wb64(pb, 0) : avio_wb32(pb, 0);
3413     else
3414         (version == 1) ? avio_wb64(pb, duration) : avio_wb32(pb, duration); /* duration */
3415     avio_wb16(pb, track->language); /* language */
3416     avio_wb16(pb, 0); /* reserved (quality) */
3417 
3418     if (version != 0 && track->mode == MODE_MOV) {
3419         av_log(NULL, AV_LOG_ERROR,
3420                "FATAL error, file duration too long for timebase, this file will not be\n"
3421                "playable with QuickTime. Choose a different timebase with "
3422                "-video_track_timescale or a different container format\n");
3423     }
3424 
3425     return 32;
3426 }
3427 
3428 static int mov_write_mdia_tag(AVFormatContext *s, AVIOContext *pb,
3429                               MOVMuxContext *mov, MOVTrack *track)
3430 {
3431     int64_t pos = avio_tell(pb);
3432     int ret;
3433 
3434     avio_wb32(pb, 0); /* size */
3435     ffio_wfourcc(pb, "mdia");
3436     mov_write_mdhd_tag(pb, mov, track);
3437     mov_write_hdlr_tag(s, pb, track);
3438     if ((ret = mov_write_minf_tag(s, pb, mov, track)) < 0)
3439         return ret;
3440     return update_size(pb, pos);
3441 }
3442 
3443 /* transformation matrix
3444      |a  b  u|
3445      |c  d  v|
3446      |tx ty w| */
3447 static void write_matrix(AVIOContext *pb, int16_t a, int16_t b, int16_t c,
3448                          int16_t d, int16_t tx, int16_t ty)
3449 {
3450     avio_wb32(pb, a << 16);  /* 16.16 format */
3451     avio_wb32(pb, b << 16);  /* 16.16 format */
3452     avio_wb32(pb, 0);        /* u in 2.30 format */
3453     avio_wb32(pb, c << 16);  /* 16.16 format */
3454     avio_wb32(pb, d << 16);  /* 16.16 format */
3455     avio_wb32(pb, 0);        /* v in 2.30 format */
3456     avio_wb32(pb, tx << 16); /* 16.16 format */
3457     avio_wb32(pb, ty << 16); /* 16.16 format */
3458     avio_wb32(pb, 1 << 30);  /* w in 2.30 format */
3459 }
3460 
3461 static int mov_write_tkhd_tag(AVIOContext *pb, MOVMuxContext *mov,
3462                               MOVTrack *track, AVStream *st)
3463 {
3464     int64_t duration = av_rescale_rnd(calc_pts_duration(mov, track),
3465                                       mov->movie_timescale, track->timescale,
3466                                       AV_ROUND_UP);
3467     int version = duration < INT32_MAX ? 0 : 1;
3468     int flags   = MOV_TKHD_FLAG_IN_MOVIE;
3469     int group   = 0;
3470 
3471     uint32_t *display_matrix = NULL;
3472     size_t display_matrix_size;
3473     int       i;
3474 
3475     if (st) {
3476         if (mov->per_stream_grouping)
3477             group = st->index;
3478         else
3479             group = st->codecpar->codec_type;
3480 
3481         display_matrix = (uint32_t*)av_stream_get_side_data(st, AV_PKT_DATA_DISPLAYMATRIX,
3482                                                             &display_matrix_size);
3483         if (display_matrix && display_matrix_size < 9 * sizeof(*display_matrix))
3484             display_matrix = NULL;
3485     }
3486 
3487     if (track->flags & MOV_TRACK_ENABLED)
3488         flags |= MOV_TKHD_FLAG_ENABLED;
3489 
3490     if (track->mode == MODE_ISM)
3491         version = 1;
3492 
3493     (version == 1) ? avio_wb32(pb, 104) : avio_wb32(pb, 92); /* size */
3494     ffio_wfourcc(pb, "tkhd");
3495     avio_w8(pb, version);
3496     avio_wb24(pb, flags);
3497     if (version == 1) {
3498         avio_wb64(pb, track->time);
3499         avio_wb64(pb, track->time);
3500     } else {
3501         avio_wb32(pb, track->time); /* creation time */
3502         avio_wb32(pb, track->time); /* modification time */
3503     }
3504     avio_wb32(pb, track->track_id); /* track-id */
3505     avio_wb32(pb, 0); /* reserved */
3506     if (!track->entry && mov->mode == MODE_ISM)
3507         (version == 1) ? avio_wb64(pb, UINT64_C(0xffffffffffffffff)) : avio_wb32(pb, 0xffffffff);
3508     else if (!track->entry)
3509         (version == 1) ? avio_wb64(pb, 0) : avio_wb32(pb, 0);
3510     else
3511         (version == 1) ? avio_wb64(pb, duration) : avio_wb32(pb, duration);
3512 
3513     avio_wb32(pb, 0); /* reserved */
3514     avio_wb32(pb, 0); /* reserved */
3515     avio_wb16(pb, 0); /* layer */
3516     avio_wb16(pb, group); /* alternate group) */
3517     /* Volume, only for audio */
3518     if (track->par->codec_type == AVMEDIA_TYPE_AUDIO)
3519         avio_wb16(pb, 0x0100);
3520     else
3521         avio_wb16(pb, 0);
3522     avio_wb16(pb, 0); /* reserved */
3523 
3524     /* Matrix structure */
3525     if (display_matrix) {
3526         for (i = 0; i < 9; i++)
3527             avio_wb32(pb, display_matrix[i]);
3528     } else {
3529         write_matrix(pb,  1,  0,  0,  1, 0, 0);
3530     }
3531     /* Track width and height, for visual only */
3532     if (st && (track->par->codec_type == AVMEDIA_TYPE_VIDEO ||
3533                track->par->codec_type == AVMEDIA_TYPE_SUBTITLE)) {
3534         int64_t track_width_1616;
3535         if (track->mode == MODE_MOV || track->mode == MODE_AVIF) {
3536             track_width_1616 = track->par->width * 0x10000ULL;
3537         } else {
3538             track_width_1616 = av_rescale(st->sample_aspect_ratio.num,
3539                                                   track->par->width * 0x10000LL,
3540                                                   st->sample_aspect_ratio.den);
3541             if (!track_width_1616 ||
3542                 track->height != track->par->height ||
3543                 track_width_1616 > UINT32_MAX)
3544                 track_width_1616 = track->par->width * 0x10000ULL;
3545         }
3546         if (track_width_1616 > UINT32_MAX) {
3547             av_log(mov->fc, AV_LOG_WARNING, "track width is too large\n");
3548             track_width_1616 = 0;
3549         }
3550         avio_wb32(pb, track_width_1616);
3551         if (track->height > 0xFFFF) {
3552             av_log(mov->fc, AV_LOG_WARNING, "track height is too large\n");
3553             avio_wb32(pb, 0);
3554         } else
3555             avio_wb32(pb, track->height * 0x10000U);
3556     } else {
3557         avio_wb32(pb, 0);
3558         avio_wb32(pb, 0);
3559     }
3560     return 0x5c;
3561 }
3562 
3563 static int mov_write_tapt_tag(AVIOContext *pb, MOVTrack *track)
3564 {
3565     int32_t width = av_rescale(track->par->sample_aspect_ratio.num, track->par->width,
3566                                track->par->sample_aspect_ratio.den);
3567 
3568     int64_t pos = avio_tell(pb);
3569 
3570     avio_wb32(pb, 0); /* size */
3571     ffio_wfourcc(pb, "tapt");
3572 
3573     avio_wb32(pb, 20);
3574     ffio_wfourcc(pb, "clef");
3575     avio_wb32(pb, 0);
3576     avio_wb32(pb, width << 16);
3577     avio_wb32(pb, track->par->height << 16);
3578 
3579     avio_wb32(pb, 20);
3580     ffio_wfourcc(pb, "prof");
3581     avio_wb32(pb, 0);
3582     avio_wb32(pb, width << 16);
3583     avio_wb32(pb, track->par->height << 16);
3584 
3585     avio_wb32(pb, 20);
3586     ffio_wfourcc(pb, "enof");
3587     avio_wb32(pb, 0);
3588     avio_wb32(pb, track->par->width << 16);
3589     avio_wb32(pb, track->par->height << 16);
3590 
3591     return update_size(pb, pos);
3592 }
3593 
3594 // This box seems important for the psp playback ... without it the movie seems to hang
3595 static int mov_write_edts_tag(AVIOContext *pb, MOVMuxContext *mov,
3596                               MOVTrack *track)
3597 {
3598     int64_t duration = av_rescale_rnd(calc_samples_pts_duration(mov, track),
3599                                       mov->movie_timescale, track->timescale,
3600                                       AV_ROUND_UP);
3601     int version = duration < INT32_MAX ? 0 : 1;
3602     int entry_size, entry_count, size;
3603     int64_t delay, start_ct = track->start_cts;
3604     int64_t start_dts = track->start_dts;
3605 
3606     if (track->entry) {
3607         if (start_dts != track->cluster[0].dts || start_ct != track->cluster[0].cts) {
3608 
3609             av_log(mov->fc, AV_LOG_DEBUG,
3610                    "EDTS using dts:%"PRId64" cts:%d instead of dts:%"PRId64" cts:%"PRId64" tid:%d\n",
3611                    track->cluster[0].dts, track->cluster[0].cts,
3612                    start_dts, start_ct, track->track_id);
3613             start_dts = track->cluster[0].dts;
3614             start_ct  = track->cluster[0].cts;
3615         }
3616     }
3617 
3618     delay = av_rescale_rnd(start_dts + start_ct, mov->movie_timescale,
3619                            track->timescale, AV_ROUND_DOWN);
3620     version |= delay < INT32_MAX ? 0 : 1;
3621 
3622     entry_size = (version == 1) ? 20 : 12;
3623     entry_count = 1 + (delay > 0);
3624     size = 24 + entry_count * entry_size;
3625 
3626     /* write the atom data */
3627     avio_wb32(pb, size);
3628     ffio_wfourcc(pb, "edts");
3629     avio_wb32(pb, size - 8);
3630     ffio_wfourcc(pb, "elst");
3631     avio_w8(pb, version);
3632     avio_wb24(pb, 0); /* flags */
3633 
3634     avio_wb32(pb, entry_count);
3635     if (delay > 0) { /* add an empty edit to delay presentation */
3636         /* In the positive delay case, the delay includes the cts
3637          * offset, and the second edit list entry below trims out
3638          * the same amount from the actual content. This makes sure
3639          * that the offset last sample is included in the edit
3640          * list duration as well. */
3641         if (version == 1) {
3642             avio_wb64(pb, delay);
3643             avio_wb64(pb, -1);
3644         } else {
3645             avio_wb32(pb, delay);
3646             avio_wb32(pb, -1);
3647         }
3648         avio_wb32(pb, 0x00010000);
3649     } else {
3650         /* Avoid accidentally ending up with start_ct = -1 which has got a
3651          * special meaning. Normally start_ct should end up positive or zero
3652          * here, but use FFMIN in case dts is a small positive integer
3653          * rounded to 0 when represented in movie timescale units. */
3654         av_assert0(av_rescale_rnd(start_dts, mov->movie_timescale, track->timescale, AV_ROUND_DOWN) <= 0);
3655         start_ct  = -FFMIN(start_dts, 0);
3656         /* Note, this delay is calculated from the pts of the first sample,
3657          * ensuring that we don't reduce the duration for cases with
3658          * dts<0 pts=0. */
3659         duration += delay;
3660     }
3661 
3662     /* For fragmented files, we don't know the full length yet. Setting
3663      * duration to 0 allows us to only specify the offset, including
3664      * the rest of the content (from all future fragments) without specifying
3665      * an explicit duration. */
3666     if (mov->flags & FF_MOV_FLAG_FRAGMENT)
3667         duration = 0;
3668 
3669     /* duration */
3670     if (version == 1) {
3671         avio_wb64(pb, duration);
3672         avio_wb64(pb, start_ct);
3673     } else {
3674         avio_wb32(pb, duration);
3675         avio_wb32(pb, start_ct);
3676     }
3677     avio_wb32(pb, 0x00010000);
3678     return size;
3679 }
3680 
3681 static int mov_write_tref_tag(AVIOContext *pb, MOVTrack *track)
3682 {
3683 #ifdef OHOS_TIMED_META_TRACK
3684     int64_t pos = avio_tell(pb);
3685     int tref_index;
3686     avio_wb32(pb, 0);
3687     ffio_wfourcc(pb, "tref");
3688     int64_t pos_cdsc = avio_tell(pb);
3689     avio_wb32(pb, 0);
3690     avio_wl32(pb, track->tref_tag);
3691     for (tref_index = 0; tref_index < track->ref_track_count; tref_index++) {
3692         avio_wb32(pb, track->tref_ids[tref_index]);
3693     }
3694     update_size(pb, pos_cdsc);
3695     return update_size(pb, pos);
3696 #else
3697     avio_wb32(pb, 20);   // size
3698     ffio_wfourcc(pb, "tref");
3699     avio_wb32(pb, 12);   // size (subatom)
3700     avio_wl32(pb, track->tref_tag);
3701     avio_wb32(pb, track->tref_id);
3702     return 20;
3703 #endif
3704 }
3705 
3706 // goes at the end of each track!  ... Critical for PSP playback ("Incompatible data" without it)
3707 static int mov_write_uuid_tag_psp(AVIOContext *pb, MOVTrack *mov)
3708 {
3709     avio_wb32(pb, 0x34); /* size ... reports as 28 in mp4box! */
3710     ffio_wfourcc(pb, "uuid");
3711     ffio_wfourcc(pb, "USMT");
3712     avio_wb32(pb, 0x21d24fce);
3713     avio_wb32(pb, 0xbb88695c);
3714     avio_wb32(pb, 0xfac9c740);
3715     avio_wb32(pb, 0x1c);     // another size here!
3716     ffio_wfourcc(pb, "MTDT");
3717     avio_wb32(pb, 0x00010012);
3718     avio_wb32(pb, 0x0a);
3719     avio_wb32(pb, 0x55c40000);
3720     avio_wb32(pb, 0x1);
3721     avio_wb32(pb, 0x0);
3722     return 0x34;
3723 }
3724 
3725 static int mov_write_udta_sdp(AVIOContext *pb, MOVTrack *track)
3726 {
3727     AVFormatContext *ctx = track->rtp_ctx;
3728     char buf[1000] = "";
3729     int len;
3730 
3731     ff_sdp_write_media(buf, sizeof(buf), ctx->streams[0], track->src_track,
3732                        NULL, NULL, 0, 0, ctx);
3733     av_strlcatf(buf, sizeof(buf), "a=control:streamid=%d\r\n", track->track_id);
3734     len = strlen(buf);
3735 
3736     avio_wb32(pb, len + 24);
3737     ffio_wfourcc(pb, "udta");
3738     avio_wb32(pb, len + 16);
3739     ffio_wfourcc(pb, "hnti");
3740     avio_wb32(pb, len + 8);
3741     ffio_wfourcc(pb, "sdp ");
3742     avio_write(pb, buf, len);
3743     return len + 24;
3744 }
3745 
3746 static int mov_write_track_metadata(AVIOContext *pb, AVStream *st,
3747                                     const char *tag, const char *str)
3748 {
3749     int64_t pos = avio_tell(pb);
3750     AVDictionaryEntry *t = av_dict_get(st->metadata, str, NULL, 0);
3751     if (!t || !utf8len(t->value))
3752         return 0;
3753 
3754     avio_wb32(pb, 0);   /* size */
3755     ffio_wfourcc(pb, tag); /* type */
3756     avio_write(pb, t->value, strlen(t->value)); /* UTF8 string value */
3757     return update_size(pb, pos);
3758 }
3759 
3760 static int mov_write_track_kind(AVIOContext *pb, const char *scheme_uri,
3761                                 const char *value)
3762 {
3763     int64_t pos = avio_tell(pb);
3764 
3765     /* Box|FullBox basics */
3766     avio_wb32(pb, 0); /* size placeholder */
3767     ffio_wfourcc(pb, (const unsigned char *)"kind");
3768     avio_w8(pb, 0);   /* version = 0 */
3769     avio_wb24(pb, 0); /* flags = 0 */
3770 
3771     /* Required null-terminated scheme URI */
3772     avio_write(pb, (const unsigned char *)scheme_uri,
3773                strlen(scheme_uri));
3774     avio_w8(pb, 0);
3775 
3776     /* Optional value string */
3777     if (value && value[0])
3778         avio_write(pb, (const unsigned char *)value,
3779                    strlen(value));
3780 
3781     avio_w8(pb, 0);
3782 
3783     return update_size(pb, pos);
3784 }
3785 
3786 static int mov_write_track_kinds(AVIOContext *pb, AVStream *st)
3787 {
3788     int ret = AVERROR_BUG;
3789 
3790     for (int i = 0; ff_mov_track_kind_table[i].scheme_uri; i++) {
3791         const struct MP4TrackKindMapping map = ff_mov_track_kind_table[i];
3792 
3793         for (int j = 0; map.value_maps[j].disposition; j++) {
3794             const struct MP4TrackKindValueMapping value_map = map.value_maps[j];
3795             if (!(st->disposition & value_map.disposition))
3796                 continue;
3797 
3798             if ((ret = mov_write_track_kind(pb, map.scheme_uri, value_map.value)) < 0)
3799                 return ret;
3800         }
3801     }
3802 
3803     return 0;
3804 }
3805 
3806 static int mov_write_track_udta_tag(AVIOContext *pb, MOVMuxContext *mov,
3807                                     AVStream *st)
3808 {
3809     AVIOContext *pb_buf;
3810     int ret, size;
3811     uint8_t *buf;
3812 
3813     if (!st)
3814         return 0;
3815 
3816     ret = avio_open_dyn_buf(&pb_buf);
3817     if (ret < 0)
3818         return ret;
3819 
3820     if (mov->mode & (MODE_MP4|MODE_MOV))
3821         mov_write_track_metadata(pb_buf, st, "name", "title");
3822 
3823     if (mov->mode & MODE_MP4) {
3824         if ((ret = mov_write_track_kinds(pb_buf, st)) < 0)
3825             return ret;
3826     }
3827 
3828     if ((size = avio_get_dyn_buf(pb_buf, &buf)) > 0) {
3829         avio_wb32(pb, size + 8);
3830         ffio_wfourcc(pb, "udta");
3831         avio_write(pb, buf, size);
3832     }
3833     ffio_free_dyn_buf(&pb_buf);
3834 
3835     return 0;
3836 }
3837 
3838 static int mov_write_trak_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov,
3839                               MOVTrack *track, AVStream *st)
3840 {
3841     int64_t pos = avio_tell(pb);
3842     int entry_backup = track->entry;
3843     int chunk_backup = track->chunkCount;
3844     int ret;
3845 
3846     /* If we want to have an empty moov, but some samples already have been
3847      * buffered (delay_moov), pretend that no samples have been written yet. */
3848     if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV)
3849         track->chunkCount = track->entry = 0;
3850 
3851     avio_wb32(pb, 0); /* size */
3852     ffio_wfourcc(pb, "trak");
3853     mov_write_tkhd_tag(pb, mov, track, st);
3854 
3855     av_assert2(mov->use_editlist >= 0);
3856 
3857     if (track->start_dts != AV_NOPTS_VALUE) {
3858         if (mov->use_editlist)
3859             mov_write_edts_tag(pb, mov, track);  // PSP Movies and several other cases require edts box
3860         else if ((track->entry && track->cluster[0].dts) || track->mode == MODE_PSP || is_clcp_track(track))
3861             av_log(mov->fc, AV_LOG_WARNING,
3862                    "Not writing any edit list even though one would have been required\n");
3863     }
3864 
3865     if (track->tref_tag)
3866         mov_write_tref_tag(pb, track);
3867 
3868     if ((ret = mov_write_mdia_tag(s, pb, mov, track)) < 0)
3869         return ret;
3870     if (track->mode == MODE_PSP)
3871         mov_write_uuid_tag_psp(pb, track); // PSP Movies require this uuid box
3872     if (track->tag == MKTAG('r','t','p',' '))
3873         mov_write_udta_sdp(pb, track);
3874     if (track->mode == MODE_MOV) {
3875         if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
3876             double sample_aspect_ratio = av_q2d(st->sample_aspect_ratio);
3877             if (st->sample_aspect_ratio.num && 1.0 != sample_aspect_ratio) {
3878                 mov_write_tapt_tag(pb, track);
3879             }
3880         }
3881         if (is_clcp_track(track) && st->sample_aspect_ratio.num) {
3882             mov_write_tapt_tag(pb, track);
3883         }
3884     }
3885     mov_write_track_udta_tag(pb, mov, st);
3886     track->entry = entry_backup;
3887     track->chunkCount = chunk_backup;
3888     return update_size(pb, pos);
3889 }
3890 
3891 static int mov_write_iods_tag(AVIOContext *pb, MOVMuxContext *mov)
3892 {
3893     int i, has_audio = 0, has_video = 0;
3894     int64_t pos = avio_tell(pb);
3895     int audio_profile = mov->iods_audio_profile;
3896     int video_profile = mov->iods_video_profile;
3897     for (i = 0; i < mov->nb_streams; i++) {
3898         if (mov->tracks[i].entry > 0 || mov->flags & FF_MOV_FLAG_EMPTY_MOOV) {
3899             has_audio |= mov->tracks[i].par->codec_type == AVMEDIA_TYPE_AUDIO;
3900             has_video |= mov->tracks[i].par->codec_type == AVMEDIA_TYPE_VIDEO;
3901         }
3902     }
3903     if (audio_profile < 0)
3904         audio_profile = 0xFF - has_audio;
3905     if (video_profile < 0)
3906         video_profile = 0xFF - has_video;
3907     avio_wb32(pb, 0x0); /* size */
3908     ffio_wfourcc(pb, "iods");
3909     avio_wb32(pb, 0);    /* version & flags */
3910     put_descr(pb, 0x10, 7);
3911     avio_wb16(pb, 0x004f);
3912     avio_w8(pb, 0xff);
3913     avio_w8(pb, 0xff);
3914     avio_w8(pb, audio_profile);
3915     avio_w8(pb, video_profile);
3916     avio_w8(pb, 0xff);
3917     return update_size(pb, pos);
3918 }
3919 
3920 static int mov_write_trex_tag(AVIOContext *pb, MOVTrack *track)
3921 {
3922     avio_wb32(pb, 0x20); /* size */
3923     ffio_wfourcc(pb, "trex");
3924     avio_wb32(pb, 0);   /* version & flags */
3925     avio_wb32(pb, track->track_id); /* track ID */
3926     avio_wb32(pb, 1);   /* default sample description index */
3927     avio_wb32(pb, 0);   /* default sample duration */
3928     avio_wb32(pb, 0);   /* default sample size */
3929     avio_wb32(pb, 0);   /* default sample flags */
3930     return 0;
3931 }
3932 
3933 static int mov_write_mvex_tag(AVIOContext *pb, MOVMuxContext *mov)
3934 {
3935     int64_t pos = avio_tell(pb);
3936     int i;
3937     avio_wb32(pb, 0x0); /* size */
3938     ffio_wfourcc(pb, "mvex");
3939     for (i = 0; i < mov->nb_streams; i++)
3940         mov_write_trex_tag(pb, &mov->tracks[i]);
3941     return update_size(pb, pos);
3942 }
3943 
3944 static int mov_write_mvhd_tag(AVIOContext *pb, MOVMuxContext *mov)
3945 {
3946     int max_track_id = 1, i;
3947     int64_t max_track_len = 0;
3948     int version;
3949     int timescale;
3950 
3951     for (i = 0; i < mov->nb_streams; i++) {
3952         if (mov->tracks[i].entry > 0 && mov->tracks[i].timescale) {
3953             int64_t max_track_len_temp = av_rescale_rnd(
3954                                                 calc_pts_duration(mov, &mov->tracks[i]),
3955                                                 mov->movie_timescale,
3956                                                 mov->tracks[i].timescale,
3957                                                 AV_ROUND_UP);
3958             if (max_track_len < max_track_len_temp)
3959                 max_track_len = max_track_len_temp;
3960             if (max_track_id < mov->tracks[i].track_id)
3961                 max_track_id = mov->tracks[i].track_id;
3962         }
3963     }
3964     /* If using delay_moov, make sure the output is the same as if no
3965      * samples had been written yet. */
3966     if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV) {
3967         max_track_len = 0;
3968         max_track_id  = 1;
3969     }
3970 
3971     version = max_track_len < UINT32_MAX ? 0 : 1;
3972     avio_wb32(pb, version == 1 ? 120 : 108); /* size */
3973 
3974     ffio_wfourcc(pb, "mvhd");
3975     avio_w8(pb, version);
3976     avio_wb24(pb, 0); /* flags */
3977     if (version == 1) {
3978         avio_wb64(pb, mov->time);
3979         avio_wb64(pb, mov->time);
3980     } else {
3981         avio_wb32(pb, mov->time); /* creation time */
3982         avio_wb32(pb, mov->time); /* modification time */
3983     }
3984 
3985     timescale = mov->movie_timescale;
3986     if (mov->mode == MODE_AVIF && !timescale)
3987         timescale = mov->tracks[0].timescale;
3988 
3989     avio_wb32(pb, timescale);
3990     (version == 1) ? avio_wb64(pb, max_track_len) : avio_wb32(pb, max_track_len); /* duration of longest track */
3991 
3992     avio_wb32(pb, 0x00010000); /* reserved (preferred rate) 1.0 = normal */
3993     avio_wb16(pb, 0x0100); /* reserved (preferred volume) 1.0 = normal */
3994     ffio_fill(pb, 0, 2 + 2 * 4); /* reserved */
3995 
3996     /* Matrix structure */
3997     write_matrix(pb, 1, 0, 0, 1, 0, 0);
3998 
3999     avio_wb32(pb, 0); /* reserved (preview time) */
4000     avio_wb32(pb, 0); /* reserved (preview duration) */
4001     avio_wb32(pb, 0); /* reserved (poster time) */
4002     avio_wb32(pb, 0); /* reserved (selection time) */
4003     avio_wb32(pb, 0); /* reserved (selection duration) */
4004     avio_wb32(pb, 0); /* reserved (current time) */
4005     avio_wb32(pb, max_track_id + 1); /* Next track id */
4006     return 0x6c;
4007 }
4008 
4009 static int mov_write_itunes_hdlr_tag(AVIOContext *pb, MOVMuxContext *mov,
4010                                      AVFormatContext *s)
4011 {
4012     avio_wb32(pb, 33); /* size */
4013     ffio_wfourcc(pb, "hdlr");
4014     avio_wb32(pb, 0);
4015     avio_wb32(pb, 0);
4016     ffio_wfourcc(pb, "mdir");
4017     ffio_wfourcc(pb, "appl");
4018     avio_wb32(pb, 0);
4019     avio_wb32(pb, 0);
4020     avio_w8(pb, 0);
4021     return 33;
4022 }
4023 
4024 /* helper function to write a data tag with the specified string as data */
4025 static int mov_write_string_data_tag(AVIOContext *pb, const char *data, int lang, int long_style)
4026 {
4027     size_t data_len = strlen(data);
4028     if (long_style) {
4029         int size = 16 + data_len;
4030         avio_wb32(pb, size); /* size */
4031         ffio_wfourcc(pb, "data");
4032         avio_wb32(pb, 1);
4033         avio_wb32(pb, 0);
4034         avio_write(pb, data, data_len);
4035         return size;
4036     } else {
4037         avio_wb16(pb, data_len); /* string length */
4038         if (!lang)
4039             lang = ff_mov_iso639_to_lang("und", 1);
4040         avio_wb16(pb, lang);
4041         avio_write(pb, data, data_len);
4042         return data_len + 4;
4043     }
4044 }
4045 
4046 #ifdef OHOS_MOOV_LEVEL_META
4047 static int mov_write_moov_level_meta_data_tag(AVIOContext *pb, const char *data)
4048 {
4049     size_t data_len = strlen(data);
4050     int size = 0;
4051     if (data_len >= 8) {
4052         if (strncmp(data, "00000001", 8) == 0) {
4053             size = 16 + data_len - 8;
4054             avio_wb32(pb, size); /* size */
4055             ffio_wfourcc(pb, "data");
4056             avio_wb32(pb, 1); // string
4057             avio_wb32(pb, 0);
4058             avio_write(pb, data + 8, data_len - 8);
4059         } else if (strncmp(data, "00000017", 8) == 0) {
4060             size = 16 + 4;
4061             avio_wb32(pb, size); /* size */
4062             ffio_wfourcc(pb, "data");
4063             avio_wb32(pb, 23); // float
4064             avio_wb32(pb, 0);
4065             avio_wb32(pb, av_float2int(atof(data + 8)));
4066         } else if (strncmp(data, "00000043", 8) == 0) {
4067             size = 16 + 4;
4068             avio_wb32(pb, size); /* size */
4069             ffio_wfourcc(pb, "data");
4070             avio_wb32(pb, 67); // int
4071             avio_wb32(pb, 0);
4072             avio_wb32(pb, atoi(data + 8));
4073         } else {
4074             size = 16 + 4;
4075             avio_wb32(pb, size); /* size */
4076             ffio_wfourcc(pb, "data");
4077             avio_wb32(pb, 77); // unkown
4078             avio_wb32(pb, 0);
4079             avio_wb32(pb, 0);
4080         }
4081     } else {
4082         size = 16 + data_len;
4083         avio_wb32(pb, size); /* size */
4084         ffio_wfourcc(pb, "data");
4085         avio_wb32(pb, 1); // default string
4086         avio_wb32(pb, 0);
4087         avio_write(pb, data, data_len);
4088     }
4089     return size;
4090 }
4091 #endif
4092 
4093 static int mov_write_string_tag(AVIOContext *pb, const char *name,
4094                                 const char *value, int lang, int long_style)
4095 {
4096     int size = 0;
4097     if (value && value[0]) {
4098         int64_t pos = avio_tell(pb);
4099         avio_wb32(pb, 0); /* size */
4100         ffio_wfourcc(pb, name);
4101         mov_write_string_data_tag(pb, value, lang, long_style);
4102         size = update_size(pb, pos);
4103     }
4104     return size;
4105 }
4106 
4107 static AVDictionaryEntry *get_metadata_lang(AVFormatContext *s,
4108                                             const char *tag, int *lang)
4109 {
4110     int l, len, len2;
4111     AVDictionaryEntry *t, *t2 = NULL;
4112     char tag2[16];
4113 
4114     *lang = 0;
4115 
4116     if (!(t = av_dict_get(s->metadata, tag, NULL, 0)))
4117         return NULL;
4118 
4119     len = strlen(t->key);
4120     snprintf(tag2, sizeof(tag2), "%s-", tag);
4121     while ((t2 = av_dict_get(s->metadata, tag2, t2, AV_DICT_IGNORE_SUFFIX))) {
4122         len2 = strlen(t2->key);
4123         if (len2 == len + 4 && !strcmp(t->value, t2->value)
4124             && (l = ff_mov_iso639_to_lang(&t2->key[len2 - 3], 1)) >= 0) {
4125             *lang = l;
4126             return t;
4127         }
4128     }
4129     return t;
4130 }
4131 
4132 static int mov_write_string_metadata(AVFormatContext *s, AVIOContext *pb,
4133                                      const char *name, const char *tag,
4134                                      int long_style)
4135 {
4136     int lang;
4137     AVDictionaryEntry *t = get_metadata_lang(s, tag, &lang);
4138     if (!t)
4139         return 0;
4140     return mov_write_string_tag(pb, name, t->value, lang, long_style);
4141 }
4142 
4143 /* iTunes bpm number */
4144 static int mov_write_tmpo_tag(AVIOContext *pb, AVFormatContext *s)
4145 {
4146     AVDictionaryEntry *t = av_dict_get(s->metadata, "tmpo", NULL, 0);
4147     int size = 0, tmpo = t ? atoi(t->value) : 0;
4148     if (tmpo) {
4149         size = 26;
4150         avio_wb32(pb, size);
4151         ffio_wfourcc(pb, "tmpo");
4152         avio_wb32(pb, size-8); /* size */
4153         ffio_wfourcc(pb, "data");
4154         avio_wb32(pb, 0x15);  //type specifier
4155         avio_wb32(pb, 0);
4156         avio_wb16(pb, tmpo);        // data
4157     }
4158     return size;
4159 }
4160 
4161 /* 3GPP TS 26.244 */
4162 static int mov_write_loci_tag(AVFormatContext *s, AVIOContext *pb)
4163 {
4164     int lang;
4165     int64_t pos = avio_tell(pb);
4166     double latitude, longitude, altitude;
4167     int32_t latitude_fix, longitude_fix, altitude_fix;
4168     AVDictionaryEntry *t = get_metadata_lang(s, "location", &lang);
4169     const char *ptr, *place = "";
4170     char *end;
4171     static const char *astronomical_body = "earth";
4172     if (!t)
4173         return 0;
4174 
4175     ptr = t->value;
4176     longitude = strtod(ptr, &end);
4177     if (end == ptr) {
4178         av_log(s, AV_LOG_WARNING, "malformed location metadata\n");
4179         return 0;
4180     }
4181     ptr = end;
4182     latitude = strtod(ptr, &end);
4183     if (end == ptr) {
4184         av_log(s, AV_LOG_WARNING, "malformed location metadata\n");
4185         return 0;
4186     }
4187     ptr = end;
4188     altitude = strtod(ptr, &end);
4189     /* If no altitude was present, the default 0 should be fine */
4190     if (*end == '/')
4191         place = end + 1;
4192 
4193     latitude_fix  = (int32_t) ((1 << 16) * latitude);
4194     longitude_fix = (int32_t) ((1 << 16) * longitude);
4195     altitude_fix  = (int32_t) ((1 << 16) * altitude);
4196 
4197     avio_wb32(pb, 0);         /* size */
4198     ffio_wfourcc(pb, "loci"); /* type */
4199     avio_wb32(pb, 0);         /* version + flags */
4200     avio_wb16(pb, lang);
4201     avio_write(pb, place, strlen(place) + 1);
4202     avio_w8(pb, 0);           /* role of place (0 == shooting location, 1 == real location, 2 == fictional location) */
4203 #ifdef OHOS_MOOV_LEVEL_META
4204     /* fix save order, refer to 3GPP TS 26.244, ffmpeg7.0 */
4205     avio_wb32(pb, longitude_fix);
4206     avio_wb32(pb, latitude_fix);
4207 #else
4208     avio_wb32(pb, latitude_fix);
4209     avio_wb32(pb, longitude_fix);
4210 #endif
4211     avio_wb32(pb, altitude_fix);
4212     avio_write(pb, astronomical_body, strlen(astronomical_body) + 1);
4213     avio_w8(pb, 0);           /* additional notes, null terminated string */
4214 
4215     return update_size(pb, pos);
4216 }
4217 
4218 #ifdef OHOS_MOOV_LEVEL_META
4219 static int mov_write_geo_tag(AVFormatContext *s, AVIOContext *pb)
4220 {
4221     int lang;
4222     int64_t pos = avio_tell(pb);
4223     float latitude, longitude, altitude;
4224     int32_t latitudex10000, longitudex10000, altitudex10000;
4225     AVDictionaryEntry *t = get_metadata_lang(s, "location", &lang);
4226     const char *ptr;
4227     char *end;
4228     if (!t)
4229         return 0;
4230 
4231     ptr = t->value;
4232     longitude = strtof(ptr, &end);
4233     if (end == ptr) {
4234         av_log(s, AV_LOG_WARNING, "malformed location metadata\n");
4235         return 0;
4236     }
4237     ptr = end;
4238     latitude = strtof(ptr, &end);
4239     if (end == ptr) {
4240         av_log(s, AV_LOG_WARNING, "malformed location metadata\n");
4241         return 0;
4242     }
4243     ptr = end;
4244     altitude = strtof(ptr, &end);
4245 
4246     latitudex10000  = (int32_t) (10000 * latitude);
4247     longitudex10000 = (int32_t) (10000 * longitude);
4248     altitudex10000  = (int32_t) (10000 * altitude);
4249     if (latitudex10000 < -900000 || latitudex10000 > 900000 ||
4250         longitudex10000 < -1800000 || longitudex10000 > 1800000) {
4251         av_log(s, AV_LOG_WARNING, "longitude or latitude is not in range\n");
4252         return 0;
4253     }
4254 
4255     // calc latitude
4256     int is_negative = latitudex10000 < 0;
4257     char sign = is_negative? '-' : '+';
4258     char latitude_str[9];
4259     memset(latitude_str, 0, sizeof(latitude_str));
4260     int32_t whole_part = latitudex10000 / 10000;
4261     if (whole_part == 0) {
4262         snprintf(latitude_str, 5, "%c%.2d.", sign, whole_part);
4263     } else {
4264         snprintf(latitude_str, 5, "%+.2d.", whole_part);
4265     }
4266     int32_t fraction_part = latitudex10000 - (whole_part * 10000);
4267     if (fraction_part < 0) {
4268         fraction_part = -fraction_part;
4269     }
4270     snprintf(&latitude_str[4], 5, "%.4d.", fraction_part);
4271 
4272     // calc longitude
4273     is_negative = longitudex10000 < 0;
4274     sign = is_negative? '-' : '+';
4275     char longitude_str[10];
4276     memset(longitude_str, 0, sizeof(longitude_str));
4277     whole_part = longitudex10000 / 10000;
4278     if (whole_part == 0) {
4279         snprintf(longitude_str, 6, "%c%.3d.", sign, whole_part);
4280     } else {
4281         snprintf(longitude_str, 6, "%+.3d.", whole_part);
4282     }
4283     fraction_part = longitudex10000 - (whole_part * 10000);
4284     if (fraction_part < 0) {
4285         fraction_part = -fraction_part;
4286     }
4287     snprintf(&longitude_str[5], 5, "%.4d.", fraction_part);
4288 
4289     avio_wb32(pb, 0);         /* size */
4290     ffio_wfourcc(pb, "\xA9xyz"); /* type */
4291     avio_wb32(pb, 0x001215c7);
4292     avio_write(pb, latitude_str, 8);
4293     avio_write(pb, longitude_str, 9);
4294     avio_w8(pb, 0x2F);
4295     return update_size(pb, pos);
4296 }
4297 
4298 static int mov_write_gnre_tag(AVIOContext* pb, MOVMuxContext* mov, AVFormatContext* s)
4299 {
4300     int64_t pos = avio_tell(pb);
4301     AVDictionaryEntry *t;
4302     if ((t = av_dict_get(s->metadata, "genre", NULL, 0))) {
4303         avio_wb32(pb, 0); /* size */
4304         ffio_wfourcc(pb, "gnre");
4305         avio_wb32(pb, 0);
4306         avio_wb16(pb, 0);
4307         avio_write(pb, t->value, strlen(t->value) + 1);
4308         avio_wb32(pb, 0);
4309         avio_wb32(pb, 0);
4310     }
4311     return update_size(pb, pos);
4312 }
4313 #endif
4314 
4315 /* iTunes track or disc number */
4316 static int mov_write_trkn_tag(AVIOContext *pb, MOVMuxContext *mov,
4317                               AVFormatContext *s, int disc)
4318 {
4319     AVDictionaryEntry *t = av_dict_get(s->metadata,
4320                                        disc ? "disc" : "track",
4321                                        NULL, 0);
4322     int size = 0, track = t ? atoi(t->value) : 0;
4323     if (track) {
4324         int tracks = 0;
4325         char *slash = strchr(t->value, '/');
4326         if (slash)
4327             tracks = atoi(slash + 1);
4328         avio_wb32(pb, 32); /* size */
4329         ffio_wfourcc(pb, disc ? "disk" : "trkn");
4330         avio_wb32(pb, 24); /* size */
4331         ffio_wfourcc(pb, "data");
4332         avio_wb32(pb, 0);        // 8 bytes empty
4333         avio_wb32(pb, 0);
4334         avio_wb16(pb, 0);        // empty
4335         avio_wb16(pb, track);    // track / disc number
4336         avio_wb16(pb, tracks);   // total track / disc number
4337         avio_wb16(pb, 0);        // empty
4338         size = 32;
4339     }
4340     return size;
4341 }
4342 
4343 static int mov_write_int8_metadata(AVFormatContext *s, AVIOContext *pb,
4344                                    const char *name, const char *tag,
4345                                    int len)
4346 {
4347     AVDictionaryEntry *t = NULL;
4348     uint8_t num;
4349     int size = 24 + len;
4350 
4351     if (len != 1 && len != 4)
4352         return -1;
4353 
4354     if (!(t = av_dict_get(s->metadata, tag, NULL, 0)))
4355         return 0;
4356     num = atoi(t->value);
4357 
4358     avio_wb32(pb, size);
4359     ffio_wfourcc(pb, name);
4360     avio_wb32(pb, size - 8);
4361     ffio_wfourcc(pb, "data");
4362     avio_wb32(pb, 0x15);
4363     avio_wb32(pb, 0);
4364     if (len==4) avio_wb32(pb, num);
4365     else        avio_w8 (pb, num);
4366 
4367     return size;
4368 }
4369 
4370 static int mov_write_covr(AVIOContext *pb, AVFormatContext *s)
4371 {
4372     MOVMuxContext *mov = s->priv_data;
4373     int64_t pos = 0;
4374     int i;
4375 
4376     for (i = 0; i < s->nb_streams; i++) {
4377         MOVTrack *trk = &mov->tracks[i];
4378 
4379         if (!is_cover_image(trk->st) || trk->cover_image->size <= 0)
4380             continue;
4381 
4382         if (!pos) {
4383             pos = avio_tell(pb);
4384             avio_wb32(pb, 0);
4385             ffio_wfourcc(pb, "covr");
4386         }
4387         avio_wb32(pb, 16 + trk->cover_image->size);
4388         ffio_wfourcc(pb, "data");
4389         avio_wb32(pb, trk->tag);
4390         avio_wb32(pb , 0);
4391         avio_write(pb, trk->cover_image->data, trk->cover_image->size);
4392     }
4393 
4394     return pos ? update_size(pb, pos) : 0;
4395 }
4396 
4397 /* iTunes meta data list */
4398 static int mov_write_ilst_tag(AVIOContext *pb, MOVMuxContext *mov,
4399                               AVFormatContext *s)
4400 {
4401     int64_t pos = avio_tell(pb);
4402     avio_wb32(pb, 0); /* size */
4403     ffio_wfourcc(pb, "ilst");
4404     mov_write_string_metadata(s, pb, "\251nam", "title"    , 1);
4405     mov_write_string_metadata(s, pb, "\251ART", "artist"   , 1);
4406     mov_write_string_metadata(s, pb, "aART", "album_artist", 1);
4407     mov_write_string_metadata(s, pb, "\251wrt", "composer" , 1);
4408     mov_write_string_metadata(s, pb, "\251alb", "album"    , 1);
4409     mov_write_string_metadata(s, pb, "\251day", "date"     , 1);
4410     if (!mov_write_string_metadata(s, pb, "\251too", "encoding_tool", 1)) {
4411         if (!(s->flags & AVFMT_FLAG_BITEXACT))
4412             mov_write_string_tag(pb, "\251too", LIBAVFORMAT_IDENT, 0, 1);
4413     }
4414     mov_write_string_metadata(s, pb, "\251cmt", "comment"  , 1);
4415     mov_write_string_metadata(s, pb, "\251gen", "genre"    , 1);
4416     mov_write_string_metadata(s, pb, "cprt",    "copyright", 1);
4417     mov_write_string_metadata(s, pb, "\251grp", "grouping" , 1);
4418     mov_write_string_metadata(s, pb, "\251lyr", "lyrics"   , 1);
4419     mov_write_string_metadata(s, pb, "desc",    "description",1);
4420     mov_write_string_metadata(s, pb, "ldes",    "synopsis" , 1);
4421     mov_write_string_metadata(s, pb, "tvsh",    "show"     , 1);
4422     mov_write_string_metadata(s, pb, "tven",    "episode_id",1);
4423     mov_write_string_metadata(s, pb, "tvnn",    "network"  , 1);
4424     mov_write_string_metadata(s, pb, "keyw",    "keywords"  , 1);
4425     mov_write_int8_metadata  (s, pb, "tves",    "episode_sort",4);
4426     mov_write_int8_metadata  (s, pb, "tvsn",    "season_number",4);
4427     mov_write_int8_metadata  (s, pb, "stik",    "media_type",1);
4428     mov_write_int8_metadata  (s, pb, "hdvd",    "hd_video",  1);
4429     mov_write_int8_metadata  (s, pb, "pgap",    "gapless_playback",1);
4430     mov_write_int8_metadata  (s, pb, "cpil",    "compilation", 1);
4431     mov_write_covr(pb, s);
4432     mov_write_trkn_tag(pb, mov, s, 0); // track number
4433     mov_write_trkn_tag(pb, mov, s, 1); // disc number
4434     mov_write_tmpo_tag(pb, s);
4435     return update_size(pb, pos);
4436 }
4437 
4438 static int mov_write_mdta_hdlr_tag(AVIOContext *pb, MOVMuxContext *mov,
4439                                    AVFormatContext *s)
4440 {
4441     avio_wb32(pb, 33); /* size */
4442     ffio_wfourcc(pb, "hdlr");
4443     avio_wb32(pb, 0);
4444     avio_wb32(pb, 0);
4445     ffio_wfourcc(pb, "mdta");
4446     avio_wb32(pb, 0);
4447     avio_wb32(pb, 0);
4448     avio_wb32(pb, 0);
4449     avio_w8(pb, 0);
4450     return 33;
4451 }
4452 
4453 static int mov_write_mdta_keys_tag(AVIOContext *pb, MOVMuxContext *mov,
4454                                    AVFormatContext *s)
4455 {
4456     AVDictionaryEntry *t = NULL;
4457     int64_t pos = avio_tell(pb);
4458     int64_t curpos, entry_pos;
4459     int count = 0;
4460 
4461     avio_wb32(pb, 0); /* size */
4462     ffio_wfourcc(pb, "keys");
4463     avio_wb32(pb, 0);
4464     entry_pos = avio_tell(pb);
4465     avio_wb32(pb, 0); /* entry count */
4466 
4467     while (t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX)) {
4468         size_t key_len = strlen(t->key);
4469         avio_wb32(pb, key_len + 8);
4470         ffio_wfourcc(pb, "mdta");
4471         avio_write(pb, t->key, key_len);
4472         count += 1;
4473     }
4474     curpos = avio_tell(pb);
4475     avio_seek(pb, entry_pos, SEEK_SET);
4476     avio_wb32(pb, count); // rewrite entry count
4477     avio_seek(pb, curpos, SEEK_SET);
4478 
4479     return update_size(pb, pos);
4480 }
4481 
4482 static int mov_write_mdta_ilst_tag(AVIOContext *pb, MOVMuxContext *mov,
4483                                    AVFormatContext *s)
4484 {
4485     AVDictionaryEntry *t = NULL;
4486     int64_t pos = avio_tell(pb);
4487     int count = 1; /* keys are 1-index based */
4488 
4489     avio_wb32(pb, 0); /* size */
4490     ffio_wfourcc(pb, "ilst");
4491 
4492     while (t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX)) {
4493         int64_t entry_pos = avio_tell(pb);
4494         avio_wb32(pb, 0); /* size */
4495         avio_wb32(pb, count); /* key */
4496         mov_write_string_data_tag(pb, t->value, 0, 1);
4497         update_size(pb, entry_pos);
4498         count += 1;
4499     }
4500     return update_size(pb, pos);
4501 }
4502 
4503 /* meta data tags */
4504 static int mov_write_meta_tag(AVIOContext *pb, MOVMuxContext *mov,
4505                               AVFormatContext *s)
4506 {
4507     int size = 0;
4508     int64_t pos = avio_tell(pb);
4509     avio_wb32(pb, 0); /* size */
4510     ffio_wfourcc(pb, "meta");
4511     avio_wb32(pb, 0);
4512     if (mov->flags & FF_MOV_FLAG_USE_MDTA) {
4513         mov_write_mdta_hdlr_tag(pb, mov, s);
4514         mov_write_mdta_keys_tag(pb, mov, s);
4515         mov_write_mdta_ilst_tag(pb, mov, s);
4516     } else if (mov->mode == MODE_AVIF) {
4517         mov_write_hdlr_tag(s, pb, &mov->tracks[0]);
4518         // We always write the primary item id as 1 since only one track is
4519         // supported for AVIF.
4520         mov_write_pitm_tag(pb, 1);
4521         mov_write_iloc_tag(pb, mov, s);
4522         mov_write_iinf_tag(pb, mov, s);
4523         if (s->nb_streams > 1)
4524             mov_write_iref_tag(pb, mov, s);
4525         mov_write_iprp_tag(pb, mov, s);
4526     } else {
4527         /* iTunes metadata tag */
4528         mov_write_itunes_hdlr_tag(pb, mov, s);
4529         mov_write_ilst_tag(pb, mov, s);
4530     }
4531     size = update_size(pb, pos);
4532     return size;
4533 }
4534 
4535 #ifdef OHOS_MOOV_LEVEL_META
4536 static int mov_write_moov_level_meta_mdta_keys_tag(AVIOContext *pb, MOVMuxContext *mov,
4537                                    AVFormatContext *s)
4538 {
4539     const AVDictionaryEntry *t = NULL;
4540     int64_t pos = avio_tell(pb);
4541     int64_t curpos, entry_pos;
4542     int count = 0;
4543 
4544     avio_wb32(pb, 0); /* size */
4545     ffio_wfourcc(pb, "keys");
4546     avio_wb32(pb, 0);
4547     entry_pos = avio_tell(pb);
4548     avio_wb32(pb, 0); /* entry count */
4549 
4550     const char *key_tag = "moov_level_meta_key_";
4551     size_t key_tag_len = strlen(key_tag);
4552     while (t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX)) {
4553         size_t key_len = strlen(t->key);
4554         if (key_len > key_tag_len && strncmp(t->key, key_tag, key_tag_len) == 0) {
4555             avio_wb32(pb, key_len + 8 - key_tag_len);
4556             ffio_wfourcc(pb, "mdta");
4557             avio_write(pb, t->key + key_tag_len, key_len - key_tag_len);
4558             count += 1;
4559         }
4560     }
4561     curpos = avio_tell(pb);
4562     avio_seek(pb, entry_pos, SEEK_SET);
4563     avio_wb32(pb, count); // rewrite entry count
4564     avio_seek(pb, curpos, SEEK_SET);
4565 
4566     return update_size(pb, pos);
4567 }
4568 
4569 static int mov_write_moov_level_meta_mdta_ilst_tag(AVIOContext *pb, MOVMuxContext *mov,
4570                                    AVFormatContext *s)
4571 {
4572     const AVDictionaryEntry *t = NULL;
4573     int64_t pos = avio_tell(pb);
4574     int count = 1; /* keys are 1-index based */
4575 
4576     avio_wb32(pb, 0); /* size */
4577     ffio_wfourcc(pb, "ilst");
4578 
4579     const char *key_tag = "moov_level_meta_key_";
4580     size_t key_tag_len = strlen(key_tag);
4581     while (t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX)) {
4582         size_t key_len = strlen(t->key);
4583         if (key_len > key_tag_len && strncmp(t->key, key_tag, key_tag_len) == 0) {
4584             int64_t entry_pos = avio_tell(pb);
4585             avio_wb32(pb, 0); /* size */
4586             avio_wb32(pb, count); /* key */
4587             mov_write_moov_level_meta_data_tag(pb, t->value);
4588             update_size(pb, entry_pos);
4589             count += 1;
4590         }
4591     }
4592     return update_size(pb, pos);
4593 }
4594 
4595 static int mov_write_moov_level_meta_tag(AVIOContext *pb, MOVMuxContext *mov,
4596                                          AVFormatContext *s)
4597 {
4598     int size = 0;
4599     int64_t pos = avio_tell(pb);
4600     avio_wb32(pb, 0); /* size */
4601     ffio_wfourcc(pb, "meta");
4602     avio_wb32(pb, 0);
4603     mov_write_mdta_hdlr_tag(pb, mov, s);
4604     mov_write_moov_level_meta_mdta_keys_tag(pb, mov, s);
4605     mov_write_moov_level_meta_mdta_ilst_tag(pb, mov, s);
4606     size = update_size(pb, pos);
4607     return size;
4608 }
4609 #endif
4610 
4611 static int mov_write_raw_metadata_tag(AVFormatContext *s, AVIOContext *pb,
4612                                       const char *name, const char *key)
4613 {
4614     int len;
4615     AVDictionaryEntry *t;
4616 
4617     if (!(t = av_dict_get(s->metadata, key, NULL, 0)))
4618         return 0;
4619 
4620     len = strlen(t->value);
4621     if (len > 0) {
4622         int size = len + 8;
4623         avio_wb32(pb, size);
4624         ffio_wfourcc(pb, name);
4625         avio_write(pb, t->value, len);
4626         return size;
4627     }
4628     return 0;
4629 }
4630 
4631 static int ascii_to_wc(AVIOContext *pb, const uint8_t *b)
4632 {
4633     int val;
4634     while (*b) {
4635         GET_UTF8(val, *b++, return -1;)
4636         avio_wb16(pb, val);
4637     }
4638     avio_wb16(pb, 0x00);
4639     return 0;
4640 }
4641 
4642 static uint16_t language_code(const char *str)
4643 {
4644     return (((str[0] - 0x60) & 0x1F) << 10) +
4645            (((str[1] - 0x60) & 0x1F) <<  5) +
4646            (( str[2] - 0x60) & 0x1F);
4647 }
4648 
4649 static int mov_write_3gp_udta_tag(AVIOContext *pb, AVFormatContext *s,
4650                                   const char *tag, const char *str)
4651 {
4652     int64_t pos = avio_tell(pb);
4653     AVDictionaryEntry *t = av_dict_get(s->metadata, str, NULL, 0);
4654     if (!t || !utf8len(t->value))
4655         return 0;
4656     avio_wb32(pb, 0);   /* size */
4657     ffio_wfourcc(pb, tag); /* type */
4658     avio_wb32(pb, 0);   /* version + flags */
4659     if (!strcmp(tag, "yrrc"))
4660         avio_wb16(pb, atoi(t->value));
4661     else {
4662         avio_wb16(pb, language_code("eng")); /* language */
4663         avio_write(pb, t->value, strlen(t->value) + 1); /* UTF8 string value */
4664         if (!strcmp(tag, "albm") &&
4665             (t = av_dict_get(s->metadata, "track", NULL, 0)))
4666             avio_w8(pb, atoi(t->value));
4667     }
4668     return update_size(pb, pos);
4669 }
4670 
4671 static int mov_write_chpl_tag(AVIOContext *pb, AVFormatContext *s)
4672 {
4673     int64_t pos = avio_tell(pb);
4674     int i, nb_chapters = FFMIN(s->nb_chapters, 255);
4675 
4676     avio_wb32(pb, 0);            // size
4677     ffio_wfourcc(pb, "chpl");
4678     avio_wb32(pb, 0x01000000);   // version + flags
4679     avio_wb32(pb, 0);            // unknown
4680     avio_w8(pb, nb_chapters);
4681 
4682     for (i = 0; i < nb_chapters; i++) {
4683         AVChapter *c = s->chapters[i];
4684         AVDictionaryEntry *t;
4685         avio_wb64(pb, av_rescale_q(c->start, c->time_base, (AVRational){1,10000000}));
4686 
4687         if ((t = av_dict_get(c->metadata, "title", NULL, 0))) {
4688             int len = FFMIN(strlen(t->value), 255);
4689             avio_w8(pb, len);
4690             avio_write(pb, t->value, len);
4691         } else
4692             avio_w8(pb, 0);
4693     }
4694     return update_size(pb, pos);
4695 }
4696 
4697 static int mov_write_udta_tag(AVIOContext *pb, MOVMuxContext *mov,
4698                               AVFormatContext *s)
4699 {
4700     AVIOContext *pb_buf;
4701     int ret, size;
4702     uint8_t *buf;
4703 
4704     ret = avio_open_dyn_buf(&pb_buf);
4705     if (ret < 0)
4706         return ret;
4707 
4708     if (mov->mode & MODE_3GP) {
4709         mov_write_3gp_udta_tag(pb_buf, s, "perf", "artist");
4710         mov_write_3gp_udta_tag(pb_buf, s, "titl", "title");
4711         mov_write_3gp_udta_tag(pb_buf, s, "auth", "author");
4712         mov_write_3gp_udta_tag(pb_buf, s, "gnre", "genre");
4713         mov_write_3gp_udta_tag(pb_buf, s, "dscp", "comment");
4714         mov_write_3gp_udta_tag(pb_buf, s, "albm", "album");
4715         mov_write_3gp_udta_tag(pb_buf, s, "cprt", "copyright");
4716         mov_write_3gp_udta_tag(pb_buf, s, "yrrc", "date");
4717         mov_write_loci_tag(s, pb_buf);
4718     } 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
4719         mov_write_string_metadata(s, pb_buf, "\251ART", "artist",      0);
4720         mov_write_string_metadata(s, pb_buf, "\251nam", "title",       0);
4721         mov_write_string_metadata(s, pb_buf, "\251aut", "author",      0);
4722         mov_write_string_metadata(s, pb_buf, "\251alb", "album",       0);
4723         mov_write_string_metadata(s, pb_buf, "\251day", "date",        0);
4724         mov_write_string_metadata(s, pb_buf, "\251swr", "encoder",     0);
4725         // currently ignored by mov.c
4726         mov_write_string_metadata(s, pb_buf, "\251des", "comment",     0);
4727         // add support for libquicktime, this atom is also actually read by mov.c
4728         mov_write_string_metadata(s, pb_buf, "\251cmt", "comment",     0);
4729         mov_write_string_metadata(s, pb_buf, "\251gen", "genre",       0);
4730         mov_write_string_metadata(s, pb_buf, "\251cpy", "copyright",   0);
4731         mov_write_string_metadata(s, pb_buf, "\251mak", "make",        0);
4732         mov_write_string_metadata(s, pb_buf, "\251mod", "model",       0);
4733         mov_write_string_metadata(s, pb_buf, "\251xyz", "location",    0);
4734         mov_write_string_metadata(s, pb_buf, "\251key", "keywords",    0);
4735         mov_write_raw_metadata_tag(s, pb_buf, "XMP_", "xmp");
4736     } else {
4737 #ifdef OHOS_MOOV_LEVEL_META
4738         if (av_dict_get(s->metadata, "moov_level_meta_flag", NULL, 0)) {
4739             mov_write_geo_tag(s, pb_buf);
4740         }
4741 #endif
4742         /* iTunes meta data */
4743         mov_write_meta_tag(pb_buf, mov, s);
4744         mov_write_loci_tag(s, pb_buf);
4745     }
4746 
4747     if (s->nb_chapters && !(mov->flags & FF_MOV_FLAG_DISABLE_CHPL))
4748         mov_write_chpl_tag(pb_buf, s);
4749 
4750     if ((size = avio_get_dyn_buf(pb_buf, &buf)) > 0) {
4751         avio_wb32(pb, size + 8);
4752         ffio_wfourcc(pb, "udta");
4753         avio_write(pb, buf, size);
4754     }
4755     ffio_free_dyn_buf(&pb_buf);
4756 
4757     return 0;
4758 }
4759 
4760 static void mov_write_psp_udta_tag(AVIOContext *pb,
4761                                    const char *str, const char *lang, int type)
4762 {
4763     int len = utf8len(str) + 1;
4764     if (len <= 0)
4765         return;
4766     avio_wb16(pb, len * 2 + 10);        /* size */
4767     avio_wb32(pb, type);                /* type */
4768     avio_wb16(pb, language_code(lang)); /* language */
4769     avio_wb16(pb, 0x01);                /* ? */
4770     ascii_to_wc(pb, str);
4771 }
4772 
4773 static int mov_write_uuidusmt_tag(AVIOContext *pb, AVFormatContext *s)
4774 {
4775     AVDictionaryEntry *title = av_dict_get(s->metadata, "title", NULL, 0);
4776     int64_t pos, pos2;
4777 
4778     if (title) {
4779         pos = avio_tell(pb);
4780         avio_wb32(pb, 0); /* size placeholder*/
4781         ffio_wfourcc(pb, "uuid");
4782         ffio_wfourcc(pb, "USMT");
4783         avio_wb32(pb, 0x21d24fce); /* 96 bit UUID */
4784         avio_wb32(pb, 0xbb88695c);
4785         avio_wb32(pb, 0xfac9c740);
4786 
4787         pos2 = avio_tell(pb);
4788         avio_wb32(pb, 0); /* size placeholder*/
4789         ffio_wfourcc(pb, "MTDT");
4790         avio_wb16(pb, 4);
4791 
4792         // ?
4793         avio_wb16(pb, 0x0C);                 /* size */
4794         avio_wb32(pb, 0x0B);                 /* type */
4795         avio_wb16(pb, language_code("und")); /* language */
4796         avio_wb16(pb, 0x0);                  /* ? */
4797         avio_wb16(pb, 0x021C);               /* data */
4798 
4799         if (!(s->flags & AVFMT_FLAG_BITEXACT))
4800             mov_write_psp_udta_tag(pb, LIBAVFORMAT_IDENT,      "eng", 0x04);
4801         mov_write_psp_udta_tag(pb, title->value,          "eng", 0x01);
4802         mov_write_psp_udta_tag(pb, "2006/04/01 11:11:11", "und", 0x03);
4803 
4804         update_size(pb, pos2);
4805         return update_size(pb, pos);
4806     }
4807 
4808     return 0;
4809 }
4810 
4811 static void build_chunks(MOVTrack *trk)
4812 {
4813     int i;
4814     MOVIentry *chunk = &trk->cluster[0];
4815     uint64_t chunkSize = chunk->size;
4816     chunk->chunkNum = 1;
4817     if (trk->chunkCount)
4818         return;
4819     trk->chunkCount = 1;
4820     for (i = 1; i<trk->entry; i++){
4821         if (chunk->pos + chunkSize == trk->cluster[i].pos &&
4822             chunkSize + trk->cluster[i].size < (1<<20)){
4823             chunkSize             += trk->cluster[i].size;
4824             chunk->samples_in_chunk += trk->cluster[i].entries;
4825         } else {
4826             trk->cluster[i].chunkNum = chunk->chunkNum+1;
4827             chunk=&trk->cluster[i];
4828             chunkSize = chunk->size;
4829             trk->chunkCount++;
4830         }
4831     }
4832 }
4833 
4834 /**
4835  * Assign track ids. If option "use_stream_ids_as_track_ids" is set,
4836  * the stream ids are used as track ids.
4837  *
4838  * This assumes mov->tracks and s->streams are in the same order and
4839  * there are no gaps in either of them (so mov->tracks[n] refers to
4840  * s->streams[n]).
4841  *
4842  * As an exception, there can be more entries in
4843  * s->streams than in mov->tracks, in which case new track ids are
4844  * generated (starting after the largest found stream id).
4845  */
4846 static int mov_setup_track_ids(MOVMuxContext *mov, AVFormatContext *s)
4847 {
4848     int i;
4849 
4850     if (mov->track_ids_ok)
4851         return 0;
4852 
4853     if (mov->use_stream_ids_as_track_ids) {
4854         int next_generated_track_id = 0;
4855         for (i = 0; i < s->nb_streams; i++) {
4856             if (s->streams[i]->id > next_generated_track_id)
4857                 next_generated_track_id = s->streams[i]->id;
4858         }
4859 
4860         for (i = 0; i < mov->nb_streams; i++) {
4861             if (mov->tracks[i].entry <= 0 && !(mov->flags & FF_MOV_FLAG_FRAGMENT))
4862                 continue;
4863 
4864             mov->tracks[i].track_id = i >= s->nb_streams ? ++next_generated_track_id : s->streams[i]->id;
4865         }
4866     } else {
4867         for (i = 0; i < mov->nb_streams; i++) {
4868             if (mov->tracks[i].entry <= 0 && !(mov->flags & FF_MOV_FLAG_FRAGMENT))
4869                 continue;
4870 
4871             mov->tracks[i].track_id = i + 1;
4872         }
4873     }
4874 
4875     mov->track_ids_ok = 1;
4876 
4877     return 0;
4878 }
4879 
4880 static int mov_write_moov_tag(AVIOContext *pb, MOVMuxContext *mov,
4881                               AVFormatContext *s)
4882 {
4883     int i;
4884     int64_t pos = avio_tell(pb);
4885     avio_wb32(pb, 0); /* size placeholder*/
4886     ffio_wfourcc(pb, "moov");
4887 
4888     mov_setup_track_ids(mov, s);
4889 
4890     for (i = 0; i < mov->nb_streams; i++) {
4891         if (mov->tracks[i].entry <= 0 && !(mov->flags & FF_MOV_FLAG_FRAGMENT))
4892             continue;
4893 
4894         mov->tracks[i].time     = mov->time;
4895 
4896         if (mov->tracks[i].entry)
4897             build_chunks(&mov->tracks[i]);
4898     }
4899 
4900     if (mov->chapter_track)
4901         for (i = 0; i < s->nb_streams; i++) {
4902             mov->tracks[i].tref_tag = MKTAG('c','h','a','p');
4903 #ifdef OHOS_TIMED_META_TRACK
4904             mov->tracks[i].ref_track_count++;
4905             mov->tracks[i].tref_ids[0]  = mov->tracks[mov->chapter_track].track_id;
4906 #else
4907             mov->tracks[i].tref_id  = mov->tracks[mov->chapter_track].track_id;
4908 #endif
4909         }
4910     for (i = 0; i < mov->nb_streams; i++) {
4911         MOVTrack *track = &mov->tracks[i];
4912         if (track->tag == MKTAG('r','t','p',' ')) {
4913             track->tref_tag = MKTAG('h','i','n','t');
4914 #ifdef OHOS_TIMED_META_TRACK
4915             track->ref_track_count++;
4916             track->tref_ids[0] = mov->tracks[track->src_track].track_id;
4917 #else
4918             track->tref_id = mov->tracks[track->src_track].track_id;
4919 #endif
4920         } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) {
4921             size_t size;
4922             int *fallback;
4923             fallback = (int*)av_stream_get_side_data(track->st,
4924                                                      AV_PKT_DATA_FALLBACK_TRACK,
4925                                                      &size);
4926             if (fallback != NULL && size == sizeof(int)) {
4927                 if (*fallback >= 0 && *fallback < mov->nb_streams) {
4928                     track->tref_tag = MKTAG('f','a','l','l');
4929 #ifdef OHOS_TIMED_META_TRACK
4930                     track->ref_track_count++;
4931                     track->tref_ids[0] = mov->tracks[*fallback].track_id;
4932 #else
4933                     track->tref_id = mov->tracks[*fallback].track_id;
4934 #endif
4935                 }
4936             }
4937         }
4938     }
4939     for (i = 0; i < mov->nb_streams; i++) {
4940         if (mov->tracks[i].tag == MKTAG('t','m','c','d')) {
4941             int src_trk = mov->tracks[i].src_track;
4942             mov->tracks[src_trk].tref_tag = mov->tracks[i].tag;
4943 #ifdef OHOS_TIMED_META_TRACK
4944             mov->tracks[src_trk].ref_track_count++;
4945             mov->tracks[src_trk].tref_ids[0]  = mov->tracks[i].track_id;
4946 #else
4947             mov->tracks[src_trk].tref_id  = mov->tracks[i].track_id;
4948 #endif
4949             //src_trk may have a different timescale than the tmcd track
4950             mov->tracks[i].track_duration = av_rescale(mov->tracks[src_trk].track_duration,
4951                                                        mov->tracks[i].timescale,
4952                                                        mov->tracks[src_trk].timescale);
4953         }
4954     }
4955 #ifdef OHOS_TIMED_META_TRACK
4956     for (i = 0; i < mov->nb_streams; i++) {
4957         if (mov->tracks[i].tag == MKTAG('c','d','s','c')) {
4958             int src_trk = mov->tracks[i].src_track;
4959             for (int j = 0; j < mov->tracks[i].ref_track_count; j++) {
4960                 mov->tracks[i].tref_ids[j] = mov->tracks[src_trk].track_id;
4961             }
4962         }
4963     }
4964 #endif
4965 
4966     mov_write_mvhd_tag(pb, mov);
4967     if (mov->mode != MODE_MOV && mov->mode != MODE_AVIF && !mov->iods_skip)
4968         mov_write_iods_tag(pb, mov);
4969     for (i = 0; i < mov->nb_streams; i++) {
4970         if (mov->tracks[i].entry > 0 || mov->flags & FF_MOV_FLAG_FRAGMENT ||
4971             mov->mode == MODE_AVIF) {
4972             int ret = mov_write_trak_tag(s, pb, mov, &(mov->tracks[i]), i < s->nb_streams ? s->streams[i] : NULL);
4973             if (ret < 0)
4974                 return ret;
4975         }
4976     }
4977     if (mov->flags & FF_MOV_FLAG_FRAGMENT)
4978         mov_write_mvex_tag(pb, mov); /* QuickTime requires trak to precede this */
4979 
4980     if (mov->mode == MODE_PSP)
4981         mov_write_uuidusmt_tag(pb, s);
4982     else if (mov->mode != MODE_AVIF)
4983         mov_write_udta_tag(pb, mov, s);
4984 
4985 #ifdef OHOS_MOOV_LEVEL_META
4986     if (av_dict_get(s->metadata, "moov_level_meta_flag", NULL, 0)) {
4987         mov_write_gnre_tag(pb, mov, s);
4988         mov_write_moov_level_meta_tag(pb, mov, s);
4989     }
4990 #endif
4991 
4992     return update_size(pb, pos);
4993 }
4994 
4995 static void param_write_int(AVIOContext *pb, const char *name, int value)
4996 {
4997     avio_printf(pb, "<param name=\"%s\" value=\"%d\" valuetype=\"data\"/>\n", name, value);
4998 }
4999 
5000 static void param_write_string(AVIOContext *pb, const char *name, const char *value)
5001 {
5002     avio_printf(pb, "<param name=\"%s\" value=\"%s\" valuetype=\"data\"/>\n", name, value);
5003 }
5004 
5005 static void param_write_hex(AVIOContext *pb, const char *name, const uint8_t *value, int len)
5006 {
5007     char buf[150];
5008     len = FFMIN(sizeof(buf) / 2 - 1, len);
5009     ff_data_to_hex(buf, value, len, 0);
5010     avio_printf(pb, "<param name=\"%s\" value=\"%s\" valuetype=\"data\"/>\n", name, buf);
5011 }
5012 
5013 static int mov_write_isml_manifest(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
5014 {
5015     int64_t pos = avio_tell(pb);
5016     int i;
5017 
5018     static const AVUUID uuid = {
5019         0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
5020         0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
5021     };
5022 
5023     avio_wb32(pb, 0);
5024     ffio_wfourcc(pb, "uuid");
5025     avio_write(pb, uuid, AV_UUID_LEN);
5026     avio_wb32(pb, 0);
5027 
5028     avio_printf(pb, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
5029     avio_printf(pb, "<smil xmlns=\"http://www.w3.org/2001/SMIL20/Language\">\n");
5030     avio_printf(pb, "<head>\n");
5031     if (!(mov->fc->flags & AVFMT_FLAG_BITEXACT))
5032         avio_printf(pb, "<meta name=\"creator\" content=\"%s\" />\n",
5033                     LIBAVFORMAT_IDENT);
5034     avio_printf(pb, "</head>\n");
5035     avio_printf(pb, "<body>\n");
5036     avio_printf(pb, "<switch>\n");
5037 
5038     mov_setup_track_ids(mov, s);
5039 
5040     for (i = 0; i < mov->nb_streams; i++) {
5041         MOVTrack *track = &mov->tracks[i];
5042         struct mpeg4_bit_rate_values bit_rates =
5043             calculate_mpeg4_bit_rates(track);
5044         const char *type;
5045         int track_id = track->track_id;
5046         char track_name_buf[32] = { 0 };
5047 
5048         AVStream *st = track->st;
5049         AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL,0);
5050 
5051         if (track->par->codec_type == AVMEDIA_TYPE_VIDEO && !is_cover_image(st)) {
5052             type = "video";
5053         } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) {
5054             type = "audio";
5055         } else {
5056             continue;
5057         }
5058 
5059         avio_printf(pb, "<%s systemBitrate=\"%"PRIu32"\">\n", type,
5060                     bit_rates.avg_bit_rate);
5061         param_write_int(pb, "systemBitrate", bit_rates.avg_bit_rate);
5062         param_write_int(pb, "trackID", track_id);
5063         param_write_string(pb, "systemLanguage", lang ? lang->value : "und");
5064 
5065         /* Build track name piece by piece: */
5066         /* 1. track type */
5067         av_strlcat(track_name_buf, type, sizeof(track_name_buf));
5068         /* 2. track language, if available */
5069         if (lang)
5070             av_strlcatf(track_name_buf, sizeof(track_name_buf),
5071                         "_%s", lang->value);
5072         /* 3. special type suffix */
5073         /* "_cc" = closed captions, "_ad" = audio_description */
5074         if (st->disposition & AV_DISPOSITION_HEARING_IMPAIRED)
5075             av_strlcat(track_name_buf, "_cc", sizeof(track_name_buf));
5076         else if (st->disposition & AV_DISPOSITION_VISUAL_IMPAIRED)
5077             av_strlcat(track_name_buf, "_ad", sizeof(track_name_buf));
5078 
5079         param_write_string(pb, "trackName", track_name_buf);
5080 
5081         if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
5082             if (track->par->codec_id == AV_CODEC_ID_H264) {
5083                 uint8_t *ptr;
5084                 int size = track->par->extradata_size;
5085                 if (!ff_avc_write_annexb_extradata(track->par->extradata, &ptr,
5086                                                    &size)) {
5087                     param_write_hex(pb, "CodecPrivateData",
5088                                     ptr ? ptr : track->par->extradata,
5089                                     size);
5090                     av_free(ptr);
5091                 }
5092                 param_write_string(pb, "FourCC", "H264");
5093             } else if (track->par->codec_id == AV_CODEC_ID_VC1) {
5094                 param_write_string(pb, "FourCC", "WVC1");
5095                 param_write_hex(pb, "CodecPrivateData", track->par->extradata,
5096                                 track->par->extradata_size);
5097             }
5098             param_write_int(pb, "MaxWidth", track->par->width);
5099             param_write_int(pb, "MaxHeight", track->par->height);
5100             param_write_int(pb, "DisplayWidth", track->par->width);
5101             param_write_int(pb, "DisplayHeight", track->par->height);
5102         } else {
5103             if (track->par->codec_id == AV_CODEC_ID_AAC) {
5104                 switch (track->par->profile)
5105                 {
5106                     case FF_PROFILE_AAC_HE_V2:
5107                         param_write_string(pb, "FourCC", "AACP");
5108                         break;
5109                     case FF_PROFILE_AAC_HE:
5110                         param_write_string(pb, "FourCC", "AACH");
5111                         break;
5112                     default:
5113                         param_write_string(pb, "FourCC", "AACL");
5114                 }
5115             } else if (track->par->codec_id == AV_CODEC_ID_WMAPRO) {
5116                 param_write_string(pb, "FourCC", "WMAP");
5117             }
5118             param_write_hex(pb, "CodecPrivateData", track->par->extradata,
5119                             track->par->extradata_size);
5120             param_write_int(pb, "AudioTag", ff_codec_get_tag(ff_codec_wav_tags,
5121                                                              track->par->codec_id));
5122             param_write_int(pb, "Channels", track->par->ch_layout.nb_channels);
5123             param_write_int(pb, "SamplingRate", track->par->sample_rate);
5124             param_write_int(pb, "BitsPerSample", 16);
5125             param_write_int(pb, "PacketSize", track->par->block_align ?
5126                                               track->par->block_align : 4);
5127         }
5128         avio_printf(pb, "</%s>\n", type);
5129     }
5130     avio_printf(pb, "</switch>\n");
5131     avio_printf(pb, "</body>\n");
5132     avio_printf(pb, "</smil>\n");
5133 
5134     return update_size(pb, pos);
5135 }
5136 
5137 static int mov_write_mfhd_tag(AVIOContext *pb, MOVMuxContext *mov)
5138 {
5139     avio_wb32(pb, 16);
5140     ffio_wfourcc(pb, "mfhd");
5141     avio_wb32(pb, 0);
5142     avio_wb32(pb, mov->fragments);
5143     return 0;
5144 }
5145 
5146 static uint32_t get_sample_flags(MOVTrack *track, MOVIentry *entry)
5147 {
5148     return entry->flags & MOV_SYNC_SAMPLE ? MOV_FRAG_SAMPLE_FLAG_DEPENDS_NO :
5149            (MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES | MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC);
5150 }
5151 
5152 static int mov_write_tfhd_tag(AVIOContext *pb, MOVMuxContext *mov,
5153                               MOVTrack *track, int64_t moof_offset)
5154 {
5155     int64_t pos = avio_tell(pb);
5156     uint32_t flags = MOV_TFHD_DEFAULT_SIZE | MOV_TFHD_DEFAULT_DURATION |
5157                      MOV_TFHD_BASE_DATA_OFFSET;
5158     if (!track->entry) {
5159         flags |= MOV_TFHD_DURATION_IS_EMPTY;
5160     } else {
5161         flags |= MOV_TFHD_DEFAULT_FLAGS;
5162     }
5163     if (mov->flags & FF_MOV_FLAG_OMIT_TFHD_OFFSET)
5164         flags &= ~MOV_TFHD_BASE_DATA_OFFSET;
5165     if (mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF) {
5166         flags &= ~MOV_TFHD_BASE_DATA_OFFSET;
5167         flags |= MOV_TFHD_DEFAULT_BASE_IS_MOOF;
5168     }
5169     /* CMAF requires all values to be explicit in tfhd atoms */
5170     if (mov->flags & FF_MOV_FLAG_CMAF)
5171         flags |= MOV_TFHD_STSD_ID;
5172 
5173     /* Don't set a default sample size, the silverlight player refuses
5174      * to play files with that set. Don't set a default sample duration,
5175      * WMP freaks out if it is set. Don't set a base data offset, PIFF
5176      * file format says it MUST NOT be set. */
5177     if (track->mode == MODE_ISM)
5178         flags &= ~(MOV_TFHD_DEFAULT_SIZE | MOV_TFHD_DEFAULT_DURATION |
5179                    MOV_TFHD_BASE_DATA_OFFSET | MOV_TFHD_STSD_ID);
5180 
5181     avio_wb32(pb, 0); /* size placeholder */
5182     ffio_wfourcc(pb, "tfhd");
5183     avio_w8(pb, 0); /* version */
5184     avio_wb24(pb, flags);
5185 
5186     avio_wb32(pb, track->track_id); /* track-id */
5187     if (flags & MOV_TFHD_BASE_DATA_OFFSET)
5188         avio_wb64(pb, moof_offset);
5189     if (flags & MOV_TFHD_STSD_ID) {
5190         avio_wb32(pb, 1);
5191     }
5192     if (flags & MOV_TFHD_DEFAULT_DURATION) {
5193         track->default_duration = get_cluster_duration(track, 0);
5194         avio_wb32(pb, track->default_duration);
5195     }
5196     if (flags & MOV_TFHD_DEFAULT_SIZE) {
5197         track->default_size = track->entry ? track->cluster[0].size : 1;
5198         avio_wb32(pb, track->default_size);
5199     } else
5200         track->default_size = -1;
5201 
5202     if (flags & MOV_TFHD_DEFAULT_FLAGS) {
5203         /* Set the default flags based on the second sample, if available.
5204          * If the first sample is different, that can be signaled via a separate field. */
5205         if (track->entry > 1)
5206             track->default_sample_flags = get_sample_flags(track, &track->cluster[1]);
5207         else
5208             track->default_sample_flags =
5209                 track->par->codec_type == AVMEDIA_TYPE_VIDEO ?
5210                 (MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES | MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC) :
5211                 MOV_FRAG_SAMPLE_FLAG_DEPENDS_NO;
5212         avio_wb32(pb, track->default_sample_flags);
5213     }
5214 
5215     return update_size(pb, pos);
5216 }
5217 
5218 static int mov_write_trun_tag(AVIOContext *pb, MOVMuxContext *mov,
5219                               MOVTrack *track, int moof_size,
5220                               int first, int end)
5221 {
5222     int64_t pos = avio_tell(pb);
5223     uint32_t flags = MOV_TRUN_DATA_OFFSET;
5224     int i;
5225 
5226     for (i = first; i < end; i++) {
5227         if (get_cluster_duration(track, i) != track->default_duration)
5228             flags |= MOV_TRUN_SAMPLE_DURATION;
5229         if (track->cluster[i].size != track->default_size)
5230             flags |= MOV_TRUN_SAMPLE_SIZE;
5231         if (i > first && get_sample_flags(track, &track->cluster[i]) != track->default_sample_flags)
5232             flags |= MOV_TRUN_SAMPLE_FLAGS;
5233     }
5234     if (!(flags & MOV_TRUN_SAMPLE_FLAGS) && track->entry > 0 &&
5235          get_sample_flags(track, &track->cluster[0]) != track->default_sample_flags)
5236         flags |= MOV_TRUN_FIRST_SAMPLE_FLAGS;
5237     if (track->flags & MOV_TRACK_CTTS)
5238         flags |= MOV_TRUN_SAMPLE_CTS;
5239 
5240     avio_wb32(pb, 0); /* size placeholder */
5241     ffio_wfourcc(pb, "trun");
5242     if (mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS)
5243         avio_w8(pb, 1); /* version */
5244     else
5245         avio_w8(pb, 0); /* version */
5246     avio_wb24(pb, flags);
5247 
5248     avio_wb32(pb, end - first); /* sample count */
5249     if (mov->flags & FF_MOV_FLAG_OMIT_TFHD_OFFSET &&
5250         !(mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF) &&
5251         !mov->first_trun)
5252         avio_wb32(pb, 0); /* Later tracks follow immediately after the previous one */
5253     else
5254         avio_wb32(pb, moof_size + 8 + track->data_offset +
5255                       track->cluster[first].pos); /* data offset */
5256     if (flags & MOV_TRUN_FIRST_SAMPLE_FLAGS)
5257         avio_wb32(pb, get_sample_flags(track, &track->cluster[first]));
5258 
5259     for (i = first; i < end; i++) {
5260         if (flags & MOV_TRUN_SAMPLE_DURATION)
5261             avio_wb32(pb, get_cluster_duration(track, i));
5262         if (flags & MOV_TRUN_SAMPLE_SIZE)
5263             avio_wb32(pb, track->cluster[i].size);
5264         if (flags & MOV_TRUN_SAMPLE_FLAGS)
5265             avio_wb32(pb, get_sample_flags(track, &track->cluster[i]));
5266         if (flags & MOV_TRUN_SAMPLE_CTS)
5267             avio_wb32(pb, track->cluster[i].cts);
5268     }
5269 
5270     mov->first_trun = 0;
5271     return update_size(pb, pos);
5272 }
5273 
5274 static int mov_write_tfxd_tag(AVIOContext *pb, MOVTrack *track)
5275 {
5276     int64_t pos = avio_tell(pb);
5277     static const uint8_t uuid[] = {
5278         0x6d, 0x1d, 0x9b, 0x05, 0x42, 0xd5, 0x44, 0xe6,
5279         0x80, 0xe2, 0x14, 0x1d, 0xaf, 0xf7, 0x57, 0xb2
5280     };
5281 
5282     avio_wb32(pb, 0); /* size placeholder */
5283     ffio_wfourcc(pb, "uuid");
5284     avio_write(pb, uuid, AV_UUID_LEN);
5285     avio_w8(pb, 1);
5286     avio_wb24(pb, 0);
5287     avio_wb64(pb, track->cluster[0].dts + track->cluster[0].cts);
5288     avio_wb64(pb, track->end_pts -
5289                   (track->cluster[0].dts + track->cluster[0].cts));
5290 
5291     return update_size(pb, pos);
5292 }
5293 
5294 static int mov_write_tfrf_tag(AVIOContext *pb, MOVMuxContext *mov,
5295                               MOVTrack *track, int entry)
5296 {
5297     int n = track->nb_frag_info - 1 - entry, i;
5298     int size = 8 + 16 + 4 + 1 + 16*n;
5299     static const uint8_t uuid[] = {
5300         0xd4, 0x80, 0x7e, 0xf2, 0xca, 0x39, 0x46, 0x95,
5301         0x8e, 0x54, 0x26, 0xcb, 0x9e, 0x46, 0xa7, 0x9f
5302     };
5303 
5304     if (entry < 0)
5305         return 0;
5306 
5307     avio_seek(pb, track->frag_info[entry].tfrf_offset, SEEK_SET);
5308     avio_wb32(pb, size);
5309     ffio_wfourcc(pb, "uuid");
5310     avio_write(pb, uuid, AV_UUID_LEN);
5311     avio_w8(pb, 1);
5312     avio_wb24(pb, 0);
5313     avio_w8(pb, n);
5314     for (i = 0; i < n; i++) {
5315         int index = entry + 1 + i;
5316         avio_wb64(pb, track->frag_info[index].time);
5317         avio_wb64(pb, track->frag_info[index].duration);
5318     }
5319     if (n < mov->ism_lookahead) {
5320         int free_size = 16 * (mov->ism_lookahead - n);
5321         avio_wb32(pb, free_size);
5322         ffio_wfourcc(pb, "free");
5323         ffio_fill(pb, 0, free_size - 8);
5324     }
5325 
5326     return 0;
5327 }
5328 
5329 static int mov_write_tfrf_tags(AVIOContext *pb, MOVMuxContext *mov,
5330                                MOVTrack *track)
5331 {
5332     int64_t pos = avio_tell(pb);
5333     int i;
5334     for (i = 0; i < mov->ism_lookahead; i++) {
5335         /* Update the tfrf tag for the last ism_lookahead fragments,
5336          * nb_frag_info - 1 is the next fragment to be written. */
5337         mov_write_tfrf_tag(pb, mov, track, track->nb_frag_info - 2 - i);
5338     }
5339     avio_seek(pb, pos, SEEK_SET);
5340     return 0;
5341 }
5342 
5343 static int mov_add_tfra_entries(AVIOContext *pb, MOVMuxContext *mov, int tracks,
5344                                 int size)
5345 {
5346     int i;
5347     for (i = 0; i < mov->nb_streams; i++) {
5348         MOVTrack *track = &mov->tracks[i];
5349         MOVFragmentInfo *info;
5350         if ((tracks >= 0 && i != tracks) || !track->entry)
5351             continue;
5352         track->nb_frag_info++;
5353         if (track->nb_frag_info >= track->frag_info_capacity) {
5354             unsigned new_capacity = track->nb_frag_info + MOV_FRAG_INFO_ALLOC_INCREMENT;
5355             if (av_reallocp_array(&track->frag_info,
5356                                   new_capacity,
5357                                   sizeof(*track->frag_info)))
5358                 return AVERROR(ENOMEM);
5359             track->frag_info_capacity = new_capacity;
5360         }
5361         info = &track->frag_info[track->nb_frag_info - 1];
5362         info->offset   = avio_tell(pb);
5363         info->size     = size;
5364         // Try to recreate the original pts for the first packet
5365         // from the fields we have stored
5366         info->time     = track->cluster[0].dts + track->cluster[0].cts;
5367         info->duration = track->end_pts -
5368                          (track->cluster[0].dts + track->cluster[0].cts);
5369         // If the pts is less than zero, we will have trimmed
5370         // away parts of the media track using an edit list,
5371         // and the corresponding start presentation time is zero.
5372         if (info->time < 0) {
5373             info->duration += info->time;
5374             info->time = 0;
5375         }
5376         info->tfrf_offset = 0;
5377         mov_write_tfrf_tags(pb, mov, track);
5378     }
5379     return 0;
5380 }
5381 
5382 static void mov_prune_frag_info(MOVMuxContext *mov, int tracks, int max)
5383 {
5384     int i;
5385     for (i = 0; i < mov->nb_streams; i++) {
5386         MOVTrack *track = &mov->tracks[i];
5387         if ((tracks >= 0 && i != tracks) || !track->entry)
5388             continue;
5389         if (track->nb_frag_info > max) {
5390             memmove(track->frag_info, track->frag_info + (track->nb_frag_info - max), max * sizeof(*track->frag_info));
5391             track->nb_frag_info = max;
5392         }
5393     }
5394 }
5395 
5396 static int mov_write_tfdt_tag(AVIOContext *pb, MOVTrack *track)
5397 {
5398     int64_t pos = avio_tell(pb);
5399 
5400     avio_wb32(pb, 0); /* size */
5401     ffio_wfourcc(pb, "tfdt");
5402     avio_w8(pb, 1); /* version */
5403     avio_wb24(pb, 0);
5404     avio_wb64(pb, track->cluster[0].dts - track->start_dts);
5405     return update_size(pb, pos);
5406 }
5407 
5408 static int mov_write_traf_tag(AVIOContext *pb, MOVMuxContext *mov,
5409                               MOVTrack *track, int64_t moof_offset,
5410                               int moof_size)
5411 {
5412     int64_t pos = avio_tell(pb);
5413     int i, start = 0;
5414     avio_wb32(pb, 0); /* size placeholder */
5415     ffio_wfourcc(pb, "traf");
5416 
5417     mov_write_tfhd_tag(pb, mov, track, moof_offset);
5418     if (mov->mode != MODE_ISM)
5419         mov_write_tfdt_tag(pb, track);
5420     for (i = 1; i < track->entry; i++) {
5421         if (track->cluster[i].pos != track->cluster[i - 1].pos + track->cluster[i - 1].size) {
5422             mov_write_trun_tag(pb, mov, track, moof_size, start, i);
5423             start = i;
5424         }
5425     }
5426     mov_write_trun_tag(pb, mov, track, moof_size, start, track->entry);
5427     if (mov->mode == MODE_ISM) {
5428         mov_write_tfxd_tag(pb, track);
5429 
5430         if (mov->ism_lookahead) {
5431             int size = 16 + 4 + 1 + 16 * mov->ism_lookahead;
5432 
5433             if (track->nb_frag_info > 0) {
5434                 MOVFragmentInfo *info = &track->frag_info[track->nb_frag_info - 1];
5435                 if (!info->tfrf_offset)
5436                     info->tfrf_offset = avio_tell(pb);
5437             }
5438             avio_wb32(pb, 8 + size);
5439             ffio_wfourcc(pb, "free");
5440             ffio_fill(pb, 0, size);
5441         }
5442     }
5443 
5444     return update_size(pb, pos);
5445 }
5446 
5447 static int mov_write_moof_tag_internal(AVIOContext *pb, MOVMuxContext *mov,
5448                                        int tracks, int moof_size)
5449 {
5450     int64_t pos = avio_tell(pb);
5451     int i;
5452 
5453     avio_wb32(pb, 0); /* size placeholder */
5454     ffio_wfourcc(pb, "moof");
5455     mov->first_trun = 1;
5456 
5457     mov_write_mfhd_tag(pb, mov);
5458     for (i = 0; i < mov->nb_streams; i++) {
5459         MOVTrack *track = &mov->tracks[i];
5460         if (tracks >= 0 && i != tracks)
5461             continue;
5462         if (!track->entry)
5463             continue;
5464         mov_write_traf_tag(pb, mov, track, pos, moof_size);
5465     }
5466 
5467     return update_size(pb, pos);
5468 }
5469 
5470 static int mov_write_sidx_tag(AVIOContext *pb,
5471                               MOVTrack *track, int ref_size, int total_sidx_size)
5472 {
5473     int64_t pos = avio_tell(pb), offset_pos, end_pos;
5474     int64_t presentation_time, duration, offset;
5475     unsigned starts_with_SAP;
5476     int i, entries;
5477 
5478     if (track->entry) {
5479         entries = 1;
5480         presentation_time = track->cluster[0].dts + track->cluster[0].cts -
5481                             track->start_dts - track->start_cts;
5482         duration = track->end_pts -
5483                    (track->cluster[0].dts + track->cluster[0].cts);
5484         starts_with_SAP = track->cluster[0].flags & MOV_SYNC_SAMPLE;
5485 
5486         // pts<0 should be cut away using edts
5487         if (presentation_time < 0) {
5488             duration += presentation_time;
5489             presentation_time = 0;
5490         }
5491     } else {
5492         entries = track->nb_frag_info;
5493         if (entries <= 0)
5494             return 0;
5495         presentation_time = track->frag_info[0].time;
5496         /* presentation_time <= 0 is handled by mov_add_tfra_entries() */
5497         if (presentation_time > 0)
5498             presentation_time -= track->start_dts + track->start_cts;
5499     }
5500 
5501     avio_wb32(pb, 0); /* size */
5502     ffio_wfourcc(pb, "sidx");
5503     avio_w8(pb, 1); /* version */
5504     avio_wb24(pb, 0);
5505     avio_wb32(pb, track->track_id); /* reference_ID */
5506     avio_wb32(pb, track->timescale); /* timescale */
5507     avio_wb64(pb, presentation_time); /* earliest_presentation_time */
5508     offset_pos = avio_tell(pb);
5509     avio_wb64(pb, 0); /* first_offset (offset to referenced moof) */
5510     avio_wb16(pb, 0); /* reserved */
5511 
5512     avio_wb16(pb, entries); /* reference_count */
5513     for (i = 0; i < entries; i++) {
5514         if (!track->entry) {
5515             if (i > 1 && track->frag_info[i].offset != track->frag_info[i - 1].offset + track->frag_info[i - 1].size) {
5516                av_log(NULL, AV_LOG_ERROR, "Non-consecutive fragments, writing incorrect sidx\n");
5517             }
5518             duration = track->frag_info[i].duration;
5519             ref_size = track->frag_info[i].size;
5520             starts_with_SAP = 1;
5521         }
5522         avio_wb32(pb, (0 << 31) | (ref_size & 0x7fffffff)); /* reference_type (0 = media) | referenced_size */
5523         avio_wb32(pb, duration); /* subsegment_duration */
5524         avio_wb32(pb, (starts_with_SAP << 31) | (0 << 28) | 0); /* starts_with_SAP | SAP_type | SAP_delta_time */
5525     }
5526 
5527     end_pos = avio_tell(pb);
5528     offset = pos + total_sidx_size - end_pos;
5529     avio_seek(pb, offset_pos, SEEK_SET);
5530     avio_wb64(pb, offset);
5531     avio_seek(pb, end_pos, SEEK_SET);
5532     return update_size(pb, pos);
5533 }
5534 
5535 static int mov_write_sidx_tags(AVIOContext *pb, MOVMuxContext *mov,
5536                                int tracks, int ref_size)
5537 {
5538     int i, round, ret;
5539     AVIOContext *avio_buf;
5540     int total_size = 0;
5541     for (round = 0; round < 2; round++) {
5542         // First run one round to calculate the total size of all
5543         // sidx atoms.
5544         // This would be much simpler if we'd only write one sidx
5545         // atom, for the first track in the moof.
5546         if (round == 0) {
5547             if ((ret = ffio_open_null_buf(&avio_buf)) < 0)
5548                 return ret;
5549         } else {
5550             avio_buf = pb;
5551         }
5552         for (i = 0; i < mov->nb_streams; i++) {
5553             MOVTrack *track = &mov->tracks[i];
5554             if (tracks >= 0 && i != tracks)
5555                 continue;
5556             // When writing a sidx for the full file, entry is 0, but
5557             // we want to include all tracks. ref_size is 0 in this case,
5558             // since we read it from frag_info instead.
5559             if (!track->entry && ref_size > 0)
5560                 continue;
5561             total_size -= mov_write_sidx_tag(avio_buf, track, ref_size,
5562                                              total_size);
5563         }
5564         if (round == 0)
5565             total_size = ffio_close_null_buf(avio_buf);
5566     }
5567     return 0;
5568 }
5569 
5570 static int mov_write_prft_tag(AVIOContext *pb, MOVMuxContext *mov, int tracks)
5571 {
5572     int64_t pos = avio_tell(pb), pts_us, ntp_ts;
5573     MOVTrack *first_track;
5574     int flags = 24;
5575 
5576     /* PRFT should be associated with at most one track. So, choosing only the
5577      * first track. */
5578     if (tracks > 0)
5579         return 0;
5580     first_track = &(mov->tracks[0]);
5581 
5582     if (!first_track->entry) {
5583         av_log(mov->fc, AV_LOG_WARNING, "Unable to write PRFT, no entries in the track\n");
5584         return 0;
5585     }
5586 
5587     if (first_track->cluster[0].pts == AV_NOPTS_VALUE) {
5588         av_log(mov->fc, AV_LOG_WARNING, "Unable to write PRFT, first PTS is invalid\n");
5589         return 0;
5590     }
5591 
5592     if (mov->write_prft == MOV_PRFT_SRC_WALLCLOCK) {
5593         if (first_track->cluster[0].prft.wallclock) {
5594             /* Round the NTP time to whole milliseconds. */
5595             ntp_ts = ff_get_formatted_ntp_time((first_track->cluster[0].prft.wallclock / 1000) * 1000 +
5596                                                NTP_OFFSET_US);
5597             flags = first_track->cluster[0].prft.flags;
5598         } else
5599             ntp_ts = ff_get_formatted_ntp_time(ff_ntp_time());
5600     } else if (mov->write_prft == MOV_PRFT_SRC_PTS) {
5601         pts_us = av_rescale_q(first_track->cluster[0].pts,
5602                               first_track->st->time_base, AV_TIME_BASE_Q);
5603         ntp_ts = ff_get_formatted_ntp_time(pts_us + NTP_OFFSET_US);
5604     } else {
5605         av_log(mov->fc, AV_LOG_WARNING, "Unsupported PRFT box configuration: %d\n",
5606                mov->write_prft);
5607         return 0;
5608     }
5609 
5610     avio_wb32(pb, 0);                           // Size place holder
5611     ffio_wfourcc(pb, "prft");                   // Type
5612     avio_w8(pb, 1);                             // Version
5613     avio_wb24(pb, flags);                       // Flags
5614     avio_wb32(pb, first_track->track_id);       // reference track ID
5615     avio_wb64(pb, ntp_ts);                      // NTP time stamp
5616     avio_wb64(pb, first_track->cluster[0].pts); //media time
5617     return update_size(pb, pos);
5618 }
5619 
5620 static int mov_write_moof_tag(AVIOContext *pb, MOVMuxContext *mov, int tracks,
5621                               int64_t mdat_size)
5622 {
5623     AVIOContext *avio_buf;
5624     int ret, moof_size;
5625 
5626     if ((ret = ffio_open_null_buf(&avio_buf)) < 0)
5627         return ret;
5628     mov_write_moof_tag_internal(avio_buf, mov, tracks, 0);
5629     moof_size = ffio_close_null_buf(avio_buf);
5630 
5631     if (mov->flags & FF_MOV_FLAG_DASH &&
5632         !(mov->flags & (FF_MOV_FLAG_GLOBAL_SIDX | FF_MOV_FLAG_SKIP_SIDX)))
5633         mov_write_sidx_tags(pb, mov, tracks, moof_size + 8 + mdat_size);
5634 
5635     if (mov->write_prft > MOV_PRFT_NONE && mov->write_prft < MOV_PRFT_NB)
5636         mov_write_prft_tag(pb, mov, tracks);
5637 
5638     if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX ||
5639         !(mov->flags & FF_MOV_FLAG_SKIP_TRAILER) ||
5640         mov->ism_lookahead) {
5641         if ((ret = mov_add_tfra_entries(pb, mov, tracks, moof_size + 8 + mdat_size)) < 0)
5642             return ret;
5643         if (!(mov->flags & FF_MOV_FLAG_GLOBAL_SIDX) &&
5644             mov->flags & FF_MOV_FLAG_SKIP_TRAILER) {
5645             mov_prune_frag_info(mov, tracks, mov->ism_lookahead + 1);
5646         }
5647     }
5648 
5649     return mov_write_moof_tag_internal(pb, mov, tracks, moof_size);
5650 }
5651 
5652 static int mov_write_tfra_tag(AVIOContext *pb, MOVTrack *track)
5653 {
5654     int64_t pos = avio_tell(pb);
5655     int i;
5656 
5657     avio_wb32(pb, 0); /* size placeholder */
5658     ffio_wfourcc(pb, "tfra");
5659     avio_w8(pb, 1); /* version */
5660     avio_wb24(pb, 0);
5661 
5662     avio_wb32(pb, track->track_id);
5663     avio_wb32(pb, 0); /* length of traf/trun/sample num */
5664     avio_wb32(pb, track->nb_frag_info);
5665     for (i = 0; i < track->nb_frag_info; i++) {
5666         avio_wb64(pb, track->frag_info[i].time);
5667         avio_wb64(pb, track->frag_info[i].offset + track->data_offset);
5668         avio_w8(pb, 1); /* traf number */
5669         avio_w8(pb, 1); /* trun number */
5670         avio_w8(pb, 1); /* sample number */
5671     }
5672 
5673     return update_size(pb, pos);
5674 }
5675 
5676 static int mov_write_mfra_tag(AVIOContext *pb, MOVMuxContext *mov)
5677 {
5678     AVIOContext *mfra_pb;
5679     int i, ret, sz;
5680     uint8_t *buf;
5681 
5682     ret = avio_open_dyn_buf(&mfra_pb);
5683     if (ret < 0)
5684         return ret;
5685 
5686     avio_wb32(mfra_pb, 0); /* size placeholder */
5687     ffio_wfourcc(mfra_pb, "mfra");
5688     /* An empty mfra atom is enough to indicate to the publishing point that
5689      * the stream has ended. */
5690     if (mov->flags & FF_MOV_FLAG_ISML)
5691         goto done_mfra;
5692 
5693     for (i = 0; i < mov->nb_streams; i++) {
5694         MOVTrack *track = &mov->tracks[i];
5695         if (track->nb_frag_info)
5696             mov_write_tfra_tag(mfra_pb, track);
5697     }
5698 
5699     avio_wb32(mfra_pb, 16);
5700     ffio_wfourcc(mfra_pb, "mfro");
5701     avio_wb32(mfra_pb, 0); /* version + flags */
5702     avio_wb32(mfra_pb, avio_tell(mfra_pb) + 4);
5703 
5704 done_mfra:
5705 
5706     sz  = update_size(mfra_pb, 0);
5707     ret = avio_get_dyn_buf(mfra_pb, &buf);
5708     avio_write(pb, buf, ret);
5709     ffio_free_dyn_buf(&mfra_pb);
5710 
5711     return sz;
5712 }
5713 
5714 static int mov_write_mdat_tag(AVIOContext *pb, MOVMuxContext *mov)
5715 {
5716     avio_wb32(pb, 8);    // placeholder for extended size field (64 bit)
5717     ffio_wfourcc(pb, mov->mode == MODE_MOV ? "wide" : "free");
5718 
5719     mov->mdat_pos = avio_tell(pb);
5720     avio_wb32(pb, 0); /* size placeholder*/
5721     ffio_wfourcc(pb, "mdat");
5722     return 0;
5723 }
5724 
5725 static void mov_write_ftyp_tag_internal(AVIOContext *pb, AVFormatContext *s,
5726                                         int has_h264, int has_video, int write_minor)
5727 {
5728     MOVMuxContext *mov = s->priv_data;
5729     int minor = 0x200;
5730 
5731     if (mov->major_brand && strlen(mov->major_brand) >= 4)
5732         ffio_wfourcc(pb, mov->major_brand);
5733     else if (mov->mode == MODE_3GP) {
5734         ffio_wfourcc(pb, has_h264 ? "3gp6"  : "3gp4");
5735         minor =     has_h264 ?   0x100 :   0x200;
5736     } else if (mov->mode == MODE_AVIF) {
5737         ffio_wfourcc(pb, mov->is_animated_avif ? "avis" : "avif");
5738         minor = 0;
5739     } else if (mov->mode & MODE_3G2) {
5740         ffio_wfourcc(pb, has_h264 ? "3g2b"  : "3g2a");
5741         minor =     has_h264 ? 0x20000 : 0x10000;
5742     } else if (mov->mode == MODE_PSP)
5743         ffio_wfourcc(pb, "MSNV");
5744     else if (mov->mode == MODE_MP4 && mov->flags & FF_MOV_FLAG_FRAGMENT &&
5745                                       mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS)
5746         ffio_wfourcc(pb, "iso6"); // Required when using signed CTS offsets in trun boxes
5747     else if (mov->mode == MODE_MP4 && mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF)
5748         ffio_wfourcc(pb, "iso5"); // Required when using default-base-is-moof
5749     else if (mov->mode == MODE_MP4 && mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS)
5750         ffio_wfourcc(pb, "iso4");
5751     else if (mov->mode == MODE_MP4)
5752         ffio_wfourcc(pb, "isom");
5753     else if (mov->mode == MODE_IPOD)
5754         ffio_wfourcc(pb, has_video ? "M4V ":"M4A ");
5755     else if (mov->mode == MODE_ISM)
5756         ffio_wfourcc(pb, "isml");
5757     else if (mov->mode == MODE_F4V)
5758         ffio_wfourcc(pb, "f4v ");
5759     else
5760         ffio_wfourcc(pb, "qt  ");
5761 
5762     if (write_minor)
5763         avio_wb32(pb, minor);
5764 }
5765 
5766 static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s)
5767 {
5768     MOVMuxContext *mov = s->priv_data;
5769     int64_t pos = avio_tell(pb);
5770     int has_h264 = 0, has_av1 = 0, has_video = 0, has_dolby = 0;
5771     int i;
5772 
5773     for (i = 0; i < s->nb_streams; i++) {
5774         AVStream *st = s->streams[i];
5775         if (is_cover_image(st))
5776             continue;
5777         if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
5778             has_video = 1;
5779         if (st->codecpar->codec_id == AV_CODEC_ID_H264)
5780             has_h264 = 1;
5781         if (st->codecpar->codec_id == AV_CODEC_ID_AV1)
5782             has_av1 = 1;
5783         if (st->codecpar->codec_id == AV_CODEC_ID_AC3 ||
5784             st->codecpar->codec_id == AV_CODEC_ID_EAC3 ||
5785             st->codecpar->codec_id == AV_CODEC_ID_TRUEHD ||
5786             av_stream_get_side_data(st, AV_PKT_DATA_DOVI_CONF, NULL))
5787             has_dolby = 1;
5788     }
5789 
5790     avio_wb32(pb, 0); /* size */
5791     ffio_wfourcc(pb, "ftyp");
5792 
5793     // Write major brand
5794     mov_write_ftyp_tag_internal(pb, s, has_h264, has_video, 1);
5795     // Write the major brand as the first compatible brand as well
5796     mov_write_ftyp_tag_internal(pb, s, has_h264, has_video, 0);
5797 
5798     // Write compatible brands, ensuring that we don't write the major brand as a
5799     // compatible brand a second time.
5800     if (mov->mode == MODE_ISM) {
5801         ffio_wfourcc(pb, "piff");
5802     } else if (mov->mode == MODE_AVIF) {
5803         const AVPixFmtDescriptor *pix_fmt_desc =
5804             av_pix_fmt_desc_get(s->streams[0]->codecpar->format);
5805         const int depth = pix_fmt_desc->comp[0].depth;
5806         if (mov->is_animated_avif) {
5807             // For animated AVIF, major brand is "avis". Add "avif" as a
5808             // compatible brand.
5809             ffio_wfourcc(pb, "avif");
5810             ffio_wfourcc(pb, "msf1");
5811             ffio_wfourcc(pb, "iso8");
5812         }
5813         ffio_wfourcc(pb, "mif1");
5814         ffio_wfourcc(pb, "miaf");
5815         if (depth == 8 || depth == 10) {
5816             // MA1B and MA1A brands are based on AV1 profile. Short hand for
5817             // computing that is based on chroma subsampling type. 420 chroma
5818             // subsampling is MA1B.  444 chroma subsampling is MA1A.
5819             if (!pix_fmt_desc->log2_chroma_w && !pix_fmt_desc->log2_chroma_h) {
5820                 // 444 chroma subsampling.
5821                 ffio_wfourcc(pb, "MA1A");
5822             } else {
5823                 // 420 chroma subsampling.
5824                 ffio_wfourcc(pb, "MA1B");
5825             }
5826         }
5827     } else if (mov->mode != MODE_MOV) {
5828         // We add tfdt atoms when fragmenting, signal this with the iso6 compatible
5829         // brand, if not already the major brand. This is compatible with users that
5830         // don't understand tfdt.
5831         if (mov->mode == MODE_MP4) {
5832             if (mov->flags & FF_MOV_FLAG_CMAF)
5833                 ffio_wfourcc(pb, "cmfc");
5834             if (mov->flags & FF_MOV_FLAG_FRAGMENT && !(mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS))
5835                 ffio_wfourcc(pb, "iso6");
5836             if (has_av1)
5837                 ffio_wfourcc(pb, "av01");
5838             if (has_dolby)
5839                 ffio_wfourcc(pb, "dby1");
5840         } else {
5841             if (mov->flags & FF_MOV_FLAG_FRAGMENT)
5842                 ffio_wfourcc(pb, "iso6");
5843             if (mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF)
5844                 ffio_wfourcc(pb, "iso5");
5845             else if (mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS)
5846                 ffio_wfourcc(pb, "iso4");
5847         }
5848         // Brands prior to iso5 can't be signaled when using default-base-is-moof
5849         if (!(mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF)) {
5850             // write isom for mp4 only if it it's not the major brand already.
5851             if (mov->mode != MODE_MP4 || mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS)
5852                 ffio_wfourcc(pb, "isom");
5853             ffio_wfourcc(pb, "iso2");
5854             if (has_h264)
5855                 ffio_wfourcc(pb, "avc1");
5856         }
5857     }
5858 
5859     if (mov->mode == MODE_MP4)
5860         ffio_wfourcc(pb, "mp41");
5861 
5862     if (mov->flags & FF_MOV_FLAG_DASH && mov->flags & FF_MOV_FLAG_GLOBAL_SIDX)
5863         ffio_wfourcc(pb, "dash");
5864 
5865     return update_size(pb, pos);
5866 }
5867 
5868 static int mov_write_uuidprof_tag(AVIOContext *pb, AVFormatContext *s)
5869 {
5870     AVStream       *video_st    = s->streams[0];
5871     AVCodecParameters *video_par = s->streams[0]->codecpar;
5872     AVCodecParameters *audio_par = s->streams[1]->codecpar;
5873     int audio_rate = audio_par->sample_rate;
5874     int64_t frame_rate = video_st->avg_frame_rate.den ?
5875                         (video_st->avg_frame_rate.num * 0x10000LL) / video_st->avg_frame_rate.den :
5876                         0;
5877     int audio_kbitrate = audio_par->bit_rate / 1000;
5878     int video_kbitrate = FFMIN(video_par->bit_rate / 1000, 800 - audio_kbitrate);
5879 
5880     if (frame_rate < 0 || frame_rate > INT32_MAX) {
5881         av_log(s, AV_LOG_ERROR, "Frame rate %f outside supported range\n", frame_rate / (double)0x10000);
5882         return AVERROR(EINVAL);
5883     }
5884 
5885     avio_wb32(pb, 0x94); /* size */
5886     ffio_wfourcc(pb, "uuid");
5887     ffio_wfourcc(pb, "PROF");
5888 
5889     avio_wb32(pb, 0x21d24fce); /* 96 bit UUID */
5890     avio_wb32(pb, 0xbb88695c);
5891     avio_wb32(pb, 0xfac9c740);
5892 
5893     avio_wb32(pb, 0x0);  /* ? */
5894     avio_wb32(pb, 0x3);  /* 3 sections ? */
5895 
5896     avio_wb32(pb, 0x14); /* size */
5897     ffio_wfourcc(pb, "FPRF");
5898     avio_wb32(pb, 0x0);  /* ? */
5899     avio_wb32(pb, 0x0);  /* ? */
5900     avio_wb32(pb, 0x0);  /* ? */
5901 
5902     avio_wb32(pb, 0x2c);  /* size */
5903     ffio_wfourcc(pb, "APRF"); /* audio */
5904     avio_wb32(pb, 0x0);
5905     avio_wb32(pb, 0x2);   /* TrackID */
5906     ffio_wfourcc(pb, "mp4a");
5907     avio_wb32(pb, 0x20f);
5908     avio_wb32(pb, 0x0);
5909     avio_wb32(pb, audio_kbitrate);
5910     avio_wb32(pb, audio_kbitrate);
5911     avio_wb32(pb, audio_rate);
5912     avio_wb32(pb, audio_par->ch_layout.nb_channels);
5913 
5914     avio_wb32(pb, 0x34);  /* size */
5915     ffio_wfourcc(pb, "VPRF");   /* video */
5916     avio_wb32(pb, 0x0);
5917     avio_wb32(pb, 0x1);    /* TrackID */
5918     if (video_par->codec_id == AV_CODEC_ID_H264) {
5919         ffio_wfourcc(pb, "avc1");
5920         avio_wb16(pb, 0x014D);
5921         avio_wb16(pb, 0x0015);
5922     } else {
5923         ffio_wfourcc(pb, "mp4v");
5924         avio_wb16(pb, 0x0000);
5925         avio_wb16(pb, 0x0103);
5926     }
5927     avio_wb32(pb, 0x0);
5928     avio_wb32(pb, video_kbitrate);
5929     avio_wb32(pb, video_kbitrate);
5930     avio_wb32(pb, frame_rate);
5931     avio_wb32(pb, frame_rate);
5932     avio_wb16(pb, video_par->width);
5933     avio_wb16(pb, video_par->height);
5934     avio_wb32(pb, 0x010001); /* ? */
5935 
5936     return 0;
5937 }
5938 
5939 static int mov_write_identification(AVIOContext *pb, AVFormatContext *s)
5940 {
5941     MOVMuxContext *mov = s->priv_data;
5942     int i;
5943 
5944     mov_write_ftyp_tag(pb,s);
5945     if (mov->mode == MODE_PSP) {
5946         int video_streams_nb = 0, audio_streams_nb = 0, other_streams_nb = 0;
5947         for (i = 0; i < s->nb_streams; i++) {
5948             AVStream *st = s->streams[i];
5949             if (is_cover_image(st))
5950                 continue;
5951             if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
5952                 video_streams_nb++;
5953             else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
5954                 audio_streams_nb++;
5955             else
5956                 other_streams_nb++;
5957             }
5958 
5959         if (video_streams_nb != 1 || audio_streams_nb != 1 || other_streams_nb) {
5960             av_log(s, AV_LOG_ERROR, "PSP mode need one video and one audio stream\n");
5961             return AVERROR(EINVAL);
5962         }
5963         return mov_write_uuidprof_tag(pb, s);
5964     }
5965     return 0;
5966 }
5967 
5968 static int mov_parse_mpeg2_frame(AVPacket *pkt, uint32_t *flags)
5969 {
5970     uint32_t c = -1;
5971     int i, closed_gop = 0;
5972 
5973     for (i = 0; i < pkt->size - 4; i++) {
5974         c = (c << 8) + pkt->data[i];
5975         if (c == 0x1b8) { // gop
5976             closed_gop = pkt->data[i + 4] >> 6 & 0x01;
5977         } else if (c == 0x100) { // pic
5978             int temp_ref = (pkt->data[i + 1] << 2) | (pkt->data[i + 2] >> 6);
5979             if (!temp_ref || closed_gop) // I picture is not reordered
5980                 *flags = MOV_SYNC_SAMPLE;
5981             else
5982                 *flags = MOV_PARTIAL_SYNC_SAMPLE;
5983             break;
5984         }
5985     }
5986     return 0;
5987 }
5988 
5989 static void mov_parse_vc1_frame(AVPacket *pkt, MOVTrack *trk)
5990 {
5991     const uint8_t *start, *next, *end = pkt->data + pkt->size;
5992     int seq = 0, entry = 0;
5993     int key = pkt->flags & AV_PKT_FLAG_KEY;
5994     start = find_next_marker(pkt->data, end);
5995     for (next = start; next < end; start = next) {
5996         next = find_next_marker(start + 4, end);
5997         switch (AV_RB32(start)) {
5998         case VC1_CODE_SEQHDR:
5999             seq = 1;
6000             break;
6001         case VC1_CODE_ENTRYPOINT:
6002             entry = 1;
6003             break;
6004         case VC1_CODE_SLICE:
6005             trk->vc1_info.slices = 1;
6006             break;
6007         }
6008     }
6009     if (!trk->entry && trk->vc1_info.first_packet_seen)
6010         trk->vc1_info.first_frag_written = 1;
6011     if (!trk->entry && !trk->vc1_info.first_frag_written) {
6012         /* First packet in first fragment */
6013         trk->vc1_info.first_packet_seq   = seq;
6014         trk->vc1_info.first_packet_entry = entry;
6015         trk->vc1_info.first_packet_seen  = 1;
6016     } else if ((seq && !trk->vc1_info.packet_seq) ||
6017                (entry && !trk->vc1_info.packet_entry)) {
6018         int i;
6019         for (i = 0; i < trk->entry; i++)
6020             trk->cluster[i].flags &= ~MOV_SYNC_SAMPLE;
6021         trk->has_keyframes = 0;
6022         if (seq)
6023             trk->vc1_info.packet_seq = 1;
6024         if (entry)
6025             trk->vc1_info.packet_entry = 1;
6026         if (!trk->vc1_info.first_frag_written) {
6027             /* First fragment */
6028             if ((!seq   || trk->vc1_info.first_packet_seq) &&
6029                 (!entry || trk->vc1_info.first_packet_entry)) {
6030                 /* First packet had the same headers as this one, readd the
6031                  * sync sample flag. */
6032                 trk->cluster[0].flags |= MOV_SYNC_SAMPLE;
6033                 trk->has_keyframes = 1;
6034             }
6035         }
6036     }
6037     if (trk->vc1_info.packet_seq && trk->vc1_info.packet_entry)
6038         key = seq && entry;
6039     else if (trk->vc1_info.packet_seq)
6040         key = seq;
6041     else if (trk->vc1_info.packet_entry)
6042         key = entry;
6043     if (key) {
6044         trk->cluster[trk->entry].flags |= MOV_SYNC_SAMPLE;
6045         trk->has_keyframes++;
6046     }
6047 }
6048 
6049 static void mov_parse_truehd_frame(AVPacket *pkt, MOVTrack *trk)
6050 {
6051     int length;
6052 
6053     if (pkt->size < 8)
6054         return;
6055 
6056     length = (AV_RB16(pkt->data) & 0xFFF) * 2;
6057     if (length < 8 || length > pkt->size)
6058         return;
6059 
6060     if (AV_RB32(pkt->data + 4) == 0xF8726FBA) {
6061         trk->cluster[trk->entry].flags |= MOV_SYNC_SAMPLE;
6062         trk->has_keyframes++;
6063     }
6064 
6065     return;
6066 }
6067 
6068 static int mov_flush_fragment_interleaving(AVFormatContext *s, MOVTrack *track)
6069 {
6070     MOVMuxContext *mov = s->priv_data;
6071     int ret, buf_size;
6072     uint8_t *buf;
6073     int i, offset;
6074 
6075     if (!track->mdat_buf)
6076         return 0;
6077     if (!mov->mdat_buf) {
6078         if ((ret = avio_open_dyn_buf(&mov->mdat_buf)) < 0)
6079             return ret;
6080     }
6081     buf_size = avio_get_dyn_buf(track->mdat_buf, &buf);
6082 
6083     offset = avio_tell(mov->mdat_buf);
6084     avio_write(mov->mdat_buf, buf, buf_size);
6085     ffio_free_dyn_buf(&track->mdat_buf);
6086 
6087     for (i = track->entries_flushed; i < track->entry; i++)
6088         track->cluster[i].pos += offset;
6089     track->entries_flushed = track->entry;
6090     return 0;
6091 }
6092 
6093 static int mov_write_squashed_packet(AVFormatContext *s, MOVTrack *track)
6094 {
6095     MOVMuxContext *mov = s->priv_data;
6096     AVPacket *squashed_packet = mov->pkt;
6097     int ret = AVERROR_BUG;
6098 
6099     switch (track->st->codecpar->codec_id) {
6100     case AV_CODEC_ID_TTML: {
6101         int had_packets = !!track->squashed_packet_queue.head;
6102 
6103         if ((ret = ff_mov_generate_squashed_ttml_packet(s, track, squashed_packet)) < 0) {
6104             goto finish_squash;
6105         }
6106 
6107         // We have generated a padding packet (no actual input packets in
6108         // queue) and its duration is zero. Skipping writing it.
6109         if (!had_packets && squashed_packet->duration == 0) {
6110             goto finish_squash;
6111         }
6112 
6113         track->end_reliable = 1;
6114         break;
6115     }
6116     default:
6117         ret = AVERROR(EINVAL);
6118         goto finish_squash;
6119     }
6120 
6121     squashed_packet->stream_index = track->st->index;
6122 
6123     ret = mov_write_single_packet(s, squashed_packet);
6124 
6125 finish_squash:
6126     av_packet_unref(squashed_packet);
6127 
6128     return ret;
6129 }
6130 
6131 static int mov_write_squashed_packets(AVFormatContext *s)
6132 {
6133     MOVMuxContext *mov = s->priv_data;
6134 
6135     for (int i = 0; i < s->nb_streams; i++) {
6136         MOVTrack *track = &mov->tracks[i];
6137         int ret = AVERROR_BUG;
6138 
6139         if (track->squash_fragment_samples_to_one && !track->entry) {
6140             if ((ret = mov_write_squashed_packet(s, track)) < 0) {
6141                 av_log(s, AV_LOG_ERROR,
6142                        "Failed to write squashed packet for %s stream with "
6143                        "index %d and track id %d. Error: %s\n",
6144                        avcodec_get_name(track->st->codecpar->codec_id),
6145                        track->st->index, track->track_id,
6146                        av_err2str(ret));
6147                 return ret;
6148             }
6149         }
6150     }
6151 
6152     return 0;
6153 }
6154 
6155 static int mov_flush_fragment(AVFormatContext *s, int force)
6156 {
6157     MOVMuxContext *mov = s->priv_data;
6158     int i, first_track = -1;
6159     int64_t mdat_size = 0;
6160     int ret;
6161     int has_video = 0, starts_with_key = 0, first_video_track = 1;
6162 
6163     if (!(mov->flags & FF_MOV_FLAG_FRAGMENT))
6164         return 0;
6165 
6166     // Check if we have any tracks that require squashing.
6167     // In that case, we'll have to write the packet here.
6168     if ((ret = mov_write_squashed_packets(s)) < 0)
6169         return ret;
6170 
6171     // Try to fill in the duration of the last packet in each stream
6172     // from queued packets in the interleave queues. If the flushing
6173     // of fragments was triggered automatically by an AVPacket, we
6174     // already have reliable info for the end of that track, but other
6175     // tracks may need to be filled in.
6176     for (i = 0; i < s->nb_streams; i++) {
6177         MOVTrack *track = &mov->tracks[i];
6178         if (!track->end_reliable) {
6179             const AVPacket *pkt = ff_interleaved_peek(s, i);
6180             if (pkt) {
6181                 int64_t offset, dts, pts;
6182                 ff_get_muxer_ts_offset(s, i, &offset);
6183                 pts = pkt->pts + offset;
6184                 dts = pkt->dts + offset;
6185                 if (track->dts_shift != AV_NOPTS_VALUE)
6186                     dts += track->dts_shift;
6187                 track->track_duration = dts - track->start_dts;
6188                 if (pts != AV_NOPTS_VALUE)
6189                     track->end_pts = pts;
6190                 else
6191                     track->end_pts = dts;
6192             }
6193         }
6194     }
6195 
6196     for (i = 0; i < mov->nb_streams; i++) {
6197         MOVTrack *track = &mov->tracks[i];
6198         if (track->entry <= 1)
6199             continue;
6200         // Sample durations are calculated as the diff of dts values,
6201         // but for the last sample in a fragment, we don't know the dts
6202         // of the first sample in the next fragment, so we have to rely
6203         // on what was set as duration in the AVPacket. Not all callers
6204         // set this though, so we might want to replace it with an
6205         // estimate if it currently is zero.
6206         if (get_cluster_duration(track, track->entry - 1) != 0)
6207             continue;
6208         // Use the duration (i.e. dts diff) of the second last sample for
6209         // the last one. This is a wild guess (and fatal if it turns out
6210         // to be too long), but probably the best we can do - having a zero
6211         // duration is bad as well.
6212         track->track_duration += get_cluster_duration(track, track->entry - 2);
6213         track->end_pts        += get_cluster_duration(track, track->entry - 2);
6214         if (!mov->missing_duration_warned) {
6215             av_log(s, AV_LOG_WARNING,
6216                    "Estimating the duration of the last packet in a "
6217                    "fragment, consider setting the duration field in "
6218                    "AVPacket instead.\n");
6219             mov->missing_duration_warned = 1;
6220         }
6221     }
6222 
6223     if (!mov->moov_written) {
6224         int64_t pos = avio_tell(s->pb);
6225         uint8_t *buf;
6226         int buf_size, moov_size;
6227 
6228         for (i = 0; i < mov->nb_streams; i++)
6229             if (!mov->tracks[i].entry && !is_cover_image(mov->tracks[i].st))
6230                 break;
6231         /* Don't write the initial moov unless all tracks have data */
6232         if (i < mov->nb_streams && !force)
6233             return 0;
6234 
6235         moov_size = get_moov_size(s);
6236         for (i = 0; i < mov->nb_streams; i++)
6237             mov->tracks[i].data_offset = pos + moov_size + 8;
6238 
6239         avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_HEADER);
6240         if (mov->flags & FF_MOV_FLAG_DELAY_MOOV)
6241             mov_write_identification(s->pb, s);
6242         if ((ret = mov_write_moov_tag(s->pb, mov, s)) < 0)
6243             return ret;
6244 
6245         if (mov->flags & FF_MOV_FLAG_DELAY_MOOV) {
6246             if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX)
6247                 mov->reserved_header_pos = avio_tell(s->pb);
6248             avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT);
6249             mov->moov_written = 1;
6250             return 0;
6251         }
6252 
6253         buf_size = avio_get_dyn_buf(mov->mdat_buf, &buf);
6254         avio_wb32(s->pb, buf_size + 8);
6255         ffio_wfourcc(s->pb, "mdat");
6256         avio_write(s->pb, buf, buf_size);
6257         ffio_free_dyn_buf(&mov->mdat_buf);
6258 
6259         if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX)
6260             mov->reserved_header_pos = avio_tell(s->pb);
6261 
6262         mov->moov_written = 1;
6263         mov->mdat_size = 0;
6264         for (i = 0; i < mov->nb_streams; i++) {
6265             mov->tracks[i].entry = 0;
6266             mov->tracks[i].end_reliable = 0;
6267         }
6268         avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT);
6269         return 0;
6270     }
6271 
6272     if (mov->frag_interleave) {
6273         for (i = 0; i < mov->nb_streams; i++) {
6274             MOVTrack *track = &mov->tracks[i];
6275             int ret;
6276             if ((ret = mov_flush_fragment_interleaving(s, track)) < 0)
6277                 return ret;
6278         }
6279 
6280         if (!mov->mdat_buf)
6281             return 0;
6282         mdat_size = avio_tell(mov->mdat_buf);
6283     }
6284 
6285     for (i = 0; i < mov->nb_streams; i++) {
6286         MOVTrack *track = &mov->tracks[i];
6287         if (mov->flags & FF_MOV_FLAG_SEPARATE_MOOF || mov->frag_interleave)
6288             track->data_offset = 0;
6289         else
6290             track->data_offset = mdat_size;
6291         if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
6292             has_video = 1;
6293             if (first_video_track) {
6294                 if (track->entry)
6295                     starts_with_key = track->cluster[0].flags & MOV_SYNC_SAMPLE;
6296                 first_video_track = 0;
6297             }
6298         }
6299         if (!track->entry)
6300             continue;
6301         if (track->mdat_buf)
6302             mdat_size += avio_tell(track->mdat_buf);
6303         if (first_track < 0)
6304             first_track = i;
6305     }
6306 
6307     if (!mdat_size)
6308         return 0;
6309 
6310     avio_write_marker(s->pb,
6311                       av_rescale(mov->tracks[first_track].cluster[0].dts, AV_TIME_BASE, mov->tracks[first_track].timescale),
6312                       (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);
6313 
6314     for (i = 0; i < mov->nb_streams; i++) {
6315         MOVTrack *track = &mov->tracks[i];
6316         int buf_size, write_moof = 1, moof_tracks = -1;
6317         uint8_t *buf;
6318 
6319         if (mov->flags & FF_MOV_FLAG_SEPARATE_MOOF) {
6320             if (!track->entry)
6321                 continue;
6322             mdat_size = avio_tell(track->mdat_buf);
6323             moof_tracks = i;
6324         } else {
6325             write_moof = i == first_track;
6326         }
6327 
6328         if (write_moof) {
6329             avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT);
6330 
6331             mov_write_moof_tag(s->pb, mov, moof_tracks, mdat_size);
6332             mov->fragments++;
6333 
6334             avio_wb32(s->pb, mdat_size + 8);
6335             ffio_wfourcc(s->pb, "mdat");
6336         }
6337 
6338         track->entry = 0;
6339         track->entries_flushed = 0;
6340         track->end_reliable = 0;
6341         if (!mov->frag_interleave) {
6342             if (!track->mdat_buf)
6343                 continue;
6344             buf_size = avio_close_dyn_buf(track->mdat_buf, &buf);
6345             track->mdat_buf = NULL;
6346         } else {
6347             if (!mov->mdat_buf)
6348                 continue;
6349             buf_size = avio_close_dyn_buf(mov->mdat_buf, &buf);
6350             mov->mdat_buf = NULL;
6351         }
6352 
6353         avio_write(s->pb, buf, buf_size);
6354         av_free(buf);
6355     }
6356 
6357     mov->mdat_size = 0;
6358 
6359     avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT);
6360     return 0;
6361 }
6362 
6363 static int mov_auto_flush_fragment(AVFormatContext *s, int force)
6364 {
6365     MOVMuxContext *mov = s->priv_data;
6366     int had_moov = mov->moov_written;
6367     int ret = mov_flush_fragment(s, force);
6368     if (ret < 0)
6369         return ret;
6370     // If using delay_moov, the first flush only wrote the moov,
6371     // not the actual moof+mdat pair, thus flush once again.
6372     if (!had_moov && mov->flags & FF_MOV_FLAG_DELAY_MOOV)
6373         ret = mov_flush_fragment(s, force);
6374     return ret;
6375 }
6376 
6377 static int check_pkt(AVFormatContext *s, AVPacket *pkt)
6378 {
6379     MOVMuxContext *mov = s->priv_data;
6380     MOVTrack *trk = &mov->tracks[pkt->stream_index];
6381     int64_t ref;
6382     uint64_t duration;
6383 
6384     if (trk->entry) {
6385         ref = trk->cluster[trk->entry - 1].dts;
6386     } else if (   trk->start_dts != AV_NOPTS_VALUE
6387                && !trk->frag_discont) {
6388         ref = trk->start_dts + trk->track_duration;
6389     } else
6390         ref = pkt->dts; // Skip tests for the first packet
6391 
6392     if (trk->dts_shift != AV_NOPTS_VALUE) {
6393         /* With negative CTS offsets we have set an offset to the DTS,
6394          * reverse this for the check. */
6395         ref -= trk->dts_shift;
6396     }
6397 
6398     duration = pkt->dts - ref;
6399     if (pkt->dts < ref || duration >= INT_MAX) {
6400         av_log(s, AV_LOG_WARNING, "Packet duration: %"PRId64" / dts: %"PRId64" is out of range\n",
6401                duration, pkt->dts);
6402 
6403         pkt->dts = ref + 1;
6404         pkt->pts = AV_NOPTS_VALUE;
6405     }
6406 
6407     if (pkt->duration < 0 || pkt->duration > INT_MAX) {
6408         av_log(s, AV_LOG_ERROR, "Application provided duration: %"PRId64" is invalid\n", pkt->duration);
6409         return AVERROR(EINVAL);
6410     }
6411     return 0;
6412 }
6413 
6414 int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
6415 {
6416     MOVMuxContext *mov = s->priv_data;
6417     AVIOContext *pb = s->pb;
6418     MOVTrack *trk = &mov->tracks[pkt->stream_index];
6419     AVCodecParameters *par = trk->par;
6420     AVProducerReferenceTime *prft;
6421     unsigned int samples_in_chunk = 0;
6422     int size = pkt->size, ret = 0, offset = 0;
6423     size_t prft_size;
6424     uint8_t *reformatted_data = NULL;
6425 
6426     ret = check_pkt(s, pkt);
6427     if (ret < 0)
6428         return ret;
6429 
6430     if (mov->flags & FF_MOV_FLAG_FRAGMENT || mov->mode == MODE_AVIF) {
6431         int ret;
6432         if (mov->moov_written || mov->flags & FF_MOV_FLAG_EMPTY_MOOV) {
6433             if (mov->frag_interleave && mov->fragments > 0) {
6434                 if (trk->entry - trk->entries_flushed >= mov->frag_interleave) {
6435                     if ((ret = mov_flush_fragment_interleaving(s, trk)) < 0)
6436                         return ret;
6437                 }
6438             }
6439 
6440             if (!trk->mdat_buf) {
6441                 if ((ret = avio_open_dyn_buf(&trk->mdat_buf)) < 0)
6442                     return ret;
6443             }
6444             pb = trk->mdat_buf;
6445         } else {
6446             if (!mov->mdat_buf) {
6447                 if ((ret = avio_open_dyn_buf(&mov->mdat_buf)) < 0)
6448                     return ret;
6449             }
6450             pb = mov->mdat_buf;
6451         }
6452     }
6453 
6454     if (par->codec_id == AV_CODEC_ID_AMR_NB) {
6455         /* We must find out how many AMR blocks there are in one packet */
6456         static const uint16_t packed_size[16] =
6457             {13, 14, 16, 18, 20, 21, 27, 32, 6, 0, 0, 0, 0, 0, 0, 1};
6458         int len = 0;
6459 
6460         while (len < size && samples_in_chunk < 100) {
6461             len += packed_size[(pkt->data[len] >> 3) & 0x0F];
6462             samples_in_chunk++;
6463         }
6464         if (samples_in_chunk > 1) {
6465             av_log(s, AV_LOG_ERROR, "fatal error, input is not a single packet, implement a AVParser for it\n");
6466             return -1;
6467         }
6468     } else if (par->codec_id == AV_CODEC_ID_ADPCM_MS ||
6469                par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) {
6470         samples_in_chunk = trk->par->frame_size;
6471     } else if (trk->sample_size)
6472         samples_in_chunk = size / trk->sample_size;
6473     else
6474         samples_in_chunk = 1;
6475 
6476     if (samples_in_chunk < 1) {
6477         av_log(s, AV_LOG_ERROR, "fatal error, input packet contains no samples\n");
6478         return AVERROR_PATCHWELCOME;
6479     }
6480 
6481     /* copy extradata if it exists */
6482     if (trk->vos_len == 0 && par->extradata_size > 0 &&
6483         !TAG_IS_AVCI(trk->tag) &&
6484         (par->codec_id != AV_CODEC_ID_DNXHD)) {
6485         trk->vos_len  = par->extradata_size;
6486         trk->vos_data = av_malloc(trk->vos_len + AV_INPUT_BUFFER_PADDING_SIZE);
6487         if (!trk->vos_data) {
6488             ret = AVERROR(ENOMEM);
6489             goto err;
6490         }
6491         memcpy(trk->vos_data, par->extradata, trk->vos_len);
6492         memset(trk->vos_data + trk->vos_len, 0, AV_INPUT_BUFFER_PADDING_SIZE);
6493     }
6494 
6495     if ((par->codec_id == AV_CODEC_ID_DNXHD ||
6496          par->codec_id == AV_CODEC_ID_H264 ||
6497          par->codec_id == AV_CODEC_ID_HEVC ||
6498          par->codec_id == AV_CODEC_ID_TRUEHD) && !trk->vos_len &&
6499          !TAG_IS_AVCI(trk->tag)) {
6500         /* copy frame to create needed atoms */
6501         trk->vos_len  = size;
6502         trk->vos_data = av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
6503         if (!trk->vos_data) {
6504             ret = AVERROR(ENOMEM);
6505             goto err;
6506         }
6507         memcpy(trk->vos_data, pkt->data, size);
6508         memset(trk->vos_data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
6509     }
6510 
6511     if (par->codec_id == AV_CODEC_ID_AAC && pkt->size > 2 &&
6512         (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) {
6513         if (!s->streams[pkt->stream_index]->nb_frames) {
6514             av_log(s, AV_LOG_ERROR, "Malformed AAC bitstream detected: "
6515                    "use the audio bitstream filter 'aac_adtstoasc' to fix it "
6516                    "('-bsf:a aac_adtstoasc' option with ffmpeg)\n");
6517             return -1;
6518         }
6519         av_log(s, AV_LOG_WARNING, "aac bitstream error\n");
6520     }
6521     if (par->codec_id == AV_CODEC_ID_H264 && trk->vos_len > 0 && *(uint8_t *)trk->vos_data != 1 && !TAG_IS_AVCI(trk->tag)) {
6522         /* from x264 or from bytestream H.264 */
6523         /* NAL reformatting needed */
6524         if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams) {
6525             ret = ff_avc_parse_nal_units_buf(pkt->data, &reformatted_data,
6526                                              &size);
6527             if (ret < 0)
6528                 return ret;
6529             avio_write(pb, reformatted_data, size);
6530         } else {
6531             if (trk->cenc.aes_ctr) {
6532                 size = ff_mov_cenc_avc_parse_nal_units(&trk->cenc, pb, pkt->data, size);
6533                 if (size < 0) {
6534                     ret = size;
6535                     goto err;
6536                 }
6537             } else {
6538                 size = ff_avc_parse_nal_units(pb, pkt->data, pkt->size);
6539             }
6540         }
6541     } else if (par->codec_id == AV_CODEC_ID_HEVC && trk->vos_len > 6 &&
6542                (AV_RB24(trk->vos_data) == 1 || AV_RB32(trk->vos_data) == 1)) {
6543         /* extradata is Annex B, assume the bitstream is too and convert it */
6544         if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams) {
6545             ret = ff_hevc_annexb2mp4_buf(pkt->data, &reformatted_data,
6546                                          &size, 0, NULL);
6547             if (ret < 0)
6548                 return ret;
6549             avio_write(pb, reformatted_data, size);
6550         } else {
6551             if (trk->cenc.aes_ctr) {
6552                 size = ff_mov_cenc_avc_parse_nal_units(&trk->cenc, pb, pkt->data, size);
6553                 if (size < 0) {
6554                     ret = size;
6555                     goto err;
6556                 }
6557             } else {
6558                 size = ff_hevc_annexb2mp4(pb, pkt->data, pkt->size, 0, NULL);
6559             }
6560         }
6561     } else if (par->codec_id == AV_CODEC_ID_AV1) {
6562         if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams) {
6563             ret = ff_av1_filter_obus_buf(pkt->data, &reformatted_data,
6564                                          &size, &offset);
6565             if (ret < 0)
6566                 return ret;
6567             avio_write(pb, reformatted_data, size);
6568         } else {
6569             size = ff_av1_filter_obus(pb, pkt->data, pkt->size);
6570             if (trk->mode == MODE_AVIF && !mov->avif_extent_length[pkt->stream_index]) {
6571                 mov->avif_extent_length[pkt->stream_index] = size;
6572             }
6573         }
6574 
6575     } else if (par->codec_id == AV_CODEC_ID_AC3 ||
6576                par->codec_id == AV_CODEC_ID_EAC3) {
6577         size = handle_eac3(mov, pkt, trk);
6578         if (size < 0)
6579             return size;
6580         else if (!size)
6581             goto end;
6582         avio_write(pb, pkt->data, size);
6583     } else if (par->codec_id == AV_CODEC_ID_EIA_608) {
6584         size = 8;
6585 
6586         for (int i = 0; i < pkt->size; i += 3) {
6587             if (pkt->data[i] == 0xFC) {
6588                 size += 2;
6589             }
6590         }
6591         avio_wb32(pb, size);
6592         ffio_wfourcc(pb, "cdat");
6593         for (int i = 0; i < pkt->size; i += 3) {
6594             if (pkt->data[i] == 0xFC) {
6595                 avio_w8(pb, pkt->data[i + 1]);
6596                 avio_w8(pb, pkt->data[i + 2]);
6597             }
6598         }
6599     } else {
6600         if (trk->cenc.aes_ctr) {
6601             if (par->codec_id == AV_CODEC_ID_H264 && par->extradata_size > 4) {
6602                 int nal_size_length = (par->extradata[4] & 0x3) + 1;
6603                 ret = ff_mov_cenc_avc_write_nal_units(s, &trk->cenc, nal_size_length, pb, pkt->data, size);
6604             } else if(par->codec_id == AV_CODEC_ID_HEVC && par->extradata_size > 21) {
6605                 int nal_size_length = (par->extradata[21] & 0x3) + 1;
6606                 ret = ff_mov_cenc_avc_write_nal_units(s, &trk->cenc, nal_size_length, pb, pkt->data, size);
6607             } else {
6608                 ret = ff_mov_cenc_write_packet(&trk->cenc, pb, pkt->data, size);
6609             }
6610 
6611             if (ret) {
6612                 goto err;
6613             }
6614         } else {
6615             avio_write(pb, pkt->data, size);
6616         }
6617     }
6618 
6619     if (trk->entry >= trk->cluster_capacity) {
6620         unsigned new_capacity = trk->entry + MOV_INDEX_CLUSTER_SIZE;
6621         void *cluster = av_realloc_array(trk->cluster, new_capacity, sizeof(*trk->cluster));
6622         if (!cluster) {
6623             ret = AVERROR(ENOMEM);
6624             goto err;
6625         }
6626         trk->cluster          = cluster;
6627         trk->cluster_capacity = new_capacity;
6628     }
6629 
6630     trk->cluster[trk->entry].pos              = avio_tell(pb) - size;
6631     trk->cluster[trk->entry].samples_in_chunk = samples_in_chunk;
6632     trk->cluster[trk->entry].chunkNum         = 0;
6633     trk->cluster[trk->entry].size             = size;
6634     trk->cluster[trk->entry].entries          = samples_in_chunk;
6635     trk->cluster[trk->entry].dts              = pkt->dts;
6636     trk->cluster[trk->entry].pts              = pkt->pts;
6637     if (!trk->squash_fragment_samples_to_one &&
6638         !trk->entry && trk->start_dts != AV_NOPTS_VALUE) {
6639         if (!trk->frag_discont) {
6640             /* First packet of a new fragment. We already wrote the duration
6641              * of the last packet of the previous fragment based on track_duration,
6642              * which might not exactly match our dts. Therefore adjust the dts
6643              * of this packet to be what the previous packets duration implies. */
6644             trk->cluster[trk->entry].dts = trk->start_dts + trk->track_duration;
6645             /* We also may have written the pts and the corresponding duration
6646              * in sidx/tfrf/tfxd tags; make sure the sidx pts and duration match up with
6647              * the next fragment. This means the cts of the first sample must
6648              * be the same in all fragments, unless end_pts was updated by
6649              * the packet causing the fragment to be written. */
6650             if ((mov->flags & FF_MOV_FLAG_DASH &&
6651                 !(mov->flags & (FF_MOV_FLAG_GLOBAL_SIDX | FF_MOV_FLAG_SKIP_SIDX))) ||
6652                 mov->mode == MODE_ISM)
6653                 pkt->pts = pkt->dts + trk->end_pts - trk->cluster[trk->entry].dts;
6654         } else {
6655             /* New fragment, but discontinuous from previous fragments.
6656              * Pretend the duration sum of the earlier fragments is
6657              * pkt->dts - trk->start_dts. */
6658             trk->end_pts = AV_NOPTS_VALUE;
6659             trk->frag_discont = 0;
6660         }
6661     }
6662 
6663     if (!trk->entry && trk->start_dts == AV_NOPTS_VALUE && !mov->use_editlist &&
6664         s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO) {
6665         /* Not using edit lists and shifting the first track to start from zero.
6666          * If the other streams start from a later timestamp, we won't be able
6667          * to signal the difference in starting time without an edit list.
6668          * Thus move the timestamp for this first sample to 0, increasing
6669          * its duration instead. */
6670         trk->cluster[trk->entry].dts = trk->start_dts = 0;
6671     }
6672     if (trk->start_dts == AV_NOPTS_VALUE) {
6673         trk->start_dts = pkt->dts;
6674         if (trk->frag_discont) {
6675             if (mov->use_editlist) {
6676                 /* Pretend the whole stream started at pts=0, with earlier fragments
6677                  * already written. If the stream started at pts=0, the duration sum
6678                  * of earlier fragments would have been pkt->pts. */
6679                 trk->start_dts  = pkt->dts - pkt->pts;
6680             } else {
6681                 /* Pretend the whole stream started at dts=0, with earlier fragments
6682                  * already written, with a duration summing up to pkt->dts. */
6683                 trk->start_dts  = 0;
6684             }
6685             trk->frag_discont = 0;
6686         } else if (pkt->dts && mov->moov_written)
6687             av_log(s, AV_LOG_WARNING,
6688                    "Track %d starts with a nonzero dts %"PRId64", while the moov "
6689                    "already has been written. Set the delay_moov flag to handle "
6690                    "this case.\n",
6691                    pkt->stream_index, pkt->dts);
6692     }
6693     trk->track_duration = pkt->dts - trk->start_dts + pkt->duration;
6694     trk->last_sample_is_subtitle_end = 0;
6695 
6696     if (pkt->pts == AV_NOPTS_VALUE) {
6697         av_log(s, AV_LOG_WARNING, "pts has no value\n");
6698         pkt->pts = pkt->dts;
6699     }
6700     if (pkt->dts != pkt->pts)
6701         trk->flags |= MOV_TRACK_CTTS;
6702     trk->cluster[trk->entry].cts   = pkt->pts - pkt->dts;
6703     trk->cluster[trk->entry].flags = 0;
6704     if (trk->start_cts == AV_NOPTS_VALUE)
6705         trk->start_cts = pkt->pts - pkt->dts;
6706     if (trk->end_pts == AV_NOPTS_VALUE)
6707         trk->end_pts = trk->cluster[trk->entry].dts +
6708                        trk->cluster[trk->entry].cts + pkt->duration;
6709     else
6710         trk->end_pts = FFMAX(trk->end_pts, trk->cluster[trk->entry].dts +
6711                                            trk->cluster[trk->entry].cts +
6712                                            pkt->duration);
6713 
6714     if (par->codec_id == AV_CODEC_ID_VC1) {
6715         mov_parse_vc1_frame(pkt, trk);
6716     } else if (par->codec_id == AV_CODEC_ID_TRUEHD) {
6717         mov_parse_truehd_frame(pkt, trk);
6718     } else if (pkt->flags & AV_PKT_FLAG_KEY) {
6719         if (mov->mode == MODE_MOV && par->codec_id == AV_CODEC_ID_MPEG2VIDEO &&
6720             trk->entry > 0) { // force sync sample for the first key frame
6721             mov_parse_mpeg2_frame(pkt, &trk->cluster[trk->entry].flags);
6722             if (trk->cluster[trk->entry].flags & MOV_PARTIAL_SYNC_SAMPLE)
6723                 trk->flags |= MOV_TRACK_STPS;
6724         } else {
6725             trk->cluster[trk->entry].flags = MOV_SYNC_SAMPLE;
6726         }
6727         if (trk->cluster[trk->entry].flags & MOV_SYNC_SAMPLE)
6728             trk->has_keyframes++;
6729     }
6730     if (pkt->flags & AV_PKT_FLAG_DISPOSABLE) {
6731         trk->cluster[trk->entry].flags |= MOV_DISPOSABLE_SAMPLE;
6732         trk->has_disposable++;
6733     }
6734 
6735 #ifdef OHOS_SDTP_BOX_EXT
6736     if (pkt->flags & AV_PKT_FLAG_DISPOSABLE_EXT) {
6737         trk->cluster[trk->entry].flags |= MOV_DISPOSABLE_EXT_SAMPLE;
6738         trk->has_disposable++;
6739     }
6740 #endif
6741 
6742     prft = (AVProducerReferenceTime *)av_packet_get_side_data(pkt, AV_PKT_DATA_PRFT, &prft_size);
6743     if (prft && prft_size == sizeof(AVProducerReferenceTime))
6744         memcpy(&trk->cluster[trk->entry].prft, prft, prft_size);
6745     else
6746         memset(&trk->cluster[trk->entry].prft, 0, sizeof(AVProducerReferenceTime));
6747 
6748     trk->entry++;
6749     trk->sample_count += samples_in_chunk;
6750     mov->mdat_size    += size;
6751 
6752     if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams)
6753         ff_mov_add_hinted_packet(s, pkt, trk->hint_track, trk->entry,
6754                                  reformatted_data ? reformatted_data + offset
6755                                                   : NULL, size);
6756 
6757 end:
6758 err:
6759 
6760     if (pkt->data != reformatted_data)
6761         av_free(reformatted_data);
6762     return ret;
6763 }
6764 
6765 static int mov_write_single_packet(AVFormatContext *s, AVPacket *pkt)
6766 {
6767     MOVMuxContext *mov = s->priv_data;
6768     MOVTrack *trk = &mov->tracks[pkt->stream_index];
6769     AVCodecParameters *par = trk->par;
6770     int64_t frag_duration = 0;
6771     int size = pkt->size;
6772 
6773     int ret = check_pkt(s, pkt);
6774     if (ret < 0)
6775         return ret;
6776 
6777     if (mov->flags & FF_MOV_FLAG_FRAG_DISCONT) {
6778         int i;
6779         for (i = 0; i < s->nb_streams; i++)
6780             mov->tracks[i].frag_discont = 1;
6781         mov->flags &= ~FF_MOV_FLAG_FRAG_DISCONT;
6782     }
6783 
6784     if (mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS) {
6785         if (trk->dts_shift == AV_NOPTS_VALUE)
6786             trk->dts_shift = pkt->pts - pkt->dts;
6787         pkt->dts += trk->dts_shift;
6788     }
6789 
6790     if (trk->par->codec_id == AV_CODEC_ID_MP4ALS ||
6791             trk->par->codec_id == AV_CODEC_ID_AAC ||
6792             trk->par->codec_id == AV_CODEC_ID_AV1 ||
6793             trk->par->codec_id == AV_CODEC_ID_FLAC) {
6794         size_t side_size;
6795         uint8_t *side = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size);
6796         if (side && side_size > 0 && (side_size != par->extradata_size || memcmp(side, par->extradata, side_size))) {
6797             void *newextra = av_mallocz(side_size + AV_INPUT_BUFFER_PADDING_SIZE);
6798             if (!newextra)
6799                 return AVERROR(ENOMEM);
6800             av_free(par->extradata);
6801             par->extradata = newextra;
6802             memcpy(par->extradata, side, side_size);
6803             par->extradata_size = side_size;
6804             if (!pkt->size) // Flush packet
6805                 mov->need_rewrite_extradata = 1;
6806         }
6807     }
6808 
6809     if (!pkt->size) {
6810         if (trk->start_dts == AV_NOPTS_VALUE && trk->frag_discont) {
6811             trk->start_dts = pkt->dts;
6812             if (pkt->pts != AV_NOPTS_VALUE)
6813                 trk->start_cts = pkt->pts - pkt->dts;
6814             else
6815                 trk->start_cts = 0;
6816         }
6817 
6818         return 0;             /* Discard 0 sized packets */
6819     }
6820 
6821     if (trk->entry && pkt->stream_index < s->nb_streams)
6822         frag_duration = av_rescale_q(pkt->dts - trk->cluster[0].dts,
6823                 s->streams[pkt->stream_index]->time_base,
6824                 AV_TIME_BASE_Q);
6825     if ((mov->max_fragment_duration &&
6826                 frag_duration >= mov->max_fragment_duration) ||
6827             (mov->max_fragment_size && mov->mdat_size + size >= mov->max_fragment_size) ||
6828             (mov->flags & FF_MOV_FLAG_FRAG_KEYFRAME &&
6829              par->codec_type == AVMEDIA_TYPE_VIDEO &&
6830              trk->entry && pkt->flags & AV_PKT_FLAG_KEY) ||
6831             (mov->flags & FF_MOV_FLAG_FRAG_EVERY_FRAME)) {
6832         if (frag_duration >= mov->min_fragment_duration) {
6833             if (trk->entry) {
6834                 // Set the duration of this track to line up with the next
6835                 // sample in this track. This avoids relying on AVPacket
6836                 // duration, but only helps for this particular track, not
6837                 // for the other ones that are flushed at the same time.
6838                 //
6839                 // If we have trk->entry == 0, no fragment will be written
6840                 // for this track, and we can't adjust the track end here.
6841                 trk->track_duration = pkt->dts - trk->start_dts;
6842                 if (pkt->pts != AV_NOPTS_VALUE)
6843                     trk->end_pts = pkt->pts;
6844                 else
6845                     trk->end_pts = pkt->dts;
6846                 trk->end_reliable = 1;
6847             }
6848             mov_auto_flush_fragment(s, 0);
6849         }
6850     }
6851 
6852     return ff_mov_write_packet(s, pkt);
6853 }
6854 
6855 static int mov_write_subtitle_end_packet(AVFormatContext *s,
6856                                          int stream_index,
6857                                          int64_t dts) {
6858     MOVMuxContext *mov = s->priv_data;
6859     AVPacket *end = mov->pkt;
6860     uint8_t data[2] = {0};
6861     int ret;
6862 
6863     end->size = sizeof(data);
6864     end->data = data;
6865     end->pts = dts;
6866     end->dts = dts;
6867     end->duration = 0;
6868     end->stream_index = stream_index;
6869 
6870     ret = mov_write_single_packet(s, end);
6871     av_packet_unref(end);
6872 
6873     return ret;
6874 }
6875 
6876 static int mov_write_packet(AVFormatContext *s, AVPacket *pkt)
6877 {
6878     MOVMuxContext *mov = s->priv_data;
6879     MOVTrack *trk;
6880 
6881     if (!pkt) {
6882         mov_flush_fragment(s, 1);
6883         return 1;
6884     }
6885 
6886     trk = &mov->tracks[pkt->stream_index];
6887 
6888     if (is_cover_image(trk->st)) {
6889         int ret;
6890 
6891         if (trk->st->nb_frames >= 1) {
6892             if (trk->st->nb_frames == 1)
6893                 av_log(s, AV_LOG_WARNING, "Got more than one picture in stream %d,"
6894                        " ignoring.\n", pkt->stream_index);
6895             return 0;
6896         }
6897 
6898         if ((ret = av_packet_ref(trk->cover_image, pkt)) < 0)
6899             return ret;
6900 
6901         return 0;
6902     } else {
6903         int i;
6904 
6905         if (!pkt->size)
6906             return mov_write_single_packet(s, pkt); /* Passthrough. */
6907 
6908         /*
6909          * Subtitles require special handling.
6910          *
6911          * 1) For full complaince, every track must have a sample at
6912          * dts == 0, which is rarely true for subtitles. So, as soon
6913          * as we see any packet with dts > 0, write an empty subtitle
6914          * at dts == 0 for any subtitle track with no samples in it.
6915          *
6916          * 2) For each subtitle track, check if the current packet's
6917          * dts is past the duration of the last subtitle sample. If
6918          * so, we now need to write an end sample for that subtitle.
6919          *
6920          * This must be done conditionally to allow for subtitles that
6921          * immediately replace each other, in which case an end sample
6922          * is not needed, and is, in fact, actively harmful.
6923          *
6924          * 3) See mov_write_trailer for how the final end sample is
6925          * handled.
6926          */
6927         for (i = 0; i < mov->nb_streams; i++) {
6928             MOVTrack *trk = &mov->tracks[i];
6929             int ret;
6930 
6931             if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT &&
6932                 trk->track_duration < pkt->dts &&
6933                 (trk->entry == 0 || !trk->last_sample_is_subtitle_end)) {
6934                 ret = mov_write_subtitle_end_packet(s, i, trk->track_duration);
6935                 if (ret < 0) return ret;
6936                 trk->last_sample_is_subtitle_end = 1;
6937             }
6938         }
6939 
6940         if (trk->squash_fragment_samples_to_one) {
6941             /*
6942              * If the track has to have its samples squashed into one sample,
6943              * we just take it into the track's queue.
6944              * This will then be utilized as the samples get written in either
6945              * mov_flush_fragment or when the mux is finalized in
6946              * mov_write_trailer.
6947              */
6948             int ret = AVERROR_BUG;
6949 
6950             if (pkt->pts == AV_NOPTS_VALUE) {
6951                 av_log(s, AV_LOG_ERROR,
6952                        "Packets without a valid presentation timestamp are "
6953                        "not supported with packet squashing!\n");
6954                 return AVERROR(EINVAL);
6955             }
6956 
6957             /* The following will reset pkt and is only allowed to be used
6958              * because we return immediately. afterwards. */
6959             if ((ret = avpriv_packet_list_put(&trk->squashed_packet_queue,
6960                                               pkt, NULL, 0)) < 0) {
6961                 return ret;
6962             }
6963 
6964             return 0;
6965         }
6966 
6967 
6968         if (trk->mode == MODE_MOV && trk->par->codec_type == AVMEDIA_TYPE_VIDEO) {
6969             AVPacket *opkt = pkt;
6970             int reshuffle_ret, ret;
6971             if (trk->is_unaligned_qt_rgb) {
6972                 int64_t bpc = trk->par->bits_per_coded_sample != 15 ? trk->par->bits_per_coded_sample : 16;
6973                 int expected_stride = ((trk->par->width * bpc + 15) >> 4)*2;
6974                 reshuffle_ret = ff_reshuffle_raw_rgb(s, &pkt, trk->par, expected_stride);
6975                 if (reshuffle_ret < 0)
6976                     return reshuffle_ret;
6977             } else
6978                 reshuffle_ret = 0;
6979             if (trk->par->format == AV_PIX_FMT_PAL8 && !trk->pal_done) {
6980                 ret = ff_get_packet_palette(s, opkt, reshuffle_ret, trk->palette);
6981                 if (ret < 0)
6982                     goto fail;
6983                 if (ret)
6984                     trk->pal_done++;
6985             } else if (trk->par->codec_id == AV_CODEC_ID_RAWVIDEO &&
6986                        (trk->par->format == AV_PIX_FMT_GRAY8 ||
6987                        trk->par->format == AV_PIX_FMT_MONOBLACK)) {
6988                 ret = av_packet_make_writable(pkt);
6989                 if (ret < 0)
6990                     goto fail;
6991                 for (i = 0; i < pkt->size; i++)
6992                     pkt->data[i] = ~pkt->data[i];
6993             }
6994             if (reshuffle_ret) {
6995                 ret = mov_write_single_packet(s, pkt);
6996 fail:
6997                 if (reshuffle_ret)
6998                     av_packet_free(&pkt);
6999                 return ret;
7000             }
7001         }
7002 
7003         return mov_write_single_packet(s, pkt);
7004     }
7005 }
7006 
7007 // QuickTime chapters involve an additional text track with the chapter names
7008 // as samples, and a tref pointing from the other tracks to the chapter one.
7009 static int mov_create_chapter_track(AVFormatContext *s, int tracknum)
7010 {
7011     static const uint8_t stub_header[] = {
7012         // TextSampleEntry
7013         0x00, 0x00, 0x00, 0x01, // displayFlags
7014         0x00, 0x00,             // horizontal + vertical justification
7015         0x00, 0x00, 0x00, 0x00, // bgColourRed/Green/Blue/Alpha
7016         // BoxRecord
7017         0x00, 0x00, 0x00, 0x00, // defTextBoxTop/Left
7018         0x00, 0x00, 0x00, 0x00, // defTextBoxBottom/Right
7019         // StyleRecord
7020         0x00, 0x00, 0x00, 0x00, // startChar + endChar
7021         0x00, 0x01,             // fontID
7022         0x00, 0x00,             // fontStyleFlags + fontSize
7023         0x00, 0x00, 0x00, 0x00, // fgColourRed/Green/Blue/Alpha
7024         // FontTableBox
7025         0x00, 0x00, 0x00, 0x0D, // box size
7026         'f', 't', 'a', 'b',     // box atom name
7027         0x00, 0x01,             // entry count
7028         // FontRecord
7029         0x00, 0x01,             // font ID
7030         0x00,                   // font name length
7031     };
7032     MOVMuxContext *mov = s->priv_data;
7033     MOVTrack *track = &mov->tracks[tracknum];
7034     AVPacket *pkt = mov->pkt;
7035     int i, len;
7036     int ret;
7037 
7038     track->mode = mov->mode;
7039     track->tag = MKTAG('t','e','x','t');
7040     track->timescale = mov->movie_timescale;
7041     track->par = avcodec_parameters_alloc();
7042     if (!track->par)
7043         return AVERROR(ENOMEM);
7044     track->par->codec_type = AVMEDIA_TYPE_SUBTITLE;
7045     ret = ff_alloc_extradata(track->par, sizeof(stub_header));
7046     if (ret < 0)
7047         return ret;
7048     memcpy(track->par->extradata, stub_header, sizeof(stub_header));
7049 
7050     pkt->stream_index = tracknum;
7051     pkt->flags = AV_PKT_FLAG_KEY;
7052 
7053     for (i = 0; i < s->nb_chapters; i++) {
7054         AVChapter *c = s->chapters[i];
7055         AVDictionaryEntry *t;
7056 
7057         int64_t end = av_rescale_q(c->end, c->time_base, (AVRational){1,mov->movie_timescale});
7058         pkt->pts = pkt->dts = av_rescale_q(c->start, c->time_base, (AVRational){1,mov->movie_timescale});
7059         pkt->duration = end - pkt->dts;
7060 
7061         if ((t = av_dict_get(c->metadata, "title", NULL, 0))) {
7062             static const char encd[12] = {
7063                 0x00, 0x00, 0x00, 0x0C,
7064                 'e',  'n',  'c',  'd',
7065                 0x00, 0x00, 0x01, 0x00 };
7066             len      = strlen(t->value);
7067             pkt->size = len + 2 + 12;
7068             pkt->data = av_malloc(pkt->size);
7069             if (!pkt->data) {
7070                 av_packet_unref(pkt);
7071                 return AVERROR(ENOMEM);
7072             }
7073             AV_WB16(pkt->data, len);
7074             memcpy(pkt->data + 2, t->value, len);
7075             memcpy(pkt->data + len + 2, encd, sizeof(encd));
7076             ff_mov_write_packet(s, pkt);
7077             av_freep(&pkt->data);
7078         }
7079     }
7080 
7081     av_packet_unref(mov->pkt);
7082 
7083     return 0;
7084 }
7085 
7086 
7087 static int mov_check_timecode_track(AVFormatContext *s, AVTimecode *tc, int src_index, const char *tcstr)
7088 {
7089     int ret;
7090 
7091     /* compute the frame number */
7092     ret = av_timecode_init_from_string(tc, s->streams[src_index]->avg_frame_rate, tcstr, s);
7093     return ret;
7094 }
7095 
7096 static int mov_create_timecode_track(AVFormatContext *s, int index, int src_index, AVTimecode tc)
7097 {
7098     MOVMuxContext *mov  = s->priv_data;
7099     MOVTrack *track     = &mov->tracks[index];
7100     AVStream *src_st    = s->streams[src_index];
7101     uint8_t data[4];
7102     AVPacket *pkt = mov->pkt;
7103     AVRational rate = src_st->avg_frame_rate;
7104     int ret;
7105 
7106     /* tmcd track based on video stream */
7107     track->mode      = mov->mode;
7108     track->tag       = MKTAG('t','m','c','d');
7109     track->src_track = src_index;
7110     track->timescale = mov->tracks[src_index].timescale;
7111     if (tc.flags & AV_TIMECODE_FLAG_DROPFRAME)
7112         track->timecode_flags |= MOV_TIMECODE_FLAG_DROPFRAME;
7113 
7114     /* set st to src_st for metadata access*/
7115     track->st = src_st;
7116 
7117     /* encode context: tmcd data stream */
7118     track->par = avcodec_parameters_alloc();
7119     if (!track->par)
7120         return AVERROR(ENOMEM);
7121     track->par->codec_type = AVMEDIA_TYPE_DATA;
7122     track->par->codec_tag  = track->tag;
7123     track->st->avg_frame_rate = rate;
7124 
7125     /* the tmcd track just contains one packet with the frame number */
7126     pkt->data = data;
7127     pkt->stream_index = index;
7128     pkt->flags = AV_PKT_FLAG_KEY;
7129     pkt->pts = pkt->dts = av_rescale_q(tc.start, av_inv_q(rate), (AVRational){1,mov->movie_timescale});
7130     pkt->size = 4;
7131     AV_WB32(pkt->data, tc.start);
7132     ret = ff_mov_write_packet(s, pkt);
7133     av_packet_unref(pkt);
7134     return ret;
7135 }
7136 
7137 #ifdef OHOS_TIMED_META_TRACK
7138 static int mov_create_timed_metadata_track(AVFormatContext *s, int index, int src_index)
7139 {
7140     MOVMuxContext *mov  = s->priv_data;
7141     MOVTrack *track     = &mov->tracks[index];
7142     AVStream *src_st    = s->streams[src_index];
7143     AVRational rate = src_st->avg_frame_rate;
7144     int ret;
7145     int track_tag = MKTAG('c','d','s','c');
7146 
7147     /* timed metadata track based on video stream */
7148     track->mode      = mov->mode;
7149     /* if the timed metadata track describes characteristics of the whole movie,
7150      * there should be no track reference of type 'cdsc'.
7151      */
7152     if (src_index >= 0) {
7153         MOVTrack *src_track     = &mov->tracks[src_index];
7154         track->tag       = track_tag;
7155         track->tref_tag  = track_tag;
7156         track->src_track = src_index;
7157         track->timescale = mov->tracks[src_index].timescale;
7158         int new_track_count = track->ref_track_count + 1;
7159         ret = av_reallocp_array(&track->tref_ids, new_track_count, sizeof(track->tref_ids));
7160         if (ret < 0)
7161             return ret;
7162         track->ref_track_count = new_track_count;
7163         track->tref_ids[track->ref_track_count - 1] = src_track->track_id;
7164     }
7165 
7166     /* set st to src_st for metadata access*/
7167     track->st = s->streams[index];
7168 
7169     track->par = avcodec_parameters_alloc();
7170     if (!track->par)
7171         return AVERROR(ENOMEM);
7172     track->par->codec_type = AVMEDIA_TYPE_TIMEDMETA;
7173     track->par->codec_id = AV_CODEC_ID_FFMETADATA;
7174     track->par->codec_tag  = track_tag;
7175     track->st->avg_frame_rate = av_inv_q(rate);
7176     return 0;
7177 }
7178 #endif
7179 
7180 /*
7181  * st->disposition controls the "enabled" flag in the tkhd tag.
7182  * QuickTime will not play a track if it is not enabled.  So make sure
7183  * that one track of each type (audio, video, subtitle) is enabled.
7184  *
7185  * Subtitles are special.  For audio and video, setting "enabled" also
7186  * makes the track "default" (i.e. it is rendered when played). For
7187  * subtitles, an "enabled" subtitle is not rendered by default, but
7188  * if no subtitle is enabled, the subtitle menu in QuickTime will be
7189  * empty!
7190  */
7191 static void enable_tracks(AVFormatContext *s)
7192 {
7193     MOVMuxContext *mov = s->priv_data;
7194     int i;
7195     int enabled[AVMEDIA_TYPE_NB];
7196     int first[AVMEDIA_TYPE_NB];
7197 
7198     for (i = 0; i < AVMEDIA_TYPE_NB; i++) {
7199         enabled[i] = 0;
7200         first[i] = -1;
7201     }
7202 
7203     for (i = 0; i < s->nb_streams; i++) {
7204         AVStream *st = s->streams[i];
7205 
7206         if (st->codecpar->codec_type <= AVMEDIA_TYPE_UNKNOWN ||
7207             st->codecpar->codec_type >= AVMEDIA_TYPE_NB ||
7208             is_cover_image(st))
7209             continue;
7210 
7211         if (first[st->codecpar->codec_type] < 0)
7212             first[st->codecpar->codec_type] = i;
7213         if (st->disposition & AV_DISPOSITION_DEFAULT) {
7214             mov->tracks[i].flags |= MOV_TRACK_ENABLED;
7215             enabled[st->codecpar->codec_type]++;
7216         }
7217     }
7218 
7219     for (i = 0; i < AVMEDIA_TYPE_NB; i++) {
7220         switch (i) {
7221         case AVMEDIA_TYPE_VIDEO:
7222         case AVMEDIA_TYPE_AUDIO:
7223         case AVMEDIA_TYPE_SUBTITLE:
7224             if (enabled[i] > 1)
7225                 mov->per_stream_grouping = 1;
7226             if (!enabled[i] && first[i] >= 0)
7227                 mov->tracks[first[i]].flags |= MOV_TRACK_ENABLED;
7228             break;
7229         }
7230     }
7231 }
7232 
7233 static void mov_free(AVFormatContext *s)
7234 {
7235     MOVMuxContext *mov = s->priv_data;
7236     int i;
7237 
7238     if (!mov->tracks)
7239         return;
7240 
7241     if (mov->chapter_track) {
7242         avcodec_parameters_free(&mov->tracks[mov->chapter_track].par);
7243     }
7244 
7245     for (i = 0; i < mov->nb_streams; i++) {
7246         MOVTrack *const track = &mov->tracks[i];
7247 
7248         if (track->tag == MKTAG('r','t','p',' '))
7249             ff_mov_close_hinting(track);
7250         else if (track->tag == MKTAG('t','m','c','d') && mov->nb_meta_tmcd)
7251             av_freep(&track->par);
7252         av_freep(&track->cluster);
7253         av_freep(&track->frag_info);
7254         av_packet_free(&track->cover_image);
7255 
7256         if (track->eac3_priv) {
7257             struct eac3_info *info = track->eac3_priv;
7258             av_packet_free(&info->pkt);
7259             av_freep(&track->eac3_priv);
7260         }
7261         if (track->vos_len)
7262             av_freep(&track->vos_data);
7263 
7264         ff_mov_cenc_free(&track->cenc);
7265         ffio_free_dyn_buf(&track->mdat_buf);
7266 
7267         avpriv_packet_list_free(&track->squashed_packet_queue);
7268 #ifdef OHOS_TIMED_META_TRACK
7269         av_freep(&track->tref_ids);
7270 #endif
7271     }
7272 
7273     av_freep(&mov->tracks);
7274     ffio_free_dyn_buf(&mov->mdat_buf);
7275 }
7276 
7277 static uint32_t rgb_to_yuv(uint32_t rgb)
7278 {
7279     uint8_t r, g, b;
7280     int y, cb, cr;
7281 
7282     r = (rgb >> 16) & 0xFF;
7283     g = (rgb >>  8) & 0xFF;
7284     b = (rgb      ) & 0xFF;
7285 
7286     y  = av_clip_uint8(( 16000 +  257 * r + 504 * g +  98 * b)/1000);
7287     cb = av_clip_uint8((128000 -  148 * r - 291 * g + 439 * b)/1000);
7288     cr = av_clip_uint8((128000 +  439 * r - 368 * g -  71 * b)/1000);
7289 
7290     return (y << 16) | (cr << 8) | cb;
7291 }
7292 
7293 static int mov_create_dvd_sub_decoder_specific_info(MOVTrack *track,
7294                                                     AVStream *st)
7295 {
7296     int i, width = 720, height = 480;
7297     int have_palette = 0, have_size = 0;
7298     uint32_t palette[16];
7299     char *cur = st->codecpar->extradata;
7300 
7301     while (cur && *cur) {
7302         if (strncmp("palette:", cur, 8) == 0) {
7303             int i, count;
7304             count = sscanf(cur + 8,
7305                 "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32", "
7306                 "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32", "
7307                 "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32", "
7308                 "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32"",
7309                 &palette[ 0], &palette[ 1], &palette[ 2], &palette[ 3],
7310                 &palette[ 4], &palette[ 5], &palette[ 6], &palette[ 7],
7311                 &palette[ 8], &palette[ 9], &palette[10], &palette[11],
7312                 &palette[12], &palette[13], &palette[14], &palette[15]);
7313 
7314             for (i = 0; i < count; i++) {
7315                 palette[i] = rgb_to_yuv(palette[i]);
7316             }
7317             have_palette = 1;
7318         } else if (!strncmp("size:", cur, 5)) {
7319             sscanf(cur + 5, "%dx%d", &width, &height);
7320             have_size = 1;
7321         }
7322         if (have_palette && have_size)
7323             break;
7324         cur += strcspn(cur, "\n\r");
7325         cur += strspn(cur, "\n\r");
7326     }
7327     if (have_palette) {
7328         track->vos_data = av_malloc(16*4 + AV_INPUT_BUFFER_PADDING_SIZE);
7329         if (!track->vos_data)
7330             return AVERROR(ENOMEM);
7331         for (i = 0; i < 16; i++) {
7332             AV_WB32(track->vos_data + i * 4, palette[i]);
7333         }
7334         memset(track->vos_data + 16*4, 0, AV_INPUT_BUFFER_PADDING_SIZE);
7335         track->vos_len = 16 * 4;
7336     }
7337     st->codecpar->width = width;
7338     st->codecpar->height = track->height = height;
7339 
7340     return 0;
7341 }
7342 
7343 static int mov_init(AVFormatContext *s)
7344 {
7345     MOVMuxContext *mov = s->priv_data;
7346     int i, ret;
7347 
7348     mov->fc = s;
7349     mov->pkt = ffformatcontext(s)->pkt;
7350 
7351     /* Default mode == MP4 */
7352     mov->mode = MODE_MP4;
7353 
7354 #define IS_MODE(muxer, config) (CONFIG_ ## config ## _MUXER && !strcmp(#muxer, s->oformat->name))
7355     if      (IS_MODE(3gp,   TGP)) mov->mode = MODE_3GP;
7356     else if (IS_MODE(3g2,   TG2)) mov->mode = MODE_3GP|MODE_3G2;
7357     else if (IS_MODE(mov,   MOV)) mov->mode = MODE_MOV;
7358     else if (IS_MODE(psp,   PSP)) mov->mode = MODE_PSP;
7359     else if (IS_MODE(ipod, IPOD)) mov->mode = MODE_IPOD;
7360     else if (IS_MODE(ismv, ISMV)) mov->mode = MODE_ISM;
7361     else if (IS_MODE(f4v,   F4V)) mov->mode = MODE_F4V;
7362     else if (IS_MODE(avif, AVIF)) mov->mode = MODE_AVIF;
7363 #undef IS_MODE
7364 
7365     if (mov->flags & FF_MOV_FLAG_DELAY_MOOV)
7366         mov->flags |= FF_MOV_FLAG_EMPTY_MOOV;
7367 
7368     if (mov->mode == MODE_AVIF)
7369         mov->flags |= FF_MOV_FLAG_DELAY_MOOV;
7370 
7371     /* Set the FRAGMENT flag if any of the fragmentation methods are
7372      * enabled. */
7373     if (mov->max_fragment_duration || mov->max_fragment_size ||
7374         mov->flags & (FF_MOV_FLAG_EMPTY_MOOV |
7375                       FF_MOV_FLAG_FRAG_KEYFRAME |
7376                       FF_MOV_FLAG_FRAG_CUSTOM |
7377                       FF_MOV_FLAG_FRAG_EVERY_FRAME))
7378         mov->flags |= FF_MOV_FLAG_FRAGMENT;
7379 
7380     /* Set other implicit flags immediately */
7381     if (mov->mode == MODE_ISM)
7382         mov->flags |= FF_MOV_FLAG_EMPTY_MOOV | FF_MOV_FLAG_SEPARATE_MOOF |
7383                       FF_MOV_FLAG_FRAGMENT | FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS;
7384     if (mov->flags & FF_MOV_FLAG_DASH)
7385         mov->flags |= FF_MOV_FLAG_FRAGMENT | FF_MOV_FLAG_EMPTY_MOOV |
7386                       FF_MOV_FLAG_DEFAULT_BASE_MOOF;
7387     if (mov->flags & FF_MOV_FLAG_CMAF)
7388         mov->flags |= FF_MOV_FLAG_FRAGMENT | FF_MOV_FLAG_EMPTY_MOOV |
7389                       FF_MOV_FLAG_DEFAULT_BASE_MOOF | FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS;
7390 
7391     if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV && s->flags & AVFMT_FLAG_AUTO_BSF) {
7392         av_log(s, AV_LOG_VERBOSE, "Empty MOOV enabled; disabling automatic bitstream filtering\n");
7393         s->flags &= ~AVFMT_FLAG_AUTO_BSF;
7394     }
7395 
7396     if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX && mov->flags & FF_MOV_FLAG_SKIP_SIDX) {
7397         av_log(s, AV_LOG_WARNING, "Global SIDX enabled; Ignoring skip_sidx option\n");
7398         mov->flags &= ~FF_MOV_FLAG_SKIP_SIDX;
7399     }
7400 
7401     if (mov->flags & FF_MOV_FLAG_FASTSTART) {
7402         mov->reserved_moov_size = -1;
7403     }
7404 
7405     if (mov->use_editlist < 0) {
7406         mov->use_editlist = 1;
7407         if (mov->flags & FF_MOV_FLAG_FRAGMENT &&
7408             !(mov->flags & FF_MOV_FLAG_DELAY_MOOV)) {
7409             // If we can avoid needing an edit list by shifting the
7410             // tracks, prefer that over (trying to) write edit lists
7411             // in fragmented output.
7412             if (s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO ||
7413                 s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO)
7414                 mov->use_editlist = 0;
7415         }
7416         if (mov->flags & FF_MOV_FLAG_CMAF) {
7417             // CMAF Track requires negative cts offsets without edit lists
7418             mov->use_editlist = 0;
7419         }
7420     }
7421     if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV &&
7422         !(mov->flags & FF_MOV_FLAG_DELAY_MOOV) && mov->use_editlist)
7423         av_log(s, AV_LOG_WARNING, "No meaningful edit list will be written when using empty_moov without delay_moov\n");
7424 
7425     if (mov->flags & FF_MOV_FLAG_CMAF && mov->use_editlist) {
7426         av_log(s, AV_LOG_WARNING, "Edit list enabled; Assuming writing CMAF Track File\n");
7427         mov->flags &= ~FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS;
7428     }
7429     if (!mov->use_editlist && s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO &&
7430         !(mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS))
7431         s->avoid_negative_ts = AVFMT_AVOID_NEG_TS_MAKE_ZERO;
7432 
7433     /* Clear the omit_tfhd_offset flag if default_base_moof is set;
7434      * if the latter is set that's enough and omit_tfhd_offset doesn't
7435      * add anything extra on top of that. */
7436     if (mov->flags & FF_MOV_FLAG_OMIT_TFHD_OFFSET &&
7437         mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF)
7438         mov->flags &= ~FF_MOV_FLAG_OMIT_TFHD_OFFSET;
7439 
7440     if (mov->frag_interleave &&
7441         mov->flags & (FF_MOV_FLAG_OMIT_TFHD_OFFSET | FF_MOV_FLAG_SEPARATE_MOOF)) {
7442         av_log(s, AV_LOG_ERROR,
7443                "Sample interleaving in fragments is mutually exclusive with "
7444                "omit_tfhd_offset and separate_moof\n");
7445         return AVERROR(EINVAL);
7446     }
7447 
7448     /* Non-seekable output is ok if using fragmentation. If ism_lookahead
7449      * is enabled, we don't support non-seekable output at all. */
7450     if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL) &&
7451         (!(mov->flags & FF_MOV_FLAG_FRAGMENT) || mov->ism_lookahead ||
7452          mov->mode == MODE_AVIF)) {
7453         av_log(s, AV_LOG_ERROR, "muxer does not support non seekable output\n");
7454         return AVERROR(EINVAL);
7455     }
7456 
7457     /* AVIF output must have at most two video streams (one for YUV and one for
7458      * alpha). */
7459     if (mov->mode == MODE_AVIF) {
7460         if (s->nb_streams > 2) {
7461             av_log(s, AV_LOG_ERROR, "AVIF output requires exactly one or two streams\n");
7462             return AVERROR(EINVAL);
7463         }
7464         if (s->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO &&
7465             (s->nb_streams > 1 && s->streams[1]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO)) {
7466             av_log(s, AV_LOG_ERROR, "AVIF output supports only video streams\n");
7467             return AVERROR(EINVAL);
7468         }
7469         if (s->nb_streams > 1) {
7470             const AVPixFmtDescriptor *pixdesc =
7471                 av_pix_fmt_desc_get(s->streams[1]->codecpar->format);
7472             if (pixdesc->nb_components != 1) {
7473                 av_log(s, AV_LOG_ERROR, "Second stream for AVIF (alpha) output must have exactly one plane\n");
7474                 return AVERROR(EINVAL);
7475             }
7476         }
7477         s->streams[0]->disposition |= AV_DISPOSITION_DEFAULT;
7478     }
7479 
7480     mov->nb_streams = s->nb_streams;
7481     if (mov->mode & (MODE_MP4|MODE_MOV|MODE_IPOD) && s->nb_chapters)
7482         mov->chapter_track = mov->nb_streams++;
7483 
7484     if (mov->flags & FF_MOV_FLAG_RTP_HINT) {
7485         for (i = 0; i < s->nb_streams; i++)
7486             if (rtp_hinting_needed(s->streams[i]))
7487                 mov->nb_streams++;
7488     }
7489 
7490     if (mov->write_btrt < 0) {
7491         mov->write_btrt = mov->mode == MODE_MP4;
7492     }
7493 
7494     if (   mov->write_tmcd == -1 && (mov->mode == MODE_MOV || mov->mode == MODE_MP4)
7495         || mov->write_tmcd == 1) {
7496         AVDictionaryEntry *global_tcr = av_dict_get(s->metadata, "timecode",
7497                                                     NULL, 0);
7498 
7499         /* +1 tmcd track for each video stream with a timecode */
7500         for (i = 0; i < s->nb_streams; i++) {
7501             AVStream *st = s->streams[i];
7502             AVDictionaryEntry *t = global_tcr;
7503             if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
7504                 (t || (t=av_dict_get(st->metadata, "timecode", NULL, 0)))) {
7505                 AVTimecode tc;
7506                 ret = mov_check_timecode_track(s, &tc, i, t->value);
7507                 if (ret >= 0)
7508                     mov->nb_meta_tmcd++;
7509             }
7510         }
7511 
7512         /* check if there is already a tmcd track to remux */
7513         if (mov->nb_meta_tmcd) {
7514             for (i = 0; i < s->nb_streams; i++) {
7515                 AVStream *st = s->streams[i];
7516                 if (st->codecpar->codec_tag == MKTAG('t','m','c','d')) {
7517                     av_log(s, AV_LOG_WARNING, "You requested a copy of the original timecode track "
7518                            "so timecode metadata are now ignored\n");
7519                     mov->nb_meta_tmcd = 0;
7520                 }
7521             }
7522         }
7523 
7524         mov->nb_streams += mov->nb_meta_tmcd;
7525     }
7526 
7527 #ifdef OHOS_TIMED_META_TRACK
7528     if (mov->flags & FF_MOV_FLAG_TIMED_METADATA) {
7529         for (i = 0; i < s->nb_streams; i++) {
7530             AVStream *st = s->streams[i];
7531             if (st->codecpar->codec_type == AVMEDIA_TYPE_TIMEDMETA)
7532                 mov->nb_timed_metadata_track++;
7533         }
7534     }
7535 #endif
7536     // Reserve an extra stream for chapters for the case where chapters
7537     // are written in the trailer
7538     mov->tracks = av_calloc(mov->nb_streams + 1, sizeof(*mov->tracks));
7539     if (!mov->tracks)
7540         return AVERROR(ENOMEM);
7541 
7542     if (mov->encryption_scheme_str != NULL && strcmp(mov->encryption_scheme_str, "none") != 0) {
7543         if (strcmp(mov->encryption_scheme_str, "cenc-aes-ctr") == 0) {
7544             mov->encryption_scheme = MOV_ENC_CENC_AES_CTR;
7545 
7546             if (mov->encryption_key_len != AES_CTR_KEY_SIZE) {
7547                 av_log(s, AV_LOG_ERROR, "Invalid encryption key len %d expected %d\n",
7548                     mov->encryption_key_len, AES_CTR_KEY_SIZE);
7549                 return AVERROR(EINVAL);
7550             }
7551 
7552             if (mov->encryption_kid_len != CENC_KID_SIZE) {
7553                 av_log(s, AV_LOG_ERROR, "Invalid encryption kid len %d expected %d\n",
7554                     mov->encryption_kid_len, CENC_KID_SIZE);
7555                 return AVERROR(EINVAL);
7556             }
7557         } else {
7558             av_log(s, AV_LOG_ERROR, "unsupported encryption scheme %s\n",
7559                 mov->encryption_scheme_str);
7560             return AVERROR(EINVAL);
7561         }
7562     }
7563 
7564     for (i = 0; i < s->nb_streams; i++) {
7565         AVStream *st= s->streams[i];
7566         MOVTrack *track= &mov->tracks[i];
7567         AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL,0);
7568 
7569         track->st  = st;
7570         track->par = st->codecpar;
7571         track->language = ff_mov_iso639_to_lang(lang?lang->value:"und", mov->mode!=MODE_MOV);
7572         if (track->language < 0)
7573             track->language = 32767;  // Unspecified Macintosh language code
7574         track->mode = mov->mode;
7575         track->tag  = mov_find_codec_tag(s, track);
7576         if (!track->tag) {
7577             av_log(s, AV_LOG_ERROR, "Could not find tag for codec %s in stream #%d, "
7578                    "codec not currently supported in container\n",
7579                    avcodec_get_name(st->codecpar->codec_id), i);
7580             return AVERROR(EINVAL);
7581         }
7582         /* If hinting of this track is enabled by a later hint track,
7583          * this is updated. */
7584         track->hint_track = -1;
7585         track->start_dts  = AV_NOPTS_VALUE;
7586         track->start_cts  = AV_NOPTS_VALUE;
7587         track->end_pts    = AV_NOPTS_VALUE;
7588         track->dts_shift  = AV_NOPTS_VALUE;
7589         if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
7590             if (track->tag == MKTAG('m','x','3','p') || track->tag == MKTAG('m','x','3','n') ||
7591                 track->tag == MKTAG('m','x','4','p') || track->tag == MKTAG('m','x','4','n') ||
7592                 track->tag == MKTAG('m','x','5','p') || track->tag == MKTAG('m','x','5','n')) {
7593                 if (st->codecpar->width != 720 || (st->codecpar->height != 608 && st->codecpar->height != 512)) {
7594                     av_log(s, AV_LOG_ERROR, "D-10/IMX must use 720x608 or 720x512 video resolution\n");
7595                     return AVERROR(EINVAL);
7596                 }
7597                 track->height = track->tag >> 24 == 'n' ? 486 : 576;
7598             }
7599             if (mov->video_track_timescale) {
7600                 track->timescale = mov->video_track_timescale;
7601                 if (mov->mode == MODE_ISM && mov->video_track_timescale != 10000000)
7602                     av_log(s, AV_LOG_WARNING, "Warning: some tools, like mp4split, assume a timescale of 10000000 for ISMV.\n");
7603             } else {
7604                 track->timescale = st->time_base.den;
7605                 while(track->timescale < 10000)
7606                     track->timescale *= 2;
7607             }
7608             if (st->codecpar->width > 65535 || st->codecpar->height > 65535) {
7609                 av_log(s, AV_LOG_ERROR, "Resolution %dx%d too large for mov/mp4\n", st->codecpar->width, st->codecpar->height);
7610                 return AVERROR(EINVAL);
7611             }
7612             if (track->mode == MODE_MOV && track->timescale > 100000)
7613                 av_log(s, AV_LOG_WARNING,
7614                        "WARNING codec timebase is very high. If duration is too long,\n"
7615                        "file may not be playable by quicktime. Specify a shorter timebase\n"
7616                        "or choose different container.\n");
7617             if (track->mode == MODE_MOV &&
7618                 track->par->codec_id == AV_CODEC_ID_RAWVIDEO &&
7619                 track->tag == MKTAG('r','a','w',' ')) {
7620                 enum AVPixelFormat pix_fmt = track->par->format;
7621                 if (pix_fmt == AV_PIX_FMT_NONE && track->par->bits_per_coded_sample == 1)
7622                     pix_fmt = AV_PIX_FMT_MONOWHITE;
7623                 track->is_unaligned_qt_rgb =
7624                         pix_fmt == AV_PIX_FMT_RGB24 ||
7625                         pix_fmt == AV_PIX_FMT_BGR24 ||
7626                         pix_fmt == AV_PIX_FMT_PAL8 ||
7627                         pix_fmt == AV_PIX_FMT_GRAY8 ||
7628                         pix_fmt == AV_PIX_FMT_MONOWHITE ||
7629                         pix_fmt == AV_PIX_FMT_MONOBLACK;
7630             }
7631             if (track->par->codec_id == AV_CODEC_ID_VP9 && track->mode != MODE_MP4) {
7632                 av_log(s, AV_LOG_ERROR, "%s only supported in MP4.\n", avcodec_get_name(track->par->codec_id));
7633                 return AVERROR(EINVAL);
7634             } else if (track->par->codec_id == AV_CODEC_ID_AV1 &&
7635                        track->mode != MODE_MP4 && track->mode != MODE_AVIF) {
7636                 av_log(s, AV_LOG_ERROR, "%s only supported in MP4 and AVIF.\n", avcodec_get_name(track->par->codec_id));
7637                 return AVERROR(EINVAL);
7638             } else if (track->par->codec_id == AV_CODEC_ID_VP8) {
7639                 /* altref frames handling is not defined in the spec as of version v1.0,
7640                  * so just forbid muxing VP8 streams altogether until a new version does */
7641                 av_log(s, AV_LOG_ERROR, "VP8 muxing is currently not supported.\n");
7642                 return AVERROR_PATCHWELCOME;
7643             }
7644             if (is_cover_image(st)) {
7645                 track->cover_image = av_packet_alloc();
7646                 if (!track->cover_image)
7647                     return AVERROR(ENOMEM);
7648             }
7649         } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
7650             track->timescale = st->codecpar->sample_rate;
7651             if (!st->codecpar->frame_size && !av_get_bits_per_sample(st->codecpar->codec_id)) {
7652                 av_log(s, AV_LOG_WARNING, "track %d: codec frame size is not set\n", i);
7653                 track->audio_vbr = 1;
7654             }else if (st->codecpar->codec_id == AV_CODEC_ID_ADPCM_MS ||
7655                      st->codecpar->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV ||
7656                      st->codecpar->codec_id == AV_CODEC_ID_ILBC){
7657                 if (!st->codecpar->block_align) {
7658                     av_log(s, AV_LOG_ERROR, "track %d: codec block align is not set for adpcm\n", i);
7659                     return AVERROR(EINVAL);
7660                 }
7661                 track->sample_size = st->codecpar->block_align;
7662             }else if (st->codecpar->frame_size > 1){ /* assume compressed audio */
7663                 track->audio_vbr = 1;
7664             }else{
7665                 track->sample_size = (av_get_bits_per_sample(st->codecpar->codec_id) >> 3) *
7666                                      st->codecpar->ch_layout.nb_channels;
7667             }
7668             if (st->codecpar->codec_id == AV_CODEC_ID_ILBC ||
7669                 st->codecpar->codec_id == AV_CODEC_ID_ADPCM_IMA_QT) {
7670                 track->audio_vbr = 1;
7671             }
7672             if (track->mode != MODE_MOV &&
7673                 track->par->codec_id == AV_CODEC_ID_MP3 && track->timescale < 16000) {
7674                 if (s->strict_std_compliance >= FF_COMPLIANCE_NORMAL) {
7675                     av_log(s, AV_LOG_ERROR, "track %d: muxing mp3 at %dhz is not standard, to mux anyway set strict to -1\n",
7676                         i, track->par->sample_rate);
7677                     return AVERROR(EINVAL);
7678                 } else {
7679                     av_log(s, AV_LOG_WARNING, "track %d: muxing mp3 at %dhz is not standard in MP4\n",
7680                            i, track->par->sample_rate);
7681                 }
7682             }
7683             if (track->par->codec_id == AV_CODEC_ID_FLAC ||
7684                 track->par->codec_id == AV_CODEC_ID_TRUEHD ||
7685                 track->par->codec_id == AV_CODEC_ID_OPUS) {
7686                 if (track->mode != MODE_MP4) {
7687                     av_log(s, AV_LOG_ERROR, "%s only supported in MP4.\n", avcodec_get_name(track->par->codec_id));
7688                     return AVERROR(EINVAL);
7689                 }
7690                 if (track->par->codec_id != AV_CODEC_ID_OPUS &&
7691                     s->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) {
7692                     av_log(s, AV_LOG_ERROR,
7693                            "%s in MP4 support is experimental, add "
7694                            "'-strict %d' if you want to use it.\n",
7695                            avcodec_get_name(track->par->codec_id), FF_COMPLIANCE_EXPERIMENTAL);
7696                     return AVERROR_EXPERIMENTAL;
7697                 }
7698             }
7699         } else if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
7700             track->timescale = st->time_base.den;
7701 
7702             if (track->par->codec_id == AV_CODEC_ID_TTML) {
7703                 /* 14496-30 requires us to use a single sample per fragment
7704                    for TTML, for which we define a per-track flag.
7705 
7706                    We set the flag in case we are receiving TTML paragraphs
7707                    from the input, in other words in case we are not doing
7708                    stream copy. */
7709                 track->squash_fragment_samples_to_one =
7710                     ff_is_ttml_stream_paragraph_based(track->par);
7711 
7712                 if (mov->flags & FF_MOV_FLAG_FRAGMENT &&
7713                     track->squash_fragment_samples_to_one) {
7714                     av_log(s, AV_LOG_ERROR,
7715                            "Fragmentation is not currently supported for "
7716                            "TTML in MP4/ISMV (track synchronization between "
7717                            "subtitles and other media is not yet implemented)!\n");
7718                     return AVERROR_PATCHWELCOME;
7719                 }
7720 
7721                 if (track->mode != MODE_ISM &&
7722                     track->par->codec_tag == MOV_ISMV_TTML_TAG &&
7723                     s->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL) {
7724                     av_log(s, AV_LOG_ERROR,
7725                            "ISMV style TTML support with the 'dfxp' tag in "
7726                            "non-ISMV formats is not officially supported. Add "
7727                            "'-strict unofficial' if you want to use it.\n");
7728                     return AVERROR_EXPERIMENTAL;
7729                 }
7730             }
7731         } else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA) {
7732             track->timescale = st->time_base.den;
7733 #ifdef OHOS_TIMED_META_TRACK
7734         } else if (st->codecpar->codec_type == AVMEDIA_TYPE_TIMEDMETA) {
7735             track->timescale = st->time_base.den;
7736 #endif
7737         } else {
7738             track->timescale = mov->movie_timescale;
7739         }
7740         if (!track->height)
7741             track->height = st->codecpar->height;
7742         /* The Protected Interoperable File Format (PIFF) standard, used by ISMV recommends but
7743            doesn't mandate a track timescale of 10,000,000. The muxer allows a custom timescale
7744            for video tracks, so if user-set, it isn't overwritten */
7745         if (mov->mode == MODE_ISM &&
7746             (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO ||
7747             (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && !mov->video_track_timescale))) {
7748              track->timescale = 10000000;
7749         }
7750 
7751         avpriv_set_pts_info(st, 64, 1, track->timescale);
7752 
7753         if (mov->encryption_scheme == MOV_ENC_CENC_AES_CTR) {
7754             ret = ff_mov_cenc_init(&track->cenc, mov->encryption_key,
7755                 (track->par->codec_id == AV_CODEC_ID_H264 || track->par->codec_id == AV_CODEC_ID_HEVC),
7756                 s->flags & AVFMT_FLAG_BITEXACT);
7757             if (ret)
7758                 return ret;
7759         }
7760     }
7761 
7762     enable_tracks(s);
7763     return 0;
7764 }
7765 
7766 static int mov_write_header(AVFormatContext *s)
7767 {
7768     AVIOContext *pb = s->pb;
7769     MOVMuxContext *mov = s->priv_data;
7770     int i, ret, hint_track = 0, tmcd_track = 0, nb_tracks = s->nb_streams;
7771 
7772     if (mov->mode & (MODE_MP4|MODE_MOV|MODE_IPOD) && s->nb_chapters)
7773         nb_tracks++;
7774 
7775     if (mov->flags & FF_MOV_FLAG_RTP_HINT) {
7776         hint_track = nb_tracks;
7777         for (i = 0; i < s->nb_streams; i++)
7778             if (rtp_hinting_needed(s->streams[i]))
7779                 nb_tracks++;
7780     }
7781 
7782     if (mov->nb_meta_tmcd)
7783         tmcd_track = nb_tracks;
7784 
7785     for (i = 0; i < s->nb_streams; i++) {
7786         int j;
7787         AVStream *st= s->streams[i];
7788         MOVTrack *track= &mov->tracks[i];
7789 
7790         /* copy extradata if it exists */
7791         if (st->codecpar->extradata_size) {
7792             if (st->codecpar->codec_id == AV_CODEC_ID_DVD_SUBTITLE)
7793                 mov_create_dvd_sub_decoder_specific_info(track, st);
7794             else if (!TAG_IS_AVCI(track->tag) && st->codecpar->codec_id != AV_CODEC_ID_DNXHD) {
7795                 track->vos_len  = st->codecpar->extradata_size;
7796                 track->vos_data = av_malloc(track->vos_len + AV_INPUT_BUFFER_PADDING_SIZE);
7797                 if (!track->vos_data) {
7798                     return AVERROR(ENOMEM);
7799                 }
7800                 memcpy(track->vos_data, st->codecpar->extradata, track->vos_len);
7801                 memset(track->vos_data + track->vos_len, 0, AV_INPUT_BUFFER_PADDING_SIZE);
7802             }
7803         }
7804 
7805         if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO ||
7806             av_channel_layout_compare(&track->par->ch_layout,
7807                                       &(AVChannelLayout)AV_CHANNEL_LAYOUT_MONO))
7808             continue;
7809 
7810         for (j = 0; j < s->nb_streams; j++) {
7811             AVStream *stj= s->streams[j];
7812             MOVTrack *trackj= &mov->tracks[j];
7813             if (j == i)
7814                 continue;
7815 
7816             if (stj->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
7817                 (trackj->par->ch_layout.nb_channels != 1 ||
7818                  !av_channel_layout_compare(&trackj->par->ch_layout,
7819                                             &(AVChannelLayout)AV_CHANNEL_LAYOUT_MONO))
7820             )
7821                 track->mono_as_fc = -1;
7822 
7823             if (stj->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
7824                 av_channel_layout_compare(&trackj->par->ch_layout,
7825                                           &(AVChannelLayout)AV_CHANNEL_LAYOUT_MONO) &&
7826                 trackj->par->ch_layout.nb_channels == 1 && track->mono_as_fc >= 0
7827             )
7828                 track->mono_as_fc++;
7829 
7830             if (stj->codecpar->codec_type != AVMEDIA_TYPE_AUDIO ||
7831                 av_channel_layout_compare(&trackj->par->ch_layout,
7832                                           &(AVChannelLayout)AV_CHANNEL_LAYOUT_MONO) ||
7833                 trackj->language != track->language ||
7834                 trackj->tag != track->tag
7835             )
7836                 continue;
7837             track->multichannel_as_mono++;
7838         }
7839     }
7840 
7841     if (!(mov->flags & FF_MOV_FLAG_DELAY_MOOV)) {
7842         if ((ret = mov_write_identification(pb, s)) < 0)
7843             return ret;
7844     }
7845 
7846     if (mov->reserved_moov_size){
7847         mov->reserved_header_pos = avio_tell(pb);
7848         if (mov->reserved_moov_size > 0)
7849             avio_skip(pb, mov->reserved_moov_size);
7850     }
7851 
7852     if (mov->flags & FF_MOV_FLAG_FRAGMENT) {
7853         /* If no fragmentation options have been set, set a default. */
7854         if (!(mov->flags & (FF_MOV_FLAG_FRAG_KEYFRAME |
7855                             FF_MOV_FLAG_FRAG_CUSTOM |
7856                             FF_MOV_FLAG_FRAG_EVERY_FRAME)) &&
7857             !mov->max_fragment_duration && !mov->max_fragment_size)
7858             mov->flags |= FF_MOV_FLAG_FRAG_KEYFRAME;
7859     } else if (mov->mode != MODE_AVIF) {
7860         if (mov->flags & FF_MOV_FLAG_FASTSTART)
7861             mov->reserved_header_pos = avio_tell(pb);
7862         mov_write_mdat_tag(pb, mov);
7863     }
7864 
7865     ff_parse_creation_time_metadata(s, &mov->time, 1);
7866     if (mov->time)
7867         mov->time += 0x7C25B080; // 1970 based -> 1904 based
7868 
7869     if (mov->chapter_track)
7870         if ((ret = mov_create_chapter_track(s, mov->chapter_track)) < 0)
7871             return ret;
7872 
7873     if (mov->flags & FF_MOV_FLAG_RTP_HINT) {
7874         for (i = 0; i < s->nb_streams; i++) {
7875             if (rtp_hinting_needed(s->streams[i])) {
7876                 if ((ret = ff_mov_init_hinting(s, hint_track, i)) < 0)
7877                     return ret;
7878                 hint_track++;
7879             }
7880         }
7881     }
7882 
7883     if (mov->nb_meta_tmcd) {
7884         const AVDictionaryEntry *t, *global_tcr = av_dict_get(s->metadata,
7885                                                               "timecode", NULL, 0);
7886         /* Initialize the tmcd tracks */
7887         for (i = 0; i < s->nb_streams; i++) {
7888             AVStream *st = s->streams[i];
7889             t = global_tcr;
7890 
7891             if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
7892                 AVTimecode tc;
7893                 if (!t)
7894                     t = av_dict_get(st->metadata, "timecode", NULL, 0);
7895                 if (!t)
7896                     continue;
7897                 if (mov_check_timecode_track(s, &tc, i, t->value) < 0)
7898                     continue;
7899                 if ((ret = mov_create_timecode_track(s, tmcd_track, i, tc)) < 0)
7900                     return ret;
7901                 tmcd_track++;
7902             }
7903         }
7904     }
7905 #ifdef OHOS_TIMED_META_TRACK
7906     if (mov->flags & FF_MOV_FLAG_TIMED_METADATA) {
7907         for (i = 0; i < s->nb_streams; i++) {
7908             AVStream *st = s->streams[i];
7909             if (st->codecpar->codec_type == AVMEDIA_TYPE_TIMEDMETA) {
7910                 const AVDictionaryEntry *t = av_dict_get(st->metadata, "src_track_id", NULL, 0);
7911                 if (!t)
7912                     continue;
7913                 size_t id_len = strlen(t->value);
7914                 int track_id = 0;
7915                 const int base = 10;
7916                 const char start = '0';
7917                 for (int j = 0; j < id_len; j++)
7918                     track_id = track_id * base + t->value[j] - start;
7919                 if ((ret = mov_create_timed_metadata_track(s, i, track_id)) < 0)
7920                     return ret;
7921             }
7922         }
7923     }
7924 #endif
7925 
7926     avio_flush(pb);
7927 
7928     if (mov->flags & FF_MOV_FLAG_ISML)
7929         mov_write_isml_manifest(pb, mov, s);
7930 
7931     if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV &&
7932         !(mov->flags & FF_MOV_FLAG_DELAY_MOOV)) {
7933         if ((ret = mov_write_moov_tag(pb, mov, s)) < 0)
7934             return ret;
7935         mov->moov_written = 1;
7936         if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX)
7937             mov->reserved_header_pos = avio_tell(pb);
7938     }
7939 
7940     return 0;
7941 }
7942 
7943 static int get_moov_size(AVFormatContext *s)
7944 {
7945     int ret;
7946     AVIOContext *moov_buf;
7947     MOVMuxContext *mov = s->priv_data;
7948 
7949     if ((ret = ffio_open_null_buf(&moov_buf)) < 0)
7950         return ret;
7951     if ((ret = mov_write_moov_tag(moov_buf, mov, s)) < 0)
7952         return ret;
7953     return ffio_close_null_buf(moov_buf);
7954 }
7955 
7956 static int get_sidx_size(AVFormatContext *s)
7957 {
7958     int ret;
7959     AVIOContext *buf;
7960     MOVMuxContext *mov = s->priv_data;
7961 
7962     if ((ret = ffio_open_null_buf(&buf)) < 0)
7963         return ret;
7964     mov_write_sidx_tags(buf, mov, -1, 0);
7965     return ffio_close_null_buf(buf);
7966 }
7967 
7968 /*
7969  * This function gets the moov size if moved to the top of the file: the chunk
7970  * offset table can switch between stco (32-bit entries) to co64 (64-bit
7971  * entries) when the moov is moved to the beginning, so the size of the moov
7972  * would change. It also updates the chunk offset tables.
7973  */
7974 static int compute_moov_size(AVFormatContext *s)
7975 {
7976     int i, moov_size, moov_size2;
7977     MOVMuxContext *mov = s->priv_data;
7978 
7979     moov_size = get_moov_size(s);
7980     if (moov_size < 0)
7981         return moov_size;
7982 
7983     for (i = 0; i < mov->nb_streams; i++)
7984         mov->tracks[i].data_offset += moov_size;
7985 
7986     moov_size2 = get_moov_size(s);
7987     if (moov_size2 < 0)
7988         return moov_size2;
7989 
7990     /* if the size changed, we just switched from stco to co64 and need to
7991      * update the offsets */
7992     if (moov_size2 != moov_size)
7993         for (i = 0; i < mov->nb_streams; i++)
7994             mov->tracks[i].data_offset += moov_size2 - moov_size;
7995 
7996     return moov_size2;
7997 }
7998 
7999 static int compute_sidx_size(AVFormatContext *s)
8000 {
8001     int i, sidx_size;
8002     MOVMuxContext *mov = s->priv_data;
8003 
8004     sidx_size = get_sidx_size(s);
8005     if (sidx_size < 0)
8006         return sidx_size;
8007 
8008     for (i = 0; i < mov->nb_streams; i++)
8009         mov->tracks[i].data_offset += sidx_size;
8010 
8011     return sidx_size;
8012 }
8013 
8014 static int shift_data(AVFormatContext *s)
8015 {
8016     int moov_size;
8017     MOVMuxContext *mov = s->priv_data;
8018 
8019     if (mov->flags & FF_MOV_FLAG_FRAGMENT)
8020         moov_size = compute_sidx_size(s);
8021     else
8022         moov_size = compute_moov_size(s);
8023     if (moov_size < 0)
8024         return moov_size;
8025 
8026     return ff_format_shift_data(s, mov->reserved_header_pos, moov_size);
8027 }
8028 
8029 static int mov_write_trailer(AVFormatContext *s)
8030 {
8031     MOVMuxContext *mov = s->priv_data;
8032     AVIOContext *pb = s->pb;
8033     int res = 0;
8034     int i;
8035     int64_t moov_pos;
8036 
8037     if (mov->need_rewrite_extradata) {
8038         for (i = 0; i < s->nb_streams; i++) {
8039             MOVTrack *track = &mov->tracks[i];
8040             AVCodecParameters *par = track->par;
8041 
8042             track->vos_len  = par->extradata_size;
8043             av_freep(&track->vos_data);
8044             track->vos_data = av_malloc(track->vos_len + AV_INPUT_BUFFER_PADDING_SIZE);
8045             if (!track->vos_data)
8046                 return AVERROR(ENOMEM);
8047             memcpy(track->vos_data, par->extradata, track->vos_len);
8048             memset(track->vos_data + track->vos_len, 0, AV_INPUT_BUFFER_PADDING_SIZE);
8049         }
8050         mov->need_rewrite_extradata = 0;
8051     }
8052 
8053     /*
8054      * Before actually writing the trailer, make sure that there are no
8055      * dangling subtitles, that need a terminating sample.
8056      */
8057     for (i = 0; i < mov->nb_streams; i++) {
8058         MOVTrack *trk = &mov->tracks[i];
8059         if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT &&
8060             !trk->last_sample_is_subtitle_end) {
8061             mov_write_subtitle_end_packet(s, i, trk->track_duration);
8062             trk->last_sample_is_subtitle_end = 1;
8063         }
8064     }
8065 
8066     // Check if we have any tracks that require squashing.
8067     // In that case, we'll have to write the packet here.
8068     if ((res = mov_write_squashed_packets(s)) < 0)
8069         return res;
8070 
8071     // If there were no chapters when the header was written, but there
8072     // are chapters now, write them in the trailer.  This only works
8073     // when we are not doing fragments.
8074     if (!mov->chapter_track && !(mov->flags & FF_MOV_FLAG_FRAGMENT)) {
8075         if (mov->mode & (MODE_MP4|MODE_MOV|MODE_IPOD) && s->nb_chapters) {
8076             mov->chapter_track = mov->nb_streams++;
8077             if ((res = mov_create_chapter_track(s, mov->chapter_track)) < 0)
8078                 return res;
8079         }
8080     }
8081 
8082     if (!(mov->flags & FF_MOV_FLAG_FRAGMENT)) {
8083         moov_pos = avio_tell(pb);
8084 
8085         /* Write size of mdat tag */
8086         if (mov->mdat_size + 8 <= UINT32_MAX) {
8087             avio_seek(pb, mov->mdat_pos, SEEK_SET);
8088             avio_wb32(pb, mov->mdat_size + 8);
8089         } else {
8090             /* overwrite 'wide' placeholder atom */
8091             avio_seek(pb, mov->mdat_pos - 8, SEEK_SET);
8092             /* special value: real atom size will be 64 bit value after
8093              * tag field */
8094             avio_wb32(pb, 1);
8095             ffio_wfourcc(pb, "mdat");
8096             avio_wb64(pb, mov->mdat_size + 16);
8097         }
8098         avio_seek(pb, mov->reserved_moov_size > 0 ? mov->reserved_header_pos : moov_pos, SEEK_SET);
8099 
8100         if (mov->flags & FF_MOV_FLAG_FASTSTART) {
8101             av_log(s, AV_LOG_INFO, "Starting second pass: moving the moov atom to the beginning of the file\n");
8102             res = shift_data(s);
8103             if (res < 0)
8104                 return res;
8105             avio_seek(pb, mov->reserved_header_pos, SEEK_SET);
8106             if ((res = mov_write_moov_tag(pb, mov, s)) < 0)
8107                 return res;
8108         } else if (mov->reserved_moov_size > 0) {
8109             int64_t size;
8110             if ((res = mov_write_moov_tag(pb, mov, s)) < 0)
8111                 return res;
8112             size = mov->reserved_moov_size - (avio_tell(pb) - mov->reserved_header_pos);
8113             if (size < 8){
8114                 av_log(s, AV_LOG_ERROR, "reserved_moov_size is too small, needed %"PRId64" additional\n", 8-size);
8115                 return AVERROR(EINVAL);
8116             }
8117             avio_wb32(pb, size);
8118             ffio_wfourcc(pb, "free");
8119             ffio_fill(pb, 0, size - 8);
8120             avio_seek(pb, moov_pos, SEEK_SET);
8121         } else {
8122             if ((res = mov_write_moov_tag(pb, mov, s)) < 0)
8123                 return res;
8124         }
8125         res = 0;
8126     } else {
8127         mov_auto_flush_fragment(s, 1);
8128         for (i = 0; i < mov->nb_streams; i++)
8129            mov->tracks[i].data_offset = 0;
8130         if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX) {
8131             int64_t end;
8132             av_log(s, AV_LOG_INFO, "Starting second pass: inserting sidx atoms\n");
8133             res = shift_data(s);
8134             if (res < 0)
8135                 return res;
8136             end = avio_tell(pb);
8137             avio_seek(pb, mov->reserved_header_pos, SEEK_SET);
8138             mov_write_sidx_tags(pb, mov, -1, 0);
8139             avio_seek(pb, end, SEEK_SET);
8140         }
8141         if (!(mov->flags & FF_MOV_FLAG_SKIP_TRAILER)) {
8142             avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_TRAILER);
8143             res = mov_write_mfra_tag(pb, mov);
8144             if (res < 0)
8145                 return res;
8146         }
8147     }
8148 
8149     return res;
8150 }
8151 
8152 static int mov_check_bitstream(AVFormatContext *s, AVStream *st,
8153                                const AVPacket *pkt)
8154 {
8155     int ret = 1;
8156 
8157     if (st->codecpar->codec_id == AV_CODEC_ID_AAC) {
8158         if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0)
8159             ret = ff_stream_add_bitstream_filter(st, "aac_adtstoasc", NULL);
8160     } else if (st->codecpar->codec_id == AV_CODEC_ID_VP9) {
8161         ret = ff_stream_add_bitstream_filter(st, "vp9_superframe", NULL);
8162     }
8163 
8164     return ret;
8165 }
8166 
8167 static int avif_write_trailer(AVFormatContext *s)
8168 {
8169     AVIOContext *pb = s->pb;
8170     MOVMuxContext *mov = s->priv_data;
8171     int64_t pos_backup, extent_offsets[2];
8172     uint8_t *buf;
8173     int buf_size, moov_size, i;
8174 
8175     if (mov->moov_written) return 0;
8176 
8177     mov->is_animated_avif = s->streams[0]->nb_frames > 1;
8178     if (mov->is_animated_avif && s->nb_streams > 1) {
8179         // For animated avif with alpha channel, we need to write a tref tag
8180         // with type "auxl".
8181         mov->tracks[1].tref_tag = MKTAG('a', 'u', 'x', 'l');
8182 #ifdef OHOS_TIMED_META_TRACK
8183         mov->tracks[1].tref_ids[0] = 1;
8184 #else
8185         mov->tracks[1].tref_id = 1;
8186 #endif
8187     }
8188     mov_write_identification(pb, s);
8189     mov_write_meta_tag(pb, mov, s);
8190 
8191     moov_size = get_moov_size(s);
8192     for (i = 0; i < s->nb_streams; i++)
8193         mov->tracks[i].data_offset = avio_tell(pb) + moov_size + 8;
8194 
8195     if (mov->is_animated_avif) {
8196         int ret;
8197         if ((ret = mov_write_moov_tag(pb, mov, s)) < 0)
8198             return ret;
8199     }
8200 
8201     buf_size = avio_get_dyn_buf(mov->mdat_buf, &buf);
8202     avio_wb32(pb, buf_size + 8);
8203     ffio_wfourcc(pb, "mdat");
8204 
8205     // The offset for the YUV planes is the starting position of mdat.
8206     extent_offsets[0] = avio_tell(pb);
8207     // The offset for alpha plane is YUV offset + YUV size.
8208     extent_offsets[1] = extent_offsets[0] + mov->avif_extent_length[0];
8209 
8210     avio_write(pb, buf, buf_size);
8211 
8212     // write extent offsets.
8213     pos_backup = avio_tell(pb);
8214     for (i = 0; i < s->nb_streams; i++) {
8215         if (extent_offsets[i] != (uint32_t)extent_offsets[i]) {
8216             av_log(s, AV_LOG_ERROR, "extent offset does not fit in 32 bits\n");
8217             return AVERROR_INVALIDDATA;
8218         }
8219         avio_seek(pb, mov->avif_extent_pos[i], SEEK_SET);
8220         avio_wb32(pb, extent_offsets[i]); /* rewrite offset */
8221     }
8222     avio_seek(pb, pos_backup, SEEK_SET);
8223 
8224     return 0;
8225 }
8226 
8227 #if CONFIG_TGP_MUXER || CONFIG_TG2_MUXER
8228 static const AVCodecTag codec_3gp_tags[] = {
8229     { AV_CODEC_ID_H263,     MKTAG('s','2','6','3') },
8230     { AV_CODEC_ID_H264,     MKTAG('a','v','c','1') },
8231     { AV_CODEC_ID_MPEG4,    MKTAG('m','p','4','v') },
8232     { AV_CODEC_ID_AAC,      MKTAG('m','p','4','a') },
8233     { AV_CODEC_ID_AMR_NB,   MKTAG('s','a','m','r') },
8234     { AV_CODEC_ID_AMR_WB,   MKTAG('s','a','w','b') },
8235     { AV_CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') },
8236     { AV_CODEC_ID_NONE, 0 },
8237 };
8238 static const AVCodecTag *const codec_3gp_tags_list[] = { codec_3gp_tags, NULL };
8239 #endif
8240 
8241 static const AVCodecTag codec_mp4_tags[] = {
8242     { AV_CODEC_ID_MPEG4,           MKTAG('m', 'p', '4', 'v') },
8243     { AV_CODEC_ID_H264,            MKTAG('a', 'v', 'c', '1') },
8244     { AV_CODEC_ID_H264,            MKTAG('a', 'v', 'c', '3') },
8245     { AV_CODEC_ID_HEVC,            MKTAG('h', 'e', 'v', '1') },
8246     { AV_CODEC_ID_HEVC,            MKTAG('h', 'v', 'c', '1') },
8247     { AV_CODEC_ID_MPEG2VIDEO,      MKTAG('m', 'p', '4', 'v') },
8248     { AV_CODEC_ID_MPEG1VIDEO,      MKTAG('m', 'p', '4', 'v') },
8249     { AV_CODEC_ID_MJPEG,           MKTAG('m', 'p', '4', 'v') },
8250     { AV_CODEC_ID_PNG,             MKTAG('m', 'p', '4', 'v') },
8251     { AV_CODEC_ID_JPEG2000,        MKTAG('m', 'p', '4', 'v') },
8252     { AV_CODEC_ID_VC1,             MKTAG('v', 'c', '-', '1') },
8253     { AV_CODEC_ID_DIRAC,           MKTAG('d', 'r', 'a', 'c') },
8254     { AV_CODEC_ID_TSCC2,           MKTAG('m', 'p', '4', 'v') },
8255     { AV_CODEC_ID_VP9,             MKTAG('v', 'p', '0', '9') },
8256     { AV_CODEC_ID_AV1,             MKTAG('a', 'v', '0', '1') },
8257     { AV_CODEC_ID_AAC,             MKTAG('m', 'p', '4', 'a') },
8258     { AV_CODEC_ID_ALAC,            MKTAG('a', 'l', 'a', 'c') },
8259     { AV_CODEC_ID_MP4ALS,          MKTAG('m', 'p', '4', 'a') },
8260     { AV_CODEC_ID_MP3,             MKTAG('m', 'p', '4', 'a') },
8261     { AV_CODEC_ID_MP2,             MKTAG('m', 'p', '4', 'a') },
8262     { AV_CODEC_ID_AC3,             MKTAG('a', 'c', '-', '3') },
8263     { AV_CODEC_ID_EAC3,            MKTAG('e', 'c', '-', '3') },
8264     { AV_CODEC_ID_DTS,             MKTAG('m', 'p', '4', 'a') },
8265     { AV_CODEC_ID_TRUEHD,          MKTAG('m', 'l', 'p', 'a') },
8266     { AV_CODEC_ID_FLAC,            MKTAG('f', 'L', 'a', 'C') },
8267     { AV_CODEC_ID_OPUS,            MKTAG('O', 'p', 'u', 's') },
8268     { AV_CODEC_ID_VORBIS,          MKTAG('m', 'p', '4', 'a') },
8269     { AV_CODEC_ID_QCELP,           MKTAG('m', 'p', '4', 'a') },
8270     { AV_CODEC_ID_EVRC,            MKTAG('m', 'p', '4', 'a') },
8271     { AV_CODEC_ID_DVD_SUBTITLE,    MKTAG('m', 'p', '4', 's') },
8272     { AV_CODEC_ID_MOV_TEXT,        MKTAG('t', 'x', '3', 'g') },
8273     { AV_CODEC_ID_BIN_DATA,        MKTAG('g', 'p', 'm', 'd') },
8274     { AV_CODEC_ID_MPEGH_3D_AUDIO,  MKTAG('m', 'h', 'm', '1') },
8275     { AV_CODEC_ID_TTML,            MOV_MP4_TTML_TAG          },
8276     { AV_CODEC_ID_TTML,            MOV_ISMV_TTML_TAG         },
8277 #ifdef OHOS_TIMED_META_TRACK
8278     { AV_CODEC_ID_FFMETADATA,      MKTAG('c', 'd', 's', 'c') },
8279 #endif
8280     { AV_CODEC_ID_NONE,               0 },
8281 };
8282 #if CONFIG_MP4_MUXER || CONFIG_PSP_MUXER
8283 static const AVCodecTag *const mp4_codec_tags_list[] = { codec_mp4_tags, NULL };
8284 #endif
8285 
8286 static const AVCodecTag codec_ism_tags[] = {
8287     { AV_CODEC_ID_WMAPRO      , MKTAG('w', 'm', 'a', ' ') },
8288     { AV_CODEC_ID_TTML        , MOV_ISMV_TTML_TAG         },
8289     { AV_CODEC_ID_NONE        ,    0 },
8290 };
8291 
8292 static const AVCodecTag codec_ipod_tags[] = {
8293     { AV_CODEC_ID_H264,     MKTAG('a','v','c','1') },
8294     { AV_CODEC_ID_MPEG4,    MKTAG('m','p','4','v') },
8295     { AV_CODEC_ID_AAC,      MKTAG('m','p','4','a') },
8296     { AV_CODEC_ID_ALAC,     MKTAG('a','l','a','c') },
8297     { AV_CODEC_ID_AC3,      MKTAG('a','c','-','3') },
8298     { AV_CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') },
8299     { AV_CODEC_ID_MOV_TEXT, MKTAG('t','e','x','t') },
8300     { AV_CODEC_ID_NONE, 0 },
8301 };
8302 
8303 static const AVCodecTag codec_f4v_tags[] = {
8304     { AV_CODEC_ID_MP3,    MKTAG('.','m','p','3') },
8305     { AV_CODEC_ID_AAC,    MKTAG('m','p','4','a') },
8306     { AV_CODEC_ID_H264,   MKTAG('a','v','c','1') },
8307     { AV_CODEC_ID_VP6A,   MKTAG('V','P','6','A') },
8308     { AV_CODEC_ID_VP6F,   MKTAG('V','P','6','F') },
8309     { AV_CODEC_ID_NONE, 0 },
8310 };
8311 
8312 #if CONFIG_AVIF_MUXER
8313 static const AVCodecTag codec_avif_tags[] = {
8314     { AV_CODEC_ID_AV1,     MKTAG('a','v','0','1') },
8315     { AV_CODEC_ID_NONE, 0 },
8316 };
8317 static const AVCodecTag *const codec_avif_tags_list[] = { codec_avif_tags, NULL };
8318 
8319 static const AVClass mov_avif_muxer_class = {
8320     .class_name = "avif muxer",
8321     .item_name  = av_default_item_name,
8322     .version    = LIBAVUTIL_VERSION_INT,
8323 };
8324 #endif
8325 
8326 #if CONFIG_MOV_MUXER
8327 const AVOutputFormat ff_mov_muxer = {
8328     .name              = "mov",
8329     .long_name         = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
8330     .extensions        = "mov",
8331     .priv_data_size    = sizeof(MOVMuxContext),
8332     .audio_codec       = AV_CODEC_ID_AAC,
8333     .video_codec       = CONFIG_LIBX264_ENCODER ?
8334                          AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4,
8335     .init              = mov_init,
8336     .write_header      = mov_write_header,
8337     .write_packet      = mov_write_packet,
8338     .write_trailer     = mov_write_trailer,
8339     .deinit            = mov_free,
8340     .flags             = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
8341     .codec_tag         = (const AVCodecTag* const []){
8342         ff_codec_movvideo_tags, ff_codec_movaudio_tags, ff_codec_movsubtitle_tags, 0
8343     },
8344     .check_bitstream   = mov_check_bitstream,
8345     .priv_class        = &mov_isobmff_muxer_class,
8346 };
8347 #endif
8348 #if CONFIG_TGP_MUXER
8349 const AVOutputFormat ff_tgp_muxer = {
8350     .name              = "3gp",
8351     .long_name         = NULL_IF_CONFIG_SMALL("3GP (3GPP file format)"),
8352     .extensions        = "3gp",
8353     .priv_data_size    = sizeof(MOVMuxContext),
8354     .audio_codec       = AV_CODEC_ID_AMR_NB,
8355     .video_codec       = AV_CODEC_ID_H263,
8356     .init              = mov_init,
8357     .write_header      = mov_write_header,
8358     .write_packet      = mov_write_packet,
8359     .write_trailer     = mov_write_trailer,
8360     .deinit            = mov_free,
8361     .flags             = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
8362     .codec_tag         = codec_3gp_tags_list,
8363     .check_bitstream   = mov_check_bitstream,
8364     .priv_class        = &mov_isobmff_muxer_class,
8365 };
8366 #endif
8367 #if CONFIG_MP4_MUXER
8368 const AVOutputFormat ff_mp4_muxer = {
8369     .name              = "mp4",
8370     .long_name         = NULL_IF_CONFIG_SMALL("MP4 (MPEG-4 Part 14)"),
8371     .mime_type         = "video/mp4",
8372     .extensions        = "mp4",
8373     .priv_data_size    = sizeof(MOVMuxContext),
8374     .audio_codec       = AV_CODEC_ID_AAC,
8375     .video_codec       = CONFIG_LIBX264_ENCODER ?
8376                          AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4,
8377     .init              = mov_init,
8378     .write_header      = mov_write_header,
8379     .write_packet      = mov_write_packet,
8380     .write_trailer     = mov_write_trailer,
8381     .deinit            = mov_free,
8382     .flags             = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
8383     .codec_tag         = mp4_codec_tags_list,
8384     .check_bitstream   = mov_check_bitstream,
8385     .priv_class        = &mov_isobmff_muxer_class,
8386 };
8387 #endif
8388 #if CONFIG_PSP_MUXER
8389 const AVOutputFormat ff_psp_muxer = {
8390     .name              = "psp",
8391     .long_name         = NULL_IF_CONFIG_SMALL("PSP MP4 (MPEG-4 Part 14)"),
8392     .extensions        = "mp4,psp",
8393     .priv_data_size    = sizeof(MOVMuxContext),
8394     .audio_codec       = AV_CODEC_ID_AAC,
8395     .video_codec       = CONFIG_LIBX264_ENCODER ?
8396                          AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4,
8397     .init              = mov_init,
8398     .write_header      = mov_write_header,
8399     .write_packet      = mov_write_packet,
8400     .write_trailer     = mov_write_trailer,
8401     .deinit            = mov_free,
8402     .flags             = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
8403     .codec_tag         = mp4_codec_tags_list,
8404     .check_bitstream   = mov_check_bitstream,
8405     .priv_class        = &mov_isobmff_muxer_class,
8406 };
8407 #endif
8408 #if CONFIG_TG2_MUXER
8409 const AVOutputFormat ff_tg2_muxer = {
8410     .name              = "3g2",
8411     .long_name         = NULL_IF_CONFIG_SMALL("3GP2 (3GPP2 file format)"),
8412     .extensions        = "3g2",
8413     .priv_data_size    = sizeof(MOVMuxContext),
8414     .audio_codec       = AV_CODEC_ID_AMR_NB,
8415     .video_codec       = AV_CODEC_ID_H263,
8416     .init              = mov_init,
8417     .write_header      = mov_write_header,
8418     .write_packet      = mov_write_packet,
8419     .write_trailer     = mov_write_trailer,
8420     .deinit            = mov_free,
8421     .flags             = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
8422     .codec_tag         = codec_3gp_tags_list,
8423     .check_bitstream   = mov_check_bitstream,
8424     .priv_class        = &mov_isobmff_muxer_class,
8425 };
8426 #endif
8427 #if CONFIG_IPOD_MUXER
8428 const AVOutputFormat ff_ipod_muxer = {
8429     .name              = "ipod",
8430     .long_name         = NULL_IF_CONFIG_SMALL("iPod H.264 MP4 (MPEG-4 Part 14)"),
8431     .mime_type         = "video/mp4",
8432     .extensions        = "m4v,m4a,m4b",
8433     .priv_data_size    = sizeof(MOVMuxContext),
8434     .audio_codec       = AV_CODEC_ID_AAC,
8435     .video_codec       = AV_CODEC_ID_H264,
8436     .init              = mov_init,
8437     .write_header      = mov_write_header,
8438     .write_packet      = mov_write_packet,
8439     .write_trailer     = mov_write_trailer,
8440     .deinit            = mov_free,
8441     .flags             = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
8442     .codec_tag         = (const AVCodecTag* const []){ codec_ipod_tags, 0 },
8443     .check_bitstream   = mov_check_bitstream,
8444     .priv_class        = &mov_isobmff_muxer_class,
8445 };
8446 #endif
8447 #if CONFIG_ISMV_MUXER
8448 const AVOutputFormat ff_ismv_muxer = {
8449     .name              = "ismv",
8450     .long_name         = NULL_IF_CONFIG_SMALL("ISMV/ISMA (Smooth Streaming)"),
8451     .mime_type         = "video/mp4",
8452     .extensions        = "ismv,isma",
8453     .priv_data_size    = sizeof(MOVMuxContext),
8454     .audio_codec       = AV_CODEC_ID_AAC,
8455     .video_codec       = AV_CODEC_ID_H264,
8456     .init              = mov_init,
8457     .write_header      = mov_write_header,
8458     .write_packet      = mov_write_packet,
8459     .write_trailer     = mov_write_trailer,
8460     .deinit            = mov_free,
8461     .flags             = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
8462     .codec_tag         = (const AVCodecTag* const []){
8463         codec_mp4_tags, codec_ism_tags, 0 },
8464     .check_bitstream   = mov_check_bitstream,
8465     .priv_class        = &mov_isobmff_muxer_class,
8466 };
8467 #endif
8468 #if CONFIG_F4V_MUXER
8469 const AVOutputFormat ff_f4v_muxer = {
8470     .name              = "f4v",
8471     .long_name         = NULL_IF_CONFIG_SMALL("F4V Adobe Flash Video"),
8472     .mime_type         = "application/f4v",
8473     .extensions        = "f4v",
8474     .priv_data_size    = sizeof(MOVMuxContext),
8475     .audio_codec       = AV_CODEC_ID_AAC,
8476     .video_codec       = AV_CODEC_ID_H264,
8477     .init              = mov_init,
8478     .write_header      = mov_write_header,
8479     .write_packet      = mov_write_packet,
8480     .write_trailer     = mov_write_trailer,
8481     .deinit            = mov_free,
8482     .flags             = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH,
8483     .codec_tag         = (const AVCodecTag* const []){ codec_f4v_tags, 0 },
8484     .check_bitstream   = mov_check_bitstream,
8485     .priv_class        = &mov_isobmff_muxer_class,
8486 };
8487 #endif
8488 #if CONFIG_AVIF_MUXER
8489 const AVOutputFormat ff_avif_muxer = {
8490     .name              = "avif",
8491     .long_name         = NULL_IF_CONFIG_SMALL("AVIF"),
8492     .mime_type         = "image/avif",
8493     .extensions        = "avif",
8494     .priv_data_size    = sizeof(MOVMuxContext),
8495     .video_codec       = AV_CODEC_ID_AV1,
8496     .init              = mov_init,
8497     .write_header      = mov_write_header,
8498     .write_packet      = mov_write_packet,
8499     .write_trailer     = avif_write_trailer,
8500     .deinit            = mov_free,
8501     .flags             = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH,
8502     .codec_tag         = codec_avif_tags_list,
8503     .priv_class        = &mov_avif_muxer_class,
8504 };
8505 #endif
8506