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