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