FFmpeg
movenc.c
Go to the documentation of this file.
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"
41 #include "libavcodec/dnxhddata.h"
42 #include "libavcodec/flac.h"
43 #include "libavcodec/get_bits.h"
44 
45 #include "libavcodec/internal.h"
46 #include "libavcodec/put_bits.h"
47 #include "libavcodec/vc1_common.h"
48 #include "libavcodec/raw.h"
49 #include "internal.h"
50 #include "libavutil/avstring.h"
52 #include "libavutil/csp.h"
53 #include "libavutil/intfloat.h"
54 #include "libavutil/mathematics.h"
55 #include "libavutil/libm.h"
56 #include "libavutil/mem.h"
57 #include "libavutil/opt.h"
58 #include "libavutil/dict.h"
59 #include "libavutil/pixdesc.h"
60 #include "libavutil/stereo3d.h"
61 #include "libavutil/timecode.h"
62 #include "libavutil/dovi_meta.h"
63 #include "libavutil/uuid.h"
64 #include "hevc.h"
65 #include "rtpenc.h"
66 #include "nal.h"
67 #include "mov_chan.h"
68 #include "movenc_ttml.h"
69 #include "mux.h"
70 #include "rawutils.h"
71 #include "ttmlenc.h"
72 #include "version.h"
73 #include "vpcc.h"
74 #include "vvc.h"
75 
76 static const AVOption options[] = {
77  { "brand", "Override major brand", offsetof(MOVMuxContext, major_brand), AV_OPT_TYPE_STRING, {.str = NULL}, .flags = AV_OPT_FLAG_ENCODING_PARAM },
78  { "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},
79  { "encryption_key", "The media encryption key (hex)", offsetof(MOVMuxContext, encryption_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_ENCODING_PARAM },
80  { "encryption_kid", "The media encryption key identifier (hex)", offsetof(MOVMuxContext, encryption_kid), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_ENCODING_PARAM },
81  { "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 },
82  { "frag_duration", "Maximum fragment duration", offsetof(MOVMuxContext, max_fragment_duration), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
83  { "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 },
84  { "frag_size", "Maximum fragment size", offsetof(MOVMuxContext, max_fragment_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
85  { "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},
86  { "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},
87  { "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},
88  { "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},
89  { "movflags", "MOV muxer flags", offsetof(MOVMuxContext, flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, .unit = "movflags" },
90  { "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" },
91  { "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" },
92  { "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" },
93  { "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" },
94  { "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" },
95  { "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" },
96  { "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" },
97  { "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" },
98  { "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" },
99  { "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" },
100  { "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" },
101  { "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" },
102  { "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" },
103  { "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 },
104  { "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" },
105  { "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" },
106  { "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" },
107  { "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" },
108  { "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" },
109  { "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" },
110  { "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" },
111  { "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" },
112  { "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" },
113  { "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" },
114  { "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" },
115  { "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},
116  { "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},
117  { "movie_timescale", "set movie timescale", offsetof(MOVMuxContext, movie_timescale), AV_OPT_TYPE_INT, {.i64 = MOV_TIMESCALE}, 1, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
118  FF_RTP_FLAG_OPTS(MOVMuxContext, rtp_flags),
119  { "skip_iods", "Skip writing iods atom.", offsetof(MOVMuxContext, iods_skip), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
120  { "use_editlist", "use edit list", offsetof(MOVMuxContext, use_editlist), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM},
121  { "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},
122  { "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},
123  { "write_btrt", "force or disable writing btrt", offsetof(MOVMuxContext, write_btrt), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM},
124  { "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"},
125  { "pts", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = MOV_PRFT_SRC_PTS}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM, .unit = "prft"},
126  { "wallclock", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = MOV_PRFT_SRC_WALLCLOCK}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM, .unit = "prft"},
127  { "write_tmcd", "force or disable writing tmcd", offsetof(MOVMuxContext, write_tmcd), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM},
128  { NULL },
129 };
130 
132  .class_name = "mov/mp4/tgp/psp/tg2/ipod/ismv/f4v muxer",
133  .item_name = av_default_item_name,
134  .option = options,
135  .version = LIBAVUTIL_VERSION_INT,
136 };
137 
138 static int get_moov_size(AVFormatContext *s);
140 
141 static int utf8len(const uint8_t *b)
142 {
143  int len = 0;
144  int val;
145  while (*b) {
146  GET_UTF8(val, *b++, return -1;)
147  len++;
148  }
149  return len;
150 }
151 
152 //FIXME support 64 bit variant with wide placeholders
154 {
155  int64_t curpos = avio_tell(pb);
156  avio_seek(pb, pos, SEEK_SET);
157  avio_wb32(pb, curpos - pos); /* rewrite size */
158  avio_seek(pb, curpos, SEEK_SET);
159 
160  return curpos - pos;
161 }
162 
163 static int co64_required(const MOVTrack *track)
164 {
165  if (track->entry > 0 && track->cluster[track->entry - 1].pos + track->data_offset > UINT32_MAX)
166  return 1;
167  return 0;
168 }
169 
170 static int is_cover_image(const AVStream *st)
171 {
172  /* Eg. AV_DISPOSITION_ATTACHED_PIC | AV_DISPOSITION_TIMED_THUMBNAILS
173  * is encoded as sparse video track */
174  return st && st->disposition == AV_DISPOSITION_ATTACHED_PIC;
175 }
176 
177 static int rtp_hinting_needed(const AVStream *st)
178 {
179  /* Add hint tracks for each real audio and video stream */
180  if (is_cover_image(st))
181  return 0;
182  return st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ||
184 }
185 
186 /* Chunk offset atom */
187 static int mov_write_stco_tag(AVIOContext *pb, MOVTrack *track)
188 {
189  int i;
190  int mode64 = co64_required(track); // use 32 bit size variant if possible
191  int64_t pos = avio_tell(pb);
192  avio_wb32(pb, 0); /* size */
193  if (mode64)
194  ffio_wfourcc(pb, "co64");
195  else
196  ffio_wfourcc(pb, "stco");
197  avio_wb32(pb, 0); /* version & flags */
198  avio_wb32(pb, track->chunkCount); /* entry count */
199  for (i = 0; i < track->entry; i++) {
200  if (!track->cluster[i].chunkNum)
201  continue;
202  if (mode64 == 1)
203  avio_wb64(pb, track->cluster[i].pos + track->data_offset);
204  else
205  avio_wb32(pb, track->cluster[i].pos + track->data_offset);
206  }
207  return update_size(pb, pos);
208 }
209 
210 /* Sample size atom */
211 static int mov_write_stsz_tag(AVIOContext *pb, MOVTrack *track)
212 {
213  int equalChunks = 1;
214  int i, j, entries = 0, tst = -1, oldtst = -1;
215 
216  int64_t pos = avio_tell(pb);
217  avio_wb32(pb, 0); /* size */
218  ffio_wfourcc(pb, "stsz");
219  avio_wb32(pb, 0); /* version & flags */
220 
221  for (i = 0; i < track->entry; i++) {
222  tst = track->cluster[i].size / track->cluster[i].entries;
223  if (oldtst != -1 && tst != oldtst)
224  equalChunks = 0;
225  oldtst = tst;
226  entries += track->cluster[i].entries;
227  }
228  if (equalChunks && track->entry) {
229  int sSize = track->entry ? track->cluster[0].size / track->cluster[0].entries : 0;
230  sSize = FFMAX(1, sSize); // adpcm mono case could make sSize == 0
231  avio_wb32(pb, sSize); // sample size
232  avio_wb32(pb, entries); // sample count
233  } else {
234  avio_wb32(pb, 0); // sample size
235  avio_wb32(pb, entries); // sample count
236  for (i = 0; i < track->entry; i++) {
237  for (j = 0; j < track->cluster[i].entries; j++) {
238  avio_wb32(pb, track->cluster[i].size /
239  track->cluster[i].entries);
240  }
241  }
242  }
243  return update_size(pb, pos);
244 }
245 
246 /* Sample to chunk atom */
247 static int mov_write_stsc_tag(AVIOContext *pb, MOVTrack *track)
248 {
249  int index = 0, oldval = -1, i;
250  int64_t entryPos, curpos;
251 
252  int64_t pos = avio_tell(pb);
253  avio_wb32(pb, 0); /* size */
254  ffio_wfourcc(pb, "stsc");
255  avio_wb32(pb, 0); // version & flags
256  entryPos = avio_tell(pb);
257  avio_wb32(pb, track->chunkCount); // entry count
258  for (i = 0; i < track->entry; i++) {
259  if (oldval != track->cluster[i].samples_in_chunk && track->cluster[i].chunkNum) {
260  avio_wb32(pb, track->cluster[i].chunkNum); // first chunk
261  avio_wb32(pb, track->cluster[i].samples_in_chunk); // samples per chunk
262  avio_wb32(pb, 0x1); // sample description index
263  oldval = track->cluster[i].samples_in_chunk;
264  index++;
265  }
266  }
267  curpos = avio_tell(pb);
268  avio_seek(pb, entryPos, SEEK_SET);
269  avio_wb32(pb, index); // rewrite size
270  avio_seek(pb, curpos, SEEK_SET);
271 
272  return update_size(pb, pos);
273 }
274 
275 /* Sync sample atom */
276 static int mov_write_stss_tag(AVIOContext *pb, MOVTrack *track, uint32_t flag)
277 {
278  int64_t curpos, entryPos;
279  int i, index = 0;
280  int64_t pos = avio_tell(pb);
281  avio_wb32(pb, 0); // size
282  ffio_wfourcc(pb, flag == MOV_SYNC_SAMPLE ? "stss" : "stps");
283  avio_wb32(pb, 0); // version & flags
284  entryPos = avio_tell(pb);
285  avio_wb32(pb, track->entry); // entry count
286  for (i = 0; i < track->entry; i++) {
287  if (track->cluster[i].flags & flag) {
288  avio_wb32(pb, i + 1);
289  index++;
290  }
291  }
292  curpos = avio_tell(pb);
293  avio_seek(pb, entryPos, SEEK_SET);
294  avio_wb32(pb, index); // rewrite size
295  avio_seek(pb, curpos, SEEK_SET);
296  return update_size(pb, pos);
297 }
298 
299 /* Sample dependency atom */
300 static int mov_write_sdtp_tag(AVIOContext *pb, MOVTrack *track)
301 {
302  int i;
303  uint8_t leading, dependent, reference, redundancy;
304  int64_t pos = avio_tell(pb);
305  avio_wb32(pb, 0); // size
306  ffio_wfourcc(pb, "sdtp");
307  avio_wb32(pb, 0); // version & flags
308  for (i = 0; i < track->entry; i++) {
309  dependent = MOV_SAMPLE_DEPENDENCY_YES;
310  leading = reference = redundancy = MOV_SAMPLE_DEPENDENCY_UNKNOWN;
311  if (track->cluster[i].flags & MOV_DISPOSABLE_SAMPLE) {
312  reference = MOV_SAMPLE_DEPENDENCY_NO;
313  }
314  if (track->cluster[i].flags & MOV_SYNC_SAMPLE) {
315  dependent = MOV_SAMPLE_DEPENDENCY_NO;
316  }
317  avio_w8(pb, (leading << 6) | (dependent << 4) |
318  (reference << 2) | redundancy);
319  }
320  return update_size(pb, pos);
321 }
322 
323 #if CONFIG_IAMFENC
324 static int mov_write_iacb_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
325 {
326  AVIOContext *dyn_bc;
327  int64_t pos = avio_tell(pb);
328  uint8_t *dyn_buf = NULL;
329  int dyn_size;
330  int ret = avio_open_dyn_buf(&dyn_bc);
331  if (ret < 0)
332  return ret;
333 
334  avio_wb32(pb, 0);
335  ffio_wfourcc(pb, "iacb");
336  avio_w8(pb, 1); // configurationVersion
337 
338  ret = ff_iamf_write_descriptors(track->iamf, dyn_bc, s);
339  if (ret < 0)
340  return ret;
341 
342  dyn_size = avio_close_dyn_buf(dyn_bc, &dyn_buf);
343  ffio_write_leb(pb, dyn_size);
344  avio_write(pb, dyn_buf, dyn_size);
345  av_free(dyn_buf);
346 
347  return update_size(pb, pos);
348 }
349 #endif
350 
351 static int mov_write_amr_tag(AVIOContext *pb, MOVTrack *track)
352 {
353  avio_wb32(pb, 0x11); /* size */
354  if (track->mode == MODE_MOV) ffio_wfourcc(pb, "samr");
355  else ffio_wfourcc(pb, "damr");
356  ffio_wfourcc(pb, "FFMP");
357  avio_w8(pb, 0); /* decoder version */
358 
359  avio_wb16(pb, 0x81FF); /* Mode set (all modes for AMR_NB) */
360  avio_w8(pb, 0x00); /* Mode change period (no restriction) */
361  avio_w8(pb, 0x01); /* Frames per sample */
362  return 0x11;
363 }
364 
365 struct eac3_info {
367  uint8_t ec3_done;
368  uint8_t num_blocks;
369 
370  /* Layout of the EC3SpecificBox */
371  /* maximum bitrate */
372  uint16_t data_rate;
374  /* number of independent substreams */
375  uint8_t num_ind_sub;
376  struct {
377  /* sample rate code (see ff_ac3_sample_rate_tab) 2 bits */
378  uint8_t fscod;
379  /* bit stream identification 5 bits */
380  uint8_t bsid;
381  /* one bit reserved */
382  /* audio service mixing (not supported yet) 1 bit */
383  /* bit stream mode 3 bits */
384  uint8_t bsmod;
385  /* audio coding mode 3 bits */
386  uint8_t acmod;
387  /* sub woofer on 1 bit */
388  uint8_t lfeon;
389  /* 3 bits reserved */
390  /* number of dependent substreams associated with this substream 4 bits */
391  uint8_t num_dep_sub;
392  /* channel locations of the dependent substream(s), if any, 9 bits */
393  uint16_t chan_loc;
394  /* if there is no dependent substream, then one bit reserved instead */
395  } substream[1]; /* TODO: support 8 independent substreams */
396 };
397 
399 {
400  struct eac3_info *info = track->eac3_priv;
401  PutBitContext pbc;
402  uint8_t buf[3];
403 
404  if (!info || !info->ec3_done) {
406  "Cannot write moov atom before AC3 packets."
407  " Set the delay_moov flag to fix this.\n");
408  return AVERROR(EINVAL);
409  }
410 
411  if (info->substream[0].bsid > 8) {
413  "RealAudio AC-3/DolbyNet with bsid %d is not defined by the "
414  "ISOBMFF specification in ETSI TS 102 366!\n",
415  info->substream[0].bsid);
416  return AVERROR(EINVAL);
417  }
418 
419  if (info->ac3_bit_rate_code < 0) {
421  "No valid AC3 bit rate code for data rate of %d!\n",
422  info->data_rate);
423  return AVERROR(EINVAL);
424  }
425 
426  avio_wb32(pb, 11);
427  ffio_wfourcc(pb, "dac3");
428 
429  init_put_bits(&pbc, buf, sizeof(buf));
430  put_bits(&pbc, 2, info->substream[0].fscod);
431  put_bits(&pbc, 5, info->substream[0].bsid);
432  put_bits(&pbc, 3, info->substream[0].bsmod);
433  put_bits(&pbc, 3, info->substream[0].acmod);
434  put_bits(&pbc, 1, info->substream[0].lfeon);
435  put_bits(&pbc, 5, info->ac3_bit_rate_code); // bit_rate_code
436  put_bits(&pbc, 5, 0); // reserved
437 
438  flush_put_bits(&pbc);
439  avio_write(pb, buf, sizeof(buf));
440 
441  return 11;
442 }
443 
444 static int handle_eac3(MOVMuxContext *mov, AVPacket *pkt, MOVTrack *track)
445 {
446  AC3HeaderInfo *hdr = NULL;
447  struct eac3_info *info;
448  int num_blocks, ret;
449 
450  if (!track->eac3_priv) {
451  if (!(track->eac3_priv = av_mallocz(sizeof(*info))))
452  return AVERROR(ENOMEM);
453 
454  ((struct eac3_info *)track->eac3_priv)->ac3_bit_rate_code = -1;
455  }
456  info = track->eac3_priv;
457 
458  if (!info->pkt && !(info->pkt = av_packet_alloc()))
459  return AVERROR(ENOMEM);
460 
461  if ((ret = avpriv_ac3_parse_header(&hdr, pkt->data, pkt->size)) < 0) {
462  if (ret == AVERROR(ENOMEM))
463  goto end;
464 
465  /* drop the packets until we see a good one */
466  if (!track->entry) {
467  av_log(mov->fc, AV_LOG_WARNING, "Dropping invalid packet from start of the stream\n");
468  ret = 0;
469  } else
471  goto end;
472  }
473 
474  info->data_rate = FFMAX(info->data_rate, hdr->bit_rate / 1000);
475  info->ac3_bit_rate_code = FFMAX(info->ac3_bit_rate_code,
476  hdr->ac3_bit_rate_code);
477  num_blocks = hdr->num_blocks;
478 
479  if (!info->ec3_done) {
480  /* AC-3 substream must be the first one */
481  if (hdr->bitstream_id <= 10 && hdr->substreamid != 0) {
482  ret = AVERROR(EINVAL);
483  goto end;
484  }
485 
486  /* this should always be the case, given that our AC-3 parser
487  * concatenates dependent frames to their independent parent */
490  /* substream ids must be incremental */
491  if (hdr->substreamid > info->num_ind_sub + 1) {
492  ret = AVERROR(EINVAL);
493  goto end;
494  }
495 
496  if (hdr->substreamid == info->num_ind_sub + 1) {
497  //info->num_ind_sub++;
498  avpriv_request_sample(mov->fc, "Multiple independent substreams");
500  goto end;
501  } else if (hdr->substreamid < info->num_ind_sub ||
502  hdr->substreamid == 0 && info->substream[0].bsid) {
503  info->ec3_done = 1;
504  goto concatenate;
505  }
506  } else {
507  if (hdr->substreamid != 0) {
508  avpriv_request_sample(mov->fc, "Multiple non EAC3 independent substreams");
510  goto end;
511  }
512  }
513 
514  /* fill the info needed for the "dec3" atom */
515  info->substream[hdr->substreamid].fscod = hdr->sr_code;
516  info->substream[hdr->substreamid].bsid = hdr->bitstream_id;
517  info->substream[hdr->substreamid].bsmod = hdr->bitstream_mode;
518  info->substream[hdr->substreamid].acmod = hdr->channel_mode;
519  info->substream[hdr->substreamid].lfeon = hdr->lfe_on;
520 
521  if (track->par->codec_id == AV_CODEC_ID_AC3) {
522  // with AC-3 we only require the information of a single packet,
523  // so we can finish as soon as the basic values of the bit stream
524  // have been set to the track's informational structure.
525  info->ec3_done = 1;
526  goto concatenate;
527  }
528 
529  /* Parse dependent substream(s), if any */
530  if (pkt->size != hdr->frame_size) {
531  int cumul_size = hdr->frame_size;
532  int parent = hdr->substreamid;
533 
534  while (cumul_size != pkt->size) {
535  GetBitContext gbc;
536  int i;
537  ret = avpriv_ac3_parse_header(&hdr, pkt->data + cumul_size, pkt->size - cumul_size);
538  if (ret < 0)
539  goto end;
541  ret = AVERROR(EINVAL);
542  goto end;
543  }
544  info->substream[parent].num_dep_sub++;
545  ret /= 8;
546 
547  /* header is parsed up to lfeon, but custom channel map may be needed */
548  init_get_bits8(&gbc, pkt->data + cumul_size + ret, pkt->size - cumul_size - ret);
549  /* skip bsid */
550  skip_bits(&gbc, 5);
551  /* skip volume control params */
552  for (i = 0; i < (hdr->channel_mode ? 1 : 2); i++) {
553  skip_bits(&gbc, 5); // skip dialog normalization
554  if (get_bits1(&gbc)) {
555  skip_bits(&gbc, 8); // skip compression gain word
556  }
557  }
558  /* get the dependent stream channel map, if exists */
559  if (get_bits1(&gbc))
560  info->substream[parent].chan_loc |= (get_bits(&gbc, 16) >> 5) & 0x1f;
561  else
562  info->substream[parent].chan_loc |= hdr->channel_mode;
563  cumul_size += hdr->frame_size;
564  }
565  }
566  }
567 
568 concatenate:
569  if (!info->num_blocks && num_blocks == 6) {
570  ret = pkt->size;
571  goto end;
572  }
573  else if (info->num_blocks + num_blocks > 6) {
575  goto end;
576  }
577 
578  if (!info->num_blocks) {
579  ret = av_packet_ref(info->pkt, pkt);
580  if (!ret)
581  info->num_blocks = num_blocks;
582  goto end;
583  } else {
584  if ((ret = av_grow_packet(info->pkt, pkt->size)) < 0)
585  goto end;
586  memcpy(info->pkt->data + info->pkt->size - pkt->size, pkt->data, pkt->size);
587  info->num_blocks += num_blocks;
588  info->pkt->duration += pkt->duration;
589  if (info->num_blocks != 6)
590  goto end;
592  av_packet_move_ref(pkt, info->pkt);
593  info->num_blocks = 0;
594  }
595  ret = pkt->size;
596 
597 end:
598  av_free(hdr);
599 
600  return ret;
601 }
602 
604 {
605  PutBitContext pbc;
606  uint8_t *buf;
607  struct eac3_info *info;
608  int size, i;
609 
610  if (!track->eac3_priv) {
612  "Cannot write moov atom before EAC3 packets parsed.\n");
613  return AVERROR(EINVAL);
614  }
615 
616  info = track->eac3_priv;
617  size = 2 + ((34 * (info->num_ind_sub + 1) + 7) >> 3);
618  buf = av_malloc(size);
619  if (!buf) {
620  return AVERROR(ENOMEM);
621  }
622 
623  init_put_bits(&pbc, buf, size);
624  put_bits(&pbc, 13, info->data_rate);
625  put_bits(&pbc, 3, info->num_ind_sub);
626  for (i = 0; i <= info->num_ind_sub; i++) {
627  put_bits(&pbc, 2, info->substream[i].fscod);
628  put_bits(&pbc, 5, info->substream[i].bsid);
629  put_bits(&pbc, 1, 0); /* reserved */
630  put_bits(&pbc, 1, 0); /* asvc */
631  put_bits(&pbc, 3, info->substream[i].bsmod);
632  put_bits(&pbc, 3, info->substream[i].acmod);
633  put_bits(&pbc, 1, info->substream[i].lfeon);
634  put_bits(&pbc, 5, 0); /* reserved */
635  put_bits(&pbc, 4, info->substream[i].num_dep_sub);
636  if (!info->substream[i].num_dep_sub) {
637  put_bits(&pbc, 1, 0); /* reserved */
638  } else {
639  put_bits(&pbc, 9, info->substream[i].chan_loc);
640  }
641  }
642  flush_put_bits(&pbc);
643  size = put_bytes_output(&pbc);
644 
645  avio_wb32(pb, size + 8);
646  ffio_wfourcc(pb, "dec3");
647  avio_write(pb, buf, size);
648 
649  av_free(buf);
650 
651  return size;
652 }
653 
654 /**
655  * This function writes extradata "as is".
656  * Extradata must be formatted like a valid atom (with size and tag).
657  */
659 {
660  avio_write(pb, track->par->extradata, track->par->extradata_size);
661  return track->par->extradata_size;
662 }
663 
665 {
666  avio_wb32(pb, 10);
667  ffio_wfourcc(pb, "enda");
668  avio_wb16(pb, 1); /* little endian */
669  return 10;
670 }
671 
673 {
674  avio_wb32(pb, 10);
675  ffio_wfourcc(pb, "enda");
676  avio_wb16(pb, 0); /* big endian */
677  return 10;
678 }
679 
680 static void put_descr(AVIOContext *pb, int tag, unsigned int size)
681 {
682  int i = 3;
683  avio_w8(pb, tag);
684  for (; i > 0; i--)
685  avio_w8(pb, (size >> (7 * i)) | 0x80);
686  avio_w8(pb, size & 0x7F);
687 }
688 
689 static unsigned compute_avg_bitrate(MOVTrack *track)
690 {
691  uint64_t size = 0;
692  int i;
693  if (!track->track_duration)
694  return 0;
695  for (i = 0; i < track->entry; i++)
696  size += track->cluster[i].size;
697  return size * 8 * track->timescale / track->track_duration;
698 }
699 
701  uint32_t buffer_size; ///< Size of the decoding buffer for the elementary stream in bytes.
702  uint32_t max_bit_rate; ///< Maximum rate in bits/second over any window of one second.
703  uint32_t avg_bit_rate; ///< Average rate in bits/second over the entire presentation.
704 };
705 
707 {
708  const AVPacketSideData *sd = track->st ?
710  track->st->codecpar->nb_coded_side_data,
712  AVCPBProperties *props = sd ? (AVCPBProperties *)sd->data : NULL;
713  struct mpeg4_bit_rate_values bit_rates = { 0 };
714 
715  bit_rates.avg_bit_rate = compute_avg_bitrate(track);
716  if (!bit_rates.avg_bit_rate) {
717  // if the average bit rate cannot be calculated at this point, such as
718  // in the case of fragmented MP4, utilize the following values as
719  // fall-back in priority order:
720  //
721  // 1. average bit rate property
722  // 2. bit rate (usually average over the whole clip)
723  // 3. maximum bit rate property
724 
725  if (props && props->avg_bitrate) {
726  bit_rates.avg_bit_rate = props->avg_bitrate;
727  } else if (track->par->bit_rate) {
728  bit_rates.avg_bit_rate = track->par->bit_rate;
729  } else if (props && props->max_bitrate) {
730  bit_rates.avg_bit_rate = props->max_bitrate;
731  }
732  }
733 
734  // (FIXME should be max rate in any 1 sec window)
735  bit_rates.max_bit_rate = FFMAX(track->par->bit_rate,
736  bit_rates.avg_bit_rate);
737 
738  // utilize values from properties if we have them available
739  if (props) {
740  bit_rates.max_bit_rate = FFMAX(bit_rates.max_bit_rate,
741  props->max_bitrate);
742  bit_rates.buffer_size = props->buffer_size / 8;
743  }
744 
745  return bit_rates;
746 }
747 
748 static int mov_write_esds_tag(AVIOContext *pb, MOVTrack *track) // Basic
749 {
750  struct mpeg4_bit_rate_values bit_rates = calculate_mpeg4_bit_rates(track);
751  int64_t pos = avio_tell(pb);
752  int decoder_specific_info_len = track->vos_len ? 5 + track->vos_len : 0;
753 
754  avio_wb32(pb, 0); // size
755  ffio_wfourcc(pb, "esds");
756  avio_wb32(pb, 0); // Version
757 
758  // ES descriptor
759  put_descr(pb, 0x03, 3 + 5+13 + decoder_specific_info_len + 5+1);
760  avio_wb16(pb, track->track_id);
761  avio_w8(pb, 0x00); // flags (= no flags)
762 
763  // DecoderConfig descriptor
764  put_descr(pb, 0x04, 13 + decoder_specific_info_len);
765 
766  // Object type indication
767  if ((track->par->codec_id == AV_CODEC_ID_MP2 ||
768  track->par->codec_id == AV_CODEC_ID_MP3) &&
769  track->par->sample_rate > 24000)
770  avio_w8(pb, 0x6B); // 11172-3
771  else
773 
774  // the following fields is made of 6 bits to identify the streamtype (4 for video, 5 for audio)
775  // plus 1 bit to indicate upstream and 1 bit set to 1 (reserved)
776  if (track->par->codec_id == AV_CODEC_ID_DVD_SUBTITLE)
777  avio_w8(pb, (0x38 << 2) | 1); // flags (= NeroSubpicStream)
778  else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO)
779  avio_w8(pb, 0x15); // flags (= Audiostream)
780  else
781  avio_w8(pb, 0x11); // flags (= Visualstream)
782 
783  avio_wb24(pb, bit_rates.buffer_size); // Buffersize DB
784  avio_wb32(pb, bit_rates.max_bit_rate); // maxbitrate
785  avio_wb32(pb, bit_rates.avg_bit_rate);
786 
787  if (track->vos_len) {
788  // DecoderSpecific info descriptor
789  put_descr(pb, 0x05, track->vos_len);
790  avio_write(pb, track->vos_data, track->vos_len);
791  }
792 
793  // SL descriptor
794  put_descr(pb, 0x06, 1);
795  avio_w8(pb, 0x02);
796  return update_size(pb, pos);
797 }
798 
800 {
801  return codec_id == AV_CODEC_ID_PCM_S24LE ||
805 }
806 
808 {
809  return codec_id == AV_CODEC_ID_PCM_S24BE ||
813 }
814 
816 {
817  int ret;
818  int64_t pos = avio_tell(pb);
819  avio_wb32(pb, 0);
820  avio_wl32(pb, track->tag); // store it byteswapped
821  track->par->codec_tag = av_bswap16(track->tag >> 16);
822  if ((ret = ff_put_wav_header(s, pb, track->par, 0)) < 0)
823  return ret;
824  return update_size(pb, pos);
825 }
826 
828 {
829  int ret;
830  int64_t pos = avio_tell(pb);
831  avio_wb32(pb, 0);
832  ffio_wfourcc(pb, "wfex");
834  return ret;
835  return update_size(pb, pos);
836 }
837 
838 static int mov_write_dfla_tag(AVIOContext *pb, MOVTrack *track)
839 {
840  int64_t pos = avio_tell(pb);
841  avio_wb32(pb, 0);
842  ffio_wfourcc(pb, "dfLa");
843  avio_w8(pb, 0); /* version */
844  avio_wb24(pb, 0); /* flags */
845 
846  /* Expect the encoder to pass a METADATA_BLOCK_TYPE_STREAMINFO. */
847  if (track->par->extradata_size != FLAC_STREAMINFO_SIZE)
848  return AVERROR_INVALIDDATA;
849 
850  /* TODO: Write other METADATA_BLOCK_TYPEs if the encoder makes them available. */
851  avio_w8(pb, 1 << 7 | FLAC_METADATA_TYPE_STREAMINFO); /* LastMetadataBlockFlag << 7 | BlockType */
852  avio_wb24(pb, track->par->extradata_size); /* Length */
853  avio_write(pb, track->par->extradata, track->par->extradata_size); /* BlockData[Length] */
854 
855  return update_size(pb, pos);
856 }
857 
859 {
860  int64_t pos = avio_tell(pb);
861  int channels, channel_map;
862  avio_wb32(pb, 0);
863  ffio_wfourcc(pb, "dOps");
864  avio_w8(pb, 0); /* Version */
865  if (track->par->extradata_size < 19) {
866  av_log(s, AV_LOG_ERROR, "invalid extradata size\n");
867  return AVERROR_INVALIDDATA;
868  }
869  /* extradata contains an Ogg OpusHead, other than byte-ordering and
870  OpusHead's preceeding magic/version, OpusSpecificBox is currently
871  identical. */
872  channels = AV_RB8(track->par->extradata + 9);
873  channel_map = AV_RB8(track->par->extradata + 18);
874 
875  avio_w8(pb, channels); /* OuputChannelCount */
876  avio_wb16(pb, AV_RL16(track->par->extradata + 10)); /* PreSkip */
877  avio_wb32(pb, AV_RL32(track->par->extradata + 12)); /* InputSampleRate */
878  avio_wb16(pb, AV_RL16(track->par->extradata + 16)); /* OutputGain */
879  avio_w8(pb, channel_map); /* ChannelMappingFamily */
880  /* Write the rest of the header out without byte-swapping. */
881  if (channel_map) {
882  if (track->par->extradata_size < 21 + channels) {
883  av_log(s, AV_LOG_ERROR, "invalid extradata size\n");
884  return AVERROR_INVALIDDATA;
885  }
886  avio_write(pb, track->par->extradata + 19, 2 + channels); /* ChannelMappingTable */
887  }
888 
889  return update_size(pb, pos);
890 }
891 
893 {
894  int64_t pos = avio_tell(pb);
895  int length;
896  avio_wb32(pb, 0);
897  ffio_wfourcc(pb, "dmlp");
898 
899  if (track->vos_len < 20) {
901  "Cannot write moov atom before TrueHD packets."
902  " Set the delay_moov flag to fix this.\n");
903  return AVERROR(EINVAL);
904  }
905 
906  length = (AV_RB16(track->vos_data) & 0xFFF) * 2;
907  if (length < 20 || length > track->vos_len)
908  return AVERROR_INVALIDDATA;
909 
910  // Only TrueHD is supported
911  if (AV_RB32(track->vos_data + 4) != 0xF8726FBA)
912  return AVERROR_INVALIDDATA;
913 
914  avio_wb32(pb, AV_RB32(track->vos_data + 8)); /* format_info */
915  avio_wb16(pb, AV_RB16(track->vos_data + 18) << 1); /* peak_data_rate */
916  avio_wb32(pb, 0); /* reserved */
917 
918  return update_size(pb, pos);
919 }
920 
922 {
923  const AVDictionaryEntry *str = av_dict_get(track->st->metadata, "SA3D", NULL, 0);
924  AVChannelLayout ch_layout = { 0 };
925  int64_t pos;
926  int ambisonic_order, ambi_channels, non_diegetic_channels;
927  int i, ret;
928 
929  if (!str)
930  return 0;
931 
932  ret = av_channel_layout_from_string(&ch_layout, str->value);
933  if (ret < 0) {
934  if (ret == AVERROR(EINVAL)) {
935 invalid:
936  av_log(s, AV_LOG_ERROR, "Invalid SA3D layout: \"%s\"\n", str->value);
937  ret = 0;
938  }
939  av_channel_layout_uninit(&ch_layout);
940  return ret;
941  }
942 
943  if (track->st->codecpar->ch_layout.nb_channels != ch_layout.nb_channels)
944  goto invalid;
945 
946  ambisonic_order = av_channel_layout_ambisonic_order(&ch_layout);
947  if (ambisonic_order < 0)
948  goto invalid;
949 
950  ambi_channels = (ambisonic_order + 1LL) * (ambisonic_order + 1LL);
951  non_diegetic_channels = ch_layout.nb_channels - ambi_channels;
952  if (non_diegetic_channels &&
953  (non_diegetic_channels != 2 ||
955  goto invalid;
956 
957  av_log(s, AV_LOG_VERBOSE, "Inserting SA3D box with layout: \"%s\"\n", str->value);
958 
959  pos = avio_tell(pb);
960 
961  avio_wb32(pb, 0); // Size
962  ffio_wfourcc(pb, "SA3D");
963  avio_w8(pb, 0); // version
964  avio_w8(pb, (!!non_diegetic_channels) << 7); // head_locked_stereo and ambisonic_type
965  avio_wb32(pb, ambisonic_order); // ambisonic_order
966  avio_w8(pb, 0); // ambisonic_channel_ordering
967  avio_w8(pb, 0); // ambisonic_normalization
968  avio_wb32(pb, ch_layout.nb_channels); // num_channels
969  for (i = 0; i < ambi_channels; i++)
971  for (; i < ch_layout.nb_channels; i++)
972  avio_wb32(pb, av_channel_layout_channel_from_index(&ch_layout, i) + ambi_channels);
973 
974  av_channel_layout_uninit(&ch_layout);
975 
976  return update_size(pb, pos);
977 }
978 
980 {
981  uint32_t layout_tag, bitmap, *channel_desc;
982  int64_t pos = avio_tell(pb);
983  int num_desc, ret;
984 
985  if (track->multichannel_as_mono)
986  return 0;
987 
988  ret = ff_mov_get_channel_layout_tag(track->par, &layout_tag,
989  &bitmap, &channel_desc);
990 
991  if (ret < 0) {
992  if (ret == AVERROR(ENOSYS)) {
993  av_log(s, AV_LOG_WARNING, "not writing 'chan' tag due to "
994  "lack of channel information\n");
995  ret = 0;
996  }
997 
998  return ret;
999  }
1000 
1001  if (layout_tag == MOV_CH_LAYOUT_MONO && track->mono_as_fc > 0) {
1002  av_assert0(!channel_desc);
1003  channel_desc = av_malloc(sizeof(*channel_desc));
1004  if (!channel_desc)
1005  return AVERROR(ENOMEM);
1006 
1007  layout_tag = 0;
1008  bitmap = 0;
1009  *channel_desc = 3; // channel label "Center"
1010  }
1011 
1012  num_desc = layout_tag ? 0 : track->par->ch_layout.nb_channels;
1013 
1014  avio_wb32(pb, 0); // Size
1015  ffio_wfourcc(pb, "chan"); // Type
1016  avio_w8(pb, 0); // Version
1017  avio_wb24(pb, 0); // Flags
1018  avio_wb32(pb, layout_tag); // mChannelLayoutTag
1019  avio_wb32(pb, bitmap); // mChannelBitmap
1020  avio_wb32(pb, num_desc); // mNumberChannelDescriptions
1021 
1022  for (int i = 0; i < num_desc; i++) {
1023  avio_wb32(pb, channel_desc[i]); // mChannelLabel
1024  avio_wb32(pb, 0); // mChannelFlags
1025  avio_wl32(pb, 0); // mCoordinates[0]
1026  avio_wl32(pb, 0); // mCoordinates[1]
1027  avio_wl32(pb, 0); // mCoordinates[2]
1028  }
1029 
1030  av_free(channel_desc);
1031 
1032  return update_size(pb, pos);
1033 }
1034 
1036 {
1037  int64_t pos = avio_tell(pb);
1038 
1039  avio_wb32(pb, 0); /* size */
1040  ffio_wfourcc(pb, "wave");
1041 
1042  if (track->par->codec_id != AV_CODEC_ID_QDM2) {
1043  avio_wb32(pb, 12); /* size */
1044  ffio_wfourcc(pb, "frma");
1045  avio_wl32(pb, track->tag);
1046  }
1047 
1048  if (track->par->codec_id == AV_CODEC_ID_AAC) {
1049  /* useless atom needed by mplayer, ipod, not needed by quicktime */
1050  avio_wb32(pb, 12); /* size */
1051  ffio_wfourcc(pb, "mp4a");
1052  avio_wb32(pb, 0);
1053  mov_write_esds_tag(pb, track);
1054  } else if (mov_pcm_le_gt16(track->par->codec_id)) {
1055  mov_write_enda_tag(pb);
1056  } else if (mov_pcm_be_gt16(track->par->codec_id)) {
1058  } else if (track->par->codec_id == AV_CODEC_ID_AMR_NB) {
1059  mov_write_amr_tag(pb, track);
1060  } else if (track->par->codec_id == AV_CODEC_ID_AC3) {
1061  mov_write_ac3_tag(s, pb, track);
1062  } else if (track->par->codec_id == AV_CODEC_ID_EAC3) {
1063  mov_write_eac3_tag(s, pb, track);
1064  } else if (track->par->codec_id == AV_CODEC_ID_ALAC ||
1065  track->par->codec_id == AV_CODEC_ID_QDM2) {
1066  mov_write_extradata_tag(pb, track);
1067  } else if (track->par->codec_id == AV_CODEC_ID_ADPCM_MS ||
1068  track->par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) {
1069  mov_write_ms_tag(s, pb, track);
1070  }
1071 
1072  avio_wb32(pb, 8); /* size */
1073  avio_wb32(pb, 0); /* null tag */
1074 
1075  return update_size(pb, pos);
1076 }
1077 
1078 static int mov_write_dvc1_structs(MOVTrack *track, uint8_t *buf)
1079 {
1080  uint8_t *unescaped;
1081  const uint8_t *start, *next, *end = track->vos_data + track->vos_len;
1082  int unescaped_size, seq_found = 0;
1083  int level = 0, interlace = 0;
1084  int packet_seq = track->vc1_info.packet_seq;
1085  int packet_entry = track->vc1_info.packet_entry;
1086  int slices = track->vc1_info.slices;
1087  PutBitContext pbc;
1088 
1089  if (track->start_dts == AV_NOPTS_VALUE) {
1090  /* No packets written yet, vc1_info isn't authoritative yet. */
1091  /* Assume inline sequence and entry headers. */
1092  packet_seq = packet_entry = 1;
1094  "moov atom written before any packets, unable to write correct "
1095  "dvc1 atom. Set the delay_moov flag to fix this.\n");
1096  }
1097 
1098  unescaped = av_mallocz(track->vos_len + AV_INPUT_BUFFER_PADDING_SIZE);
1099  if (!unescaped)
1100  return AVERROR(ENOMEM);
1101  start = find_next_marker(track->vos_data, end);
1102  for (next = start; next < end; start = next) {
1103  GetBitContext gb;
1104  int size;
1105  next = find_next_marker(start + 4, end);
1106  size = next - start - 4;
1107  if (size <= 0)
1108  continue;
1109  unescaped_size = vc1_unescape_buffer(start + 4, size, unescaped);
1110  init_get_bits(&gb, unescaped, 8 * unescaped_size);
1111  if (AV_RB32(start) == VC1_CODE_SEQHDR) {
1112  int profile = get_bits(&gb, 2);
1113  if (profile != PROFILE_ADVANCED) {
1114  av_free(unescaped);
1115  return AVERROR(ENOSYS);
1116  }
1117  seq_found = 1;
1118  level = get_bits(&gb, 3);
1119  /* chromaformat, frmrtq_postproc, bitrtq_postproc, postprocflag,
1120  * width, height */
1121  skip_bits_long(&gb, 2 + 3 + 5 + 1 + 2*12);
1122  skip_bits(&gb, 1); /* broadcast */
1123  interlace = get_bits1(&gb);
1124  skip_bits(&gb, 4); /* tfcntrflag, finterpflag, reserved, psf */
1125  }
1126  }
1127  if (!seq_found) {
1128  av_free(unescaped);
1129  return AVERROR(ENOSYS);
1130  }
1131 
1132  init_put_bits(&pbc, buf, 7);
1133  /* VC1DecSpecStruc */
1134  put_bits(&pbc, 4, 12); /* profile - advanced */
1135  put_bits(&pbc, 3, level);
1136  put_bits(&pbc, 1, 0); /* reserved */
1137  /* VC1AdvDecSpecStruc */
1138  put_bits(&pbc, 3, level);
1139  put_bits(&pbc, 1, 0); /* cbr */
1140  put_bits(&pbc, 6, 0); /* reserved */
1141  put_bits(&pbc, 1, !interlace); /* no interlace */
1142  put_bits(&pbc, 1, !packet_seq); /* no multiple seq */
1143  put_bits(&pbc, 1, !packet_entry); /* no multiple entry */
1144  put_bits(&pbc, 1, !slices); /* no slice code */
1145  put_bits(&pbc, 1, 0); /* no bframe */
1146  put_bits(&pbc, 1, 0); /* reserved */
1147 
1148  /* framerate */
1149  if (track->st->avg_frame_rate.num > 0 && track->st->avg_frame_rate.den > 0)
1150  put_bits32(&pbc, track->st->avg_frame_rate.num / track->st->avg_frame_rate.den);
1151  else
1152  put_bits32(&pbc, 0xffffffff);
1153 
1154  flush_put_bits(&pbc);
1155 
1156  av_free(unescaped);
1157 
1158  return 0;
1159 }
1160 
1161 static int mov_write_dvc1_tag(AVIOContext *pb, MOVTrack *track)
1162 {
1163  uint8_t buf[7] = { 0 };
1164  int ret;
1165 
1166  if ((ret = mov_write_dvc1_structs(track, buf)) < 0)
1167  return ret;
1168 
1169  avio_wb32(pb, track->vos_len + 8 + sizeof(buf));
1170  ffio_wfourcc(pb, "dvc1");
1171  avio_write(pb, buf, sizeof(buf));
1172  avio_write(pb, track->vos_data, track->vos_len);
1173 
1174  return 0;
1175 }
1176 
1177 static int mov_write_glbl_tag(AVIOContext *pb, MOVTrack *track)
1178 {
1179  avio_wb32(pb, track->vos_len + 8);
1180  ffio_wfourcc(pb, "glbl");
1181  avio_write(pb, track->vos_data, track->vos_len);
1182  return 8 + track->vos_len;
1183 }
1184 
1185 /**
1186  * Compute flags for 'lpcm' tag.
1187  * See CoreAudioTypes and AudioStreamBasicDescription at Apple.
1188  */
1190 {
1191  switch (codec_id) {
1192  case AV_CODEC_ID_PCM_F32BE:
1193  case AV_CODEC_ID_PCM_F64BE:
1194  return 11;
1195  case AV_CODEC_ID_PCM_F32LE:
1196  case AV_CODEC_ID_PCM_F64LE:
1197  return 9;
1198  case AV_CODEC_ID_PCM_U8:
1199  return 10;
1200  case AV_CODEC_ID_PCM_S16BE:
1201  case AV_CODEC_ID_PCM_S24BE:
1202  case AV_CODEC_ID_PCM_S32BE:
1203  return 14;
1204  case AV_CODEC_ID_PCM_S8:
1205  case AV_CODEC_ID_PCM_S16LE:
1206  case AV_CODEC_ID_PCM_S24LE:
1207  case AV_CODEC_ID_PCM_S32LE:
1208  return 12;
1209  default:
1210  return 0;
1211  }
1212 }
1213 
1214 static int get_cluster_duration(MOVTrack *track, int cluster_idx)
1215 {
1216  int64_t next_dts;
1217 
1218  if (cluster_idx >= track->entry)
1219  return 0;
1220 
1221  if (cluster_idx + 1 == track->entry)
1222  next_dts = track->track_duration + track->start_dts;
1223  else
1224  next_dts = track->cluster[cluster_idx + 1].dts;
1225 
1226  next_dts -= track->cluster[cluster_idx].dts;
1227 
1228  av_assert0(next_dts >= 0);
1229  av_assert0(next_dts <= INT_MAX);
1230 
1231  return next_dts;
1232 }
1233 
1235 {
1236  int i, first_duration;
1237 
1238  /* use 1 for raw PCM */
1239  if (!track->audio_vbr)
1240  return 1;
1241 
1242  /* check to see if duration is constant for all clusters */
1243  if (!track->entry)
1244  return 0;
1245  first_duration = get_cluster_duration(track, 0);
1246  for (i = 1; i < track->entry; i++) {
1247  if (get_cluster_duration(track, i) != first_duration)
1248  return 0;
1249  }
1250  return first_duration;
1251 }
1252 
1253 static int mov_write_btrt_tag(AVIOContext *pb, MOVTrack *track)
1254 {
1255  int64_t pos = avio_tell(pb);
1256  struct mpeg4_bit_rate_values bit_rates = calculate_mpeg4_bit_rates(track);
1257  if (!bit_rates.max_bit_rate && !bit_rates.avg_bit_rate &&
1258  !bit_rates.buffer_size)
1259  // no useful data to be written, skip
1260  return 0;
1261 
1262  avio_wb32(pb, 0); /* size */
1263  ffio_wfourcc(pb, "btrt");
1264 
1265  avio_wb32(pb, bit_rates.buffer_size);
1266  avio_wb32(pb, bit_rates.max_bit_rate);
1267  avio_wb32(pb, bit_rates.avg_bit_rate);
1268 
1269  return update_size(pb, pos);
1270 }
1271 
1273 {
1274  int64_t pos = avio_tell(pb);
1275  int config = 0;
1276  int ret;
1277  uint8_t *speaker_pos = NULL;
1278  const AVChannelLayout *layout = &track->par->ch_layout;
1279 
1281  if (ret || !config) {
1282  config = 0;
1283  speaker_pos = av_malloc(layout->nb_channels);
1284  if (!speaker_pos)
1285  return AVERROR(ENOMEM);
1287  speaker_pos, layout->nb_channels);
1288  if (ret) {
1289  char buf[128] = {0};
1290 
1291  av_freep(&speaker_pos);
1292  av_channel_layout_describe(layout, buf, sizeof(buf));
1293  av_log(s, AV_LOG_ERROR, "unsupported channel layout %s\n", buf);
1294  return ret;
1295  }
1296  }
1297 
1298  avio_wb32(pb, 0); /* size */
1299  ffio_wfourcc(pb, "chnl");
1300  avio_wb32(pb, 0); /* version & flags */
1301 
1302  avio_w8(pb, 1); /* stream_structure */
1303  avio_w8(pb, config);
1304  if (config) {
1305  avio_wb64(pb, 0);
1306  } else {
1307  avio_write(pb, speaker_pos, layout->nb_channels);
1308  av_freep(&speaker_pos);
1309  }
1310 
1311  return update_size(pb, pos);
1312 }
1313 
1315 {
1316  int64_t pos = avio_tell(pb);
1317  int format_flags;
1318  int sample_size;
1319 
1320  avio_wb32(pb, 0); /* size */
1321  ffio_wfourcc(pb, "pcmC");
1322  avio_wb32(pb, 0); /* version & flags */
1323 
1324  /* 0x01: indicates little-endian format */
1325  format_flags = (track->par->codec_id == AV_CODEC_ID_PCM_F32LE ||
1326  track->par->codec_id == AV_CODEC_ID_PCM_F64LE ||
1327  track->par->codec_id == AV_CODEC_ID_PCM_S16LE ||
1328  track->par->codec_id == AV_CODEC_ID_PCM_S24LE ||
1329  track->par->codec_id == AV_CODEC_ID_PCM_S32LE);
1330  avio_w8(pb, format_flags);
1331  sample_size = track->par->bits_per_raw_sample;
1332  if (!sample_size)
1333  sample_size = av_get_exact_bits_per_sample(track->par->codec_id);
1334  av_assert0(sample_size);
1335  avio_w8(pb, sample_size);
1336 
1337  return update_size(pb, pos);
1338 }
1339 
1341 {
1342  int64_t pos = avio_tell(pb);
1343  int version = 0;
1344  uint32_t tag = track->tag;
1345  int ret = 0;
1346 
1347  if (track->mode == MODE_MOV) {
1348  if (track->timescale > UINT16_MAX || !track->par->ch_layout.nb_channels) {
1349  if (mov_get_lpcm_flags(track->par->codec_id))
1350  tag = AV_RL32("lpcm");
1351  version = 2;
1352  } else if (track->audio_vbr || mov_pcm_le_gt16(track->par->codec_id) ||
1353  mov_pcm_be_gt16(track->par->codec_id) ||
1354  track->par->codec_id == AV_CODEC_ID_ADPCM_MS ||
1355  track->par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV ||
1356  track->par->codec_id == AV_CODEC_ID_QDM2) {
1357  version = 1;
1358  }
1359  }
1360 
1361  avio_wb32(pb, 0); /* size */
1362  if (mov->encryption_scheme != MOV_ENC_NONE) {
1363  ffio_wfourcc(pb, "enca");
1364  } else {
1365  avio_wl32(pb, tag); // store it byteswapped
1366  }
1367  avio_wb32(pb, 0); /* Reserved */
1368  avio_wb16(pb, 0); /* Reserved */
1369  avio_wb16(pb, 1); /* Data-reference index, XXX == 1 */
1370 
1371  /* SoundDescription */
1372  avio_wb16(pb, version); /* Version */
1373  avio_wb16(pb, 0); /* Revision level */
1374  avio_wb32(pb, 0); /* Reserved */
1375 
1376  if (version == 2) {
1377  avio_wb16(pb, 3);
1378  avio_wb16(pb, 16);
1379  avio_wb16(pb, 0xfffe);
1380  avio_wb16(pb, 0);
1381  avio_wb32(pb, 0x00010000);
1382  avio_wb32(pb, 72);
1383  avio_wb64(pb, av_double2int(track->par->sample_rate));
1384  avio_wb32(pb, track->par->ch_layout.nb_channels);
1385  avio_wb32(pb, 0x7F000000);
1387  avio_wb32(pb, mov_get_lpcm_flags(track->par->codec_id));
1388  avio_wb32(pb, track->sample_size);
1389  avio_wb32(pb, get_samples_per_packet(track));
1390  } else {
1391  if (track->mode == MODE_MOV) {
1392  avio_wb16(pb, track->par->ch_layout.nb_channels);
1393  if (track->par->codec_id == AV_CODEC_ID_PCM_U8 ||
1394  track->par->codec_id == AV_CODEC_ID_PCM_S8)
1395  avio_wb16(pb, 8); /* bits per sample */
1396  else if (track->par->codec_id == AV_CODEC_ID_ADPCM_G726)
1397  avio_wb16(pb, track->par->bits_per_coded_sample);
1398  else
1399  avio_wb16(pb, 16);
1400  avio_wb16(pb, track->audio_vbr ? -2 : 0); /* compression ID */
1401  } else { /* reserved for mp4/3gp */
1402  avio_wb16(pb, track->tag == MKTAG('i', 'a', 'm', 'f') ?
1403  0 : track->par->ch_layout.nb_channels);
1404  if (track->par->codec_id == AV_CODEC_ID_FLAC ||
1405  track->par->codec_id == AV_CODEC_ID_ALAC) {
1406  avio_wb16(pb, track->par->bits_per_raw_sample);
1407  } else {
1408  avio_wb16(pb, 16);
1409  }
1410  avio_wb16(pb, 0);
1411  }
1412 
1413  avio_wb16(pb, 0); /* packet size (= 0) */
1414  if (track->tag == MKTAG('i','a','m','f'))
1415  avio_wb16(pb, 0); /* samplerate must be 0 for IAMF */
1416  else if (track->par->codec_id == AV_CODEC_ID_OPUS)
1417  avio_wb16(pb, 48000);
1418  else if (track->par->codec_id == AV_CODEC_ID_TRUEHD)
1419  avio_wb32(pb, track->par->sample_rate);
1420  else
1421  avio_wb16(pb, track->par->sample_rate <= UINT16_MAX ?
1422  track->par->sample_rate : 0);
1423 
1424  if (track->par->codec_id != AV_CODEC_ID_TRUEHD)
1425  avio_wb16(pb, 0); /* Reserved */
1426  }
1427 
1428  if (version == 1) { /* SoundDescription V1 extended info */
1429  if (mov_pcm_le_gt16(track->par->codec_id) ||
1430  mov_pcm_be_gt16(track->par->codec_id))
1431  avio_wb32(pb, 1); /* must be 1 for uncompressed formats */
1432  else
1433  avio_wb32(pb, track->par->frame_size); /* Samples per packet */
1434  avio_wb32(pb, track->sample_size / track->par->ch_layout.nb_channels); /* Bytes per packet */
1435  avio_wb32(pb, track->sample_size); /* Bytes per frame */
1436  avio_wb32(pb, 2); /* Bytes per sample */
1437  }
1438 
1439  if (track->mode == MODE_MOV &&
1440  (track->par->codec_id == AV_CODEC_ID_AAC ||
1441  track->par->codec_id == AV_CODEC_ID_AC3 ||
1442  track->par->codec_id == AV_CODEC_ID_EAC3 ||
1443  track->par->codec_id == AV_CODEC_ID_AMR_NB ||
1444  track->par->codec_id == AV_CODEC_ID_ALAC ||
1445  track->par->codec_id == AV_CODEC_ID_ADPCM_MS ||
1446  track->par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV ||
1447  track->par->codec_id == AV_CODEC_ID_QDM2 ||
1448  (mov_pcm_le_gt16(track->par->codec_id) && version==1) ||
1449  (mov_pcm_be_gt16(track->par->codec_id) && version==1)))
1450  ret = mov_write_wave_tag(s, pb, track);
1451  else if (track->tag == MKTAG('m','p','4','a'))
1452  ret = mov_write_esds_tag(pb, track);
1453 #if CONFIG_IAMFENC
1454  else if (track->tag == MKTAG('i','a','m','f'))
1455  ret = mov_write_iacb_tag(mov->fc, pb, track);
1456 #endif
1457  else if (track->par->codec_id == AV_CODEC_ID_AMR_NB)
1458  ret = mov_write_amr_tag(pb, track);
1459  else if (track->par->codec_id == AV_CODEC_ID_AC3)
1460  ret = mov_write_ac3_tag(s, pb, track);
1461  else if (track->par->codec_id == AV_CODEC_ID_EAC3)
1462  ret = mov_write_eac3_tag(s, pb, track);
1463  else if (track->par->codec_id == AV_CODEC_ID_ALAC)
1464  ret = mov_write_extradata_tag(pb, track);
1465  else if (track->par->codec_id == AV_CODEC_ID_WMAPRO)
1466  ret = mov_write_wfex_tag(s, pb, track);
1467  else if (track->par->codec_id == AV_CODEC_ID_FLAC)
1468  ret = mov_write_dfla_tag(pb, track);
1469  else if (track->par->codec_id == AV_CODEC_ID_OPUS)
1470  ret = mov_write_dops_tag(s, pb, track);
1471  else if (track->par->codec_id == AV_CODEC_ID_TRUEHD)
1472  ret = mov_write_dmlp_tag(s, pb, track);
1473  else if (tag == MOV_MP4_IPCM_TAG || tag == MOV_MP4_FPCM_TAG) {
1474  if (track->par->ch_layout.nb_channels > 1)
1475  ret = mov_write_chnl_tag(s, pb, track);
1476  if (ret < 0)
1477  return ret;
1478  ret = mov_write_pcmc_tag(s, pb, track);
1479  } else if (track->vos_len > 0)
1480  ret = mov_write_glbl_tag(pb, track);
1481 
1482  if (ret < 0)
1483  return ret;
1484 
1485  if (track->mode == MODE_MP4 && track->par->codec_type == AVMEDIA_TYPE_AUDIO
1486  && ((ret = mov_write_SA3D_tag(s, pb, track)) < 0)) {
1487  return ret;
1488  }
1489 
1490  if (track->mode == MODE_MOV && track->par->codec_type == AVMEDIA_TYPE_AUDIO
1491  && ((ret = mov_write_chan_tag(s, pb, track)) < 0)) {
1492  return ret;
1493  }
1494 
1495  if (mov->encryption_scheme != MOV_ENC_NONE
1496  && ((ret = ff_mov_cenc_write_sinf_tag(track, pb, mov->encryption_kid)) < 0)) {
1497  return ret;
1498  }
1499 
1500  if (mov->write_btrt &&
1501  ((ret = mov_write_btrt_tag(pb, track)) < 0))
1502  return ret;
1503 
1504  ret = update_size(pb, pos);
1505  return ret;
1506 }
1507 
1509 {
1510  avio_wb32(pb, 0xf); /* size */
1511  ffio_wfourcc(pb, "d263");
1512  ffio_wfourcc(pb, "FFMP");
1513  avio_w8(pb, 0); /* decoder version */
1514  /* FIXME use AVCodecContext level/profile, when encoder will set values */
1515  avio_w8(pb, 0xa); /* level */
1516  avio_w8(pb, 0); /* profile */
1517  return 0xf;
1518 }
1519 
1520 static int mov_write_av1c_tag(AVIOContext *pb, MOVTrack *track)
1521 {
1522  int64_t pos = avio_tell(pb);
1523 
1524  avio_wb32(pb, 0);
1525  ffio_wfourcc(pb, "av1C");
1526  ff_isom_write_av1c(pb, track->vos_data, track->vos_len, track->mode != MODE_AVIF);
1527  return update_size(pb, pos);
1528 }
1529 
1530 static int mov_write_avcc_tag(AVIOContext *pb, MOVTrack *track)
1531 {
1532  int64_t pos = avio_tell(pb);
1533 
1534  avio_wb32(pb, 0);
1535  ffio_wfourcc(pb, "avcC");
1536  ff_isom_write_avcc(pb, track->vos_data, track->vos_len);
1537  return update_size(pb, pos);
1538 }
1539 
1541 {
1542  int64_t pos = avio_tell(pb);
1543 
1544  avio_wb32(pb, 0);
1545  ffio_wfourcc(pb, "vpcC");
1546  ff_isom_write_vpcc(s, pb, track->vos_data, track->vos_len, track->par);
1547  return update_size(pb, pos);
1548 }
1549 
1550 static int mov_write_hvcc_tag(AVIOContext *pb, MOVTrack *track)
1551 {
1552  int64_t pos = avio_tell(pb);
1553 
1554  avio_wb32(pb, 0);
1555  ffio_wfourcc(pb, "hvcC");
1556  if (track->tag == MKTAG('h','v','c','1'))
1557  ff_isom_write_hvcc(pb, track->vos_data, track->vos_len, 1);
1558  else
1559  ff_isom_write_hvcc(pb, track->vos_data, track->vos_len, 0);
1560  return update_size(pb, pos);
1561 }
1562 
1563 static int mov_write_lhvc_tag(AVIOContext *pb, MOVTrack *track)
1564 {
1565  int64_t pos = avio_tell(pb);
1566  int ret;
1567 
1568  avio_wb32(pb, 0);
1569  ffio_wfourcc(pb, "lhvC");
1570  if (track->tag == MKTAG('h','v','c','1'))
1571  ret = ff_isom_write_lhvc(pb, track->vos_data, track->vos_len, 1);
1572  else
1573  ret = ff_isom_write_lhvc(pb, track->vos_data, track->vos_len, 0);
1574 
1575  if (ret < 0) {
1576  avio_seek(pb, pos, SEEK_SET);
1577  return ret;
1578  }
1579 
1580  return update_size(pb, pos);
1581 }
1582 
1583 static int mov_write_evcc_tag(AVIOContext *pb, MOVTrack *track)
1584 {
1585  int64_t pos = avio_tell(pb);
1586 
1587  avio_wb32(pb, 0);
1588  ffio_wfourcc(pb, "evcC");
1589 
1590  if (track->tag == MKTAG('e','v','c','1'))
1591  ff_isom_write_evcc(pb, track->vos_data, track->vos_len, 1);
1592  else
1593  ff_isom_write_evcc(pb, track->vos_data, track->vos_len, 0);
1594 
1595  return update_size(pb, pos);
1596 }
1597 
1598 static int mov_write_vvcc_tag(AVIOContext *pb, MOVTrack *track)
1599 {
1600  int64_t pos = avio_tell(pb);
1601 
1602  avio_wb32(pb, 0);
1603  ffio_wfourcc(pb, "vvcC");
1604 
1605  avio_w8 (pb, 0); /* version */
1606  avio_wb24(pb, 0); /* flags */
1607 
1608  if (track->tag == MKTAG('v','v','c','1'))
1609  ff_isom_write_vvcc(pb, track->vos_data, track->vos_len, 1);
1610  else
1611  ff_isom_write_vvcc(pb, track->vos_data, track->vos_len, 0);
1612  return update_size(pb, pos);
1613 }
1614 
1615 /* also used by all avid codecs (dv, imx, meridien) and their variants */
1616 static int mov_write_avid_tag(AVIOContext *pb, MOVTrack *track)
1617 {
1618  int interlaced;
1619  int cid;
1620  int display_width = track->par->width;
1621 
1622  if (track->vos_data && track->vos_len > 0x29) {
1623  if (ff_dnxhd_parse_header_prefix(track->vos_data) != 0) {
1624  /* looks like a DNxHD bit stream */
1625  interlaced = (track->vos_data[5] & 2);
1626  cid = AV_RB32(track->vos_data + 0x28);
1627  } else {
1628  av_log(NULL, AV_LOG_WARNING, "Could not locate DNxHD bit stream in vos_data\n");
1629  return 0;
1630  }
1631  } else {
1632  av_log(NULL, AV_LOG_WARNING, "Could not locate DNxHD bit stream, vos_data too small\n");
1633  return 0;
1634  }
1635 
1636  avio_wb32(pb, 24); /* size */
1637  ffio_wfourcc(pb, "ACLR");
1638  ffio_wfourcc(pb, "ACLR");
1639  ffio_wfourcc(pb, "0001");
1640  if (track->par->color_range == AVCOL_RANGE_MPEG || /* Legal range (16-235) */
1642  avio_wb32(pb, 1); /* Corresponds to 709 in official encoder */
1643  } else { /* Full range (0-255) */
1644  avio_wb32(pb, 2); /* Corresponds to RGB in official encoder */
1645  }
1646  avio_wb32(pb, 0); /* unknown */
1647 
1648  if (track->tag == MKTAG('A','V','d','h')) {
1649  avio_wb32(pb, 32);
1650  ffio_wfourcc(pb, "ADHR");
1651  ffio_wfourcc(pb, "0001");
1652  avio_wb32(pb, cid);
1653  avio_wb32(pb, 0); /* unknown */
1654  avio_wb32(pb, 1); /* unknown */
1655  avio_wb32(pb, 0); /* unknown */
1656  avio_wb32(pb, 0); /* unknown */
1657  return 0;
1658  }
1659 
1660  avio_wb32(pb, 24); /* size */
1661  ffio_wfourcc(pb, "APRG");
1662  ffio_wfourcc(pb, "APRG");
1663  ffio_wfourcc(pb, "0001");
1664  avio_wb32(pb, 1); /* unknown */
1665  avio_wb32(pb, 0); /* unknown */
1666 
1667  avio_wb32(pb, 120); /* size */
1668  ffio_wfourcc(pb, "ARES");
1669  ffio_wfourcc(pb, "ARES");
1670  ffio_wfourcc(pb, "0001");
1671  avio_wb32(pb, cid); /* dnxhd cid, some id ? */
1672  if ( track->par->sample_aspect_ratio.num > 0
1673  && track->par->sample_aspect_ratio.den > 0)
1674  display_width = display_width * track->par->sample_aspect_ratio.num / track->par->sample_aspect_ratio.den;
1675  avio_wb32(pb, display_width);
1676  /* values below are based on samples created with quicktime and avid codecs */
1677  if (interlaced) {
1678  avio_wb32(pb, track->par->height / 2);
1679  avio_wb32(pb, 2); /* unknown */
1680  avio_wb32(pb, 0); /* unknown */
1681  avio_wb32(pb, 4); /* unknown */
1682  } else {
1683  avio_wb32(pb, track->par->height);
1684  avio_wb32(pb, 1); /* unknown */
1685  avio_wb32(pb, 0); /* unknown */
1686  if (track->par->height == 1080)
1687  avio_wb32(pb, 5); /* unknown */
1688  else
1689  avio_wb32(pb, 6); /* unknown */
1690  }
1691  /* padding */
1692  ffio_fill(pb, 0, 10 * 8);
1693 
1694  return 0;
1695 }
1696 
1697 static int mov_write_dpxe_tag(AVIOContext *pb, MOVTrack *track)
1698 {
1699  avio_wb32(pb, 12);
1700  ffio_wfourcc(pb, "DpxE");
1701  if (track->par->extradata_size >= 12 &&
1702  !memcmp(&track->par->extradata[4], "DpxE", 4)) {
1703  avio_wb32(pb, track->par->extradata[11]);
1704  } else {
1705  avio_wb32(pb, 1);
1706  }
1707  return 0;
1708 }
1709 
1711 {
1712  int tag;
1713 
1714  if (track->par->width == 720) { /* SD */
1715  if (track->par->height == 480) { /* NTSC */
1716  if (track->par->format == AV_PIX_FMT_YUV422P) tag = MKTAG('d','v','5','n');
1717  else tag = MKTAG('d','v','c',' ');
1718  }else if (track->par->format == AV_PIX_FMT_YUV422P) tag = MKTAG('d','v','5','p');
1719  else if (track->par->format == AV_PIX_FMT_YUV420P) tag = MKTAG('d','v','c','p');
1720  else tag = MKTAG('d','v','p','p');
1721  } else if (track->par->height == 720) { /* HD 720 line */
1722  if (track->st->time_base.den == 50) tag = MKTAG('d','v','h','q');
1723  else tag = MKTAG('d','v','h','p');
1724  } else if (track->par->height == 1080) { /* HD 1080 line */
1725  if (track->st->time_base.den == 25) tag = MKTAG('d','v','h','5');
1726  else tag = MKTAG('d','v','h','6');
1727  } else {
1728  av_log(s, AV_LOG_ERROR, "unsupported height for dv codec\n");
1729  return 0;
1730  }
1731 
1732  return tag;
1733 }
1734 
1736 {
1737  AVRational rational_framerate = st->avg_frame_rate;
1738  int rate = 0;
1739  if (rational_framerate.den != 0)
1740  rate = av_q2d(rational_framerate);
1741  return rate;
1742 }
1743 
1745 {
1746  int tag = track->par->codec_tag;
1748  AVStream *st = track->st;
1749  int rate = defined_frame_rate(s, st);
1750 
1751  if (!tag)
1752  tag = MKTAG('m', '2', 'v', '1'); //fallback tag
1753 
1754  if (track->par->format == AV_PIX_FMT_YUV420P) {
1755  if (track->par->width == 1280 && track->par->height == 720) {
1756  if (!interlaced) {
1757  if (rate == 24) tag = MKTAG('x','d','v','4');
1758  else if (rate == 25) tag = MKTAG('x','d','v','5');
1759  else if (rate == 30) tag = MKTAG('x','d','v','1');
1760  else if (rate == 50) tag = MKTAG('x','d','v','a');
1761  else if (rate == 60) tag = MKTAG('x','d','v','9');
1762  }
1763  } else if (track->par->width == 1440 && track->par->height == 1080) {
1764  if (!interlaced) {
1765  if (rate == 24) tag = MKTAG('x','d','v','6');
1766  else if (rate == 25) tag = MKTAG('x','d','v','7');
1767  else if (rate == 30) tag = MKTAG('x','d','v','8');
1768  } else {
1769  if (rate == 25) tag = MKTAG('x','d','v','3');
1770  else if (rate == 30) tag = MKTAG('x','d','v','2');
1771  }
1772  } else if (track->par->width == 1920 && track->par->height == 1080) {
1773  if (!interlaced) {
1774  if (rate == 24) tag = MKTAG('x','d','v','d');
1775  else if (rate == 25) tag = MKTAG('x','d','v','e');
1776  else if (rate == 30) tag = MKTAG('x','d','v','f');
1777  } else {
1778  if (rate == 25) tag = MKTAG('x','d','v','c');
1779  else if (rate == 30) tag = MKTAG('x','d','v','b');
1780  }
1781  }
1782  } else if (track->par->format == AV_PIX_FMT_YUV422P) {
1783  if (track->par->width == 1280 && track->par->height == 720) {
1784  if (!interlaced) {
1785  if (rate == 24) tag = MKTAG('x','d','5','4');
1786  else if (rate == 25) tag = MKTAG('x','d','5','5');
1787  else if (rate == 30) tag = MKTAG('x','d','5','1');
1788  else if (rate == 50) tag = MKTAG('x','d','5','a');
1789  else if (rate == 60) tag = MKTAG('x','d','5','9');
1790  }
1791  } else if (track->par->width == 1920 && track->par->height == 1080) {
1792  if (!interlaced) {
1793  if (rate == 24) tag = MKTAG('x','d','5','d');
1794  else if (rate == 25) tag = MKTAG('x','d','5','e');
1795  else if (rate == 30) tag = MKTAG('x','d','5','f');
1796  } else {
1797  if (rate == 25) tag = MKTAG('x','d','5','c');
1798  else if (rate == 30) tag = MKTAG('x','d','5','b');
1799  }
1800  }
1801  }
1802 
1803  return tag;
1804 }
1805 
1807 {
1808  int tag = track->par->codec_tag;
1810  AVStream *st = track->st;
1811  int rate = defined_frame_rate(s, st);
1812 
1813  if (!tag)
1814  tag = MKTAG('a', 'v', 'c', 'i'); //fallback tag
1815 
1816  if (track->par->format == AV_PIX_FMT_YUV420P10) {
1817  if (track->par->width == 960 && track->par->height == 720) {
1818  if (!interlaced) {
1819  if (rate == 24) tag = MKTAG('a','i','5','p');
1820  else if (rate == 25) tag = MKTAG('a','i','5','q');
1821  else if (rate == 30) tag = MKTAG('a','i','5','p');
1822  else if (rate == 50) tag = MKTAG('a','i','5','q');
1823  else if (rate == 60) tag = MKTAG('a','i','5','p');
1824  }
1825  } else if (track->par->width == 1440 && track->par->height == 1080) {
1826  if (!interlaced) {
1827  if (rate == 24) tag = MKTAG('a','i','5','3');
1828  else if (rate == 25) tag = MKTAG('a','i','5','2');
1829  else if (rate == 30) tag = MKTAG('a','i','5','3');
1830  } else {
1831  if (rate == 50) tag = MKTAG('a','i','5','5');
1832  else if (rate == 60) tag = MKTAG('a','i','5','6');
1833  }
1834  }
1835  } else if (track->par->format == AV_PIX_FMT_YUV422P10) {
1836  if (track->par->width == 1280 && track->par->height == 720) {
1837  if (!interlaced) {
1838  if (rate == 24) tag = MKTAG('a','i','1','p');
1839  else if (rate == 25) tag = MKTAG('a','i','1','q');
1840  else if (rate == 30) tag = MKTAG('a','i','1','p');
1841  else if (rate == 50) tag = MKTAG('a','i','1','q');
1842  else if (rate == 60) tag = MKTAG('a','i','1','p');
1843  }
1844  } else if (track->par->width == 1920 && track->par->height == 1080) {
1845  if (!interlaced) {
1846  if (rate == 24) tag = MKTAG('a','i','1','3');
1847  else if (rate == 25) tag = MKTAG('a','i','1','2');
1848  else if (rate == 30) tag = MKTAG('a','i','1','3');
1849  } else {
1850  if (rate == 25) tag = MKTAG('a','i','1','5');
1851  else if (rate == 50) tag = MKTAG('a','i','1','5');
1852  else if (rate == 60) tag = MKTAG('a','i','1','6');
1853  }
1854  } else if ( track->par->width == 4096 && track->par->height == 2160
1855  || track->par->width == 3840 && track->par->height == 2160
1856  || track->par->width == 2048 && track->par->height == 1080) {
1857  tag = MKTAG('a','i','v','x');
1858  }
1859  }
1860 
1861  return tag;
1862 }
1863 
1865 {
1866  int tag = track->par->codec_tag;
1867 
1868  if (!tag)
1869  tag = MKTAG('e', 'v', 'c', '1');
1870 
1871  return tag;
1872 }
1873 
1874 static const struct {
1876  uint32_t tag;
1877  unsigned bps;
1878 } mov_pix_fmt_tags[] = {
1879  { AV_PIX_FMT_YUYV422, MKTAG('y','u','v','2'), 0 },
1880  { AV_PIX_FMT_YUYV422, MKTAG('y','u','v','s'), 0 },
1881  { AV_PIX_FMT_UYVY422, MKTAG('2','v','u','y'), 0 },
1882  { AV_PIX_FMT_RGB555BE,MKTAG('r','a','w',' '), 16 },
1883  { AV_PIX_FMT_RGB555LE,MKTAG('L','5','5','5'), 16 },
1884  { AV_PIX_FMT_RGB565LE,MKTAG('L','5','6','5'), 16 },
1885  { AV_PIX_FMT_RGB565BE,MKTAG('B','5','6','5'), 16 },
1886  { AV_PIX_FMT_GRAY16BE,MKTAG('b','1','6','g'), 16 },
1887  { AV_PIX_FMT_RGB24, MKTAG('r','a','w',' '), 24 },
1888  { AV_PIX_FMT_BGR24, MKTAG('2','4','B','G'), 24 },
1889  { AV_PIX_FMT_ARGB, MKTAG('r','a','w',' '), 32 },
1890  { AV_PIX_FMT_BGRA, MKTAG('B','G','R','A'), 32 },
1891  { AV_PIX_FMT_RGBA, MKTAG('R','G','B','A'), 32 },
1892  { AV_PIX_FMT_ABGR, MKTAG('A','B','G','R'), 32 },
1893  { AV_PIX_FMT_RGB48BE, MKTAG('b','4','8','r'), 48 },
1894 };
1895 
1897 {
1898  int tag = MKTAG('A','V','d','n');
1899  if (track->par->profile != AV_PROFILE_UNKNOWN &&
1900  track->par->profile != AV_PROFILE_DNXHD)
1901  tag = MKTAG('A','V','d','h');
1902  return tag;
1903 }
1904 
1906 {
1907  int tag = track->par->codec_tag;
1908  int i;
1909  enum AVPixelFormat pix_fmt;
1910 
1911  for (i = 0; i < FF_ARRAY_ELEMS(mov_pix_fmt_tags); i++) {
1912  if (track->par->format == mov_pix_fmt_tags[i].pix_fmt) {
1913  tag = mov_pix_fmt_tags[i].tag;
1915  if (track->par->codec_tag == mov_pix_fmt_tags[i].tag)
1916  break;
1917  }
1918  }
1919 
1921  track->par->bits_per_coded_sample);
1922  if (tag == MKTAG('r','a','w',' ') &&
1923  track->par->format != pix_fmt &&
1924  track->par->format != AV_PIX_FMT_GRAY8 &&
1925  track->par->format != AV_PIX_FMT_NONE)
1926  av_log(s, AV_LOG_ERROR, "%s rawvideo cannot be written to mov, output file will be unreadable\n",
1927  av_get_pix_fmt_name(track->par->format));
1928  return tag;
1929 }
1930 
1931 static unsigned int mov_get_codec_tag(AVFormatContext *s, MOVTrack *track)
1932 {
1933  unsigned int tag = track->par->codec_tag;
1934 
1935  // "rtp " is used to distinguish internally created RTP-hint tracks
1936  // (with rtp_ctx) from other tracks.
1937  if (tag == MKTAG('r','t','p',' '))
1938  tag = 0;
1939  if (!tag || (s->strict_std_compliance >= FF_COMPLIANCE_NORMAL &&
1940  (track->par->codec_id == AV_CODEC_ID_DVVIDEO ||
1941  track->par->codec_id == AV_CODEC_ID_RAWVIDEO ||
1942  track->par->codec_id == AV_CODEC_ID_H263 ||
1943  track->par->codec_id == AV_CODEC_ID_H264 ||
1944  track->par->codec_id == AV_CODEC_ID_DNXHD ||
1945  track->par->codec_id == AV_CODEC_ID_MPEG2VIDEO ||
1946  av_get_bits_per_sample(track->par->codec_id)))) { // pcm audio
1947  if (track->par->codec_id == AV_CODEC_ID_DVVIDEO)
1948  tag = mov_get_dv_codec_tag(s, track);
1949  else if (track->par->codec_id == AV_CODEC_ID_RAWVIDEO)
1950  tag = mov_get_rawvideo_codec_tag(s, track);
1951  else if (track->par->codec_id == AV_CODEC_ID_MPEG2VIDEO)
1953  else if (track->par->codec_id == AV_CODEC_ID_H264)
1954  tag = mov_get_h264_codec_tag(s, track);
1955  else if (track->par->codec_id == AV_CODEC_ID_EVC)
1956  tag = mov_get_evc_codec_tag(s, track);
1957  else if (track->par->codec_id == AV_CODEC_ID_DNXHD)
1958  tag = mov_get_dnxhd_codec_tag(s, track);
1959  else if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
1961  if (!tag) { // if no mac fcc found, try with Microsoft tags
1963  if (tag)
1964  av_log(s, AV_LOG_WARNING, "Using MS style video codec tag, "
1965  "the file may be unplayable!\n");
1966  }
1967  } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) {
1969  if (!tag) { // if no mac fcc found, try with Microsoft tags
1970  int ms_tag = ff_codec_get_tag(ff_codec_wav_tags, track->par->codec_id);
1971  if (ms_tag) {
1972  tag = MKTAG('m', 's', ((ms_tag >> 8) & 0xff), (ms_tag & 0xff));
1973  av_log(s, AV_LOG_WARNING, "Using MS style audio codec tag, "
1974  "the file may be unplayable!\n");
1975  }
1976  }
1977  } else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE)
1979  }
1980 
1981  return tag;
1982 }
1983 
1985  { AV_CODEC_ID_MJPEG, 0xD },
1986  { AV_CODEC_ID_PNG, 0xE },
1987  { AV_CODEC_ID_BMP, 0x1B },
1988  { AV_CODEC_ID_NONE, 0 },
1989 };
1990 
1991 static unsigned int validate_codec_tag(const AVCodecTag *const *tags,
1992  unsigned int tag, int codec_id)
1993 {
1994  int i;
1995 
1996  /**
1997  * Check that tag + id is in the table
1998  */
1999  for (i = 0; tags && tags[i]; i++) {
2000  const AVCodecTag *codec_tags = tags[i];
2001  while (codec_tags->id != AV_CODEC_ID_NONE) {
2002  if (ff_toupper4(codec_tags->tag) == ff_toupper4(tag) &&
2003  codec_tags->id == codec_id)
2004  return codec_tags->tag;
2005  codec_tags++;
2006  }
2007  }
2008  return 0;
2009 }
2010 
2011 static unsigned int mov_find_codec_tag(AVFormatContext *s, MOVTrack *track)
2012 {
2013  if (is_cover_image(track->st))
2015 
2016  if (track->mode == MODE_IPOD)
2017  if (!av_match_ext(s->url, "m4a") &&
2018  !av_match_ext(s->url, "m4v") &&
2019  !av_match_ext(s->url, "m4b"))
2020  av_log(s, AV_LOG_WARNING, "Warning, extension is not .m4a nor .m4v "
2021  "Quicktime/Ipod might not play the file\n");
2022 
2023  if (track->mode == MODE_MOV) {
2024  return mov_get_codec_tag(s, track);
2025  } else
2026  return validate_codec_tag(s->oformat->codec_tag, track->par->codec_tag,
2027  track->par->codec_id);
2028 }
2029 
2030 /** Write uuid atom.
2031  * Needed to make file play in iPods running newest firmware
2032  * goes after avcC atom in moov.trak.mdia.minf.stbl.stsd.avc1
2033  */
2035 {
2036  avio_wb32(pb, 28);
2037  ffio_wfourcc(pb, "uuid");
2038  avio_wb32(pb, 0x6b6840f2);
2039  avio_wb32(pb, 0x5f244fc5);
2040  avio_wb32(pb, 0xba39a51b);
2041  avio_wb32(pb, 0xcf0323f3);
2042  avio_wb32(pb, 0x0);
2043  return 28;
2044 }
2045 
2046 static const uint16_t fiel_data[] = {
2047  0x0000, 0x0100, 0x0201, 0x0206, 0x0209, 0x020e
2048 };
2049 
2050 static int mov_write_fiel_tag(AVIOContext *pb, MOVTrack *track, int field_order)
2051 {
2052  unsigned mov_field_order = 0;
2053  if (field_order < FF_ARRAY_ELEMS(fiel_data))
2054  mov_field_order = fiel_data[field_order];
2055  else
2056  return 0;
2057  avio_wb32(pb, 10);
2058  ffio_wfourcc(pb, "fiel");
2059  avio_wb16(pb, mov_field_order);
2060  return 10;
2061 }
2062 
2064 {
2065  MOVMuxContext *mov = s->priv_data;
2066  int ret = AVERROR_BUG;
2067  int64_t pos = avio_tell(pb);
2068  avio_wb32(pb, 0); /* size */
2069  avio_wl32(pb, track->tag); // store it byteswapped
2070  avio_wb32(pb, 0); /* Reserved */
2071  avio_wb16(pb, 0); /* Reserved */
2072  avio_wb16(pb, 1); /* Data-reference index */
2073 
2074  if (track->par->codec_id == AV_CODEC_ID_DVD_SUBTITLE)
2075  mov_write_esds_tag(pb, track);
2076  else if (track->par->codec_id == AV_CODEC_ID_TTML) {
2077  switch (track->par->codec_tag) {
2078  case MOV_ISMV_TTML_TAG:
2079  // ISMV dfxp requires no extradata.
2080  break;
2081  case MOV_MP4_TTML_TAG:
2082  // As specified in 14496-30, XMLSubtitleSampleEntry
2083  // Namespace
2084  avio_put_str(pb, "http://www.w3.org/ns/ttml");
2085  // Empty schema_location
2086  avio_w8(pb, 0);
2087  // Empty auxiliary_mime_types
2088  avio_w8(pb, 0);
2089  break;
2090  default:
2092  "Unknown codec tag '%s' utilized for TTML stream with "
2093  "index %d (track id %d)!\n",
2094  av_fourcc2str(track->par->codec_tag), track->st->index,
2095  track->track_id);
2096  return AVERROR(EINVAL);
2097  }
2098  } else if (track->par->extradata_size)
2099  avio_write(pb, track->par->extradata, track->par->extradata_size);
2100 
2101  if (mov->write_btrt &&
2102  ((ret = mov_write_btrt_tag(pb, track)) < 0))
2103  return ret;
2104 
2105  return update_size(pb, pos);
2106 }
2107 
2109 {
2110  int8_t stereo_mode;
2111 
2112  if (stereo_3d->flags != 0) {
2113  av_log(s, AV_LOG_WARNING, "Unsupported stereo_3d flags %x. st3d not written.\n", stereo_3d->flags);
2114  return 0;
2115  }
2116 
2117  switch (stereo_3d->type) {
2118  case AV_STEREO3D_2D:
2119  stereo_mode = 0;
2120  break;
2121  case AV_STEREO3D_TOPBOTTOM:
2122  stereo_mode = 1;
2123  break;
2125  stereo_mode = 2;
2126  break;
2127  default:
2128  av_log(s, AV_LOG_WARNING, "Unsupported stereo_3d type %s. st3d not written.\n", av_stereo3d_type_name(stereo_3d->type));
2129  return 0;
2130  }
2131  avio_wb32(pb, 13); /* size */
2132  ffio_wfourcc(pb, "st3d");
2133  avio_wb32(pb, 0); /* version = 0 & flags = 0 */
2134  avio_w8(pb, stereo_mode);
2135  return 13;
2136 }
2137 
2139 {
2140  int64_t sv3d_pos, svhd_pos, proj_pos;
2141  const char* metadata_source = s->flags & AVFMT_FLAG_BITEXACT ? "Lavf" : LIBAVFORMAT_IDENT;
2142 
2143  if (spherical_mapping->projection != AV_SPHERICAL_EQUIRECTANGULAR &&
2144  spherical_mapping->projection != AV_SPHERICAL_EQUIRECTANGULAR_TILE &&
2145  spherical_mapping->projection != AV_SPHERICAL_CUBEMAP) {
2146  av_log(s, AV_LOG_WARNING, "Unsupported projection %d. sv3d not written.\n", spherical_mapping->projection);
2147  return 0;
2148  }
2149 
2150  sv3d_pos = avio_tell(pb);
2151  avio_wb32(pb, 0); /* size */
2152  ffio_wfourcc(pb, "sv3d");
2153 
2154  svhd_pos = avio_tell(pb);
2155  avio_wb32(pb, 0); /* size */
2156  ffio_wfourcc(pb, "svhd");
2157  avio_wb32(pb, 0); /* version = 0 & flags = 0 */
2158  avio_put_str(pb, metadata_source);
2159  update_size(pb, svhd_pos);
2160 
2161  proj_pos = avio_tell(pb);
2162  avio_wb32(pb, 0); /* size */
2163  ffio_wfourcc(pb, "proj");
2164 
2165  avio_wb32(pb, 24); /* size */
2166  ffio_wfourcc(pb, "prhd");
2167  avio_wb32(pb, 0); /* version = 0 & flags = 0 */
2168  avio_wb32(pb, spherical_mapping->yaw);
2169  avio_wb32(pb, spherical_mapping->pitch);
2170  avio_wb32(pb, spherical_mapping->roll);
2171 
2172  switch (spherical_mapping->projection) {
2175  avio_wb32(pb, 28); /* size */
2176  ffio_wfourcc(pb, "equi");
2177  avio_wb32(pb, 0); /* version = 0 & flags = 0 */
2178  avio_wb32(pb, spherical_mapping->bound_top);
2179  avio_wb32(pb, spherical_mapping->bound_bottom);
2180  avio_wb32(pb, spherical_mapping->bound_left);
2181  avio_wb32(pb, spherical_mapping->bound_right);
2182  break;
2183  case AV_SPHERICAL_CUBEMAP:
2184  avio_wb32(pb, 20); /* size */
2185  ffio_wfourcc(pb, "cbmp");
2186  avio_wb32(pb, 0); /* version = 0 & flags = 0 */
2187  avio_wb32(pb, 0); /* layout */
2188  avio_wb32(pb, spherical_mapping->padding); /* padding */
2189  break;
2190  }
2191  update_size(pb, proj_pos);
2192 
2193  return update_size(pb, sv3d_pos);
2194 }
2195 
2196 static inline int64_t rescale_rational(AVRational q, int b)
2197 {
2198  return av_rescale(q.num, b, q.den);
2199 }
2200 
2202  const AVStereo3D *stereo3d)
2203 {
2204  if (!stereo3d->horizontal_field_of_view.num)
2205  return;
2206 
2207  avio_wb32(pb, 12); /* size */
2208  ffio_wfourcc(pb, "hfov");
2209  avio_wb32(pb, rescale_rational(stereo3d->horizontal_field_of_view, 1000));
2210 }
2211 
2213  const AVSphericalMapping *spherical_mapping)
2214 {
2215  avio_wb32(pb, 24); /* size */
2216  ffio_wfourcc(pb, "proj");
2217  avio_wb32(pb, 16); /* size */
2218  ffio_wfourcc(pb, "prji");
2219  avio_wb32(pb, 0); /* version + flags */
2220 
2221  switch (spherical_mapping->projection) {
2223  ffio_wfourcc(pb, "rect");
2224  break;
2226  ffio_wfourcc(pb, "equi");
2227  break;
2229  ffio_wfourcc(pb, "hequ");
2230  break;
2231  case AV_SPHERICAL_FISHEYE:
2232  ffio_wfourcc(pb, "fish");
2233  break;
2234  default:
2235  av_assert0(0);
2236  }
2237 }
2238 
2240  const AVStereo3D *stereo3d)
2241 {
2242  int64_t pos = avio_tell(pb);
2243  int view = 0;
2244 
2245  avio_wb32(pb, 0); /* size */
2246  ffio_wfourcc(pb, "eyes");
2247 
2248  // stri is mandatory
2249  avio_wb32(pb, 13); /* size */
2250  ffio_wfourcc(pb, "stri");
2251  avio_wb32(pb, 0); /* version + flags */
2252  switch (stereo3d->view) {
2253  case AV_STEREO3D_VIEW_LEFT:
2254  view |= 1 << 0;
2255  break;
2257  view |= 1 << 1;
2258  break;
2260  view |= (1 << 0) | (1 << 1);
2261  break;
2262  }
2263  view |= !!(stereo3d->flags & AV_STEREO3D_FLAG_INVERT) << 3;
2264  avio_w8(pb, view);
2265 
2266  // hero is optional
2267  if (stereo3d->primary_eye != AV_PRIMARY_EYE_NONE) {
2268  avio_wb32(pb, 13); /* size */
2269  ffio_wfourcc(pb, "hero");
2270  avio_wb32(pb, 0); /* version + flags */
2271  avio_w8(pb, stereo3d->primary_eye);
2272  }
2273 
2274  // it's not clear if cams is mandatory or optional
2275  if (stereo3d->baseline) {
2276  avio_wb32(pb, 24); /* size */
2277  ffio_wfourcc(pb, "cams");
2278  avio_wb32(pb, 16); /* size */
2279  ffio_wfourcc(pb, "blin");
2280  avio_wb32(pb, 0); /* version + flags */
2281  avio_wb32(pb, stereo3d->baseline);
2282  }
2283 
2284  // it's not clear if cmfy is mandatory or optional
2285  if (stereo3d->horizontal_disparity_adjustment.num) {
2286  avio_wb32(pb, 24); /* size */
2287  ffio_wfourcc(pb, "cmfy");
2288  avio_wb32(pb, 16); /* size */
2289  ffio_wfourcc(pb, "dadj");
2290  avio_wb32(pb, 0); /* version + flags */
2292  }
2293 
2294  return update_size(pb, pos);
2295 }
2296 
2298  const AVStereo3D *stereo3d,
2299  const AVSphericalMapping *spherical_mapping)
2300 {
2301  int64_t pos;
2302 
2303  if (spherical_mapping &&
2304  spherical_mapping->projection != AV_SPHERICAL_RECTILINEAR &&
2305  spherical_mapping->projection != AV_SPHERICAL_EQUIRECTANGULAR &&
2306  spherical_mapping->projection != AV_SPHERICAL_HALF_EQUIRECTANGULAR &&
2307  spherical_mapping->projection != AV_SPHERICAL_FISHEYE) {
2308  av_log(s, AV_LOG_WARNING, "Unsupported projection %d. proj not written.\n",
2309  spherical_mapping->projection);
2310  spherical_mapping = NULL;
2311  }
2312 
2313  if (stereo3d && (stereo3d->type == AV_STEREO3D_2D ||
2314  (!(stereo3d->flags & AV_STEREO3D_FLAG_INVERT) &&
2315  stereo3d->view == AV_STEREO3D_VIEW_UNSPEC &&
2316  stereo3d->primary_eye == AV_PRIMARY_EYE_NONE &&
2317  !stereo3d->baseline &&
2318  !stereo3d->horizontal_disparity_adjustment.num))) {
2319  av_log(s, AV_LOG_WARNING, "Unsupported stereo 3d metadata. eyes not written.\n");
2320  stereo3d = NULL;
2321  }
2322 
2323  if (!spherical_mapping && !stereo3d)
2324  return 0;
2325 
2326  pos = avio_tell(pb);
2327  avio_wb32(pb, 0); /* size */
2328  ffio_wfourcc(pb, "vexu");
2329 
2330  if (spherical_mapping)
2331  mov_write_vexu_proj_tag(s, pb, spherical_mapping);
2332 
2333  if (stereo3d)
2334  mov_write_eyes_tag(s, pb, stereo3d);
2335 
2336  return update_size(pb, pos);
2337 }
2338 
2340 {
2341  uint8_t buf[ISOM_DVCC_DVVC_SIZE];
2342 
2343  avio_wb32(pb, 32); /* size = 8 + 24 */
2344  if (dovi->dv_profile > 10)
2345  ffio_wfourcc(pb, "dvwC");
2346  else if (dovi->dv_profile > 7)
2347  ffio_wfourcc(pb, "dvvC");
2348  else
2349  ffio_wfourcc(pb, "dvcC");
2350 
2351  ff_isom_put_dvcc_dvvc(s, buf, dovi);
2352  avio_write(pb, buf, sizeof(buf));
2353 
2354  return 32; /* 8 + 24 */
2355 }
2356 
2357 static int mov_write_clap_tag(AVIOContext *pb, MOVTrack *track,
2358  uint32_t top, uint32_t bottom,
2359  uint32_t left, uint32_t right)
2360 {
2361  uint32_t cropped_width = track->par->width - left - right;
2362  uint32_t cropped_height = track->height - top - bottom;
2363  AVRational horizOff =
2364  av_sub_q((AVRational) { track->par->width - cropped_width, 2 },
2365  (AVRational) { left, 1 });
2366  AVRational vertOff =
2367  av_sub_q((AVRational) { track->height - cropped_height, 2 },
2368  (AVRational) { top, 1 });
2369 
2370  avio_wb32(pb, 40);
2371  ffio_wfourcc(pb, "clap");
2372  avio_wb32(pb, cropped_width); /* apertureWidthN */
2373  avio_wb32(pb, 1); /* apertureWidthD */
2374  avio_wb32(pb, cropped_height); /* apertureHeightN */
2375  avio_wb32(pb, 1); /* apertureHeightD */
2376 
2377  avio_wb32(pb, -horizOff.num);
2378  avio_wb32(pb, horizOff.den);
2379  avio_wb32(pb, -vertOff.num);
2380  avio_wb32(pb, vertOff.den);
2381 
2382  return 40;
2383 }
2384 
2385 static int mov_write_pasp_tag(AVIOContext *pb, MOVTrack *track)
2386 {
2387  AVRational sar;
2388  av_reduce(&sar.num, &sar.den, track->par->sample_aspect_ratio.num,
2389  track->par->sample_aspect_ratio.den, INT_MAX);
2390 
2391  avio_wb32(pb, 16);
2392  ffio_wfourcc(pb, "pasp");
2393  avio_wb32(pb, sar.num);
2394  avio_wb32(pb, sar.den);
2395  return 16;
2396 }
2397 
2398 static int mov_write_gama_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track, double gamma)
2399 {
2400  uint32_t gama = 0;
2401  if (gamma <= 0.0)
2402  gamma = av_csp_approximate_trc_gamma(track->par->color_trc);
2403  av_log(s, AV_LOG_DEBUG, "gamma value %g\n", gamma);
2404 
2405  if (gamma > 1e-6) {
2406  gama = (uint32_t)lrint((double)(1<<16) * gamma);
2407  av_log(s, AV_LOG_DEBUG, "writing gama value %"PRId32"\n", gama);
2408 
2409  av_assert0(track->mode == MODE_MOV);
2410  avio_wb32(pb, 12);
2411  ffio_wfourcc(pb, "gama");
2412  avio_wb32(pb, gama);
2413  return 12;
2414  } else {
2415  av_log(s, AV_LOG_WARNING, "gamma value unknown, unable to write gama atom\n");
2416  }
2417  return 0;
2418 }
2419 
2420 static int mov_write_colr_tag(AVIOContext *pb, MOVTrack *track, int prefer_icc)
2421 {
2422  int64_t pos = avio_tell(pb);
2423 
2424  // Ref (MOV): https://developer.apple.com/library/mac/technotes/tn2162/_index.html#//apple_ref/doc/uid/DTS40013070-CH1-TNTAG9
2425  // Ref (MP4): ISO/IEC 14496-12:2012
2426 
2427  if (prefer_icc) {
2429  track->st->codecpar->nb_coded_side_data,
2431 
2432  if (sd) {
2433  avio_wb32(pb, 12 + sd->size);
2434  ffio_wfourcc(pb, "colr");
2435  ffio_wfourcc(pb, "prof");
2436  avio_write(pb, sd->data, sd->size);
2437  return 12 + sd->size;
2438  }
2439  else {
2440  av_log(NULL, AV_LOG_INFO, "no ICC profile found, will write nclx/nclc colour info instead\n");
2441  }
2442  }
2443 
2444  /* We should only ever be called for MOV, MP4 and AVIF. */
2445  av_assert0(track->mode == MODE_MOV || track->mode == MODE_MP4 ||
2446  track->mode == MODE_AVIF);
2447 
2448  avio_wb32(pb, 0); /* size */
2449  ffio_wfourcc(pb, "colr");
2450  if (track->mode == MODE_MP4 || track->mode == MODE_AVIF)
2451  ffio_wfourcc(pb, "nclx");
2452  else
2453  ffio_wfourcc(pb, "nclc");
2454  // Do not try to guess the color info if it is AVCOL_PRI_UNSPECIFIED.
2455  // e.g., Dolby Vision for Apple devices should be set to AVCOL_PRI_UNSPECIFIED. See
2456  // https://developer.apple.com/av-foundation/High-Dynamic-Range-Metadata-for-Apple-Devices.pdf
2457  avio_wb16(pb, track->par->color_primaries);
2458  avio_wb16(pb, track->par->color_trc);
2459  avio_wb16(pb, track->par->color_space);
2460  if (track->mode == MODE_MP4 || track->mode == MODE_AVIF) {
2461  int full_range = track->par->color_range == AVCOL_RANGE_JPEG;
2462  avio_w8(pb, full_range << 7);
2463  }
2464 
2465  return update_size(pb, pos);
2466 }
2467 
2468 static int mov_write_clli_tag(AVIOContext *pb, MOVTrack *track)
2469 {
2470  const AVPacketSideData *side_data;
2471  const AVContentLightMetadata *content_light_metadata;
2472 
2473  side_data = av_packet_side_data_get(track->st->codecpar->coded_side_data,
2474  track->st->codecpar->nb_coded_side_data,
2476  if (!side_data) {
2477  return 0;
2478  }
2479  content_light_metadata = (const AVContentLightMetadata*)side_data->data;
2480 
2481  avio_wb32(pb, 12); // size
2482  ffio_wfourcc(pb, "clli");
2483  avio_wb16(pb, content_light_metadata->MaxCLL);
2484  avio_wb16(pb, content_light_metadata->MaxFALL);
2485  return 12;
2486 }
2487 
2488 static int mov_write_mdcv_tag(AVIOContext *pb, MOVTrack *track)
2489 {
2490  const int chroma_den = 50000;
2491  const int luma_den = 10000;
2492  const AVPacketSideData *side_data;
2493  const AVMasteringDisplayMetadata *metadata = NULL;
2494 
2495  side_data = av_packet_side_data_get(track->st->codecpar->coded_side_data,
2496  track->st->codecpar->nb_coded_side_data,
2498  if (side_data)
2499  metadata = (const AVMasteringDisplayMetadata*)side_data->data;
2500  if (!metadata || !metadata->has_primaries || !metadata->has_luminance) {
2501  return 0;
2502  }
2503 
2504  avio_wb32(pb, 32); // size
2505  ffio_wfourcc(pb, "mdcv");
2506  avio_wb16(pb, rescale_rational(metadata->display_primaries[1][0], chroma_den));
2507  avio_wb16(pb, rescale_rational(metadata->display_primaries[1][1], chroma_den));
2508  avio_wb16(pb, rescale_rational(metadata->display_primaries[2][0], chroma_den));
2509  avio_wb16(pb, rescale_rational(metadata->display_primaries[2][1], chroma_den));
2510  avio_wb16(pb, rescale_rational(metadata->display_primaries[0][0], chroma_den));
2511  avio_wb16(pb, rescale_rational(metadata->display_primaries[0][1], chroma_den));
2512  avio_wb16(pb, rescale_rational(metadata->white_point[0], chroma_den));
2513  avio_wb16(pb, rescale_rational(metadata->white_point[1], chroma_den));
2514  avio_wb32(pb, rescale_rational(metadata->max_luminance, luma_den));
2515  avio_wb32(pb, rescale_rational(metadata->min_luminance, luma_den));
2516  return 32;
2517 }
2518 
2519 static int mov_write_amve_tag(AVIOContext *pb, MOVTrack *track)
2520 {
2521  const int illuminance_den = 10000;
2522  const int ambient_den = 50000;
2523  const AVPacketSideData *side_data;
2524  const AVAmbientViewingEnvironment *ambient;
2525 
2526 
2527  side_data = av_packet_side_data_get(track->st->codecpar->coded_side_data,
2528  track->st->codecpar->nb_coded_side_data,
2530 
2531  if (!side_data)
2532  return 0;
2533 
2534  ambient = (const AVAmbientViewingEnvironment*)side_data->data;
2535  if (!ambient || !ambient->ambient_illuminance.num)
2536  return 0;
2537 
2538  avio_wb32(pb, 16); // size
2539  ffio_wfourcc(pb, "amve");
2540  avio_wb32(pb, rescale_rational(ambient->ambient_illuminance, illuminance_den));
2541  avio_wb16(pb, rescale_rational(ambient->ambient_light_x, ambient_den));
2542  avio_wb16(pb, rescale_rational(ambient->ambient_light_y, ambient_den));
2543  return 16;
2544 }
2545 
2546 static void find_compressor(char * compressor_name, int len, MOVTrack *track)
2547 {
2548  AVDictionaryEntry *encoder;
2549  int xdcam_res = (track->par->width == 1280 && track->par->height == 720)
2550  || (track->par->width == 1440 && track->par->height == 1080)
2551  || (track->par->width == 1920 && track->par->height == 1080);
2552 
2553  if ((track->mode == MODE_AVIF ||
2554  track->mode == MODE_MOV ||
2555  track->mode == MODE_MP4) &&
2556  (encoder = av_dict_get(track->st->metadata, "encoder", NULL, 0))) {
2557  av_strlcpy(compressor_name, encoder->value, 32);
2558  } else if (track->par->codec_id == AV_CODEC_ID_MPEG2VIDEO && xdcam_res) {
2560  AVStream *st = track->st;
2561  int rate = defined_frame_rate(NULL, st);
2562  av_strlcatf(compressor_name, len, "XDCAM");
2563  if (track->par->format == AV_PIX_FMT_YUV422P) {
2564  av_strlcatf(compressor_name, len, " HD422");
2565  } else if(track->par->width == 1440) {
2566  av_strlcatf(compressor_name, len, " HD");
2567  } else
2568  av_strlcatf(compressor_name, len, " EX");
2569 
2570  av_strlcatf(compressor_name, len, " %d%c", track->par->height, interlaced ? 'i' : 'p');
2571 
2572  av_strlcatf(compressor_name, len, "%d", rate * (interlaced + 1));
2573  }
2574 }
2575 
2577 {
2578  int64_t pos = avio_tell(pb);
2579  // Write sane defaults:
2580  // all_ref_pics_intra = 0 : all samples can use any type of reference.
2581  // intra_pred_used = 1 : intra prediction may or may not be used.
2582  // max_ref_per_pic = 15 : reserved value to indicate that any number of
2583  // reference images can be used.
2584  uint8_t ccstValue = (0 << 7) | /* all_ref_pics_intra */
2585  (1 << 6) | /* intra_pred_used */
2586  (15 << 2); /* max_ref_per_pic */
2587  avio_wb32(pb, 0); /* size */
2588  ffio_wfourcc(pb, "ccst");
2589  avio_wb32(pb, 0); /* Version & flags */
2590  avio_w8(pb, ccstValue);
2591  avio_wb24(pb, 0); /* reserved */
2592  return update_size(pb, pos);
2593 }
2594 
2595 static int mov_write_aux_tag(AVIOContext *pb, const char *aux_type)
2596 {
2597  int64_t pos = avio_tell(pb);
2598  avio_wb32(pb, 0); /* size */
2599  ffio_wfourcc(pb, aux_type);
2600  avio_wb32(pb, 0); /* Version & flags */
2601  avio_write(pb, "urn:mpeg:mpegB:cicp:systems:auxiliary:alpha\0", 44);
2602  return update_size(pb, pos);
2603 }
2604 
2606 {
2607  int ret = AVERROR_BUG;
2608  int64_t pos = avio_tell(pb);
2609  const AVPacketSideData *sd;
2610  char compressor_name[32] = { 0 };
2611  int avid = 0;
2612 
2613  int uncompressed_ycbcr = ((track->par->codec_id == AV_CODEC_ID_RAWVIDEO && track->par->format == AV_PIX_FMT_UYVY422)
2614  || (track->par->codec_id == AV_CODEC_ID_RAWVIDEO && track->par->format == AV_PIX_FMT_YUYV422)
2615  || track->par->codec_id == AV_CODEC_ID_V308
2616  || track->par->codec_id == AV_CODEC_ID_V408
2617  || track->par->codec_id == AV_CODEC_ID_V410
2618  || track->par->codec_id == AV_CODEC_ID_V210);
2619 
2620  avio_wb32(pb, 0); /* size */
2621  if (mov->encryption_scheme != MOV_ENC_NONE) {
2622  ffio_wfourcc(pb, "encv");
2623  } else {
2624  avio_wl32(pb, track->tag); // store it byteswapped
2625  }
2626  avio_wb32(pb, 0); /* Reserved */
2627  avio_wb16(pb, 0); /* Reserved */
2628  avio_wb16(pb, 1); /* Data-reference index */
2629 
2630  if (uncompressed_ycbcr) {
2631  avio_wb16(pb, 2); /* Codec stream version */
2632  } else {
2633  avio_wb16(pb, 0); /* Codec stream version */
2634  }
2635  avio_wb16(pb, 0); /* Codec stream revision (=0) */
2636  if (track->mode == MODE_MOV) {
2637  ffio_wfourcc(pb, "FFMP"); /* Vendor */
2638  if (track->par->codec_id == AV_CODEC_ID_RAWVIDEO || uncompressed_ycbcr) {
2639  avio_wb32(pb, 0); /* Temporal Quality */
2640  avio_wb32(pb, 0x400); /* Spatial Quality = lossless*/
2641  } else {
2642  avio_wb32(pb, 0x200); /* Temporal Quality = normal */
2643  avio_wb32(pb, 0x200); /* Spatial Quality = normal */
2644  }
2645  } else {
2646  ffio_fill(pb, 0, 3 * 4); /* Reserved */
2647  }
2648  avio_wb16(pb, track->par->width); /* Video width */
2649  avio_wb16(pb, track->height); /* Video height */
2650  avio_wb32(pb, 0x00480000); /* Horizontal resolution 72dpi */
2651  avio_wb32(pb, 0x00480000); /* Vertical resolution 72dpi */
2652  avio_wb32(pb, 0); /* Data size (= 0) */
2653  avio_wb16(pb, 1); /* Frame count (= 1) */
2654 
2655  find_compressor(compressor_name, 32, track);
2656  avio_w8(pb, strlen(compressor_name));
2657  avio_write(pb, compressor_name, 31);
2658 
2659  if (track->mode == MODE_MOV &&
2660  (track->par->codec_id == AV_CODEC_ID_V410 || track->par->codec_id == AV_CODEC_ID_V210))
2661  avio_wb16(pb, 0x18);
2662  else if (track->mode == MODE_MOV && track->par->bits_per_coded_sample)
2663  avio_wb16(pb, track->par->bits_per_coded_sample |
2664  (track->par->format == AV_PIX_FMT_GRAY8 ? 0x20 : 0));
2665  else
2666  avio_wb16(pb, 0x18); /* Reserved */
2667 
2668  if (track->mode == MODE_MOV && track->par->format == AV_PIX_FMT_PAL8) {
2669  int pal_size, i;
2670  avio_wb16(pb, 0); /* Color table ID */
2671  avio_wb32(pb, 0); /* Color table seed */
2672  avio_wb16(pb, 0x8000); /* Color table flags */
2673  if (track->par->bits_per_coded_sample < 0 || track->par->bits_per_coded_sample > 8)
2674  return AVERROR(EINVAL);
2675  pal_size = 1 << track->par->bits_per_coded_sample;
2676  avio_wb16(pb, pal_size - 1); /* Color table size (zero-relative) */
2677  for (i = 0; i < pal_size; i++) {
2678  uint32_t rgb = track->palette[i];
2679  uint16_t r = (rgb >> 16) & 0xff;
2680  uint16_t g = (rgb >> 8) & 0xff;
2681  uint16_t b = rgb & 0xff;
2682  avio_wb16(pb, 0);
2683  avio_wb16(pb, (r << 8) | r);
2684  avio_wb16(pb, (g << 8) | g);
2685  avio_wb16(pb, (b << 8) | b);
2686  }
2687  } else
2688  avio_wb16(pb, 0xffff); /* Reserved */
2689 
2690  if (track->tag == MKTAG('m','p','4','v'))
2691  mov_write_esds_tag(pb, track);
2692  else if (track->par->codec_id == AV_CODEC_ID_H263)
2693  mov_write_d263_tag(pb);
2694  else if (track->par->codec_id == AV_CODEC_ID_AVUI ||
2695  track->par->codec_id == AV_CODEC_ID_SVQ3) {
2696  mov_write_extradata_tag(pb, track);
2697  avio_wb32(pb, 0);
2698  } else if (track->par->codec_id == AV_CODEC_ID_DNXHD) {
2699  mov_write_avid_tag(pb, track);
2700  avid = 1;
2701  } else if (track->par->codec_id == AV_CODEC_ID_HEVC) {
2702  mov_write_hvcc_tag(pb, track);
2703  if (track->st->disposition & AV_DISPOSITION_MULTILAYER) {
2704  ret = mov_write_lhvc_tag(pb, track);
2705  if (ret < 0)
2706  av_log(mov->fc, AV_LOG_WARNING, "Not writing 'lhvC' atom for multilayer stream.\n");
2707  }
2708  } else if (track->par->codec_id == AV_CODEC_ID_VVC)
2709  mov_write_vvcc_tag(pb, track);
2710  else if (track->par->codec_id == AV_CODEC_ID_H264 && !TAG_IS_AVCI(track->tag)) {
2711  mov_write_avcc_tag(pb, track);
2712  if (track->mode == MODE_IPOD)
2714  }
2715  else if (track->par->codec_id ==AV_CODEC_ID_EVC) {
2716  mov_write_evcc_tag(pb, track);
2717  } else if (track->par->codec_id == AV_CODEC_ID_VP9) {
2718  mov_write_vpcc_tag(mov->fc, pb, track);
2719  } else if (track->par->codec_id == AV_CODEC_ID_AV1) {
2720  mov_write_av1c_tag(pb, track);
2721  } else if (track->par->codec_id == AV_CODEC_ID_VC1 && track->vos_len > 0)
2722  mov_write_dvc1_tag(pb, track);
2723  else if (track->par->codec_id == AV_CODEC_ID_VP6F ||
2724  track->par->codec_id == AV_CODEC_ID_VP6A) {
2725  /* Don't write any potential extradata here - the cropping
2726  * is signalled via the normal width/height fields. */
2727  } else if (track->par->codec_id == AV_CODEC_ID_R10K) {
2728  if (track->par->codec_tag == MKTAG('R','1','0','k'))
2729  mov_write_dpxe_tag(pb, track);
2730  } else if (track->vos_len > 0)
2731  mov_write_glbl_tag(pb, track);
2732 
2733  if (track->par->codec_id != AV_CODEC_ID_H264 &&
2734  track->par->codec_id != AV_CODEC_ID_MPEG4 &&
2735  track->par->codec_id != AV_CODEC_ID_DNXHD) {
2736  int field_order = track->par->field_order;
2737 
2738  if (field_order != AV_FIELD_UNKNOWN)
2739  mov_write_fiel_tag(pb, track, field_order);
2740  }
2741 
2742  if (mov->flags & FF_MOV_FLAG_WRITE_GAMA) {
2743  if (track->mode == MODE_MOV)
2744  mov_write_gama_tag(s, pb, track, mov->gamma);
2745  else
2746  av_log(mov->fc, AV_LOG_WARNING, "Not writing 'gama' atom. Format is not MOV.\n");
2747  }
2748  if (track->mode == MODE_MOV || track->mode == MODE_MP4 || track->mode == MODE_AVIF) {
2749  int has_color_info = track->par->color_primaries != AVCOL_PRI_UNSPECIFIED &&
2750  track->par->color_trc != AVCOL_TRC_UNSPECIFIED &&
2752  if (has_color_info || mov->flags & FF_MOV_FLAG_WRITE_COLR ||
2755  int prefer_icc = mov->flags & FF_MOV_FLAG_PREFER_ICC || !has_color_info;
2756  mov_write_colr_tag(pb, track, prefer_icc);
2757  }
2758  } else if (mov->flags & FF_MOV_FLAG_WRITE_COLR) {
2759  av_log(mov->fc, AV_LOG_WARNING, "Not writing 'colr' atom. Format is not MOV or MP4 or AVIF.\n");
2760  }
2761 
2762  if (track->mode == MODE_MOV || track->mode == MODE_MP4) {
2763  mov_write_clli_tag(pb, track);
2764  mov_write_mdcv_tag(pb, track);
2765  mov_write_amve_tag(pb, track);
2766  }
2767 
2768  if (track->mode == MODE_MP4 && mov->fc->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL) {
2770  track->st->codecpar->nb_coded_side_data,
2772  const AVPacketSideData *spherical_mapping = av_packet_side_data_get(track->st->codecpar->coded_side_data,
2773  track->st->codecpar->nb_coded_side_data,
2775  if (stereo_3d)
2776  mov_write_st3d_tag(s, pb, (AVStereo3D*)stereo_3d->data);
2777  if (spherical_mapping)
2778  mov_write_sv3d_tag(mov->fc, pb, (AVSphericalMapping*)spherical_mapping->data);
2779  }
2780 
2781  if (track->mode == MODE_MOV || (track->mode == MODE_MP4 &&
2783  const AVStereo3D *stereo3d = NULL;
2784  const AVSphericalMapping *spherical_mapping = NULL;
2785 
2787  track->st->codecpar->nb_coded_side_data,
2789  if (sd)
2790  stereo3d = (AVStereo3D *)sd->data;
2791 
2793  track->st->codecpar->nb_coded_side_data,
2795  if (sd)
2796  spherical_mapping = (AVSphericalMapping *)sd->data;
2797 
2798  if (stereo3d || spherical_mapping)
2799  mov_write_vexu_tag(s, pb, stereo3d, spherical_mapping);
2800  if (stereo3d)
2801  mov_write_hfov_tag(s, pb, stereo3d);
2802  }
2803 
2804  if (track->mode == MODE_MP4) {
2806  track->st->codecpar->nb_coded_side_data,
2808  if (dovi && mov->fc->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL) {
2810  } else if (dovi) {
2811  av_log(mov->fc, AV_LOG_WARNING, "Not writing 'dvcC'/'dvvC' box. Requires -strict unofficial.\n");
2812  }
2813  }
2814 
2815  if (track->par->sample_aspect_ratio.den && track->par->sample_aspect_ratio.num) {
2816  mov_write_pasp_tag(pb, track);
2817  }
2818 
2820  track->st->codecpar->nb_coded_side_data,
2822  if (sd && sd->size >= sizeof(uint32_t) * 4) {
2823  uint64_t top = AV_RL32(sd->data + 0);
2824  uint64_t bottom = AV_RL32(sd->data + 4);
2825  uint64_t left = AV_RL32(sd->data + 8);
2826  uint64_t right = AV_RL32(sd->data + 12);
2827 
2828  if ((left + right) >= track->par->width ||
2829  (top + bottom) >= track->height) {
2830  av_log(s, AV_LOG_ERROR, "Invalid cropping dimensions in stream side data\n");
2831  return AVERROR(EINVAL);
2832  }
2833  if (top || bottom || left || right)
2834  mov_write_clap_tag(pb, track, top, bottom, left, right);
2835  } else if (uncompressed_ycbcr)
2836  mov_write_clap_tag(pb, track, 0, 0, 0, 0);
2837 
2838  if (mov->encryption_scheme != MOV_ENC_NONE) {
2839  ff_mov_cenc_write_sinf_tag(track, pb, mov->encryption_kid);
2840  }
2841 
2842  if (mov->write_btrt &&
2843  ((ret = mov_write_btrt_tag(pb, track)) < 0))
2844  return ret;
2845 
2846  /* extra padding for avid stsd */
2847  /* https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/QTFFChap2/qtff2.html#//apple_ref/doc/uid/TP40000939-CH204-61112 */
2848  if (avid)
2849  avio_wb32(pb, 0);
2850 
2851  if (track->mode == MODE_AVIF) {
2852  mov_write_ccst_tag(pb);
2853  if (mov->nb_streams > 0 && track == &mov->tracks[1])
2854  mov_write_aux_tag(pb, "auxi");
2855  }
2856 
2857  return update_size(pb, pos);
2858 }
2859 
2860 static int mov_write_rtp_tag(AVIOContext *pb, MOVTrack *track)
2861 {
2862  int64_t pos = avio_tell(pb);
2863  avio_wb32(pb, 0); /* size */
2864  ffio_wfourcc(pb, "rtp ");
2865  avio_wb32(pb, 0); /* Reserved */
2866  avio_wb16(pb, 0); /* Reserved */
2867  avio_wb16(pb, 1); /* Data-reference index */
2868 
2869  avio_wb16(pb, 1); /* Hint track version */
2870  avio_wb16(pb, 1); /* Highest compatible version */
2871  avio_wb32(pb, track->max_packet_size); /* Max packet size */
2872 
2873  avio_wb32(pb, 12); /* size */
2874  ffio_wfourcc(pb, "tims");
2875  avio_wb32(pb, track->timescale);
2876 
2877  return update_size(pb, pos);
2878 }
2879 
2880 static int mov_write_source_reference_tag(AVIOContext *pb, MOVTrack *track, const char *reel_name)
2881 {
2882  uint64_t str_size =strlen(reel_name);
2883  int64_t pos = avio_tell(pb);
2884 
2885  if (str_size >= UINT16_MAX){
2886  av_log(NULL, AV_LOG_ERROR, "reel_name length %"PRIu64" is too large\n", str_size);
2887  avio_wb16(pb, 0);
2888  return AVERROR(EINVAL);
2889  }
2890 
2891  avio_wb32(pb, 0); /* size */
2892  ffio_wfourcc(pb, "name"); /* Data format */
2893  avio_wb16(pb, str_size); /* string size */
2894  avio_wb16(pb, track->language); /* langcode */
2895  avio_write(pb, reel_name, str_size); /* reel name */
2896  return update_size(pb,pos);
2897 }
2898 
2899 static int mov_write_tmcd_tag(AVIOContext *pb, MOVTrack *track)
2900 {
2901  int64_t pos = avio_tell(pb);
2902 #if 1
2903  int frame_duration;
2904  int nb_frames;
2905  AVDictionaryEntry *t = NULL;
2906 
2907  if (!track->st->avg_frame_rate.num || !track->st->avg_frame_rate.den) {
2908  av_log(NULL, AV_LOG_ERROR, "avg_frame_rate not set for tmcd track.\n");
2909  return AVERROR(EINVAL);
2910  } else {
2911  frame_duration = av_rescale(track->timescale, track->st->avg_frame_rate.den, track->st->avg_frame_rate.num);
2912  nb_frames = ROUNDED_DIV(track->st->avg_frame_rate.num, track->st->avg_frame_rate.den);
2913  }
2914 
2915  if (nb_frames > 255) {
2916  av_log(NULL, AV_LOG_ERROR, "fps %d is too large\n", nb_frames);
2917  return AVERROR(EINVAL);
2918  }
2919 
2920  avio_wb32(pb, 0); /* size */
2921  ffio_wfourcc(pb, "tmcd"); /* Data format */
2922  avio_wb32(pb, 0); /* Reserved */
2923  avio_wb32(pb, 1); /* Data reference index */
2924  avio_wb32(pb, 0); /* Flags */
2925  avio_wb32(pb, track->timecode_flags); /* Flags (timecode) */
2926  avio_wb32(pb, track->timescale); /* Timescale */
2927  avio_wb32(pb, frame_duration); /* Frame duration */
2928  avio_w8(pb, nb_frames); /* Number of frames */
2929  avio_w8(pb, 0); /* Reserved */
2930 
2931  t = av_dict_get(track->st->metadata, "reel_name", NULL, 0);
2932  if (t && utf8len(t->value) && track->mode != MODE_MP4)
2933  mov_write_source_reference_tag(pb, track, t->value);
2934  else
2935  avio_wb16(pb, 0); /* zero size */
2936 #else
2937 
2938  avio_wb32(pb, 0); /* size */
2939  ffio_wfourcc(pb, "tmcd"); /* Data format */
2940  avio_wb32(pb, 0); /* Reserved */
2941  avio_wb32(pb, 1); /* Data reference index */
2942  if (track->par->extradata_size)
2943  avio_write(pb, track->par->extradata, track->par->extradata_size);
2944 #endif
2945  return update_size(pb, pos);
2946 }
2947 
2948 static int mov_write_gpmd_tag(AVIOContext *pb, const MOVTrack *track)
2949 {
2950  int64_t pos = avio_tell(pb);
2951  avio_wb32(pb, 0); /* size */
2952  ffio_wfourcc(pb, "gpmd");
2953  avio_wb32(pb, 0); /* Reserved */
2954  avio_wb16(pb, 0); /* Reserved */
2955  avio_wb16(pb, 1); /* Data-reference index */
2956  avio_wb32(pb, 0); /* Reserved */
2957  return update_size(pb, pos);
2958 }
2959 
2961 {
2962  int64_t pos = avio_tell(pb);
2963  int ret = 0;
2964  avio_wb32(pb, 0); /* size */
2965  ffio_wfourcc(pb, "stsd");
2966  avio_wb32(pb, 0); /* version & flags */
2967  avio_wb32(pb, 1); /* entry count */
2968  if (track->par->codec_type == AVMEDIA_TYPE_VIDEO)
2969  ret = mov_write_video_tag(s, pb, mov, track);
2970  else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO)
2971  ret = mov_write_audio_tag(s, pb, mov, track);
2972  else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE)
2973  ret = mov_write_subtitle_tag(s, pb, track);
2974  else if (track->par->codec_tag == MKTAG('r','t','p',' '))
2975  ret = mov_write_rtp_tag(pb, track);
2976  else if (track->par->codec_tag == MKTAG('t','m','c','d'))
2977  ret = mov_write_tmcd_tag(pb, track);
2978  else if (track->par->codec_tag == MKTAG('g','p','m','d'))
2979  ret = mov_write_gpmd_tag(pb, track);
2980 
2981  if (ret < 0)
2982  return ret;
2983 
2984  return update_size(pb, pos);
2985 }
2986 
2988 {
2989  MOVMuxContext *mov = s->priv_data;
2990  MOVCtts *ctts_entries;
2991  uint32_t entries = 0;
2992  uint32_t atom_size;
2993  int i;
2994 
2995  ctts_entries = av_malloc_array((track->entry + 1), sizeof(*ctts_entries)); /* worst case */
2996  if (!ctts_entries)
2997  return AVERROR(ENOMEM);
2998  ctts_entries[0].count = 1;
2999  ctts_entries[0].duration = track->cluster[0].cts;
3000  for (i = 1; i < track->entry; i++) {
3001  if (track->cluster[i].cts == ctts_entries[entries].duration) {
3002  ctts_entries[entries].count++; /* compress */
3003  } else {
3004  entries++;
3005  ctts_entries[entries].duration = track->cluster[i].cts;
3006  ctts_entries[entries].count = 1;
3007  }
3008  }
3009  entries++; /* last one */
3010  atom_size = 16 + (entries * 8);
3011  avio_wb32(pb, atom_size); /* size */
3012  ffio_wfourcc(pb, "ctts");
3014  avio_w8(pb, 1); /* version */
3015  else
3016  avio_w8(pb, 0); /* version */
3017  avio_wb24(pb, 0); /* flags */
3018  avio_wb32(pb, entries); /* entry count */
3019  for (i = 0; i < entries; i++) {
3020  avio_wb32(pb, ctts_entries[i].count);
3021  avio_wb32(pb, ctts_entries[i].duration);
3022  }
3023  av_free(ctts_entries);
3024  return atom_size;
3025 }
3026 
3027 /* Time to sample atom */
3028 static int mov_write_stts_tag(AVIOContext *pb, MOVTrack *track)
3029 {
3030  MOVStts *stts_entries = NULL;
3031  uint32_t entries = -1;
3032  uint32_t atom_size;
3033  int i;
3034 
3035  if (track->par->codec_type == AVMEDIA_TYPE_AUDIO && !track->audio_vbr) {
3036  stts_entries = av_malloc(sizeof(*stts_entries)); /* one entry */
3037  if (!stts_entries)
3038  return AVERROR(ENOMEM);
3039  stts_entries[0].count = track->sample_count;
3040  stts_entries[0].duration = 1;
3041  entries = 1;
3042  } else {
3043  if (track->entry) {
3044  stts_entries = av_malloc_array(track->entry, sizeof(*stts_entries)); /* worst case */
3045  if (!stts_entries)
3046  return AVERROR(ENOMEM);
3047  }
3048  for (i = 0; i < track->entry; i++) {
3049  int duration = get_cluster_duration(track, i);
3050  if (i && duration == stts_entries[entries].duration) {
3051  stts_entries[entries].count++; /* compress */
3052  } else {
3053  entries++;
3054  stts_entries[entries].duration = duration;
3055  stts_entries[entries].count = 1;
3056  }
3057  }
3058  entries++; /* last one */
3059  }
3060  atom_size = 16 + (entries * 8);
3061  avio_wb32(pb, atom_size); /* size */
3062  ffio_wfourcc(pb, "stts");
3063  avio_wb32(pb, 0); /* version & flags */
3064  avio_wb32(pb, entries); /* entry count */
3065  for (i = 0; i < entries; i++) {
3066  avio_wb32(pb, stts_entries[i].count);
3067  avio_wb32(pb, stts_entries[i].duration);
3068  }
3069  av_free(stts_entries);
3070  return atom_size;
3071 }
3072 
3074 {
3075  avio_wb32(pb, 28); /* size */
3076  ffio_wfourcc(pb, "dref");
3077  avio_wb32(pb, 0); /* version & flags */
3078  avio_wb32(pb, 1); /* entry count */
3079 
3080  avio_wb32(pb, 0xc); /* size */
3081  //FIXME add the alis and rsrc atom
3082  ffio_wfourcc(pb, "url ");
3083  avio_wb32(pb, 1); /* version & flags */
3084 
3085  return 28;
3086 }
3087 
3089 {
3090  struct sgpd_entry {
3091  int count;
3092  int16_t roll_distance;
3093  int group_description_index;
3094  };
3095 
3096  struct sgpd_entry *sgpd_entries = NULL;
3097  int entries = -1;
3098  int group = 0;
3099  int i, j;
3100 
3101  const int OPUS_SEEK_PREROLL_MS = 80;
3102  int roll_samples = av_rescale_q(OPUS_SEEK_PREROLL_MS,
3103  (AVRational){1, 1000},
3104  (AVRational){1, 48000});
3105 
3106  if (!track->entry)
3107  return 0;
3108 
3109  sgpd_entries = av_malloc_array(track->entry, sizeof(*sgpd_entries));
3110  if (!sgpd_entries)
3111  return AVERROR(ENOMEM);
3112 
3114 
3115  if (track->par->codec_id == AV_CODEC_ID_OPUS) {
3116  for (i = 0; i < track->entry; i++) {
3117  int roll_samples_remaining = roll_samples;
3118  int distance = 0;
3119  for (j = i - 1; j >= 0; j--) {
3120  roll_samples_remaining -= get_cluster_duration(track, j);
3121  distance++;
3122  if (roll_samples_remaining <= 0)
3123  break;
3124  }
3125  /* We don't have enough preceeding samples to compute a valid
3126  roll_distance here, so this sample can't be independently
3127  decoded. */
3128  if (roll_samples_remaining > 0)
3129  distance = 0;
3130  /* Verify distance is a maximum of 32 (2.5ms) packets. */
3131  if (distance > 32)
3132  return AVERROR_INVALIDDATA;
3133  if (i && distance == sgpd_entries[entries].roll_distance) {
3134  sgpd_entries[entries].count++;
3135  } else {
3136  entries++;
3137  sgpd_entries[entries].count = 1;
3138  sgpd_entries[entries].roll_distance = distance;
3139  sgpd_entries[entries].group_description_index = distance ? ++group : 0;
3140  }
3141  }
3142  } else {
3143  entries++;
3144  sgpd_entries[entries].count = track->sample_count;
3145  sgpd_entries[entries].roll_distance = 1;
3146  sgpd_entries[entries].group_description_index = ++group;
3147  }
3148  entries++;
3149 
3150  if (!group) {
3151  av_free(sgpd_entries);
3152  return 0;
3153  }
3154 
3155  /* Write sgpd tag */
3156  avio_wb32(pb, 24 + (group * 2)); /* size */
3157  ffio_wfourcc(pb, "sgpd");
3158  avio_wb32(pb, 1 << 24); /* fullbox */
3159  ffio_wfourcc(pb, "roll");
3160  avio_wb32(pb, 2); /* default_length */
3161  avio_wb32(pb, group); /* entry_count */
3162  for (i = 0; i < entries; i++) {
3163  if (sgpd_entries[i].group_description_index) {
3164  avio_wb16(pb, -sgpd_entries[i].roll_distance); /* roll_distance */
3165  }
3166  }
3167 
3168  /* Write sbgp tag */
3169  avio_wb32(pb, 20 + (entries * 8)); /* size */
3170  ffio_wfourcc(pb, "sbgp");
3171  avio_wb32(pb, 0); /* fullbox */
3172  ffio_wfourcc(pb, "roll");
3173  avio_wb32(pb, entries); /* entry_count */
3174  for (i = 0; i < entries; i++) {
3175  avio_wb32(pb, sgpd_entries[i].count); /* sample_count */
3176  avio_wb32(pb, sgpd_entries[i].group_description_index); /* group_description_index */
3177  }
3178 
3179  av_free(sgpd_entries);
3180  return 0;
3181 }
3182 
3184 {
3185  int64_t pos = avio_tell(pb);
3186  int ret = 0;
3187 
3188  avio_wb32(pb, 0); /* size */
3189  ffio_wfourcc(pb, "stbl");
3190  if ((ret = mov_write_stsd_tag(s, pb, mov, track)) < 0)
3191  return ret;
3192  mov_write_stts_tag(pb, track);
3193  if ((track->par->codec_type == AVMEDIA_TYPE_VIDEO ||
3194  track->par->codec_id == AV_CODEC_ID_TRUEHD ||
3196  track->par->codec_tag == MKTAG('r','t','p',' ')) &&
3197  track->has_keyframes && track->has_keyframes < track->entry)
3198  mov_write_stss_tag(pb, track, MOV_SYNC_SAMPLE);
3199  if (track->par->codec_type == AVMEDIA_TYPE_VIDEO && track->has_disposable)
3200  mov_write_sdtp_tag(pb, track);
3201  if (track->mode == MODE_MOV && track->flags & MOV_TRACK_STPS)
3203  if (track->par->codec_type == AVMEDIA_TYPE_VIDEO &&
3204  track->flags & MOV_TRACK_CTTS && track->entry) {
3205 
3206  if ((ret = mov_write_ctts_tag(s, pb, track)) < 0)
3207  return ret;
3208  }
3209  mov_write_stsc_tag(pb, track);
3210  mov_write_stsz_tag(pb, track);
3211  mov_write_stco_tag(pb, track);
3212  if (track->cenc.aes_ctr) {
3213  ff_mov_cenc_write_stbl_atoms(&track->cenc, pb);
3214  }
3215  if (track->par->codec_id == AV_CODEC_ID_OPUS || track->par->codec_id == AV_CODEC_ID_AAC) {
3216  mov_preroll_write_stbl_atoms(pb, track);
3217  }
3218  return update_size(pb, pos);
3219 }
3220 
3222 {
3223  int64_t pos = avio_tell(pb);
3224  avio_wb32(pb, 0); /* size */
3225  ffio_wfourcc(pb, "dinf");
3226  mov_write_dref_tag(pb);
3227  return update_size(pb, pos);
3228 }
3229 
3231 {
3232  avio_wb32(pb, 12);
3233  ffio_wfourcc(pb, "nmhd");
3234  avio_wb32(pb, 0);
3235  return 12;
3236 }
3237 
3239 {
3240  avio_wb32(pb, 12);
3241  ffio_wfourcc(pb, "sthd");
3242  avio_wb32(pb, 0);
3243  return 12;
3244 }
3245 
3246 static int mov_write_tcmi_tag(AVIOContext *pb, MOVTrack *track)
3247 {
3248  int64_t pos = avio_tell(pb);
3249  const char *font = "Lucida Grande";
3250  avio_wb32(pb, 0); /* size */
3251  ffio_wfourcc(pb, "tcmi"); /* timecode media information atom */
3252  avio_wb32(pb, 0); /* version & flags */
3253  avio_wb16(pb, 0); /* text font */
3254  avio_wb16(pb, 0); /* text face */
3255  avio_wb16(pb, 12); /* text size */
3256  avio_wb16(pb, 0); /* (unknown, not in the QT specs...) */
3257  avio_wb16(pb, 0x0000); /* text color (red) */
3258  avio_wb16(pb, 0x0000); /* text color (green) */
3259  avio_wb16(pb, 0x0000); /* text color (blue) */
3260  avio_wb16(pb, 0xffff); /* background color (red) */
3261  avio_wb16(pb, 0xffff); /* background color (green) */
3262  avio_wb16(pb, 0xffff); /* background color (blue) */
3263  avio_w8(pb, strlen(font)); /* font len (part of the pascal string) */
3264  avio_write(pb, font, strlen(font)); /* font name */
3265  return update_size(pb, pos);
3266 }
3267 
3268 static int mov_write_gmhd_tag(AVIOContext *pb, MOVTrack *track)
3269 {
3270  int64_t pos = avio_tell(pb);
3271  avio_wb32(pb, 0); /* size */
3272  ffio_wfourcc(pb, "gmhd");
3273  avio_wb32(pb, 0x18); /* gmin size */
3274  ffio_wfourcc(pb, "gmin");/* generic media info */
3275  avio_wb32(pb, 0); /* version & flags */
3276  avio_wb16(pb, 0x40); /* graphics mode = */
3277  avio_wb16(pb, 0x8000); /* opColor (r?) */
3278  avio_wb16(pb, 0x8000); /* opColor (g?) */
3279  avio_wb16(pb, 0x8000); /* opColor (b?) */
3280  avio_wb16(pb, 0); /* balance */
3281  avio_wb16(pb, 0); /* reserved */
3282 
3283  /*
3284  * This special text atom is required for
3285  * Apple Quicktime chapters. The contents
3286  * don't appear to be documented, so the
3287  * bytes are copied verbatim.
3288  */
3289  if (track->tag != MKTAG('c','6','0','8')) {
3290  avio_wb32(pb, 0x2C); /* size */
3291  ffio_wfourcc(pb, "text");
3292  avio_wb16(pb, 0x01);
3293  avio_wb32(pb, 0x00);
3294  avio_wb32(pb, 0x00);
3295  avio_wb32(pb, 0x00);
3296  avio_wb32(pb, 0x01);
3297  avio_wb32(pb, 0x00);
3298  avio_wb32(pb, 0x00);
3299  avio_wb32(pb, 0x00);
3300  avio_wb32(pb, 0x00004000);
3301  avio_wb16(pb, 0x0000);
3302  }
3303 
3304  if (track->par->codec_tag == MKTAG('t','m','c','d')) {
3305  int64_t tmcd_pos = avio_tell(pb);
3306  avio_wb32(pb, 0); /* size */
3307  ffio_wfourcc(pb, "tmcd");
3308  mov_write_tcmi_tag(pb, track);
3309  update_size(pb, tmcd_pos);
3310  } else if (track->par->codec_tag == MKTAG('g','p','m','d')) {
3311  int64_t gpmd_pos = avio_tell(pb);
3312  avio_wb32(pb, 0); /* size */
3313  ffio_wfourcc(pb, "gpmd");
3314  avio_wb32(pb, 0); /* version */
3315  update_size(pb, gpmd_pos);
3316  }
3317  return update_size(pb, pos);
3318 }
3319 
3321 {
3322  avio_wb32(pb, 16); /* size */
3323  ffio_wfourcc(pb, "smhd");
3324  avio_wb32(pb, 0); /* version & flags */
3325  avio_wb16(pb, 0); /* reserved (balance, normally = 0) */
3326  avio_wb16(pb, 0); /* reserved */
3327  return 16;
3328 }
3329 
3331 {
3332  avio_wb32(pb, 0x14); /* size (always 0x14) */
3333  ffio_wfourcc(pb, "vmhd");
3334  avio_wb32(pb, 0x01); /* version & flags */
3335  avio_wb64(pb, 0); /* reserved (graphics mode = copy) */
3336  return 0x14;
3337 }
3338 
3339 static int is_clcp_track(MOVTrack *track)
3340 {
3341  return track->tag == MKTAG('c','7','0','8') ||
3342  track->tag == MKTAG('c','6','0','8');
3343 }
3344 
3346 {
3347  MOVMuxContext *mov = s->priv_data;
3348  const char *hdlr, *descr = NULL, *hdlr_type = NULL;
3349  int64_t pos = avio_tell(pb);
3350  size_t descr_len;
3351 
3352  hdlr = "dhlr";
3353  hdlr_type = "url ";
3354  descr = "DataHandler";
3355 
3356  if (track) {
3357  hdlr = (track->mode == MODE_MOV) ? "mhlr" : "\0\0\0\0";
3358  if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
3359  if (track->mode == MODE_AVIF) {
3360  hdlr_type = (track == &mov->tracks[0]) ? "pict" : "auxv";
3361  descr = "PictureHandler";
3362  } else {
3363  hdlr_type = "vide";
3364  descr = "VideoHandler";
3365  }
3366  } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) {
3367  hdlr_type = "soun";
3368  descr = "SoundHandler";
3369  } else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE) {
3370  if (is_clcp_track(track)) {
3371  hdlr_type = "clcp";
3372  descr = "ClosedCaptionHandler";
3373  } else {
3374  if (track->tag == MKTAG('t','x','3','g')) {
3375  hdlr_type = "sbtl";
3376  } else if (track->tag == MKTAG('m','p','4','s')) {
3377  hdlr_type = "subp";
3378  } else if (track->tag == MOV_MP4_TTML_TAG) {
3379  hdlr_type = "subt";
3380  } else {
3381  hdlr_type = "text";
3382  }
3383  descr = "SubtitleHandler";
3384  }
3385  } else if (track->par->codec_tag == MKTAG('r','t','p',' ')) {
3386  hdlr_type = "hint";
3387  descr = "HintHandler";
3388  } else if (track->par->codec_tag == MKTAG('t','m','c','d')) {
3389  hdlr_type = "tmcd";
3390  descr = "TimeCodeHandler";
3391  } else if (track->par->codec_tag == MKTAG('g','p','m','d')) {
3392  hdlr_type = "meta";
3393  descr = "GoPro MET"; // GoPro Metadata
3394  } else {
3396  "Unknown hdlr_type for %s, writing dummy values\n",
3397  av_fourcc2str(track->par->codec_tag));
3398  }
3399  if (track->st) {
3400  // hdlr.name is used by some players to identify the content title
3401  // of the track. So if an alternate handler description is
3402  // specified, use it.
3403  AVDictionaryEntry *t;
3404  t = av_dict_get(track->st->metadata, "handler_name", NULL, 0);
3405  if (t && utf8len(t->value))
3406  descr = t->value;
3407  }
3408  }
3409 
3410  if (mov->empty_hdlr_name) /* expressly allowed by QTFF and not prohibited in ISO 14496-12 8.4.3.3 */
3411  descr = "";
3412 
3413  avio_wb32(pb, 0); /* size */
3414  ffio_wfourcc(pb, "hdlr");
3415  avio_wb32(pb, 0); /* Version & flags */
3416  avio_write(pb, hdlr, 4); /* handler */
3417  ffio_wfourcc(pb, hdlr_type); /* handler type */
3418  avio_wb32(pb, 0); /* reserved */
3419  avio_wb32(pb, 0); /* reserved */
3420  avio_wb32(pb, 0); /* reserved */
3421  descr_len = strlen(descr);
3422  if (!track || track->mode == MODE_MOV)
3423  avio_w8(pb, descr_len); /* pascal string */
3424  avio_write(pb, descr, descr_len); /* handler description */
3425  if (track && track->mode != MODE_MOV)
3426  avio_w8(pb, 0); /* c string */
3427  return update_size(pb, pos);
3428 }
3429 
3430 static int mov_write_pitm_tag(AVIOContext *pb, int item_id)
3431 {
3432  int64_t pos = avio_tell(pb);
3433  avio_wb32(pb, 0); /* size */
3434  ffio_wfourcc(pb, "pitm");
3435  avio_wb32(pb, 0); /* Version & flags */
3436  avio_wb16(pb, item_id); /* item_id */
3437  return update_size(pb, pos);
3438 }
3439 
3441 {
3442  int64_t pos = avio_tell(pb);
3443  avio_wb32(pb, 0); /* size */
3444  ffio_wfourcc(pb, "iloc");
3445  avio_wb32(pb, 0); /* Version & flags */
3446  avio_w8(pb, (4 << 4) + 4); /* offset_size(4) and length_size(4) */
3447  avio_w8(pb, 0); /* base_offset_size(4) and reserved(4) */
3448  avio_wb16(pb, mov->nb_streams); /* item_count */
3449 
3450  for (int i = 0; i < mov->nb_streams; i++) {
3451  avio_wb16(pb, i + 1); /* item_id */
3452  avio_wb16(pb, 0); /* data_reference_index */
3453  avio_wb16(pb, 1); /* extent_count */
3454  mov->avif_extent_pos[i] = avio_tell(pb);
3455  avio_wb32(pb, 0); /* extent_offset (written later) */
3456  // For animated AVIF, we simply write the first packet's size.
3457  avio_wb32(pb, mov->avif_extent_length[i]); /* extent_length */
3458  }
3459 
3460  return update_size(pb, pos);
3461 }
3462 
3464 {
3465  int64_t iinf_pos = avio_tell(pb);
3466  avio_wb32(pb, 0); /* size */
3467  ffio_wfourcc(pb, "iinf");
3468  avio_wb32(pb, 0); /* Version & flags */
3469  avio_wb16(pb, mov->nb_streams); /* entry_count */
3470 
3471  for (int i = 0; i < mov->nb_streams; i++) {
3472  int64_t infe_pos = avio_tell(pb);
3473  avio_wb32(pb, 0); /* size */
3474  ffio_wfourcc(pb, "infe");
3475  avio_w8(pb, 0x2); /* Version */
3476  avio_wb24(pb, 0); /* flags */
3477  avio_wb16(pb, i + 1); /* item_id */
3478  avio_wb16(pb, 0); /* item_protection_index */
3479  avio_write(pb, "av01", 4); /* item_type */
3480  avio_write(pb, !i ? "Color\0" : "Alpha\0", 6); /* item_name */
3481  update_size(pb, infe_pos);
3482  }
3483 
3484  return update_size(pb, iinf_pos);
3485 }
3486 
3487 
3489 {
3490  int64_t auxl_pos;
3491  int64_t iref_pos = avio_tell(pb);
3492  avio_wb32(pb, 0); /* size */
3493  ffio_wfourcc(pb, "iref");
3494  avio_wb32(pb, 0); /* Version & flags */
3495 
3496  auxl_pos = avio_tell(pb);
3497  avio_wb32(pb, 0); /* size */
3498  ffio_wfourcc(pb, "auxl");
3499  avio_wb16(pb, 2); /* from_item_ID */
3500  avio_wb16(pb, 1); /* reference_count */
3501  avio_wb16(pb, 1); /* to_item_ID */
3502  update_size(pb, auxl_pos);
3503 
3504  return update_size(pb, iref_pos);
3505 }
3506 
3508  int stream_index)
3509 {
3510  int64_t pos = avio_tell(pb);
3511  avio_wb32(pb, 0); /* size */
3512  ffio_wfourcc(pb, "ispe");
3513  avio_wb32(pb, 0); /* Version & flags */
3514  avio_wb32(pb, s->streams[stream_index]->codecpar->width); /* image_width */
3515  avio_wb32(pb, s->streams[stream_index]->codecpar->height); /* image_height */
3516  return update_size(pb, pos);
3517 }
3518 
3520  int stream_index)
3521 {
3522  int64_t pos = avio_tell(pb);
3523  const AVPixFmtDescriptor *pixdesc =
3524  av_pix_fmt_desc_get(s->streams[stream_index]->codecpar->format);
3525  avio_wb32(pb, 0); /* size */
3526  ffio_wfourcc(pb, "pixi");
3527  avio_wb32(pb, 0); /* Version & flags */
3528  avio_w8(pb, pixdesc->nb_components); /* num_channels */
3529  for (int i = 0; i < pixdesc->nb_components; ++i) {
3530  avio_w8(pb, pixdesc->comp[i].depth); /* bits_per_channel */
3531  }
3532  return update_size(pb, pos);
3533 }
3534 
3536 {
3537  int64_t pos = avio_tell(pb);
3538  avio_wb32(pb, 0); /* size */
3539  ffio_wfourcc(pb, "ipco");
3540  for (int i = 0; i < mov->nb_streams; i++) {
3541  mov_write_ispe_tag(pb, mov, s, i);
3542  mov_write_pixi_tag(pb, mov, s, i);
3543  mov_write_av1c_tag(pb, &mov->tracks[i]);
3544  if (!i)
3545  mov_write_colr_tag(pb, &mov->tracks[0], 0);
3546  else
3547  mov_write_aux_tag(pb, "auxC");
3548  }
3549  return update_size(pb, pos);
3550 }
3551 
3553 {
3554  int64_t pos = avio_tell(pb);
3555  avio_wb32(pb, 0); /* size */
3556  ffio_wfourcc(pb, "ipma");
3557  avio_wb32(pb, 0); /* Version & flags */
3558  avio_wb32(pb, mov->nb_streams); /* entry_count */
3559 
3560  for (int i = 0, index = 1; i < mov->nb_streams; i++) {
3561  avio_wb16(pb, i + 1); /* item_ID */
3562  avio_w8(pb, 4); /* association_count */
3563 
3564  // ispe association.
3565  avio_w8(pb, index++); /* essential and property_index */
3566  // pixi association.
3567  avio_w8(pb, index++); /* essential and property_index */
3568  // av1C association.
3569  avio_w8(pb, 0x80 | index++); /* essential and property_index */
3570  // colr/auxC association.
3571  avio_w8(pb, index++); /* essential and property_index */
3572  }
3573  return update_size(pb, pos);
3574 }
3575 
3577 {
3578  int64_t pos = avio_tell(pb);
3579  avio_wb32(pb, 0); /* size */
3580  ffio_wfourcc(pb, "iprp");
3581  mov_write_ipco_tag(pb, mov, s);
3582  mov_write_ipma_tag(pb, mov, s);
3583  return update_size(pb, pos);
3584 }
3585 
3587 {
3588  /* This atom must be present, but leaving the values at zero
3589  * seems harmless. */
3590  avio_wb32(pb, 28); /* size */
3591  ffio_wfourcc(pb, "hmhd");
3592  avio_wb32(pb, 0); /* version, flags */
3593  avio_wb16(pb, 0); /* maxPDUsize */
3594  avio_wb16(pb, 0); /* avgPDUsize */
3595  avio_wb32(pb, 0); /* maxbitrate */
3596  avio_wb32(pb, 0); /* avgbitrate */
3597  avio_wb32(pb, 0); /* reserved */
3598  return 28;
3599 }
3600 
3602 {
3603  int64_t pos = avio_tell(pb);
3604  int ret;
3605 
3606  avio_wb32(pb, 0); /* size */
3607  ffio_wfourcc(pb, "minf");
3608  if (track->par->codec_type == AVMEDIA_TYPE_VIDEO)
3609  mov_write_vmhd_tag(pb);
3610  else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO)
3611  mov_write_smhd_tag(pb);
3612  else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE) {
3613  if (track->tag == MKTAG('t','e','x','t') || is_clcp_track(track)) {
3614  mov_write_gmhd_tag(pb, track);
3615  } else if (track->tag == MOV_MP4_TTML_TAG) {
3616  mov_write_sthd_tag(pb);
3617  } else {
3618  mov_write_nmhd_tag(pb);
3619  }
3620  } else if (track->tag == MKTAG('r','t','p',' ')) {
3621  mov_write_hmhd_tag(pb);
3622  } else if (track->tag == MKTAG('t','m','c','d')) {
3623  if (track->mode != MODE_MOV)
3624  mov_write_nmhd_tag(pb);
3625  else
3626  mov_write_gmhd_tag(pb, track);
3627  } else if (track->tag == MKTAG('g','p','m','d')) {
3628  mov_write_gmhd_tag(pb, track);
3629  }
3630  if (track->mode == MODE_MOV) /* ISO 14496-12 8.4.3.1 specifies hdlr only within mdia or meta boxes */
3631  mov_write_hdlr_tag(s, pb, NULL);
3632  mov_write_dinf_tag(pb);
3633  if ((ret = mov_write_stbl_tag(s, pb, mov, track)) < 0)
3634  return ret;
3635  return update_size(pb, pos);
3636 }
3637 
3638 static void get_pts_range(MOVMuxContext *mov, MOVTrack *track,
3639  int64_t *start, int64_t *end)
3640 {
3641  if (track->tag == MKTAG('t','m','c','d') && mov->nb_meta_tmcd) {
3642  // tmcd tracks gets track_duration set in mov_write_moov_tag from
3643  // another track's duration, while the end_pts may be left at zero.
3644  // Calculate the pts duration for that track instead.
3645  get_pts_range(mov, &mov->tracks[track->src_track], start, end);
3646  *start = av_rescale(*start, track->timescale,
3647  mov->tracks[track->src_track].timescale);
3648  *end = av_rescale(*end, track->timescale,
3649  mov->tracks[track->src_track].timescale);
3650  return;
3651  }
3652  if (track->end_pts != AV_NOPTS_VALUE &&
3653  track->start_dts != AV_NOPTS_VALUE &&
3654  track->start_cts != AV_NOPTS_VALUE) {
3655  *start = track->start_dts + track->start_cts;
3656  *end = track->end_pts;
3657  return;
3658  }
3659  *start = 0;
3660  *end = track->track_duration;
3661 }
3662 
3664 {
3665  int64_t start, end;
3666  get_pts_range(mov, track, &start, &end);
3667  return end - start;
3668 }
3669 
3670 // Calculate the actual duration of the track, after edits.
3671 // If it starts with a pts < 0, that is removed by the edit list.
3672 // If it starts with a pts > 0, the edit list adds a delay before that.
3673 // Thus, with edit lists enabled, the post-edit output of the file is
3674 // starting with pts=0.
3676 {
3677  int64_t start, end;
3678  get_pts_range(mov, track, &start, &end);
3679  if (mov->use_editlist != 0)
3680  start = 0;
3681  return end - start;
3682 }
3683 
3685 {
3686  if (track && track->mode == MODE_ISM)
3687  return 1;
3688  if (duration < INT32_MAX)
3689  return 0;
3690  return 1;
3691 }
3692 
3694  MOVTrack *track)
3695 {
3697  int version = mov_mdhd_mvhd_tkhd_version(mov, track, duration);
3698 
3699  (version == 1) ? avio_wb32(pb, 44) : avio_wb32(pb, 32); /* size */
3700  ffio_wfourcc(pb, "mdhd");
3701  avio_w8(pb, version);
3702  avio_wb24(pb, 0); /* flags */
3703  if (version == 1) {
3704  avio_wb64(pb, track->time);
3705  avio_wb64(pb, track->time);
3706  } else {
3707  avio_wb32(pb, track->time); /* creation time */
3708  avio_wb32(pb, track->time); /* modification time */
3709  }
3710  avio_wb32(pb, track->timescale); /* time scale (sample rate for audio) */
3711  if (!track->entry && mov->mode == MODE_ISM)
3712  (version == 1) ? avio_wb64(pb, UINT64_C(0xffffffffffffffff)) : avio_wb32(pb, 0xffffffff);
3713  else if (!track->entry)
3714  (version == 1) ? avio_wb64(pb, 0) : avio_wb32(pb, 0);
3715  else
3716  (version == 1) ? avio_wb64(pb, duration) : avio_wb32(pb, duration); /* duration */
3717  avio_wb16(pb, track->language); /* language */
3718  avio_wb16(pb, 0); /* reserved (quality) */
3719 
3720  if (version != 0 && track->mode == MODE_MOV) {
3722  "FATAL error, file duration too long for timebase, this file will not be\n"
3723  "playable with QuickTime. Choose a different timebase with "
3724  "-video_track_timescale or a different container format\n");
3725  }
3726 
3727  return 32;
3728 }
3729 
3731  MOVMuxContext *mov, MOVTrack *track)
3732 {
3733  int64_t pos = avio_tell(pb);
3734  int ret;
3735 
3736  avio_wb32(pb, 0); /* size */
3737  ffio_wfourcc(pb, "mdia");
3738  mov_write_mdhd_tag(pb, mov, track);
3739  mov_write_hdlr_tag(s, pb, track);
3740  if ((ret = mov_write_minf_tag(s, pb, mov, track)) < 0)
3741  return ret;
3742  return update_size(pb, pos);
3743 }
3744 
3745 /* transformation matrix
3746  |a b u|
3747  |c d v|
3748  |tx ty w| */
3749 static void write_matrix(AVIOContext *pb, int16_t a, int16_t b, int16_t c,
3750  int16_t d, int16_t tx, int16_t ty)
3751 {
3752  avio_wb32(pb, a << 16); /* 16.16 format */
3753  avio_wb32(pb, b << 16); /* 16.16 format */
3754  avio_wb32(pb, 0); /* u in 2.30 format */
3755  avio_wb32(pb, c << 16); /* 16.16 format */
3756  avio_wb32(pb, d << 16); /* 16.16 format */
3757  avio_wb32(pb, 0); /* v in 2.30 format */
3758  avio_wb32(pb, tx << 16); /* 16.16 format */
3759  avio_wb32(pb, ty << 16); /* 16.16 format */
3760  avio_wb32(pb, 1 << 30); /* w in 2.30 format */
3761 }
3762 
3764  MOVTrack *track, AVStream *st)
3765 {
3767  mov->movie_timescale, track->timescale,
3768  AV_ROUND_UP);
3769  int version;
3771  int group = 0;
3772 
3773  uint32_t *display_matrix = NULL;
3774  int i;
3775 
3776  if (mov->mode == MODE_AVIF)
3777  if (!mov->avif_loop_count)
3778  duration = INT64_MAX;
3779  else
3780  duration *= mov->avif_loop_count;
3781 
3782  if (st) {
3783  const AVPacketSideData *sd;
3784  if (mov->per_stream_grouping)
3785  group = st->index;
3786  else
3787  group = st->codecpar->codec_type;
3788 
3792  if (sd && sd->size == 9 * sizeof(*display_matrix))
3793  display_matrix = (uint32_t *)sd->data;
3794  }
3795 
3796  if (track->flags & MOV_TRACK_ENABLED)
3798 
3800 
3801  (version == 1) ? avio_wb32(pb, 104) : avio_wb32(pb, 92); /* size */
3802  ffio_wfourcc(pb, "tkhd");
3803  avio_w8(pb, version);
3804  avio_wb24(pb, flags);
3805  if (version == 1) {
3806  avio_wb64(pb, track->time);
3807  avio_wb64(pb, track->time);
3808  } else {
3809  avio_wb32(pb, track->time); /* creation time */
3810  avio_wb32(pb, track->time); /* modification time */
3811  }
3812  avio_wb32(pb, track->track_id); /* track-id */
3813  avio_wb32(pb, 0); /* reserved */
3814  if (!track->entry && mov->mode == MODE_ISM)
3815  (version == 1) ? avio_wb64(pb, UINT64_C(0xffffffffffffffff)) : avio_wb32(pb, 0xffffffff);
3816  else if (!track->entry)
3817  (version == 1) ? avio_wb64(pb, 0) : avio_wb32(pb, 0);
3818  else
3819  (version == 1) ? avio_wb64(pb, duration) : avio_wb32(pb, duration);
3820 
3821  avio_wb32(pb, 0); /* reserved */
3822  avio_wb32(pb, 0); /* reserved */
3823  avio_wb16(pb, 0); /* layer */
3824  avio_wb16(pb, group); /* alternate group) */
3825  /* Volume, only for audio */
3826  if (track->par->codec_type == AVMEDIA_TYPE_AUDIO)
3827  avio_wb16(pb, 0x0100);
3828  else
3829  avio_wb16(pb, 0);
3830  avio_wb16(pb, 0); /* reserved */
3831 
3832  /* Matrix structure */
3833  if (display_matrix) {
3834  for (i = 0; i < 9; i++)
3835  avio_wb32(pb, display_matrix[i]);
3836  } else {
3837  write_matrix(pb, 1, 0, 0, 1, 0, 0);
3838  }
3839  /* Track width and height, for visual only */
3840  if (st && (track->par->codec_type == AVMEDIA_TYPE_VIDEO ||
3841  track->par->codec_type == AVMEDIA_TYPE_SUBTITLE)) {
3842  int64_t track_width_1616;
3843  if (track->mode == MODE_MOV || track->mode == MODE_AVIF) {
3844  track_width_1616 = track->par->width * 0x10000ULL;
3845  } else {
3846  track_width_1616 = av_rescale(st->sample_aspect_ratio.num,
3847  track->par->width * 0x10000LL,
3848  st->sample_aspect_ratio.den);
3849  if (!track_width_1616 ||
3850  track->height != track->par->height ||
3851  track_width_1616 > UINT32_MAX)
3852  track_width_1616 = track->par->width * 0x10000ULL;
3853  }
3854  if (track_width_1616 > UINT32_MAX) {
3855  av_log(mov->fc, AV_LOG_WARNING, "track width is too large\n");
3856  track_width_1616 = 0;
3857  }
3858  avio_wb32(pb, track_width_1616);
3859  if (track->height > 0xFFFF) {
3860  av_log(mov->fc, AV_LOG_WARNING, "track height is too large\n");
3861  avio_wb32(pb, 0);
3862  } else
3863  avio_wb32(pb, track->height * 0x10000U);
3864  } else {
3865  avio_wb32(pb, 0);
3866  avio_wb32(pb, 0);
3867  }
3868  return 0x5c;
3869 }
3870 
3871 static int mov_write_tapt_tag(AVIOContext *pb, MOVTrack *track)
3872 {
3874  track->par->sample_aspect_ratio.den);
3875 
3876  int64_t pos = avio_tell(pb);
3877 
3878  avio_wb32(pb, 0); /* size */
3879  ffio_wfourcc(pb, "tapt");
3880 
3881  avio_wb32(pb, 20);
3882  ffio_wfourcc(pb, "clef");
3883  avio_wb32(pb, 0);
3884  avio_wb32(pb, width << 16);
3885  avio_wb32(pb, track->par->height << 16);
3886 
3887  avio_wb32(pb, 20);
3888  ffio_wfourcc(pb, "prof");
3889  avio_wb32(pb, 0);
3890  avio_wb32(pb, width << 16);
3891  avio_wb32(pb, track->par->height << 16);
3892 
3893  avio_wb32(pb, 20);
3894  ffio_wfourcc(pb, "enof");
3895  avio_wb32(pb, 0);
3896  avio_wb32(pb, track->par->width << 16);
3897  avio_wb32(pb, track->par->height << 16);
3898 
3899  return update_size(pb, pos);
3900 }
3901 
3902 // This box is written in the following cases:
3903 // * Seems important for the psp playback. Without it the movie seems to hang.
3904 // * Used for specifying the looping behavior of animated AVIF (as specified
3905 // in Section 9.6 of the HEIF specification ISO/IEC 23008-12).
3907  MOVTrack *track)
3908 {
3910  mov->movie_timescale, track->timescale,
3911  AV_ROUND_UP);
3912  int version = duration < INT32_MAX ? 0 : 1;
3913  int entry_size, entry_count, size;
3914  int64_t delay, start_ct = track->start_cts;
3915  int64_t start_dts = track->start_dts;
3916  int flags = 0;
3917 
3918  if (track->entry) {
3919  if (start_dts != track->cluster[0].dts || start_ct != track->cluster[0].cts) {
3920 
3921  av_log(mov->fc, AV_LOG_DEBUG,
3922  "EDTS using dts:%"PRId64" cts:%d instead of dts:%"PRId64" cts:%"PRId64" tid:%d\n",
3923  track->cluster[0].dts, track->cluster[0].cts,
3924  start_dts, start_ct, track->track_id);
3925  start_dts = track->cluster[0].dts;
3926  start_ct = track->cluster[0].cts;
3927  }
3928  }
3929 
3930  delay = av_rescale_rnd(start_dts + start_ct, mov->movie_timescale,
3931  track->timescale, AV_ROUND_DOWN);
3932 
3933  if (mov->mode == MODE_AVIF) {
3934  delay = 0;
3935  // Section 9.6.3 of ISO/IEC 23008-12: flags specifies repetition of the
3936  // edit list as follows: (flags & 1) equal to 0 specifies that the edit
3937  // list is not repeated, while (flags & 1) equal to 1 specifies that the
3938  // edit list is repeated.
3939  flags = mov->avif_loop_count != 1;
3940  start_ct = 0;
3941  }
3942 
3943  version |= delay < INT32_MAX ? 0 : 1;
3944 
3945  entry_size = (version == 1) ? 20 : 12;
3946  entry_count = 1 + (delay > 0);
3947  size = 24 + entry_count * entry_size;
3948 
3949  /* write the atom data */
3950  avio_wb32(pb, size);
3951  ffio_wfourcc(pb, "edts");
3952  avio_wb32(pb, size - 8);
3953  ffio_wfourcc(pb, "elst");
3954  avio_w8(pb, version);
3955  avio_wb24(pb, flags); /* flags */
3956 
3957  avio_wb32(pb, entry_count);
3958  if (delay > 0) { /* add an empty edit to delay presentation */
3959  /* In the positive delay case, the delay includes the cts
3960  * offset, and the second edit list entry below trims out
3961  * the same amount from the actual content. This makes sure
3962  * that the offset last sample is included in the edit
3963  * list duration as well. */
3964  if (version == 1) {
3965  avio_wb64(pb, delay);
3966  avio_wb64(pb, -1);
3967  } else {
3968  avio_wb32(pb, delay);
3969  avio_wb32(pb, -1);
3970  }
3971  avio_wb32(pb, 0x00010000);
3972  } else if (mov->mode != MODE_AVIF) {
3973  /* Avoid accidentally ending up with start_ct = -1 which has got a
3974  * special meaning. Normally start_ct should end up positive or zero
3975  * here, but use FFMIN in case dts is a small positive integer
3976  * rounded to 0 when represented in movie timescale units. */
3977  av_assert0(av_rescale_rnd(start_dts, mov->movie_timescale, track->timescale, AV_ROUND_DOWN) <= 0);
3978  start_ct = -FFMIN(start_dts, 0);
3979  /* Note, this delay is calculated from the pts of the first sample,
3980  * ensuring that we don't reduce the duration for cases with
3981  * dts<0 pts=0. */
3982  duration += delay;
3983  }
3984 
3985  /* For fragmented files, we don't know the full length yet. Setting
3986  * duration to 0 allows us to only specify the offset, including
3987  * the rest of the content (from all future fragments) without specifying
3988  * an explicit duration. */
3989  if (mov->flags & FF_MOV_FLAG_FRAGMENT)
3990  duration = 0;
3991 
3992  /* duration */
3993  if (version == 1) {
3994  avio_wb64(pb, duration);
3995  avio_wb64(pb, start_ct);
3996  } else {
3997  avio_wb32(pb, duration);
3998  avio_wb32(pb, start_ct);
3999  }
4000  avio_wb32(pb, 0x00010000);
4001  return size;
4002 }
4003 
4004 static int mov_write_tref_tag(AVIOContext *pb, MOVTrack *track)
4005 {
4006  avio_wb32(pb, 20); // size
4007  ffio_wfourcc(pb, "tref");
4008  avio_wb32(pb, 12); // size (subatom)
4009  avio_wl32(pb, track->tref_tag);
4010  avio_wb32(pb, track->tref_id);
4011  return 20;
4012 }
4013 
4014 // goes at the end of each track! ... Critical for PSP playback ("Incompatible data" without it)
4016 {
4017  avio_wb32(pb, 0x34); /* size ... reports as 28 in mp4box! */
4018  ffio_wfourcc(pb, "uuid");
4019  ffio_wfourcc(pb, "USMT");
4020  avio_wb32(pb, 0x21d24fce);
4021  avio_wb32(pb, 0xbb88695c);
4022  avio_wb32(pb, 0xfac9c740);
4023  avio_wb32(pb, 0x1c); // another size here!
4024  ffio_wfourcc(pb, "MTDT");
4025  avio_wb32(pb, 0x00010012);
4026  avio_wb32(pb, 0x0a);
4027  avio_wb32(pb, 0x55c40000);
4028  avio_wb32(pb, 0x1);
4029  avio_wb32(pb, 0x0);
4030  return 0x34;
4031 }
4032 
4033 static int mov_write_udta_sdp(AVIOContext *pb, MOVTrack *track)
4034 {
4035  AVFormatContext *ctx = track->rtp_ctx;
4036  char buf[1000] = "";
4037  int len;
4038 
4039  ff_sdp_write_media(buf, sizeof(buf), ctx->streams[0], track->src_track,
4040  NULL, NULL, 0, 0, ctx);
4041  av_strlcatf(buf, sizeof(buf), "a=control:streamid=%d\r\n", track->track_id);
4042  len = strlen(buf);
4043 
4044  avio_wb32(pb, len + 24);
4045  ffio_wfourcc(pb, "udta");
4046  avio_wb32(pb, len + 16);
4047  ffio_wfourcc(pb, "hnti");
4048  avio_wb32(pb, len + 8);
4049  ffio_wfourcc(pb, "sdp ");
4050  avio_write(pb, buf, len);
4051  return len + 24;
4052 }
4053 
4055  const char *tag, const char *str)
4056 {
4057  int64_t pos = avio_tell(pb);
4058  AVDictionaryEntry *t = av_dict_get(st->metadata, str, NULL, 0);
4059  if (!t || !utf8len(t->value))
4060  return 0;
4061 
4062  avio_wb32(pb, 0); /* size */
4063  ffio_wfourcc(pb, tag); /* type */
4064  avio_write(pb, t->value, strlen(t->value)); /* UTF8 string value */
4065  return update_size(pb, pos);
4066 }
4067 
4068 static int mov_write_track_kind(AVIOContext *pb, const char *scheme_uri,
4069  const char *value)
4070 {
4071  int64_t pos = avio_tell(pb);
4072 
4073  /* Box|FullBox basics */
4074  avio_wb32(pb, 0); /* size placeholder */
4075  ffio_wfourcc(pb, (const unsigned char *)"kind");
4076  avio_w8(pb, 0); /* version = 0 */
4077  avio_wb24(pb, 0); /* flags = 0 */
4078 
4079  /* Required null-terminated scheme URI */
4080  avio_write(pb, (const unsigned char *)scheme_uri,
4081  strlen(scheme_uri));
4082  avio_w8(pb, 0);
4083 
4084  /* Optional value string */
4085  if (value && value[0])
4086  avio_write(pb, (const unsigned char *)value,
4087  strlen(value));
4088 
4089  avio_w8(pb, 0);
4090 
4091  return update_size(pb, pos);
4092 }
4093 
4095 {
4096  int ret = AVERROR_BUG;
4097 
4098  for (int i = 0; ff_mov_track_kind_table[i].scheme_uri; i++) {
4100 
4101  for (int j = 0; map.value_maps[j].disposition; j++) {
4102  const struct MP4TrackKindValueMapping value_map = map.value_maps[j];
4103  if (!(st->disposition & value_map.disposition))
4104  continue;
4105 
4106  if ((ret = mov_write_track_kind(pb, map.scheme_uri, value_map.value)) < 0)
4107  return ret;
4108  }
4109  }
4110 
4111  return 0;
4112 }
4113 
4115  AVStream *st)
4116 {
4117  AVIOContext *pb_buf;
4118  int ret, size;
4119  uint8_t *buf;
4120 
4121  if (!st)
4122  return 0;
4123 
4124  ret = avio_open_dyn_buf(&pb_buf);
4125  if (ret < 0)
4126  return ret;
4127 
4128  if (mov->mode & (MODE_MP4|MODE_MOV))
4129  mov_write_track_metadata(pb_buf, st, "name", "title");
4130 
4131  if (mov->mode & MODE_MP4) {
4132  if ((ret = mov_write_track_kinds(pb_buf, st)) < 0)
4133  return ret;
4134  }
4135 
4136  if ((size = avio_get_dyn_buf(pb_buf, &buf)) > 0) {
4137  avio_wb32(pb, size + 8);
4138  ffio_wfourcc(pb, "udta");
4139  avio_write(pb, buf, size);
4140  }
4141  ffio_free_dyn_buf(&pb_buf);
4142 
4143  return 0;
4144 }
4145 
4147  MOVTrack *track, AVStream *st)
4148 {
4149  int64_t pos = avio_tell(pb);
4150  int entry_backup = track->entry;
4151  int chunk_backup = track->chunkCount;
4152  int ret;
4153 
4154  /* If we want to have an empty moov, but some samples already have been
4155  * buffered (delay_moov), pretend that no samples have been written yet. */
4156  if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV)
4157  track->chunkCount = track->entry = 0;
4158 
4159  avio_wb32(pb, 0); /* size */
4160  ffio_wfourcc(pb, "trak");
4161  mov_write_tkhd_tag(pb, mov, track, st);
4162 
4163  av_assert2(mov->use_editlist >= 0);
4164 
4165  if (track->start_dts != AV_NOPTS_VALUE) {
4166  if (mov->use_editlist)
4167  mov_write_edts_tag(pb, mov, track); // PSP Movies and several other cases require edts box
4168  else if ((track->entry && track->cluster[0].dts) || track->mode == MODE_PSP || is_clcp_track(track))
4169  av_log(mov->fc, AV_LOG_WARNING,
4170  "Not writing any edit list even though one would have been required\n");
4171  }
4172 
4173  if (mov->is_animated_avif)
4174