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