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