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