FFmpeg
Loading...
Searching...
No Matches
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"
40#include "apv.h"
41#include "lcevc.h"
44#include "libavcodec/flac.h"
45#include "libavcodec/get_bits.h"
46
47#include "libavcodec/internal.h"
48#include "libavcodec/put_bits.h"
50#include "libavcodec/raw.h"
51#include "internal.h"
52#include "libavutil/avstring.h"
54#include "libavutil/csp.h"
55#include "libavutil/intfloat.h"
57#include "libavutil/libm.h"
58#include "libavutil/mem.h"
59#include "libavutil/opt.h"
60#include "libavutil/dict.h"
61#include "libavutil/pixdesc.h"
62#include "libavutil/stereo3d.h"
63#include "libavutil/timecode.h"
64#include "libavutil/dovi_meta.h"
65#include "libavutil/uuid.h"
66#include "hevc.h"
67#include "rtpenc.h"
68#include "nal.h"
69#include "mov_chan.h"
70#include "movenc_ttml.h"
71#include "mux.h"
72#include "rawutils.h"
73#include "ttmlenc.h"
74#include "version.h"
75#include "vpcc.h"
76#include "vvc.h"
77
78static const AVOption options[] = {
79 { "brand", "Override major brand", offsetof(MOVMuxContext, major_brand), AV_OPT_TYPE_STRING, {.str = NULL}, .flags = AV_OPT_FLAG_ENCODING_PARAM },
80 { "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},
81 { "encryption_key", "The media encryption key (hex)", offsetof(MOVMuxContext, encryption_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_ENCODING_PARAM },
82 { "encryption_kid", "The media encryption key identifier (hex)", offsetof(MOVMuxContext, encryption_kid), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_ENCODING_PARAM },
83 { "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 },
84 { "frag_duration", "Maximum fragment duration", offsetof(MOVMuxContext, max_fragment_duration), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
85 { "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 },
86 { "frag_size", "Maximum fragment size", offsetof(MOVMuxContext, max_fragment_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
87 { "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},
88 { "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},
89 { "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},
90 { "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},
91 { "movflags", "MOV muxer flags", offsetof(MOVMuxContext, flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, .unit = "movflags" },
92 { "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" },
93 { "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" },
94 { "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" },
95 { "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" },
96 { "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" },
97 { "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" },
98 { "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" },
99 { "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" },
100 { "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" },
101 { "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" },
102 { "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" },
103 { "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" },
104 { "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" },
105 { "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 },
106 { "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" },
107 { "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" },
108 { "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" },
109 { "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" },
110 { "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" },
111 { "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" },
112 { "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" },
113 { "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" },
114 { "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" },
115 { "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" },
116 { "hybrid_fragmented", "For recoverability, write a fragmented file that is converted to non-fragmented at the end.", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_HYBRID_FRAGMENTED}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, .unit = "movflags" },
117 { "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},
118 { "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},
119 { "movie_timescale", "set movie timescale", offsetof(MOVMuxContext, movie_timescale), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
121 { "skip_iods", "Skip writing iods atom.", offsetof(MOVMuxContext, iods_skip), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
122 { "use_editlist", "use edit list", offsetof(MOVMuxContext, use_editlist), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM},
123 { "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},
124 { "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},
125 { "write_btrt", "force or disable writing btrt", offsetof(MOVMuxContext, write_btrt), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM},
126 { "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"},
127 { "pts", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = MOV_PRFT_SRC_PTS}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM, .unit = "prft"},
128 { "wallclock", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = MOV_PRFT_SRC_WALLCLOCK}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM, .unit = "prft"},
129 { "write_tmcd", "force or disable writing tmcd", offsetof(MOVMuxContext, write_tmcd), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM},
130 { NULL },
131};
132
134 .class_name = "mov/mp4/tgp/psp/tg2/ipod/ismv/f4v muxer",
135 .item_name = av_default_item_name,
136 .option = options,
137 .version = LIBAVUTIL_VERSION_INT,
138};
139
140static int get_moov_size(AVFormatContext *s);
142
143static int utf8len(const uint8_t *b)
144{
145 int len = 0;
146 int val;
147 while (*b) {
148 GET_UTF8(val, *b++, return -1;)
149 len++;
150 }
151 return len;
152}
153
154//FIXME support 64 bit variant with wide placeholders
156{
157 int64_t curpos = avio_tell(pb);
158 avio_seek(pb, pos, SEEK_SET);
159 avio_wb32(pb, curpos - pos); /* rewrite size */
160 avio_seek(pb, curpos, SEEK_SET);
161
162 return curpos - pos;
163}
164
166{
167 int64_t curpos = avio_tell(pb);
168 avio_seek(pb, pos, SEEK_SET);
169 avio_wb32(pb, curpos - pos); /* rewrite size */
170 avio_skip(pb, 4);
171 avio_w8(pb, version); /* rewrite version */
172 avio_seek(pb, curpos, SEEK_SET);
173
174 return curpos - pos;
175}
176
177static int co64_required(const MOVTrack *track)
178{
179 if (track->entry > 0 && track->cluster[track->entry - 1].pos + track->data_offset > UINT32_MAX)
180 return 1;
181 return 0;
182}
183
184static int is_cover_image(const AVStream *st)
185{
186 /* Eg. AV_DISPOSITION_ATTACHED_PIC | AV_DISPOSITION_TIMED_THUMBNAILS
187 * is encoded as sparse video track */
188 return st && st->disposition == AV_DISPOSITION_ATTACHED_PIC;
189}
190
191static int rtp_hinting_needed(const AVStream *st)
192{
193 /* Add hint tracks for each real audio and video stream */
194 if (is_cover_image(st))
195 return 0;
196 return st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ||
198}
199
200/* Chunk offset atom */
202{
203 int i;
204 int mode64 = co64_required(track); // use 32 bit size variant if possible
205 int64_t pos = avio_tell(pb);
206 avio_wb32(pb, 0); /* size */
207 if (mode64)
208 ffio_wfourcc(pb, "co64");
209 else
210 ffio_wfourcc(pb, "stco");
211 avio_wb32(pb, 0); /* version & flags */
212 avio_wb32(pb, track->chunkCount); /* entry count */
213 for (i = 0; i < track->entry; i++) {
214 if (!track->cluster[i].chunkNum)
215 continue;
216 if (mode64 == 1)
217 avio_wb64(pb, track->cluster[i].pos + track->data_offset);
218 else
219 avio_wb32(pb, track->cluster[i].pos + track->data_offset);
220 }
221 return update_size(pb, pos);
222}
223
224/* Sample size atom */
226{
227 int equalChunks = 1;
228 int i, j, entries = 0, tst = -1, oldtst = -1;
229
230 int64_t pos = avio_tell(pb);
231 avio_wb32(pb, 0); /* size */
232 ffio_wfourcc(pb, "stsz");
233 avio_wb32(pb, 0); /* version & flags */
234
235 for (i = 0; i < track->entry; i++) {
236 tst = track->cluster[i].size / track->cluster[i].entries;
237 if (oldtst != -1 && tst != oldtst)
238 equalChunks = 0;
239 oldtst = tst;
240 entries += track->cluster[i].entries;
241 }
242 if (equalChunks && track->entry) {
243 int sSize = track->entry ? track->cluster[0].size / track->cluster[0].entries : 0;
244 sSize = FFMAX(1, sSize); // adpcm mono case could make sSize == 0
245 avio_wb32(pb, sSize); // sample size
246 avio_wb32(pb, entries); // sample count
247 } else {
248 avio_wb32(pb, 0); // sample size
249 avio_wb32(pb, entries); // sample count
250 for (i = 0; i < track->entry; i++) {
251 for (j = 0; j < track->cluster[i].entries; j++) {
252 avio_wb32(pb, track->cluster[i].size /
253 track->cluster[i].entries);
254 }
255 }
256 }
257 return update_size(pb, pos);
258}
259
260/* Sample to chunk atom */
262{
263 int index = 0, oldidx = -1, oldval = -1, i;
264 int64_t entryPos, curpos;
265
266 int64_t pos = avio_tell(pb);
267 avio_wb32(pb, 0); /* size */
268 ffio_wfourcc(pb, "stsc");
269 avio_wb32(pb, 0); // version & flags
270 entryPos = avio_tell(pb);
271 avio_wb32(pb, track->chunkCount); // entry count
272 for (i = 0; i < track->entry; i++) {
273 if ((oldval != track->cluster[i].samples_in_chunk ||
274 oldidx != track->cluster[i].stsd_index) && track->cluster[i].chunkNum) {
275 avio_wb32(pb, track->cluster[i].chunkNum); // first chunk
276 avio_wb32(pb, track->cluster[i].samples_in_chunk); // samples per chunk
277 avio_wb32(pb, track->cluster[i].stsd_index + 1); // sample description index
278 oldval = track->cluster[i].samples_in_chunk;
279 oldidx = track->cluster[i].stsd_index;
280 index++;
281 }
282 }
283 curpos = avio_tell(pb);
284 avio_seek(pb, entryPos, SEEK_SET);
285 avio_wb32(pb, index); // rewrite size
286 avio_seek(pb, curpos, SEEK_SET);
287
288 return update_size(pb, pos);
289}
290
291/* Sync sample atom */
292static int mov_write_stss_tag(AVIOContext *pb, MOVTrack *track, uint32_t flag)
293{
294 int64_t curpos, entryPos;
295 int i, index = 0;
296 int64_t pos = avio_tell(pb);
297 avio_wb32(pb, 0); // size
298 ffio_wfourcc(pb, flag == MOV_SYNC_SAMPLE ? "stss" : "stps");
299 avio_wb32(pb, 0); // version & flags
300 entryPos = avio_tell(pb);
301 avio_wb32(pb, track->entry); // entry count
302 for (i = 0; i < track->entry; i++) {
303 if (track->cluster[i].flags & flag) {
304 avio_wb32(pb, i + 1);
305 index++;
306 }
307 }
308 curpos = avio_tell(pb);
309 avio_seek(pb, entryPos, SEEK_SET);
310 avio_wb32(pb, index); // rewrite size
311 avio_seek(pb, curpos, SEEK_SET);
312 return update_size(pb, pos);
313}
314
315/* Sample dependency atom */
317{
318 int i;
319 uint8_t leading, dependent, reference, redundancy;
320 int64_t pos = avio_tell(pb);
321 avio_wb32(pb, 0); // size
322 ffio_wfourcc(pb, "sdtp");
323 avio_wb32(pb, 0); // version & flags
324 for (i = 0; i < track->entry; i++) {
325 dependent = MOV_SAMPLE_DEPENDENCY_YES;
326 leading = reference = redundancy = MOV_SAMPLE_DEPENDENCY_UNKNOWN;
327 if (track->cluster[i].flags & MOV_DISPOSABLE_SAMPLE) {
328 reference = MOV_SAMPLE_DEPENDENCY_NO;
329 }
330 if (track->cluster[i].flags & MOV_SYNC_SAMPLE) {
331 dependent = MOV_SAMPLE_DEPENDENCY_NO;
332 }
333 avio_w8(pb, (leading << 6) | (dependent << 4) |
334 (reference << 2) | redundancy);
335 }
336 return update_size(pb, pos);
337}
338
339#if CONFIG_IAMFENC
340static int mov_write_iacb_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
341{
342 AVIOContext *dyn_bc;
343 int64_t pos = avio_tell(pb);
344 uint8_t *dyn_buf = NULL;
345 int dyn_size;
346 int ret = avio_open_dyn_buf(&dyn_bc);
347 if (ret < 0)
348 return ret;
349
350 avio_wb32(pb, 0);
351 ffio_wfourcc(pb, "iacb");
352 avio_w8(pb, 1); // configurationVersion
353
354 ret = ff_iamf_write_descriptors(track->iamf, dyn_bc, s);
355 if (ret < 0) {
356 ffio_free_dyn_buf(&dyn_bc);
357 return ret;
358 }
359
360 dyn_size = avio_close_dyn_buf(dyn_bc, &dyn_buf);
361 ffio_write_leb(pb, dyn_size);
362 avio_write(pb, dyn_buf, dyn_size);
363 av_free(dyn_buf);
364
365 return update_size(pb, pos);
366}
367#endif
368
370{
371 avio_wb32(pb, 0x11); /* size */
372 if (track->mode == MODE_MOV) ffio_wfourcc(pb, "samr");
373 else ffio_wfourcc(pb, "damr");
374 ffio_wfourcc(pb, "FFMP");
375 avio_w8(pb, 0); /* decoder version */
376
377 avio_wb16(pb, 0x81FF); /* Mode set (all modes for AMR_NB) */
378 avio_w8(pb, 0x00); /* Mode change period (no restriction) */
379 avio_w8(pb, 0x01); /* Frames per sample */
380 return 0x11;
381}
382
383struct eac3_info {
385 uint8_t eof;
386 uint8_t ec3_done;
387 uint8_t num_blocks;
388
389 /* Layout of the EC3SpecificBox */
390 /* maximum bitrate */
391 uint16_t data_rate;
393 /* number of independent substreams */
394 uint8_t num_ind_sub;
395 struct {
396 /* sample rate code (see ff_ac3_sample_rate_tab) 2 bits */
397 uint8_t fscod;
398 /* bit stream identification 5 bits */
399 uint8_t bsid;
400 /* one bit reserved */
401 /* audio service mixing (not supported yet) 1 bit */
402 /* bit stream mode 3 bits */
403 uint8_t bsmod;
404 /* audio coding mode 3 bits */
405 uint8_t acmod;
406 /* sub woofer on 1 bit */
407 uint8_t lfeon;
408 /* 3 bits reserved */
409 /* number of dependent substreams associated with this substream 4 bits */
410 uint8_t num_dep_sub;
411 /* channel locations of the dependent substream(s), if any, 9 bits */
412 uint16_t chan_loc;
413 /* if there is no dependent substream, then one bit reserved instead */
414 } substream[1]; /* TODO: support 8 independent substreams */
415 /* indicates the decoding complexity, 8 bits */
417};
418
420{
421 struct eac3_info *info = track->eac3_priv;
422 PutBitContext pbc;
423 uint8_t buf[3];
424
425 if (!info || !info->ec3_done) {
427 "Cannot write moov atom before AC3 packets."
428 " Set the delay_moov flag to fix this.\n");
429 return AVERROR(EINVAL);
430 }
431
432 if (info->substream[0].bsid > 8) {
434 "RealAudio AC-3/DolbyNet with bsid %d is not defined by the "
435 "ISOBMFF specification in ETSI TS 102 366!\n",
436 info->substream[0].bsid);
437 return AVERROR(EINVAL);
438 }
439
440 if (info->ac3_bit_rate_code < 0) {
442 "No valid AC3 bit rate code for data rate of %d!\n",
443 info->data_rate);
444 return AVERROR(EINVAL);
445 }
446
447 avio_wb32(pb, 11);
448 ffio_wfourcc(pb, "dac3");
449
450 init_put_bits(&pbc, buf, sizeof(buf));
451 put_bits(&pbc, 2, info->substream[0].fscod);
452 put_bits(&pbc, 5, info->substream[0].bsid);
453 put_bits(&pbc, 3, info->substream[0].bsmod);
454 put_bits(&pbc, 3, info->substream[0].acmod);
455 put_bits(&pbc, 1, info->substream[0].lfeon);
456 put_bits(&pbc, 5, info->ac3_bit_rate_code); // bit_rate_code
457 put_bits(&pbc, 5, 0); // reserved
458
459 flush_put_bits(&pbc);
460 avio_write(pb, buf, sizeof(buf));
461
462 return 11;
463}
464
466{
467 AC3HeaderInfo *hdr = NULL;
468 struct eac3_info *info;
469 int num_blocks, ret;
470
471 if (!track->eac3_priv) {
472 if (!(track->eac3_priv = av_mallocz(sizeof(*info))))
473 return AVERROR(ENOMEM);
474
475 ((struct eac3_info *)track->eac3_priv)->ac3_bit_rate_code = -1;
476 }
477 info = track->eac3_priv;
478
479 if (!info->pkt && !(info->pkt = av_packet_alloc()))
480 return AVERROR(ENOMEM);
481
482 if (info->eof) {
483 av_assert1(!info->pkt->size);
484 ret = pkt->size;
485 goto end;
486 }
487
488 if ((ret = avpriv_ac3_parse_header(&hdr, pkt->data, pkt->size)) < 0) {
489 if (ret == AVERROR(ENOMEM))
490 goto end;
491
492 /* drop the packets until we see a good one */
493 if (!track->entry) {
494 av_log(mov->fc, AV_LOG_WARNING, "Dropping invalid packet from start of the stream\n");
495 ret = 0;
496 } else
498 goto end;
499 }
500
501 info->data_rate = FFMAX(info->data_rate, hdr->bit_rate / 1000);
503 hdr->ac3_bit_rate_code);
505
506 num_blocks = hdr->num_blocks;
507
508 if (!info->ec3_done) {
509 /* AC-3 substream must be the first one */
510 if (hdr->bitstream_id <= 10 && hdr->substreamid != 0) {
511 ret = AVERROR(EINVAL);
512 goto end;
513 }
514
515 /* this should always be the case, given that our AC-3 parser
516 * concatenates dependent frames to their independent parent */
519 /* substream ids must be incremental */
520 if (hdr->substreamid > info->num_ind_sub + 1) {
521 ret = AVERROR(EINVAL);
522 goto end;
523 }
524
525 if (hdr->substreamid == info->num_ind_sub + 1) {
526 //info->num_ind_sub++;
527 avpriv_request_sample(mov->fc, "Multiple independent substreams");
529 goto end;
530 } else if (hdr->substreamid < info->num_ind_sub ||
531 hdr->substreamid == 0 && info->substream[0].bsid) {
532 info->ec3_done = 1;
533 goto concatenate;
534 }
535 } else {
536 if (hdr->substreamid != 0) {
537 avpriv_request_sample(mov->fc, "Multiple non EAC3 independent substreams");
539 goto end;
540 }
541 }
542
543 /* fill the info needed for the "dec3" atom */
544 info->substream[hdr->substreamid].fscod = hdr->sr_code;
545 info->substream[hdr->substreamid].bsid = hdr->bitstream_id;
546 info->substream[hdr->substreamid].bsmod = hdr->bitstream_mode;
547 info->substream[hdr->substreamid].acmod = hdr->channel_mode;
548 info->substream[hdr->substreamid].lfeon = hdr->lfe_on;
549
550 if (track->par->codec_id == AV_CODEC_ID_AC3) {
551 // with AC-3 we only require the information of a single packet,
552 // so we can finish as soon as the basic values of the bit stream
553 // have been set to the track's informational structure.
554 info->ec3_done = 1;
555 goto concatenate;
556 }
557
558 /* Parse dependent substream(s), if any */
559 if (pkt->size != hdr->frame_size) {
560 int cumul_size = hdr->frame_size;
561 int parent = hdr->substreamid;
562
563 while (cumul_size != pkt->size) {
564 ret = avpriv_ac3_parse_header(&hdr, pkt->data + cumul_size, pkt->size - cumul_size);
565 if (ret < 0)
566 goto end;
568 ret = AVERROR(EINVAL);
569 goto end;
570 }
571 info->substream[parent].num_dep_sub++;
572 ret /= 8;
573
574 /* get the dependent stream channel map, if exists */
575 if (hdr->channel_map_present)
576 info->substream[parent].chan_loc |= (hdr->channel_map >> 5) & 0x1f;
577 else
578 info->substream[parent].chan_loc |= hdr->channel_mode;
579 cumul_size += hdr->frame_size;
580 }
581 }
582 }
583
584concatenate:
585 if (!info->num_blocks && num_blocks == 6) {
586 ret = pkt->size;
587 goto end;
588 }
589 else if (info->num_blocks + num_blocks > 6) {
591 goto end;
592 }
593
594 if (!info->num_blocks) {
595 ret = av_packet_ref(info->pkt, pkt);
596 if (!ret)
597 info->num_blocks = num_blocks;
598 goto end;
599 } else {
600 const AVPacketSideData *sd;
601 int64_t duration = pkt->duration;
602 if ((ret = av_grow_packet(info->pkt, pkt->size)) < 0)
603 goto end;
604 sd = av_packet_side_data_get(pkt->side_data, pkt->side_data_elems, AV_PKT_DATA_SKIP_SAMPLES);
605 if (sd && sd->size >= 10) {
606 uint8_t *buf = av_packet_new_side_data(info->pkt, AV_PKT_DATA_SKIP_SAMPLES, sd->size);
607 if (buf)
608 memcpy(buf, sd->data, sd->size);
609 if (track->par->frame_size)
610 duration = FFMAX(av_rescale_q(track->par->frame_size, (AVRational){ 1, track->par->sample_rate },
611 track->st->time_base), duration);
612 }
613 memcpy(info->pkt->data + info->pkt->size - pkt->size, pkt->data, pkt->size);
614 info->num_blocks += num_blocks;
615 info->pkt->duration += duration;
616 if (info->num_blocks != 6)
617 goto end;
619 av_packet_move_ref(pkt, info->pkt);
620 info->num_blocks = 0;
621 }
622 ret = pkt->size;
623
624end:
625 av_free(hdr);
626
627 return ret;
628}
629
631{
632 PutBitContext pbc;
633 uint8_t *buf;
634 struct eac3_info *info;
635 int size, i;
636
637 if (!track->eac3_priv) {
639 "Cannot write moov atom before EAC3 packets parsed.\n");
640 return AVERROR(EINVAL);
641 }
642
643 info = track->eac3_priv;
644 size = 2 + (4 * (info->num_ind_sub + 1)) + (2 * !!info->complexity_index_type_a);
645 buf = av_malloc(size);
646 if (!buf) {
647 return AVERROR(ENOMEM);
648 }
649
650 init_put_bits(&pbc, buf, size);
651 put_bits(&pbc, 13, info->data_rate);
652 put_bits(&pbc, 3, info->num_ind_sub);
653 for (i = 0; i <= info->num_ind_sub; i++) {
654 put_bits(&pbc, 2, info->substream[i].fscod);
655 put_bits(&pbc, 5, info->substream[i].bsid);
656 put_bits(&pbc, 1, 0); /* reserved */
657 put_bits(&pbc, 1, 0); /* asvc */
658 put_bits(&pbc, 3, info->substream[i].bsmod);
659 put_bits(&pbc, 3, info->substream[i].acmod);
660 put_bits(&pbc, 1, info->substream[i].lfeon);
661 put_bits(&pbc, 3, 0); /* reserved */
662 put_bits(&pbc, 4, info->substream[i].num_dep_sub);
663 if (!info->substream[i].num_dep_sub) {
664 put_bits(&pbc, 1, 0); /* reserved */
665 } else {
666 put_bits(&pbc, 9, info->substream[i].chan_loc);
667 }
668 }
669 if (info->complexity_index_type_a) {
670 put_bits(&pbc, 7, 0); /* reserved */
671 put_bits(&pbc, 1, 1); // flag_eac3_extension_type_a
672 put_bits(&pbc, 8, info->complexity_index_type_a);
673 }
674 flush_put_bits(&pbc);
675 size = put_bytes_output(&pbc);
676
677 avio_wb32(pb, size + 8);
678 ffio_wfourcc(pb, "dec3");
679 avio_write(pb, buf, size);
680
681 av_free(buf);
682
683 return size;
684}
685
686/**
687 * This function writes extradata "as is".
688 * Extradata must be formatted like a valid atom (with size and tag).
689 */
691{
692 avio_write(pb, track->extradata[track->last_stsd_index], track->extradata_size[track->last_stsd_index]);
693 return track->extradata_size[track->last_stsd_index];
694}
695
697{
698 avio_wb32(pb, 10);
699 ffio_wfourcc(pb, "enda");
700 avio_wb16(pb, 1); /* little endian */
701 return 10;
702}
703
705{
706 avio_wb32(pb, 10);
707 ffio_wfourcc(pb, "enda");
708 avio_wb16(pb, 0); /* big endian */
709 return 10;
710}
711
712static void put_descr(AVIOContext *pb, int tag, unsigned int size)
713{
714 int i = 3;
715 avio_w8(pb, tag);
716 for (; i > 0; i--)
717 avio_w8(pb, (size >> (7 * i)) | 0x80);
718 avio_w8(pb, size & 0x7F);
719}
720
721static unsigned compute_avg_bitrate(MOVTrack *track)
722{
723 uint64_t size = 0;
724 int i;
725 if (!track->track_duration)
726 return 0;
727 for (i = 0; i < track->entry; i++)
728 size += track->cluster[i].size;
729 return size * 8 * track->timescale / track->track_duration;
730}
731
733 uint32_t buffer_size; ///< Size of the decoding buffer for the elementary stream in bytes.
734 uint32_t max_bit_rate; ///< Maximum rate in bits/second over any window of one second.
735 uint32_t avg_bit_rate; ///< Average rate in bits/second over the entire presentation.
736};
737
739{
740 const AVPacketSideData *sd = track->st ?
744 AVCPBProperties *props = sd ? (AVCPBProperties *)sd->data : NULL;
745 struct mpeg4_bit_rate_values bit_rates = { 0 };
746
747 bit_rates.avg_bit_rate = compute_avg_bitrate(track);
748 if (!bit_rates.avg_bit_rate) {
749 // if the average bit rate cannot be calculated at this point, such as
750 // in the case of fragmented MP4, utilize the following values as
751 // fall-back in priority order:
752 //
753 // 1. average bit rate property
754 // 2. bit rate (usually average over the whole clip)
755 // 3. maximum bit rate property
756
757 if (props && props->avg_bitrate) {
758 bit_rates.avg_bit_rate = props->avg_bitrate;
759 } else if (track->par->bit_rate) {
760 bit_rates.avg_bit_rate = track->par->bit_rate;
761 } else if (props && props->max_bitrate) {
762 bit_rates.avg_bit_rate = props->max_bitrate;
763 }
764 }
765
766 // (FIXME should be max rate in any 1 sec window)
767 bit_rates.max_bit_rate = FFMAX(track->par->bit_rate,
768 bit_rates.avg_bit_rate);
769
770 // utilize values from properties if we have them available
771 if (props) {
772 // no avg_bitrate signals that the track is VBR
773 if (!props->avg_bitrate)
774 bit_rates.avg_bit_rate = props->avg_bitrate;
775 bit_rates.max_bit_rate = FFMAX(bit_rates.max_bit_rate,
776 props->max_bitrate);
777 bit_rates.buffer_size = props->buffer_size / 8;
778 }
779
780 return bit_rates;
781}
782
783static int mov_write_esds_tag(AVIOContext *pb, MOVTrack *track) // Basic
784{
785 struct mpeg4_bit_rate_values bit_rates = calculate_mpeg4_bit_rates(track);
786 int64_t pos = avio_tell(pb);
787 int decoder_specific_info_len = track->extradata_size[track->last_stsd_index] ?
788 5 + track->extradata_size[track->last_stsd_index] : 0;
789
790 avio_wb32(pb, 0); // size
791 ffio_wfourcc(pb, "esds");
792 avio_wb32(pb, 0); // Version
793
794 // ES descriptor
795 put_descr(pb, 0x03, 3 + 5+13 + decoder_specific_info_len + 5+1);
796 avio_wb16(pb, track->track_id);
797 avio_w8(pb, 0x00); // flags (= no flags)
798
799 // DecoderConfig descriptor
800 put_descr(pb, 0x04, 13 + decoder_specific_info_len);
801
802 // Object type indication
803 if ((track->par->codec_id == AV_CODEC_ID_MP2 ||
804 track->par->codec_id == AV_CODEC_ID_MP3) &&
805 track->par->sample_rate > 24000)
806 avio_w8(pb, 0x6B); // 11172-3
807 else
809
810 // the following fields is made of 6 bits to identify the streamtype (4 for video, 5 for audio)
811 // plus 1 bit to indicate upstream and 1 bit set to 1 (reserved)
813 avio_w8(pb, (0x38 << 2) | 1); // flags (= NeroSubpicStream)
814 else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO)
815 avio_w8(pb, 0x15); // flags (= Audiostream)
816 else
817 avio_w8(pb, 0x11); // flags (= Visualstream)
818
819 avio_wb24(pb, bit_rates.buffer_size); // Buffersize DB
820 avio_wb32(pb, bit_rates.max_bit_rate); // maxbitrate
821 avio_wb32(pb, bit_rates.avg_bit_rate);
822
823 if (track->extradata_size[track->last_stsd_index]) {
824 // DecoderSpecific info descriptor
825 put_descr(pb, 0x05, track->extradata_size[track->last_stsd_index]);
826 avio_write(pb, track->extradata[track->last_stsd_index],
827 track->extradata_size[track->last_stsd_index]);
828 }
829
830 // SL descriptor
831 put_descr(pb, 0x06, 1);
832 avio_w8(pb, 0x02);
833 return update_size(pb, pos);
834}
835
843
851
853{
854 int ret;
855 int64_t pos = avio_tell(pb);
856 avio_wb32(pb, 0);
857 avio_wl32(pb, track->tag); // store it byteswapped
858 track->par->codec_tag = av_bswap16(track->tag >> 16);
859 if ((ret = ff_put_wav_header(s, pb, track->par, 0)) < 0)
860 return ret;
861 return update_size(pb, pos);
862}
863
865{
866 int ret;
867 int64_t pos = avio_tell(pb);
868 avio_wb32(pb, 0);
869 ffio_wfourcc(pb, "wfex");
871 return ret;
872 return update_size(pb, pos);
873}
874
876{
877 int64_t pos = avio_tell(pb);
878 avio_wb32(pb, 0);
879 ffio_wfourcc(pb, "dfLa");
880 avio_w8(pb, 0); /* version */
881 avio_wb24(pb, 0); /* flags */
882
883 /* Expect the encoder to pass a METADATA_BLOCK_TYPE_STREAMINFO. */
885 return AVERROR_INVALIDDATA;
886
887 /* TODO: Write other METADATA_BLOCK_TYPEs if the encoder makes them available. */
888 avio_w8(pb, 1 << 7 | FLAC_METADATA_TYPE_STREAMINFO); /* LastMetadataBlockFlag << 7 | BlockType */
889 avio_wb24(pb, track->extradata_size[track->last_stsd_index]); /* Length */
890 avio_write(pb, track->extradata[track->last_stsd_index], track->extradata_size[track->last_stsd_index]); /* BlockData[Length] */
891
892 return update_size(pb, pos);
893}
894
896{
897 int64_t pos = avio_tell(pb);
899 avio_wb32(pb, 0);
900 ffio_wfourcc(pb, "dOps");
901 avio_w8(pb, 0); /* Version */
902 if (track->extradata_size[track->last_stsd_index] < 19) {
903 av_log(s, AV_LOG_ERROR, "invalid extradata size\n");
904 return AVERROR_INVALIDDATA;
905 }
906 /* extradata contains an Ogg OpusHead, other than byte-ordering and
907 OpusHead's preceding magic/version, OpusSpecificBox is currently
908 identical. */
909 channels = AV_RB8(track->extradata[track->last_stsd_index] + 9);
910 channel_map = AV_RB8(track->extradata[track->last_stsd_index] + 18);
911
912 avio_w8(pb, channels); /* OuputChannelCount */
913 avio_wb16(pb, AV_RL16(track->extradata[track->last_stsd_index] + 10)); /* PreSkip */
914 avio_wb32(pb, AV_RL32(track->extradata[track->last_stsd_index] + 12)); /* InputSampleRate */
915 avio_wb16(pb, AV_RL16(track->extradata[track->last_stsd_index] + 16)); /* OutputGain */
916 avio_w8(pb, channel_map); /* ChannelMappingFamily */
917 /* Write the rest of the header out without byte-swapping. */
918 if (channel_map) {
919 if (track->extradata_size[track->last_stsd_index] < 21 + channels) {
920 av_log(s, AV_LOG_ERROR, "invalid extradata size\n");
921 return AVERROR_INVALIDDATA;
922 }
923 avio_write(pb, track->extradata[track->last_stsd_index] + 19, 2 + channels); /* ChannelMappingTable */
924 }
925
926 return update_size(pb, pos);
927}
928
930{
931 int64_t pos = avio_tell(pb);
932 int length;
933 avio_wb32(pb, 0);
934 ffio_wfourcc(pb, "dmlp");
935
936 if (track->extradata_size[track->last_stsd_index] < 20) {
938 "Cannot write moov atom before TrueHD packets."
939 " Set the delay_moov flag to fix this.\n");
940 return AVERROR(EINVAL);
941 }
942
943 length = (AV_RB16(track->extradata[track->last_stsd_index]) & 0xFFF) * 2;
944 if (length < 20 || length > track->extradata_size[track->last_stsd_index])
945 return AVERROR_INVALIDDATA;
946
947 // Only TrueHD is supported
948 if (AV_RB32(track->extradata[track->last_stsd_index] + 4) != 0xF8726FBA)
949 return AVERROR_INVALIDDATA;
950
951 avio_wb32(pb, AV_RB32(track->extradata[track->last_stsd_index] + 8)); /* format_info */
952 avio_wb16(pb, AV_RB16(track->extradata[track->last_stsd_index] + 18) << 1); /* peak_data_rate */
953 avio_wb32(pb, 0); /* reserved */
954
955 return update_size(pb, pos);
956}
957
959{
960 const AVDictionaryEntry *str = av_dict_get(track->st->metadata, "SA3D", NULL, 0);
961 AVChannelLayout ch_layout = { 0 };
962 int64_t pos;
963 int ambisonic_order, ambi_channels, non_diegetic_channels;
964 int i, ret;
965
966 if (!str)
967 return 0;
968
969 ret = av_channel_layout_from_string(&ch_layout, str->value);
970 if (ret < 0) {
971 if (ret == AVERROR(EINVAL)) {
972invalid:
973 av_log(s, AV_LOG_ERROR, "Invalid SA3D layout: \"%s\"\n", str->value);
974 ret = 0;
975 }
976 av_channel_layout_uninit(&ch_layout);
977 return ret;
978 }
979
980 if (track->st->codecpar->ch_layout.nb_channels != ch_layout.nb_channels)
981 goto invalid;
982
983 ambisonic_order = av_channel_layout_ambisonic_order(&ch_layout);
984 if (ambisonic_order < 0)
985 goto invalid;
986
987 ambi_channels = (ambisonic_order + 1LL) * (ambisonic_order + 1LL);
988 non_diegetic_channels = ch_layout.nb_channels - ambi_channels;
989 if (non_diegetic_channels &&
990 (non_diegetic_channels != 2 ||
992 goto invalid;
993
994 av_log(s, AV_LOG_VERBOSE, "Inserting SA3D box with layout: \"%s\"\n", str->value);
995
996 pos = avio_tell(pb);
997
998 avio_wb32(pb, 0); // Size
999 ffio_wfourcc(pb, "SA3D");
1000 avio_w8(pb, 0); // version
1001 avio_w8(pb, (!!non_diegetic_channels) << 7); // head_locked_stereo and ambisonic_type
1002 avio_wb32(pb, ambisonic_order); // ambisonic_order
1003 avio_w8(pb, 0); // ambisonic_channel_ordering
1004 avio_w8(pb, 0); // ambisonic_normalization
1005 avio_wb32(pb, ch_layout.nb_channels); // num_channels
1006 for (i = 0; i < ambi_channels; i++)
1008 for (; i < ch_layout.nb_channels; i++)
1009 avio_wb32(pb, av_channel_layout_channel_from_index(&ch_layout, i) + ambi_channels);
1010
1011 av_channel_layout_uninit(&ch_layout);
1012
1013 return update_size(pb, pos);
1014}
1015
1017{
1018 uint32_t layout_tag, bitmap, *channel_desc;
1019 int64_t pos = avio_tell(pb);
1020 int num_desc, ret;
1021
1022 if (track->multichannel_as_mono)
1023 return 0;
1024
1025 ret = ff_mov_get_channel_layout_tag(track->par, &layout_tag,
1026 &bitmap, &channel_desc);
1027
1028 if (ret < 0) {
1029 if (ret == AVERROR(ENOSYS)) {
1030 av_log(s, AV_LOG_WARNING, "not writing 'chan' tag due to "
1031 "lack of channel information\n");
1032 ret = 0;
1033 }
1034
1035 return ret;
1036 }
1037
1038 /* no predefined tag found + ch_layout in AV_CHANNEL_ORDER_NATIVE
1039 * but bitstream channels not actually in native order */
1040 if (layout_tag == MOV_CH_LAYOUT_UNKNOWN)
1041 return 0;
1042
1043 if (layout_tag == MOV_CH_LAYOUT_MONO && track->mono_as_fc > 0) {
1044 av_assert0(!channel_desc);
1045 channel_desc = av_malloc(sizeof(*channel_desc));
1046 if (!channel_desc)
1047 return AVERROR(ENOMEM);
1048
1049 layout_tag = 0;
1050 bitmap = 0;
1051 *channel_desc = 3; // channel label "Center"
1052 }
1053
1054 num_desc = layout_tag ? 0 : track->par->ch_layout.nb_channels;
1055
1056 avio_wb32(pb, 0); // Size
1057 ffio_wfourcc(pb, "chan"); // Type
1058 avio_w8(pb, 0); // Version
1059 avio_wb24(pb, 0); // Flags
1060 avio_wb32(pb, layout_tag); // mChannelLayoutTag
1061 avio_wb32(pb, bitmap); // mChannelBitmap
1062 avio_wb32(pb, num_desc); // mNumberChannelDescriptions
1063
1064 for (int i = 0; i < num_desc; i++) {
1065 avio_wb32(pb, channel_desc[i]); // mChannelLabel
1066 avio_wb32(pb, 0); // mChannelFlags
1067 avio_wl32(pb, 0); // mCoordinates[0]
1068 avio_wl32(pb, 0); // mCoordinates[1]
1069 avio_wl32(pb, 0); // mCoordinates[2]
1070 }
1071
1072 av_free(channel_desc);
1073
1074 return update_size(pb, pos);
1075}
1076
1078{
1079 int64_t pos = avio_tell(pb);
1080
1081 avio_wb32(pb, 0); /* size */
1082 ffio_wfourcc(pb, "wave");
1083
1084 if (track->par->codec_id != AV_CODEC_ID_QDM2) {
1085 avio_wb32(pb, 12); /* size */
1086 ffio_wfourcc(pb, "frma");
1087 avio_wl32(pb, track->tag);
1088 }
1089
1090 if (track->par->codec_id == AV_CODEC_ID_AAC) {
1091 /* useless atom needed by mplayer, ipod, not needed by quicktime */
1092 avio_wb32(pb, 12); /* size */
1093 ffio_wfourcc(pb, "mp4a");
1094 avio_wb32(pb, 0);
1095 mov_write_esds_tag(pb, track);
1096 } else if (mov_pcm_le_gt16(track->par->codec_id)) {
1098 } else if (mov_pcm_be_gt16(track->par->codec_id)) {
1100 } else if (track->par->codec_id == AV_CODEC_ID_AMR_NB) {
1101 mov_write_amr_tag(pb, track);
1102 } else if (track->par->codec_id == AV_CODEC_ID_AC3) {
1103 mov_write_ac3_tag(s, pb, track);
1104 } else if (track->par->codec_id == AV_CODEC_ID_EAC3) {
1105 mov_write_eac3_tag(s, pb, track);
1106 } else if (track->par->codec_id == AV_CODEC_ID_ALAC ||
1107 track->par->codec_id == AV_CODEC_ID_QDM2) {
1108 mov_write_extradata_tag(pb, track);
1109 } else if (track->par->codec_id == AV_CODEC_ID_ADPCM_MS ||
1111 mov_write_ms_tag(s, pb, track);
1112 }
1113
1114 avio_wb32(pb, 8); /* size */
1115 avio_wb32(pb, 0); /* null tag */
1116
1117 return update_size(pb, pos);
1118}
1119
1120static int mov_write_dvc1_structs(MOVTrack *track, uint8_t *buf)
1121{
1122 uint8_t *unescaped;
1123 const uint8_t *start, *next, *end = track->extradata[track->last_stsd_index] +
1124 track->extradata_size[track->last_stsd_index];
1125 int unescaped_size, seq_found = 0;
1126 int level = 0, interlace = 0;
1127 int packet_seq = track->vc1_info.packet_seq;
1128 int packet_entry = track->vc1_info.packet_entry;
1129 int slices = track->vc1_info.slices;
1130 PutBitContext pbc;
1131
1132 if (track->start_dts == AV_NOPTS_VALUE) {
1133 /* No packets written yet, vc1_info isn't authoritative yet. */
1134 /* Assume inline sequence and entry headers. */
1135 packet_seq = packet_entry = 1;
1137 "moov atom written before any packets, unable to write correct "
1138 "dvc1 atom. Set the delay_moov flag to fix this.\n");
1139 }
1140
1142 if (!unescaped)
1143 return AVERROR(ENOMEM);
1144 start = find_next_marker(track->extradata[track->last_stsd_index], end);
1145 for (next = start; next < end; start = next) {
1146 GetBitContext gb;
1147 int size;
1148 next = find_next_marker(start + 4, end);
1149 size = next - start - 4;
1150 if (size <= 0)
1151 continue;
1152 unescaped_size = vc1_unescape_buffer(start + 4, size, unescaped);
1153 init_get_bits(&gb, unescaped, 8 * unescaped_size);
1154 if (AV_RB32(start) == VC1_CODE_SEQHDR) {
1155 int profile = get_bits(&gb, 2);
1156 if (profile != PROFILE_ADVANCED) {
1157 av_free(unescaped);
1158 return AVERROR(ENOSYS);
1159 }
1160 seq_found = 1;
1161 level = get_bits(&gb, 3);
1162 /* chromaformat, frmrtq_postproc, bitrtq_postproc, postprocflag,
1163 * width, height */
1164 skip_bits_long(&gb, 2 + 3 + 5 + 1 + 2*12);
1165 skip_bits(&gb, 1); /* broadcast */
1166 interlace = get_bits1(&gb);
1167 skip_bits(&gb, 4); /* tfcntrflag, finterpflag, reserved, psf */
1168 }
1169 }
1170 if (!seq_found) {
1171 av_free(unescaped);
1172 return AVERROR(ENOSYS);
1173 }
1174
1175 init_put_bits(&pbc, buf, 7);
1176 /* VC1DecSpecStruc */
1177 put_bits(&pbc, 4, 12); /* profile - advanced */
1178 put_bits(&pbc, 3, level);
1179 put_bits(&pbc, 1, 0); /* reserved */
1180 /* VC1AdvDecSpecStruc */
1181 put_bits(&pbc, 3, level);
1182 put_bits(&pbc, 1, 0); /* cbr */
1183 put_bits(&pbc, 6, 0); /* reserved */
1184 put_bits(&pbc, 1, !interlace); /* no interlace */
1185 put_bits(&pbc, 1, !packet_seq); /* no multiple seq */
1186 put_bits(&pbc, 1, !packet_entry); /* no multiple entry */
1187 put_bits(&pbc, 1, !slices); /* no slice code */
1188 put_bits(&pbc, 1, 0); /* no bframe */
1189 put_bits(&pbc, 1, 0); /* reserved */
1190
1191 /* framerate */
1192 if (track->st->avg_frame_rate.num > 0 && track->st->avg_frame_rate.den > 0)
1193 put_bits32(&pbc, track->st->avg_frame_rate.num / track->st->avg_frame_rate.den);
1194 else
1195 put_bits32(&pbc, 0xffffffff);
1196
1197 flush_put_bits(&pbc);
1198
1199 av_free(unescaped);
1200
1201 return 0;
1202}
1203
1205{
1206 uint8_t buf[7] = { 0 };
1207 int ret;
1208
1209 if ((ret = mov_write_dvc1_structs(track, buf)) < 0)
1210 return ret;
1211
1212 avio_wb32(pb, track->extradata_size[track->last_stsd_index] + 8 + sizeof(buf));
1213 ffio_wfourcc(pb, "dvc1");
1214 avio_write(pb, buf, sizeof(buf));
1215 avio_write(pb, track->extradata[track->last_stsd_index],
1216 track->extradata_size[track->last_stsd_index]);
1217
1218 return 0;
1219}
1220
1222{
1223 avio_wb32(pb, track->extradata_size[track->last_stsd_index] + 8);
1224 ffio_wfourcc(pb, "glbl");
1225 avio_write(pb, track->extradata[track->last_stsd_index],
1226 track->extradata_size[track->last_stsd_index]);
1227 return 8 + track->extradata_size[track->last_stsd_index];
1228}
1229
1230/**
1231 * Compute flags for 'lpcm' tag.
1232 * See CoreAudioTypes and AudioStreamBasicDescription at Apple.
1233 */
1235{
1236 switch (codec_id) {
1239 return 11;
1242 return 9;
1243 case AV_CODEC_ID_PCM_U8:
1244 return 10;
1248 return 14;
1249 case AV_CODEC_ID_PCM_S8:
1253 return 12;
1254 default:
1255 return 0;
1256 }
1257}
1258
1259static int get_cluster_duration(MOVTrack *track, int cluster_idx)
1260{
1261 int64_t next_dts;
1262
1263 if (cluster_idx >= track->entry)
1264 return 0;
1265
1266 if (cluster_idx + 1 == track->entry)
1267 next_dts = track->track_duration + track->start_dts;
1268 else
1269 next_dts = track->cluster[cluster_idx + 1].dts;
1270
1271 next_dts -= track->cluster[cluster_idx].dts;
1272
1273 av_assert0(next_dts >= 0);
1274 av_assert0(next_dts <= INT_MAX);
1275
1276 return next_dts;
1277}
1278
1280{
1281 int i, first_duration;
1282
1283 /* use 1 for raw PCM */
1284 if (!track->audio_vbr)
1285 return 1;
1286
1287 /* check to see if duration is constant for all clusters */
1288 if (!track->entry)
1289 return 0;
1290 first_duration = get_cluster_duration(track, 0);
1291 for (i = 1; i < track->entry; i++) {
1292 if (get_cluster_duration(track, i) != first_duration)
1293 return 0;
1294 }
1295 return first_duration;
1296}
1297
1299{
1300 int64_t pos = avio_tell(pb);
1301 struct mpeg4_bit_rate_values bit_rates = calculate_mpeg4_bit_rates(track);
1302 if (!bit_rates.max_bit_rate && !bit_rates.avg_bit_rate &&
1303 !bit_rates.buffer_size)
1304 // no useful data to be written, skip
1305 return 0;
1306
1307 avio_wb32(pb, 0); /* size */
1308 ffio_wfourcc(pb, "btrt");
1309
1310 avio_wb32(pb, bit_rates.buffer_size);
1311 avio_wb32(pb, bit_rates.max_bit_rate);
1312 avio_wb32(pb, bit_rates.avg_bit_rate);
1313
1314 return update_size(pb, pos);
1315}
1316
1318{
1319 int64_t pos = avio_tell(pb);
1320 int config = 0;
1321 int ret;
1322 uint8_t *speaker_pos = NULL;
1323 const AVChannelLayout *layout = &track->par->ch_layout;
1324
1326 if (ret || !config) {
1327 config = 0;
1328 speaker_pos = av_malloc(layout->nb_channels);
1329 if (!speaker_pos)
1330 return AVERROR(ENOMEM);
1332 speaker_pos, layout->nb_channels);
1333 if (ret) {
1334 char buf[128] = {0};
1335
1336 av_freep(&speaker_pos);
1337 av_channel_layout_describe(layout, buf, sizeof(buf));
1338 av_log(s, AV_LOG_ERROR, "unsupported channel layout %s\n", buf);
1339 return ret;
1340 }
1341 }
1342
1343 avio_wb32(pb, 0); /* size */
1344 ffio_wfourcc(pb, "chnl");
1345 avio_wb32(pb, 0); /* version & flags */
1346
1347 avio_w8(pb, 1); /* stream_structure */
1348 avio_w8(pb, config);
1349 if (config) {
1350 avio_wb64(pb, 0);
1351 } else {
1352 avio_write(pb, speaker_pos, layout->nb_channels);
1353 av_freep(&speaker_pos);
1354 }
1355
1356 return update_size(pb, pos);
1357}
1358
1360{
1361 int64_t pos = avio_tell(pb);
1362 int format_flags;
1363 int sample_size;
1364
1365 avio_wb32(pb, 0); /* size */
1366 ffio_wfourcc(pb, "pcmC");
1367 avio_wb32(pb, 0); /* version & flags */
1368
1369 /* 0x01: indicates little-endian format */
1370 format_flags = (track->par->codec_id == AV_CODEC_ID_PCM_F32LE ||
1371 track->par->codec_id == AV_CODEC_ID_PCM_F64LE ||
1372 track->par->codec_id == AV_CODEC_ID_PCM_S16LE ||
1373 track->par->codec_id == AV_CODEC_ID_PCM_S24LE ||
1375 avio_w8(pb, format_flags);
1376 sample_size = track->par->bits_per_raw_sample;
1377 if (!sample_size)
1378 sample_size = av_get_exact_bits_per_sample(track->par->codec_id);
1379 av_assert0(sample_size);
1380 avio_w8(pb, sample_size);
1381
1382 return update_size(pb, pos);
1383}
1384
1386{
1387 int64_t pos = avio_tell(pb);
1388 avio_wb32(pb, 0); /* size */
1389 ffio_wfourcc(pb, "srat");
1390 avio_wb32(pb, 0); /* version & flags */
1391
1392 avio_wb32(pb, track->par->sample_rate);
1393
1394 return update_size(pb, pos);
1395}
1396
1398{
1399 int64_t pos = avio_tell(pb);
1400 int version = 0;
1401 uint32_t tag = track->tag;
1402 int ret = 0;
1403
1404 if (track->mode == MODE_MOV) {
1405 if (track->par->sample_rate > UINT16_MAX || !track->par->ch_layout.nb_channels ||
1406 track->par->codec_id == AV_CODEC_ID_EAC3 ||
1407 track->par->ch_layout.nb_channels > 2) {
1408 if (mov_get_lpcm_flags(track->par->codec_id))
1409 tag = AV_RL32("lpcm");
1410 version = 2;
1411 } else if (track->audio_vbr || mov_pcm_le_gt16(track->par->codec_id) ||
1412 mov_pcm_be_gt16(track->par->codec_id) ||
1413 track->par->codec_id == AV_CODEC_ID_ADPCM_MS ||
1415 track->par->codec_id == AV_CODEC_ID_QDM2) {
1416 version = 1;
1417 }
1418 } else if (track->mode == MODE_MP4) {
1419 if (track->par->sample_rate > UINT16_MAX &&
1421 version = 1;
1422 }
1423
1424 avio_wb32(pb, 0); /* size */
1425 if (mov->encryption_scheme != MOV_ENC_NONE) {
1426 ffio_wfourcc(pb, "enca");
1427 } else {
1428 avio_wl32(pb, tag); // store it byteswapped
1429 }
1430 avio_wb32(pb, 0); /* Reserved */
1431 avio_wb16(pb, 0); /* Reserved */
1432 avio_wb16(pb, 1); /* Data-reference index, XXX == 1 */
1433
1434 /* SoundDescription */
1435 avio_wb16(pb, version); /* Version */
1436 avio_wb16(pb, 0); /* Revision level */
1437 avio_wb32(pb, 0); /* Reserved */
1438
1439 if (version == 2) {
1440 avio_wb16(pb, 3);
1441 avio_wb16(pb, 16);
1442 avio_wb16(pb, 0xfffe);
1443 avio_wb16(pb, 0);
1444 avio_wb32(pb, 0x00010000);
1445 avio_wb32(pb, 72);
1446 avio_wb64(pb, av_double2int(track->par->sample_rate));
1447 avio_wb32(pb, track->par->ch_layout.nb_channels);
1448 avio_wb32(pb, 0x7F000000);
1451 avio_wb32(pb, track->sample_size);
1453 } else {
1454 unsigned sample_rate = track->par->sample_rate;
1455
1456 if (track->mode == MODE_MOV) {
1457 avio_wb16(pb, track->par->ch_layout.nb_channels);
1458 if (track->par->codec_id == AV_CODEC_ID_PCM_U8 ||
1459 track->par->codec_id == AV_CODEC_ID_PCM_S8)
1460 avio_wb16(pb, 8); /* bits per sample */
1461 else if (track->par->codec_id == AV_CODEC_ID_ADPCM_G726)
1462 avio_wb16(pb, track->par->bits_per_coded_sample);
1463 else
1464 avio_wb16(pb, 16);
1465 avio_wb16(pb, track->audio_vbr ? -2 : 0); /* compression ID */
1466 } else { /* reserved for mp4/3gp */
1467 avio_wb16(pb, track->tag == MKTAG('i', 'a', 'm', 'f') ?
1468 0 : track->par->ch_layout.nb_channels);
1469 if (track->par->codec_id == AV_CODEC_ID_FLAC ||
1470 track->par->codec_id == AV_CODEC_ID_ALAC) {
1471 avio_wb16(pb, track->par->bits_per_raw_sample);
1472 } else {
1473 avio_wb16(pb, 16);
1474 }
1475 avio_wb16(pb, 0);
1476
1477 while (sample_rate > UINT16_MAX)
1478 sample_rate >>= 1;
1479 }
1480
1481 avio_wb16(pb, 0); /* packet size (= 0) */
1482 if (track->tag == MKTAG('i','a','m','f'))
1483 avio_wb16(pb, 0); /* samplerate must be 0 for IAMF */
1484 else if (track->par->codec_id == AV_CODEC_ID_OPUS)
1485 avio_wb16(pb, 48000);
1486 else if (track->par->codec_id == AV_CODEC_ID_TRUEHD)
1487 avio_wb32(pb, track->par->sample_rate);
1488 else
1489 avio_wb16(pb, sample_rate);
1490
1491 if (track->par->codec_id != AV_CODEC_ID_TRUEHD)
1492 avio_wb16(pb, 0); /* Reserved */
1493 }
1494
1495 if (track->mode == MODE_MOV && version == 1) { /* SoundDescription V1 extended info */
1496 if (mov_pcm_le_gt16(track->par->codec_id) ||
1497 mov_pcm_be_gt16(track->par->codec_id))
1498 avio_wb32(pb, 1); /* must be 1 for uncompressed formats */
1499 else
1500 avio_wb32(pb, track->par->frame_size); /* Samples per packet */
1501 avio_wb32(pb, track->sample_size / track->par->ch_layout.nb_channels); /* Bytes per packet */
1502 avio_wb32(pb, track->sample_size); /* Bytes per frame */
1503 avio_wb32(pb, 2); /* Bytes per sample */
1504 }
1505
1506 if (track->mode == MODE_MOV &&
1507 (track->par->codec_id == AV_CODEC_ID_AAC ||
1508 track->par->codec_id == AV_CODEC_ID_AC3 ||
1509 track->par->codec_id == AV_CODEC_ID_EAC3 ||
1510 track->par->codec_id == AV_CODEC_ID_AMR_NB ||
1511 track->par->codec_id == AV_CODEC_ID_ALAC ||
1512 track->par->codec_id == AV_CODEC_ID_ADPCM_MS ||
1514 track->par->codec_id == AV_CODEC_ID_QDM2 ||
1515 (mov_pcm_le_gt16(track->par->codec_id) && version==1) ||
1516 (mov_pcm_be_gt16(track->par->codec_id) && version==1)))
1517 ret = mov_write_wave_tag(s, pb, track);
1518 else if (track->tag == MKTAG('m','p','4','a'))
1519 ret = mov_write_esds_tag(pb, track);
1520#if CONFIG_IAMFENC
1521 else if (track->tag == MKTAG('i','a','m','f'))
1522 ret = mov_write_iacb_tag(mov->fc, pb, track);
1523#endif
1524 else if (track->par->codec_id == AV_CODEC_ID_AMR_NB)
1525 ret = mov_write_amr_tag(pb, track);
1526 else if (track->par->codec_id == AV_CODEC_ID_AC3)
1527 ret = mov_write_ac3_tag(s, pb, track);
1528 else if (track->par->codec_id == AV_CODEC_ID_EAC3)
1529 ret = mov_write_eac3_tag(s, pb, track);
1530 else if (track->par->codec_id == AV_CODEC_ID_ALAC)
1531 ret = mov_write_extradata_tag(pb, track);
1532 else if (track->par->codec_id == AV_CODEC_ID_WMAPRO)
1533 ret = mov_write_wfex_tag(s, pb, track);
1534 else if (track->par->codec_id == AV_CODEC_ID_FLAC)
1535 ret = mov_write_dfla_tag(pb, track);
1536 else if (track->par->codec_id == AV_CODEC_ID_OPUS)
1537 ret = mov_write_dops_tag(s, pb, track);
1538 else if (track->par->codec_id == AV_CODEC_ID_TRUEHD)
1539 ret = mov_write_dmlp_tag(s, pb, track);
1540 else if (tag == MOV_MP4_IPCM_TAG || tag == MOV_MP4_FPCM_TAG) {
1541 if (track->par->sample_rate > UINT16_MAX)
1542 mov_write_srat_tag(pb, track);
1543 if (track->par->ch_layout.nb_channels > 1)
1544 ret = mov_write_chnl_tag(s, pb, track);
1545 if (ret < 0)
1546 return ret;
1547 ret = mov_write_pcmc_tag(s, pb, track);
1548 } else if (track->extradata_size[track->last_stsd_index] > 0)
1549 ret = mov_write_glbl_tag(pb, track);
1550
1551 if (ret < 0)
1552 return ret;
1553
1554 if (track->mode == MODE_MP4 && track->par->codec_type == AVMEDIA_TYPE_AUDIO
1555 && ((ret = mov_write_SA3D_tag(s, pb, track)) < 0)) {
1556 return ret;
1557 }
1558
1559 if (track->mode == MODE_MOV && track->par->codec_type == AVMEDIA_TYPE_AUDIO
1560 && ((ret = mov_write_chan_tag(s, pb, track)) < 0)) {
1561 return ret;
1562 }
1563
1565 && ((ret = ff_mov_cenc_write_sinf_tag(track, pb, mov->encryption_kid)) < 0)) {
1566 return ret;
1567 }
1568
1569 if (mov->write_btrt &&
1570 ((ret = mov_write_btrt_tag(pb, track)) < 0))
1571 return ret;
1572
1573 if (track->mode == MODE_MP4)
1574 track->entry_version = version;
1575
1576 ret = update_size(pb, pos);
1577 return ret;
1578}
1579
1581{
1582 avio_wb32(pb, 0xf); /* size */
1583 ffio_wfourcc(pb, "d263");
1584 ffio_wfourcc(pb, "FFMP");
1585 avio_w8(pb, 0); /* decoder version */
1586 /* FIXME use AVCodecContext level/profile, when encoder will set values */
1587 avio_w8(pb, 0xa); /* level */
1588 avio_w8(pb, 0); /* profile */
1589 return 0xf;
1590}
1591
1593{
1594 int64_t pos = avio_tell(pb);
1595
1596 avio_wb32(pb, 0);
1597 ffio_wfourcc(pb, "av1C");
1598 ff_isom_write_av1c(pb, track->extradata[track->last_stsd_index],
1599 track->extradata_size[track->last_stsd_index], track->mode != MODE_AVIF);
1600 return update_size(pb, pos);
1601}
1602
1604{
1605 int64_t pos = avio_tell(pb);
1606
1607 avio_wb32(pb, 0);
1608 ffio_wfourcc(pb, "avcC");
1609 ff_isom_write_avcc(pb, track->extradata[track->last_stsd_index],
1610 track->extradata_size[track->last_stsd_index]);
1611 return update_size(pb, pos);
1612}
1613
1614/* AVS3 Intelligent Media Coding
1615 * Information Technology - Intelligent Media Coding
1616 * Part 6: Intelligent Media Format
1617 */
1618static int mov_write_av3c(AVIOContext *pb, const uint8_t *data, int len)
1619{
1620 if (len < 4)
1621 return AVERROR_INVALIDDATA;
1622
1623 if (data[0] == 1) {
1624 // In Avs3DecoderConfigurationRecord format
1625 avio_write(pb, data, len);
1626 return 0;
1627 }
1628
1629 avio_w8(pb, 1); // version
1630 avio_wb16(pb, len); // sequence_header_length
1631 avio_write(pb, data, len); // sequence_header
1632 avio_w8(pb, 0xFC); // Only support library_dependency_idc = 0
1633
1634 return 0;
1635}
1636
1638{
1639 int64_t pos = avio_tell(pb);
1640 avio_wb32(pb, 0);
1641 ffio_wfourcc(pb, "av3c");
1642 mov_write_av3c(pb, track->extradata[track->last_stsd_index],
1643 track->extradata_size[track->last_stsd_index]);
1644 return update_size(pb, pos);
1645}
1646
1648{
1649 int64_t pos = avio_tell(pb);
1650
1651 avio_wb32(pb, 0);
1652 ffio_wfourcc(pb, "vpcC");
1653 ff_isom_write_vpcc(s, pb, track->extradata[track->last_stsd_index],
1654 track->extradata_size[track->last_stsd_index], track->par);
1655 return update_size(pb, pos);
1656}
1657
1659{
1660 int64_t pos = avio_tell(pb);
1661
1662 avio_wb32(pb, 0);
1663 ffio_wfourcc(pb, "hvcC");
1664 if (track->tag == MKTAG('h','v','c','1'))
1665 ff_isom_write_hvcc(pb, track->extradata[track->last_stsd_index],
1666 track->extradata_size[track->last_stsd_index], 1, s);
1667 else
1668 ff_isom_write_hvcc(pb, track->extradata[track->last_stsd_index],
1669 track->extradata_size[track->last_stsd_index], 0, s);
1670 return update_size(pb, pos);
1671}
1672
1674{
1675 int64_t pos = avio_tell(pb);
1676 int ret;
1677
1678 avio_wb32(pb, 0);
1679 ffio_wfourcc(pb, "lhvC");
1680 if (track->tag == MKTAG('h','v','c','1'))
1681 ret = ff_isom_write_lhvc(pb, track->extradata[track->last_stsd_index],
1682 track->extradata_size[track->last_stsd_index], 1, s);
1683 else
1684 ret = ff_isom_write_lhvc(pb, track->extradata[track->last_stsd_index],
1685 track->extradata_size[track->last_stsd_index], 0, s);
1686
1687 if (ret < 0) {
1688 avio_seek(pb, pos, SEEK_SET);
1689 return ret;
1690 }
1691
1692 return update_size(pb, pos);
1693}
1694
1696{
1697 int64_t pos = avio_tell(pb);
1698
1699 avio_wb32(pb, 0);
1700 ffio_wfourcc(pb, "evcC");
1701
1702 if (track->tag == MKTAG('e','v','c','1'))
1703 ff_isom_write_evcc(pb, track->extradata[track->last_stsd_index],
1704 track->extradata_size[track->last_stsd_index], 1);
1705 else
1706 ff_isom_write_evcc(pb, track->extradata[track->last_stsd_index],
1707 track->extradata_size[track->last_stsd_index], 0);
1708
1709 return update_size(pb, pos);
1710}
1711
1713{
1714 int64_t pos = avio_tell(pb);
1715
1716 avio_wb32(pb, 0);
1717 ffio_wfourcc(pb, "lvcC");
1718
1719 ff_isom_write_lvcc(pb, track->extradata[track->last_stsd_index],
1720 track->extradata_size[track->last_stsd_index], s);
1721
1722 return update_size(pb, pos);
1723}
1724
1726{
1727 int64_t pos = avio_tell(pb);
1728
1729 avio_wb32(pb, 0);
1730 ffio_wfourcc(pb, "vvcC");
1731
1732 avio_w8 (pb, 0); /* version */
1733 avio_wb24(pb, 0); /* flags */
1734
1735 if (track->tag == MKTAG('v','v','c','1'))
1736 ff_isom_write_vvcc(pb, track->extradata[track->last_stsd_index],
1737 track->extradata_size[track->last_stsd_index], 1);
1738 else
1739 ff_isom_write_vvcc(pb, track->extradata[track->last_stsd_index],
1740 track->extradata_size[track->last_stsd_index], 0);
1741 return update_size(pb, pos);
1742}
1743
1745{
1746 int64_t pos = avio_tell(pb);
1747
1748 avio_wb32(pb, 0);
1749 ffio_wfourcc(pb, "apvC");
1750
1751 avio_w8 (pb, 0); /* version */
1752 avio_wb24(pb, 0); /* flags */
1753
1754 ff_isom_write_apvc(pb, track->apv, s);
1755
1756 return update_size(pb, pos);
1757}
1758
1759/* also used by all avid codecs (dv, imx, meridien) and their variants */
1760/* https://community.avid.com/forums/t/136517.aspx */
1762{
1763 int interlaced;
1764 int cid;
1765 int display_width = track->par->width;
1766 const uint8_t *extradata;
1767
1768 if (track->extradata[track->last_stsd_index] && track->extradata_size[track->last_stsd_index] > 0x29) {
1769 if (ff_dnxhd_parse_header_prefix(track->extradata[track->last_stsd_index]) != 0) {
1770 /* looks like a DNxHD bit stream */
1771 extradata = track->extradata[track->last_stsd_index];
1772 } else {
1773 av_log(NULL, AV_LOG_WARNING, "Could not locate DNxHD bit stream in vos_data\n");
1774 return 0;
1775 }
1776 } else {
1777 av_log(NULL, AV_LOG_WARNING, "Could not locate DNxHD bit stream, vos_data too small\n");
1778 return 0;
1779 }
1780
1781 cid = AV_RB32(extradata + 0x28);
1782
1783 avio_wb32(pb, 24); /* size */
1784 ffio_wfourcc(pb, "ACLR");
1785 ffio_wfourcc(pb, "ACLR");
1786 ffio_wfourcc(pb, "0001");
1787 // 1: CCIR (supercolors will be dropped, 16 will be displayed as black)
1788 // 2: FullRange (0 will be displayed as black, 16 will be displayed as dark grey)
1789 if (track->par->color_range == AVCOL_RANGE_MPEG || /* Legal range (16-235) */
1791 avio_wb32(pb, 1);
1792 } else {
1793 avio_wb32(pb, 2);
1794 }
1795 avio_wb32(pb, 0); /* reserved */
1796
1797 if (track->tag == MKTAG('A','V','d','h')) {
1798 int alp = extradata[0x07] & 1;
1799 int pma = (extradata[0x07] >> 2) & 1;
1800 int sbd = (extradata[0x21] >> 5) & 3;
1801 int ssc = (extradata[0x2C] >> 5) & 3;
1802 int clv = (extradata[0x2C] >> 1) & 3;
1803 int clf = extradata[0x2C] & 1;
1804
1805 avio_wb32(pb, 32);
1806 ffio_wfourcc(pb, "ADHR");
1807 ffio_wfourcc(pb, "0001");
1808 avio_wb32(pb, cid); // Compression ID
1809 // 0: 4:2:2 Sub Sampling
1810 // 1: 4:2:0 Sub Sampling
1811 // 2: 4:4:4 Sub Sampling
1812 avio_wb32(pb, ssc); // Sub Sampling Control
1813 // 1: 8-bits per sample
1814 // 2: 10-bits per sample
1815 // 3: 12-bits per sample
1816 avio_wb32(pb, sbd); // Sample Bit Depth
1817 // 0: Bitstream is encoded using the YCBCR format rules and tables
1818 // 1: Bitstream is encoded using the RGB format rules and tables – only Compression IDs 1256, 1270
1819 avio_wb16(pb, clf); // Color Format
1820 // 0: ITU-R BT.709
1821 // 1: ITU-R BT.2020
1822 // 2: ITU-R BT.2020 C
1823 // 3: Out-of-band
1824 avio_wb16(pb, clv); // Color Volume
1825 // 0: Alpha channel not present
1826 // 1: Alpha channel present
1827 avio_wb16(pb, alp); // Alpha Present
1828 // 0: Alpha has not been applied to video channels
1829 // 1: Alpha has been applied to the video channels prior to encoding
1830 avio_wb16(pb, pma); // Pre-Multiplied Alpha
1831 return 0;
1832 }
1833
1834 interlaced = extradata[5] & 2;
1835
1836 avio_wb32(pb, 24); /* size */
1837 ffio_wfourcc(pb, "APRG");
1838 ffio_wfourcc(pb, "APRG");
1839 ffio_wfourcc(pb, "0001");
1840 // 1 for progressive or 2 for interlaced
1841 if (interlaced)
1842 avio_wb32(pb, 2);
1843 else
1844 avio_wb32(pb, 1);
1845 avio_wb32(pb, 0); /* reserved */
1846
1847 avio_wb32(pb, 120); /* size */
1848 ffio_wfourcc(pb, "ARES");
1849 ffio_wfourcc(pb, "ARES");
1850 ffio_wfourcc(pb, "0001");
1851 avio_wb32(pb, cid); /* cid */
1852 if ( track->par->sample_aspect_ratio.num > 0
1853 && track->par->sample_aspect_ratio.den > 0)
1854 display_width = display_width * track->par->sample_aspect_ratio.num / track->par->sample_aspect_ratio.den;
1855 avio_wb32(pb, display_width); // field width
1856 if (interlaced) {
1857 avio_wb32(pb, track->par->height / 2); // field height
1858 avio_wb32(pb, 2); // num fields
1859 avio_wb32(pb, 0); // num black lines (must be 0)
1860 // 4: HD1080i
1861 // 5: HD1080P
1862 // 6: HD720P
1863 avio_wb32(pb, 4); // video format
1864 } else {
1865 avio_wb32(pb, track->par->height);
1866 avio_wb32(pb, 1); // num fields
1867 avio_wb32(pb, 0);
1868 if (track->par->height == 1080)
1869 avio_wb32(pb, 5);
1870 else
1871 avio_wb32(pb, 6);
1872 }
1873 /* padding */
1874 ffio_fill(pb, 0, 10 * 8);
1875
1876 return 0;
1877}
1878
1880{
1881 avio_wb32(pb, 12);
1882 ffio_wfourcc(pb, "DpxE");
1883 if (track->extradata_size[track->last_stsd_index] >= 12 &&
1884 !memcmp(&track->extradata[track->last_stsd_index][4], "DpxE", 4)) {
1885 avio_wb32(pb, track->extradata[track->last_stsd_index][11]);
1886 } else {
1887 avio_wb32(pb, 1);
1888 }
1889 return 0;
1890}
1891
1893{
1894 int tag;
1895
1896 if (track->par->width == 720) { /* SD */
1897 if (track->par->height == 480) { /* NTSC */
1898 if (track->par->format == AV_PIX_FMT_YUV422P) tag = MKTAG('d','v','5','n');
1899 else tag = MKTAG('d','v','c',' ');
1900 }else if (track->par->format == AV_PIX_FMT_YUV422P) tag = MKTAG('d','v','5','p');
1901 else if (track->par->format == AV_PIX_FMT_YUV420P) tag = MKTAG('d','v','c','p');
1902 else tag = MKTAG('d','v','p','p');
1903 } else if (track->par->height == 720) { /* HD 720 line */
1904 if (track->st->time_base.den == 50) tag = MKTAG('d','v','h','q');
1905 else tag = MKTAG('d','v','h','p');
1906 } else if (track->par->height == 1080) { /* HD 1080 line */
1907 if (track->st->time_base.den == 25) tag = MKTAG('d','v','h','5');
1908 else tag = MKTAG('d','v','h','6');
1909 } else {
1910 av_log(s, AV_LOG_ERROR, "unsupported height for dv codec\n");
1911 return 0;
1912 }
1913
1914 return tag;
1915}
1916
1918{
1919 AVRational rational_framerate = st->avg_frame_rate;
1920 int rate = 0;
1921 if (rational_framerate.den != 0)
1922 rate = av_q2d(rational_framerate);
1923 return rate;
1924}
1925
1927{
1928 int tag = track->par->codec_tag;
1930 AVStream *st = track->st;
1931 int rate = defined_frame_rate(s, st);
1932
1933 if (!tag)
1934 tag = MKTAG('m', '2', 'v', '1'); //fallback tag
1935
1936 if (track->par->format == AV_PIX_FMT_YUV420P) {
1937 if (track->par->width == 1280 && track->par->height == 720) {
1938 if (!interlaced) {
1939 if (rate == 24) tag = MKTAG('x','d','v','4');
1940 else if (rate == 25) tag = MKTAG('x','d','v','5');
1941 else if (rate == 30) tag = MKTAG('x','d','v','1');
1942 else if (rate == 50) tag = MKTAG('x','d','v','a');
1943 else if (rate == 60) tag = MKTAG('x','d','v','9');
1944 }
1945 } else if (track->par->width == 1440 && track->par->height == 1080) {
1946 if (!interlaced) {
1947 if (rate == 24) tag = MKTAG('x','d','v','6');
1948 else if (rate == 25) tag = MKTAG('x','d','v','7');
1949 else if (rate == 30) tag = MKTAG('x','d','v','8');
1950 } else {
1951 if (rate == 25) tag = MKTAG('x','d','v','3');
1952 else if (rate == 30) tag = MKTAG('x','d','v','2');
1953 }
1954 } else if (track->par->width == 1920 && track->par->height == 1080) {
1955 if (!interlaced) {
1956 if (rate == 24) tag = MKTAG('x','d','v','d');
1957 else if (rate == 25) tag = MKTAG('x','d','v','e');
1958 else if (rate == 30) tag = MKTAG('x','d','v','f');
1959 } else {
1960 if (rate == 25) tag = MKTAG('x','d','v','c');
1961 else if (rate == 30) tag = MKTAG('x','d','v','b');
1962 }
1963 }
1964 } else if (track->par->format == AV_PIX_FMT_YUV422P) {
1965 if (track->par->width == 1280 && track->par->height == 720) {
1966 if (!interlaced) {
1967 if (rate == 24) tag = MKTAG('x','d','5','4');
1968 else if (rate == 25) tag = MKTAG('x','d','5','5');
1969 else if (rate == 30) tag = MKTAG('x','d','5','1');
1970 else if (rate == 50) tag = MKTAG('x','d','5','a');
1971 else if (rate == 60) tag = MKTAG('x','d','5','9');
1972 }
1973 } else if (track->par->width == 1920 && track->par->height == 1080) {
1974 if (!interlaced) {
1975 if (rate == 24) tag = MKTAG('x','d','5','d');
1976 else if (rate == 25) tag = MKTAG('x','d','5','e');
1977 else if (rate == 30) tag = MKTAG('x','d','5','f');
1978 } else {
1979 if (rate == 25) tag = MKTAG('x','d','5','c');
1980 else if (rate == 30) tag = MKTAG('x','d','5','b');
1981 }
1982 }
1983 }
1984
1985 return tag;
1986}
1987
1989{
1990 int tag = track->par->codec_tag;
1992 AVStream *st = track->st;
1993 int rate = defined_frame_rate(s, st);
1994
1995 if (!tag)
1996 tag = MKTAG('a', 'v', 'c', 'i'); //fallback tag
1997
1998 if (track->par->profile == AV_PROFILE_UNKNOWN ||
1999 !(track->par->profile & AV_PROFILE_H264_INTRA))
2000 return tag;
2001
2002 if (track->par->format == AV_PIX_FMT_YUV420P10) {
2003 if (track->par->width == 960 && track->par->height == 720) {
2004 if (!interlaced) {
2005 if (rate == 24) tag = MKTAG('a','i','5','p');
2006 else if (rate == 25) tag = MKTAG('a','i','5','q');
2007 else if (rate == 30) tag = MKTAG('a','i','5','p');
2008 else if (rate == 50) tag = MKTAG('a','i','5','q');
2009 else if (rate == 60) tag = MKTAG('a','i','5','p');
2010 }
2011 } else if (track->par->width == 1440 && track->par->height == 1080) {
2012 if (!interlaced) {
2013 if (rate == 24) tag = MKTAG('a','i','5','3');
2014 else if (rate == 25) tag = MKTAG('a','i','5','2');
2015 else if (rate == 30) tag = MKTAG('a','i','5','3');
2016 } else {
2017 if (rate == 50) tag = MKTAG('a','i','5','5');
2018 else if (rate == 60) tag = MKTAG('a','i','5','6');
2019 }
2020 }
2021 } else if (track->par->format == AV_PIX_FMT_YUV422P10) {
2022 if (track->par->width == 1280 && track->par->height == 720) {
2023 if (!interlaced) {
2024 if (rate == 24) tag = MKTAG('a','i','1','p');
2025 else if (rate == 25) tag = MKTAG('a','i','1','q');
2026 else if (rate == 30) tag = MKTAG('a','i','1','p');
2027 else if (rate == 50) tag = MKTAG('a','i','1','q');
2028 else if (rate == 60) tag = MKTAG('a','i','1','p');
2029 }
2030 } else if (track->par->width == 1920 && track->par->height == 1080) {
2031 if (!interlaced) {
2032 if (rate == 24) tag = MKTAG('a','i','1','3');
2033 else if (rate == 25) tag = MKTAG('a','i','1','2');
2034 else if (rate == 30) tag = MKTAG('a','i','1','3');
2035 } else {
2036 if (rate == 25) tag = MKTAG('a','i','1','5');
2037 else if (rate == 50) tag = MKTAG('a','i','1','5');
2038 else if (rate == 60) tag = MKTAG('a','i','1','6');
2039 }
2040 } else if ( track->par->width == 4096 && track->par->height == 2160
2041 || track->par->width == 3840 && track->par->height == 2160
2042 || track->par->width == 2048 && track->par->height == 1080) {
2043 tag = MKTAG('a','i','v','x');
2044 }
2045 }
2046
2047 return tag;
2048}
2049
2051{
2052 int tag = track->par->codec_tag;
2053
2054 if (!tag)
2055 tag = MKTAG('e', 'v', 'c', '1');
2056
2057 return tag;
2058}
2059
2061{
2062 int tag = track->par->codec_tag;
2063
2064 if (!tag)
2065 tag = MKTAG('a', 'p', 'v', '1');
2066
2067 return tag;
2068}
2069
2070
2071static const struct {
2073 uint32_t tag;
2074 unsigned bps;
2075} mov_pix_fmt_tags[] = {
2076 { AV_PIX_FMT_YUYV422, MKTAG('y','u','v','2'), 0 },
2077 { AV_PIX_FMT_YUYV422, MKTAG('y','u','v','s'), 0 },
2078 { AV_PIX_FMT_UYVY422, MKTAG('2','v','u','y'), 0 },
2079 { AV_PIX_FMT_VYU444, MKTAG('v','3','0','8'), 0 },
2080 { AV_PIX_FMT_UYVA, MKTAG('v','4','0','8'), 0 },
2081 { AV_PIX_FMT_V30XLE, MKTAG('v','4','1','0'), 0 },
2082 { AV_PIX_FMT_RGB555BE,MKTAG('r','a','w',' '), 16 },
2083 { AV_PIX_FMT_RGB555LE,MKTAG('L','5','5','5'), 16 },
2084 { AV_PIX_FMT_RGB565LE,MKTAG('L','5','6','5'), 16 },
2085 { AV_PIX_FMT_RGB565BE,MKTAG('B','5','6','5'), 16 },
2086 { AV_PIX_FMT_GRAY16BE,MKTAG('b','1','6','g'), 16 },
2087 { AV_PIX_FMT_RGB24, MKTAG('r','a','w',' '), 24 },
2088 { AV_PIX_FMT_BGR24, MKTAG('2','4','B','G'), 24 },
2089 { AV_PIX_FMT_ARGB, MKTAG('r','a','w',' '), 32 },
2090 { AV_PIX_FMT_BGRA, MKTAG('B','G','R','A'), 32 },
2091 { AV_PIX_FMT_RGBA, MKTAG('R','G','B','A'), 32 },
2092 { AV_PIX_FMT_ABGR, MKTAG('A','B','G','R'), 32 },
2093 { AV_PIX_FMT_RGB48BE, MKTAG('b','4','8','r'), 48 },
2095
2097{
2098 int tag = MKTAG('A','V','d','n');
2099 if (track->par->profile != AV_PROFILE_UNKNOWN &&
2100 track->par->profile != AV_PROFILE_DNXHD)
2101 tag = MKTAG('A','V','d','h');
2102 return tag;
2103}
2104
2106{
2107 int tag = track->par->codec_tag;
2108 int i;
2110
2111 for (i = 0; i < FF_ARRAY_ELEMS(mov_pix_fmt_tags); i++) {
2112 if (track->par->format == mov_pix_fmt_tags[i].pix_fmt) {
2113 tag = mov_pix_fmt_tags[i].tag;
2115 if (track->par->codec_tag == mov_pix_fmt_tags[i].tag)
2116 break;
2117 }
2118 }
2119
2121 track->par->bits_per_coded_sample);
2122 if (tag == MKTAG('r','a','w',' ') &&
2123 track->par->format != pix_fmt &&
2124 track->par->format != AV_PIX_FMT_GRAY8 &&
2125 track->par->format != AV_PIX_FMT_NONE)
2126 av_log(s, AV_LOG_ERROR, "%s rawvideo cannot be written to mov, output file will be unreadable\n",
2127 av_get_pix_fmt_name(track->par->format));
2128 return tag;
2129}
2130
2131static unsigned int mov_get_codec_tag(AVFormatContext *s, MOVTrack *track)
2132{
2133 unsigned int tag = track->par->codec_tag;
2134
2135 // "rtp " is used to distinguish internally created RTP-hint tracks
2136 // (with rtp_ctx) from other tracks.
2137 if (tag == MKTAG('r','t','p',' '))
2138 tag = 0;
2139 if (!tag || (s->strict_std_compliance >= FF_COMPLIANCE_NORMAL &&
2140 (track->par->codec_id == AV_CODEC_ID_DVVIDEO ||
2141 track->par->codec_id == AV_CODEC_ID_RAWVIDEO ||
2142 track->par->codec_id == AV_CODEC_ID_H263 ||
2143 track->par->codec_id == AV_CODEC_ID_H264 ||
2144 track->par->codec_id == AV_CODEC_ID_DNXHD ||
2145 track->par->codec_id == AV_CODEC_ID_MPEG2VIDEO ||
2146 av_get_bits_per_sample(track->par->codec_id)))) { // pcm audio
2147 if (track->par->codec_id == AV_CODEC_ID_DVVIDEO)
2148 tag = mov_get_dv_codec_tag(s, track);
2149 else if (track->par->codec_id == AV_CODEC_ID_RAWVIDEO)
2151 else if (track->par->codec_id == AV_CODEC_ID_MPEG2VIDEO)
2153 else if (track->par->codec_id == AV_CODEC_ID_H264)
2154 tag = mov_get_h264_codec_tag(s, track);
2155 else if (track->par->codec_id == AV_CODEC_ID_EVC)
2156 tag = mov_get_evc_codec_tag(s, track);
2157 else if (track->par->codec_id == AV_CODEC_ID_APV)
2158 tag = mov_get_apv_codec_tag(s, track);
2159 else if (track->par->codec_id == AV_CODEC_ID_DNXHD)
2160 tag = mov_get_dnxhd_codec_tag(s, track);
2161 else if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
2163 if (!tag) { // if no mac fcc found, try with Microsoft tags
2165 if (tag)
2166 av_log(s, AV_LOG_WARNING, "Using MS style video codec tag, "
2167 "the file may be unplayable!\n");
2168 }
2169 } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) {
2171 if (!tag) { // if no mac fcc found, try with Microsoft tags
2172 int ms_tag = ff_codec_get_tag(ff_codec_wav_tags, track->par->codec_id);
2173 if (ms_tag) {
2174 tag = MKTAG('m', 's', ((ms_tag >> 8) & 0xff), (ms_tag & 0xff));
2175 av_log(s, AV_LOG_WARNING, "Using MS style audio codec tag, "
2176 "the file may be unplayable!\n");
2177 }
2178 }
2179 } else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE)
2181 }
2182
2183 return tag;
2184}
2185
2187 { AV_CODEC_ID_MJPEG, 0xD },
2188 { AV_CODEC_ID_PNG, 0xE },
2189 { AV_CODEC_ID_BMP, 0x1B },
2190 { AV_CODEC_ID_NONE, 0 },
2191};
2192
2193static unsigned int validate_codec_tag(const AVCodecTag *const *tags,
2194 unsigned int tag, int codec_id)
2195{
2196 int i;
2197
2198 /**
2199 * Check that tag + id is in the table
2200 */
2201 for (i = 0; tags && tags[i]; i++) {
2202 const AVCodecTag *codec_tags = tags[i];
2203 while (codec_tags->id != AV_CODEC_ID_NONE) {
2204 if (ff_toupper4(codec_tags->tag) == ff_toupper4(tag) &&
2205 codec_tags->id == codec_id)
2206 return codec_tags->tag;
2207 codec_tags++;
2208 }
2209 }
2210 return 0;
2211}
2212
2213static unsigned int mov_find_codec_tag(AVFormatContext *s, MOVTrack *track)
2214{
2215 if (is_cover_image(track->st))
2217
2218 if (track->mode == MODE_IPOD)
2219 if (!av_match_ext(s->url, "m4a") &&
2220 !av_match_ext(s->url, "m4v") &&
2221 !av_match_ext(s->url, "m4b"))
2222 av_log(s, AV_LOG_WARNING, "Warning, extension is not .m4a nor .m4v "
2223 "Quicktime/Ipod might not play the file\n");
2224
2225 if (track->mode == MODE_MOV) {
2226 return mov_get_codec_tag(s, track);
2227 } else
2228 return validate_codec_tag(s->oformat->codec_tag, track->par->codec_tag,
2229 track->par->codec_id);
2230}
2231
2232/** Write uuid atom.
2233 * Needed to make file play in iPods running newest firmware
2234 * goes after avcC atom in moov.trak.mdia.minf.stbl.stsd.avc1
2235 */
2237{
2238 avio_wb32(pb, 28);
2239 ffio_wfourcc(pb, "uuid");
2240 avio_wb32(pb, 0x6b6840f2);
2241 avio_wb32(pb, 0x5f244fc5);
2242 avio_wb32(pb, 0xba39a51b);
2243 avio_wb32(pb, 0xcf0323f3);
2244 avio_wb32(pb, 0x0);
2245 return 28;
2246}
2247
2248static const uint16_t fiel_data[] = {
2249 0x0000, 0x0100, 0x0201, 0x0206, 0x0209, 0x020e
2250};
2251
2252static int mov_write_fiel_tag(AVIOContext *pb, MOVTrack *track, int field_order)
2253{
2254 unsigned mov_field_order = 0;
2255 if (field_order < FF_ARRAY_ELEMS(fiel_data))
2256 mov_field_order = fiel_data[field_order];
2257 else
2258 return 0;
2259 avio_wb32(pb, 10);
2260 ffio_wfourcc(pb, "fiel");
2261 avio_wb16(pb, mov_field_order);
2262 return 10;
2263}
2264
2266{
2267 MOVMuxContext *mov = s->priv_data;
2268 int ret = AVERROR_BUG;
2269 int64_t pos = avio_tell(pb);
2270 avio_wb32(pb, 0); /* size */
2271 avio_wl32(pb, track->tag); // store it byteswapped
2272 avio_wb32(pb, 0); /* Reserved */
2273 avio_wb16(pb, 0); /* Reserved */
2274 avio_wb16(pb, 1); /* Data-reference index */
2275
2276 if (track->par->codec_id == AV_CODEC_ID_DVD_SUBTITLE)
2277 mov_write_esds_tag(pb, track);
2278 else if (track->par->codec_id == AV_CODEC_ID_TTML) {
2279 switch (track->par->codec_tag) {
2280 case MOV_ISMV_TTML_TAG:
2281 // ISMV dfxp requires no extradata.
2282 break;
2283 case MOV_MP4_TTML_TAG:
2284 // As specified in 14496-30, XMLSubtitleSampleEntry
2285 // Namespace
2286 avio_put_str(pb, "http://www.w3.org/ns/ttml");
2287 // Empty schema_location
2288 avio_w8(pb, 0);
2289 // Empty auxiliary_mime_types
2290 avio_w8(pb, 0);
2291 break;
2292 default:
2294 "Unknown codec tag '%s' utilized for TTML stream with "
2295 "index %d (track id %d)!\n",
2296 av_fourcc2str(track->par->codec_tag), track->st->index,
2297 track->track_id);
2298 return AVERROR(EINVAL);
2299 }
2300 } else if (track->extradata_size[track->last_stsd_index])
2301 avio_write(pb, track->extradata[track->last_stsd_index], track->extradata_size[track->last_stsd_index]);
2302
2303 if (mov->write_btrt &&
2304 ((ret = mov_write_btrt_tag(pb, track)) < 0))
2305 return ret;
2306
2307 return update_size(pb, pos);
2308}
2309
2311{
2312 int8_t stereo_mode;
2313
2314 if (stereo_3d->flags != 0) {
2315 av_log(s, AV_LOG_WARNING, "Unsupported stereo_3d flags %x. st3d not written.\n", stereo_3d->flags);
2316 return 0;
2317 }
2318
2319 switch (stereo_3d->type) {
2320 case AV_STEREO3D_2D:
2321 stereo_mode = 0;
2322 break;
2324 stereo_mode = 1;
2325 break;
2327 stereo_mode = 2;
2328 break;
2329 default:
2330 av_log(s, AV_LOG_WARNING, "Unsupported stereo_3d type %s. st3d not written.\n", av_stereo3d_type_name(stereo_3d->type));
2331 return 0;
2332 }
2333 avio_wb32(pb, 13); /* size */
2334 ffio_wfourcc(pb, "st3d");
2335 avio_wb32(pb, 0); /* version = 0 & flags = 0 */
2336 avio_w8(pb, stereo_mode);
2337 return 13;
2338}
2339
2341{
2342 int64_t sv3d_pos, svhd_pos, proj_pos;
2343 const char* metadata_source = s->flags & AVFMT_FLAG_BITEXACT ? "Lavf" : LIBAVFORMAT_IDENT;
2344
2345 if (spherical_mapping->projection != AV_SPHERICAL_EQUIRECTANGULAR &&
2346 spherical_mapping->projection != AV_SPHERICAL_EQUIRECTANGULAR_TILE &&
2347 spherical_mapping->projection != AV_SPHERICAL_CUBEMAP) {
2348 av_log(s, AV_LOG_WARNING, "Unsupported projection %d. sv3d not written.\n", spherical_mapping->projection);
2349 return 0;
2350 }
2351
2352 sv3d_pos = avio_tell(pb);
2353 avio_wb32(pb, 0); /* size */
2354 ffio_wfourcc(pb, "sv3d");
2355
2356 svhd_pos = avio_tell(pb);
2357 avio_wb32(pb, 0); /* size */
2358 ffio_wfourcc(pb, "svhd");
2359 avio_wb32(pb, 0); /* version = 0 & flags = 0 */
2360 avio_put_str(pb, metadata_source);
2361 update_size(pb, svhd_pos);
2362
2363 proj_pos = avio_tell(pb);
2364 avio_wb32(pb, 0); /* size */
2365 ffio_wfourcc(pb, "proj");
2366
2367 avio_wb32(pb, 24); /* size */
2368 ffio_wfourcc(pb, "prhd");
2369 avio_wb32(pb, 0); /* version = 0 & flags = 0 */
2370 avio_wb32(pb, spherical_mapping->yaw);
2371 avio_wb32(pb, spherical_mapping->pitch);
2372 avio_wb32(pb, spherical_mapping->roll);
2373
2374 switch (spherical_mapping->projection) {
2377 avio_wb32(pb, 28); /* size */
2378 ffio_wfourcc(pb, "equi");
2379 avio_wb32(pb, 0); /* version = 0 & flags = 0 */
2380 avio_wb32(pb, spherical_mapping->bound_top);
2381 avio_wb32(pb, spherical_mapping->bound_bottom);
2382 avio_wb32(pb, spherical_mapping->bound_left);
2383 avio_wb32(pb, spherical_mapping->bound_right);
2384 break;
2386 avio_wb32(pb, 20); /* size */
2387 ffio_wfourcc(pb, "cbmp");
2388 avio_wb32(pb, 0); /* version = 0 & flags = 0 */
2389 avio_wb32(pb, 0); /* layout */
2390 avio_wb32(pb, spherical_mapping->padding); /* padding */
2391 break;
2392 }
2393 update_size(pb, proj_pos);
2394
2395 return update_size(pb, sv3d_pos);
2396}
2397
2399{
2400 return av_rescale(q.num, b, q.den);
2401}
2402
2404 const AVStereo3D *stereo3d)
2405{
2406 if (!stereo3d->horizontal_field_of_view.num)
2407 return;
2408
2409 avio_wb32(pb, 12); /* size */
2410 ffio_wfourcc(pb, "hfov");
2412}
2413
2415 const AVSphericalMapping *spherical_mapping)
2416{
2417 avio_wb32(pb, 24); /* size */
2418 ffio_wfourcc(pb, "proj");
2419 avio_wb32(pb, 16); /* size */
2420 ffio_wfourcc(pb, "prji");
2421 avio_wb32(pb, 0); /* version + flags */
2422
2423 switch (spherical_mapping->projection) {
2425 ffio_wfourcc(pb, "rect");
2426 break;
2428 ffio_wfourcc(pb, "equi");
2429 break;
2431 ffio_wfourcc(pb, "hequ");
2432 break;
2434 ffio_wfourcc(pb, "fish");
2435 break;
2436 default:
2437 av_assert0(0);
2438 }
2439}
2440
2442 const AVStereo3D *stereo3d)
2443{
2444 int64_t pos = avio_tell(pb);
2445 int view = 0;
2446
2447 avio_wb32(pb, 0); /* size */
2448 ffio_wfourcc(pb, "eyes");
2449
2450 // stri is mandatory
2451 avio_wb32(pb, 13); /* size */
2452 ffio_wfourcc(pb, "stri");
2453 avio_wb32(pb, 0); /* version + flags */
2454 switch (stereo3d->view) {
2456 view |= 1 << 0;
2457 break;
2459 view |= 1 << 1;
2460 break;
2462 view |= (1 << 0) | (1 << 1);
2463 break;
2464 }
2465 view |= !!(stereo3d->flags & AV_STEREO3D_FLAG_INVERT) << 3;
2466 avio_w8(pb, view);
2467
2468 // hero is optional
2469 if (stereo3d->primary_eye != AV_PRIMARY_EYE_NONE) {
2470 avio_wb32(pb, 13); /* size */
2471 ffio_wfourcc(pb, "hero");
2472 avio_wb32(pb, 0); /* version + flags */
2473 avio_w8(pb, stereo3d->primary_eye);
2474 }
2475
2476 // it's not clear if cams is mandatory or optional
2477 if (stereo3d->baseline) {
2478 avio_wb32(pb, 24); /* size */
2479 ffio_wfourcc(pb, "cams");
2480 avio_wb32(pb, 16); /* size */
2481 ffio_wfourcc(pb, "blin");
2482 avio_wb32(pb, 0); /* version + flags */
2483 avio_wb32(pb, stereo3d->baseline);
2484 }
2485
2486 // it's not clear if cmfy is mandatory or optional
2487 if (stereo3d->horizontal_disparity_adjustment.num) {
2488 avio_wb32(pb, 24); /* size */
2489 ffio_wfourcc(pb, "cmfy");
2490 avio_wb32(pb, 16); /* size */
2491 ffio_wfourcc(pb, "dadj");
2492 avio_wb32(pb, 0); /* version + flags */
2494 }
2495
2496 return update_size(pb, pos);
2497}
2498
2500 const AVStereo3D *stereo3d,
2501 const AVSphericalMapping *spherical_mapping)
2502{
2503 int64_t pos;
2504
2505 if (spherical_mapping &&
2506 spherical_mapping->projection != AV_SPHERICAL_RECTILINEAR &&
2507 spherical_mapping->projection != AV_SPHERICAL_EQUIRECTANGULAR &&
2508 spherical_mapping->projection != AV_SPHERICAL_HALF_EQUIRECTANGULAR &&
2509 spherical_mapping->projection != AV_SPHERICAL_FISHEYE) {
2510 av_log(s, AV_LOG_WARNING, "Unsupported projection %d. proj not written.\n",
2511 spherical_mapping->projection);
2512 spherical_mapping = NULL;
2513 }
2514
2515 if (stereo3d && (stereo3d->type == AV_STEREO3D_2D ||
2516 (!(stereo3d->flags & AV_STEREO3D_FLAG_INVERT) &&
2517 stereo3d->view == AV_STEREO3D_VIEW_UNSPEC &&
2518 stereo3d->primary_eye == AV_PRIMARY_EYE_NONE &&
2519 !stereo3d->baseline &&
2520 !stereo3d->horizontal_disparity_adjustment.num))) {
2521 av_log(s, AV_LOG_WARNING, "Unsupported stereo 3d metadata. eyes not written.\n");
2522 stereo3d = NULL;
2523 }
2524
2525 if (!spherical_mapping && !stereo3d)
2526 return 0;
2527
2528 pos = avio_tell(pb);
2529 avio_wb32(pb, 0); /* size */
2530 ffio_wfourcc(pb, "vexu");
2531
2532 if (spherical_mapping)
2533 mov_write_vexu_proj_tag(s, pb, spherical_mapping);
2534
2535 if (stereo3d)
2536 mov_write_eyes_tag(s, pb, stereo3d);
2537
2538 return update_size(pb, pos);
2539}
2540
2542{
2543 uint8_t buf[ISOM_DVCC_DVVC_SIZE];
2544
2545 avio_wb32(pb, 32); /* size = 8 + 24 */
2546 if (dovi->dv_profile > 10)
2547 ffio_wfourcc(pb, "dvwC");
2548 else if (dovi->dv_profile > 7)
2549 ffio_wfourcc(pb, "dvvC");
2550 else
2551 ffio_wfourcc(pb, "dvcC");
2552
2553 ff_isom_put_dvcc_dvvc(s, buf, dovi);
2554 avio_write(pb, buf, sizeof(buf));
2555
2556 return 32; /* 8 + 24 */
2557}
2558
2560{
2561 avio_wb32(pb, 8 + sd->size);
2562 ffio_wfourcc(pb, "hvcE");
2563 avio_write(pb, sd->data, sd->size);
2564 return 8 + sd->size;
2565}
2566
2568 uint32_t top, uint32_t bottom,
2569 uint32_t left, uint32_t right)
2570{
2571 uint32_t cropped_width = track->par->width - left - right;
2572 uint32_t cropped_height = track->height - top - bottom;
2573 AVRational horizOff =
2574 av_sub_q((AVRational) { track->par->width - cropped_width, 2 },
2575 (AVRational) { left, 1 });
2576 AVRational vertOff =
2577 av_sub_q((AVRational) { track->height - cropped_height, 2 },
2578 (AVRational) { top, 1 });
2579
2580 avio_wb32(pb, 40);
2581 ffio_wfourcc(pb, "clap");
2582 avio_wb32(pb, cropped_width); /* apertureWidthN */
2583 avio_wb32(pb, 1); /* apertureWidthD */
2584 avio_wb32(pb, cropped_height); /* apertureHeightN */
2585 avio_wb32(pb, 1); /* apertureHeightD */
2586
2587 avio_wb32(pb, -horizOff.num);
2588 avio_wb32(pb, horizOff.den);
2589 avio_wb32(pb, -vertOff.num);
2590 avio_wb32(pb, vertOff.den);
2591
2592 return 40;
2593}
2594
2596{
2597 AVRational sar;
2598 av_reduce(&sar.num, &sar.den, track->par->sample_aspect_ratio.num,
2599 track->par->sample_aspect_ratio.den, INT_MAX);
2600
2601 avio_wb32(pb, 16);
2602 ffio_wfourcc(pb, "pasp");
2603 avio_wb32(pb, sar.num);
2604 avio_wb32(pb, sar.den);
2605 return 16;
2606}
2607
2608static int mov_write_gama_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track, double gamma)
2609{
2610 uint32_t gama = 0;
2611 if (gamma <= 0.0)
2613 av_log(s, AV_LOG_DEBUG, "gamma value %g\n", gamma);
2614
2615 if (gamma > 1e-6) {
2616 gama = (uint32_t)lrint((double)(1<<16) * gamma);
2617 av_log(s, AV_LOG_DEBUG, "writing gama value %"PRId32"\n", gama);
2618
2619 av_assert0(track->mode == MODE_MOV);
2620 avio_wb32(pb, 12);
2621 ffio_wfourcc(pb, "gama");
2622 avio_wb32(pb, gama);
2623 return 12;
2624 } else {
2625 av_log(s, AV_LOG_WARNING, "gamma value unknown, unable to write gama atom\n");
2626 }
2627 return 0;
2628}
2629
2630static int mov_write_colr_tag(AVIOContext *pb, MOVTrack *track, int prefer_icc)
2631{
2632 int64_t pos = avio_tell(pb);
2633
2634 // Ref (MOV): https://developer.apple.com/library/mac/technotes/tn2162/_index.html#//apple_ref/doc/uid/DTS40013070-CH1-TNTAG9
2635 // Ref (MP4): ISO/IEC 14496-12:2012
2636
2637 if (prefer_icc) {
2641
2642 if (sd) {
2643 avio_wb32(pb, 12 + sd->size);
2644 ffio_wfourcc(pb, "colr");
2645 ffio_wfourcc(pb, "prof");
2646 avio_write(pb, sd->data, sd->size);
2647 return 12 + sd->size;
2648 }
2649 else {
2650 av_log(NULL, AV_LOG_INFO, "no ICC profile found, will write nclx/nclc colour info instead\n");
2651 }
2652 }
2653
2654 /* We should only ever be called for MOV, MP4 and AVIF. */
2655 av_assert0(track->mode == MODE_MOV || track->mode == MODE_MP4 ||
2656 track->mode == MODE_AVIF);
2657
2658 avio_wb32(pb, 0); /* size */
2659 ffio_wfourcc(pb, "colr");
2660 if (track->mode == MODE_MP4 || track->mode == MODE_AVIF)
2661 ffio_wfourcc(pb, "nclx");
2662 else
2663 ffio_wfourcc(pb, "nclc");
2664 // Do not try to guess the color info if it is AVCOL_PRI_UNSPECIFIED.
2665 // e.g., Dolby Vision for Apple devices should be set to AVCOL_PRI_UNSPECIFIED. See
2666 // https://developer.apple.com/av-foundation/High-Dynamic-Range-Metadata-for-Apple-Devices.pdf
2667 avio_wb16(pb, track->par->color_primaries);
2668 avio_wb16(pb, track->par->color_trc);
2669 avio_wb16(pb, track->par->color_space);
2670 if (track->mode == MODE_MP4 || track->mode == MODE_AVIF) {
2671 int full_range = track->par->color_range == AVCOL_RANGE_JPEG;
2672 avio_w8(pb, full_range << 7);
2673 }
2674
2675 return update_size(pb, pos);
2676}
2677
2679{
2680 const AVPacketSideData *side_data;
2681 const AVContentLightMetadata *content_light_metadata;
2682
2686 if (!side_data) {
2687 return 0;
2688 }
2689 content_light_metadata = (const AVContentLightMetadata*)side_data->data;
2690
2691 avio_wb32(pb, 12); // size
2692 ffio_wfourcc(pb, "clli");
2693 avio_wb16(pb, content_light_metadata->MaxCLL);
2694 avio_wb16(pb, content_light_metadata->MaxFALL);
2695 return 12;
2696}
2697
2699{
2700 const int chroma_den = 50000;
2701 const int luma_den = 10000;
2702 const AVPacketSideData *side_data;
2704
2708 if (side_data)
2709 metadata = (const AVMasteringDisplayMetadata*)side_data->data;
2710 if (!metadata || !metadata->has_primaries || !metadata->has_luminance) {
2711 return 0;
2712 }
2713
2714 avio_wb32(pb, 32); // size
2715 ffio_wfourcc(pb, "mdcv");
2716 avio_wb16(pb, rescale_rational(metadata->display_primaries[1][0], chroma_den));
2717 avio_wb16(pb, rescale_rational(metadata->display_primaries[1][1], chroma_den));
2718 avio_wb16(pb, rescale_rational(metadata->display_primaries[2][0], chroma_den));
2719 avio_wb16(pb, rescale_rational(metadata->display_primaries[2][1], chroma_den));
2720 avio_wb16(pb, rescale_rational(metadata->display_primaries[0][0], chroma_den));
2721 avio_wb16(pb, rescale_rational(metadata->display_primaries[0][1], chroma_den));
2722 avio_wb16(pb, rescale_rational(metadata->white_point[0], chroma_den));
2723 avio_wb16(pb, rescale_rational(metadata->white_point[1], chroma_den));
2724 avio_wb32(pb, rescale_rational(metadata->max_luminance, luma_den));
2725 avio_wb32(pb, rescale_rational(metadata->min_luminance, luma_den));
2726 return 32;
2727}
2728
2730{
2731 const int illuminance_den = 10000;
2732 const int ambient_den = 50000;
2733 const AVPacketSideData *side_data;
2734 const AVAmbientViewingEnvironment *ambient;
2735
2736
2740
2741 if (!side_data)
2742 return 0;
2743
2744 ambient = (const AVAmbientViewingEnvironment*)side_data->data;
2745 if (!ambient || !ambient->ambient_illuminance.num)
2746 return 0;
2747
2748 avio_wb32(pb, 16); // size
2749 ffio_wfourcc(pb, "amve");
2750 avio_wb32(pb, rescale_rational(ambient->ambient_illuminance, illuminance_den));
2751 avio_wb16(pb, rescale_rational(ambient->ambient_light_x, ambient_den));
2752 avio_wb16(pb, rescale_rational(ambient->ambient_light_y, ambient_den));
2753 return 16;
2754}
2755
2756static void find_compressor(char * compressor_name, int len, MOVTrack *track)
2757{
2758 AVDictionaryEntry *encoder;
2759 int xdcam_res = (track->par->width == 1280 && track->par->height == 720)
2760 || (track->par->width == 1440 && track->par->height == 1080)
2761 || (track->par->width == 1920 && track->par->height == 1080);
2762
2763 if ((track->mode == MODE_AVIF ||
2764 track->mode == MODE_MOV ||
2765 track->mode == MODE_MP4) &&
2766 (encoder = av_dict_get(track->st->metadata, "encoder", NULL, 0))) {
2767 av_strlcpy(compressor_name, encoder->value, 32);
2768 } else if (track->par->codec_id == AV_CODEC_ID_MPEG2VIDEO && xdcam_res) {
2770 AVStream *st = track->st;
2771 int rate = defined_frame_rate(NULL, st);
2772 av_strlcatf(compressor_name, len, "XDCAM");
2773 if (track->par->format == AV_PIX_FMT_YUV422P) {
2774 av_strlcatf(compressor_name, len, " HD422");
2775 } else if(track->par->width == 1440) {
2776 av_strlcatf(compressor_name, len, " HD");
2777 } else
2778 av_strlcatf(compressor_name, len, " EX");
2779
2780 av_strlcatf(compressor_name, len, " %d%c", track->par->height, interlaced ? 'i' : 'p');
2781
2782 av_strlcatf(compressor_name, len, "%d", rate * (interlaced + 1));
2783 }
2784}
2785
2787{
2788 int64_t pos = avio_tell(pb);
2789 // Write sane defaults:
2790 // all_ref_pics_intra = 0 : all samples can use any type of reference.
2791 // intra_pred_used = 1 : intra prediction may or may not be used.
2792 // max_ref_per_pic = 15 : reserved value to indicate that any number of
2793 // reference images can be used.
2794 uint8_t ccstValue = (0 << 7) | /* all_ref_pics_intra */
2795 (1 << 6) | /* intra_pred_used */
2796 (15 << 2); /* max_ref_per_pic */
2797 avio_wb32(pb, 0); /* size */
2798 ffio_wfourcc(pb, "ccst");
2799 avio_wb32(pb, 0); /* Version & flags */
2800 avio_w8(pb, ccstValue);
2801 avio_wb24(pb, 0); /* reserved */
2802 return update_size(pb, pos);
2803}
2804
2805static int mov_write_aux_tag(AVIOContext *pb, const char *aux_type)
2806{
2807 int64_t pos = avio_tell(pb);
2808 avio_wb32(pb, 0); /* size */
2809 ffio_wfourcc(pb, aux_type);
2810 avio_wb32(pb, 0); /* Version & flags */
2811 avio_write(pb, "urn:mpeg:mpegB:cicp:systems:auxiliary:alpha\0", 44);
2812 return update_size(pb, pos);
2813}
2814
2816{
2817 int ret = AVERROR_BUG;
2818 int64_t pos = avio_tell(pb);
2819 const AVPacketSideData *sd;
2820 char compressor_name[32] = { 0 };
2821 int avid = 0;
2822
2823 int uncompressed_ycbcr = ((track->par->codec_id == AV_CODEC_ID_RAWVIDEO && track->par->format == AV_PIX_FMT_UYVY422)
2824 || (track->par->codec_id == AV_CODEC_ID_RAWVIDEO && track->par->format == AV_PIX_FMT_YUYV422)
2825 || (track->par->codec_id == AV_CODEC_ID_RAWVIDEO && track->par->format == AV_PIX_FMT_VYU444)
2826 || (track->par->codec_id == AV_CODEC_ID_RAWVIDEO && track->par->format == AV_PIX_FMT_UYVA)
2827 || (track->par->codec_id == AV_CODEC_ID_RAWVIDEO && track->par->format == AV_PIX_FMT_V30XLE)
2828 || track->par->codec_id == AV_CODEC_ID_V210);
2829
2830 avio_wb32(pb, 0); /* size */
2831 if (mov->encryption_scheme != MOV_ENC_NONE) {
2832 ffio_wfourcc(pb, "encv");
2833 } else {
2834 avio_wl32(pb, track->tag); // store it byteswapped
2835 }
2836 avio_wb32(pb, 0); /* Reserved */
2837 avio_wb16(pb, 0); /* Reserved */
2838 avio_wb16(pb, 1); /* Data-reference index */
2839
2840 if (uncompressed_ycbcr) {
2841 avio_wb16(pb, 2); /* Codec stream version */
2842 } else {
2843 avio_wb16(pb, 0); /* Codec stream version */
2844 }
2845 avio_wb16(pb, 0); /* Codec stream revision (=0) */
2846 if (track->mode == MODE_MOV) {
2847 ffio_wfourcc(pb, "FFMP"); /* Vendor */
2848 if (track->par->codec_id == AV_CODEC_ID_RAWVIDEO || uncompressed_ycbcr) {
2849 avio_wb32(pb, 0); /* Temporal Quality */
2850 avio_wb32(pb, 0x400); /* Spatial Quality = lossless*/
2851 } else {
2852 avio_wb32(pb, 0x200); /* Temporal Quality = normal */
2853 avio_wb32(pb, 0x200); /* Spatial Quality = normal */
2854 }
2855 } else {
2856 ffio_fill(pb, 0, 3 * 4); /* Reserved */
2857 }
2858 avio_wb16(pb, track->par->width); /* Video width */
2859 avio_wb16(pb, track->height); /* Video height */
2860 avio_wb32(pb, 0x00480000); /* Horizontal resolution 72dpi */
2861 avio_wb32(pb, 0x00480000); /* Vertical resolution 72dpi */
2862 avio_wb32(pb, 0); /* Data size (= 0) */
2863 avio_wb16(pb, 1); /* Frame count (= 1) */
2864
2865 find_compressor(compressor_name, 32, track);
2866 avio_w8(pb, strlen(compressor_name));
2867 avio_write(pb, compressor_name, 31);
2868
2869 if (track->mode == MODE_MOV && track->par->codec_id == AV_CODEC_ID_V210)
2870 avio_wb16(pb, 0x18);
2871 else if (track->mode == MODE_MOV && track->par->bits_per_coded_sample)
2872 avio_wb16(pb, track->par->bits_per_coded_sample |
2873 (track->par->format == AV_PIX_FMT_GRAY8 ? 0x20 : 0));
2874 else
2875 avio_wb16(pb, 0x18); /* Reserved */
2876
2877 if (track->mode == MODE_MOV && track->par->format == AV_PIX_FMT_PAL8) {
2878 int pal_size, i;
2879 avio_wb16(pb, 0); /* Color table ID */
2880 avio_wb32(pb, 0); /* Color table seed */
2881 avio_wb16(pb, 0x8000); /* Color table flags */
2882 if (track->par->bits_per_coded_sample < 0 || track->par->bits_per_coded_sample > 8)
2883 return AVERROR(EINVAL);
2884 pal_size = 1 << track->par->bits_per_coded_sample;
2885 avio_wb16(pb, pal_size - 1); /* Color table size (zero-relative) */
2886 for (i = 0; i < pal_size; i++) {
2887 uint32_t rgb = track->palette[i];
2888 uint16_t r = (rgb >> 16) & 0xff;
2889 uint16_t g = (rgb >> 8) & 0xff;
2890 uint16_t b = rgb & 0xff;
2891 avio_wb16(pb, 0);
2892 avio_wb16(pb, (r << 8) | r);
2893 avio_wb16(pb, (g << 8) | g);
2894 avio_wb16(pb, (b << 8) | b);
2895 }
2896 } else
2897 avio_wb16(pb, 0xffff); /* Reserved */
2898
2899 if (track->tag == MKTAG('m','p','4','v'))
2900 mov_write_esds_tag(pb, track);
2901 else if (track->par->codec_id == AV_CODEC_ID_H263)
2903 else if (track->par->codec_id == AV_CODEC_ID_AVUI ||
2904 track->par->codec_id == AV_CODEC_ID_SVQ3) {
2905 mov_write_extradata_tag(pb, track);
2906 avio_wb32(pb, 0);
2907 } else if (track->par->codec_id == AV_CODEC_ID_DNXHD) {
2908 mov_write_avid_tag(pb, track);
2909 avid = 1;
2910 } else if (track->par->codec_id == AV_CODEC_ID_HEVC) {
2911 mov_write_hvcc_tag(mov->fc, pb, track);
2913 ret = mov_write_lhvc_tag(mov->fc, pb, track);
2914 if (ret < 0)
2915 av_log(mov->fc, AV_LOG_WARNING, "Not writing 'lhvC' atom for multilayer stream.\n");
2916 }
2917 } else if (track->par->codec_id == AV_CODEC_ID_VVC)
2918 mov_write_vvcc_tag(pb, track);
2919 else if (track->par->codec_id == AV_CODEC_ID_H264 && !TAG_IS_AVCI(track->tag)) {
2920 mov_write_avcc_tag(pb, track);
2921 if (track->mode == MODE_IPOD)
2923 }
2924 else if (track->par->codec_id ==AV_CODEC_ID_EVC) {
2925 mov_write_evcc_tag(pb, track);
2926 } else if (track->par->codec_id == AV_CODEC_ID_LCEVC) {
2927 mov_write_lvcc_tag(mov->fc, pb, track);
2928 } else if (track->par->codec_id ==AV_CODEC_ID_APV) {
2929 mov_write_apvc_tag(mov->fc, pb, track);
2930 } else if (track->par->codec_id == AV_CODEC_ID_VP9) {
2931 mov_write_vpcc_tag(mov->fc, pb, track);
2932 } else if (track->par->codec_id == AV_CODEC_ID_AV1) {
2933 mov_write_av1c_tag(pb, track);
2934 } else if (track->par->codec_id == AV_CODEC_ID_VC1 && track->extradata_size[track->last_stsd_index] > 0)
2935 mov_write_dvc1_tag(pb, track);
2936 else if (track->par->codec_id == AV_CODEC_ID_VP6F ||
2937 track->par->codec_id == AV_CODEC_ID_VP6A) {
2938 /* Don't write any potential extradata here - the cropping
2939 * is signalled via the normal width/height fields. */
2940 } else if (track->par->codec_id == AV_CODEC_ID_R10K) {
2941 if (track->par->codec_tag == MKTAG('R','1','0','k'))
2942 mov_write_dpxe_tag(pb, track);
2943 } else if (track->par->codec_id == AV_CODEC_ID_AVS3) {
2944 mov_write_av3c_tag(pb, track);
2945 } else if (track->extradata_size[track->last_stsd_index] > 0)
2946 mov_write_glbl_tag(pb, track);
2947
2948 if (track->par->codec_id != AV_CODEC_ID_H264 &&
2949 track->par->codec_id != AV_CODEC_ID_MPEG4 &&
2950 track->par->codec_id != AV_CODEC_ID_DNXHD) {
2951 int field_order = track->par->field_order;
2952
2953 if (field_order != AV_FIELD_UNKNOWN)
2954 mov_write_fiel_tag(pb, track, field_order);
2955 }
2956
2957 if (mov->flags & FF_MOV_FLAG_WRITE_GAMA) {
2958 if (track->mode == MODE_MOV)
2959 mov_write_gama_tag(s, pb, track, mov->gamma);
2960 else
2961 av_log(mov->fc, AV_LOG_WARNING, "Not writing 'gama' atom. Format is not MOV.\n");
2962 }
2963 if (track->mode == MODE_MOV || track->mode == MODE_MP4 || track->mode == MODE_AVIF) {
2964 int has_color_info = track->par->color_primaries != AVCOL_PRI_UNSPECIFIED &&
2965 track->par->color_trc != AVCOL_TRC_UNSPECIFIED &&
2967 if (has_color_info || mov->flags & FF_MOV_FLAG_WRITE_COLR ||
2970 int prefer_icc = mov->flags & FF_MOV_FLAG_PREFER_ICC || !has_color_info;
2971 mov_write_colr_tag(pb, track, prefer_icc);
2972 }
2973 } else if (mov->flags & FF_MOV_FLAG_WRITE_COLR) {
2974 av_log(mov->fc, AV_LOG_WARNING, "Not writing 'colr' atom. Format is not MOV or MP4 or AVIF.\n");
2975 }
2976
2977 if (track->mode == MODE_MOV || track->mode == MODE_MP4) {
2978 mov_write_clli_tag(pb, track);
2979 mov_write_mdcv_tag(pb, track);
2980 mov_write_amve_tag(pb, track);
2981 }
2982
2987 const AVPacketSideData *spherical_mapping = av_packet_side_data_get(track->st->codecpar->coded_side_data,
2990 if (stereo_3d)
2991 mov_write_st3d_tag(s, pb, (AVStereo3D*)stereo_3d->data);
2992 if (spherical_mapping)
2993 mov_write_sv3d_tag(mov->fc, pb, (AVSphericalMapping*)spherical_mapping->data);
2994 }
2995
2996 if (track->mode == MODE_MOV || (track->mode == MODE_MP4 &&
2998 const AVStereo3D *stereo3d = NULL;
2999 const AVSphericalMapping *spherical_mapping = NULL;
3000
3004 if (sd)
3005 stereo3d = (AVStereo3D *)sd->data;
3006
3010 if (sd)
3011 spherical_mapping = (AVSphericalMapping *)sd->data;
3012
3013 if (stereo3d || spherical_mapping)
3014 mov_write_vexu_tag(s, pb, stereo3d, spherical_mapping);
3015 if (stereo3d)
3016 mov_write_hfov_tag(s, pb, stereo3d);
3017 }
3018
3019 if (track->mode == MODE_MP4) {
3023 if (dovi && mov->fc->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL) {
3025 } else if (dovi) {
3026 av_log(mov->fc, AV_LOG_WARNING, "Not writing 'dvcC'/'dvvC' box. Requires -strict unofficial.\n");
3027 }
3028
3032 if (hvce && mov->fc->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL) {
3033 mov_write_hvce_tag(pb, hvce);
3034 } else if (hvce) {
3035 av_log(mov->fc, AV_LOG_WARNING, "Not writing 'hvcE' box. Requires -strict unofficial.\n");
3036 }
3037 }
3038
3039 if (track->par->sample_aspect_ratio.den && track->par->sample_aspect_ratio.num) {
3040 mov_write_pasp_tag(pb, track);
3041 }
3042
3046 if (sd && sd->size >= sizeof(uint32_t) * 4) {
3047 uint64_t top = AV_RL32(sd->data + 0);
3048 uint64_t bottom = AV_RL32(sd->data + 4);
3049 uint64_t left = AV_RL32(sd->data + 8);
3050 uint64_t right = AV_RL32(sd->data + 12);
3051
3052 if ((left + right) >= track->par->width ||
3053 (top + bottom) >= track->height) {
3054 av_log(s, AV_LOG_ERROR, "Invalid cropping dimensions in stream side data\n");
3055 return AVERROR(EINVAL);
3056 }
3057 if (top || bottom || left || right)
3058 mov_write_clap_tag(pb, track, top, bottom, left, right);
3059 } else if (uncompressed_ycbcr)
3060 mov_write_clap_tag(pb, track, 0, 0, 0, 0);
3061
3062 if (mov->encryption_scheme != MOV_ENC_NONE) {
3064 }
3065
3066 if (mov->write_btrt &&
3067 ((ret = mov_write_btrt_tag(pb, track)) < 0))
3068 return ret;
3069
3070 /* extra padding for avid stsd */
3071 /* https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/QTFFChap2/qtff2.html#//apple_ref/doc/uid/TP40000939-CH204-61112 */
3072 if (avid)
3073 avio_wb32(pb, 0);
3074
3075 if (track->mode == MODE_AVIF) {
3077 if (mov->nb_streams > 0 && track == &mov->tracks[1])
3078 mov_write_aux_tag(pb, "auxi");
3079 }
3080
3081 return update_size(pb, pos);
3082}
3083
3085{
3086 int64_t pos = avio_tell(pb);
3087 avio_wb32(pb, 0); /* size */
3088 ffio_wfourcc(pb, "rtp ");
3089 avio_wb32(pb, 0); /* Reserved */
3090 avio_wb16(pb, 0); /* Reserved */
3091 avio_wb16(pb, 1); /* Data-reference index */
3092
3093 avio_wb16(pb, 1); /* Hint track version */
3094 avio_wb16(pb, 1); /* Highest compatible version */
3095 avio_wb32(pb, track->max_packet_size); /* Max packet size */
3096
3097 avio_wb32(pb, 12); /* size */
3098 ffio_wfourcc(pb, "tims");
3099 avio_wb32(pb, track->timescale);
3100
3101 return update_size(pb, pos);
3102}
3103
3104static int mov_write_source_reference_tag(AVIOContext *pb, MOVTrack *track, const char *reel_name)
3105{
3106 uint64_t str_size =strlen(reel_name);
3107 int64_t pos = avio_tell(pb);
3108
3109 if (str_size >= UINT16_MAX){
3110 av_log(NULL, AV_LOG_ERROR, "reel_name length %"PRIu64" is too large\n", str_size);
3111 avio_wb16(pb, 0);
3112 return AVERROR(EINVAL);
3113 }
3114
3115 avio_wb32(pb, 0); /* size */
3116 ffio_wfourcc(pb, "name"); /* Data format */
3117 avio_wb16(pb, str_size); /* string size */
3118 avio_wb16(pb, track->language); /* langcode */
3119 avio_write(pb, reel_name, str_size); /* reel name */
3120 return update_size(pb,pos);
3121}
3122
3124{
3125 int64_t pos = avio_tell(pb);
3126#if 1
3127 int frame_duration;
3128 int nb_frames;
3130
3131 if (!track->st->avg_frame_rate.num || !track->st->avg_frame_rate.den) {
3132 av_log(NULL, AV_LOG_ERROR, "avg_frame_rate not set for tmcd track.\n");
3133 return AVERROR(EINVAL);
3134 } else {
3135 frame_duration = av_rescale(track->timescale, track->st->avg_frame_rate.den, track->st->avg_frame_rate.num);
3136 nb_frames = ROUNDED_DIV(track->st->avg_frame_rate.num, track->st->avg_frame_rate.den);
3137 }
3138
3139 if (nb_frames > 255) {
3140 av_log(NULL, AV_LOG_ERROR, "fps %d is too large\n", nb_frames);
3141 return AVERROR(EINVAL);
3142 }
3143
3144 avio_wb32(pb, 0); /* size */
3145 ffio_wfourcc(pb, "tmcd"); /* Data format */
3146 avio_wb32(pb, 0); /* Reserved */
3147 avio_wb32(pb, 1); /* Data reference index */
3148 avio_wb32(pb, 0); /* Flags */
3149 avio_wb32(pb, track->timecode_flags); /* Flags (timecode) */
3150 avio_wb32(pb, track->timescale); /* Timescale */
3151 avio_wb32(pb, frame_duration); /* Frame duration */
3152 avio_w8(pb, nb_frames); /* Number of frames */
3153 avio_w8(pb, 0); /* Reserved */
3154
3155 t = av_dict_get(track->st->metadata, "reel_name", NULL, 0);
3156 if (t && utf8len(t->value) && track->mode != MODE_MP4)
3158 else
3159 avio_wb16(pb, 0); /* zero size */
3160#else
3161
3162 avio_wb32(pb, 0); /* size */
3163 ffio_wfourcc(pb, "tmcd"); /* Data format */
3164 avio_wb32(pb, 0); /* Reserved */
3165 avio_wb32(pb, 1); /* Data reference index */
3166 if (track->par->extradata_size)
3167 avio_write(pb, track->par->extradata, track->par->extradata_size);
3168#endif
3169 return update_size(pb, pos);
3170}
3171
3172static int mov_write_gpmd_tag(AVIOContext *pb, const MOVTrack *track)
3173{
3174 int64_t pos = avio_tell(pb);
3175 avio_wb32(pb, 0); /* size */
3176 ffio_wfourcc(pb, "gpmd");
3177 avio_wb32(pb, 0); /* Reserved */
3178 avio_wb16(pb, 0); /* Reserved */
3179 avio_wb16(pb, 1); /* Data-reference index */
3180 avio_wb32(pb, 0); /* Reserved */
3181 return update_size(pb, pos);
3182}
3183
3185{
3186 int64_t pos = avio_tell(pb);
3187 int ret = 0;
3188 avio_wb32(pb, 0); /* size */
3189 ffio_wfourcc(pb, "stsd");
3190 avio_wb32(pb, 0); /* version & flags */
3191 avio_wb32(pb, track->stsd_count);
3192
3193 int stsd_index_back = track->last_stsd_index;
3194 for (track->last_stsd_index = 0;
3195 track->last_stsd_index < track->stsd_count;
3196 track->last_stsd_index++) {
3197 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO)
3198 ret = mov_write_video_tag(s, pb, mov, track);
3199 else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO)
3200 ret = mov_write_audio_tag(s, pb, mov, track);
3201 else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE)
3202 ret = mov_write_subtitle_tag(s, pb, track);
3203 else if (track->par->codec_tag == MKTAG('r','t','p',' '))
3204 ret = mov_write_rtp_tag(pb, track);
3205 else if (track->par->codec_tag == MKTAG('t','m','c','d'))
3206 ret = mov_write_tmcd_tag(pb, track);
3207 else if (track->par->codec_tag == MKTAG('g','p','m','d'))
3208 ret = mov_write_gpmd_tag(pb, track);
3209
3210 if (ret < 0)
3211 return ret;
3212 }
3213
3214 track->last_stsd_index = stsd_index_back;
3215
3216 return update_size_and_version(pb, pos, track->entry_version);
3217}
3218
3220{
3221 MOVMuxContext *mov = s->priv_data;
3222 MOVCtts *ctts_entries;
3223 uint32_t entries = 0;
3224 uint32_t atom_size;
3225 int i;
3226
3227 ctts_entries = av_malloc_array((track->entry + 1), sizeof(*ctts_entries)); /* worst case */
3228 if (!ctts_entries)
3229 return AVERROR(ENOMEM);
3230 ctts_entries[0].count = 1;
3231 ctts_entries[0].offset = track->cluster[0].cts;
3232 for (i = 1; i < track->entry; i++) {
3233 if (track->cluster[i].cts == ctts_entries[entries].offset) {
3234 ctts_entries[entries].count++; /* compress */
3235 } else {
3236 entries++;
3237 ctts_entries[entries].offset = track->cluster[i].cts;
3238 ctts_entries[entries].count = 1;
3239 }
3240 }
3241 entries++; /* last one */
3242 atom_size = 16 + (entries * 8);
3243 avio_wb32(pb, atom_size); /* size */
3244 ffio_wfourcc(pb, "ctts");
3246 avio_w8(pb, 1); /* version */
3247 else
3248 avio_w8(pb, 0); /* version */
3249 avio_wb24(pb, 0); /* flags */
3250 avio_wb32(pb, entries); /* entry count */
3251 for (i = 0; i < entries; i++) {
3252 avio_wb32(pb, ctts_entries[i].count);
3253 avio_wb32(pb, ctts_entries[i].offset);
3254 }
3255 av_free(ctts_entries);
3256 return atom_size;
3257}
3258
3259/* Time to sample atom */
3261{
3262 MOVStts *stts_entries = NULL;
3263 uint32_t entries = -1;
3264 uint32_t atom_size;
3265 int i;
3266
3267 if (track->par->codec_type == AVMEDIA_TYPE_AUDIO && !track->audio_vbr) {
3268 stts_entries = av_malloc(sizeof(*stts_entries)); /* one entry */
3269 if (!stts_entries)
3270 return AVERROR(ENOMEM);
3271 stts_entries[0].count = track->sample_count;
3272 stts_entries[0].duration = 1;
3273 entries = 1;
3274 } else {
3275 if (track->entry) {
3276 stts_entries = av_malloc_array(track->entry, sizeof(*stts_entries)); /* worst case */
3277 if (!stts_entries)
3278 return AVERROR(ENOMEM);
3279 }
3280 for (i = 0; i < track->entry; i++) {
3281 int duration = get_cluster_duration(track, i);
3282#if CONFIG_IAMFENC
3283 if (track->iamf && track->par->codec_id == AV_CODEC_ID_OPUS)
3284 duration = av_rescale(duration, 48000, track->par->sample_rate);
3285#endif
3286 if (i && duration == stts_entries[entries].duration) {
3287 stts_entries[entries].count++; /* compress */
3288 } else {
3289 entries++;
3290 stts_entries[entries].duration = duration;
3291 stts_entries[entries].count = 1;
3292 }
3293 }
3294 entries++; /* last one */
3295 }
3296 atom_size = 16 + (entries * 8);
3297 avio_wb32(pb, atom_size); /* size */
3298 ffio_wfourcc(pb, "stts");
3299 avio_wb32(pb, 0); /* version & flags */
3300 avio_wb32(pb, entries); /* entry count */
3301 for (i = 0; i < entries; i++) {
3302 avio_wb32(pb, stts_entries[i].count);
3303 avio_wb32(pb, stts_entries[i].duration);
3304 }
3305 av_free(stts_entries);
3306 return atom_size;
3307}
3308
3310{
3311 avio_wb32(pb, 28); /* size */
3312 ffio_wfourcc(pb, "dref");
3313 avio_wb32(pb, 0); /* version & flags */
3314 avio_wb32(pb, 1); /* entry count */
3315
3316 avio_wb32(pb, 0xc); /* size */
3317 //FIXME add the alis and rsrc atom
3318 ffio_wfourcc(pb, "url ");
3319 avio_wb32(pb, 1); /* version & flags */
3320
3321 return 28;
3322}
3323
3325{
3326 struct sgpd_entry {
3327 int count;
3328 int16_t roll_distance;
3329 int group_description_index;
3330 };
3331
3332 struct sgpd_entry *sgpd_entries = NULL;
3333 int entries = -1;
3334 int group = 0;
3335 int i, j;
3336
3337 const int OPUS_SEEK_PREROLL_MS = 80;
3338 int roll_samples = av_rescale_q(OPUS_SEEK_PREROLL_MS,
3339 (AVRational){1, 1000},
3340 (AVRational){1, 48000});
3341
3342 if (!track->entry)
3343 return 0;
3344
3345 sgpd_entries = av_malloc_array(track->entry, sizeof(*sgpd_entries));
3346 if (!sgpd_entries)
3347 return AVERROR(ENOMEM);
3348
3350
3351 if (track->par->codec_id == AV_CODEC_ID_OPUS) {
3352 for (i = 0; i < track->entry; i++) {
3353 int roll_samples_remaining = roll_samples;
3354 int distance = 0;
3355 for (j = i - 1; j >= 0; j--) {
3356 roll_samples_remaining -= get_cluster_duration(track, j);
3357 distance++;
3358 if (roll_samples_remaining <= 0)
3359 break;
3360 }
3361 /* We don't have enough preceding samples to compute a valid
3362 roll_distance here, so this sample can't be independently
3363 decoded. */
3364 if (roll_samples_remaining > 0)
3365 distance = 0;
3366 /* Verify distance is a maximum of 32 (2.5ms) packets. */
3367 if (distance > 32) {
3368 av_freep(&sgpd_entries);
3369 return AVERROR_INVALIDDATA;
3370 }
3371 if (i && distance == sgpd_entries[entries].roll_distance) {
3372 sgpd_entries[entries].count++;
3373 } else {
3374 entries++;
3375 sgpd_entries[entries].count = 1;
3376 sgpd_entries[entries].roll_distance = distance;
3377 sgpd_entries[entries].group_description_index = distance ? ++group : 0;
3378 }
3379 }
3380 } else {
3381 entries++;
3382 sgpd_entries[entries].count = track->sample_count;
3383 sgpd_entries[entries].roll_distance = 1;
3384 sgpd_entries[entries].group_description_index = ++group;
3385 }
3386 entries++;
3387
3388 if (!group) {
3389 av_free(sgpd_entries);
3390 return 0;
3391 }
3392
3393 /* Write sgpd tag */
3394 avio_wb32(pb, 24 + (group * 2)); /* size */
3395 ffio_wfourcc(pb, "sgpd");
3396 avio_wb32(pb, 1 << 24); /* fullbox */
3397 ffio_wfourcc(pb, "roll");
3398 avio_wb32(pb, 2); /* default_length */
3399 avio_wb32(pb, group); /* entry_count */
3400 for (i = 0; i < entries; i++) {
3401 if (sgpd_entries[i].group_description_index) {
3402 avio_wb16(pb, -sgpd_entries[i].roll_distance); /* roll_distance */
3403 }
3404 }
3405
3406 /* Write sbgp tag */
3407 avio_wb32(pb, 20 + (entries * 8)); /* size */
3408 ffio_wfourcc(pb, "sbgp");
3409 avio_wb32(pb, 0); /* fullbox */
3410 ffio_wfourcc(pb, "roll");
3411 avio_wb32(pb, entries); /* entry_count */
3412 for (i = 0; i < entries; i++) {
3413 avio_wb32(pb, sgpd_entries[i].count); /* sample_count */
3414 avio_wb32(pb, sgpd_entries[i].group_description_index); /* group_description_index */
3415 }
3416
3417 av_free(sgpd_entries);
3418 return 0;
3419}
3420
3422{
3423 int64_t pos = avio_tell(pb);
3424 int ret = 0;
3425
3426 avio_wb32(pb, 0); /* size */
3427 ffio_wfourcc(pb, "stbl");
3428 if ((ret = mov_write_stsd_tag(s, pb, mov, track)) < 0)
3429 return ret;
3430 mov_write_stts_tag(pb, track);
3431 if ((track->par->codec_type == AVMEDIA_TYPE_VIDEO ||
3432 track->par->codec_id == AV_CODEC_ID_TRUEHD ||
3434 (track->par->codec_id == AV_CODEC_ID_AAC && track->par->profile == AV_PROFILE_AAC_USAC) ||
3435 track->par->codec_tag == MKTAG('r','t','p',' ')) &&
3436 track->has_keyframes && track->has_keyframes < track->entry)
3438 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO && track->has_disposable && track->entry)
3439 mov_write_sdtp_tag(pb, track);
3440 if (track->mode == MODE_MOV && track->flags & MOV_TRACK_STPS)
3442 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO &&
3443 track->flags & MOV_TRACK_CTTS && track->entry) {
3444
3445 if ((ret = mov_write_ctts_tag(s, pb, track)) < 0)
3446 return ret;
3447 }
3448 mov_write_stsc_tag(pb, track);
3449 mov_write_stsz_tag(pb, track);
3450 mov_write_stco_tag(pb, track);
3451 if (track->cenc.aes_ctr && !(mov->flags & FF_MOV_FLAG_FRAGMENT)) {
3452 ff_mov_cenc_write_stbl_atoms(&track->cenc, pb, 0);
3453 }
3454 if (track->par->codec_id == AV_CODEC_ID_OPUS || track->par->codec_id == AV_CODEC_ID_AAC) {
3456 }
3457 return update_size(pb, pos);
3458}
3459
3461{
3462 int64_t pos = avio_tell(pb);
3463 avio_wb32(pb, 0); /* size */
3464 ffio_wfourcc(pb, "dinf");
3466 return update_size(pb, pos);
3467}
3468
3470{
3471 avio_wb32(pb, 12);
3472 ffio_wfourcc(pb, "nmhd");
3473 avio_wb32(pb, 0);
3474 return 12;
3475}
3476
3478{
3479 avio_wb32(pb, 12);
3480 ffio_wfourcc(pb, "sthd");
3481 avio_wb32(pb, 0);
3482 return 12;
3483}
3484
3486{
3487 int64_t pos = avio_tell(pb);
3488 const char *font = "Lucida Grande";
3489 avio_wb32(pb, 0); /* size */
3490 ffio_wfourcc(pb, "tcmi"); /* timecode media information atom */
3491 avio_wb32(pb, 0); /* version & flags */
3492 avio_wb16(pb, 0); /* text font */
3493 avio_wb16(pb, 0); /* text face */
3494 avio_wb16(pb, 12); /* text size */
3495 avio_wb16(pb, 0); /* (unknown, not in the QT specs...) */
3496 avio_wb16(pb, 0x0000); /* text color (red) */
3497 avio_wb16(pb, 0x0000); /* text color (green) */
3498 avio_wb16(pb, 0x0000); /* text color (blue) */
3499 avio_wb16(pb, 0xffff); /* background color (red) */
3500 avio_wb16(pb, 0xffff); /* background color (green) */
3501 avio_wb16(pb, 0xffff); /* background color (blue) */
3502 avio_w8(pb, strlen(font)); /* font len (part of the pascal string) */
3503 avio_write(pb, font, strlen(font)); /* font name */
3504 return update_size(pb, pos);
3505}
3506
3508{
3509 int64_t pos = avio_tell(pb);
3510 avio_wb32(pb, 0); /* size */
3511 ffio_wfourcc(pb, "gmhd");
3512 avio_wb32(pb, 0x18); /* gmin size */
3513 ffio_wfourcc(pb, "gmin");/* generic media info */
3514 avio_wb32(pb, 0); /* version & flags */
3515 avio_wb16(pb, 0x40); /* graphics mode = */
3516 avio_wb16(pb, 0x8000); /* opColor (r?) */
3517 avio_wb16(pb, 0x8000); /* opColor (g?) */
3518 avio_wb16(pb, 0x8000); /* opColor (b?) */
3519 avio_wb16(pb, 0); /* balance */
3520 avio_wb16(pb, 0); /* reserved */
3521
3522 /*
3523 * This special text atom is required for
3524 * Apple Quicktime chapters. The contents
3525 * don't appear to be documented, so the
3526 * bytes are copied verbatim.
3527 */
3528 if (track->tag != MKTAG('c','6','0','8')) {
3529 avio_wb32(pb, 0x2C); /* size */
3530 ffio_wfourcc(pb, "text");
3531 avio_wb16(pb, 0x01);
3532 avio_wb32(pb, 0x00);
3533 avio_wb32(pb, 0x00);
3534 avio_wb32(pb, 0x00);
3535 avio_wb32(pb, 0x01);
3536 avio_wb32(pb, 0x00);
3537 avio_wb32(pb, 0x00);
3538 avio_wb32(pb, 0x00);
3539 avio_wb32(pb, 0x00004000);
3540 avio_wb16(pb, 0x0000);
3541 }
3542
3543 if (track->par->codec_tag == MKTAG('t','m','c','d')) {
3544 int64_t tmcd_pos = avio_tell(pb);
3545 avio_wb32(pb, 0); /* size */
3546 ffio_wfourcc(pb, "tmcd");
3547 mov_write_tcmi_tag(pb, track);
3548 update_size(pb, tmcd_pos);
3549 } else if (track->par->codec_tag == MKTAG('g','p','m','d')) {
3550 int64_t gpmd_pos = avio_tell(pb);
3551 avio_wb32(pb, 0); /* size */
3552 ffio_wfourcc(pb, "gpmd");
3553 avio_wb32(pb, 0); /* version */
3554 update_size(pb, gpmd_pos);
3555 }
3556 return update_size(pb, pos);
3557}
3558
3560{
3561 avio_wb32(pb, 16); /* size */
3562 ffio_wfourcc(pb, "smhd");
3563 avio_wb32(pb, 0); /* version & flags */
3564 avio_wb16(pb, 0); /* reserved (balance, normally = 0) */
3565 avio_wb16(pb, 0); /* reserved */
3566 return 16;
3567}
3568
3570{
3571 avio_wb32(pb, 0x14); /* size (always 0x14) */
3572 ffio_wfourcc(pb, "vmhd");
3573 avio_wb32(pb, 0x01); /* version & flags */
3574 avio_wb64(pb, 0); /* reserved (graphics mode = copy) */
3575 return 0x14;
3576}
3577
3578static int is_clcp_track(MOVTrack *track)
3579{
3580 return track->tag == MKTAG('c','7','0','8') ||
3581 track->tag == MKTAG('c','6','0','8');
3582}
3583
3585{
3586 MOVMuxContext *mov = s->priv_data;
3587 const char *hdlr, *descr = NULL, *hdlr_type = NULL;
3588 int64_t pos = avio_tell(pb);
3589 size_t descr_len;
3590
3591 hdlr = "dhlr";
3592 hdlr_type = "url ";
3593 descr = "DataHandler";
3594
3595 if (track) {
3596 hdlr = (track->mode == MODE_MOV) ? "mhlr" : "\0\0\0\0";
3597 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
3598 if (track->mode == MODE_AVIF) {
3599 hdlr_type = (track == &mov->tracks[0]) ? "pict" : "auxv";
3600 descr = "PictureHandler";
3601 } else {
3602 hdlr_type = "vide";
3603 descr = "VideoHandler";
3604 }
3605 } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) {
3606 hdlr_type = "soun";
3607 descr = "SoundHandler";
3608 } else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE) {
3609 if (is_clcp_track(track)) {
3610 hdlr_type = "clcp";
3611 descr = "ClosedCaptionHandler";
3612 } else {
3613 if (track->tag == MKTAG('t','x','3','g')) {
3614 hdlr_type = "sbtl";
3615 } else if (track->tag == MKTAG('m','p','4','s')) {
3616 hdlr_type = "subp";
3617 } else if (track->tag == MOV_MP4_TTML_TAG) {
3618 hdlr_type = "subt";
3619 } else {
3620 hdlr_type = "text";
3621 }
3622 descr = "SubtitleHandler";
3623 }
3624 } else if (track->par->codec_tag == MKTAG('r','t','p',' ')) {
3625 hdlr_type = "hint";
3626 descr = "HintHandler";
3627 } else if (track->par->codec_tag == MKTAG('t','m','c','d')) {
3628 hdlr_type = "tmcd";
3629 descr = "TimeCodeHandler";
3630 } else if (track->par->codec_tag == MKTAG('g','p','m','d')) {
3631 hdlr_type = "meta";
3632 descr = "GoPro MET"; // GoPro Metadata
3633 } else {
3635 "Unknown hdlr_type for %s, writing dummy values\n",
3636 av_fourcc2str(track->par->codec_tag));
3637 }
3638 if (track->st) {
3639 // hdlr.name is used by some players to identify the content title
3640 // of the track. So if an alternate handler description is
3641 // specified, use it.
3643 t = av_dict_get(track->st->metadata, "handler_name", NULL, 0);
3644 if (t && utf8len(t->value))
3645 descr = t->value;
3646 }
3647 }
3648
3649 if (mov->empty_hdlr_name) /* expressly allowed by QTFF and not prohibited in ISO 14496-12 8.4.3.3 */
3650 descr = "";
3651
3652 avio_wb32(pb, 0); /* size */
3653 ffio_wfourcc(pb, "hdlr");
3654 avio_wb32(pb, 0); /* Version & flags */
3655 avio_write(pb, hdlr, 4); /* handler */
3656 ffio_wfourcc(pb, hdlr_type); /* handler type */
3657 avio_wb32(pb, 0); /* reserved */
3658 avio_wb32(pb, 0); /* reserved */
3659 avio_wb32(pb, 0); /* reserved */
3660 descr_len = strlen(descr);
3661 if (!track || track->mode == MODE_MOV)
3662 avio_w8(pb, descr_len); /* pascal string */
3663 avio_write(pb, descr, descr_len); /* handler description */
3664 if (track && track->mode != MODE_MOV)
3665 avio_w8(pb, 0); /* c string */
3666 return update_size(pb, pos);
3667}
3668
3669static int mov_write_pitm_tag(AVIOContext *pb, int item_id)
3670{
3671 int64_t pos = avio_tell(pb);
3672 avio_wb32(pb, 0); /* size */
3673 ffio_wfourcc(pb, "pitm");
3674 avio_wb32(pb, 0); /* Version & flags */
3675 avio_wb16(pb, item_id); /* item_id */
3676 return update_size(pb, pos);
3677}
3678
3680{
3681 int64_t pos = avio_tell(pb);
3682 avio_wb32(pb, 0); /* size */
3683 ffio_wfourcc(pb, "iloc");
3684 avio_wb32(pb, 0); /* Version & flags */
3685 avio_w8(pb, (4 << 4) + 4); /* offset_size(4) and length_size(4) */
3686 avio_w8(pb, 0); /* base_offset_size(4) and reserved(4) */
3687 avio_wb16(pb, mov->nb_streams); /* item_count */
3688
3689 for (int i = 0; i < mov->nb_streams; i++) {
3690 avio_wb16(pb, i + 1); /* item_id */
3691 avio_wb16(pb, 0); /* data_reference_index */
3692 avio_wb16(pb, 1); /* extent_count */
3693 mov->avif_extent_pos[i] = avio_tell(pb);
3694 avio_wb32(pb, 0); /* extent_offset (written later) */
3695 // For animated AVIF, we simply write the first packet's size.
3696 avio_wb32(pb, mov->avif_extent_length[i]); /* extent_length */
3697 }
3698
3699 return update_size(pb, pos);
3700}
3701
3703{
3704 int64_t iinf_pos = avio_tell(pb);
3705 avio_wb32(pb, 0); /* size */
3706 ffio_wfourcc(pb, "iinf");
3707 avio_wb32(pb, 0); /* Version & flags */
3708 avio_wb16(pb, mov->nb_streams); /* entry_count */
3709
3710 for (int i = 0; i < mov->nb_streams; i++) {
3711 int64_t infe_pos = avio_tell(pb);
3712 avio_wb32(pb, 0); /* size */
3713 ffio_wfourcc(pb, "infe");
3714 avio_w8(pb, 0x2); /* Version */
3715 avio_wb24(pb, 0); /* flags */
3716 avio_wb16(pb, i + 1); /* item_id */
3717 avio_wb16(pb, 0); /* item_protection_index */
3718 avio_write(pb, "av01", 4); /* item_type */
3719 avio_write(pb, !i ? "Color\0" : "Alpha\0", 6); /* item_name */
3720 update_size(pb, infe_pos);
3721 }
3722
3723 return update_size(pb, iinf_pos);
3724}
3725
3726
3728{
3729 int64_t auxl_pos;
3730 int64_t iref_pos = avio_tell(pb);
3731 avio_wb32(pb, 0); /* size */
3732 ffio_wfourcc(pb, "iref");
3733 avio_wb32(pb, 0); /* Version & flags */
3734
3735 auxl_pos = avio_tell(pb);
3736 avio_wb32(pb, 0); /* size */
3737 ffio_wfourcc(pb, "auxl");
3738 avio_wb16(pb, 2); /* from_item_ID */
3739 avio_wb16(pb, 1); /* reference_count */
3740 avio_wb16(pb, 1); /* to_item_ID */
3741 update_size(pb, auxl_pos);
3742
3743 return update_size(pb, iref_pos);
3744}
3745
3747 int stream_index)
3748{
3749 int64_t pos = avio_tell(pb);
3750 avio_wb32(pb, 0); /* size */
3751 ffio_wfourcc(pb, "ispe");
3752 avio_wb32(pb, 0); /* Version & flags */
3753 avio_wb32(pb, s->streams[stream_index]->codecpar->width); /* image_width */
3754 avio_wb32(pb, s->streams[stream_index]->codecpar->height); /* image_height */
3755 return update_size(pb, pos);
3756}
3757
3759 int stream_index)
3760{
3761 int64_t pos = avio_tell(pb);
3762 const AVPixFmtDescriptor *pixdesc =
3763 av_pix_fmt_desc_get(s->streams[stream_index]->codecpar->format);
3764 avio_wb32(pb, 0); /* size */
3765 ffio_wfourcc(pb, "pixi");
3766 avio_wb32(pb, 0); /* Version & flags */
3767 avio_w8(pb, pixdesc->nb_components); /* num_channels */
3768 for (int i = 0; i < pixdesc->nb_components; ++i) {
3769 avio_w8(pb, pixdesc->comp[i].depth); /* bits_per_channel */
3770 }
3771 return update_size(pb, pos);
3772}
3773
3775{
3776 int64_t pos = avio_tell(pb);
3777 avio_wb32(pb, 0); /* size */
3778 ffio_wfourcc(pb, "ipco");
3779 for (int i = 0; i < mov->nb_streams; i++) {
3780 mov_write_ispe_tag(pb, mov, s, i);
3781 mov_write_pixi_tag(pb, mov, s, i);
3782 mov_write_av1c_tag(pb, &mov->tracks[i]);
3783 if (!i)
3784 mov_write_colr_tag(pb, &mov->tracks[0], 0);
3785 else
3786 mov_write_aux_tag(pb, "auxC");
3787 }
3788 return update_size(pb, pos);
3789}
3790
3792{
3793 int64_t pos = avio_tell(pb);
3794 avio_wb32(pb, 0); /* size */
3795 ffio_wfourcc(pb, "ipma");
3796 avio_wb32(pb, 0); /* Version & flags */
3797 avio_wb32(pb, mov->nb_streams); /* entry_count */
3798
3799 for (int i = 0, index = 1; i < mov->nb_streams; i++) {
3800 avio_wb16(pb, i + 1); /* item_ID */
3801 avio_w8(pb, 4); /* association_count */
3802
3803 // ispe association.
3804 avio_w8(pb, index++); /* essential and property_index */
3805 // pixi association.
3806 avio_w8(pb, index++); /* essential and property_index */
3807 // av1C association.
3808 avio_w8(pb, 0x80 | index++); /* essential and property_index */
3809 // colr/auxC association.
3810 avio_w8(pb, index++); /* essential and property_index */
3811 }
3812 return update_size(pb, pos);
3813}
3814
3816{
3817 int64_t pos = avio_tell(pb);
3818 avio_wb32(pb, 0); /* size */
3819 ffio_wfourcc(pb, "iprp");
3820 mov_write_ipco_tag(pb, mov, s);
3821 mov_write_ipma_tag(pb, mov, s);
3822 return update_size(pb, pos);
3823}
3824
3826{
3827 /* This atom must be present, but leaving the values at zero
3828 * seems harmless. */
3829 avio_wb32(pb, 28); /* size */
3830 ffio_wfourcc(pb, "hmhd");
3831 avio_wb32(pb, 0); /* version, flags */
3832 avio_wb16(pb, 0); /* maxPDUsize */
3833 avio_wb16(pb, 0); /* avgPDUsize */
3834 avio_wb32(pb, 0); /* maxbitrate */
3835 avio_wb32(pb, 0); /* avgbitrate */
3836 avio_wb32(pb, 0); /* reserved */
3837 return 28;
3838}
3839
3841{
3842 int64_t pos = avio_tell(pb);
3843 int ret;
3844
3845 avio_wb32(pb, 0); /* size */
3846 ffio_wfourcc(pb, "minf");
3847 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO)
3849 else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO)
3851 else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE) {
3852 if (track->tag == MKTAG('t','e','x','t') || is_clcp_track(track)) {
3853 mov_write_gmhd_tag(pb, track);
3854 } else if (track->tag == MOV_MP4_TTML_TAG) {
3856 } else {
3858 }
3859 } else if (track->tag == MKTAG('r','t','p',' ')) {
3861 } else if (track->tag == MKTAG('t','m','c','d')) {
3862 if (track->mode != MODE_MOV)
3864 else
3865 mov_write_gmhd_tag(pb, track);
3866 } else if (track->tag == MKTAG('g','p','m','d')) {
3867 mov_write_gmhd_tag(pb, track);
3868 }
3869 if (track->mode == MODE_MOV) /* ISO 14496-12 8.4.3.1 specifies hdlr only within mdia or meta boxes */
3872 if ((ret = mov_write_stbl_tag(s, pb, mov, track)) < 0)
3873 return ret;
3874 return update_size(pb, pos);
3875}
3876
3877static void get_pts_range(MOVMuxContext *mov, MOVTrack *track,
3878 int64_t *start, int64_t *end, int elst, int mdhd)
3879{
3880 if (track->tag == MKTAG('t','m','c','d') && mov->nb_meta_tmcd && track->nb_src_track) {
3881 // tmcd tracks gets track_duration set in mov_write_moov_tag from
3882 // another track's duration, while the end_pts may be left at zero.
3883 // Calculate the pts duration for that track instead.
3884 get_pts_range(mov, &mov->tracks[*track->src_track], start, end, elst, mdhd);
3885 *start = av_rescale(*start, track->timescale,
3886 mov->tracks[*track->src_track].timescale);
3887 *end = av_rescale(*end, track->timescale,
3888 mov->tracks[*track->src_track].timescale);
3889 return;
3890 }
3891 if (!mdhd && track->end_pts != AV_NOPTS_VALUE &&
3892 track->start_dts != AV_NOPTS_VALUE &&
3893 track->start_cts != AV_NOPTS_VALUE) {
3894 *start = track->start_dts + track->start_cts;
3895 *end = elst ? track->elst_end_pts : track->end_pts;
3896 return;
3897 }
3898 *start = 0;
3899 *end = track->track_duration;
3900}
3901
3903{
3904 int64_t start, end;
3905 get_pts_range(mov, track, &start, &end, 0, 1);
3906 return end - start;
3907}
3908
3909// Calculate the actual duration of the track, after edits.
3910// If it starts with a pts < 0, that is removed by the edit list.
3911// If it starts with a pts > 0, the edit list adds a delay before that.
3912// Thus, with edit lists enabled, the post-edit output of the file is
3913// starting with pts=0.
3915{
3916 int64_t start, end;
3917 get_pts_range(mov, track, &start, &end, 0, 0);
3918 if (mov->use_editlist != 0)
3919 start = 0;
3920 return end - start;
3921}
3922
3924{
3925 int64_t start, end;
3926 get_pts_range(mov, track, &start, &end, 1, 0);
3927 return end - start;
3928}
3929
3931{
3932 if (track && track->mode == MODE_ISM)
3933 return 1;
3934 if (duration < INT32_MAX)
3935 return 0;
3936 return 1;
3937}
3938
3940 MOVTrack *track)
3941{
3943 int version = mov_mdhd_mvhd_tkhd_version(mov, track, duration);
3944
3945 (version == 1) ? avio_wb32(pb, 44) : avio_wb32(pb, 32); /* size */
3946 ffio_wfourcc(pb, "mdhd");
3947 avio_w8(pb, version);
3948 avio_wb24(pb, 0); /* flags */
3949 if (version == 1) {
3950 avio_wb64(pb, track->time);
3951 avio_wb64(pb, track->time);
3952 } else {
3953 avio_wb32(pb, track->time); /* creation time */
3954 avio_wb32(pb, track->time); /* modification time */
3955 }
3956 avio_wb32(pb, track->timescale); /* time scale (sample rate for audio) */
3957 if (!track->entry && mov->mode == MODE_ISM)
3958 (version == 1) ? avio_wb64(pb, UINT64_C(0xffffffffffffffff)) : avio_wb32(pb, 0xffffffff);
3959 else if (!track->entry)
3960 (version == 1) ? avio_wb64(pb, 0) : avio_wb32(pb, 0);
3961 else
3962 (version == 1) ? avio_wb64(pb, duration) : avio_wb32(pb, duration); /* duration */
3963 avio_wb16(pb, track->language); /* language */
3964 avio_wb16(pb, 0); /* reserved (quality) */
3965
3966 if (version != 0 && track->mode == MODE_MOV) {
3968 "FATAL error, file duration too long for timebase, this file will not be\n"
3969 "playable with QuickTime. Choose a different timebase with "
3970 "-video_track_timescale or a different container format\n");
3971 }
3972
3973 return 32;
3974}
3975
3977 MOVMuxContext *mov, MOVTrack *track)
3978{
3979 int64_t pos = avio_tell(pb);
3980 int ret;
3981
3982 avio_wb32(pb, 0); /* size */
3983 ffio_wfourcc(pb, "mdia");
3984 mov_write_mdhd_tag(pb, mov, track);
3985 mov_write_hdlr_tag(s, pb, track);
3986 if ((ret = mov_write_minf_tag(s, pb, mov, track)) < 0)
3987 return ret;
3988 return update_size(pb, pos);
3989}
3990
3991/* transformation matrix
3992 |a b u|
3993 |c d v|
3994 |tx ty w| */
3995static void write_matrix(AVIOContext *pb, int16_t a, int16_t b, int16_t c,
3996 int16_t d, int16_t tx, int16_t ty)
3997{
3998 avio_wb32(pb, a << 16); /* 16.16 format */
3999 avio_wb32(pb, b << 16); /* 16.16 format */
4000 avio_wb32(pb, 0); /* u in 2.30 format */
4001 avio_wb32(pb, c << 16); /* 16.16 format */
4002 avio_wb32(pb, d << 16); /* 16.16 format */
4003 avio_wb32(pb, 0); /* v in 2.30 format */
4004 avio_wb32(pb, tx << 16); /* 16.16 format */
4005 avio_wb32(pb, ty << 16); /* 16.16 format */
4006 avio_wb32(pb, 1 << 30); /* w in 2.30 format */
4007}
4008
4010 MOVTrack *track, AVStream *st)
4011{
4013 mov->movie_timescale, track->timescale,
4014 AV_ROUND_UP);
4015 int version;
4017 int group = 0;
4018
4019 uint32_t *display_matrix = NULL;
4020 int i;
4021
4022 if (mov->mode == MODE_AVIF)
4023 if (!mov->avif_loop_count)
4024 duration = INT64_MAX;
4025 else
4026 duration *= mov->avif_loop_count;
4027
4028 if (st) {
4029 const AVPacketSideData *sd;
4030 if (mov->per_stream_grouping)
4031 group = st->index;
4032 else
4033 group = st->codecpar->codec_type;
4034
4038 if (sd && sd->size == 9 * sizeof(*display_matrix))
4039 display_matrix = (uint32_t *)sd->data;
4040 }
4041
4042 if (track->flags & MOV_TRACK_ENABLED)
4044
4046
4047 (version == 1) ? avio_wb32(pb, 104) : avio_wb32(pb, 92); /* size */
4048 ffio_wfourcc(pb, "tkhd");
4049 avio_w8(pb, version);
4050 avio_wb24(pb, flags);
4051 if (version == 1) {
4052 avio_wb64(pb, track->time);
4053 avio_wb64(pb, track->time);
4054 } else {
4055 avio_wb32(pb, track->time); /* creation time */
4056 avio_wb32(pb, track->time); /* modification time */
4057 }
4058 avio_wb32(pb, track->track_id); /* track-id */
4059 avio_wb32(pb, 0); /* reserved */
4060 if (!track->entry && mov->mode == MODE_ISM)
4061 (version == 1) ? avio_wb64(pb, UINT64_C(0xffffffffffffffff)) : avio_wb32(pb, 0xffffffff);
4062 else if (!track->entry)
4063 (version == 1) ? avio_wb64(pb, 0) : avio_wb32(pb, 0);
4064 else
4065 (version == 1) ? avio_wb64(pb, duration) : avio_wb32(pb, duration);
4066
4067 avio_wb32(pb, 0); /* reserved */
4068 avio_wb32(pb, 0); /* reserved */
4069 avio_wb16(pb, 0); /* layer */
4070 avio_wb16(pb, group); /* alternate group) */
4071 /* Volume, only for audio */
4072 if (track->par->codec_type == AVMEDIA_TYPE_AUDIO)
4073 avio_wb16(pb, 0x0100);
4074 else
4075 avio_wb16(pb, 0);
4076 avio_wb16(pb, 0); /* reserved */
4077
4078 /* Matrix structure */
4079 if (display_matrix) {
4080 for (i = 0; i < 9; i++)
4081 avio_wb32(pb, display_matrix[i]);
4082 } else {
4083 write_matrix(pb, 1, 0, 0, 1, 0, 0);
4084 }
4085 /* Track width and height, for visual only */
4086 if (st && (track->par->codec_type == AVMEDIA_TYPE_VIDEO ||
4087 track->par->codec_type == AVMEDIA_TYPE_SUBTITLE)) {
4088 int64_t track_width_1616;
4089 if (track->mode == MODE_MOV || track->mode == MODE_AVIF) {
4090 track_width_1616 = track->par->width * 0x10000ULL;
4091 } else {
4092 track_width_1616 = av_rescale(st->sample_aspect_ratio.num,
4093 track->par->width * 0x10000LL,
4095 if (!track_width_1616 ||
4096 track->height != track->par->height ||
4097 track_width_1616 > UINT32_MAX)
4098 track_width_1616 = track->par->width * 0x10000ULL;
4099 }
4100 if (track_width_1616 > UINT32_MAX) {
4101 av_log(mov->fc, AV_LOG_WARNING, "track width is too large\n");
4102 track_width_1616 = 0;
4103 }
4104 avio_wb32(pb, track_width_1616);
4105 if (track->height > 0xFFFF) {
4106 av_log(mov->fc, AV_LOG_WARNING, "track height is too large\n");
4107 avio_wb32(pb, 0);
4108 } else
4109 avio_wb32(pb, track->height * 0x10000U);
4110 } else {
4111 avio_wb32(pb, 0);
4112 avio_wb32(pb, 0);
4113 }
4114 return 0x5c;
4115}
4116
4118{
4120 track->par->sample_aspect_ratio.den);
4121
4122 int64_t pos = avio_tell(pb);
4123
4124 avio_wb32(pb, 0); /* size */
4125 ffio_wfourcc(pb, "tapt");
4126
4127 avio_wb32(pb, 20);
4128 ffio_wfourcc(pb, "clef");
4129 avio_wb32(pb, 0);
4130 avio_wb32(pb, width << 16);
4131 avio_wb32(pb, track->par->height << 16);
4132
4133 avio_wb32(pb, 20);
4134 ffio_wfourcc(pb, "prof");
4135 avio_wb32(pb, 0);
4136 avio_wb32(pb, width << 16);
4137 avio_wb32(pb, track->par->height << 16);
4138
4139 avio_wb32(pb, 20);
4140 ffio_wfourcc(pb, "enof");
4141 avio_wb32(pb, 0);
4142 avio_wb32(pb, track->par->width << 16);
4143 avio_wb32(pb, track->par->height << 16);
4144
4145 return update_size(pb, pos);
4146}
4147
4148// This box is written in the following cases:
4149// * Seems important for the psp playback. Without it the movie seems to hang.
4150// * Used for specifying the looping behavior of animated AVIF (as specified
4151// in Section 9.6 of the HEIF specification ISO/IEC 23008-12).
4153 MOVTrack *track)
4154{
4156 mov->movie_timescale, track->timescale,
4157 AV_ROUND_UP);
4158 int version = duration < INT32_MAX ? 0 : 1;
4159 int entry_size, entry_count, size;
4160 int64_t delay, start_ct = track->start_cts;
4161 int64_t start_dts = track->start_dts;
4162 int flags = 0;
4163
4164 if (track->entry) {
4165 if (start_dts != track->cluster[0].dts || (start_ct != track->cluster[0].cts && track->cluster[0].dts >= 0)) {
4166
4167 av_log(mov->fc, AV_LOG_DEBUG,
4168 "EDTS using dts:%"PRId64" cts:%d instead of dts:%"PRId64" cts:%"PRId64" tid:%d\n",
4169 track->cluster[0].dts, track->cluster[0].cts,
4170 start_dts, start_ct, track->track_id);
4171 start_dts = track->cluster[0].dts;
4172 start_ct = track->cluster[0].cts;
4173 }
4174 }
4175
4176 delay = av_rescale_rnd(start_dts + start_ct, mov->movie_timescale,
4177 track->timescale, AV_ROUND_DOWN);
4178
4179 if (mov->mode == MODE_AVIF) {
4180 delay = 0;
4181 // Section 9.6.3 of ISO/IEC 23008-12: flags specifies repetition of the
4182 // edit list as follows: (flags & 1) equal to 0 specifies that the edit
4183 // list is not repeated, while (flags & 1) equal to 1 specifies that the
4184 // edit list is repeated.
4185 flags = mov->avif_loop_count != 1;
4186 start_ct = 0;
4187 }
4188
4189 version |= delay < INT32_MAX ? 0 : 1;
4190
4191 entry_size = (version == 1) ? 20 : 12;
4192 entry_count = 1 + (delay > 0);
4193 size = 24 + entry_count * entry_size;
4194
4195 /* write the atom data */
4196 avio_wb32(pb, size);
4197 ffio_wfourcc(pb, "edts");
4198 avio_wb32(pb, size - 8);
4199 ffio_wfourcc(pb, "elst");
4200 avio_w8(pb, version);
4201 avio_wb24(pb, flags); /* flags */
4202
4203 avio_wb32(pb, entry_count);
4204 if (delay > 0) { /* add an empty edit to delay presentation */
4205 /* In the positive delay case, the delay includes the cts
4206 * offset, and the second edit list entry below trims out
4207 * the same amount from the actual content. This makes sure
4208 * that the offset last sample is included in the edit
4209 * list duration as well. */
4210 if (version == 1) {
4211 avio_wb64(pb, delay);
4212 avio_wb64(pb, -1);
4213 } else {
4214 avio_wb32(pb, delay);
4215 avio_wb32(pb, -1);
4216 }
4217 avio_wb32(pb, 0x00010000);
4218 } else if (mov->mode != MODE_AVIF) {
4219 /* Avoid accidentally ending up with start_ct = -1 which has got a
4220 * special meaning. Normally start_ct should end up positive or zero
4221 * here, but use FFMIN in case dts is a small positive integer
4222 * rounded to 0 when represented in movie timescale units. */
4223 av_assert0(av_rescale_rnd(start_dts, mov->movie_timescale, track->timescale, AV_ROUND_DOWN) <= 0);
4224 start_ct = -FFMIN(start_dts, 0);
4225
4226#if CONFIG_IAMFENC
4227 if (track->iamf && track->par->codec_id == AV_CODEC_ID_OPUS)
4228 start_ct = av_rescale(start_ct, 48000, track->par->sample_rate);
4229#endif
4230 /* Note, this delay is calculated from the pts of the first sample,
4231 * ensuring that we don't reduce the duration for cases with
4232 * dts<0 pts=0. */
4233 duration += delay;
4234 }
4235
4236 /* For fragmented files, we don't know the full length yet. Setting
4237 * duration to 0 allows us to only specify the offset, including
4238 * the rest of the content (from all future fragments) without specifying
4239 * an explicit duration.
4240 *
4241 * For hybrid_fragmented during mov_write_trailer (mov->moov_written != 0),
4242 * don't reset duration to zero.
4243 */
4244 if (mov->flags & FF_MOV_FLAG_FRAGMENT &&
4246 duration = 0;
4247
4248 /* duration */
4249 if (version == 1) {
4250 avio_wb64(pb, duration);
4251 avio_wb64(pb, start_ct);
4252 } else {
4253 avio_wb32(pb, duration);
4254 avio_wb32(pb, start_ct);
4255 }
4256 avio_wb32(pb, 0x00010000);
4257 return size;
4258}
4259
4261{
4262 int64_t pos = avio_tell(pb);
4263 avio_wb32(pb, 0); // size placeholder
4264 ffio_wfourcc(pb, "tref");
4265
4266 for (int i = 0; i < track->nb_tref_tags; i++) {
4267 MovTag *tag = &track->tref_tags[i];
4268 avio_wb32(pb, 8 + tag->nb_id * sizeof(*tag->id)); // size (subatom)
4269 avio_wl32(pb, tag->name);
4270 for (int j = 0; j < tag->nb_id; j++)
4271 avio_wb32(pb, tag->id[j]);
4272 }
4273 return update_size(pb, pos);
4274}
4275
4276// goes at the end of each track! ... Critical for PSP playback ("Incompatible data" without it)
4278{
4279 avio_wb32(pb, 0x34); /* size ... reports as 28 in mp4box! */
4280 ffio_wfourcc(pb, "uuid");
4281 ffio_wfourcc(pb, "USMT");
4282 avio_wb32(pb, 0x21d24fce);
4283 avio_wb32(pb, 0xbb88695c);
4284 avio_wb32(pb, 0xfac9c740);
4285 avio_wb32(pb, 0x1c); // another size here!
4286 ffio_wfourcc(pb, "MTDT");
4287 avio_wb32(pb, 0x00010012);
4288 avio_wb32(pb, 0x0a);
4289 avio_wb32(pb, 0x55c40000);
4290 avio_wb32(pb, 0x1);
4291 avio_wb32(pb, 0x0);
4292 return 0x34;
4293}
4294
4296{
4297 AVFormatContext *ctx = track->rtp_ctx;
4298 char buf[1000] = "";
4299 int len;
4300
4301 av_assert0(track->nb_src_track);
4302 ff_sdp_write_media(buf, sizeof(buf), ctx->streams[0], *track->src_track,
4303 NULL, NULL, 0, 0, ctx);
4304 av_strlcatf(buf, sizeof(buf), "a=control:streamid=%d\r\n", track->track_id);
4305 len = strlen(buf);
4306
4307 avio_wb32(pb, len + 24);
4308 ffio_wfourcc(pb, "udta");
4309 avio_wb32(pb, len + 16);
4310 ffio_wfourcc(pb, "hnti");
4311 avio_wb32(pb, len + 8);
4312 ffio_wfourcc(pb, "sdp ");
4313 avio_write(pb, buf, len);
4314 return len + 24;
4315}
4316
4318 const char *tag, const char *str)
4319{
4320 int64_t pos = avio_tell(pb);
4321 AVDictionaryEntry *t = av_dict_get(st->metadata, str, NULL, 0);
4322 if (!t || !utf8len(t->value))
4323 return 0;
4324
4325 avio_wb32(pb, 0); /* size */
4326 ffio_wfourcc(pb, tag); /* type */
4327 avio_write(pb, t->value, strlen(t->value)); /* UTF8 string value */
4328 return update_size(pb, pos);
4329}
4330
4331static int mov_write_track_kind(AVIOContext *pb, const char *scheme_uri,
4332 const char *value)
4333{
4334 int64_t pos = avio_tell(pb);
4335
4336 /* Box|FullBox basics */
4337 avio_wb32(pb, 0); /* size placeholder */
4338 ffio_wfourcc(pb, (const unsigned char *)"kind");
4339 avio_w8(pb, 0); /* version = 0 */
4340 avio_wb24(pb, 0); /* flags = 0 */
4341
4342 /* Required null-terminated scheme URI */
4343 avio_write(pb, (const unsigned char *)scheme_uri,
4344 strlen(scheme_uri));
4345 avio_w8(pb, 0);
4346
4347 /* Optional value string */
4348 if (value && value[0])
4349 avio_write(pb, (const unsigned char *)value,
4350 strlen(value));
4351
4352 avio_w8(pb, 0);
4353
4354 return update_size(pb, pos);
4355}
4356
4358{
4359 int ret = AVERROR_BUG;
4360
4361 for (int i = 0; ff_mov_track_kind_table[i].scheme_uri; i++) {
4363
4364 for (int j = 0; map.value_maps[j].disposition; j++) {
4365 const struct MP4TrackKindValueMapping value_map = map.value_maps[j];
4366 if (!(st->disposition & value_map.disposition))
4367 continue;
4368
4369 if ((ret = mov_write_track_kind(pb, map.scheme_uri, value_map.value)) < 0)
4370 return ret;
4371 }
4372 }
4373
4374 return 0;
4375}
4376
4378 AVStream *st)
4379{
4380 AVIOContext *pb_buf;
4381 int ret, size;
4382 uint8_t *buf;
4383
4384 if (!st)
4385 return 0;
4386
4387 ret = avio_open_dyn_buf(&pb_buf);
4388 if (ret < 0)
4389 return ret;
4390
4391 if (mov->mode & (MODE_MP4|MODE_MOV))
4392 mov_write_track_metadata(pb_buf, st, "name", "title");
4393
4394 if (mov->mode & MODE_MP4) {
4395 if ((ret = mov_write_track_kinds(pb_buf, st)) < 0)
4396 goto end;
4397 }
4398
4399 if ((size = avio_get_dyn_buf(pb_buf, &buf)) > 0) {
4400 avio_wb32(pb, size + 8);
4401 ffio_wfourcc(pb, "udta");
4402 avio_write(pb, buf, size);
4403 }
4404end:
4405 ffio_free_dyn_buf(&pb_buf);
4406
4407 return ret;
4408}
4409
4411 MOVTrack *track, AVStream *st)
4412{
4413 int64_t pos = avio_tell(pb);
4414 int entry_backup = track->entry;
4415 int chunk_backup = track->chunkCount;
4416 int ret;
4417
4418 /* If we want to have an empty moov, but some samples already have been
4419 * buffered (delay_moov), pretend that no samples have been written yet. */
4420 if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV)
4421 track->chunkCount = track->entry = 0;
4422
4423 avio_wb32(pb, 0); /* size */
4424 ffio_wfourcc(pb, "trak");
4425 mov_write_tkhd_tag(pb, mov, track, st);
4426
4427 av_assert2(mov->use_editlist >= 0);
4428
4429 if (track->start_dts != AV_NOPTS_VALUE) {
4430 if (mov->use_editlist)
4431 mov_write_edts_tag(pb, mov, track); // PSP Movies and several other cases require edts box
4432 else if ((track->entry && track->cluster[0].dts) || track->mode == MODE_PSP || is_clcp_track(track))
4433 av_log(mov->fc, AV_LOG_WARNING,
4434 "Not writing any edit list even though one would have been required\n");
4435 }
4436
4437 if (mov->is_animated_avif)
4438 mov_write_edts_tag(pb, mov, track);
4439
4440 if (track->nb_tref_tags)
4441 mov_write_tref_tag(pb, track);
4442
4443 if ((ret = mov_write_mdia_tag(s, pb, mov, track)) < 0)
4444 return ret;
4445 if (track->mode == MODE_PSP)
4446 mov_write_uuid_tag_psp(pb, track); // PSP Movies require this uuid box
4447 if (track->tag == MKTAG('r','t','p',' '))
4448 mov_write_udta_sdp(pb, track);
4449 if (track->mode == MODE_MOV) {
4450 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
4451 double sample_aspect_ratio = av_q2d(st->sample_aspect_ratio);
4452 if (st->sample_aspect_ratio.num && 1.0 != sample_aspect_ratio) {
4453 mov_write_tapt_tag(pb, track);
4454 }
4455 }
4456 if (is_clcp_track(track) && st->sample_aspect_ratio.num) {
4457 mov_write_tapt_tag(pb, track);
4458 }
4459 }
4460 mov_write_track_udta_tag(pb, mov, st);
4461 track->entry = entry_backup;
4462 track->chunkCount = chunk_backup;
4463 return update_size(pb, pos);
4464}
4465
4467{
4468 int i, has_audio = 0, has_video = 0;
4469 int64_t pos = avio_tell(pb);
4470 int audio_profile = mov->iods_audio_profile;
4471 int video_profile = mov->iods_video_profile;
4472 for (i = 0; i < mov->nb_tracks; i++) {
4473 if (mov->tracks[i].entry > 0 || mov->flags & FF_MOV_FLAG_EMPTY_MOOV) {
4474 has_audio |= mov->tracks[i].par->codec_type == AVMEDIA_TYPE_AUDIO;
4475 has_video |= mov->tracks[i].par->codec_type == AVMEDIA_TYPE_VIDEO;
4476 }
4477 }
4478 if (audio_profile < 0)
4479 audio_profile = 0xFF - has_audio;
4480 if (video_profile < 0)
4481 video_profile = 0xFF - has_video;
4482 avio_wb32(pb, 0x0); /* size */
4483 ffio_wfourcc(pb, "iods");
4484 avio_wb32(pb, 0); /* version & flags */
4485 put_descr(pb, 0x10, 7);
4486 avio_wb16(pb, 0x004f);
4487 avio_w8(pb, 0xff);
4488 avio_w8(pb, 0xff);
4489 avio_w8(pb, audio_profile);
4490 avio_w8(pb, video_profile);
4491 avio_w8(pb, 0xff);
4492 return update_size(pb, pos);
4493}
4494
4496{
4497 avio_wb32(pb, 0x20); /* size */
4498 ffio_wfourcc(pb, "trex");
4499 avio_wb32(pb, 0); /* version & flags */
4500 avio_wb32(pb, track->track_id); /* track ID */
4501 avio_wb32(pb, 1); /* default sample description index */
4502 avio_wb32(pb, 0); /* default sample duration */
4503 avio_wb32(pb, 0); /* default sample size */
4504 avio_wb32(pb, 0); /* default sample flags */
4505 return 0;
4506}
4507
4509{
4510 int64_t pos = avio_tell(pb);
4511 int i;
4512 avio_wb32(pb, 0x0); /* size */
4513 ffio_wfourcc(pb, "mvex");
4514 for (i = 0; i < mov->nb_tracks; i++)
4515 mov_write_trex_tag(pb, &mov->tracks[i]);
4516 return update_size(pb, pos);
4517}
4518
4520{
4521 int max_track_id = 1, i;
4522 int64_t max_track_len = 0;
4523 int version;
4524 int timescale;
4525
4526 for (i = 0; i < mov->nb_tracks; i++) {
4527 if (mov->tracks[i].entry > 0 && mov->tracks[i].timescale) {
4528 int64_t max_track_len_temp = av_rescale_rnd(
4529 calc_pts_duration(mov, &mov->tracks[i]),
4530 mov->movie_timescale,
4531 mov->tracks[i].timescale,
4532 AV_ROUND_UP);
4533 if (max_track_len < max_track_len_temp)
4534 max_track_len = max_track_len_temp;
4535 if (max_track_id < mov->tracks[i].track_id)
4536 max_track_id = mov->tracks[i].track_id;
4537 }
4538 }
4539 /* If using delay_moov, make sure the output is the same as if no
4540 * samples had been written yet. */
4541 if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV) {
4542 max_track_len = 0;
4543 max_track_id = 1;
4544 }
4545
4546 version = mov_mdhd_mvhd_tkhd_version(mov, NULL, max_track_len);
4547 avio_wb32(pb, version == 1 ? 120 : 108); /* size */
4548
4549 ffio_wfourcc(pb, "mvhd");
4550 avio_w8(pb, version);
4551 avio_wb24(pb, 0); /* flags */
4552 if (version == 1) {
4553 avio_wb64(pb, mov->time);
4554 avio_wb64(pb, mov->time);
4555 } else {
4556 avio_wb32(pb, mov->time); /* creation time */
4557 avio_wb32(pb, mov->time); /* modification time */
4558 }
4559
4560 timescale = mov->movie_timescale;
4561 if (mov->mode == MODE_AVIF && !timescale)
4562 timescale = mov->tracks[0].timescale;
4563
4564 avio_wb32(pb, timescale);
4565 (version == 1) ? avio_wb64(pb, max_track_len) : avio_wb32(pb, max_track_len); /* duration of longest track */
4566
4567 avio_wb32(pb, 0x00010000); /* reserved (preferred rate) 1.0 = normal */
4568 avio_wb16(pb, 0x0100); /* reserved (preferred volume) 1.0 = normal */
4569 ffio_fill(pb, 0, 2 + 2 * 4); /* reserved */
4570
4571 /* Matrix structure */
4572 write_matrix(pb, 1, 0, 0, 1, 0, 0);
4573
4574 avio_wb32(pb, 0); /* reserved (preview time) */
4575 avio_wb32(pb, 0); /* reserved (preview duration) */
4576 avio_wb32(pb, 0); /* reserved (poster time) */
4577 avio_wb32(pb, 0); /* reserved (selection time) */
4578 avio_wb32(pb, 0); /* reserved (selection duration) */
4579 avio_wb32(pb, 0); /* reserved (current time) */
4580 avio_wb32(pb, max_track_id + 1); /* Next track id */
4581 return 0x6c;
4582}
4583
4586{
4587 avio_wb32(pb, 33); /* size */
4588 ffio_wfourcc(pb, "hdlr");
4589 avio_wb32(pb, 0);
4590 avio_wb32(pb, 0);
4591 ffio_wfourcc(pb, "mdir");
4592 ffio_wfourcc(pb, "appl");
4593 avio_wb32(pb, 0);
4594 avio_wb32(pb, 0);
4595 avio_w8(pb, 0);
4596 return 33;
4597}
4598
4599/* helper function to write a data tag with the specified string as data */
4600static int mov_write_string_data_tag(AVIOContext *pb, const char *data, int lang, int long_style)
4601{
4602 size_t data_len = strlen(data);
4603 if (long_style) {
4604 int size = 16 + data_len;
4605 avio_wb32(pb, size); /* size */
4606 ffio_wfourcc(pb, "data");
4607 avio_wb32(pb, 1);
4608 avio_wb32(pb, 0);
4609 avio_write(pb, data, data_len);
4610 return size;
4611 } else {
4612 avio_wb16(pb, data_len); /* string length */
4613 if (!lang)
4614 lang = ff_mov_iso639_to_lang("und", 1);
4615 avio_wb16(pb, lang);
4616 avio_write(pb, data, data_len);
4617 return data_len + 4;
4618 }
4619}
4620
4621static int mov_write_string_tag(AVIOContext *pb, const char *name,
4622 const char *value, int lang, int long_style)
4623{
4624 int size = 0;
4625 if (value && value[0]) {
4626 int64_t pos = avio_tell(pb);
4627 avio_wb32(pb, 0); /* size */
4628 ffio_wfourcc(pb, name);
4629 mov_write_string_data_tag(pb, value, lang, long_style);
4630 size = update_size(pb, pos);
4631 }
4632 return size;
4633}
4634
4635static int mov_write_freeform_tag(AVIOContext *pb, const char *mean,
4636 const char *name, const char *data)
4637{
4638 if (!data || !data[0])
4639 return 0;
4640
4641 static const char stub_flags[4] = {0, 0, 0, 0};
4642
4643 int64_t entry_pos = avio_tell(pb);
4644 avio_wb32(pb, 0); /* size */
4645 ffio_wfourcc(pb, "----"); /* freeform */
4646
4647 size_t mean_len = strlen(mean);
4648 avio_wb32(pb, 12 + mean_len);
4649 ffio_wfourcc(pb, "mean");
4650 avio_write(pb, &stub_flags[0], sizeof(stub_flags));
4651 avio_write(pb, mean, mean_len);
4652
4653 size_t name_len = strlen(name);
4654 avio_wb32(pb, 12 + name_len);
4655 ffio_wfourcc(pb, "name");
4656 avio_write(pb, &stub_flags[0], sizeof(stub_flags));
4657 avio_write(pb, name, name_len);
4658
4660
4661 return update_size(pb, entry_pos);
4662}
4663
4665 const char *tag, int *lang)
4666{
4667 int l, len, len2;
4668 AVDictionaryEntry *t, *t2 = NULL;
4669 char tag2[16];
4670
4671 *lang = 0;
4672
4673 if (!(t = av_dict_get(s->metadata, tag, NULL, 0)))
4674 return NULL;
4675
4676 len = strlen(t->key);
4677 snprintf(tag2, sizeof(tag2), "%s-", tag);
4678 while ((t2 = av_dict_get(s->metadata, tag2, t2, AV_DICT_IGNORE_SUFFIX))) {
4679 len2 = strlen(t2->key);
4680 if (len2 == len + 4 && !strcmp(t->value, t2->value)
4681 && (l = ff_mov_iso639_to_lang(&t2->key[len2 - 3], 1)) >= 0) {
4682 *lang = l;
4683 return t;
4684 }
4685 }
4686 return t;
4687}
4688
4690 const char *name, const char *tag,
4691 int long_style)
4692{
4693 int lang;
4695 if (!t)
4696 return 0;
4697 return mov_write_string_tag(pb, name, t->value, lang, long_style);
4698}
4699
4701 const char *mean, const char *name,
4702 const char *tag)
4703{
4704 AVDictionaryEntry *t = av_dict_get(s->metadata, tag, NULL, 0);
4705 if (!t)
4706 return 0;
4707 return mov_write_freeform_tag(pb, mean, name, t->value);
4708}
4709
4710/* iTunes bpm number */
4712{
4713 AVDictionaryEntry *t = av_dict_get(s->metadata, "tmpo", NULL, 0);
4714 int size = 0, tmpo = t ? atoi(t->value) : 0;
4715 if (tmpo) {
4716 size = 26;
4717 avio_wb32(pb, size);
4718 ffio_wfourcc(pb, "tmpo");
4719 avio_wb32(pb, size-8); /* size */
4720 ffio_wfourcc(pb, "data");
4721 avio_wb32(pb, 0x15); //type specifier
4722 avio_wb32(pb, 0);
4723 avio_wb16(pb, tmpo); // data
4724 }
4725 return size;
4726}
4727
4728/* 3GPP TS 26.244 */
4730{
4731 int lang;
4732 int64_t pos = avio_tell(pb);
4733 double latitude, longitude, altitude;
4734 int32_t latitude_fix, longitude_fix, altitude_fix;
4735 AVDictionaryEntry *t = get_metadata_lang(s, "location", &lang);
4736 const char *ptr, *place = "";
4737 char *end;
4738 static const char *astronomical_body = "earth";
4739 if (!t)
4740 return 0;
4741
4742 ptr = t->value;
4743 latitude = strtod(ptr, &end);
4744 if (end == ptr) {
4745 av_log(s, AV_LOG_WARNING, "malformed location metadata\n");
4746 return 0;
4747 }
4748 ptr = end;
4749 longitude = strtod(ptr, &end);
4750 if (end == ptr) {
4751 av_log(s, AV_LOG_WARNING, "malformed location metadata\n");
4752 return 0;
4753 }
4754 ptr = end;
4755 altitude = strtod(ptr, &end);
4756 /* If no altitude was present, the default 0 should be fine */
4757 if (*end == '/')
4758 place = end + 1;
4759
4760 latitude_fix = (int32_t) ((1 << 16) * latitude);
4761 longitude_fix = (int32_t) ((1 << 16) * longitude);
4762 altitude_fix = (int32_t) ((1 << 16) * altitude);
4763
4764 avio_wb32(pb, 0); /* size */
4765 ffio_wfourcc(pb, "loci"); /* type */
4766 avio_wb32(pb, 0); /* version + flags */
4767 avio_wb16(pb, lang);
4768 avio_write(pb, place, strlen(place) + 1);
4769 avio_w8(pb, 0); /* role of place (0 == shooting location, 1 == real location, 2 == fictional location) */
4770 avio_wb32(pb, longitude_fix);
4771 avio_wb32(pb, latitude_fix);
4772 avio_wb32(pb, altitude_fix);
4773 avio_write(pb, astronomical_body, strlen(astronomical_body) + 1);
4774 avio_w8(pb, 0); /* additional notes, null terminated string */
4775
4776 return update_size(pb, pos);
4777}
4778
4779/* iTunes track or disc number */
4781 AVFormatContext *s, int disc)
4782{
4783 AVDictionaryEntry *t = av_dict_get(s->metadata,
4784 disc ? "disc" : "track",
4785 NULL, 0);
4786 int size = 0, track = t ? atoi(t->value) : 0;
4787 if (track) {
4788 int tracks = 0;
4789 char *slash = strchr(t->value, '/');
4790 if (slash)
4791 tracks = atoi(slash + 1);
4792 avio_wb32(pb, 32); /* size */
4793 ffio_wfourcc(pb, disc ? "disk" : "trkn");
4794 avio_wb32(pb, 24); /* size */
4795 ffio_wfourcc(pb, "data");
4796 avio_wb32(pb, 0); // 8 bytes empty
4797 avio_wb32(pb, 0);
4798 avio_wb16(pb, 0); // empty
4799 avio_wb16(pb, track); // track / disc number
4800 avio_wb16(pb, tracks); // total track / disc number
4801 avio_wb16(pb, 0); // empty
4802 size = 32;
4803 }
4804 return size;
4805}
4806
4808 const char *name, const char *tag,
4809 int len)
4810{
4812 uint8_t num;
4813 int size = 24 + len;
4814
4815 if (len != 1 && len != 4)
4816 return -1;
4817
4818 if (!(t = av_dict_get(s->metadata, tag, NULL, 0)))
4819 return 0;
4820 num = atoi(t->value);
4821
4822 avio_wb32(pb, size);
4823 ffio_wfourcc(pb, name);
4824 avio_wb32(pb, size - 8);
4825 ffio_wfourcc(pb, "data");
4826 avio_wb32(pb, 0x15);
4827 avio_wb32(pb, 0);
4828 if (len==4) avio_wb32(pb, num);
4829 else avio_w8 (pb, num);
4830
4831 return size;
4832}
4833
4835{
4836 MOVMuxContext *mov = s->priv_data;
4837 int64_t pos = 0;
4838
4839 for (int i = 0; i < mov->nb_streams; i++) {
4840 MOVTrack *trk = &mov->tracks[i];
4841
4842 if (!is_cover_image(trk->st) || trk->cover_image->size <= 0)
4843 continue;
4844
4845 if (!pos) {
4846 pos = avio_tell(pb);
4847 avio_wb32(pb, 0);
4848 ffio_wfourcc(pb, "covr");
4849 }
4850 avio_wb32(pb, 16 + trk->cover_image->size);
4851 ffio_wfourcc(pb, "data");
4852 avio_wb32(pb, trk->tag);
4853 avio_wb32(pb , 0);
4854 avio_write(pb, trk->cover_image->data, trk->cover_image->size);
4855 }
4856
4857 return pos ? update_size(pb, pos) : 0;
4858}
4859
4860/* iTunes meta data list */
4863{
4864 int64_t pos = avio_tell(pb);
4865 avio_wb32(pb, 0); /* size */
4866 ffio_wfourcc(pb, "ilst");
4867 mov_write_string_metadata(s, pb, "\251nam", "title" , 1);
4868 mov_write_string_metadata(s, pb, "\251ART", "artist" , 1);
4869 mov_write_string_metadata(s, pb, "aART", "album_artist", 1);
4870 mov_write_string_metadata(s, pb, "\251wrt", "composer" , 1);
4871 mov_write_string_metadata(s, pb, "\251alb", "album" , 1);
4872 mov_write_string_metadata(s, pb, "\251day", "date" , 1);
4873 if (!mov_write_string_metadata(s, pb, "\251too", "encoding_tool", 1)) {
4874 if (!(s->flags & AVFMT_FLAG_BITEXACT))
4875 mov_write_string_tag(pb, "\251too", LIBAVFORMAT_IDENT, 0, 1);
4876 }
4877 mov_write_string_metadata(s, pb, "\251cmt", "comment" , 1);
4878 mov_write_string_metadata(s, pb, "\251gen", "genre" , 1);
4879 mov_write_string_metadata(s, pb, "cprt", "copyright", 1);
4880 mov_write_string_metadata(s, pb, "\251grp", "grouping" , 1);
4881 mov_write_string_metadata(s, pb, "\251lyr", "lyrics" , 1);
4882 mov_write_string_metadata(s, pb, "desc", "description",1);
4883 mov_write_string_metadata(s, pb, "ldes", "synopsis" , 1);
4884 mov_write_string_metadata(s, pb, "tvsh", "show" , 1);
4885 mov_write_string_metadata(s, pb, "tven", "episode_id",1);
4886 mov_write_string_metadata(s, pb, "tvnn", "network" , 1);
4887 mov_write_string_metadata(s, pb, "keyw", "keywords" , 1);
4888 mov_write_int8_metadata (s, pb, "tves", "episode_sort",4);
4889 mov_write_int8_metadata (s, pb, "tvsn", "season_number",4);
4890 mov_write_int8_metadata (s, pb, "stik", "media_type",1);
4891 mov_write_int8_metadata (s, pb, "hdvd", "hd_video", 1);
4892 mov_write_int8_metadata (s, pb, "pgap", "gapless_playback",1);
4893 mov_write_int8_metadata (s, pb, "cpil", "compilation", 1);
4894 mov_write_covr(pb, s);
4895 mov_write_trkn_tag(pb, mov, s, 0); // track number
4896 mov_write_trkn_tag(pb, mov, s, 1); // disc number
4897 mov_write_tmpo_tag(pb, s);
4898 mov_write_custom_metadata(s, pb, "com.apple.iTunes", "DISCSUBTITLE", "disc_subtitle");
4899 return update_size(pb, pos);
4900}
4901
4904{
4905 avio_wb32(pb, 33); /* size */
4906 ffio_wfourcc(pb, "hdlr");
4907 avio_wb32(pb, 0);
4908 avio_wb32(pb, 0);
4909 ffio_wfourcc(pb, "mdta");
4910 avio_wb32(pb, 0);
4911 avio_wb32(pb, 0);
4912 avio_wb32(pb, 0);
4913 avio_w8(pb, 0);
4914 return 33;
4915}
4916
4919{
4920 const AVDictionaryEntry *t = NULL;
4921 int64_t pos = avio_tell(pb);
4922 int64_t curpos, entry_pos;
4923 int count = 0;
4924
4925 avio_wb32(pb, 0); /* size */
4926 ffio_wfourcc(pb, "keys");
4927 avio_wb32(pb, 0);
4928 entry_pos = avio_tell(pb);
4929 avio_wb32(pb, 0); /* entry count */
4930
4931 while (t = av_dict_iterate(s->metadata, t)) {
4932 size_t key_len = strlen(t->key);
4933 avio_wb32(pb, key_len + 8);
4934 ffio_wfourcc(pb, "mdta");
4935 avio_write(pb, t->key, key_len);
4936 count += 1;
4937 }
4938 curpos = avio_tell(pb);
4939 avio_seek(pb, entry_pos, SEEK_SET);
4940 avio_wb32(pb, count); // rewrite entry count
4941 avio_seek(pb, curpos, SEEK_SET);
4942
4943 return update_size(pb, pos);
4944}
4945
4948{
4949 const AVDictionaryEntry *t = NULL;
4950 int64_t pos = avio_tell(pb);
4951 int count = 1; /* keys are 1-index based */
4952
4953 avio_wb32(pb, 0); /* size */
4954 ffio_wfourcc(pb, "ilst");
4955
4956 while (t = av_dict_iterate(s->metadata, t)) {
4957 int64_t entry_pos = avio_tell(pb);
4958 avio_wb32(pb, 0); /* size */
4959 avio_wb32(pb, count); /* key */
4960 mov_write_string_data_tag(pb, t->value, 0, 1);
4961 update_size(pb, entry_pos);
4962 count += 1;
4963 }
4964 return update_size(pb, pos);
4965}
4966
4967/* meta data tags */
4970{
4971 int size = 0;
4972 int64_t pos = avio_tell(pb);
4973 avio_wb32(pb, 0); /* size */
4974 ffio_wfourcc(pb, "meta");
4975 avio_wb32(pb, 0);
4976 if (mov->flags & FF_MOV_FLAG_USE_MDTA) {
4977 mov_write_mdta_hdlr_tag(pb, mov, s);
4978 mov_write_mdta_keys_tag(pb, mov, s);
4979 mov_write_mdta_ilst_tag(pb, mov, s);
4980 } else if (mov->mode == MODE_AVIF) {
4981 mov_write_hdlr_tag(s, pb, &mov->tracks[0]);
4982 // We always write the primary item id as 1 since only one track is
4983 // supported for AVIF.
4984 mov_write_pitm_tag(pb, 1);
4985 mov_write_iloc_tag(pb, mov, s);
4986 mov_write_iinf_tag(pb, mov, s);
4987 if (mov->nb_streams > 1)
4988 mov_write_iref_tag(pb, mov, s);
4989 mov_write_iprp_tag(pb, mov, s);
4990 } else {
4991 /* iTunes metadata tag */
4992 mov_write_itunes_hdlr_tag(pb, mov, s);
4993 mov_write_ilst_tag(pb, mov, s);
4994 }
4995 size = update_size(pb, pos);
4996 return size;
4997}
4998
5000 const char *name, const char *key)
5001{
5002 int len;
5004
5005 if (!(t = av_dict_get(s->metadata, key, NULL, 0)))
5006 return 0;
5007
5008 len = strlen(t->value);
5009 if (len > 0) {
5010 int size = len + 8;
5011 avio_wb32(pb, size);
5012 ffio_wfourcc(pb, name);
5013 avio_write(pb, t->value, len);
5014 return size;
5015 }
5016 return 0;
5017}
5018
5019static int ascii_to_wc(AVIOContext *pb, const uint8_t *b)
5020{
5021 int val;
5022 while (*b) {
5023 GET_UTF8(val, *b++, return -1;)
5024 avio_wb16(pb, val);
5025 }
5026 avio_wb16(pb, 0x00);
5027 return 0;
5028}
5029
5030static uint16_t language_code(const char *str)
5031{
5032 return (((str[0] - 0x60) & 0x1F) << 10) +
5033 (((str[1] - 0x60) & 0x1F) << 5) +
5034 (( str[2] - 0x60) & 0x1F);
5035}
5036
5038 const char *tag, const char *str)
5039{
5040 int64_t pos = avio_tell(pb);
5041 AVDictionaryEntry *t = av_dict_get(s->metadata, str, NULL, 0);
5042 if (!t || !utf8len(t->value))
5043 return 0;
5044 avio_wb32(pb, 0); /* size */
5045 ffio_wfourcc(pb, tag); /* type */
5046 avio_wb32(pb, 0); /* version + flags */
5047 if (!strcmp(tag, "yrrc"))
5048 avio_wb16(pb, atoi(t->value));
5049 else {
5050 avio_wb16(pb, language_code("eng")); /* language */
5051 avio_write(pb, t->value, strlen(t->value) + 1); /* UTF8 string value */
5052 if (!strcmp(tag, "albm") &&
5053 (t = av_dict_get(s->metadata, "track", NULL, 0)))
5054 avio_w8(pb, atoi(t->value));
5055 }
5056 return update_size(pb, pos);
5057}
5058
5060{
5061 int64_t pos = avio_tell(pb);
5062 int i, nb_chapters = FFMIN(s->nb_chapters, 255);
5063
5064 avio_wb32(pb, 0); // size
5065 ffio_wfourcc(pb, "chpl");
5066 avio_wb32(pb, 0x01000000); // version + flags
5067 avio_wb32(pb, 0); // unknown
5068 avio_w8(pb, nb_chapters);
5069
5070 for (i = 0; i < nb_chapters; i++) {
5071 AVChapter *c = s->chapters[i];
5073 avio_wb64(pb, av_rescale_q(c->start, c->time_base, (AVRational){1,10000000}));
5074
5075 if ((t = av_dict_get(c->metadata, "title", NULL, 0))) {
5076 int len = FFMIN(strlen(t->value), 255);
5077 avio_w8(pb, len);
5078 avio_write(pb, t->value, len);
5079 } else
5080 avio_w8(pb, 0);
5081 }
5082 return update_size(pb, pos);
5083}
5084
5087{
5088 AVIOContext *pb_buf;
5089 int ret, size;
5090 uint8_t *buf;
5091
5092 ret = avio_open_dyn_buf(&pb_buf);
5093 if (ret < 0)
5094 return ret;
5095
5096 if (mov->mode & MODE_3GP) {
5097 mov_write_3gp_udta_tag(pb_buf, s, "perf", "artist");
5098 mov_write_3gp_udta_tag(pb_buf, s, "titl", "title");
5099 mov_write_3gp_udta_tag(pb_buf, s, "auth", "author");
5100 mov_write_3gp_udta_tag(pb_buf, s, "gnre", "genre");
5101 mov_write_3gp_udta_tag(pb_buf, s, "dscp", "comment");
5102 mov_write_3gp_udta_tag(pb_buf, s, "albm", "album");
5103 mov_write_3gp_udta_tag(pb_buf, s, "cprt", "copyright");
5104 mov_write_3gp_udta_tag(pb_buf, s, "yrrc", "date");
5105 mov_write_loci_tag(s, pb_buf);
5106 } else if (mov->mode == MODE_MOV && !(mov->flags & FF_MOV_FLAG_USE_MDTA)) { // the title field breaks gtkpod with mp4 and my suspicion is that stuff is not valid in mp4
5107 mov_write_string_metadata(s, pb_buf, "\251ART", "artist", 0);
5108 mov_write_string_metadata(s, pb_buf, "\251nam", "title", 0);
5109 mov_write_string_metadata(s, pb_buf, "\251aut", "author", 0);
5110 mov_write_string_metadata(s, pb_buf, "\251alb", "album", 0);
5111 mov_write_string_metadata(s, pb_buf, "\251day", "date", 0);
5112 mov_write_string_metadata(s, pb_buf, "\251swr", "encoder", 0);
5113 // currently ignored by mov.c
5114 mov_write_string_metadata(s, pb_buf, "\251des", "comment", 0);
5115 // add support for libquicktime, this atom is also actually read by mov.c
5116 mov_write_string_metadata(s, pb_buf, "\251cmt", "comment", 0);
5117 mov_write_string_metadata(s, pb_buf, "\251gen", "genre", 0);
5118 mov_write_string_metadata(s, pb_buf, "\251cpy", "copyright", 0);
5119 mov_write_string_metadata(s, pb_buf, "\251mak", "make", 0);
5120 mov_write_string_metadata(s, pb_buf, "\251mod", "model", 0);
5121 mov_write_string_metadata(s, pb_buf, "\251xyz", "location", 0);
5122 mov_write_string_metadata(s, pb_buf, "\251key", "keywords", 0);
5123 mov_write_raw_metadata_tag(s, pb_buf, "XMP_", "xmp");
5124 } else {
5125 /* iTunes meta data */
5126 mov_write_meta_tag(pb_buf, mov, s);
5127 mov_write_loci_tag(s, pb_buf);
5128 }
5129
5130 if (s->nb_chapters && !(mov->flags & FF_MOV_FLAG_DISABLE_CHPL))
5131 mov_write_chpl_tag(pb_buf, s);
5132
5133 if ((size = avio_get_dyn_buf(pb_buf, &buf)) > 0) {
5134 avio_wb32(pb, size + 8);
5135 ffio_wfourcc(pb, "udta");
5136 avio_write(pb, buf, size);
5137 }
5138 ffio_free_dyn_buf(&pb_buf);
5139
5140 return 0;
5141}
5142
5144 const char *str, const char *lang, int type)
5145{
5146 int len = utf8len(str) + 1;
5147 if (len <= 0)
5148 return;
5149 avio_wb16(pb, len * 2 + 10); /* size */
5150 avio_wb32(pb, type); /* type */
5151 avio_wb16(pb, language_code(lang)); /* language */
5152 avio_wb16(pb, 0x01); /* ? */
5153 ascii_to_wc(pb, str);
5154}
5155
5157{
5158 AVDictionaryEntry *title = av_dict_get(s->metadata, "title", NULL, 0);
5159 int64_t pos, pos2;
5160
5161 if (title) {
5162 pos = avio_tell(pb);
5163 avio_wb32(pb, 0); /* size placeholder*/
5164 ffio_wfourcc(pb, "uuid");
5165 ffio_wfourcc(pb, "USMT");
5166 avio_wb32(pb, 0x21d24fce); /* 96 bit UUID */
5167 avio_wb32(pb, 0xbb88695c);
5168 avio_wb32(pb, 0xfac9c740);
5169
5170 pos2 = avio_tell(pb);
5171 avio_wb32(pb, 0); /* size placeholder*/
5172 ffio_wfourcc(pb, "MTDT");
5173 avio_wb16(pb, 4);
5174
5175 // ?
5176 avio_wb16(pb, 0x0C); /* size */
5177 avio_wb32(pb, 0x0B); /* type */
5178 avio_wb16(pb, language_code("und")); /* language */
5179 avio_wb16(pb, 0x0); /* ? */
5180 avio_wb16(pb, 0x021C); /* data */
5181
5182 if (!(s->flags & AVFMT_FLAG_BITEXACT))
5183 mov_write_psp_udta_tag(pb, LIBAVFORMAT_IDENT, "eng", 0x04);
5184 mov_write_psp_udta_tag(pb, title->value, "eng", 0x01);
5185 mov_write_psp_udta_tag(pb, "2006/04/01 11:11:11", "und", 0x03);
5186
5187 update_size(pb, pos2);
5188 return update_size(pb, pos);
5189 }
5190
5191 return 0;
5192}
5193
5195{
5200 if (!sd)
5201 return 0;
5202
5204 for (AVEncryptionInitInfo *copy = info; copy; copy = copy->next) {
5205 int64_t pos;
5206
5207 if (!copy->data_size && !copy->num_key_ids)
5208 continue;
5209
5210 pos = avio_tell(pb);
5211 avio_wb32(pb, 0); /* size placeholder */
5212 ffio_wfourcc(pb, "pssh");
5213 avio_w8(pb, 1); /* version */
5214 avio_wb24(pb, 0);
5215 for (int i = 0; i < copy->system_id_size; i++)
5216 avio_w8(pb, copy->system_id[i]);
5217 avio_wb32(pb, copy->num_key_ids);
5218 for (int i = 0; i < copy->num_key_ids; i++)
5219 for (int j = 0; j < copy->key_id_size; j++)
5220 avio_w8(pb, copy->key_ids[i][j]);
5221 avio_wb32(pb, copy->data_size);
5222 avio_write(pb, copy->data, copy->data_size);
5223 update_size(pb, pos);
5224 }
5225
5227
5228 return 0;
5229}
5230
5231static void build_chunks(MOVTrack *trk)
5232{
5233 int i;
5234 MOVIentry *chunk = &trk->cluster[0];
5235 uint64_t chunkSize = chunk->size;
5236 chunk->chunkNum = 1;
5237 if (trk->chunkCount)
5238 return;
5239 trk->chunkCount = 1;
5240 for (i = 1; i<trk->entry; i++){
5241 if (chunk->pos + chunkSize == trk->cluster[i].pos &&
5242 chunk->stsd_index == trk->cluster[i].stsd_index &&
5243 chunkSize + trk->cluster[i].size < (1<<20)){
5244 chunkSize += trk->cluster[i].size;
5245 chunk->samples_in_chunk += trk->cluster[i].entries;
5246 } else {
5247 trk->cluster[i].chunkNum = chunk->chunkNum+1;
5248 chunk=&trk->cluster[i];
5249 chunkSize = chunk->size;
5250 trk->chunkCount++;
5251 }
5252 }
5253}
5254
5255/**
5256 * Assign track ids. If option "use_stream_ids_as_track_ids" is set,
5257 * the stream ids are used as track ids.
5258 *
5259 * This assumes mov->tracks and s->streams are in the same order and
5260 * there are no gaps in either of them (so mov->tracks[n] refers to
5261 * s->streams[n]).
5262 *
5263 * As an exception, there can be more entries in
5264 * s->streams than in mov->tracks, in which case new track ids are
5265 * generated (starting after the largest found stream id).
5266 */
5268{
5269 int i;
5270
5271 if (mov->track_ids_ok)
5272 return 0;
5273
5274 if (mov->use_stream_ids_as_track_ids) {
5275 int next_generated_track_id = 0;
5276 for (i = 0; i < mov->nb_streams; i++) {
5277 AVStream *st = mov->tracks[i].st;
5278 if (st->id > next_generated_track_id)
5279 next_generated_track_id = st->id;
5280 }
5281
5282 for (i = 0; i < mov->nb_tracks; i++) {
5283 if (mov->tracks[i].entry <= 0 && !(mov->flags & FF_MOV_FLAG_FRAGMENT))
5284 continue;
5285
5286 mov->tracks[i].track_id = i >= mov->nb_streams ? ++next_generated_track_id : mov->tracks[i].st->id;
5287 }
5288 } else {
5289 int last_track_id = 0;
5290 for (i = 0; i < mov->nb_tracks; i++) {
5291 if (mov->tracks[i].entry <= 0 && !(mov->flags & FF_MOV_FLAG_FRAGMENT))
5292 continue;
5293
5294 last_track_id =
5295 mov->tracks[i].track_id = (mov->tracks[i].st
5296 ? FFMAX(mov->tracks[i].st->index, last_track_id)
5297 : FFMAX(i, last_track_id)) + 1;
5298 }
5299 }
5300
5301 mov->track_ids_ok = 1;
5302
5303 return 0;
5304}
5305
5306static int mov_find_tref_id(MOVMuxContext *mov, const MovTag *tag, uint32_t id)
5307{
5308 for (int i = 0; i < tag->nb_id; i++) {
5309 if (tag->id[i] == id)
5310 return 1;
5311 }
5312 return 0;
5313}
5314
5315static int mov_add_tref_id(MOVMuxContext *mov, MovTag *tag, uint32_t id)
5316{
5317 int ret = mov_find_tref_id(mov, tag, id);
5318
5319 if (!ret) {
5320 uint32_t *tmp = av_realloc_array(tag->id, tag->nb_id + 1, sizeof(*tag->id));
5321 if (!tmp)
5322 return AVERROR(ENOMEM);
5323 tag->id = tmp;
5324 tag->id[tag->nb_id++] = id;
5325 }
5326
5327 return 0;
5328}
5329
5330static MovTag *mov_find_tref_tag(MOVMuxContext *mov, const MOVTrack *trk, uint32_t name)
5331{
5332 for (int i = 0; i < trk->nb_tref_tags; i++) {
5333 MovTag *entry = &trk->tref_tags[i];
5334
5335 if (entry->name == name)
5336 return entry;
5337 }
5338 return NULL;
5339}
5340
5342{
5343 MovTag *tag = mov_find_tref_tag(mov, trk, name);
5344
5345 if (!tag) {
5347 sizeof(*trk->tref_tags));
5348 if (!tmp)
5349 return NULL;
5350 trk->tref_tags = tmp;
5351 tag = &trk->tref_tags[trk->nb_tref_tags++];
5352 *tag = (MovTag){ .name = name };
5353 }
5354
5355 return tag;
5356}
5357
5360{
5361 int i;
5362 int64_t pos = avio_tell(pb);
5363 avio_wb32(pb, 0); /* size placeholder*/
5364 ffio_wfourcc(pb, "moov");
5365
5366 mov_setup_track_ids(mov, s);
5367
5368 for (i = 0; i < mov->nb_tracks; i++) {
5369 if (mov->tracks[i].entry <= 0 && !(mov->flags & FF_MOV_FLAG_FRAGMENT))
5370 continue;
5371
5372 mov->tracks[i].time = mov->time;
5373
5374 if (mov->tracks[i].entry)
5375 build_chunks(&mov->tracks[i]);
5376 }
5377
5378 if (mov->chapter_track)
5379 for (i = 0; i < mov->nb_streams; i++) {
5380 MovTag *tag = mov_add_tref_tag(mov, &mov->tracks[i], MKTAG('c','h','a','p'));
5381 if (!tag)
5382 return AVERROR(ENOMEM);
5383
5384 int ret = mov_add_tref_id(mov, tag, mov->tracks[mov->chapter_track].track_id);
5385 if (ret < 0)
5386 return ret;
5387 }
5388 for (i = 0; i < mov->nb_tracks; i++) {
5389 MOVTrack *track = &mov->tracks[i];
5390 if (track->tag == MKTAG('r','t','p',' ')) {
5391 MovTag *tag = mov_add_tref_tag(mov, track, MKTAG('h','i','n','t'));
5392 if (!tag)
5393 return AVERROR(ENOMEM);
5394
5395 av_assert0(track->nb_src_track);
5396 int ret = mov_add_tref_id(mov, tag, mov->tracks[*track->src_track].track_id);
5397 if (ret < 0)
5398 return ret;
5399 } else if (track->tag == MKTAG('l','v','c','1') && track->nb_src_track) {
5400 MovTag *tag = mov_add_tref_tag(mov, track, MKTAG('s','b','a','s'));
5401 if (!tag)
5402 return AVERROR(ENOMEM);
5403
5404 int ret = mov_add_tref_id(mov, tag, mov->tracks[*track->src_track].track_id);
5405 if (ret < 0)
5406 return ret;
5407 } else {
5408 if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) {
5412 if (sd && sd->size == sizeof(int)) {
5413 int *fallback = (int *)sd->data;
5414 if (*fallback >= 0 && *fallback < mov->nb_tracks) {
5415 MovTag *tag = mov_add_tref_tag(mov, track, MKTAG('f','a','l','l'));
5416 if (!tag)
5417 return AVERROR(ENOMEM);
5418
5419 int ret = mov_add_tref_id(mov, tag, mov->tracks[*fallback].track_id);
5420 if (ret < 0)
5421 return ret;
5422 }
5423 }
5424 }
5425 for (int j = 0; j < track->nb_src_track; j++) {
5426 int src_trk = track->src_track[j];
5427 MovTag *tag = mov_add_tref_tag(mov, &mov->tracks[src_trk], track->tag);
5428 if (!tag)
5429 return AVERROR(ENOMEM);
5430 int ret = mov_add_tref_id(mov, tag, track->track_id);
5431 if (ret < 0)
5432 return ret;
5433 }
5434 if (mov->nb_meta_tmcd && track->nb_src_track) {
5435 /* Derive the duration from the first source track, matching
5436 * the convention used by get_pts_range() and the rtp/lvc1
5437 * branches above. The source may use a different timescale. */
5438 int src_trk = track->src_track[0];
5439 track->track_duration = av_rescale(mov->tracks[src_trk].track_duration,
5440 track->timescale,
5441 mov->tracks[src_trk].timescale);
5442 }
5443 }
5444 }
5445
5446 mov_write_mvhd_tag(pb, mov);
5447 if (mov->mode != MODE_MOV && mov->mode != MODE_AVIF && !mov->iods_skip)
5448 mov_write_iods_tag(pb, mov);
5449 for (i = 0; i < mov->nb_tracks; i++) {
5450 if (mov->tracks[i].entry > 0 || mov->flags & FF_MOV_FLAG_FRAGMENT ||
5451 mov->mode == MODE_AVIF) {
5452 int ret = mov_write_trak_tag(s, pb, mov, &(mov->tracks[i]), i < mov->nb_streams ? mov->tracks[i].st : NULL);
5453 if (ret < 0)
5454 return ret;
5455 }
5456 }
5457 /* Don't write mvex for hybrid_fragmented during mov_write_trailer
5458 * (mov->moov_written != 0)
5459 */
5460 if (mov->flags & FF_MOV_FLAG_FRAGMENT &&
5462 mov_write_mvex_tag(pb, mov); /* QuickTime requires trak to precede this */
5463
5464 if (mov->mode == MODE_PSP)
5466 else if (mov->mode != MODE_AVIF)
5467 mov_write_udta_tag(pb, mov, s);
5468 for (i = 0; i < mov->nb_streams; i++)
5469 mov_write_pssh_tag(pb, mov->tracks[i].st);
5470
5471 return update_size(pb, pos);
5472}
5473
5474static void param_write_int(AVIOContext *pb, const char *name, int value)
5475{
5476 avio_printf(pb, "<param name=\"%s\" value=\"%d\" valuetype=\"data\"/>\n", name, value);
5477}
5478
5479static void param_write_string(AVIOContext *pb, const char *name, const char *value)
5480{
5481 avio_printf(pb, "<param name=\"%s\" value=\"%s\" valuetype=\"data\"/>\n", name, value);
5482}
5483
5484static void param_write_hex(AVIOContext *pb, const char *name, const uint8_t *value, int len)
5485{
5486 char buf[150];
5487 len = FFMIN(sizeof(buf) / 2 - 1, len);
5488 ff_data_to_hex(buf, value, len, 0);
5489 avio_printf(pb, "<param name=\"%s\" value=\"%s\" valuetype=\"data\"/>\n", name, buf);
5490}
5491
5493{
5494 int64_t pos = avio_tell(pb);
5495 int i;
5496
5497 static const AVUUID uuid = {
5498 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
5499 0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
5500 };
5501
5502 avio_wb32(pb, 0);
5503 ffio_wfourcc(pb, "uuid");
5504 avio_write(pb, uuid, AV_UUID_LEN);
5505 avio_wb32(pb, 0);
5506
5507 avio_printf(pb, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
5508 avio_printf(pb, "<smil xmlns=\"http://www.w3.org/2001/SMIL20/Language\">\n");
5509 avio_printf(pb, "<head>\n");
5510 if (!(mov->fc->flags & AVFMT_FLAG_BITEXACT))
5511 avio_printf(pb, "<meta name=\"creator\" content=\"%s\" />\n",
5513 avio_printf(pb, "</head>\n");
5514 avio_printf(pb, "<body>\n");
5515 avio_printf(pb, "<switch>\n");
5516
5517 mov_setup_track_ids(mov, s);
5518
5519 for (i = 0; i < mov->nb_tracks; i++) {
5520 MOVTrack *track = &mov->tracks[i];
5521 struct mpeg4_bit_rate_values bit_rates =
5523 const char *type;
5524 int track_id = track->track_id;
5525 char track_name_buf[32] = { 0 };
5526
5527 AVStream *st = track->st;
5528 AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL,0);
5529
5530 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO && !is_cover_image(st)) {
5531 type = "video";
5532 } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) {
5533 type = "audio";
5534 } else {
5535 continue;
5536 }
5537
5538 avio_printf(pb, "<%s systemBitrate=\"%"PRIu32"\">\n", type,
5539 bit_rates.avg_bit_rate);
5540 param_write_int(pb, "systemBitrate", bit_rates.avg_bit_rate);
5541 param_write_int(pb, "trackID", track_id);
5542 param_write_string(pb, "systemLanguage", lang ? lang->value : "und");
5543
5544 /* Build track name piece by piece: */
5545 /* 1. track type */
5546 av_strlcat(track_name_buf, type, sizeof(track_name_buf));
5547 /* 2. track language, if available */
5548 if (lang)
5549 av_strlcatf(track_name_buf, sizeof(track_name_buf),
5550 "_%s", lang->value);
5551 /* 3. special type suffix */
5552 /* "_cc" = closed captions, "_ad" = audio_description */
5554 av_strlcat(track_name_buf, "_cc", sizeof(track_name_buf));
5556 av_strlcat(track_name_buf, "_ad", sizeof(track_name_buf));
5557
5558 param_write_string(pb, "trackName", track_name_buf);
5559
5560 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
5561 if (track->par->codec_id == AV_CODEC_ID_H264) {
5562 uint8_t *ptr;
5563 int size = track->extradata_size[track->last_stsd_index];
5565 &size)) {
5566 param_write_hex(pb, "CodecPrivateData",
5567 ptr ? ptr : track->extradata[track->last_stsd_index],
5568 size);
5569 av_free(ptr);
5570 }
5571 param_write_string(pb, "FourCC", "H264");
5572 } else if (track->par->codec_id == AV_CODEC_ID_VC1) {
5573 param_write_string(pb, "FourCC", "WVC1");
5574 param_write_hex(pb, "CodecPrivateData", track->extradata[track->last_stsd_index],
5575 track->extradata_size[track->last_stsd_index]);
5576 }
5577 param_write_int(pb, "MaxWidth", track->par->width);
5578 param_write_int(pb, "MaxHeight", track->par->height);
5579 param_write_int(pb, "DisplayWidth", track->par->width);
5580 param_write_int(pb, "DisplayHeight", track->par->height);
5581 } else {
5582 if (track->par->codec_id == AV_CODEC_ID_AAC) {
5583 switch (track->par->profile) {
5585 param_write_string(pb, "FourCC", "AACP");
5586 break;
5587 case AV_PROFILE_AAC_HE:
5588 param_write_string(pb, "FourCC", "AACH");
5589 break;
5590 default:
5591 param_write_string(pb, "FourCC", "AACL");
5592 }
5593 } else if (track->par->codec_id == AV_CODEC_ID_WMAPRO) {
5594 param_write_string(pb, "FourCC", "WMAP");
5595 }
5596 param_write_hex(pb, "CodecPrivateData", track->extradata[track->last_stsd_index],
5597 track->extradata_size[track->last_stsd_index]);
5599 track->par->codec_id));
5600 param_write_int(pb, "Channels", track->par->ch_layout.nb_channels);
5601 param_write_int(pb, "SamplingRate", track->tag == MKTAG('i','a','m','f') ?
5602 0 : track->par->sample_rate);
5603 param_write_int(pb, "BitsPerSample", 16);
5604 param_write_int(pb, "PacketSize", track->par->block_align ?
5605 track->par->block_align : 4);
5606 }
5607 avio_printf(pb, "</%s>\n", type);
5608 }
5609 avio_printf(pb, "</switch>\n");
5610 avio_printf(pb, "</body>\n");
5611 avio_printf(pb, "</smil>\n");
5612
5613 return update_size(pb, pos);
5614}
5615
5617{
5618 avio_wb32(pb, 16);
5619 ffio_wfourcc(pb, "mfhd");
5620 avio_wb32(pb, 0);
5621 avio_wb32(pb, mov->fragments);
5622 return 0;
5623}
5624
5630
5632 MOVTrack *track, int64_t moof_offset)
5633{
5634 int64_t pos = avio_tell(pb);
5637 if (!track->entry) {
5639 } else {
5641 }
5647 }
5648 /* CMAF requires all values to be explicit in tfhd atoms */
5649 if (mov->flags & FF_MOV_FLAG_CMAF)
5651
5652 /* Don't set a default sample size, the silverlight player refuses
5653 * to play files with that set. Don't set a default sample duration,
5654 * WMP freaks out if it is set. Don't set a base data offset, PIFF
5655 * file format says it MUST NOT be set. */
5656 if (track->mode == MODE_ISM)
5659
5660 avio_wb32(pb, 0); /* size placeholder */
5661 ffio_wfourcc(pb, "tfhd");
5662 avio_w8(pb, 0); /* version */
5663 avio_wb24(pb, flags);
5664
5665 avio_wb32(pb, track->track_id); /* track-id */
5667 avio_wb64(pb, moof_offset);
5668 if (flags & MOV_TFHD_STSD_ID) {
5669 avio_wb32(pb, 1);
5670 }
5672 track->default_duration = get_cluster_duration(track, 0);
5673 avio_wb32(pb, track->default_duration);
5674 }
5676 track->default_size = track->entry ? track->cluster[0].size : 1;
5677 avio_wb32(pb, track->default_size);
5678 } else
5679 track->default_size = -1;
5680
5682 /* Set the default flags based on the second sample, if available.
5683 * If the first sample is different, that can be signaled via a separate field. */
5684 if (track->entry > 1)
5685 track->default_sample_flags = get_sample_flags(track, &track->cluster[1]);
5686 else
5687 track->default_sample_flags =
5688 track->par->codec_type == AVMEDIA_TYPE_VIDEO ?
5691 avio_wb32(pb, track->default_sample_flags);
5692 }
5693
5694 return update_size(pb, pos);
5695}
5696
5698 MOVTrack *track, int moof_size,
5699 int first, int end)
5700{
5701 int64_t pos = avio_tell(pb);
5702 uint32_t flags = MOV_TRUN_DATA_OFFSET;
5703 int i;
5704
5705 for (i = first; i < end; i++) {
5706 if (get_cluster_duration(track, i) != track->default_duration)
5708 if (track->cluster[i].size != track->default_size)
5710 if (i > first && get_sample_flags(track, &track->cluster[i]) != track->default_sample_flags)
5712 }
5713 if (!(flags & MOV_TRUN_SAMPLE_FLAGS) && track->entry > first &&
5714 get_sample_flags(track, &track->cluster[first]) != track->default_sample_flags)
5716 if (track->flags & MOV_TRACK_CTTS)
5718
5719 avio_wb32(pb, 0); /* size placeholder */
5720 ffio_wfourcc(pb, "trun");
5722 avio_w8(pb, 1); /* version */
5723 else
5724 avio_w8(pb, 0); /* version */
5725 avio_wb24(pb, flags);
5726
5727 avio_wb32(pb, end - first); /* sample count */
5730 !mov->first_trun)
5731 avio_wb32(pb, 0); /* Later tracks follow immediately after the previous one */
5732 else
5733 avio_wb32(pb, moof_size + 8 + track->data_offset +
5734 track->cluster[first].pos); /* data offset */
5736 avio_wb32(pb, get_sample_flags(track, &track->cluster[first]));
5737
5738 for (i = first; i < end; i++) {
5740 avio_wb32(pb, get_cluster_duration(track, i));
5742 avio_wb32(pb, track->cluster[i].size);
5744 avio_wb32(pb, get_sample_flags(track, &track->cluster[i]));
5746 avio_wb32(pb, track->cluster[i].cts);
5747 }
5748
5749 mov->first_trun = 0;
5750 return update_size(pb, pos);
5751}
5752
5754{
5755 int64_t pos = avio_tell(pb);
5756 static const uint8_t uuid[] = {
5757 0x6d, 0x1d, 0x9b, 0x05, 0x42, 0xd5, 0x44, 0xe6,
5758 0x80, 0xe2, 0x14, 0x1d, 0xaf, 0xf7, 0x57, 0xb2
5759 };
5760
5761 avio_wb32(pb, 0); /* size placeholder */
5762 ffio_wfourcc(pb, "uuid");
5763 avio_write(pb, uuid, AV_UUID_LEN);
5764 avio_w8(pb, 1);
5765 avio_wb24(pb, 0);
5766 avio_wb64(pb, track->cluster[0].dts + track->cluster[0].cts);
5767 avio_wb64(pb, track->end_pts -
5768 (track->cluster[0].dts + track->cluster[0].cts));
5769
5770 return update_size(pb, pos);
5771}
5772
5774 MOVTrack *track, int entry)
5775{
5776 int n = track->nb_frag_info - 1 - entry, i;
5777 int size = 8 + 16 + 4 + 1 + 16*n;
5778 static const uint8_t uuid[] = {
5779 0xd4, 0x80, 0x7e, 0xf2, 0xca, 0x39, 0x46, 0x95,
5780 0x8e, 0x54, 0x26, 0xcb, 0x9e, 0x46, 0xa7, 0x9f
5781 };
5782
5783 if (entry < 0)
5784 return 0;
5785
5786 avio_seek(pb, track->frag_info[entry].tfrf_offset, SEEK_SET);
5787 avio_wb32(pb, size);
5788 ffio_wfourcc(pb, "uuid");
5789 avio_write(pb, uuid, AV_UUID_LEN);
5790 avio_w8(pb, 1);
5791 avio_wb24(pb, 0);
5792 avio_w8(pb, n);
5793 for (i = 0; i < n; i++) {
5794 int index = entry + 1 + i;
5795 avio_wb64(pb, track->frag_info[index].time);
5796 avio_wb64(pb, track->frag_info[index].duration);
5797 }
5798 if (n < mov->ism_lookahead) {
5799 int free_size = 16 * (mov->ism_lookahead - n);
5800 avio_wb32(pb, free_size);
5801 ffio_wfourcc(pb, "free");
5802 ffio_fill(pb, 0, free_size - 8);
5803 }
5804
5805 return 0;
5806}
5807
5809 MOVTrack *track)
5810{
5811 int64_t pos = avio_tell(pb);
5812 int i;
5813 for (i = 0; i < mov->ism_lookahead; i++) {
5814 /* Update the tfrf tag for the last ism_lookahead fragments,
5815 * nb_frag_info - 1 is the next fragment to be written. */
5816 mov_write_tfrf_tag(pb, mov, track, track->nb_frag_info - 2 - i);
5817 }
5818 avio_seek(pb, pos, SEEK_SET);
5819 return 0;
5820}
5821
5822static int mov_add_tfra_entries(AVIOContext *pb, MOVMuxContext *mov, int tracks,
5823 int size)
5824{
5825 int i;
5826 for (i = 0; i < mov->nb_tracks; i++) {
5827 MOVTrack *track = &mov->tracks[i];
5828 MOVFragmentInfo *info;
5829 if ((tracks >= 0 && i != tracks) || !track->entry)
5830 continue;
5831 track->nb_frag_info++;
5832 if (track->nb_frag_info >= track->frag_info_capacity) {
5833 unsigned new_capacity = track->nb_frag_info + MOV_FRAG_INFO_ALLOC_INCREMENT;
5834 if (av_reallocp_array(&track->frag_info,
5835 new_capacity,
5836 sizeof(*track->frag_info)))
5837 return AVERROR(ENOMEM);
5838 track->frag_info_capacity = new_capacity;
5839 }
5840 info = &track->frag_info[track->nb_frag_info - 1];
5841 info->offset = avio_tell(pb);
5842 info->size = size;
5843 // Try to recreate the original pts for the first packet
5844 // from the fields we have stored
5845 info->time = track->cluster[0].dts + track->cluster[0].cts;
5846 info->duration = track->end_pts -
5847 (track->cluster[0].dts + track->cluster[0].cts);
5848 // If the pts is less than zero, we will have trimmed
5849 // away parts of the media track using an edit list,
5850 // and the corresponding start presentation time is zero.
5851 if (info->time < 0) {
5852 info->duration += info->time;
5853 info->time = 0;
5854 }
5855 info->tfrf_offset = 0;
5856 mov_write_tfrf_tags(pb, mov, track);
5857 }
5858 return 0;
5859}
5860
5861static void mov_prune_frag_info(MOVMuxContext *mov, int tracks, int max)
5862{
5863 int i;
5864 for (i = 0; i < mov->nb_tracks; i++) {
5865 MOVTrack *track = &mov->tracks[i];
5866 if ((tracks >= 0 && i != tracks) || !track->entry)
5867 continue;
5868 if (track->nb_frag_info > max) {
5869 memmove(track->frag_info, track->frag_info + (track->nb_frag_info - max), max * sizeof(*track->frag_info));
5870 track->nb_frag_info = max;
5871 }
5872 }
5873}
5874
5876{
5877 int64_t pos = avio_tell(pb);
5878
5879 avio_wb32(pb, 0); /* size */
5880 ffio_wfourcc(pb, "tfdt");
5881 avio_w8(pb, 1); /* version */
5882 avio_wb24(pb, 0);
5883 avio_wb64(pb, track->cluster[0].dts - track->start_dts);
5884 return update_size(pb, pos);
5885}
5886
5888 MOVTrack *track, int64_t moof_offset,
5889 int moof_size)
5890{
5891 int64_t pos = avio_tell(pb);
5892 int i, start = 0;
5893 avio_wb32(pb, 0); /* size placeholder */
5894 ffio_wfourcc(pb, "traf");
5895
5896 mov_write_tfhd_tag(pb, mov, track, moof_offset);
5897 if (mov->mode != MODE_ISM)
5898 mov_write_tfdt_tag(pb, track);
5899 for (i = 1; i < track->entry; i++) {
5900 if (track->cluster[i].pos != track->cluster[i - 1].pos + track->cluster[i - 1].size) {
5901 mov_write_trun_tag(pb, mov, track, moof_size, start, i);
5902 start = i;
5903 }
5904 }
5905 mov_write_trun_tag(pb, mov, track, moof_size, start, track->entry);
5906 if (mov->mode == MODE_ISM) {
5907 mov_write_tfxd_tag(pb, track);
5908
5909 if (mov->ism_lookahead) {
5910 int size = 16 + 4 + 1 + 16 * mov->ism_lookahead;
5911
5912 if (track->nb_frag_info > 0) {
5913 MOVFragmentInfo *info = &track->frag_info[track->nb_frag_info - 1];
5914 if (!info->tfrf_offset)
5915 info->tfrf_offset = avio_tell(pb);
5916 }
5917 avio_wb32(pb, 8 + size);
5918 ffio_wfourcc(pb, "free");
5919 ffio_fill(pb, 0, size);
5920 }
5921 }
5922
5923 if (track->cenc.aes_ctr && (mov->flags & FF_MOV_FLAG_FRAGMENT))
5924 ff_mov_cenc_write_stbl_atoms(&track->cenc, pb, moof_offset);
5925
5926 return update_size(pb, pos);
5927}
5928
5930 int tracks, int moof_size)
5931{
5932 int64_t pos = avio_tell(pb);
5933 int i;
5934
5935 avio_wb32(pb, 0); /* size placeholder */
5936 ffio_wfourcc(pb, "moof");
5937 mov->first_trun = 1;
5938
5939 mov_write_mfhd_tag(pb, mov);
5940 for (i = 0; i < mov->nb_tracks; i++) {
5941 MOVTrack *track = &mov->tracks[i];
5942 if (tracks >= 0 && i != tracks)
5943 continue;
5944 if (!track->entry)
5945 continue;
5946 if (track->cenc.aes_ctr && (mov->flags & FF_MOV_FLAG_FRAGMENT))
5947 mov_write_pssh_tag(pb, track->st);
5948 mov_write_traf_tag(pb, mov, track, pos, moof_size);
5949 }
5950
5951 return update_size(pb, pos);
5952}
5953
5955 MOVTrack *track, int ref_size, int total_sidx_size)
5956{
5957 int64_t pos = avio_tell(pb), offset_pos, end_pos;
5958 int64_t presentation_time, duration, offset;
5959 unsigned starts_with_SAP;
5960 int i, entries;
5961
5962 if (track->entry) {
5963 entries = 1;
5964 presentation_time = track->cluster[0].dts + track->cluster[0].cts;
5965 duration = track->end_pts -
5966 (track->cluster[0].dts + track->cluster[0].cts);
5967 starts_with_SAP = track->cluster[0].flags & MOV_SYNC_SAMPLE;
5968
5969 // pts<0 should be cut away using edts
5970 if (presentation_time < 0) {
5971 duration += presentation_time;
5972 presentation_time = 0;
5973 }
5974 } else {
5975 entries = track->nb_frag_info;
5976 if (entries <= 0)
5977 return 0;
5978 presentation_time = track->frag_info[0].time;
5979 }
5980
5981 avio_wb32(pb, 0); /* size */
5982 ffio_wfourcc(pb, "sidx");
5983 avio_w8(pb, 1); /* version */
5984 avio_wb24(pb, 0);
5985 avio_wb32(pb, track->track_id); /* reference_ID */
5986 avio_wb32(pb, track->timescale); /* timescale */
5987 avio_wb64(pb, presentation_time); /* earliest_presentation_time */
5988 offset_pos = avio_tell(pb);
5989 avio_wb64(pb, 0); /* first_offset (offset to referenced moof) */
5990 avio_wb16(pb, 0); /* reserved */
5991
5992 avio_wb16(pb, entries); /* reference_count */
5993 for (i = 0; i < entries; i++) {
5994 if (!track->entry) {
5995 if (i > 1 && track->frag_info[i].offset != track->frag_info[i - 1].offset + track->frag_info[i - 1].size) {
5996 av_log(NULL, AV_LOG_ERROR, "Non-consecutive fragments, writing incorrect sidx\n");
5997 }
5998 duration = track->frag_info[i].duration;
5999 ref_size = track->frag_info[i].size;
6000 starts_with_SAP = 1;
6001 }
6002 avio_wb32(pb, (0 << 31) | (ref_size & 0x7fffffff)); /* reference_type (0 = media) | referenced_size */
6003 avio_wb32(pb, duration); /* subsegment_duration */
6004 avio_wb32(pb, (starts_with_SAP << 31) | (0 << 28) | 0); /* starts_with_SAP | SAP_type | SAP_delta_time */
6005 }
6006
6007 end_pos = avio_tell(pb);
6008 offset = pos + total_sidx_size - end_pos;
6009 avio_seek(pb, offset_pos, SEEK_SET);
6010 avio_wb64(pb, offset);
6011 avio_seek(pb, end_pos, SEEK_SET);
6012 return update_size(pb, pos);
6013}
6014
6016 int tracks, int ref_size)
6017{
6018 int i, round, ret;
6019 AVIOContext *avio_buf;
6020 int total_size = 0;
6021 for (round = 0; round < 2; round++) {
6022 // First run one round to calculate the total size of all
6023 // sidx atoms.
6024 // This would be much simpler if we'd only write one sidx
6025 // atom, for the first track in the moof.
6026 if (round == 0) {
6027 if ((ret = ffio_open_null_buf(&avio_buf)) < 0)
6028 return ret;
6029 } else {
6030 avio_buf = pb;
6031 }
6032 for (i = 0; i < mov->nb_tracks; i++) {
6033 MOVTrack *track = &mov->tracks[i];
6034 if (tracks >= 0 && i != tracks)
6035 continue;
6036 // When writing a sidx for the full file, entry is 0, but
6037 // we want to include all tracks. ref_size is 0 in this case,
6038 // since we read it from frag_info instead.
6039 if (!track->entry && ref_size > 0)
6040 continue;
6041 total_size -= mov_write_sidx_tag(avio_buf, track, ref_size,
6042 total_size);
6043 }
6044 if (round == 0) {
6045 total_size = ffio_close_null_buf(avio_buf);
6046 if (total_size < 0)
6047 return total_size;
6048 }
6049 }
6050 return 0;
6051}
6052
6053static int mov_write_prft_tag(AVIOContext *pb, MOVMuxContext *mov, int tracks)
6054{
6055 int64_t pos = avio_tell(pb), pts_us, ntp_ts;
6056 MOVTrack *first_track;
6057 int flags = 24;
6058
6059 /* PRFT should be associated with at most one track. So, choosing only the
6060 * first track. */
6061 if (tracks > 0)
6062 return 0;
6063 first_track = &(mov->tracks[0]);
6064
6065 if (!first_track->entry) {
6066 av_log(mov->fc, AV_LOG_WARNING, "Unable to write PRFT, no entries in the track\n");
6067 return 0;
6068 }
6069
6070 if (first_track->cluster[0].pts == AV_NOPTS_VALUE) {
6071 av_log(mov->fc, AV_LOG_WARNING, "Unable to write PRFT, first PTS is invalid\n");
6072 return 0;
6073 }
6074
6075 if (mov->write_prft == MOV_PRFT_SRC_WALLCLOCK) {
6076 if (first_track->cluster[0].prft.wallclock) {
6077 /* Round the NTP time to whole milliseconds. */
6078 ntp_ts = ff_get_formatted_ntp_time((first_track->cluster[0].prft.wallclock / 1000) * 1000 +
6080 flags = first_track->cluster[0].prft.flags;
6081 } else
6083 } else if (mov->write_prft == MOV_PRFT_SRC_PTS) {
6084 pts_us = av_rescale_q(first_track->cluster[0].pts,
6085 first_track->st->time_base, AV_TIME_BASE_Q);
6086 ntp_ts = ff_get_formatted_ntp_time(pts_us + NTP_OFFSET_US);
6087 } else {
6088 av_log(mov->fc, AV_LOG_WARNING, "Unsupported PRFT box configuration: %d\n",
6089 mov->write_prft);
6090 return 0;
6091 }
6092
6093 avio_wb32(pb, 0); // Size place holder
6094 ffio_wfourcc(pb, "prft"); // Type
6095 avio_w8(pb, 1); // Version
6096 avio_wb24(pb, flags); // Flags
6097 avio_wb32(pb, first_track->track_id); // reference track ID
6098 avio_wb64(pb, ntp_ts); // NTP time stamp
6099 avio_wb64(pb, first_track->cluster[0].pts); //media time
6100 return update_size(pb, pos);
6101}
6102
6103static int mov_write_moof_tag(AVIOContext *pb, MOVMuxContext *mov, int tracks,
6104 int64_t mdat_size)
6105{
6106 AVIOContext *avio_buf;
6107 int ret, moof_size;
6108
6109 if ((ret = ffio_open_null_buf(&avio_buf)) < 0)
6110 return ret;
6111 mov_write_moof_tag_internal(avio_buf, mov, tracks, 0);
6112 moof_size = ffio_close_null_buf(avio_buf);
6113 if (moof_size < 0)
6114 return moof_size;
6115
6116 if (mov->flags & FF_MOV_FLAG_DASH &&
6118 mov_write_sidx_tags(pb, mov, tracks, moof_size + 8 + mdat_size);
6119
6120 if (mov->write_prft > MOV_PRFT_NONE && mov->write_prft < MOV_PRFT_NB)
6121 mov_write_prft_tag(pb, mov, tracks);
6122
6123 if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX ||
6124 !(mov->flags & FF_MOV_FLAG_SKIP_TRAILER) ||
6125 mov->ism_lookahead) {
6126 if ((ret = mov_add_tfra_entries(pb, mov, tracks, moof_size + 8 + mdat_size)) < 0)
6127 return ret;
6128 if (!(mov->flags & FF_MOV_FLAG_GLOBAL_SIDX) &&
6130 mov_prune_frag_info(mov, tracks, mov->ism_lookahead + 1);
6131 }
6132 }
6133
6134 return mov_write_moof_tag_internal(pb, mov, tracks, moof_size);
6135}
6136
6138{
6139 int64_t pos = avio_tell(pb);
6140 int i;
6141
6142 avio_wb32(pb, 0); /* size placeholder */
6143 ffio_wfourcc(pb, "tfra");
6144 avio_w8(pb, 1); /* version */
6145 avio_wb24(pb, 0);
6146
6147 avio_wb32(pb, track->track_id);
6148 avio_wb32(pb, 0); /* length of traf/trun/sample num */
6149 avio_wb32(pb, track->nb_frag_info);
6150 for (i = 0; i < track->nb_frag_info; i++) {
6151 avio_wb64(pb, track->frag_info[i].time);
6152 avio_wb64(pb, track->frag_info[i].offset + track->data_offset);
6153 avio_w8(pb, 1); /* traf number */
6154 avio_w8(pb, 1); /* trun number */
6155 avio_w8(pb, 1); /* sample number */
6156 }
6157
6158 return update_size(pb, pos);
6159}
6160
6162{
6163 AVIOContext *mfra_pb;
6164 int i, ret, sz;
6165 uint8_t *buf;
6166
6167 ret = avio_open_dyn_buf(&mfra_pb);
6168 if (ret < 0)
6169 return ret;
6170
6171 avio_wb32(mfra_pb, 0); /* size placeholder */
6172 ffio_wfourcc(mfra_pb, "mfra");
6173 /* An empty mfra atom is enough to indicate to the publishing point that
6174 * the stream has ended. */
6175 if (mov->flags & FF_MOV_FLAG_ISML)
6176 goto done_mfra;
6177
6178 for (i = 0; i < mov->nb_tracks; i++) {
6179 MOVTrack *track = &mov->tracks[i];
6180 if (track->nb_frag_info)
6181 mov_write_tfra_tag(mfra_pb, track);
6182 }
6183
6184 avio_wb32(mfra_pb, 16);
6185 ffio_wfourcc(mfra_pb, "mfro");
6186 avio_wb32(mfra_pb, 0); /* version + flags */
6187 avio_wb32(mfra_pb, avio_tell(mfra_pb) + 4);
6188
6189done_mfra:
6190
6191 sz = update_size(mfra_pb, 0);
6192 ret = avio_get_dyn_buf(mfra_pb, &buf);
6193 avio_write(pb, buf, ret);
6194 ffio_free_dyn_buf(&mfra_pb);
6195
6196 return sz;
6197}
6198
6200{
6201 avio_wb32(pb, 8); // placeholder for extended size field (64 bit)
6202 ffio_wfourcc(pb, mov->mode == MODE_MOV ? "wide" : "free");
6203
6204 mov->mdat_pos = avio_tell(pb);
6205 avio_wb32(pb, 0); /* size placeholder*/
6206 ffio_wfourcc(pb, "mdat");
6207 return 0;
6208}
6209
6211 int has_h264, int has_video, int write_minor)
6212{
6213 MOVMuxContext *mov = s->priv_data;
6214 int minor = 0x200;
6215
6216 if (mov->major_brand && strlen(mov->major_brand) >= 4)
6217 ffio_wfourcc(pb, mov->major_brand);
6218 else if (mov->mode == MODE_3GP) {
6219 ffio_wfourcc(pb, has_h264 ? "3gp6" : "3gp4");
6220 minor = has_h264 ? 0x100 : 0x200;
6221 } else if (mov->mode == MODE_AVIF) {
6222 ffio_wfourcc(pb, mov->is_animated_avif ? "avis" : "avif");
6223 minor = 0;
6224 } else if (mov->mode & MODE_3G2) {
6225 ffio_wfourcc(pb, has_h264 ? "3g2b" : "3g2a");
6226 minor = has_h264 ? 0x20000 : 0x10000;
6227 } else if (mov->mode == MODE_PSP)
6228 ffio_wfourcc(pb, "MSNV");
6229 else if (mov->mode == MODE_MP4 && mov->flags & FF_MOV_FLAG_FRAGMENT &&
6231 ffio_wfourcc(pb, "iso6"); // Required when using signed CTS offsets in trun boxes
6232 else if (mov->mode == MODE_MP4 && mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF)
6233 ffio_wfourcc(pb, "iso5"); // Required when using default-base-is-moof
6234 else if (mov->mode == MODE_MP4 && mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS)
6235 ffio_wfourcc(pb, "iso4");
6236 else if (mov->mode == MODE_MP4)
6237 ffio_wfourcc(pb, "isom");
6238 else if (mov->mode == MODE_IPOD)
6239 ffio_wfourcc(pb, has_video ? "M4V ":"M4A ");
6240 else if (mov->mode == MODE_ISM)
6241 ffio_wfourcc(pb, "isml");
6242 else if (mov->mode == MODE_F4V)
6243 ffio_wfourcc(pb, "f4v ");
6244 else
6245 ffio_wfourcc(pb, "qt ");
6246
6247 if (write_minor)
6248 avio_wb32(pb, minor);
6249}
6250
6252{
6253 MOVMuxContext *mov = s->priv_data;
6254 int64_t pos = avio_tell(pb);
6255 int has_h264 = 0, has_av1 = 0, has_video = 0, has_dolby = 0, has_id3 = 0;
6256 int has_iamf = 0;
6257
6258#if CONFIG_IAMFENC
6259 for (int i = 0; i < s->nb_stream_groups; i++) {
6260 const AVStreamGroup *stg = s->stream_groups[i];
6261
6264 has_iamf = 1;
6265 break;
6266 }
6267 }
6268#endif
6269 for (int i = 0; i < mov->nb_streams; i++) {
6270 AVStream *st = mov->tracks[i].st;
6271 if (is_cover_image(st))
6272 continue;
6274 has_video = 1;
6276 has_h264 = 1;
6277 if (st->codecpar->codec_id == AV_CODEC_ID_AV1)
6278 has_av1 = 1;
6279 if (st->codecpar->codec_id == AV_CODEC_ID_AC3 ||
6285 has_dolby = 1;
6287 has_id3 = 1;
6288 }
6289
6290 avio_wb32(pb, 0); /* size */
6291 ffio_wfourcc(pb, "ftyp");
6292
6293 // Write major brand
6294 mov_write_ftyp_tag_internal(pb, s, has_h264, has_video, 1);
6295 // Write the major brand as the first compatible brand as well
6296 mov_write_ftyp_tag_internal(pb, s, has_h264, has_video, 0);
6297
6298 // Write compatible brands, ensuring that we don't write the major brand as a
6299 // compatible brand a second time.
6300 if (mov->mode == MODE_ISM) {
6301 ffio_wfourcc(pb, "piff");
6302 } else if (mov->mode == MODE_AVIF) {
6303 const AVPixFmtDescriptor *pix_fmt_desc =
6304 av_pix_fmt_desc_get(s->streams[0]->codecpar->format);
6305 const int depth = pix_fmt_desc->comp[0].depth;
6306 if (mov->is_animated_avif) {
6307 // For animated AVIF, major brand is "avis". Add "avif" as a
6308 // compatible brand.
6309 ffio_wfourcc(pb, "avif");
6310 ffio_wfourcc(pb, "msf1");
6311 ffio_wfourcc(pb, "iso8");
6312 }
6313 ffio_wfourcc(pb, "mif1");
6314 ffio_wfourcc(pb, "miaf");
6315 if (depth == 8 || depth == 10) {
6316 // MA1B and MA1A brands are based on AV1 profile. Short hand for
6317 // computing that is based on chroma subsampling type. 420 chroma
6318 // subsampling is MA1B. 444 chroma subsampling is MA1A.
6319 if (!pix_fmt_desc->log2_chroma_w && !pix_fmt_desc->log2_chroma_h) {
6320 // 444 chroma subsampling.
6321 ffio_wfourcc(pb, "MA1A");
6322 } else {
6323 // 420 chroma subsampling.
6324 ffio_wfourcc(pb, "MA1B");
6325 }
6326 }
6327 } else if (mov->mode != MODE_MOV) {
6328 // We add tfdt atoms when fragmenting, signal this with the iso6 compatible
6329 // brand, if not already the major brand. This is compatible with users that
6330 // don't understand tfdt.
6331 if (mov->mode == MODE_MP4) {
6332 if (mov->flags & FF_MOV_FLAG_CMAF)
6333 ffio_wfourcc(pb, "cmfc");
6335 ffio_wfourcc(pb, "iso6");
6336 if (has_av1)
6337 ffio_wfourcc(pb, "av01");
6338 if (has_dolby)
6339 ffio_wfourcc(pb, "dby1");
6340 if (has_iamf)
6341 ffio_wfourcc(pb, "iamf");
6342 } else {
6343 if (mov->flags & FF_MOV_FLAG_FRAGMENT)
6344 ffio_wfourcc(pb, "iso6");
6346 ffio_wfourcc(pb, "iso5");
6348 ffio_wfourcc(pb, "iso4");
6349 }
6350 // Brands prior to iso5 can't be signaled when using default-base-is-moof
6351 if (!(mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF)) {
6352 // write isom for mp4 only if it it's not the major brand already.
6354 ffio_wfourcc(pb, "isom");
6355 ffio_wfourcc(pb, "iso2");
6356 if (has_h264)
6357 ffio_wfourcc(pb, "avc1");
6358 }
6359 }
6360
6361 if (mov->mode == MODE_MP4)
6362 ffio_wfourcc(pb, "mp41");
6363
6365 ffio_wfourcc(pb, "dash");
6366
6367 if (has_id3)
6368 ffio_wfourcc(pb, "aid3");
6369
6370 return update_size(pb, pos);
6371}
6372
6374{
6375 AVStream *video_st = s->streams[0];
6376 AVCodecParameters *video_par = s->streams[0]->codecpar;
6377 AVCodecParameters *audio_par = s->streams[1]->codecpar;
6378 int audio_rate = audio_par->sample_rate;
6379 int64_t frame_rate = video_st->avg_frame_rate.den ?
6380 (video_st->avg_frame_rate.num * 0x10000LL) / video_st->avg_frame_rate.den :
6381 0;
6382 int audio_kbitrate = audio_par->bit_rate / 1000;
6383 int video_kbitrate = FFMIN(video_par->bit_rate / 1000, 800 - audio_kbitrate);
6384
6385 if (frame_rate < 0 || frame_rate > INT32_MAX) {
6386 av_log(s, AV_LOG_ERROR, "Frame rate %f outside supported range\n", frame_rate / (double)0x10000);
6387 return AVERROR(EINVAL);
6388 }
6389
6390 avio_wb32(pb, 0x94); /* size */
6391 ffio_wfourcc(pb, "uuid");
6392 ffio_wfourcc(pb, "PROF");
6393
6394 avio_wb32(pb, 0x21d24fce); /* 96 bit UUID */
6395 avio_wb32(pb, 0xbb88695c);
6396 avio_wb32(pb, 0xfac9c740);
6397
6398 avio_wb32(pb, 0x0); /* ? */
6399 avio_wb32(pb, 0x3); /* 3 sections ? */
6400
6401 avio_wb32(pb, 0x14); /* size */
6402 ffio_wfourcc(pb, "FPRF");
6403 avio_wb32(pb, 0x0); /* ? */
6404 avio_wb32(pb, 0x0); /* ? */
6405 avio_wb32(pb, 0x0); /* ? */
6406
6407 avio_wb32(pb, 0x2c); /* size */
6408 ffio_wfourcc(pb, "APRF"); /* audio */
6409 avio_wb32(pb, 0x0);
6410 avio_wb32(pb, 0x2); /* TrackID */
6411 ffio_wfourcc(pb, "mp4a");
6412 avio_wb32(pb, 0x20f);
6413 avio_wb32(pb, 0x0);
6414 avio_wb32(pb, audio_kbitrate);
6415 avio_wb32(pb, audio_kbitrate);
6416 avio_wb32(pb, audio_rate);
6417 avio_wb32(pb, audio_par->ch_layout.nb_channels);
6418
6419 avio_wb32(pb, 0x34); /* size */
6420 ffio_wfourcc(pb, "VPRF"); /* video */
6421 avio_wb32(pb, 0x0);
6422 avio_wb32(pb, 0x1); /* TrackID */
6423 if (video_par->codec_id == AV_CODEC_ID_H264) {
6424 ffio_wfourcc(pb, "avc1");
6425 avio_wb16(pb, 0x014D);
6426 avio_wb16(pb, 0x0015);
6427 } else {
6428 ffio_wfourcc(pb, "mp4v");
6429 avio_wb16(pb, 0x0000);
6430 avio_wb16(pb, 0x0103);
6431 }
6432 avio_wb32(pb, 0x0);
6433 avio_wb32(pb, video_kbitrate);
6434 avio_wb32(pb, video_kbitrate);
6435 avio_wb32(pb, frame_rate);
6436 avio_wb32(pb, frame_rate);
6437 avio_wb16(pb, video_par->width);
6438 avio_wb16(pb, video_par->height);
6439 avio_wb32(pb, 0x010001); /* ? */
6440
6441 return 0;
6442}
6443
6445{
6446 MOVMuxContext *mov = s->priv_data;
6447 int i;
6448
6450 if (mov->mode == MODE_PSP) {
6451 int video_streams_nb = 0, audio_streams_nb = 0, other_streams_nb = 0;
6452 for (i = 0; i < mov->nb_streams; i++) {
6453 AVStream *st = mov->tracks[i].st;
6454 if (is_cover_image(st))
6455 continue;
6457 video_streams_nb++;
6458 else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
6459 audio_streams_nb++;
6460 else
6461 other_streams_nb++;
6462 }
6463
6464 if (video_streams_nb != 1 || audio_streams_nb != 1 || other_streams_nb) {
6465 av_log(s, AV_LOG_ERROR, "PSP mode need one video and one audio stream\n");
6466 return AVERROR(EINVAL);
6467 }
6468 return mov_write_uuidprof_tag(pb, s);
6469 }
6470 return 0;
6471}
6472
6474{
6475 uint32_t c = -1;
6476 int i, closed_gop = 0;
6477
6478 for (i = 0; i < pkt->size - 4; i++) {
6479 c = (c << 8) + pkt->data[i];
6480 if (c == 0x1b8) { // gop
6481 closed_gop = pkt->data[i + 4] >> 6 & 0x01;
6482 } else if (c == 0x100) { // pic
6483 int temp_ref = (pkt->data[i + 1] << 2) | (pkt->data[i + 2] >> 6);
6484 if (!temp_ref || closed_gop) // I picture is not reordered
6486 else
6488 break;
6489 }
6490 }
6491 return 0;
6492}
6493
6495{
6496 const uint8_t *start, *next, *end = pkt->data + pkt->size;
6497 int seq = 0, entry = 0;
6498 int key = pkt->flags & AV_PKT_FLAG_KEY;
6499 start = find_next_marker(pkt->data, end);
6500 for (next = start; next < end; start = next) {
6501 next = find_next_marker(start + 4, end);
6502 switch (AV_RB32(start)) {
6503 case VC1_CODE_SEQHDR:
6504 seq = 1;
6505 break;
6507 entry = 1;
6508 break;
6509 case VC1_CODE_SLICE:
6510 trk->vc1_info.slices = 1;
6511 break;
6512 }
6513 }
6514 if (!trk->entry && trk->vc1_info.first_packet_seen)
6516 if (!trk->entry && !trk->vc1_info.first_frag_written) {
6517 /* First packet in first fragment */
6518 trk->vc1_info.first_packet_seq = seq;
6520 trk->vc1_info.first_packet_seen = 1;
6521 } else if ((seq && !trk->vc1_info.packet_seq) ||
6522 (entry && !trk->vc1_info.packet_entry)) {
6523 int i;
6524 for (i = 0; i < trk->entry; i++)
6525 trk->cluster[i].flags &= ~MOV_SYNC_SAMPLE;
6526 trk->has_keyframes = 0;
6527 if (seq)
6528 trk->vc1_info.packet_seq = 1;
6529 if (entry)
6530 trk->vc1_info.packet_entry = 1;
6531 if (!trk->vc1_info.first_frag_written) {
6532 /* First fragment */
6533 if ((!seq || trk->vc1_info.first_packet_seq) &&
6534 (!entry || trk->vc1_info.first_packet_entry)) {
6535 /* First packet had the same headers as this one, readd the
6536 * sync sample flag. */
6537 trk->cluster[0].flags |= MOV_SYNC_SAMPLE;
6538 trk->has_keyframes = 1;
6539 }
6540 }
6541 }
6542 if (trk->vc1_info.packet_seq && trk->vc1_info.packet_entry)
6543 key = seq && entry;
6544 else if (trk->vc1_info.packet_seq)
6545 key = seq;
6546 else if (trk->vc1_info.packet_entry)
6547 key = entry;
6548 if (key) {
6549 trk->cluster[trk->entry].flags |= MOV_SYNC_SAMPLE;
6550 trk->has_keyframes++;
6551 }
6552}
6553
6555{
6556 int length;
6557
6558 if (pkt->size < 8)
6559 return;
6560
6561 length = (AV_RB16(pkt->data) & 0xFFF) * 2;
6562 if (length < 8 || length > pkt->size)
6563 return;
6564
6565 if (AV_RB32(pkt->data + 4) == 0xF8726FBA) {
6566 trk->cluster[trk->entry].flags |= MOV_SYNC_SAMPLE;
6567 trk->has_keyframes++;
6568 }
6569
6570 return;
6571}
6572
6574{
6575 MOVMuxContext *mov = s->priv_data;
6576 int ret, buf_size;
6577 uint8_t *buf;
6578 int i, offset;
6579
6580 if (!track->mdat_buf)
6581 return 0;
6582 if (!mov->mdat_buf) {
6583 if ((ret = avio_open_dyn_buf(&mov->mdat_buf)) < 0)
6584 return ret;
6585 }
6586 buf_size = avio_get_dyn_buf(track->mdat_buf, &buf);
6587
6588 offset = avio_tell(mov->mdat_buf);
6589 avio_write(mov->mdat_buf, buf, buf_size);
6591
6592 for (i = track->entries_flushed; i < track->entry; i++)
6593 track->cluster[i].pos += offset;
6594 track->entries_flushed = track->entry;
6595 return 0;
6596}
6597
6599{
6600 MOVMuxContext *mov = s->priv_data;
6601 AVPacket *squashed_packet = mov->pkt;
6602 int ret = AVERROR_BUG;
6603
6604 switch (track->st->codecpar->codec_id) {
6605 case AV_CODEC_ID_TTML: {
6606 int had_packets = !!track->squashed_packet_queue.head;
6607
6608 if ((ret = ff_mov_generate_squashed_ttml_packet(s, track, squashed_packet)) < 0) {
6609 goto finish_squash;
6610 }
6611
6612 // We have generated a padding packet (no actual input packets in
6613 // queue) and its duration is zero. Skipping writing it.
6614 if (!had_packets && squashed_packet->duration == 0) {
6615 goto finish_squash;
6616 }
6617
6618 track->end_reliable = 1;
6619 break;
6620 }
6621 default:
6622 ret = AVERROR(EINVAL);
6623 goto finish_squash;
6624 }
6625
6626 squashed_packet->stream_index = track->st->index;
6627
6628 ret = mov_write_single_packet(s, squashed_packet);
6629
6630finish_squash:
6631 av_packet_unref(squashed_packet);
6632
6633 return ret;
6634}
6635
6637{
6638 MOVMuxContext *mov = s->priv_data;
6639
6640 for (int i = 0; i < mov->nb_streams; i++) {
6641 MOVTrack *track = &mov->tracks[i];
6642 int ret = AVERROR_BUG;
6643
6644 if (track->squash_fragment_samples_to_one && !track->entry) {
6645 if ((ret = mov_write_squashed_packet(s, track)) < 0) {
6647 "Failed to write squashed packet for %s stream with "
6648 "index %d and track id %d. Error: %s\n",
6650 track->st->index, track->track_id,
6651 av_err2str(ret));
6652 return ret;
6653 }
6654 }
6655 }
6656
6657 return 0;
6658}
6659
6661 int64_t ref_pos)
6662{
6663 int i;
6664 if (!track->entry)
6665 return 0;
6667 for (i = 0; i < track->entry; i++)
6668 track->cluster[i].pos += ref_pos + track->data_offset;
6669 if (track->cluster_written == 0) {
6670 // First flush. Chunking for this fragment may already have been
6671 // done, either if we didn't use empty_moov, or if we did use
6672 // delay_moov. In either case, reset chunking here.
6673 for (i = 0; i < track->entry; i++) {
6674 track->cluster[i].chunkNum = 0;
6675 track->cluster[i].samples_in_chunk = track->cluster[i].entries;
6676 }
6677 }
6679 track->entry_written + track->entry,
6680 sizeof(*track->cluster)))
6681 return AVERROR(ENOMEM);
6682 memcpy(&track->cluster_written[track->entry_written],
6683 track->cluster, track->entry * sizeof(*track->cluster));
6684 track->entry_written += track->entry;
6685 }
6686 track->entry = 0;
6687 track->entries_flushed = 0;
6688 track->end_reliable = 0;
6689 return 0;
6690}
6691
6692static int mov_flush_fragment(AVFormatContext *s, int force)
6693{
6694 MOVMuxContext *mov = s->priv_data;
6695 int i, first_track = -1;
6696 int64_t mdat_size = 0, mdat_start = 0;
6697 int ret;
6698 int has_video = 0, starts_with_key = 0, first_video_track = 1;
6699
6700 if (!(mov->flags & FF_MOV_FLAG_FRAGMENT))
6701 return 0;
6702
6703 // Check if we have any tracks that require squashing.
6704 // In that case, we'll have to write the packet here.
6705 if ((ret = mov_write_squashed_packets(s)) < 0)
6706 return ret;
6707
6708 // Try to fill in the duration of the last packet in each stream
6709 // from queued packets in the interleave queues. If the flushing
6710 // of fragments was triggered automatically by an AVPacket, we
6711 // already have reliable info for the end of that track, but other
6712 // tracks may need to be filled in.
6713 for (i = 0; i < mov->nb_streams; i++) {
6714 MOVTrack *track = &mov->tracks[i];
6715 if (!track->end_reliable) {
6716 const AVPacket *pkt = ff_interleaved_peek(s, i);
6717 if (pkt) {
6718 int64_t offset, dts, pts;
6720 pts = pkt->pts + offset;
6721 dts = pkt->dts + offset;
6722 if (track->dts_shift != AV_NOPTS_VALUE)
6723 dts += track->dts_shift;
6724 track->track_duration = dts - track->start_dts;
6725 if (pts != AV_NOPTS_VALUE)
6726 track->end_pts = pts;
6727 else
6728 track->end_pts = dts;
6729 if (!(pkt->flags & AV_PKT_FLAG_DISCARD))
6730 track->elst_end_pts = track->end_pts;
6731 }
6732 }
6733 }
6734
6735 for (i = 0; i < mov->nb_tracks; i++) {
6736 MOVTrack *track = &mov->tracks[i];
6737 if (track->entry <= 1)
6738 continue;
6739 // Sample durations are calculated as the diff of dts values,
6740 // but for the last sample in a fragment, we don't know the dts
6741 // of the first sample in the next fragment, so we have to rely
6742 // on what was set as duration in the AVPacket. Not all callers
6743 // set this though, so we might want to replace it with an
6744 // estimate if it currently is zero.
6745 if (get_cluster_duration(track, track->entry - 1) != 0)
6746 continue;
6747 // Use the duration (i.e. dts diff) of the second last sample for
6748 // the last one. This is a wild guess (and fatal if it turns out
6749 // to be too long), but probably the best we can do - having a zero
6750 // duration is bad as well.
6751 track->track_duration += get_cluster_duration(track, track->entry - 2);
6752 track->end_pts += get_cluster_duration(track, track->entry - 2);
6753 if (!mov->missing_duration_warned) {
6755 "Estimating the duration of the last packet in a "
6756 "fragment, consider setting the duration field in "
6757 "AVPacket instead.\n");
6758 mov->missing_duration_warned = 1;
6759 }
6760 }
6761
6762 if (!mov->moov_written) {
6763 int64_t pos = avio_tell(s->pb);
6764 uint8_t *buf;
6765 int buf_size, moov_size;
6766
6767 for (i = 0; i < mov->nb_tracks; i++)
6768 if (!mov->tracks[i].entry && !is_cover_image(mov->tracks[i].st))
6769 break;
6770 /* Don't write the initial moov unless all tracks have data */
6771 if (i < mov->nb_tracks && !force)
6772 return 0;
6773
6774 moov_size = get_moov_size(s);
6775 for (i = 0; i < mov->nb_tracks; i++)
6776 mov->tracks[i].data_offset = pos + moov_size + 8;
6777
6779 if (mov->flags & FF_MOV_FLAG_DELAY_MOOV &&
6782 if ((ret = mov_write_moov_tag(s->pb, mov, s)) < 0)
6783 return ret;
6784
6785 if (mov->flags & FF_MOV_FLAG_DELAY_MOOV) {
6786 if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX)
6787 mov->reserved_header_pos = avio_tell(s->pb);
6789 mov->moov_written = 1;
6790 return 0;
6791 }
6792
6793 buf_size = avio_get_dyn_buf(mov->mdat_buf, &buf);
6794 avio_wb32(s->pb, buf_size + 8);
6795 ffio_wfourcc(s->pb, "mdat");
6796 avio_write(s->pb, buf, buf_size);
6798
6799 if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX)
6800 mov->reserved_header_pos = avio_tell(s->pb);
6801
6802 mov->moov_written = 1;
6803 mov->mdat_size = 0;
6804 for (i = 0; i < mov->nb_tracks; i++)
6805 mov_finish_fragment(mov, &mov->tracks[i], 0);
6807 return 0;
6808 }
6809
6810 if (mov->frag_interleave) {
6811 for (i = 0; i < mov->nb_tracks; i++) {
6812 MOVTrack *track = &mov->tracks[i];
6813 int ret;
6814 if ((ret = mov_flush_fragment_interleaving(s, track)) < 0)
6815 return ret;
6816 }
6817
6818 if (!mov->mdat_buf)
6819 return 0;
6820 mdat_size = avio_tell(mov->mdat_buf);
6821 }
6822
6823 for (i = 0; i < mov->nb_tracks; i++) {
6824 MOVTrack *track = &mov->tracks[i];
6826 track->data_offset = 0;
6827 else
6828 track->data_offset = mdat_size;
6829 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
6830 has_video = 1;
6831 if (first_video_track) {
6832 if (track->entry)
6833 starts_with_key = track->cluster[0].flags & MOV_SYNC_SAMPLE;
6834 first_video_track = 0;
6835 }
6836 }
6837 if (!track->entry)
6838 continue;
6839 if (track->mdat_buf)
6840 mdat_size += avio_tell(track->mdat_buf);
6841 if (first_track < 0)
6842 first_track = i;
6843 }
6844
6845 if (!mdat_size)
6846 return 0;
6847
6848 avio_write_marker(s->pb,
6849 av_rescale(mov->tracks[first_track].cluster[0].dts, AV_TIME_BASE, mov->tracks[first_track].timescale),
6850 (has_video ? starts_with_key : mov->tracks[first_track].cluster[0].flags & MOV_SYNC_SAMPLE) ? AVIO_DATA_MARKER_SYNC_POINT : AVIO_DATA_MARKER_BOUNDARY_POINT);
6851
6852 for (i = first_track; i < mov->nb_tracks; i++) {
6853 MOVTrack *track = &mov->tracks[i];
6854 int buf_size, write_moof = 1, moof_tracks = -1;
6855 uint8_t *buf;
6856
6857 if (!track->entry)
6858 continue;
6859 if (mov->flags & FF_MOV_FLAG_SEPARATE_MOOF) {
6860 mdat_size = avio_tell(track->mdat_buf);
6861 moof_tracks = i;
6862 } else {
6863 write_moof = i == first_track;
6864 }
6865
6866 if (write_moof) {
6868
6869 mov_write_moof_tag(s->pb, mov, moof_tracks, mdat_size);
6870 mov->fragments++;
6871
6872 if (track->cenc.aes_ctr)
6873 ff_mov_cenc_flush(&track->cenc);
6874
6875 avio_wb32(s->pb, mdat_size + 8);
6876 ffio_wfourcc(s->pb, "mdat");
6877 mdat_start = avio_tell(s->pb);
6878 }
6879
6880 mov_finish_fragment(mov, &mov->tracks[i], mdat_start);
6881 if (!mov->frag_interleave) {
6882 if (!track->mdat_buf)
6883 continue;
6884 buf_size = avio_get_dyn_buf(track->mdat_buf, &buf);
6885 avio_write(s->pb, buf, buf_size);
6887 } else {
6888 if (!mov->mdat_buf)
6889 continue;
6890 buf_size = avio_get_dyn_buf(mov->mdat_buf, &buf);
6891 avio_write(s->pb, buf, buf_size);
6893 }
6894 }
6895
6896 mov->mdat_size = 0;
6897
6899 return 0;
6900}
6901
6903{
6904 MOVMuxContext *mov = s->priv_data;
6905 int had_moov = mov->moov_written;
6906 int ret = mov_flush_fragment(s, force);
6907 if (ret < 0)
6908 return ret;
6909 // If using delay_moov, the first flush only wrote the moov,
6910 // not the actual moof+mdat pair, thus flush once again.
6911 if (!had_moov && mov->flags & FF_MOV_FLAG_DELAY_MOOV)
6912 ret = mov_flush_fragment(s, force);
6913 return ret;
6914}
6915
6917{
6918 int64_t ref;
6919 uint64_t duration;
6920
6921 if (trk->entry) {
6922 ref = trk->cluster[trk->entry - 1].dts;
6923 } else if ( trk->start_dts != AV_NOPTS_VALUE
6924 && !trk->frag_discont) {
6925 ref = trk->start_dts + trk->track_duration;
6926 } else
6927 ref = pkt->dts; // Skip tests for the first packet
6928
6929 if (trk->dts_shift != AV_NOPTS_VALUE) {
6930 /* With negative CTS offsets we have set an offset to the DTS,
6931 * reverse this for the check. */
6932 ref -= trk->dts_shift;
6933 }
6934
6935 duration = pkt->dts - ref;
6936 if (pkt->dts < ref || duration >= INT_MAX) {
6937 av_log(s, AV_LOG_WARNING, "Packet duration: %"PRId64" / dts: %"PRId64" in stream %d is out of range\n",
6938 duration, pkt->dts, pkt->stream_index);
6939
6940 pkt->dts = ref + 1;
6941 pkt->pts = AV_NOPTS_VALUE;
6942 }
6943
6944 if (pkt->duration < 0 || pkt->duration > INT_MAX) {
6945 av_log(s, AV_LOG_ERROR, "Application provided duration: %"PRId64" in stream %d is invalid\n", pkt->duration, pkt->stream_index);
6946 return AVERROR(EINVAL);
6947 }
6948 return 0;
6949}
6950
6952{
6953 MOVMuxContext *mov = s->priv_data;
6954 AVIOContext *pb = s->pb;
6955 MOVTrack *trk;
6956 AVCodecParameters *par;
6958 unsigned int samples_in_chunk = 0;
6960 int size = pkt->size, ret = 0, offset = 0;
6961 size_t prft_size;
6962 uint8_t *reformatted_data = NULL;
6963
6964 if (pkt->stream_index < s->nb_streams)
6965 trk = s->streams[pkt->stream_index]->priv_data;
6966 else // Timecode or chapter
6967 trk = &mov->tracks[pkt->stream_index];
6968 par = trk->par;
6969
6970 ret = check_pkt(s, trk, pkt);
6971 if (ret < 0)
6972 return ret;
6973
6974 if (pkt->pts != AV_NOPTS_VALUE &&
6975 (uint64_t)pkt->dts - pkt->pts != (int32_t)((uint64_t)pkt->dts - pkt->pts)) {
6976 av_log(s, AV_LOG_WARNING, "pts/dts pair unsupported\n");
6977 return AVERROR_PATCHWELCOME;
6978 }
6979
6980 if (mov->flags & FF_MOV_FLAG_FRAGMENT || mov->mode == MODE_AVIF) {
6981 int ret;
6982 if (mov->moov_written || mov->flags & FF_MOV_FLAG_EMPTY_MOOV) {
6983 if (mov->frag_interleave && mov->fragments > 0) {
6984 if (trk->entry - trk->entries_flushed >= mov->frag_interleave) {
6985 if ((ret = mov_flush_fragment_interleaving(s, trk)) < 0)
6986 return ret;
6987 }
6988 }
6989
6990 if (!trk->mdat_buf) {
6991 if ((ret = avio_open_dyn_buf(&trk->mdat_buf)) < 0)
6992 return ret;
6993 }
6994 pb = trk->mdat_buf;
6995 } else {
6996 if (!mov->mdat_buf) {
6997 if ((ret = avio_open_dyn_buf(&mov->mdat_buf)) < 0)
6998 return ret;
6999 }
7000 pb = mov->mdat_buf;
7001 }
7002 }
7003
7004 if (par->codec_id == AV_CODEC_ID_AMR_NB) {
7005 /* We must find out how many AMR blocks there are in one packet */
7006 static const uint16_t packed_size[16] =
7007 {13, 14, 16, 18, 20, 21, 27, 32, 6, 0, 0, 0, 0, 0, 0, 1};
7008 int len = 0;
7009
7010 while (len < size && samples_in_chunk < 100) {
7011 len += packed_size[(pkt->data[len] >> 3) & 0x0F];
7012 samples_in_chunk++;
7013 }
7014 if (samples_in_chunk > 1) {
7015 av_log(s, AV_LOG_ERROR, "fatal error, input is not a single packet, implement a AVParser for it\n");
7016 return -1;
7017 }
7018 } else if (par->codec_id == AV_CODEC_ID_ADPCM_MS ||
7020 samples_in_chunk = trk->par->frame_size;
7021 } else if (trk->sample_size)
7022 samples_in_chunk = size / trk->sample_size;
7023 else
7024 samples_in_chunk = 1;
7025
7026 if (samples_in_chunk < 1) {
7027 av_log(s, AV_LOG_ERROR, "fatal error, input packet contains no samples\n");
7028 return AVERROR_PATCHWELCOME;
7029 }
7030
7031 /* copy extradata if it exists */
7032 if (trk->extradata_size[0] == 0 && par->extradata_size > 0 &&
7033 !TAG_IS_AVCI(trk->tag) &&
7034 (par->codec_id != AV_CODEC_ID_DNXHD)) {
7035 trk->extradata[0] = av_memdup(par->extradata, par->extradata_size);
7036 if (!trk->extradata[0]) {
7037 ret = AVERROR(ENOMEM);
7038 goto err;
7039 }
7040 trk->extradata_size[0] = par->extradata_size;
7041 }
7042
7043 if ((par->codec_id == AV_CODEC_ID_DNXHD ||
7044 par->codec_id == AV_CODEC_ID_H264 ||
7045 par->codec_id == AV_CODEC_ID_HEVC ||
7046 par->codec_id == AV_CODEC_ID_VVC ||
7047 par->codec_id == AV_CODEC_ID_VP9 ||
7048 par->codec_id == AV_CODEC_ID_EVC ||
7049 par->codec_id == AV_CODEC_ID_LCEVC ||
7050 par->codec_id == AV_CODEC_ID_TRUEHD) && !trk->extradata_size[0] &&
7051 !TAG_IS_AVCI(trk->tag)) {
7052 /* copy frame to create needed atoms */
7053 trk->extradata_size[0] = size;
7055 if (!trk->extradata[0]) {
7056 ret = AVERROR(ENOMEM);
7057 goto err;
7058 }
7059 memcpy(trk->extradata[0], pkt->data, size);
7060 memset(trk->extradata[0] + size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
7061 }
7062
7063 const AVPacketSideData *sd = av_packet_side_data_get(pkt->side_data, pkt->side_data_elems, AV_PKT_DATA_NEW_EXTRADATA);
7064 if (pkt->size && sd && sd->size > 0) {
7065 int i;
7066 for (i = 0; i < trk->stsd_count; i++) {
7067 if (trk->extradata_size[i] == sd->size && !memcmp(trk->extradata[i], sd->data, sd->size))
7068 break;
7069 }
7070
7071 if (i < trk->stsd_count)
7072 trk->last_stsd_index = i;
7073 else if (trk->stsd_count <= INT_MAX - 1) {
7074 int new_count = trk->stsd_count + 1;
7075 uint8_t **extradata = av_realloc_array(trk->extradata, new_count, sizeof(*trk->extradata));
7076 if (!extradata)
7077 return AVERROR(ENOMEM);
7078 trk->extradata = extradata;
7079
7080 int *extradata_size = av_realloc_array(trk->extradata_size, new_count, sizeof(*trk->extradata_size));
7081 if (!extradata_size)
7082 return AVERROR(ENOMEM);
7083 trk->extradata_size = extradata_size;
7084
7085 trk->extradata[trk->stsd_count] = av_memdup(sd->data, sd->size);
7086 if (!trk->extradata[trk->stsd_count])
7087 return AVERROR(ENOMEM);
7088
7089 trk->extradata_size[trk->stsd_count] = sd->size;
7090 trk->last_stsd_index = trk->stsd_count;
7091 trk->stsd_count = new_count;
7092 } else
7093 return AVERROR(ENOMEM);
7094 }
7095
7096 if (par->codec_id == AV_CODEC_ID_AAC && pkt->size > 2 &&
7097 (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) {
7098 if (!trk->st->nb_frames) {
7099 av_log(s, AV_LOG_ERROR, "Malformed AAC bitstream detected: "
7100 "use the audio bitstream filter 'aac_adtstoasc' to fix it "
7101 "('-bsf:a aac_adtstoasc' option with ffmpeg)\n");
7102 return -1;
7103 }
7104 av_log(s, AV_LOG_WARNING, "aac bitstream error\n");
7105 }
7106 if (par->codec_id == AV_CODEC_ID_H264 && trk->extradata_size[trk->last_stsd_index] > 0 &&
7107 *(uint8_t *)trk->extradata[trk->last_stsd_index] != 1 && !TAG_IS_AVCI(trk->tag)) {
7108 /* from x264 or from bytestream H.264 */
7109 /* NAL reformatting needed */
7110 if (trk->hint_track >= 0 && trk->hint_track < mov->nb_tracks) {
7111 ret = ff_nal_parse_units_buf(pkt->data, &reformatted_data,
7112 &size);
7113 if (ret < 0)
7114 return ret;
7115 avio_write(pb, reformatted_data, size);
7116 } else {
7117 if (trk->cenc.aes_ctr) {
7118 size = ff_mov_cenc_avc_parse_nal_units(&trk->cenc, pb, pkt->data, size);
7119 if (size < 0) {
7120 ret = size;
7121 goto err;
7122 }
7123 } else {
7124 size = ff_nal_parse_units(pb, pkt->data, pkt->size);
7125 }
7126 }
7127 } else if (par->codec_id == AV_CODEC_ID_HEVC && trk->extradata_size[trk->last_stsd_index] > 6 &&
7128 (AV_RB24(trk->extradata[trk->last_stsd_index]) == 1 || AV_RB32(trk->extradata[trk->last_stsd_index]) == 1)) {
7129 /* extradata is Annex B, assume the bitstream is too and convert it */
7130 int filter_ps = (trk->tag == MKTAG('h','v','c','1'));
7131 if (trk->hint_track >= 0 && trk->hint_track < mov->nb_tracks) {
7132 ret = ff_hevc_annexb2mp4_buf(pkt->data, &reformatted_data,
7133 &size, filter_ps, NULL);
7134 if (ret < 0)
7135 return ret;
7136 avio_write(pb, reformatted_data, size);
7137 } else {
7138 if (trk->cenc.aes_ctr) {
7139 size = ff_mov_cenc_avc_parse_nal_units(&trk->cenc, pb, pkt->data, size);
7140 if (size < 0) {
7141 ret = size;
7142 goto err;
7143 }
7144 } else {
7145 size = ff_hevc_annexb2mp4(pb, pkt->data, pkt->size, filter_ps, NULL);
7146 }
7147 }
7148 } else if (par->codec_id == AV_CODEC_ID_VVC && trk->extradata_size[trk->last_stsd_index] > 6 &&
7149 (AV_RB24(trk->extradata[trk->last_stsd_index]) == 1 || AV_RB32(trk->extradata[trk->last_stsd_index]) == 1)) {
7150 /* extradata is Annex B, assume the bitstream is too and convert it */
7151 if (trk->hint_track >= 0 && trk->hint_track < mov->nb_tracks) {
7152 ret = ff_vvc_annexb2mp4_buf(pkt->data, &reformatted_data,
7153 &size, 0, NULL);
7154 if (ret < 0)
7155 return ret;
7156 avio_write(pb, reformatted_data, size);
7157 } else {
7158 size = ff_vvc_annexb2mp4(pb, pkt->data, pkt->size, 0, NULL);
7159 }
7160 } else if (par->codec_id == AV_CODEC_ID_LCEVC && trk->extradata_size[trk->last_stsd_index] > 0 &&
7161 *(uint8_t *)trk->extradata[trk->last_stsd_index] != 1) {
7162 /* extradata is Annex B, assume the bitstream is too and convert it */
7163 if (trk->hint_track >= 0 && trk->hint_track < mov->nb_tracks) {
7164 ret = ff_nal_parse_units_buf(pkt->data, &reformatted_data, &size);
7165 if (ret < 0)
7166 return ret;
7167 avio_write(pb, reformatted_data, size);
7168 } else {
7169 if (trk->cenc.aes_ctr) {
7170 size = ff_mov_cenc_avc_parse_nal_units(&trk->cenc, pb, pkt->data, size);
7171 if (size < 0) {
7172 ret = size;
7173 goto err;
7174 }
7175 } else {
7176 size = ff_nal_parse_units(pb, pkt->data, pkt->size);
7177 }
7178 }
7179 } else if (par->codec_id == AV_CODEC_ID_AV1 && !trk->cenc.aes_ctr) {
7180 if (trk->hint_track >= 0 && trk->hint_track < mov->nb_tracks) {
7181 ret = ff_av1_filter_obus_buf(pkt->data, &reformatted_data,
7182 &size, &offset);
7183 if (ret < 0)
7184 return ret;
7185 avio_write(pb, reformatted_data, size);
7186 } else {
7187 size = ff_av1_filter_obus(pb, pkt->data, pkt->size);
7188 if (trk->mode == MODE_AVIF && !mov->avif_extent_length[pkt->stream_index]) {
7189 mov->avif_extent_length[pkt->stream_index] = size;
7190 }
7191 }
7192
7193 } else if (par->codec_id == AV_CODEC_ID_AC3 ||
7194 par->codec_id == AV_CODEC_ID_EAC3) {
7195 size = handle_eac3(mov, pkt, trk);
7196 if (size < 0)
7197 return size;
7198 else if (!size)
7199 goto end;
7200 avio_write(pb, pkt->data, size);
7201 } else if (par->codec_id == AV_CODEC_ID_EIA_608) {
7202 size = 8;
7203
7204 for (int i = 0; i < pkt->size; i += 3) {
7205 if (pkt->data[i] == 0xFC) {
7206 size += 2;
7207 }
7208 }
7209 avio_wb32(pb, size);
7210 ffio_wfourcc(pb, "cdat");
7211 for (int i = 0; i < pkt->size; i += 3) {
7212 if (pkt->data[i] == 0xFC) {
7213 avio_w8(pb, pkt->data[i + 1]);
7214 avio_w8(pb, pkt->data[i + 2]);
7215 }
7216 }
7217 } else if (par->codec_id == AV_CODEC_ID_APV) {
7218 ff_isom_parse_apvc(trk->apv, pkt, s);
7219 avio_wb32(s->pb, pkt->size);
7220 size += 4;
7221
7222 avio_write(s->pb, pkt->data, pkt->size);
7223 } else {
7224 if (trk->cenc.aes_ctr) {
7225 uint8_t *extradata = trk->extradata[trk->last_stsd_index];
7226 int extradata_size = trk->extradata_size[trk->last_stsd_index];
7227 if (par->codec_id == AV_CODEC_ID_H264 && extradata_size > 4) {
7228 int nal_size_length = (extradata[4] & 0x3) + 1;
7229 ret = ff_mov_cenc_avc_write_nal_units(s, &trk->cenc, nal_size_length, pb, pkt->data, size);
7230 } else if(par->codec_id == AV_CODEC_ID_HEVC && extradata_size > 21) {
7231 int nal_size_length = (extradata[21] & 0x3) + 1;
7232 ret = ff_mov_cenc_avc_write_nal_units(s, &trk->cenc, nal_size_length, pb, pkt->data, size);
7233 } else if(par->codec_id == AV_CODEC_ID_VVC) {
7235 } else if(par->codec_id == AV_CODEC_ID_AV1) {
7236 av_assert0(size == pkt->size);
7237 ret = ff_mov_cenc_av1_write_obus(s, &trk->cenc, pb, pkt);
7238 if (ret > 0) {
7239 size = ret;
7240 ret = 0;
7241 }
7242 } else {
7243 ret = ff_mov_cenc_write_packet(&trk->cenc, pb, pkt->data, size);
7244 }
7245
7246 if (ret) {
7247 goto err;
7248 }
7249 } else {
7250 avio_write(pb, pkt->data, size);
7251 }
7252 }
7253
7254 if (trk->entry >= trk->cluster_capacity) {
7255 unsigned new_capacity = trk->entry + MOV_INDEX_CLUSTER_SIZE;
7256 void *cluster = av_realloc_array(trk->cluster, new_capacity, sizeof(*trk->cluster));
7257 if (!cluster) {
7258 ret = AVERROR(ENOMEM);
7259 goto err;
7260 }
7261 trk->cluster = cluster;
7262 trk->cluster_capacity = new_capacity;
7263 }
7264
7265 trk->cluster[trk->entry].pos = avio_tell(pb) - size;
7266 trk->cluster[trk->entry].stsd_index = trk->last_stsd_index;
7267 trk->cluster[trk->entry].samples_in_chunk = samples_in_chunk;
7268 trk->cluster[trk->entry].chunkNum = 0;
7269 trk->cluster[trk->entry].size = size;
7270 trk->cluster[trk->entry].entries = samples_in_chunk;
7271 trk->cluster[trk->entry].dts = pkt->dts;
7272 trk->cluster[trk->entry].pts = pkt->pts;
7274 !trk->entry && trk->start_dts != AV_NOPTS_VALUE) {
7275 if (!trk->frag_discont) {
7276 /* First packet of a new fragment. We already wrote the duration
7277 * of the last packet of the previous fragment based on track_duration,
7278 * which might not exactly match our dts. Therefore adjust the dts
7279 * of this packet to be what the previous packets duration implies. */
7280 trk->cluster[trk->entry].dts = trk->start_dts + trk->track_duration;
7281 /* We also may have written the pts and the corresponding duration
7282 * in sidx/tfrf/tfxd tags; make sure the sidx pts and duration match up with
7283 * the next fragment. This means the cts of the first sample must
7284 * be the same in all fragments, unless end_pts was updated by
7285 * the packet causing the fragment to be written. */
7286 if ((mov->flags & FF_MOV_FLAG_DASH &&
7288 mov->mode == MODE_ISM)
7289 pkt->pts = pkt->dts + trk->end_pts - trk->cluster[trk->entry].dts;
7290 } else {
7291 /* New fragment, but discontinuous from previous fragments.
7292 * Pretend the duration sum of the earlier fragments is
7293 * pkt->dts - trk->start_dts. */
7294 trk->end_pts = trk->elst_end_pts = AV_NOPTS_VALUE;
7295 trk->frag_discont = 0;
7296 }
7297 }
7298
7299 if (!trk->entry && trk->start_dts == AV_NOPTS_VALUE && !mov->use_editlist &&
7300 s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO) {
7301 /* Not using edit lists and shifting the first track to start from zero.
7302 * If the other streams start from a later timestamp, we won't be able
7303 * to signal the difference in starting time without an edit list.
7304 * Thus move the timestamp for this first sample to 0, increasing
7305 * its duration instead. */
7306 trk->cluster[trk->entry].dts = trk->start_dts = 0;
7307 }
7308 if (trk->start_dts == AV_NOPTS_VALUE) {
7309 trk->start_dts = pkt->dts;
7310 if (trk->frag_discont) {
7311 if (mov->use_editlist) {
7312 /* Pretend the whole stream started at pts=0, with earlier fragments
7313 * already written. If the stream started at pts=0, the duration sum
7314 * of earlier fragments would have been pkt->pts. */
7315 trk->start_dts = pkt->dts - pkt->pts;
7316 } else {
7317 /* Pretend the whole stream started at dts=0, with earlier fragments
7318 * already written, with a duration summing up to pkt->dts. */
7319 trk->start_dts = 0;
7320 }
7321 trk->frag_discont = 0;
7322 } else if (pkt->dts && mov->moov_written)
7324 "Track %d starts with a nonzero dts %"PRId64", while the moov "
7325 "already has been written. Set the delay_moov flag to handle "
7326 "this case.\n",
7327 pkt->stream_index, pkt->dts);
7328 }
7329
7330 sd = av_packet_side_data_get(pkt->side_data, pkt->side_data_elems, AV_PKT_DATA_SKIP_SAMPLES);
7331 if (sd && sd->size >= 10 && trk->par->frame_size) {
7332 duration = FFMAX(av_rescale_q(trk->par->frame_size, (AVRational){ 1, trk->par->sample_rate },
7333 trk->st->time_base), pkt->duration);
7334 if (mov->use_editlist)
7335 pkt->duration = duration;
7336 duration -= av_rescale_q(AV_RL32(sd->data + 4), (AVRational){ 1, trk->par->sample_rate },
7337 trk->st->time_base);
7338 if (duration < 0)
7339 return AVERROR_INVALIDDATA;
7340 } else
7341 duration = pkt->duration;
7342
7343 trk->track_duration = pkt->dts - trk->start_dts + pkt->duration;
7345
7346 if (pkt->pts == AV_NOPTS_VALUE) {
7347 av_log(s, AV_LOG_WARNING, "pts has no value\n");
7348 pkt->pts = pkt->dts;
7349 }
7350 if (pkt->dts != pkt->pts)
7351 trk->flags |= MOV_TRACK_CTTS;
7352 trk->cluster[trk->entry].cts = pkt->pts - pkt->dts;
7353 trk->cluster[trk->entry].flags = 0;
7354 if (trk->start_cts == AV_NOPTS_VALUE || (pkt->dts <= 0 && trk->start_cts > pkt->pts - pkt->dts))
7355 trk->start_cts = pkt->pts - pkt->dts;
7356 if (trk->end_pts == AV_NOPTS_VALUE)
7357 trk->end_pts = trk->cluster[trk->entry].dts +
7358 trk->cluster[trk->entry].cts + duration;
7359 else
7360 trk->end_pts = FFMAX(trk->end_pts, trk->cluster[trk->entry].dts +
7361 trk->cluster[trk->entry].cts +
7362 duration);
7363 if (!(pkt->flags & AV_PKT_FLAG_DISCARD))
7364 trk->elst_end_pts = trk->end_pts;
7365
7366 if (par->codec_id == AV_CODEC_ID_VC1) {
7368 } else if (par->codec_id == AV_CODEC_ID_TRUEHD) {
7370 } else if (pkt->flags & AV_PKT_FLAG_KEY) {
7371 if (mov->mode == MODE_MOV && par->codec_id == AV_CODEC_ID_MPEG2VIDEO &&
7372 trk->entry > 0) { // force sync sample for the first key frame
7374 if (trk->cluster[trk->entry].flags & MOV_PARTIAL_SYNC_SAMPLE)
7375 trk->flags |= MOV_TRACK_STPS;
7376 } else {
7377 trk->cluster[trk->entry].flags = MOV_SYNC_SAMPLE;
7378 }
7379 if (trk->cluster[trk->entry].flags & MOV_SYNC_SAMPLE)
7380 trk->has_keyframes++;
7381 }
7382 if (pkt->flags & AV_PKT_FLAG_DISPOSABLE) {
7384 trk->has_disposable++;
7385 }
7386
7388 if (prft && prft_size == sizeof(AVProducerReferenceTime))
7389 memcpy(&trk->cluster[trk->entry].prft, prft, prft_size);
7390 else
7391 memset(&trk->cluster[trk->entry].prft, 0, sizeof(AVProducerReferenceTime));
7392
7393 trk->entry++;
7394 trk->sample_count += samples_in_chunk;
7395 mov->mdat_size += size;
7396
7397 if (trk->hint_track >= 0 && trk->hint_track < mov->nb_tracks)
7399 reformatted_data ? reformatted_data + offset
7400 : NULL, size);
7401
7402end:
7403err:
7404
7405 if (pkt->data != reformatted_data)
7406 av_free(reformatted_data);
7407 return ret;
7408}
7409
7411{
7412 MOVMuxContext *mov = s->priv_data;
7413 MOVTrack *trk = s->streams[pkt->stream_index]->priv_data;
7414 AVCodecParameters *par = trk->par;
7415 int64_t frag_duration = 0;
7416 int size = pkt->size;
7417
7418 int ret = check_pkt(s, trk, pkt);
7419 if (ret < 0)
7420 return ret;
7421
7422 if (mov->flags & FF_MOV_FLAG_FRAG_DISCONT) {
7423 for (int i = 0; i < mov->nb_streams; i++)
7424 mov->tracks[i].frag_discont = 1;
7426 }
7427
7429 if (trk->dts_shift == AV_NOPTS_VALUE)
7430 trk->dts_shift = pkt->pts - pkt->dts;
7431 pkt->dts += trk->dts_shift;
7432 }
7433
7434 if (trk->par->codec_id == AV_CODEC_ID_MP4ALS ||
7435 trk->par->codec_id == AV_CODEC_ID_AAC ||
7436 trk->par->codec_id == AV_CODEC_ID_AV1 ||
7437 trk->par->codec_id == AV_CODEC_ID_FLAC) {
7438 size_t side_size;
7439 uint8_t *side = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size);
7440 /* Overwrite extradata only on flush packets or when no extradata was available during init */
7441 if (side_size > 0 && (!pkt->size || !trk->extradata_size[trk->last_stsd_index])) {
7442 void *newextra = av_malloc(side_size + AV_INPUT_BUFFER_PADDING_SIZE);
7443 if (!newextra)
7444 return AVERROR(ENOMEM);
7445 memset((uint8_t*)newextra + side_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
7446 memcpy(newextra, side, side_size);
7447 av_free(trk->extradata[trk->last_stsd_index]);
7448 trk->extradata[trk->last_stsd_index] = newextra;
7449 trk->extradata_size[trk->last_stsd_index] = side_size;
7450 }
7451 }
7452
7453 if (!pkt->size) {
7454 if (trk->start_dts == AV_NOPTS_VALUE && trk->frag_discont) {
7455 trk->start_dts = pkt->dts;
7456 if (pkt->pts != AV_NOPTS_VALUE)
7457 trk->start_cts = pkt->pts - pkt->dts;
7458 else
7459 trk->start_cts = 0;
7460 }
7461
7462 return 0; /* Discard 0 sized packets */
7463 }
7464
7465 if (trk->entry && pkt->stream_index < mov->nb_streams)
7466 frag_duration = av_rescale_q(pkt->dts - trk->cluster[0].dts,
7467 s->streams[pkt->stream_index]->time_base,
7469 if ((mov->max_fragment_duration &&
7470 frag_duration >= mov->max_fragment_duration) ||
7471 (mov->max_fragment_size && mov->mdat_size + size >= mov->max_fragment_size) ||
7474 trk->entry && pkt->flags & AV_PKT_FLAG_KEY) ||
7476 if (frag_duration >= mov->min_fragment_duration) {
7477 if (trk->entry) {
7478 // Set the duration of this track to line up with the next
7479 // sample in this track. This avoids relying on AVPacket
7480 // duration, but only helps for this particular track, not
7481 // for the other ones that are flushed at the same time.
7482 //
7483 // If we have trk->entry == 0, no fragment will be written
7484 // for this track, and we can't adjust the track end here.
7485 trk->track_duration = pkt->dts - trk->start_dts;
7486 if (pkt->pts != AV_NOPTS_VALUE)
7487 trk->end_pts = pkt->pts;
7488 else
7489 trk->end_pts = pkt->dts;
7490 if (!(pkt->flags & AV_PKT_FLAG_DISCARD))
7491 trk->elst_end_pts = trk->end_pts;
7492 trk->end_reliable = 1;
7493 }
7495 }
7496 }
7497
7498 return ff_mov_write_packet(s, pkt);
7499}
7500
7502 int stream_index,
7503 int64_t dts) {
7504 MOVMuxContext *mov = s->priv_data;
7505 AVPacket *end = mov->pkt;
7506 uint8_t data[2] = {0};
7507 int ret;
7508
7509 end->size = sizeof(data);
7510 end->data = data;
7511 end->pts = dts;
7512 end->dts = dts;
7513 end->duration = 0;
7514 end->stream_index = stream_index;
7515
7516 ret = mov_write_single_packet(s, end);
7517 av_packet_unref(end);
7518
7519 return ret;
7520}
7521
7522#if CONFIG_IAMFENC
7523static int mov_build_iamf_packet(AVFormatContext *s, MOVTrack *trk, AVPacket *pkt)
7524{
7525 uint8_t *data;
7526 int ret;
7527
7528 if (pkt->stream_index == trk->first_iamf_idx) {
7529 ret = ff_iamf_write_parameter_blocks(trk->iamf, trk->iamf_buf, pkt, s);
7530 if (ret < 0)
7531 return ret;
7532 }
7533
7534 ret = ff_iamf_write_audio_frame(trk->iamf, trk->iamf_buf,
7535 s->streams[pkt->stream_index]->id, pkt);
7536 if (ret < 0)
7537 return ret;
7538
7539 if (pkt->stream_index != trk->last_iamf_idx)
7540 return AVERROR(EAGAIN);
7541
7542 ret = avio_close_dyn_buf(trk->iamf_buf, &data);
7543 trk->iamf_buf = NULL;
7544 if (!ret) {
7545 if (pkt->size) {
7546 // Either all or none of the packets for a single
7547 // IA Sample may be empty.
7548 av_log(s, AV_LOG_ERROR, "Unexpected packet from "
7549 "stream #%d\n", pkt->stream_index);
7550 ret = AVERROR_INVALIDDATA;
7551 }
7552 av_free(data);
7553 return ret;
7554 }
7555
7556 av_buffer_unref(&pkt->buf);
7557 pkt->buf = av_buffer_create(data, ret, NULL, NULL, 0);
7558 if (!pkt->buf) {
7559 av_free(data);
7560 return AVERROR(ENOMEM);
7561 }
7562 pkt->data = data;
7563 pkt->size = ret;
7564 pkt->stream_index = trk->first_iamf_idx;
7565
7566 return avio_open_dyn_buf(&trk->iamf_buf);
7567}
7568#endif
7569
7571{
7572 int64_t pos = avio_tell(pb);
7573 const char *scheme_id_uri = "https://aomedia.org/emsg/ID3";
7574 const char *value = "";
7575
7576 av_assert0(st->time_base.num == 1);
7577
7581
7582 avio_wb32(pb, 0); /* size */
7583 ffio_wfourcc(pb, "emsg");
7584 avio_w8(pb, 1); /* version */
7585 avio_wb24(pb, 0);
7586 avio_wb32(pb, st->time_base.den); /* timescale */
7587 avio_wb64(pb, pkt->pts); /* presentation_time */
7588 avio_wb32(pb, 0xFFFFFFFFU); /* event_duration */
7589 avio_wb32(pb, 0); /* id */
7590 /* null terminated UTF8 strings */
7591 avio_write(pb, scheme_id_uri, strlen(scheme_id_uri) + 1);
7592 avio_write(pb, value, strlen(value) + 1);
7593 avio_write(pb, pkt->data, pkt->size);
7594
7595 return update_size(pb, pos);
7596}
7597
7599{
7600 MOVMuxContext *mov = s->priv_data;
7601 MOVTrack *trk;
7602
7603 if (!pkt) {
7605 return 1;
7606 }
7607
7608 if (s->streams[pkt->stream_index]->codecpar->codec_id == AV_CODEC_ID_TIMED_ID3) {
7609 mov_write_emsg_tag(s->pb, s->streams[pkt->stream_index], pkt);
7610 return 0;
7611 }
7612
7613 trk = s->streams[pkt->stream_index]->priv_data;
7614
7615#if CONFIG_IAMFENC
7616 if (trk->iamf) {
7617 int ret = mov_build_iamf_packet(s, trk, pkt);
7618 if (ret < 0) {
7619 if (ret == AVERROR(EAGAIN))
7620 return 0;
7621 av_log(s, AV_LOG_ERROR, "Error assembling an IAMF packet "
7622 "for stream #%d\n", trk->st->index);
7623 return ret;
7624 }
7625 }
7626#endif
7627
7628 if (is_cover_image(trk->st)) {
7629 int ret;
7630
7631 if (trk->st->nb_frames >= 1) {
7632 if (trk->st->nb_frames == 1)
7633 av_log(s, AV_LOG_WARNING, "Got more than one picture in stream %d,"
7634 " ignoring.\n", pkt->stream_index);
7635 return 0;
7636 }
7637
7638 if ((ret = av_packet_ref(trk->cover_image, pkt)) < 0)
7639 return ret;
7640
7641 return 0;
7642 } else {
7643 int i;
7644
7645 if (!pkt->size)
7646 return mov_write_single_packet(s, pkt); /* Passthrough. */
7647
7648 /*
7649 * Subtitles require special handling.
7650 *
7651 * 1) For full compliance, every track must have a sample at
7652 * dts == 0, which is rarely true for subtitles. So, as soon
7653 * as we see any packet with dts > 0, write an empty subtitle
7654 * at dts == 0 for any subtitle track with no samples in it.
7655 *
7656 * 2) For each subtitle track, check if the current packet's
7657 * dts is past the duration of the last subtitle sample. If
7658 * so, we now need to write an end sample for that subtitle.
7659 *
7660 * This must be done conditionally to allow for subtitles that
7661 * immediately replace each other, in which case an end sample
7662 * is not needed, and is, in fact, actively harmful.
7663 *
7664 * 3) See mov_write_trailer for how the final end sample is
7665 * handled.
7666 */
7667 for (i = 0; i < mov->nb_tracks; i++) {
7668 MOVTrack *trk = &mov->tracks[i];
7669 int ret;
7670
7671 if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT &&
7672 trk->track_duration < pkt->dts &&
7673 (trk->entry == 0 || !trk->last_sample_is_subtitle_end)) {
7675 if (ret < 0) return ret;
7677 }
7678 }
7679
7681 /*
7682 * If the track has to have its samples squashed into one sample,
7683 * we just take it into the track's queue.
7684 * This will then be utilized as the samples get written in either
7685 * mov_flush_fragment or when the mux is finalized in
7686 * mov_write_trailer.
7687 */
7688 int ret = AVERROR_BUG;
7689
7690 if (pkt->pts == AV_NOPTS_VALUE) {
7692 "Packets without a valid presentation timestamp are "
7693 "not supported with packet squashing!\n");
7694 return AVERROR(EINVAL);
7695 }
7696
7697 /* The following will reset pkt and is only allowed to be used
7698 * because we return immediately. afterwards. */
7700 pkt, NULL, 0)) < 0) {
7701 return ret;
7702 }
7703
7704 return 0;
7705 }
7706
7707
7708 if (trk->mode == MODE_MOV && trk->par->codec_type == AVMEDIA_TYPE_VIDEO) {
7709 AVPacket *opkt = pkt;
7710 int reshuffle_ret, ret;
7711 if (trk->is_unaligned_qt_rgb) {
7712 int64_t bpc = trk->par->bits_per_coded_sample != 15 ? trk->par->bits_per_coded_sample : 16;
7713 int expected_stride = ((trk->par->width * bpc + 15) >> 4)*2;
7714 reshuffle_ret = ff_reshuffle_raw_rgb(s, &pkt, trk->par, expected_stride);
7715 if (reshuffle_ret < 0)
7716 return reshuffle_ret;
7717 } else
7718 reshuffle_ret = 0;
7719 if (trk->par->format == AV_PIX_FMT_PAL8 && !trk->pal_done) {
7720 ret = ff_get_packet_palette(s, opkt, reshuffle_ret, trk->palette);
7721 if (ret < 0)
7722 goto fail;
7723 if (ret)
7724 trk->pal_done++;
7725 } else if (trk->par->codec_id == AV_CODEC_ID_RAWVIDEO &&
7726 (trk->par->format == AV_PIX_FMT_GRAY8 ||
7727 trk->par->format == AV_PIX_FMT_MONOBLACK)) {
7729 if (ret < 0)
7730 goto fail;
7731 for (i = 0; i < pkt->size; i++)
7732 pkt->data[i] = ~pkt->data[i];
7733 }
7734 if (reshuffle_ret) {
7736fail:
7737 if (reshuffle_ret)
7739 return ret;
7740 }
7741 }
7742
7743 return mov_write_single_packet(s, pkt);
7744 }
7745}
7746
7747// QuickTime chapters involve an additional text track with the chapter names
7748// as samples, and a tref pointing from the other tracks to the chapter one.
7750{
7751 static const uint8_t stub_header[] = {
7752 // TextSampleEntry
7753 0x00, 0x00, 0x00, 0x01, // displayFlags
7754 0x00, 0x00, // horizontal + vertical justification
7755 0x00, 0x00, 0x00, 0x00, // bgColourRed/Green/Blue/Alpha
7756 // BoxRecord
7757 0x00, 0x00, 0x00, 0x00, // defTextBoxTop/Left
7758 0x00, 0x00, 0x00, 0x00, // defTextBoxBottom/Right
7759 // StyleRecord
7760 0x00, 0x00, 0x00, 0x00, // startChar + endChar
7761 0x00, 0x01, // fontID
7762 0x00, 0x00, // fontStyleFlags + fontSize
7763 0x00, 0x00, 0x00, 0x00, // fgColourRed/Green/Blue/Alpha
7764 // FontTableBox
7765 0x00, 0x00, 0x00, 0x0D, // box size
7766 'f', 't', 'a', 'b', // box atom name
7767 0x00, 0x01, // entry count
7768 // FontRecord
7769 0x00, 0x01, // font ID
7770 0x00, // font name length
7771 };
7772 MOVMuxContext *mov = s->priv_data;
7773 MOVTrack *track = &mov->tracks[tracknum];
7774 AVPacket *pkt = mov->pkt;
7775 int i, len;
7776 int ret;
7777
7778 track->mode = mov->mode;
7779 track->tag = MKTAG('t','e','x','t');
7780 track->timescale = mov->movie_timescale;
7781 track->par = avcodec_parameters_alloc();
7782 if (!track->par)
7783 return AVERROR(ENOMEM);
7785 ret = ff_alloc_extradata(track->par, sizeof(stub_header));
7786 if (ret < 0)
7787 return ret;
7788 memcpy(track->par->extradata, stub_header, sizeof(stub_header));
7789
7790 if (track->extradata == NULL) {
7791 track->stsd_count = 1;
7792 track->extradata = av_calloc(1, sizeof(*track->extradata));
7793 track->extradata_size = av_calloc(1, sizeof(*track->extradata_size));
7794 if (!track->extradata || !track->extradata_size)
7795 return AVERROR(ENOMEM);
7796 }
7797
7798 track->extradata[0] = av_memdup(stub_header, sizeof(stub_header));
7799 if (!track->extradata[0])
7800 return AVERROR(ENOMEM);
7801 track->extradata_size[0] = sizeof(stub_header);
7802
7803 pkt->stream_index = tracknum;
7804 pkt->flags = AV_PKT_FLAG_KEY;
7805
7806 for (i = 0; i < s->nb_chapters; i++) {
7807 AVChapter *c = s->chapters[i];
7809
7810 int64_t end = av_rescale_q(c->end, c->time_base, (AVRational){1,mov->movie_timescale});
7811 pkt->pts = pkt->dts = av_rescale_q(c->start, c->time_base, (AVRational){1,mov->movie_timescale});
7812 pkt->duration = end - pkt->dts;
7813
7814 if ((t = av_dict_get(c->metadata, "title", NULL, 0))) {
7815 static const char encd[12] = {
7816 0x00, 0x00, 0x00, 0x0C,
7817 'e', 'n', 'c', 'd',
7818 0x00, 0x00, 0x01, 0x00 };
7819 len = strlen(t->value);
7820 pkt->size = len + 2 + 12;
7821 pkt->data = av_malloc(pkt->size);
7822 if (!pkt->data) {
7824 return AVERROR(ENOMEM);
7825 }
7826 AV_WB16(pkt->data, len);
7827 memcpy(pkt->data + 2, t->value, len);
7828 memcpy(pkt->data + len + 2, encd, sizeof(encd));
7830 av_freep(&pkt->data);
7831 }
7832 }
7833
7834 av_packet_unref(mov->pkt);
7835
7836 return 0;
7837}
7838
7839
7840static int mov_check_timecode_track(AVFormatContext *s, AVTimecode *tc, AVStream *src_st, const char *tcstr)
7841{
7842 int ret;
7843
7844 /* compute the frame number */
7845 ret = av_timecode_init_from_string(tc, src_st->avg_frame_rate, tcstr, s);
7846 return ret;
7847}
7848
7849static int mov_create_timecode_track(AVFormatContext *s, int index, int src_index, AVTimecode tc)
7850{
7851 MOVMuxContext *mov = s->priv_data;
7852 MOVTrack *track = &mov->tracks[index];
7853 AVStream *src_st = mov->tracks[src_index].st;
7854 uint8_t data[4];
7855 AVPacket *pkt = mov->pkt;
7856 AVRational rate = src_st->avg_frame_rate;
7857 int ret;
7858
7859 /* tmcd track based on video stream */
7860 track->mode = mov->mode;
7861 track->tag = MKTAG('t','m','c','d');
7862 track->src_track = av_malloc(sizeof(*track->src_track));
7863 if (!track->src_track)
7864 return AVERROR(ENOMEM);
7865 *track->src_track = src_index;
7866 track->nb_src_track = 1;
7867 track->timescale = mov->tracks[src_index].timescale;
7870
7871 /* set st to src_st for metadata access*/
7872 track->st = src_st;
7873
7874 /* encode context: tmcd data stream */
7875 track->par = avcodec_parameters_alloc();
7876 if (!track->par)
7877 return AVERROR(ENOMEM);
7879 track->par->codec_tag = track->tag;
7880 track->st->avg_frame_rate = rate;
7881
7882 /* the tmcd track just contains one packet with the frame number */
7883 pkt->data = data;
7884 pkt->stream_index = index;
7885 pkt->flags = AV_PKT_FLAG_KEY;
7886 pkt->pts = pkt->dts = av_rescale_q(tc.start, av_inv_q(rate), (AVRational){ 1, track->timescale });
7887 pkt->size = 4;
7888 AV_WB32(pkt->data, tc.start);
7889 ret = ff_mov_write_packet(s, pkt);
7891 return ret;
7892}
7893
7894/*
7895 * st->disposition controls the "enabled" flag in the tkhd tag.
7896 * QuickTime will not play a track if it is not enabled. So make sure
7897 * that one track of each type (audio, video, subtitle) is enabled.
7898 *
7899 * Subtitles are special. For audio and video, setting "enabled" also
7900 * makes the track "default" (i.e. it is rendered when played). For
7901 * subtitles, an "enabled" subtitle is not rendered by default, but
7902 * if no subtitle is enabled, the subtitle menu in QuickTime will be
7903 * empty!
7904 */
7906{
7907 MOVMuxContext *mov = s->priv_data;
7908 int i;
7909 int enabled[AVMEDIA_TYPE_NB];
7910 int first[AVMEDIA_TYPE_NB];
7911
7912 for (i = 0; i < AVMEDIA_TYPE_NB; i++) {
7913 enabled[i] = 0;
7914 first[i] = -1;
7915 }
7916
7917 for (i = 0; i < mov->nb_streams; i++) {
7918 AVStream *st = mov->tracks[i].st;
7919
7922 is_cover_image(st))
7923 continue;
7924
7925 if (first[st->codecpar->codec_type] < 0)
7926 first[st->codecpar->codec_type] = i;
7929 enabled[st->codecpar->codec_type]++;
7930 }
7931 }
7932
7933 for (i = 0; i < AVMEDIA_TYPE_NB; i++) {
7934 switch (i) {
7935 case AVMEDIA_TYPE_VIDEO:
7936 case AVMEDIA_TYPE_AUDIO:
7938 if (enabled[i] > 1)
7939 mov->per_stream_grouping = 1;
7940 if (!enabled[i] && first[i] >= 0)
7941 mov->tracks[first[i]].flags |= MOV_TRACK_ENABLED;
7942 break;
7943 }
7944 }
7945}
7946
7948{
7949 MOVMuxContext *mov = s->priv_data;
7950
7951 for (int i = 0; i < s->nb_streams; i++)
7952 s->streams[i]->priv_data = NULL;
7953
7954 if (!mov->tracks)
7955 return;
7956
7957 if (mov->chapter_track) {
7959 }
7960
7961 for (int i = 0; i < mov->nb_tracks; i++) {
7962 MOVTrack *const track = &mov->tracks[i];
7963
7964 if (track->tag == MKTAG('r','t','p',' '))
7965 ff_mov_close_hinting(track);
7966 else if (track->tag == MKTAG('t','m','c','d') && mov->nb_meta_tmcd)
7967 av_freep(&track->par);
7968 av_freep(&track->cluster);
7969 av_freep(&track->cluster_written);
7970 av_freep(&track->frag_info);
7971 av_packet_free(&track->cover_image);
7972
7973 if (track->eac3_priv) {
7974 struct eac3_info *info = track->eac3_priv;
7975 av_packet_free(&info->pkt);
7976 av_freep(&track->eac3_priv);
7977 }
7978 for (int j = 0; j < track->stsd_count; j++)
7979 av_freep(&track->extradata[j]);
7980 av_freep(&track->extradata);
7981 av_freep(&track->extradata_size);
7982
7983 for (int i = 0; i < track->nb_tref_tags; i++)
7984 av_freep(&track->tref_tags[i].id);
7985 av_freep(&track->tref_tags);
7986 av_freep(&track->src_track);
7987
7988 ff_mov_cenc_free(&track->cenc);
7989 ffio_free_dyn_buf(&track->mdat_buf);
7990
7991#if CONFIG_IAMFENC
7992 ffio_free_dyn_buf(&track->iamf_buf);
7993 if (track->iamf)
7995 av_freep(&track->iamf);
7996#endif
7997 ff_isom_close_apvc(&track->apv);
7998
8000 }
8001
8002 av_freep(&mov->tracks);
8004}
8005
8006static uint32_t rgb_to_yuv(uint32_t rgb)
8007{
8008 uint8_t r, g, b;
8009 int y, cb, cr;
8010
8011 r = (rgb >> 16) & 0xFF;
8012 g = (rgb >> 8) & 0xFF;
8013 b = (rgb ) & 0xFF;
8014
8015 y = av_clip_uint8(( 16000 + 257 * r + 504 * g + 98 * b)/1000);
8016 cb = av_clip_uint8((128000 - 148 * r - 291 * g + 439 * b)/1000);
8017 cr = av_clip_uint8((128000 + 439 * r - 368 * g - 71 * b)/1000);
8018
8019 return (y << 16) | (cr << 8) | cb;
8020}
8021
8023 AVStream *st)
8024{
8025 int i, width = 720, height = 480;
8026 int have_palette = 0, have_size = 0;
8027 uint32_t palette[16];
8028 char *cur = st->codecpar->extradata;
8029
8030 while (cur && *cur) {
8031 if (strncmp("palette:", cur, 8) == 0) {
8032 int i, count;
8033 count = sscanf(cur + 8,
8034 "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32", "
8035 "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32", "
8036 "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32", "
8037 "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32"",
8038 &palette[ 0], &palette[ 1], &palette[ 2], &palette[ 3],
8039 &palette[ 4], &palette[ 5], &palette[ 6], &palette[ 7],
8040 &palette[ 8], &palette[ 9], &palette[10], &palette[11],
8041 &palette[12], &palette[13], &palette[14], &palette[15]);
8042
8043 for (i = 0; i < count; i++) {
8044 palette[i] = rgb_to_yuv(palette[i]);
8045 }
8046 have_palette = 1;
8047 } else if (!strncmp("size:", cur, 5)) {
8048 sscanf(cur + 5, "%dx%d", &width, &height);
8049 have_size = 1;
8050 }
8051 if (have_palette && have_size)
8052 break;
8053 cur += strcspn(cur, "\n\r");
8054 cur += strspn(cur, "\n\r");
8055 }
8056 if (have_palette) {
8058 if (!track->extradata[track->last_stsd_index])
8059 return AVERROR(ENOMEM);
8060 for (i = 0; i < 16; i++) {
8061 AV_WB32(track->extradata[track->last_stsd_index] + i * 4, palette[i]);
8062 }
8063 memset(track->extradata[track->last_stsd_index] + 16*4, 0, AV_INPUT_BUFFER_PADDING_SIZE);
8064 track->extradata_size[track->last_stsd_index] = 16 * 4;
8065 }
8066 st->codecpar->width = width;
8067 st->codecpar->height = track->height = height;
8068
8069 return 0;
8070}
8071
8072#if CONFIG_IAMFENC
8073static int mov_init_iamf_track(AVFormatContext *s)
8074{
8075 MOVMuxContext *mov = s->priv_data;
8076 MOVTrack *track;
8077 IAMFContext *iamf;
8078 int first_iamf_idx = INT_MAX, last_iamf_idx = 0;
8079 int nb_audio_elements = 0, nb_mix_presentations = 0;
8080 int ret;
8081
8082 for (int i = 0; i < s->nb_stream_groups; i++) {
8083 const AVStreamGroup *stg = s->stream_groups[i];
8084
8086 nb_audio_elements++;
8088 nb_mix_presentations++;
8089 }
8090
8091 if (!nb_audio_elements && !nb_mix_presentations)
8092 return 0;
8093
8094 if (nb_audio_elements < 1 || nb_audio_elements > 2 || nb_mix_presentations < 1) {
8095 av_log(s, AV_LOG_ERROR, "There must be >= 1 and <= 2 IAMF_AUDIO_ELEMENT and at least "
8096 "one IAMF_MIX_PRESENTATION stream groups to write a IMAF track\n");
8097 return AVERROR(EINVAL);
8098 }
8099
8100 iamf = av_mallocz(sizeof(*iamf));
8101 if (!iamf)
8102 return AVERROR(ENOMEM);
8103
8104
8105 for (int i = 0; i < s->nb_stream_groups; i++) {
8106 const AVStreamGroup *stg = s->stream_groups[i];
8107 switch(stg->type) {
8109 for (int j = 0; j < stg->nb_streams; j++) {
8110 first_iamf_idx = FFMIN(stg->streams[j]->index, first_iamf_idx);
8111 last_iamf_idx = FFMAX(stg->streams[j]->index, last_iamf_idx);
8112 }
8113
8114 ret = ff_iamf_add_audio_element(iamf, stg, s);
8115 break;
8117 ret = ff_iamf_add_mix_presentation(iamf, stg, s);
8118 break;
8119 default:
8120 av_assert0(0);
8121 }
8122 if (ret < 0) {
8124 av_free(iamf);
8125 return ret;
8126 }
8127 }
8128
8129 track = &mov->tracks[first_iamf_idx];
8130 track->iamf = iamf;
8131 track->first_iamf_idx = first_iamf_idx;
8132 track->last_iamf_idx = last_iamf_idx;
8133 track->tag = MKTAG('i','a','m','f');
8134
8135 for (int i = 0; i < s->nb_stream_groups; i++) {
8136 AVStreamGroup *stg = s->stream_groups[i];
8138 continue;
8139 for (int j = 0; j < stg->nb_streams; j++)
8140 stg->streams[j]->priv_data = track;
8141 }
8142
8143 ret = avio_open_dyn_buf(&track->iamf_buf);
8144 if (ret < 0)
8145 return ret;
8146
8147 return 0;
8148}
8149#endif
8150
8152{
8153 MOVMuxContext *mov = s->priv_data;
8154 int has_iamf = 0;
8155 int i, ret;
8156
8157 mov->fc = s;
8158 mov->pkt = ffformatcontext(s)->pkt;
8159
8160 /* Default mode == MP4 */
8161 mov->mode = MODE_MP4;
8162
8163#define IS_MODE(muxer, config) (CONFIG_ ## config ## _MUXER && !strcmp(#muxer, s->oformat->name))
8164 if (IS_MODE(3gp, TGP)) mov->mode = MODE_3GP;
8165 else if (IS_MODE(3g2, TG2)) mov->mode = MODE_3GP|MODE_3G2;
8166 else if (IS_MODE(mov, MOV)) mov->mode = MODE_MOV;
8167 else if (IS_MODE(psp, PSP)) mov->mode = MODE_PSP;
8168 else if (IS_MODE(ipod, IPOD)) mov->mode = MODE_IPOD;
8169 else if (IS_MODE(ismv, ISMV)) mov->mode = MODE_ISM;
8170 else if (IS_MODE(f4v, F4V)) mov->mode = MODE_F4V;
8171 else if (IS_MODE(avif, AVIF)) mov->mode = MODE_AVIF;
8172#undef IS_MODE
8173
8174 if (mov->flags & FF_MOV_FLAG_DELAY_MOOV)
8176
8177 if (mov->mode == MODE_AVIF)
8179
8180 /* Set the FRAGMENT flag if any of the fragmentation methods are
8181 * enabled. */
8182 if (mov->max_fragment_duration || mov->max_fragment_size ||
8188
8191 av_log(s, AV_LOG_ERROR, "Setting both hybrid_fragmented and faststart is not supported.\n");
8192 return AVERROR(EINVAL);
8193 }
8194
8195 /* Set other implicit flags immediately */
8198
8199 if (mov->mode == MODE_ISM)
8202 if (mov->flags & FF_MOV_FLAG_DASH)
8205 if (mov->flags & FF_MOV_FLAG_CMAF)
8208
8209 if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV && s->flags & AVFMT_FLAG_AUTO_BSF) {
8210 av_log(s, AV_LOG_VERBOSE, "Empty MOOV enabled; disabling automatic bitstream filtering\n");
8211 s->flags &= ~AVFMT_FLAG_AUTO_BSF;
8212 }
8213
8215 av_log(s, AV_LOG_WARNING, "Global SIDX enabled; Ignoring skip_sidx option\n");
8217 }
8218
8219 if (mov->flags & FF_MOV_FLAG_FASTSTART) {
8220 mov->reserved_moov_size = -1;
8221 }
8222
8223 if (mov->use_editlist < 0) {
8224 mov->use_editlist = 1;
8225 if (mov->flags & FF_MOV_FLAG_FRAGMENT &&
8226 !(mov->flags & FF_MOV_FLAG_DELAY_MOOV)) {
8227 // If we can avoid needing an edit list by shifting the
8228 // tracks, prefer that over (trying to) write edit lists
8229 // in fragmented output.
8230 if (s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO ||
8231 s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO)
8232 mov->use_editlist = 0;
8233 }
8234 }
8235 if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV &&
8236 !(mov->flags & FF_MOV_FLAG_DELAY_MOOV) && mov->use_editlist)
8237 av_log(s, AV_LOG_WARNING, "No meaningful edit list will be written when using empty_moov without delay_moov\n");
8238
8239 if (mov->flags & FF_MOV_FLAG_CMAF && mov->use_editlist)
8241
8242 if (!mov->use_editlist && s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO &&
8244 s->avoid_negative_ts = AVFMT_AVOID_NEG_TS_MAKE_ZERO;
8245
8246 /* Clear the omit_tfhd_offset flag if default_base_moof is set;
8247 * if the latter is set that's enough and omit_tfhd_offset doesn't
8248 * add anything extra on top of that. */
8252
8253 if (mov->frag_interleave &&
8256 "Sample interleaving in fragments is mutually exclusive with "
8257 "omit_tfhd_offset and separate_moof\n");
8258 return AVERROR(EINVAL);
8259 }
8260
8261 /* Non-seekable output is ok if using fragmentation. If ism_lookahead
8262 * is enabled, we don't support non-seekable output at all. */
8263 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL) &&
8264 (!(mov->flags & FF_MOV_FLAG_FRAGMENT) || mov->ism_lookahead ||
8265 mov->mode == MODE_AVIF)) {
8266 av_log(s, AV_LOG_ERROR, "muxer does not support non seekable output\n");
8267 return AVERROR(EINVAL);
8268 }
8269
8270 /* AVIF output must have at most two video streams (one for YUV and one for
8271 * alpha). */
8272 if (mov->mode == MODE_AVIF) {
8273 if (s->nb_streams > 2) {
8274 av_log(s, AV_LOG_ERROR, "AVIF output requires exactly one or two streams\n");
8275 return AVERROR(EINVAL);
8276 }
8277 if (s->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO &&
8278 (s->nb_streams > 1 && s->streams[1]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO)) {
8279 av_log(s, AV_LOG_ERROR, "AVIF output supports only video streams\n");
8280 return AVERROR(EINVAL);
8281 }
8282 if (s->nb_streams > 1) {
8283 const AVPixFmtDescriptor *pixdesc =
8284 av_pix_fmt_desc_get(s->streams[1]->codecpar->format);
8285 if (pixdesc->nb_components != 1) {
8286 av_log(s, AV_LOG_ERROR, "Second stream for AVIF (alpha) output must have exactly one plane\n");
8287 return AVERROR(EINVAL);
8288 }
8289 }
8290 s->streams[0]->disposition |= AV_DISPOSITION_DEFAULT;
8291 }
8292
8293 for (i = 0; i < s->nb_stream_groups; i++) {
8294 AVStreamGroup *stg = s->stream_groups[i];
8295
8296 if (stg->type == AV_STREAM_GROUP_PARAMS_LCEVC) {
8297 if (stg->nb_streams != 2) {
8298 av_log(s, AV_LOG_ERROR, "Exactly two Streams are supported for Stream Groups of type LCEVC\n");
8299 return AVERROR(EINVAL);
8300 }
8302 if (lcevc->el_index > 1)
8303 return AVERROR(EINVAL);
8304 AVStream *st = stg->streams[lcevc->el_index];
8305 if (st->codecpar->codec_id != AV_CODEC_ID_LCEVC) {
8306 av_log(s, AV_LOG_ERROR, "Stream #%u is not an LCEVC stream\n", lcevc->el_index);
8307 return AVERROR(EINVAL);
8308 }
8309 }
8310
8311#if CONFIG_IAMFENC
8313 continue;
8314
8315 for (int j = 0; j < stg->nb_streams; j++) {
8316 AVStream *st = stg->streams[j];
8317
8318 if (st->priv_data) {
8319 av_log(s, AV_LOG_ERROR, "Stream %d is present in more than one Stream Group of type "
8320 "IAMF Audio Element\n", j);
8321 return AVERROR(EINVAL);
8322 }
8323 st->priv_data = st;
8324 }
8325 has_iamf = 1;
8326
8327 if (!mov->nb_tracks) // We support one track for the entire IAMF structure
8328 mov->nb_tracks++;
8329#endif
8330 }
8331
8332 for (i = 0; i < s->nb_streams; i++) {
8333 AVStream *st = s->streams[i];
8334 if (st->priv_data)
8335 continue;
8336 // Don't produce a track in the output file for timed ID3 streams.
8338 // Leave priv_data set to NULL for these AVStreams that don't
8339 // have a corresponding track.
8340 continue;
8341 }
8342 st->priv_data = st;
8343 mov->nb_tracks++;
8344 }
8345
8346 mov->nb_streams = mov->nb_tracks;
8347
8348 if (mov->mode & (MODE_MP4|MODE_MOV|MODE_IPOD) && s->nb_chapters)
8349 mov->chapter_track = mov->nb_tracks++;
8350
8351 if (mov->flags & FF_MOV_FLAG_RTP_HINT) {
8352 for (i = 0; i < s->nb_streams; i++)
8353 if (rtp_hinting_needed(s->streams[i]))
8354 mov->nb_tracks++;
8355 }
8356
8357 if (mov->write_btrt < 0) {
8358 mov->write_btrt = mov->mode == MODE_MP4;
8359 }
8360
8361 if ( mov->write_tmcd == -1 && (mov->mode == MODE_MOV || mov->mode == MODE_MP4)
8362 || mov->write_tmcd == 1) {
8363 AVDictionaryEntry *global_tcr = av_dict_get(s->metadata, "timecode",
8364 NULL, 0);
8365
8366 /* +1 tmcd track for each video stream with a timecode */
8367 for (i = 0; i < s->nb_streams; i++) {
8368 AVStream *st = s->streams[i];
8369 AVDictionaryEntry *t = global_tcr;
8371 (t || (t=av_dict_get(st->metadata, "timecode", NULL, 0)))) {
8372 AVTimecode tc;
8373 ret = mov_check_timecode_track(s, &tc, st, t->value);
8374 if (ret >= 0)
8375 mov->nb_meta_tmcd++;
8376 }
8377 }
8378
8379 /* check if there is already a tmcd track to remux */
8380 if (mov->nb_meta_tmcd) {
8381 for (i = 0; i < s->nb_streams; i++) {
8382 AVStream *st = s->streams[i];
8383 if (st->codecpar->codec_tag == MKTAG('t','m','c','d')) {
8384 av_log(s, AV_LOG_WARNING, "You requested a copy of the original timecode track "
8385 "so timecode metadata are now ignored\n");
8386 mov->nb_meta_tmcd = 0;
8387 }
8388 }
8389 }
8390
8391 mov->nb_tracks += mov->nb_meta_tmcd;
8392 }
8393
8394 // Reserve an extra stream for chapters for the case where chapters
8395 // are written in the trailer
8396 mov->tracks = av_calloc(mov->nb_tracks + 1, sizeof(*mov->tracks));
8397 if (!mov->tracks)
8398 return AVERROR(ENOMEM);
8399
8400 for (i = 0; i < mov->nb_tracks; i++) {
8401 MOVTrack *track = &mov->tracks[i];
8402
8403 track->stsd_count = 1;
8404 track->extradata = av_calloc(track->stsd_count, sizeof(*track->extradata));
8405 track->extradata_size = av_calloc(track->stsd_count, sizeof(*track->extradata_size));
8406 if (!track->extradata || !track->extradata_size)
8407 return AVERROR(ENOMEM);
8408 }
8409
8410 if (mov->encryption_scheme_str != NULL && strcmp(mov->encryption_scheme_str, "none") != 0) {
8411 if (strcmp(mov->encryption_scheme_str, "cenc-aes-ctr") == 0) {
8413
8415 av_log(s, AV_LOG_ERROR, "Invalid encryption key len %d expected %d\n",
8417 return AVERROR(EINVAL);
8418 }
8419
8420 if (mov->encryption_kid_len != CENC_KID_SIZE) {
8421 av_log(s, AV_LOG_ERROR, "Invalid encryption kid len %d expected %d\n",
8423 return AVERROR(EINVAL);
8424 }
8425 } else {
8426 av_log(s, AV_LOG_ERROR, "unsupported encryption scheme %s\n",
8428 return AVERROR(EINVAL);
8429 }
8430 }
8431
8432#if CONFIG_IAMFENC
8433 ret = mov_init_iamf_track(s);
8434 if (ret < 0)
8435 return ret;
8436#endif
8437
8438 for (int j = 0, i = 0; j < s->nb_streams; j++) {
8439 AVStream *st = s->streams[j];
8440
8441 if (st != st->priv_data) {
8442 if (has_iamf)
8443 i += has_iamf--;
8444 continue;
8445 }
8446 st->priv_data = &mov->tracks[i++];
8447 }
8448
8449 AVRational movie_timescale = (AVRational) { 0, 1 };
8450 for (i = 0; i < s->nb_streams; i++) {
8451 AVStream *st= s->streams[i];
8452 MOVTrack *track = st->priv_data;
8453
8454 if (!track)
8455 continue;
8456
8457 if (!track->st) {
8458 track->st = st;
8459 track->par = st->codecpar;
8460 }
8461
8462 movie_timescale = av_gcd_q(movie_timescale, st->time_base, INT_MAX, (AVRational){1,0});
8463 }
8464 if (!movie_timescale.den)
8465 movie_timescale = MOV_TIMESCALE_Q;
8466
8467 if (!mov->movie_timescale)
8468 mov->movie_timescale = FFMAX(movie_timescale.den, MOV_TIMESCALE);
8469
8470 for (i = 0; i < s->nb_streams; i++) {
8471 AVStream *st= s->streams[i];
8472 MOVTrack *track = st->priv_data;
8473 AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL,0);
8474
8475 if (!track)
8476 continue;
8477
8478 track->language = ff_mov_iso639_to_lang(lang?lang->value:"und", mov->mode!=MODE_MOV);
8479 if (track->language < 0)
8480 track->language = 32767; // Unspecified Macintosh language code
8481 track->mode = mov->mode;
8482 if (!track->tag)
8483 track->tag = mov_find_codec_tag(s, track);
8484 if (!track->tag) {
8485 av_log(s, AV_LOG_ERROR, "Could not find tag for codec %s in stream #%d, "
8486 "codec not currently supported in container\n",
8488 return AVERROR(EINVAL);
8489 }
8490 /* If hinting of this track is enabled by a later hint track,
8491 * this is updated. */
8492 track->hint_track = -1;
8493 track->start_dts = AV_NOPTS_VALUE;
8494 track->start_cts = AV_NOPTS_VALUE;
8495 track->end_pts = AV_NOPTS_VALUE;
8496 track->dts_shift = AV_NOPTS_VALUE;
8498 if (track->tag == MKTAG('m','x','3','p') || track->tag == MKTAG('m','x','3','n') ||
8499 track->tag == MKTAG('m','x','4','p') || track->tag == MKTAG('m','x','4','n') ||
8500 track->tag == MKTAG('m','x','5','p') || track->tag == MKTAG('m','x','5','n')) {
8501 if (st->codecpar->width != 720 || (st->codecpar->height != 608 && st->codecpar->height != 512)) {
8502 av_log(s, AV_LOG_ERROR, "D-10/IMX must use 720x608 or 720x512 video resolution\n");
8503 return AVERROR(EINVAL);
8504 }
8505 track->height = track->tag >> 24 == 'n' ? 486 : 576;
8506 }
8507 if (mov->video_track_timescale) {
8508 track->timescale = mov->video_track_timescale;
8509 if (mov->mode == MODE_ISM && mov->video_track_timescale != 10000000)
8510 av_log(s, AV_LOG_WARNING, "Warning: some tools, like mp4split, assume a timescale of 10000000 for ISMV.\n");
8511 } else {
8512 track->timescale = st->time_base.den;
8513 while(track->timescale < 10000)
8514 track->timescale *= 2;
8515 }
8516 if (st->codecpar->width > 65535 || st->codecpar->height > 65535) {
8517 av_log(s, AV_LOG_ERROR, "Resolution %dx%d too large for mov/mp4\n", st->codecpar->width, st->codecpar->height);
8518 return AVERROR(EINVAL);
8519 }
8520 if (track->mode == MODE_MOV && track->timescale > 100000)
8522 "WARNING codec timebase is very high. If duration is too long,\n"
8523 "file may not be playable by quicktime. Specify a shorter timebase\n"
8524 "or choose different container.\n");
8525 if (track->mode == MODE_MOV &&
8526 track->par->codec_id == AV_CODEC_ID_RAWVIDEO &&
8527 track->tag == MKTAG('r','a','w',' ')) {
8528 enum AVPixelFormat pix_fmt = track->par->format;
8529 if (pix_fmt == AV_PIX_FMT_NONE && track->par->bits_per_coded_sample == 1)
8531 track->is_unaligned_qt_rgb =
8538 }
8539 if (track->par->codec_id == AV_CODEC_ID_VP9 && track->mode != MODE_MP4) {
8540 av_log(s, AV_LOG_ERROR, "%s only supported in MP4.\n", avcodec_get_name(track->par->codec_id));
8541 return AVERROR(EINVAL);
8542 } else if (track->par->codec_id == AV_CODEC_ID_AV1 &&
8543 track->mode != MODE_MP4 && track->mode != MODE_AVIF) {
8544 av_log(s, AV_LOG_ERROR, "%s only supported in MP4 and AVIF.\n", avcodec_get_name(track->par->codec_id));
8545 return AVERROR(EINVAL);
8546 } else if (track->par->codec_id == AV_CODEC_ID_VP8) {
8547 /* altref frames handling is not defined in the spec as of version v1.0,
8548 * so just forbid muxing VP8 streams altogether until a new version does */
8549 av_log(s, AV_LOG_ERROR, "VP8 muxing is currently not supported.\n");
8550 return AVERROR_PATCHWELCOME;
8551 } else if (track->par->codec_id == AV_CODEC_ID_APV) {
8552 ret = ff_isom_init_apvc(&track->apv, s);
8553 if (ret < 0)
8554 return ret;
8555 }
8556 if (is_cover_image(st)) {
8557 track->cover_image = av_packet_alloc();
8558 if (!track->cover_image)
8559 return AVERROR(ENOMEM);
8560 }
8561 } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
8562 track->timescale = st->codecpar->sample_rate;
8564 av_log(s, AV_LOG_WARNING, "track %d: codec frame size is not set\n", i);
8565 track->audio_vbr = 1;
8566 }else if (st->codecpar->codec_id == AV_CODEC_ID_ADPCM_MS ||
8569 if (!st->codecpar->block_align) {
8570 av_log(s, AV_LOG_ERROR, "track %d: codec block align is not set for adpcm\n", i);
8571 return AVERROR(EINVAL);
8572 }
8573 track->sample_size = st->codecpar->block_align;
8574 }else if (st->codecpar->frame_size > 1){ /* assume compressed audio */
8575 track->audio_vbr = 1;
8576 }else{
8577 track->sample_size = (av_get_bits_per_sample(st->codecpar->codec_id) >> 3) *
8579 }
8580 if (st->codecpar->codec_id == AV_CODEC_ID_ILBC ||
8582 track->audio_vbr = 1;
8583 }
8584 if (track->mode != MODE_MOV &&
8585 track->par->codec_id == AV_CODEC_ID_MP3 && track->timescale < 16000) {
8586 if (s->strict_std_compliance >= FF_COMPLIANCE_NORMAL) {
8587 av_log(s, AV_LOG_ERROR, "track %d: muxing mp3 at %dhz is not standard, to mux anyway set strict to -1\n",
8588 i, track->par->sample_rate);
8589 return AVERROR(EINVAL);
8590 } else {
8591 av_log(s, AV_LOG_WARNING, "track %d: muxing mp3 at %dhz is not standard in MP4\n",
8592 i, track->par->sample_rate);
8593 }
8594 }
8595 if (track->par->codec_id == AV_CODEC_ID_FLAC ||
8596 track->par->codec_id == AV_CODEC_ID_TRUEHD ||
8597 track->par->codec_id == AV_CODEC_ID_OPUS) {
8598 if (track->mode != MODE_MP4) {
8599 av_log(s, AV_LOG_ERROR, "%s only supported in MP4.\n", avcodec_get_name(track->par->codec_id));
8600 return AVERROR(EINVAL);
8601 }
8602 if (track->par->codec_id == AV_CODEC_ID_TRUEHD &&
8603 s->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) {
8605 "%s in MP4 support is experimental, add "
8606 "'-strict %d' if you want to use it.\n",
8608 return AVERROR_EXPERIMENTAL;
8609 }
8610 }
8611 } else if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
8612 track->timescale = st->time_base.den;
8613
8614 if (track->par->codec_id == AV_CODEC_ID_TTML) {
8615 /* 14496-30 requires us to use a single sample per fragment
8616 for TTML, for which we define a per-track flag.
8617
8618 We set the flag in case we are receiving TTML paragraphs
8619 from the input, in other words in case we are not doing
8620 stream copy. */
8623
8624 if (track->mode != MODE_ISM &&
8625 track->par->codec_tag == MOV_ISMV_TTML_TAG &&
8626 s->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL) {
8628 "ISMV style TTML support with the 'dfxp' tag in "
8629 "non-ISMV formats is not officially supported. Add "
8630 "'-strict unofficial' if you want to use it.\n");
8631 return AVERROR_EXPERIMENTAL;
8632 }
8633 }
8634 } else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA) {
8635 track->timescale = st->time_base.den;
8636 } else {
8637 track->timescale = mov->movie_timescale;
8638 }
8639 if (!track->height)
8640 track->height = st->codecpar->height;
8641 /* The Protected Interoperable File Format (PIFF) standard, used by ISMV recommends but
8642 doesn't mandate a track timescale of 10,000,000. The muxer allows a custom timescale
8643 for video tracks, so if user-set, it isn't overwritten */
8644 if (mov->mode == MODE_ISM &&
8647 track->timescale = 10000000;
8648 }
8649
8650 avpriv_set_pts_info(st, 64, 1, track->timescale);
8651
8653 ret = ff_mov_cenc_init(&track->cenc, mov->encryption_key,
8654 (track->par->codec_id == AV_CODEC_ID_H264 || track->par->codec_id == AV_CODEC_ID_HEVC ||
8655 track->par->codec_id == AV_CODEC_ID_VVC || track->par->codec_id == AV_CODEC_ID_AV1),
8656 track->par->codec_id, s->flags & AVFMT_FLAG_BITEXACT);
8657 if (ret)
8658 return ret;
8659 }
8660 }
8661
8662 for (i = 0; i < s->nb_stream_groups; i++) {
8663 AVStreamGroup *stg = s->stream_groups[i];
8664
8665 switch (stg->type) {
8668 AVStream *st = stg->streams[lcevc->el_index];
8669 MOVTrack *track = st->priv_data;
8670
8671 for (int j = 0; j < mov->nb_tracks; j++) {
8672 MOVTrack *trk = &mov->tracks[j];
8673
8674 if (trk->st == stg->streams[!lcevc->el_index]) {
8675 track->src_track = av_malloc(sizeof(*track->src_track));
8676 if (!track->src_track)
8677 return AVERROR(ENOMEM);
8678 *track->src_track = j;
8679 track->nb_src_track = 1;
8680 break;
8681 }
8682 }
8683
8684 track->par->width = lcevc->width;
8685 track->par->height = track->height = lcevc->height;
8686 break;
8687 }
8689 const AVStreamGroupTREF *tref = stg->params.tref;
8690 MOVTrack *track;
8691
8692 if (tref->metadata_index >= stg->nb_streams)
8693 return AVERROR(EINVAL);
8694
8695 track = stg->streams[tref->metadata_index]->priv_data;
8696 for (int j = 0; j < stg->nb_streams; j++) {
8697 const AVStream *st2 = stg->streams[j];
8698 int index = -1;
8699
8700 if (j == tref->metadata_index)
8701 continue;
8702
8703 for (int k = 0; k < mov->nb_tracks; k++) {
8704 if (mov->tracks[k].st != st2)
8705 continue;
8706 index = k;
8707 break;
8708 }
8709 if (index < 0)
8710 return AVERROR(EINVAL);
8711
8712 int *tmp = av_realloc(track->src_track,
8713 (track->nb_src_track + 1) * sizeof(*track->src_track));
8714 if (!tmp)
8715 return AVERROR(ENOMEM);
8716 track->src_track = tmp;
8717 track->src_track[track->nb_src_track++] = index;
8718 }
8719 break;
8720 }
8721 default:
8722 break;
8723 }
8724 }
8725
8726 /* fill src_track for tmcd tracks not covered by stream groups or
8727 * created by this muxer, retaining the old behavior of src_track
8728 * being arbitrarily 0. */
8729 for (i = 0; i < s->nb_streams; i++) {
8730 AVStream *st = s->streams[i];
8731 MOVTrack *track = st->priv_data;
8732 if (st->codecpar->codec_tag != MKTAG('t','m','c','d') ||
8733 track->nb_src_track)
8734 continue;
8735
8736 track->src_track = av_malloc(sizeof(*track->src_track));
8737 if (!track->src_track)
8738 return AVERROR(ENOMEM);
8739 *track->src_track = 0;
8740 track->nb_src_track = 1;
8741 }
8742
8744 return 0;
8745}
8746
8748{
8749 AVIOContext *pb = s->pb;
8750 MOVMuxContext *mov = s->priv_data;
8751 int ret, hint_track = 0, tmcd_track = 0, nb_tracks = mov->nb_streams;
8752
8753 if (mov->mode & (MODE_MP4|MODE_MOV|MODE_IPOD) && s->nb_chapters)
8754 nb_tracks++;
8755
8756 if (mov->flags & FF_MOV_FLAG_RTP_HINT) {
8757 hint_track = nb_tracks;
8758 for (int i = 0; i < mov->nb_streams; i++) {
8759 if (rtp_hinting_needed(mov->tracks[i].st))
8760 nb_tracks++;
8761 }
8762 }
8763
8764 if (mov->nb_meta_tmcd)
8765 tmcd_track = nb_tracks;
8766
8767 for (int i = 0; i < mov->nb_streams; i++) {
8768 MOVTrack *track = &mov->tracks[i];
8769 AVStream *st = track->st;
8770
8771 /* copy extradata if it exists */
8772 if (st->codecpar->extradata_size) {
8775 else if (!TAG_IS_AVCI(track->tag) && st->codecpar->codec_id != AV_CODEC_ID_DNXHD) {
8777 track->extradata[track->last_stsd_index] =
8779 if (!track->extradata[track->last_stsd_index]) {
8780 return AVERROR(ENOMEM);
8781 }
8782 memcpy(track->extradata[track->last_stsd_index],
8783 st->codecpar->extradata, track->extradata_size[track->last_stsd_index]);
8784 memset(track->extradata[track->last_stsd_index] + track->extradata_size[track->last_stsd_index],
8786 }
8787 }
8788
8792 continue;
8793
8794 for (int j = 0; j < mov->nb_streams; j++) {
8795 AVStream *stj= mov->tracks[j].st;
8796 MOVTrack *trackj= &mov->tracks[j];
8797 if (j == i)
8798 continue;
8799
8800 if (stj->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
8801 (trackj->par->ch_layout.nb_channels != 1 ||
8804 )
8805 track->mono_as_fc = -1;
8806
8807 if (stj->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
8810 trackj->par->ch_layout.nb_channels == 1 && track->mono_as_fc >= 0
8811 )
8812 track->mono_as_fc++;
8813
8814 if (stj->codecpar->codec_type != AVMEDIA_TYPE_AUDIO ||
8817 trackj->language != track->language ||
8818 trackj->tag != track->tag
8819 )
8820 continue;
8821 track->multichannel_as_mono++;
8822 }
8823 }
8824
8825 if (!(mov->flags & FF_MOV_FLAG_DELAY_MOOV) ||
8827 if ((ret = mov_write_identification(pb, s)) < 0)
8828 return ret;
8829 }
8830
8831 if (mov->reserved_moov_size){
8832 mov->reserved_header_pos = avio_tell(pb);
8833 if (mov->reserved_moov_size > 0)
8834 avio_skip(pb, mov->reserved_moov_size);
8835 }
8836
8837 if (mov->flags & FF_MOV_FLAG_FRAGMENT) {
8838 /* If no fragmentation options have been set, set a default. */
8839 if (!(mov->flags & (FF_MOV_FLAG_FRAG_KEYFRAME |
8845 avio_wb32(pb, 8); // placeholder for extended size field (64 bit)
8846 ffio_wfourcc(pb, mov->mode == MODE_MOV ? "wide" : "free");
8847 mov->mdat_pos = avio_tell(pb);
8848 // The free/wide header that later will be converted into an
8849 // mdat, covering the initial moov and all the fragments.
8850 avio_wb32(pb, 0);
8851 ffio_wfourcc(pb, mov->mode == MODE_MOV ? "wide" : "free");
8852 // Write an ftyp atom, hidden in a free/wide. This is neither
8853 // exposed while the file is written, as fragmented, nor when the
8854 // file is finalized into non-fragmented form. However, this allows
8855 // accessing a pristine, sequential ftyp+moov init segment, even
8856 // after the file is finalized. It also allows dumping the whole
8857 // contents of the mdat box, to get the fragmented form of the
8858 // file.
8859 if ((ret = mov_write_identification(pb, s)) < 0)
8860 return ret;
8861 update_size(pb, mov->mdat_pos);
8862 }
8863 } else if (mov->mode != MODE_AVIF) {
8864 if (mov->flags & FF_MOV_FLAG_FASTSTART)
8865 mov->reserved_header_pos = avio_tell(pb);
8866 mov_write_mdat_tag(pb, mov);
8867 }
8868
8870 if (mov->time)
8871 mov->time += 0x7C25B080; // 1970 based -> 1904 based
8872
8873 if (mov->chapter_track)
8874 if ((ret = mov_create_chapter_track(s, mov->chapter_track)) < 0)
8875 return ret;
8876
8877 if (mov->flags & FF_MOV_FLAG_RTP_HINT) {
8878 for (int i = 0; i < mov->nb_streams; i++) {
8879 if (rtp_hinting_needed(mov->tracks[i].st)) {
8880 if ((ret = ff_mov_init_hinting(s, hint_track, i)) < 0)
8881 return ret;
8882 hint_track++;
8883 }
8884 }
8885 }
8886
8887 if (mov->nb_meta_tmcd) {
8888 const AVDictionaryEntry *t, *global_tcr = av_dict_get(s->metadata,
8889 "timecode", NULL, 0);
8890 /* Initialize the tmcd tracks */
8891 for (int i = 0; i < mov->nb_streams; i++) {
8892 AVStream *st = mov->tracks[i].st;
8893 t = global_tcr;
8894
8896 AVTimecode tc;
8897 if (!t)
8898 t = av_dict_get(st->metadata, "timecode", NULL, 0);
8899 if (!t)
8900 continue;
8901 if (mov_check_timecode_track(s, &tc, st, t->value) < 0)
8902 continue;
8903 if ((ret = mov_create_timecode_track(s, tmcd_track, i, tc)) < 0)
8904 return ret;
8905 tmcd_track++;
8906 }
8907 }
8908 }
8909
8910 avio_flush(pb);
8911
8912 if (mov->flags & FF_MOV_FLAG_ISML)
8913 mov_write_isml_manifest(pb, mov, s);
8914
8915 if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV &&
8916 !(mov->flags & FF_MOV_FLAG_DELAY_MOOV)) {
8917 if ((ret = mov_write_moov_tag(pb, mov, s)) < 0)
8918 return ret;
8919 mov->moov_written = 1;
8920 if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX)
8921 mov->reserved_header_pos = avio_tell(pb);
8922 }
8923
8924 return 0;
8925}
8926
8928{
8929 int ret;
8930 AVIOContext *moov_buf;
8931 MOVMuxContext *mov = s->priv_data;
8932
8933 if ((ret = ffio_open_null_buf(&moov_buf)) < 0)
8934 return ret;
8935 if ((ret = mov_write_moov_tag(moov_buf, mov, s)) < 0)
8936 return ret;
8937 return ffio_close_null_buf(moov_buf);
8938}
8939
8941{
8942 int ret;
8943 AVIOContext *buf;
8944 MOVMuxContext *mov = s->priv_data;
8945
8946 if ((ret = ffio_open_null_buf(&buf)) < 0)
8947 return ret;
8948 mov_write_sidx_tags(buf, mov, -1, 0);
8949 return ffio_close_null_buf(buf);
8950}
8951
8952/*
8953 * This function gets the moov size if moved to the top of the file: the chunk
8954 * offset table can switch between stco (32-bit entries) to co64 (64-bit
8955 * entries) when the moov is moved to the beginning, so the size of the moov
8956 * would change. It also updates the chunk offset tables.
8957 */
8959{
8960 int i, moov_size, moov_size2;
8961 MOVMuxContext *mov = s->priv_data;
8962
8963 moov_size = get_moov_size(s);
8964 if (moov_size < 0)
8965 return moov_size;
8966
8967 for (i = 0; i < mov->nb_tracks; i++)
8968 mov->tracks[i].data_offset += moov_size;
8969
8970 moov_size2 = get_moov_size(s);
8971 if (moov_size2 < 0)
8972 return moov_size2;
8973
8974 /* if the size changed, we just switched from stco to co64 and need to
8975 * update the offsets */
8976 if (moov_size2 != moov_size)
8977 for (i = 0; i < mov->nb_tracks; i++)
8978 mov->tracks[i].data_offset += moov_size2 - moov_size;
8979
8980 return moov_size2;
8981}
8982
8984{
8985 int i, sidx_size;
8986 MOVMuxContext *mov = s->priv_data;
8987
8988 sidx_size = get_sidx_size(s);
8989 if (sidx_size < 0)
8990 return sidx_size;
8991
8992 for (i = 0; i < mov->nb_tracks; i++)
8993 mov->tracks[i].data_offset += sidx_size;
8994
8995 return sidx_size;
8996}
8997
8999{
9000 int moov_size;
9001 MOVMuxContext *mov = s->priv_data;
9002
9003 if (mov->flags & FF_MOV_FLAG_FRAGMENT)
9004 moov_size = compute_sidx_size(s);
9005 else
9006 moov_size = compute_moov_size(s);
9007 if (moov_size < 0)
9008 return moov_size;
9009
9010 return ff_format_shift_data(s, mov->reserved_header_pos, moov_size);
9011}
9012
9014{
9015 MOVMuxContext *mov = s->priv_data;
9016 AVIOContext *pb = s->pb;
9017
9018 /* Write size of mdat tag */
9019 if (mov->mdat_size + 8 <= UINT32_MAX) {
9020 avio_seek(pb, mov->mdat_pos, SEEK_SET);
9021 avio_wb32(pb, mov->mdat_size + 8);
9023 ffio_wfourcc(pb, "mdat"); // overwrite the original free/wide into a mdat
9024 } else {
9025 /* overwrite 'wide' placeholder atom */
9026 avio_seek(pb, mov->mdat_pos - 8, SEEK_SET);
9027 /* special value: real atom size will be 64 bit value after
9028 * tag field */
9029 avio_wb32(pb, 1);
9030 ffio_wfourcc(pb, "mdat");
9031 avio_wb64(pb, mov->mdat_size + 16);
9032 }
9033}
9034
9036{
9037 MOVMuxContext *mov = s->priv_data;
9038 AVIOContext *pb = s->pb;
9039 int res = 0;
9040 int i;
9041 int64_t moov_pos;
9042
9043 /*
9044 * Before actually writing the trailer, make sure that there are no
9045 * dangling subtitles, that need a terminating sample.
9046 */
9047 for (i = 0; i < mov->nb_tracks; i++) {
9048 MOVTrack *trk = &mov->tracks[i];
9049 if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT &&
9053 }
9054 }
9055
9056 //Also check for a buffered EAC3 packet
9057 for (i = 0; i < mov->nb_tracks; i++) {
9058 MOVTrack *trk = &mov->tracks[i];
9059 if (trk->par->codec_id != AV_CODEC_ID_EAC3)
9060 continue;
9061 struct eac3_info *info = trk->eac3_priv;
9062 if (!info || !info->pkt || !info->pkt->size)
9063 continue;
9064
9065 av_packet_move_ref(mov->pkt, info->pkt);
9066 info->eof = 1;
9067 res = mov_write_single_packet(s, mov->pkt);
9068 if (res < 0)
9069 return res;
9070
9071 av_packet_unref(mov->pkt);
9072 }
9073
9074 // Check if we have any tracks that require squashing.
9075 // In that case, we'll have to write the packet here.
9076 if ((res = mov_write_squashed_packets(s)) < 0)
9077 return res;
9078
9079 // If there were no chapters when the header was written, but there
9080 // are chapters now, write them in the trailer. This only works
9081 // when we are not doing fragments.
9082 if (!mov->chapter_track && !(mov->flags & FF_MOV_FLAG_FRAGMENT)) {
9083 if (mov->mode & (MODE_MP4|MODE_MOV|MODE_IPOD) && s->nb_chapters) {
9084 mov->chapter_track = mov->nb_tracks++;
9085 if ((res = mov_create_chapter_track(s, mov->chapter_track)) < 0)
9086 return res;
9087 }
9088 }
9089
9090 if (!(mov->flags & FF_MOV_FLAG_FRAGMENT) ||
9094 mov->mdat_size = avio_tell(pb) - mov->mdat_pos - 8;
9095 for (i = 0; i < mov->nb_tracks; i++) {
9096 MOVTrack *track = &mov->tracks[i];
9097 track->data_offset = 0;
9098 av_free(track->cluster);
9099 track->cluster = track->cluster_written;
9100 track->entry = track->entry_written;
9101 track->cluster_written = NULL;
9102 track->entry_written = 0;
9103 track->chunkCount = 0; // Force build_chunks to rebuild the list of chunks
9104 }
9105 // Clear the empty_moov flag, as we do want the moov to include
9106 // all the samples at this point.
9108 }
9109
9110 moov_pos = avio_tell(pb);
9111
9114
9115 avio_seek(pb, mov->reserved_moov_size > 0 ? mov->reserved_header_pos : moov_pos, SEEK_SET);
9116
9117 if (mov->flags & FF_MOV_FLAG_FASTSTART) {
9118 av_log(s, AV_LOG_INFO, "Starting second pass: moving the moov atom to the beginning of the file\n");
9119 res = shift_data(s);
9120 if (res < 0)
9121 return res;
9122 avio_seek(pb, mov->reserved_header_pos, SEEK_SET);
9123 if ((res = mov_write_moov_tag(pb, mov, s)) < 0)
9124 return res;
9125 } else if (mov->reserved_moov_size > 0) {
9126 int64_t size;
9127 if ((res = mov_write_moov_tag(pb, mov, s)) < 0)
9128 return res;
9130 if (size < 8){
9131 av_log(s, AV_LOG_ERROR, "reserved_moov_size is too small, needed %"PRId64" additional\n", 8-size);
9132 return AVERROR(EINVAL);
9133 }
9134 avio_wb32(pb, size);
9135 ffio_wfourcc(pb, "free");
9136 ffio_fill(pb, 0, size - 8);
9137 avio_seek(pb, moov_pos, SEEK_SET);
9138 } else {
9139 if ((res = mov_write_moov_tag(pb, mov, s)) < 0)
9140 return res;
9141 }
9142
9144 // With hybrid fragmentation, only write the mdat size (hiding
9145 // the original moov and all the fragments within the mdat)
9146 // after we've successfully written the complete moov, to avoid
9147 // risk for an unreadable file if writing the final moov fails.
9149 }
9150
9151 res = 0;
9152 } else {
9154 for (i = 0; i < mov->nb_tracks; i++)
9155 mov->tracks[i].data_offset = 0;
9156 if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX) {
9157 int64_t end;
9158 av_log(s, AV_LOG_INFO, "Starting second pass: inserting sidx atoms\n");
9159 res = shift_data(s);
9160 if (res < 0)
9161 return res;
9162 end = avio_tell(pb);
9163 avio_seek(pb, mov->reserved_header_pos, SEEK_SET);
9164 mov_write_sidx_tags(pb, mov, -1, 0);
9165 avio_seek(pb, end, SEEK_SET);
9166 }
9167 if (!(mov->flags & FF_MOV_FLAG_SKIP_TRAILER)) {
9169 res = mov_write_mfra_tag(pb, mov);
9170 if (res < 0)
9171 return res;
9172 }
9173 }
9174
9175 return res;
9176}
9177
9179 const AVPacket *pkt)
9180{
9181 int ret = 1;
9182
9183 if (st->codecpar->codec_id == AV_CODEC_ID_AAC) {
9184 if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0)
9185 ret = ff_stream_add_bitstream_filter(st, "aac_adtstoasc", NULL);
9186 } else if (st->codecpar->codec_id == AV_CODEC_ID_VP9) {
9187 ret = ff_stream_add_bitstream_filter(st, "vp9_superframe", NULL);
9188 }
9189
9190 return ret;
9191}
9192
9193#if CONFIG_AVIF_MUXER
9194static int avif_write_trailer(AVFormatContext *s)
9195{
9196 AVIOContext *pb = s->pb;
9197 MOVMuxContext *mov = s->priv_data;
9198 int64_t pos_backup, extent_offsets[2];
9199 uint8_t *buf;
9200 int buf_size, moov_size;
9201
9202 if (mov->moov_written) return 0;
9203
9204 mov->is_animated_avif = s->streams[0]->nb_frames > 1;
9205 if (mov->is_animated_avif && mov->nb_streams > 1) {
9206 // For animated avif with alpha channel, we need to write a tref tag
9207 // with type "auxl".
9208 MovTag *tag = mov_add_tref_tag(mov, &mov->tracks[1], MKTAG('a', 'u', 'x', 'l'));
9209 if (!tag)
9210 return AVERROR(ENOMEM);
9211
9212 int ret = mov_add_tref_id(mov, tag, 1);
9213 if (ret < 0)
9214 return ret;
9215 }
9217 mov_write_meta_tag(pb, mov, s);
9218
9219 moov_size = get_moov_size(s);
9220 for (int i = 0; i < mov->nb_tracks; i++)
9221 mov->tracks[i].data_offset = avio_tell(pb) + moov_size + 8;
9222
9223 if (mov->is_animated_avif) {
9224 int ret;
9225 if ((ret = mov_write_moov_tag(pb, mov, s)) < 0)
9226 return ret;
9227 }
9228
9229 buf_size = avio_get_dyn_buf(mov->mdat_buf, &buf);
9230 avio_wb32(pb, buf_size + 8);
9231 ffio_wfourcc(pb, "mdat");
9232
9233 // The offset for the YUV planes is the starting position of mdat.
9234 extent_offsets[0] = avio_tell(pb);
9235 // The offset for alpha plane is YUV offset + YUV size.
9236 extent_offsets[1] = extent_offsets[0] + mov->avif_extent_length[0];
9237
9238 avio_write(pb, buf, buf_size);
9239
9240 // write extent offsets.
9241 pos_backup = avio_tell(pb);
9242 for (int i = 0; i < mov->nb_streams; i++) {
9243 if (extent_offsets[i] != (uint32_t)extent_offsets[i]) {
9244 av_log(s, AV_LOG_ERROR, "extent offset does not fit in 32 bits\n");
9245 return AVERROR_INVALIDDATA;
9246 }
9247 avio_seek(pb, mov->avif_extent_pos[i], SEEK_SET);
9248 avio_wb32(pb, extent_offsets[i]); /* rewrite offset */
9249 }
9250 avio_seek(pb, pos_backup, SEEK_SET);
9251
9252 return 0;
9253}
9254#endif
9255
9256#if CONFIG_TGP_MUXER || CONFIG_TG2_MUXER
9257static const AVCodecTag codec_3gp_tags[] = {
9258 { AV_CODEC_ID_H263, MKTAG('s','2','6','3') },
9259 { AV_CODEC_ID_H264, MKTAG('a','v','c','1') },
9260 { AV_CODEC_ID_MPEG4, MKTAG('m','p','4','v') },
9261 { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') },
9262 { AV_CODEC_ID_AMR_NB, MKTAG('s','a','m','r') },
9263 { AV_CODEC_ID_AMR_WB, MKTAG('s','a','w','b') },
9264 { AV_CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') },
9265 { AV_CODEC_ID_NONE, 0 },
9266};
9267static const AVCodecTag *const codec_3gp_tags_list[] = { codec_3gp_tags, NULL };
9268#endif
9269
9270static const AVCodecTag codec_mp4_tags[] = {
9271 { AV_CODEC_ID_MPEG4, MKTAG('m', 'p', '4', 'v') },
9272 { AV_CODEC_ID_H264, MKTAG('a', 'v', 'c', '1') },
9273 { AV_CODEC_ID_H264, MKTAG('a', 'v', 'c', '3') },
9274 { AV_CODEC_ID_HEVC, MKTAG('h', 'e', 'v', '1') },
9275 { AV_CODEC_ID_HEVC, MKTAG('h', 'v', 'c', '1') },
9276 { AV_CODEC_ID_HEVC, MKTAG('d', 'v', 'h', '1') },
9277 { AV_CODEC_ID_VVC, MKTAG('v', 'v', 'c', '1') },
9278 { AV_CODEC_ID_VVC, MKTAG('v', 'v', 'i', '1') },
9279 { AV_CODEC_ID_EVC, MKTAG('e', 'v', 'c', '1') },
9280 { AV_CODEC_ID_LCEVC, MKTAG('l', 'v', 'c', '1') },
9281 { AV_CODEC_ID_APV, MKTAG('a', 'p', 'v', '1') },
9282 { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'p', '4', 'v') },
9283 { AV_CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', '4', 'v') },
9284 { AV_CODEC_ID_MJPEG, MKTAG('m', 'p', '4', 'v') },
9285 { AV_CODEC_ID_PNG, MKTAG('m', 'p', '4', 'v') },
9286 { AV_CODEC_ID_JPEG2000, MKTAG('m', 'p', '4', 'v') },
9287 { AV_CODEC_ID_VC1, MKTAG('v', 'c', '-', '1') },
9288 { AV_CODEC_ID_DIRAC, MKTAG('d', 'r', 'a', 'c') },
9289 { AV_CODEC_ID_TSCC2, MKTAG('m', 'p', '4', 'v') },
9290 { AV_CODEC_ID_VP9, MKTAG('v', 'p', '0', '9') },
9291 { AV_CODEC_ID_AV1, MKTAG('a', 'v', '0', '1') },
9292 { AV_CODEC_ID_AAC, MKTAG('m', 'p', '4', 'a') },
9293 { AV_CODEC_ID_ALAC, MKTAG('a', 'l', 'a', 'c') },
9294 { AV_CODEC_ID_MP4ALS, MKTAG('m', 'p', '4', 'a') },
9295 { AV_CODEC_ID_MP3, MKTAG('m', 'p', '4', 'a') },
9296 { AV_CODEC_ID_MP2, MKTAG('m', 'p', '4', 'a') },
9297 { AV_CODEC_ID_AC3, MKTAG('a', 'c', '-', '3') },
9298 { AV_CODEC_ID_EAC3, MKTAG('e', 'c', '-', '3') },
9299 { AV_CODEC_ID_DTS, MKTAG('m', 'p', '4', 'a') },
9300 { AV_CODEC_ID_TRUEHD, MKTAG('m', 'l', 'p', 'a') },
9301 { AV_CODEC_ID_FLAC, MKTAG('f', 'L', 'a', 'C') },
9302 { AV_CODEC_ID_OPUS, MKTAG('O', 'p', 'u', 's') },
9303 { AV_CODEC_ID_VORBIS, MKTAG('m', 'p', '4', 'a') },
9304 { AV_CODEC_ID_QCELP, MKTAG('m', 'p', '4', 'a') },
9305 { AV_CODEC_ID_EVRC, MKTAG('m', 'p', '4', 'a') },
9306 { AV_CODEC_ID_DVD_SUBTITLE, MKTAG('m', 'p', '4', 's') },
9307 { AV_CODEC_ID_MOV_TEXT, MKTAG('t', 'x', '3', 'g') },
9308 { AV_CODEC_ID_BIN_DATA, MKTAG('g', 'p', 'm', 'd') },
9309 { AV_CODEC_ID_MPEGH_3D_AUDIO, MKTAG('m', 'h', 'm', '1') },
9312 { AV_CODEC_ID_FFV1, MKTAG('F', 'F', 'V', '1') },
9313
9314 /* ISO/IEC 23003-5 integer formats */
9321 /* ISO/IEC 23003-5 floating-point formats */
9326
9327 { AV_CODEC_ID_AVS3, MKTAG('a', 'v', 's', '3') },
9328
9329 { AV_CODEC_ID_NONE, 0 },
9330};
9331#if CONFIG_MP4_MUXER || CONFIG_PSP_MUXER
9332static const AVCodecTag *const mp4_codec_tags_list[] = { codec_mp4_tags, NULL };
9333#endif
9334
9335static const AVCodecTag codec_ism_tags[] = {
9336 { AV_CODEC_ID_WMAPRO , MKTAG('w', 'm', 'a', ' ') },
9338 { AV_CODEC_ID_NONE , 0 },
9339};
9340
9341static const AVCodecTag codec_ipod_tags[] = {
9342 { AV_CODEC_ID_H264, MKTAG('a','v','c','1') },
9343 { AV_CODEC_ID_MPEG4, MKTAG('m','p','4','v') },
9344 { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') },
9345 { AV_CODEC_ID_ALAC, MKTAG('a','l','a','c') },
9346 { AV_CODEC_ID_AC3, MKTAG('a','c','-','3') },
9347 { AV_CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') },
9348 { AV_CODEC_ID_MOV_TEXT, MKTAG('t','e','x','t') },
9349 { AV_CODEC_ID_NONE, 0 },
9350};
9351
9352static const AVCodecTag codec_f4v_tags[] = {
9353 { AV_CODEC_ID_MP3, MKTAG('.','m','p','3') },
9354 { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') },
9355 { AV_CODEC_ID_H264, MKTAG('a','v','c','1') },
9356 { AV_CODEC_ID_VP6A, MKTAG('V','P','6','A') },
9357 { AV_CODEC_ID_VP6F, MKTAG('V','P','6','F') },
9358 { AV_CODEC_ID_NONE, 0 },
9359};
9360
9361#if CONFIG_AVIF_MUXER
9362
9363static const AVOption avif_options[] = {
9364 { "movie_timescale", "set movie timescale", offsetof(MOVMuxContext, movie_timescale), AV_OPT_TYPE_INT, {.i64 = MOV_TIMESCALE}, 1, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
9365 { "loop", "Number of times to loop animated AVIF: 0 - infinite loop", offsetof(MOVMuxContext, avif_loop_count), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, .unit = 0 },
9366 { NULL },
9367};
9368static const AVCodecTag codec_avif_tags[] = {
9369 { AV_CODEC_ID_AV1, MKTAG('a','v','0','1') },
9370 { AV_CODEC_ID_NONE, 0 },
9371};
9372static const AVCodecTag *const codec_avif_tags_list[] = { codec_avif_tags, NULL };
9373
9374static const AVClass mov_avif_muxer_class = {
9375 .class_name = "avif muxer",
9376 .item_name = av_default_item_name,
9377 .option = avif_options,
9378 .version = LIBAVUTIL_VERSION_INT,
9379};
9380#endif
9381
9382#if CONFIG_MOV_MUXER
9384 .p.name = "mov",
9385 .p.long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
9386 .p.extensions = "mov",
9387 .priv_data_size = sizeof(MOVMuxContext),
9388 .p.audio_codec = AV_CODEC_ID_AAC,
9389 .p.video_codec = CONFIG_LIBX264_ENCODER ?
9391 .init = mov_init,
9395 .deinit = mov_free,
9397 .p.codec_tag = (const AVCodecTag* const []){
9399 },
9400 .check_bitstream = mov_check_bitstream,
9401 .p.priv_class = &mov_isobmff_muxer_class,
9402 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
9403};
9404#endif
9405#if CONFIG_TGP_MUXER
9407 .p.name = "3gp",
9408 .p.long_name = NULL_IF_CONFIG_SMALL("3GP (3GPP file format)"),
9409 .p.extensions = "3gp",
9410 .priv_data_size = sizeof(MOVMuxContext),
9411 .p.audio_codec = AV_CODEC_ID_AMR_NB,
9412 .p.video_codec = AV_CODEC_ID_H263,
9413 .init = mov_init,
9414 .write_header = mov_write_header,
9415 .write_packet = mov_write_packet,
9416 .write_trailer = mov_write_trailer,
9417 .deinit = mov_free,
9419 .p.codec_tag = codec_3gp_tags_list,
9420 .check_bitstream = mov_check_bitstream,
9421 .p.priv_class = &mov_isobmff_muxer_class,
9422 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
9423};
9424#endif
9425#if CONFIG_MP4_MUXER
9427 .p.name = "mp4",
9428 .p.long_name = NULL_IF_CONFIG_SMALL("MP4 (MPEG-4 Part 14)"),
9429 .p.mime_type = "video/mp4",
9430 .p.extensions = "mp4",
9431 .priv_data_size = sizeof(MOVMuxContext),
9432 .p.audio_codec = AV_CODEC_ID_AAC,
9433 .p.video_codec = CONFIG_LIBX264_ENCODER ?
9435 .init = mov_init,
9439 .deinit = mov_free,
9441 .p.codec_tag = mp4_codec_tags_list,
9443 .p.priv_class = &mov_isobmff_muxer_class,
9444 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
9445};
9446#endif
9447#if CONFIG_PSP_MUXER
9449 .p.name = "psp",
9450 .p.long_name = NULL_IF_CONFIG_SMALL("PSP MP4 (MPEG-4 Part 14)"),
9451 .p.extensions = "mp4,psp",
9452 .priv_data_size = sizeof(MOVMuxContext),
9453 .p.audio_codec = AV_CODEC_ID_AAC,
9454 .p.video_codec = CONFIG_LIBX264_ENCODER ?
9456 .init = mov_init,
9460 .deinit = mov_free,
9462 .p.codec_tag = mp4_codec_tags_list,
9464 .p.priv_class = &mov_isobmff_muxer_class,
9465 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
9466};
9467#endif
9468#if CONFIG_TG2_MUXER
9470 .p.name = "3g2",
9471 .p.long_name = NULL_IF_CONFIG_SMALL("3GP2 (3GPP2 file format)"),
9472 .p.extensions = "3g2",
9473 .priv_data_size = sizeof(MOVMuxContext),
9474 .p.audio_codec = AV_CODEC_ID_AMR_NB,
9475 .p.video_codec = AV_CODEC_ID_H263,
9476 .init = mov_init,
9477 .write_header = mov_write_header,
9478 .write_packet = mov_write_packet,
9479 .write_trailer = mov_write_trailer,
9480 .deinit = mov_free,
9482 .p.codec_tag = codec_3gp_tags_list,
9483 .check_bitstream = mov_check_bitstream,
9484 .p.priv_class = &mov_isobmff_muxer_class,
9485 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
9486};
9487#endif
9488#if CONFIG_IPOD_MUXER
9490 .p.name = "ipod",
9491 .p.long_name = NULL_IF_CONFIG_SMALL("iPod H.264 MP4 (MPEG-4 Part 14)"),
9492 .p.mime_type = "video/mp4",
9493 .p.extensions = "m4v,m4a,m4b",
9494 .priv_data_size = sizeof(MOVMuxContext),
9495 .p.audio_codec = AV_CODEC_ID_AAC,
9496 .p.video_codec = AV_CODEC_ID_H264,
9497 .init = mov_init,
9498 .write_header = mov_write_header,
9499 .write_packet = mov_write_packet,
9500 .write_trailer = mov_write_trailer,
9501 .deinit = mov_free,
9503 .p.codec_tag = (const AVCodecTag* const []){ codec_ipod_tags, 0 },
9504 .check_bitstream = mov_check_bitstream,
9505 .p.priv_class = &mov_isobmff_muxer_class,
9506 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
9507};
9508#endif
9509#if CONFIG_ISMV_MUXER
9511 .p.name = "ismv",
9512 .p.long_name = NULL_IF_CONFIG_SMALL("ISMV/ISMA (Smooth Streaming)"),
9513 .p.mime_type = "video/mp4",
9514 .p.extensions = "ismv,isma",
9515 .priv_data_size = sizeof(MOVMuxContext),
9516 .p.audio_codec = AV_CODEC_ID_AAC,
9517 .p.video_codec = AV_CODEC_ID_H264,
9518 .init = mov_init,
9519 .write_header = mov_write_header,
9520 .write_packet = mov_write_packet,
9521 .write_trailer = mov_write_trailer,
9522 .deinit = mov_free,
9524 .p.codec_tag = (const AVCodecTag* const []){
9526 .check_bitstream = mov_check_bitstream,
9527 .p.priv_class = &mov_isobmff_muxer_class,
9528 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
9529};
9530#endif
9531#if CONFIG_F4V_MUXER
9533 .p.name = "f4v",
9534 .p.long_name = NULL_IF_CONFIG_SMALL("F4V Adobe Flash Video"),
9535 .p.mime_type = "application/f4v",
9536 .p.extensions = "f4v",
9537 .priv_data_size = sizeof(MOVMuxContext),
9538 .p.audio_codec = AV_CODEC_ID_AAC,
9539 .p.video_codec = AV_CODEC_ID_H264,
9540 .init = mov_init,
9541 .write_header = mov_write_header,
9542 .write_packet = mov_write_packet,
9543 .write_trailer = mov_write_trailer,
9544 .deinit = mov_free,
9545 .p.flags = AVFMT_GLOBALHEADER,
9546 .p.codec_tag = (const AVCodecTag* const []){ codec_f4v_tags, 0 },
9547 .check_bitstream = mov_check_bitstream,
9548 .p.priv_class = &mov_isobmff_muxer_class,
9549 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
9550};
9551#endif
9552#if CONFIG_AVIF_MUXER
9554 .p.name = "avif",
9555 .p.long_name = NULL_IF_CONFIG_SMALL("AVIF"),
9556 .p.mime_type = "image/avif",
9557 .p.extensions = "avif",
9558 .priv_data_size = sizeof(MOVMuxContext),
9559 .p.video_codec = AV_CODEC_ID_AV1,
9560 .init = mov_init,
9561 .write_header = mov_write_header,
9562 .write_packet = mov_write_packet,
9563 .write_trailer = avif_write_trailer,
9564 .deinit = mov_free,
9565 .p.flags = AVFMT_GLOBALHEADER,
9566 .p.codec_tag = codec_avif_tags_list,
9567 .p.priv_class = &mov_avif_muxer_class,
9568 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
9569};
9570#endif
int avpriv_ac3_parse_header(AC3HeaderInfo **phdr, const uint8_t *buf, size_t size)
Definition ac3_parser.c:491
@ EAC3_FRAME_TYPE_DEPENDENT
Definition ac3defs.h:112
@ EAC3_FRAME_TYPE_INDEPENDENT
Definition ac3defs.h:111
@ EAC3_FRAME_TYPE_AC3_CONVERT
Definition ac3defs.h:113
static double val(void *priv, double ch)
Definition aeval.c:77
const FFOutputFormat ff_avif_muxer
const FFOutputFormat ff_psp_muxer
const FFOutputFormat ff_tg2_muxer
const FFOutputFormat ff_mp4_muxer
const FFOutputFormat ff_f4v_muxer
const FFOutputFormat ff_mov_muxer
const FFOutputFormat ff_ipod_muxer
const FFOutputFormat ff_ismv_muxer
const FFOutputFormat ff_tgp_muxer
#define entry
static AVStream * video_st
static AVFormatContext * ctx
channels
Definition aptx.h:31
static const uint8_t channel_map[8][8]
int32_t
int ff_av1_filter_obus_buf(const uint8_t *in, uint8_t **out, int *size, int *offset)
Filter out AV1 OBUs not meant to be present in ISOBMFF sample data and return the result in a data bu...
Definition av1.c:88
int ff_isom_write_av1c(AVIOContext *pb, const uint8_t *buf, int size, int write_seq_header)
Writes AV1 extradata (Sequence Header and Metadata OBUs) to the provided AVIOContext.
Definition av1.c:399
int ff_av1_filter_obus(AVIOContext *pb, const uint8_t *buf, int size)
Filter out AV1 OBUs not meant to be present in ISOBMFF sample data and write the resulting bitstream ...
Definition av1.c:83
#define av_assert2(cond)
assert() equivalent, that does lie in speed critical code.
Definition avassert.h:68
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
Definition avassert.h:58
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition avassert.h:42
int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len)
Definition avc.c:32
int ff_avc_write_annexb_extradata(const uint8_t *in, uint8_t **buf, int *size)
Definition avc.c:145
void avpriv_set_pts_info(AVStream *st, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
Definition avformat.c:834
Main libavformat public API header.
#define AVFMT_FLAG_BITEXACT
When muxing, try to avoid writing any random/volatile data to the output.
Definition avformat.h:1501
#define AV_DISPOSITION_HEARING_IMPAIRED
The stream is intended for hearing impaired audiences.
Definition avformat.h:676
@ AV_STREAM_GROUP_PARAMS_TREF
Definition avformat.h:1152
@ AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION
Definition avformat.h:1149
@ AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT
Definition avformat.h:1148
@ AV_STREAM_GROUP_PARAMS_LCEVC
Definition avformat.h:1151
#define AVFMT_VARIABLE_FPS
Format allows variable fps.
Definition avformat.h:501
#define AV_DISPOSITION_MULTILAYER
The video stream contains multiple layers, e.g.
Definition avformat.h:736
#define AVFMT_TS_NEGATIVE
Format allows muxing negative timestamps.
Definition avformat.h:510
#define AVFMT_AVOID_NEG_TS_AUTO
Enabled when required by target format.
Definition avformat.h:1738
#define AVFMT_FLAG_AUTO_BSF
Add bitstream filters as requested by the muxer.
Definition avformat.h:1504
#define AV_DISPOSITION_VISUAL_IMPAIRED
The stream is intended for visually impaired audiences.
Definition avformat.h:680
#define AVFMT_GLOBALHEADER
Format wants global header.
Definition avformat.h:497
#define AV_DISPOSITION_ATTACHED_PIC
The stream is stored in the file as an attached picture/"cover art" (e.g.
Definition avformat.h:692
#define AVFMT_AVOID_NEG_TS_MAKE_ZERO
Shift timestamps so that they start at 0.
Definition avformat.h:1741
#define AV_DISPOSITION_DEFAULT
The stream should be chosen by default among other streams of the same type, unless the user has expl...
Definition avformat.h:639
Buffered I/O operations.
void avio_write_marker(AVIOContext *s, int64_t time, enum AVIODataMarkerType type)
Mark the written bytestream as a specific type.
Definition aviobuf.c:464
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition aviobuf.c:236
#define AVIO_SEEKABLE_NORMAL
Seeking works like for a local file.
Definition avio.h:41
void avio_wl32(AVIOContext *s, unsigned int val)
Definition aviobuf.c:360
int avio_put_str(AVIOContext *s, const char *str)
Write a NULL-terminated string.
Definition aviobuf.c:376
void avio_w8(AVIOContext *s, int b)
Definition aviobuf.c:184
void avio_wb32(AVIOContext *s, unsigned int val)
Definition aviobuf.c:368
void avio_wb16(AVIOContext *s, unsigned int val)
Definition aviobuf.c:446
@ AVIO_DATA_MARKER_BOUNDARY_POINT
A point in the output bytestream where a demuxer can start parsing (for non self synchronizing bytest...
Definition avio.h:127
@ AVIO_DATA_MARKER_TRAILER
Trailer data, which doesn't contain actual content, but only for finalizing the output file.
Definition avio.h:139
@ AVIO_DATA_MARKER_HEADER
Header data; this needs to be present for the stream to be decodeable.
Definition avio.h:114
@ AVIO_DATA_MARKER_FLUSH_POINT
A point in the output bytestream where the underlying AVIOContext might flush the buffer depending on...
Definition avio.h:145
@ AVIO_DATA_MARKER_SYNC_POINT
A point in the output bytestream where a decoder can start decoding (i.e.
Definition avio.h:121
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition avio.h:494
int avio_printf(AVIOContext *s, const char *fmt,...) av_printf_format(2
Writes a formatted string to the context.
void avio_wb24(AVIOContext *s, unsigned int val)
Definition aviobuf.c:458
int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
Return the written size and a pointer to the buffer.
Definition aviobuf.c:1410
void avio_wb64(AVIOContext *s, uint64_t val)
Definition aviobuf.c:434
int64_t avio_skip(AVIOContext *s, int64_t offset)
Skip given number of bytes forward.
Definition aviobuf.c:321
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
Definition aviobuf.c:206
void avio_flush(AVIOContext *s)
Force flushing of buffered data.
Definition aviobuf.c:228
int avio_open_dyn_buf(AVIOContext **s)
Open a write only memory stream.
Definition aviobuf.c:1365
int avio_get_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
Return the written size and a pointer to the buffer.
Definition aviobuf.c:1377
void ffio_free_dyn_buf(AVIOContext **s)
Free a dynamic buffer.
Definition aviobuf.c:1438
static av_always_inline void ffio_wfourcc(AVIOContext *pb, const uint8_t *s)
void ffio_reset_dyn_buf(AVIOContext *s)
Reset a dynamic buffer.
Definition aviobuf.c:1399
void ffio_write_leb(AVIOContext *s, unsigned val)
Definition aviobuf.c:947
int ffio_open_null_buf(AVIOContext **s)
Open a write-only fake memory stream.
Definition aviobuf.c:1462
void ffio_fill(AVIOContext *s, int b, int64_t count)
Definition aviobuf.c:192
int ffio_close_null_buf(AVIOContext *s)
Close a null buffer.
Definition aviobuf.c:1472
size_t av_strlcatf(char *dst, size_t size, const char *fmt,...)
Definition avstring.c:103
static int BS_FUNC left(const BSCTX *bc)
Return the number of the bits left in a buffer.
static int FUNC metadata(CodedBitstreamContext *ctx, RWContext *rw, APVRawMetadata *current)
#define flag(name)
Definition cbs_h264.c:60
#define flags(name, subs,...)
Definition cbs_h264.c:74
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define s(width, name)
Definition cbs_vp9.c:198
Public libavutil channel layout APIs header.
static void deinit(AVFormatContext *s)
Definition chromaprint.c:53
AVCodecParameters * avcodec_parameters_alloc(void)
Definition codec_par.c:57
void avcodec_parameters_free(AVCodecParameters **ppar)
Definition codec_par.c:67
#define GET_UTF8(val, GET_BYTE, ERROR)
Convert a UTF-8 character (up to 4 bytes) to its 32-bit UCS-4 encoded form.
Definition common.h:477
#define ROUNDED_DIV(a, b)
Definition common.h:58
#define av_clip_uint8
Definition common.h:106
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
Colorspace value utility functions for libavutil.
#define max(a, b)
#define FF_COMPLIANCE_UNOFFICIAL
Allow unofficial extensions.
Definition defs.h:61
#define AV_PROFILE_AAC_HE
Definition defs.h:72
#define FF_COMPLIANCE_EXPERIMENTAL
Allow nonstandardized experimental things.
Definition defs.h:62
#define AV_PROFILE_UNKNOWN
Definition defs.h:65
#define FF_COMPLIANCE_NORMAL
Definition defs.h:60
#define AV_PROFILE_AAC_HE_V2
Definition defs.h:73
#define AV_PROFILE_H264_INTRA
Definition defs.h:108
@ AV_FIELD_UNKNOWN
Definition defs.h:212
@ AV_FIELD_PROGRESSIVE
Definition defs.h:213
#define AV_PROFILE_AAC_USAC
Definition defs.h:76
#define AV_PROFILE_DNXHD
Definition defs.h:80
static AVPacket * pkt
static enum AVPixelFormat pix_fmt
Public dictionary API.
static av_always_inline uint64_t ff_dnxhd_parse_header_prefix(const uint8_t *buf)
Definition dnxhddata.h:85
void ff_isom_put_dvcc_dvvc(void *logctx, uint8_t out[ISOM_DVCC_DVVC_SIZE], const AVDOVIDecoderConfigurationRecord *dovi)
Definition dovi_isom.c:89
#define ISOM_DVCC_DVVC_SIZE
Definition dovi_isom.h:29
DOVI configuration.
enum AVCodecID id
Definition dts2pts.c:607
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
AVEncryptionInitInfo * av_encryption_init_info_get_side_data(const uint8_t *side_data, size_t side_data_size)
Creates a copy of the AVEncryptionInitInfo that is contained in the given side data.
void av_encryption_init_info_free(AVEncryptionInitInfo *info)
Frees the given encryption init info object.
double value
Definition eval.c:102
int ff_isom_write_evcc(AVIOContext *pb, const uint8_t *data, int size, int ps_array_completeness)
Writes EVC sample metadata to the provided AVIOContext.
Definition evc.c:298
static int write_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt)
Definition ffmpeg_mux.c:204
const char * key
static int64_t duration
Definition ffplay.c:330
static unsigned int nb_streams
Definition ffprobe.c:352
static void write_header(FFV1Context *f)
Definition ffv1enc.c:384
FLAC (Free Lossless Audio Codec) common stuff.
@ FLAC_METADATA_TYPE_STREAMINFO
Definition flac.h:46
#define FLAC_STREAMINFO_SIZE
Definition flac.h:32
bitstream reader API header.
static void skip_bits_long(GetBitContext *s, int n)
Skips the specified number of bits.
Definition get_bits.h:280
static unsigned int get_bits1(GetBitContext *s)
Definition get_bits.h:391
static void skip_bits(GetBitContext *s, int n)
Definition get_bits.h:383
static unsigned int get_bits(GetBitContext *s, int n)
Read 1-25 bits.
Definition get_bits.h:337
static int init_get_bits(GetBitContext *s, const uint8_t *buffer, int bit_size)
Initialize GetBitContext.
Definition get_bits.h:517
#define fail
Definition test.h:479
#define AV_OPT_FLAG_ENCODING_PARAM
A generic parameter which can be set by the user for muxing or encoding.
Definition opt.h:351
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
Definition opt.h:298
@ AV_OPT_TYPE_BINARY
Underlying C type is a uint8_t* that is either NULL or points to an array allocated with the av_mallo...
Definition opt.h:285
@ AV_OPT_TYPE_FLAGS
Underlying C type is unsigned int.
Definition opt.h:254
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition opt.h:258
@ AV_OPT_TYPE_FLOAT
Underlying C type is float.
Definition opt.h:270
@ AV_OPT_TYPE_BOOL
Underlying C type is int.
Definition opt.h:326
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
Definition opt.h:275
#define AV_CH_LAYOUT_STEREO
int av_get_bits_per_sample(enum AVCodecID codec_id)
Return codec bits per sample.
Definition utils.c:556
const char * avcodec_get_name(enum AVCodecID id)
Get the name of a codec.
Definition utils.c:421
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition codec_id.h:47
int av_get_exact_bits_per_sample(enum AVCodecID codec_id)
Return codec bits per sample.
Definition utils.c:461
@ AV_CODEC_ID_DIRAC
Definition codec_id.h:166
@ AV_CODEC_ID_PCM_F32LE
Definition codec_id.h:351
@ AV_CODEC_ID_PCM_S24BE
Definition codec_id.h:343
@ AV_CODEC_ID_AVS3
Definition codec_id.h:245
@ AV_CODEC_ID_VORBIS
Definition codec_id.h:458
@ AV_CODEC_ID_V210
Definition codec_id.h:177
@ AV_CODEC_ID_TIMED_ID3
Definition codec_id.h:606
@ AV_CODEC_ID_PNG
Definition codec_id.h:111
@ AV_CODEC_ID_VP6F
Definition codec_id.h:142
@ AV_CODEC_ID_EAC3
Definition codec_id.h:493
@ AV_CODEC_ID_RAWVIDEO
Definition codec_id.h:63
@ AV_CODEC_ID_PCM_U8
Definition codec_id.h:335
@ AV_CODEC_ID_APV
Definition codec_id.h:323
@ AV_CODEC_ID_LCEVC
Definition codec_id.h:609
@ AV_CODEC_ID_PCM_S16LE
Definition codec_id.h:330
@ AV_CODEC_ID_DVD_SUBTITLE
Definition codec_id.h:566
@ AV_CODEC_ID_TTML
Definition codec_id.h:590
@ AV_CODEC_ID_PCM_F32BE
Definition codec_id.h:350
@ AV_CODEC_ID_MP4ALS
Definition codec_id.h:498
@ AV_CODEC_ID_SVQ3
Definition codec_id.h:73
@ AV_CODEC_ID_H264
Definition codec_id.h:77
@ AV_CODEC_ID_NONE
Definition codec_id.h:48
@ AV_CODEC_ID_EVRC
Definition codec_id.h:524
@ AV_CODEC_ID_JPEG2000
Definition codec_id.h:138
@ AV_CODEC_ID_PCM_S16BE
Definition codec_id.h:331
@ AV_CODEC_ID_PCM_S24LE
Definition codec_id.h:342
@ AV_CODEC_ID_VVC
Definition codec_id.h:247
@ AV_CODEC_ID_FFV1
Definition codec_id.h:83
@ AV_CODEC_ID_PCM_S32LE
Definition codec_id.h:338
@ AV_CODEC_ID_PCM_S8
Definition codec_id.h:334
@ AV_CODEC_ID_AV1
Definition codec_id.h:275
@ AV_CODEC_ID_ADPCM_MS
Definition codec_id.h:376
@ AV_CODEC_ID_VC1
Definition codec_id.h:120
@ AV_CODEC_ID_VP8
Definition codec_id.h:190
@ AV_CODEC_ID_MPEGH_3D_AUDIO
Definition codec_id.h:544
@ AV_CODEC_ID_PCM_F64LE
Definition codec_id.h:353
@ AV_CODEC_ID_ALAC
Definition codec_id.h:469
@ AV_CODEC_ID_EIA_608
Definition codec_id.h:576
@ AV_CODEC_ID_AMR_NB
Definition codec_id.h:434
@ AV_CODEC_ID_VP6A
Definition codec_id.h:156
@ AV_CODEC_ID_MP2
Definition codec_id.h:453
@ AV_CODEC_ID_DVVIDEO
Definition codec_id.h:74
@ AV_CODEC_ID_ADPCM_IMA_QT
Definition codec_id.h:370
@ AV_CODEC_ID_DTS
Definition codec_id.h:457
@ AV_CODEC_ID_HEVC
Definition codec_id.h:223
@ AV_CODEC_ID_BIN_DATA
Definition codec_id.h:607
@ AV_CODEC_ID_ADPCM_G726
Definition codec_id.h:381
@ AV_CODEC_ID_AAC
Definition codec_id.h:455
@ AV_CODEC_ID_TRUEHD
Definition codec_id.h:497
@ AV_CODEC_ID_FLAC
Definition codec_id.h:465
@ AV_CODEC_ID_BMP
Definition codec_id.h:128
@ AV_CODEC_ID_PCM_F64BE
Definition codec_id.h:352
@ AV_CODEC_ID_H263
Definition codec_id.h:54
@ AV_CODEC_ID_QCELP
Definition codec_id.h:477
@ AV_CODEC_ID_AMR_WB
Definition codec_id.h:435
@ AV_CODEC_ID_AC3
Definition codec_id.h:456
@ AV_CODEC_ID_TSCC2
Definition codec_id.h:213
@ AV_CODEC_ID_QDM2
Definition codec_id.h:472
@ AV_CODEC_ID_PCM_S32BE
Definition codec_id.h:339
@ AV_CODEC_ID_DNXHD
Definition codec_id.h:149
@ AV_CODEC_ID_MPEG4
Definition codec_id.h:62
@ AV_CODEC_ID_MJPEG
Definition codec_id.h:57
@ AV_CODEC_ID_ADPCM_IMA_WAV
Definition codec_id.h:371
@ AV_CODEC_ID_R10K
Definition codec_id.h:195
@ AV_CODEC_ID_EVC
Definition codec_id.h:316
@ AV_CODEC_ID_AVUI
Definition codec_id.h:252
@ AV_CODEC_ID_ILBC
Definition codec_id.h:512
@ AV_CODEC_ID_MP3
preferred ID for decoding MPEG audio layer 1, 2 or 3
Definition codec_id.h:454
@ AV_CODEC_ID_VP9
Definition codec_id.h:217
@ AV_CODEC_ID_MPEG1VIDEO
Definition codec_id.h:51
@ AV_CODEC_ID_OPUS
Definition codec_id.h:513
@ AV_CODEC_ID_MPEG2VIDEO
preferred ID for MPEG-1/2 video decoding
Definition codec_id.h:52
@ AV_CODEC_ID_WMAPRO
Definition codec_id.h:490
@ AV_CODEC_ID_MOV_TEXT
Definition codec_id.h:571
#define AV_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding.
Definition defs.h:40
const AVPacketSideData * av_packet_side_data_get(const AVPacketSideData *sd, int nb_sd, enum AVPacketSideDataType type)
Get side information from a side data array.
Definition packet.c:570
@ AV_PKT_DATA_HEVC_CONF
Dolby Vision enhancement-layer HEVC decoder configuration.
Definition packet.h:384
@ AV_PKT_DATA_AMBIENT_VIEWING_ENVIRONMENT
Ambient viewing environment metadata, as defined by H.274.
Definition packet.h:327
@ AV_PKT_DATA_SKIP_SAMPLES
Recommends skipping the specified number of samples.
Definition packet.h:153
@ AV_PKT_DATA_PRFT
Producer Reference Time data corresponding to the AVProducerReferenceTime struct, usually exported by...
Definition packet.h:265
@ AV_PKT_DATA_ICC_PROFILE
ICC profile data consisting of an opaque octet buffer following the format described by ISO 15076-1.
Definition packet.h:271
@ AV_PKT_DATA_MASTERING_DISPLAY_METADATA
Mastering display metadata (based on SMPTE-2086:2014).
Definition packet.h:219
@ AV_PKT_DATA_SPHERICAL
This side data should be associated with a video stream and corresponds to the AVSphericalMapping str...
Definition packet.h:225
@ AV_PKT_DATA_DISPLAYMATRIX
This side data contains a 3x3 transformation matrix describing an affine transformation that needs to...
Definition packet.h:105
@ AV_PKT_DATA_ENCRYPTION_INIT_INFO
This side data is encryption initialization data.
Definition packet.h:246
@ AV_PKT_DATA_CPB_PROPERTIES
This side data corresponds to the AVCPBProperties struct.
Definition packet.h:142
@ AV_PKT_DATA_NEW_EXTRADATA
The AV_PKT_DATA_NEW_EXTRADATA is used to notify the codec or the format that the extradata buffer was...
Definition packet.h:56
@ AV_PKT_DATA_STEREO3D
This side data should be associated with a video stream and contains Stereoscopic 3D information in f...
Definition packet.h:111
@ AV_PKT_DATA_FRAME_CROPPING
The number of pixels to discard from the top/bottom/left/right border of the decoded frame to obtain ...
Definition packet.h:340
@ AV_PKT_DATA_CONTENT_LIGHT_LEVEL
Content light level (based on CTA-861.3).
Definition packet.h:232
@ AV_PKT_DATA_FALLBACK_TRACK
This side data contains an integer value representing the stream index of a "fallback" track.
Definition packet.h:137
@ AV_PKT_DATA_DOVI_CONF
DOVI configuration ref: dolby-vision-bitstreams-within-the-iso-base-media-file-format-v2....
Definition packet.h:280
void av_packet_free(AVPacket **pkt)
Free the packet, if the packet is reference counted, it will be unreferenced first.
Definition packet.c:74
#define AV_PKT_FLAG_DISCARD
Flag is used to discard packets which are required to maintain valid decoder state but are not requir...
Definition packet.h:657
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition packet.c:434
uint8_t * av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type, size_t size)
Allocate new information of a packet.
Definition packet.c:231
int av_grow_packet(AVPacket *pkt, int grow_by)
Increase packet size, correctly zeroing padding.
Definition packet.c:121
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition packet.h:650
#define AV_PKT_FLAG_DISPOSABLE
Flag is used to indicate packets that contain frames that can be discarded by the decoder.
Definition packet.h:669
void av_packet_move_ref(AVPacket *dst, AVPacket *src)
Move every field in src to dst and reset src.
Definition packet.c:491
int av_packet_make_writable(AVPacket *pkt)
Create a writable reference for the data described by a given packet, avoiding data copy if possible.
Definition packet.c:516
uint8_t * av_packet_get_side_data(const AVPacket *pkt, enum AVPacketSideDataType type, size_t *size)
Get side information from packet.
Definition packet.c:252
AVPacket * av_packet_alloc(void)
Allocate an AVPacket and set its fields to default values.
Definition packet.c:63
int av_packet_ref(AVPacket *dst, const AVPacket *src)
Setup a new reference to the data described by a given packet.
Definition packet.c:442
int av_match_ext(const char *filename, const char *extensions)
Return a positive value if the given filename has one of the given extensions, 0 otherwise.
Definition format.c:41
#define AES_CTR_KEY_SIZE
Definition aes_ctr.h:35
int av_channel_layout_from_string(AVChannelLayout *channel_layout, const char *str)
Initialize a channel layout from a given string description.
int av_channel_layout_ambisonic_order(const AVChannelLayout *channel_layout)
Return the order if the layout is n-th order standard-order ambisonic.
int av_channel_layout_compare(const AVChannelLayout *chl, const AVChannelLayout *chl1)
Check whether two channel layouts are semantically the same, i.e.
#define AV_CHANNEL_LAYOUT_MONO
enum AVChannel av_channel_layout_channel_from_index(const AVChannelLayout *channel_layout, unsigned int idx)
Get the channel with the given index in a channel layout.
void av_channel_layout_uninit(AVChannelLayout *channel_layout)
Free any allocated data in the channel layout and reset the channel count to 0.
int av_channel_layout_describe(const AVChannelLayout *channel_layout, char *buf, size_t buf_size)
Get a human-readable string describing the channel layout properties.
uint64_t av_channel_layout_subset(const AVChannelLayout *channel_layout, uint64_t mask)
Find out what channels from a given set are present in a channel layout, without regard for their pos...
@ AV_CHAN_AMBISONIC_BASE
Range of channels between AV_CHAN_AMBISONIC_BASE and AV_CHAN_AMBISONIC_END represent Ambisonic compon...
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
Definition buffer.c:139
AVBufferRef * av_buffer_create(uint8_t *data, size_t size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
Definition buffer.c:55
AVDictionaryEntry * av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
Definition dict.c:60
#define AV_DICT_IGNORE_SUFFIX
Return first entry in a dictionary whose first part corresponds to the search key,...
Definition dict.h:75
const AVDictionaryEntry * av_dict_iterate(const AVDictionary *m, const AVDictionaryEntry *prev)
Iterate over a dictionary.
Definition dict.c:42
#define AVERROR_EXPERIMENTAL
Requested feature is flagged experimental. Set strict_std_compliance if you really want to use it.
Definition error.h:74
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition error.h:64
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition error.h:52
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition error.h:61
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition error.h:122
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition log.h:231
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition log.h:216
#define AV_LOG_VERBOSE
Detailed information.
Definition log.h:226
#define AV_LOG_INFO
Standard information.
Definition log.h:221
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
const char * av_default_item_name(void *ptr)
Return the context name.
Definition log.c:241
double av_csp_approximate_eotf_gamma(enum AVColorTransferCharacteristic trc)
Determine a suitable EOTF 'gamma' value to match the supplied AVColorTransferCharacteristic.
Definition csp.c:187
int av_reduce(int *dst_num, int *dst_den, int64_t num, int64_t den, int64_t max)
Reduce a fraction.
Definition rational.c:35
AVRational av_gcd_q(AVRational a, AVRational b, int max_den, AVRational def)
Return the best rational so that a and b are multiple of it.
Definition rational.c:188
static double av_q2d(AVRational a)
Convert an AVRational to a double.
Definition rational.h:104
static av_always_inline AVRational av_inv_q(AVRational q)
Invert a rational.
Definition rational.h:159
AVRational av_sub_q(AVRational b, AVRational c)
Subtract one rational from another.
Definition rational.c:101
int64_t av_rescale(int64_t a, int64_t b, int64_t c)
Rescale a 64-bit integer with rounding to nearest.
int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding rnd)
Rescale a 64-bit integer with specified rounding.
Definition mathematics.c:58
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
@ AV_ROUND_DOWN
Round toward -infinity.
@ AV_ROUND_UP
Round toward +infinity.
void * av_realloc_array(void *ptr, size_t nmemb, size_t size)
Definition mem.c:217
void * av_memdup(const void *p, size_t size)
Duplicate a buffer with av_malloc().
Definition mem.c:302
int av_reallocp_array(void *ptr, size_t nmemb, size_t size)
Allocate, reallocate an array through a pointer to a pointer.
Definition mem.c:225
#define av_fourcc2str(fourcc)
Definition avutil.h:323
@ AVMEDIA_TYPE_AUDIO
Definition avutil.h:201
@ AVMEDIA_TYPE_NB
Definition avutil.h:205
@ AVMEDIA_TYPE_SUBTITLE
Definition avutil.h:203
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
@ AVMEDIA_TYPE_DATA
Opaque data information usually continuous.
Definition avutil.h:202
@ AVMEDIA_TYPE_UNKNOWN
Usually treated as AVMEDIA_TYPE_DATA.
Definition avutil.h:199
size_t av_strlcat(char *dst, const char *src, size_t size)
Append the string src to the string dst, but to a total length of no more than size - 1 bytes,...
Definition avstring.c:95
size_t av_strlcpy(char *dst, const char *src, size_t size)
Copy the string src to dst, but no more than size - 1 bytes, and null-terminate dst.
Definition avstring.c:85
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition avutil.h:247
#define AV_TIME_BASE
Internal time base represented as integer.
Definition avutil.h:253
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition avutil.h:263
#define LIBAVUTIL_VERSION_INT
Definition version.h:85
@ AV_SPHERICAL_RECTILINEAR
Video frame displays on a flat, rectangular 2D surface.
Definition spherical.h:78
@ AV_SPHERICAL_EQUIRECTANGULAR
Video represents a sphere mapped on a flat surface using equirectangular projection.
Definition spherical.h:52
@ AV_SPHERICAL_EQUIRECTANGULAR_TILE
Video represents a portion of a sphere mapped on a flat surface using equirectangular projection.
Definition spherical.h:68
@ AV_SPHERICAL_CUBEMAP
Video frame is split into 6 faces of a cube, and arranged on a 3x2 layout.
Definition spherical.h:61
@ AV_SPHERICAL_HALF_EQUIRECTANGULAR
Video frame displays as a 180 degree equirectangular projection.
Definition spherical.h:73
@ AV_SPHERICAL_FISHEYE
Fisheye projection (Apple).
Definition spherical.h:84
const char * av_stereo3d_type_name(unsigned int type)
Provide a human-readable name of a given stereo3d type.
Definition stereo3d.c:93
#define AV_STEREO3D_FLAG_INVERT
Inverted views, Right/Bottom represents the left view.
Definition stereo3d.h:194
@ AV_STEREO3D_2D
Video is not stereoscopic (and metadata has to be there).
Definition stereo3d.h:52
@ AV_STEREO3D_TOPBOTTOM
Views are on top of each other.
Definition stereo3d.h:76
@ AV_STEREO3D_SIDEBYSIDE
Views are next to each other.
Definition stereo3d.h:64
@ AV_PRIMARY_EYE_NONE
Neither eye.
Definition stereo3d.h:178
@ AV_STEREO3D_VIEW_RIGHT
Frame contains only the right view.
Definition stereo3d.h:163
@ AV_STEREO3D_VIEW_PACKED
Frame contains two packed views.
Definition stereo3d.h:153
@ AV_STEREO3D_VIEW_LEFT
Frame contains only the left view.
Definition stereo3d.h:158
@ AV_STEREO3D_VIEW_UNSPEC
Content is unspecified.
Definition stereo3d.h:168
int index
Definition gxfenc.c:90
int a
int ff_isom_write_lhvc(AVIOContext *pb, const uint8_t *data, int size, int ps_array_completeness, void *logctx)
Writes L-HEVC extradata (parameter sets with nuh_layer_id > 0, as a LHEVCDecoderConfigurationRecord) ...
Definition hevc.c:1408
int ff_hevc_annexb2mp4_buf(const uint8_t *buf_in, uint8_t **buf_out, int *size, int filter_ps, int *ps_count)
Writes Annex B formatted HEVC NAL units to a data buffer.
Definition hevc.c:1252
int ff_hevc_annexb2mp4(AVIOContext *pb, const uint8_t *buf_in, int size, int filter_ps, int *ps_count)
Writes Annex B formatted HEVC NAL units to the provided AVIOContext.
Definition hevc.c:1204
int ff_isom_write_hvcc(AVIOContext *pb, const uint8_t *data, int size, int ps_array_completeness, void *logctx)
Writes HEVC extradata (parameter sets and declarative SEI NAL units with nuh_layer_id == 0,...
Definition hevc.c:1401
cl_device_type type
const VDPAUPixFmtMap * map
int ff_iamf_write_descriptors(const IAMFContext *iamf, AVIOContext *pb, void *log_ctx)
int ff_iamf_write_audio_frame(const IAMFContext *iamf, AVIOContext *pb, unsigned audio_substream_id, const AVPacket *pkt)
int ff_iamf_add_mix_presentation(IAMFContext *iamf, const AVStreamGroup *stg, void *log_ctx)
int ff_iamf_add_audio_element(IAMFContext *iamf, const AVStreamGroup *stg, void *log_ctx)
int ff_iamf_write_parameter_blocks(const IAMFContext *iamf, AVIOContext *pb, const AVPacket *pkt, void *log_ctx)
#define r
Definition input.c:42
#define b
Definition input.c:43
static av_always_inline uint64_t av_double2int(double f)
Reinterpret a double as a 64-bit integer.
Definition intfloat.h:70
#define AV_WB32(p, v)
#define AV_RB8(x)
#define AV_RL32(p)
#define AV_RB32(p)
#define AV_RL16(p)
#define AV_WB16(p, v)
#define AV_RB24(x)
#define AV_RB16(p)
const AVCodecTag ff_mp4_obj_type[]
Definition isom.c:34
int ff_mov_iso639_to_lang(const char lang[4], int mp4)
Definition isom.c:234
const struct MP4TrackKindMapping ff_mov_track_kind_table[]
Definition isom.c:465
const AVCodecTag ff_codec_movsubtitle_tags[]
Definition isom.c:75
#define MOV_TRUN_SAMPLE_DURATION
Definition isom.h:418
#define MOV_TRUN_SAMPLE_CTS
Definition isom.h:421
#define MOV_TKHD_FLAG_ENABLED
Definition isom.h:433
#define MOV_TFHD_DEFAULT_BASE_IS_MOOF
Definition isom.h:414
const AVCodecTag ff_codec_movaudio_tags[]
Definition isom_tags.c:306
#define MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES
Definition isom.h:431
const AVCodecTag ff_codec_movvideo_tags[]
Definition isom_tags.c:29
#define MOV_TFHD_DEFAULT_SIZE
Definition isom.h:411
#define MOV_ISMV_TTML_TAG
Definition isom.h:482
#define MOV_FRAG_SAMPLE_FLAG_DEPENDS_NO
Definition isom.h:430
#define TAG_IS_AVCI(tag)
Definition isom.h:442
#define MOV_TRUN_FIRST_SAMPLE_FLAGS
Definition isom.h:417
#define MOV_MP4_FPCM_TAG
Definition isom.h:484
#define MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC
Definition isom.h:424
#define MOV_SAMPLE_DEPENDENCY_UNKNOWN
Definition isom.h:438
#define MOV_TFHD_STSD_ID
Definition isom.h:409
#define MOV_TRUN_SAMPLE_FLAGS
Definition isom.h:420
#define MOV_MP4_TTML_TAG
Definition isom.h:483
#define MOV_TFHD_DEFAULT_FLAGS
Definition isom.h:412
#define MOV_SAMPLE_DEPENDENCY_YES
Definition isom.h:439
#define MOV_TRUN_DATA_OFFSET
Definition isom.h:416
#define MOV_TFHD_BASE_DATA_OFFSET
Definition isom.h:408
#define MOV_MP4_IPCM_TAG
Definition isom.h:485
#define MOV_TFHD_DURATION_IS_EMPTY
Definition isom.h:413
#define MOV_TKHD_FLAG_IN_MOVIE
Definition isom.h:434
#define MOV_TRUN_SAMPLE_SIZE
Definition isom.h:419
#define MOV_SAMPLE_DEPENDENCY_NO
Definition isom.h:440
#define MOV_TFHD_DEFAULT_DURATION
Definition isom.h:410
static void put_bits(Jpeg2000EncoderContext *s, int val, int n)
put n times val bit
Definition j2kenc.c:154
int ff_isom_write_lvcc(AVIOContext *pb, const uint8_t *data, int len, void *logctx)
Definition lcevc.c:251
unsigned offset
Definition libaomenc.c:763
common internal api header.
unsigned int ff_toupper4(unsigned int x)
Definition to_upper4.h:29
void ff_isom_write_apvc(AVIOContext *pb, const APVDecoderConfigurationRecord *apvc, void *logctx)
Definition apv.c:80
int ff_isom_init_apvc(APVDecoderConfigurationRecord **papvc, void *logctx)
Definition apv.c:352
void ff_isom_close_apvc(APVDecoderConfigurationRecord **papvc)
Definition apv.c:375
int ff_isom_parse_apvc(APVDecoderConfigurationRecord *apvc, const AVPacket *pkt, void *logctx)
Definition apv.c:252
internal header for HEVC (de)muxer utilities
void ff_iamf_uninit_context(IAMFContext *c)
Definition iamf.c:172
unsigned int ff_codec_get_tag(const AVCodecTag *tags, enum AVCodecID id)
Definition utils.c:133
int ff_sdp_write_media(char *buff, int size, const AVStream *st, int idx, const char *dest_addr, const char *dest_type, int port, int ttl, AVFormatContext *fmt)
Append the media-specific SDP fragment for the media stream c to the buffer buff.
Definition sdp.c:955
uint64_t ff_ntp_time(void)
Get the current time since NTP epoch in microseconds.
Definition utils.c:257
char * ff_data_to_hex(char *buf, const uint8_t *src, int size, int lowercase)
Write hexadecimal string corresponding to given binary data.
Definition utils.c:464
uint64_t ff_get_formatted_ntp_time(uint64_t ntp_time_us)
Get the NTP time stamp formatted as per the RFC-5905.
Definition utils.c:262
int ff_alloc_extradata(AVCodecParameters *par, int size)
Allocate extradata with additional AV_INPUT_BUFFER_PADDING_SIZE at end which is always set to 0.
Definition utils.c:237
static av_always_inline FFFormatContext * ffformatcontext(AVFormatContext *s)
Definition internal.h:130
#define NTP_OFFSET_US
Definition internal.h:422
const AVPacket * ff_interleaved_peek(AVFormatContext *s, int stream)
Find the next packet in the interleaving queue for the given stream.
Definition mux.c:1043
static int check_bitstream(AVFormatContext *s, FFStream *sti, AVPacket *pkt)
Definition mux.c:1056
int ff_stream_add_bitstream_filter(AVStream *st, const char *name, const char *args)
Add a bitstream filter to a stream.
Definition mux.c:1294
int ff_get_muxer_ts_offset(AVFormatContext *s, int stream_index, int64_t *offset)
Definition mux.c:1027
void ff_packet_list_free(PacketList *list)
Wipe the list and unref all the packets in it.
int ff_packet_list_put(PacketList *list, AVPacket *pkt, int(*copy)(AVPacket *dst, const AVPacket *src), int flags)
Append an AVPacket to the list.
Definition packet_list.c:40
static unsigned int ff_is_ttml_stream_paragraph_based(const AVCodecParameters *codecpar)
Definition ttmlenc.h:28
Libavformat version macros.
#define LIBAVFORMAT_IDENT
Definition version.h:45
internal header for H.266/VVC (de)muxer utilities
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition internal.h:88
Stereoscopic video.
version
Definition libkvazaar.c:313
Replacements for frequently missing libm functions.
static av_always_inline av_const double round(double x)
Definition libm.h:446
#define FFMIN(a, b)
Definition macros.h:49
#define MKTAG(a, b, c, d)
Definition macros.h:55
#define FFMAX(a, b)
Definition macros.h:47
uint64_t layout
void * av_calloc(size_t nmemb, size_t size)
Definition mem.c:264
Memory handling functions.
int ff_mov_get_channel_positions_from_layout(const AVChannelLayout *layout, uint8_t *position, int position_num)
Get ISO/IEC 23001-8 OutputChannelPosition from AVChannelLayout.
Definition mov_chan.c:741
int ff_mov_get_channel_layout_tag(const AVCodecParameters *par, uint32_t *layout, uint32_t *bitmap, uint32_t **pchannel_desc)
Get the channel layout tag for the specified codec id and channel layout.
Definition mov_chan.c:476
int ff_mov_get_channel_config_from_layout(const AVChannelLayout *layout, int *config)
Get ISO/IEC 23001-8 ChannelConfiguration from AVChannelLayout.
Definition mov_chan.c:705
@ MOV_CH_LAYOUT_MONO
Definition mov_chan.h:56
#define MOV_CH_LAYOUT_UNKNOWN
Definition mov_chan.h:52
static int mov_write_stsd_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
Definition movenc.c:3184
static int mov_write_stco_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:201
static int mov_write_vmhd_tag(AVIOContext *pb)
Definition movenc.c:3569
static int mov_write_av3c(AVIOContext *pb, const uint8_t *data, int len)
Definition movenc.c:1618
static int mov_write_trex_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:4495
static int get_moov_size(AVFormatContext *s)
Definition movenc.c:8927
static unsigned compute_avg_bitrate(MOVTrack *track)
Definition movenc.c:721
static int mov_write_sidx_tag(AVIOContext *pb, MOVTrack *track, int ref_size, int total_sidx_size)
Definition movenc.c:5954
static const AVCodecTag codec_cover_image_tags[]
Definition movenc.c:2186
static int mov_write_header(AVFormatContext *s)
Definition movenc.c:8747
static int mov_write_sdtp_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:316
static const AVCodecTag codec_ism_tags[]
Definition movenc.c:9335
static MovTag * mov_add_tref_tag(MOVMuxContext *mov, MOVTrack *trk, uint32_t name)
Definition movenc.c:5341
static int utf8len(const uint8_t *b)
Definition movenc.c:143
static AVDictionaryEntry * get_metadata_lang(AVFormatContext *s, const char *tag, int *lang)
Definition movenc.c:4664
static int mov_write_stbl_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
Definition movenc.c:3421
static int mov_write_ac3_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
Definition movenc.c:419
static int mov_write_hvcc_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
Definition movenc.c:1658
static int mov_write_stsz_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:225
static int mov_write_iref_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
Definition movenc.c:3727
static int mov_write_uuid_tag_psp(AVIOContext *pb, MOVTrack *mov)
Definition movenc.c:4277
static int mov_write_evcc_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:1695
static int mov_write_raw_metadata_tag(AVFormatContext *s, AVIOContext *pb, const char *name, const char *key)
Definition movenc.c:4999
static int mov_write_dfla_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:875
static int mov_write_dinf_tag(AVIOContext *pb)
Definition movenc.c:3460
static int mov_write_dpxe_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:1879
#define IS_MODE(muxer, config)
static void write_matrix(AVIOContext *pb, int16_t a, int16_t b, int16_t c, int16_t d, int16_t tx, int16_t ty)
Definition movenc.c:3995
static int mov_write_traf_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track, int64_t moof_offset, int moof_size)
Definition movenc.c:5887
uint32_t tag
Definition movenc.c:2073
static int mov_write_emsg_tag(AVIOContext *pb, AVStream *st, AVPacket *pkt)
Definition movenc.c:7570
static int mov_flush_fragment_interleaving(AVFormatContext *s, MOVTrack *track)
Definition movenc.c:6573
static int mov_get_mpeg2_xdcam_codec_tag(AVFormatContext *s, MOVTrack *track)
Definition movenc.c:1926
static int mov_write_iinf_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
Definition movenc.c:3702
static int mov_write_mdhd_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
Definition movenc.c:3939
static int mov_create_chapter_track(AVFormatContext *s, int tracknum)
Definition movenc.c:7749
static int mov_mdhd_mvhd_tkhd_version(MOVMuxContext *mov, MOVTrack *track, int64_t duration)
Definition movenc.c:3930
static int mov_add_tfra_entries(AVIOContext *pb, MOVMuxContext *mov, int tracks, int size)
Definition movenc.c:5822
static int shift_data(AVFormatContext *s)
Definition movenc.c:8998
static int mov_write_av3c_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:1637
static int64_t update_size_and_version(AVIOContext *pb, int64_t pos, int version)
Definition movenc.c:165
static int mov_write_wfex_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
Definition movenc.c:864
static int mov_write_chan_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
Definition movenc.c:1016
unsigned bps
Definition movenc.c:2074
static int mov_write_gama_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track, double gamma)
Definition movenc.c:2608
static int mov_write_amve_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:2729
static const AVCodecTag codec_ipod_tags[]
Definition movenc.c:9341
static int mov_write_eac3_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
Definition movenc.c:630
static int co64_required(const MOVTrack *track)
Definition movenc.c:177
static int mov_write_sthd_tag(AVIOContext *pb)
Definition movenc.c:3477
static int mov_write_aux_tag(AVIOContext *pb, const char *aux_type)
Definition movenc.c:2805
static int mov_write_pasp_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:2595
static int compute_moov_size(AVFormatContext *s)
Definition movenc.c:8958
static int mov_write_loci_tag(AVFormatContext *s, AVIOContext *pb)
Definition movenc.c:4729
static int mov_write_tfra_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:6137
static int ascii_to_wc(AVIOContext *pb, const uint8_t *b)
Definition movenc.c:5019
static int mov_write_sidx_tags(AVIOContext *pb, MOVMuxContext *mov, int tracks, int ref_size)
Definition movenc.c:6015
static int mov_write_vexu_tag(AVFormatContext *s, AVIOContext *pb, const AVStereo3D *stereo3d, const AVSphericalMapping *spherical_mapping)
Definition movenc.c:2499
static MovTag * mov_find_tref_tag(MOVMuxContext *mov, const MOVTrack *trk, uint32_t name)
Definition movenc.c:5330
static const AVClass mov_isobmff_muxer_class
Definition movenc.c:133
static int mov_preroll_write_stbl_atoms(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:3324
static void mov_write_ftyp_tag_internal(AVIOContext *pb, AVFormatContext *s, int has_h264, int has_video, int write_minor)
Definition movenc.c:6210
static int mov_write_dmlp_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
Definition movenc.c:929
static int mov_write_vvcc_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:1725
static int mov_write_iprp_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
Definition movenc.c:3815
static int mov_write_tmcd_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:3123
static int mov_create_timecode_track(AVFormatContext *s, int index, int src_index, AVTimecode tc)
Definition movenc.c:7849
static int mov_create_dvd_sub_decoder_specific_info(MOVTrack *track, AVStream *st)
Definition movenc.c:8022
static int mov_write_prft_tag(AVIOContext *pb, MOVMuxContext *mov, int tracks)
Definition movenc.c:6053
static int mov_write_glbl_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:1221
static int mov_write_ipco_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
Definition movenc.c:3774
static void mov_write_mdat_size(AVFormatContext *s)
Definition movenc.c:9013
static uint32_t get_sample_flags(MOVTrack *track, MOVIentry *entry)
Definition movenc.c:5625
static void enable_tracks(AVFormatContext *s)
Definition movenc.c:7905
static int mov_write_minf_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
Definition movenc.c:3840
static int mov_pcm_le_gt16(enum AVCodecID codec_id)
Definition movenc.c:836
static int mov_write_tfrf_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track, int entry)
Definition movenc.c:5773
static int mov_write_avcc_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:1603
static int mov_write_extradata_tag(AVIOContext *pb, MOVTrack *track)
This function writes extradata "as is".
Definition movenc.c:690
static int mov_write_covr(AVIOContext *pb, AVFormatContext *s)
Definition movenc.c:4834
static int mov_write_srat_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:1385
static int mov_write_smhd_tag(AVIOContext *pb)
Definition movenc.c:3559
static int mov_write_clap_tag(AVIOContext *pb, MOVTrack *track, uint32_t top, uint32_t bottom, uint32_t left, uint32_t right)
Definition movenc.c:2567
static int mov_finish_fragment(MOVMuxContext *mov, MOVTrack *track, int64_t ref_pos)
Definition movenc.c:6660
static int mov_write_mdta_keys_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
Definition movenc.c:4917
static void find_compressor(char *compressor_name, int len, MOVTrack *track)
Definition movenc.c:2756
static void mov_parse_truehd_frame(AVPacket *pkt, MOVTrack *trk)
Definition movenc.c:6554
static int mov_write_tkhd_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track, AVStream *st)
Definition movenc.c:4009
static int mov_write_amr_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:369
static int mov_write_sv3d_tag(AVFormatContext *s, AVIOContext *pb, AVSphericalMapping *spherical_mapping)
Definition movenc.c:2340
static int mov_get_h264_codec_tag(AVFormatContext *s, MOVTrack *track)
Definition movenc.c:1988
static int mov_get_dnxhd_codec_tag(AVFormatContext *s, MOVTrack *track)
Definition movenc.c:2096
static uint32_t rgb_to_yuv(uint32_t rgb)
Definition movenc.c:8006
static int mov_write_lhvc_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
Definition movenc.c:1673
static struct mpeg4_bit_rate_values calculate_mpeg4_bit_rates(MOVTrack *track)
Definition movenc.c:738
static int mov_auto_flush_fragment(AVFormatContext *s, int force)
Definition movenc.c:6902
static int mov_write_moof_tag(AVIOContext *pb, MOVMuxContext *mov, int tracks, int64_t mdat_size)
Definition movenc.c:6103
static int mov_write_moof_tag_internal(AVIOContext *pb, MOVMuxContext *mov, int tracks, int moof_size)
Definition movenc.c:5929
static int mov_write_edts_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
Definition movenc.c:4152
static int mov_write_enda_tag_be(AVIOContext *pb)
Definition movenc.c:704
static int mov_write_track_metadata(AVIOContext *pb, AVStream *st, const char *tag, const char *str)
Definition movenc.c:4317
static void param_write_hex(AVIOContext *pb, const char *name, const uint8_t *value, int len)
Definition movenc.c:5484
static int mov_write_ilst_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
Definition movenc.c:4861
static void mov_prune_frag_info(MOVMuxContext *mov, int tracks, int max)
Definition movenc.c:5861
static int mov_write_d263_tag(AVIOContext *pb)
Definition movenc.c:1580
static int mov_write_tmpo_tag(AVIOContext *pb, AVFormatContext *s)
Definition movenc.c:4711
static int mov_write_iloc_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
Definition movenc.c:3679
static int mov_write_int8_metadata(AVFormatContext *s, AVIOContext *pb, const char *name, const char *tag, int len)
Definition movenc.c:4807
static int mov_check_timecode_track(AVFormatContext *s, AVTimecode *tc, AVStream *src_st, const char *tcstr)
Definition movenc.c:7840
static int mov_write_ms_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
Definition movenc.c:852
static uint16_t language_code(const char *str)
Definition movenc.c:5030
static int mov_write_custom_metadata(AVFormatContext *s, AVIOContext *pb, const char *mean, const char *name, const char *tag)
Definition movenc.c:4700
static int mov_write_tref_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:4260
static void param_write_string(AVIOContext *pb, const char *name, const char *value)
Definition movenc.c:5479
static int mov_write_esds_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:783
static int mov_write_avid_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:1761
static int mov_write_ispe_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s, int stream_index)
Definition movenc.c:3746
static int64_t update_size(AVIOContext *pb, int64_t pos)
Definition movenc.c:155
static int mov_write_ipma_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
Definition movenc.c:3791
static int64_t calc_elst_duration(MOVMuxContext *mov, MOVTrack *track)
Definition movenc.c:3923
static int mov_add_tref_id(MOVMuxContext *mov, MovTag *tag, uint32_t id)
Definition movenc.c:5315
static int mov_write_moov_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
Definition movenc.c:5358
static int64_t calc_pts_duration(MOVMuxContext *mov, MOVTrack *track)
Definition movenc.c:3914
static int mov_write_dvc1_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:1204
static int mov_write_tfrf_tags(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
Definition movenc.c:5808
static int mov_write_chpl_tag(AVIOContext *pb, AVFormatContext *s)
Definition movenc.c:5059
static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
Definition movenc.c:1397
static int mov_write_string_tag(AVIOContext *pb, const char *name, const char *value, int lang, int long_style)
Definition movenc.c:4621
static int mov_write_rtp_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:3084
static int mov_write_dref_tag(AVIOContext *pb)
Definition movenc.c:3309
static int mov_write_hdlr_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
Definition movenc.c:3584
static int mov_write_iods_tag(AVIOContext *pb, MOVMuxContext *mov)
Definition movenc.c:4466
static int mov_write_3gp_udta_tag(AVIOContext *pb, AVFormatContext *s, const char *tag, const char *str)
Definition movenc.c:5037
static int mov_find_tref_id(MOVMuxContext *mov, const MovTag *tag, uint32_t id)
Definition movenc.c:5306
static int mov_write_subtitle_end_packet(AVFormatContext *s, int stream_index, int64_t dts)
Definition movenc.c:7501
static int mov_write_gmhd_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:3507
static int mov_write_dvcc_dvvc_tag(AVFormatContext *s, AVIOContext *pb, AVDOVIDecoderConfigurationRecord *dovi)
Definition movenc.c:2541
static int mov_write_pssh_tag(AVIOContext *pb, AVStream *st)
Definition movenc.c:5194
static int mov_init(AVFormatContext *s)
Definition movenc.c:8151
static void param_write_int(AVIOContext *pb, const char *name, int value)
Definition movenc.c:5474
static int mov_write_string_metadata(AVFormatContext *s, AVIOContext *pb, const char *name, const char *tag, int long_style)
Definition movenc.c:4689
static int mov_get_evc_codec_tag(AVFormatContext *s, MOVTrack *track)
Definition movenc.c:2050
static int mov_write_mdta_hdlr_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
Definition movenc.c:4902
static int mov_write_mvhd_tag(AVIOContext *pb, MOVMuxContext *mov)
Definition movenc.c:4519
static int mov_write_track_kind(AVIOContext *pb, const char *scheme_uri, const char *value)
Definition movenc.c:4331
static void mov_write_psp_udta_tag(AVIOContext *pb, const char *str, const char *lang, int type)
Definition movenc.c:5143
static unsigned int mov_find_codec_tag(AVFormatContext *s, MOVTrack *track)
Definition movenc.c:2213
static const uint16_t fiel_data[]
Definition movenc.c:2248
static int mov_write_apvc_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
Definition movenc.c:1744
static int mov_write_lvcc_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
Definition movenc.c:1712
static int mov_write_dops_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
Definition movenc.c:895
static int mov_write_tcmi_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:3485
static int64_t rescale_rational(AVRational q, int b)
Definition movenc.c:2398
static int mov_write_mfhd_tag(AVIOContext *pb, MOVMuxContext *mov)
Definition movenc.c:5616
static int mov_write_tfhd_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track, int64_t moof_offset)
Definition movenc.c:5631
static int mov_write_stts_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:3260
static int mov_write_mfra_tag(AVIOContext *pb, MOVMuxContext *mov)
Definition movenc.c:6161
static int mov_write_clli_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:2678
static int mov_write_mdat_tag(AVIOContext *pb, MOVMuxContext *mov)
Definition movenc.c:6199
static int mov_write_chnl_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
Definition movenc.c:1317
static int mov_write_pcmc_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
Definition movenc.c:1359
static int mov_write_vpcc_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
Definition movenc.c:1647
static int mov_write_video_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
Definition movenc.c:2815
static int mov_write_gpmd_tag(AVIOContext *pb, const MOVTrack *track)
Definition movenc.c:3172
static int check_pkt(AVFormatContext *s, MOVTrack *trk, AVPacket *pkt)
Definition movenc.c:6916
static int mov_write_uuidprof_tag(AVIOContext *pb, AVFormatContext *s)
Definition movenc.c:6373
static int mov_write_pitm_tag(AVIOContext *pb, int item_id)
Definition movenc.c:3669
static int mov_write_identification(AVIOContext *pb, AVFormatContext *s)
Definition movenc.c:6444
static int mov_write_ctts_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
Definition movenc.c:3219
static int mov_write_trkn_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s, int disc)
Definition movenc.c:4780
static int mov_write_wave_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
Definition movenc.c:1077
static int mov_write_udta_sdp(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:4295
static int mov_write_mdia_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
Definition movenc.c:3976
static const AVCodecTag codec_f4v_tags[]
Definition movenc.c:9352
static int is_clcp_track(MOVTrack *track)
Definition movenc.c:3578
static int mov_write_trak_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track, AVStream *st)
Definition movenc.c:4410
static int compute_sidx_size(AVFormatContext *s)
Definition movenc.c:8983
static int mov_write_itunes_hdlr_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
Definition movenc.c:4584
static int mov_write_dvc1_structs(MOVTrack *track, uint8_t *buf)
Definition movenc.c:1120
static int mov_write_track_kinds(AVIOContext *pb, AVStream *st)
Definition movenc.c:4357
static int handle_eac3(MOVMuxContext *mov, AVPacket *pkt, MOVTrack *track)
Definition movenc.c:465
static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s)
Definition movenc.c:6251
static int get_sidx_size(AVFormatContext *s)
Definition movenc.c:8940
static int mov_write_stsc_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:261
static int get_samples_per_packet(MOVTrack *track)
Definition movenc.c:1279
static int mov_write_udta_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
Definition movenc.c:5085
static int mov_pcm_be_gt16(enum AVCodecID codec_id)
Definition movenc.c:844
static int mov_write_trailer(AVFormatContext *s)
Definition movenc.c:9035
static int mov_write_btrt_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:1298
static int rtp_hinting_needed(const AVStream *st)
Definition movenc.c:191
static int mov_write_nmhd_tag(AVIOContext *pb)
Definition movenc.c:3469
static int mov_get_lpcm_flags(enum AVCodecID codec_id)
Compute flags for 'lpcm' tag.
Definition movenc.c:1234
static int mov_write_pixi_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s, int stream_index)
Definition movenc.c:3758
static int mov_get_rawvideo_codec_tag(AVFormatContext *s, MOVTrack *track)
Definition movenc.c:2105
static int mov_write_squashed_packet(AVFormatContext *s, MOVTrack *track)
Definition movenc.c:6598
static int mov_write_ccst_tag(AVIOContext *pb)
Definition movenc.c:2786
static int mov_write_tapt_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:4117
static int defined_frame_rate(AVFormatContext *s, AVStream *st)
Definition movenc.c:1917
static void mov_free(AVFormatContext *s)
Definition movenc.c:7947
static int mov_write_uuid_tag_ipod(AVIOContext *pb)
Write uuid atom.
Definition movenc.c:2236
static void put_descr(AVIOContext *pb, int tag, unsigned int size)
Definition movenc.c:712
int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
Definition movenc.c:6951
static int mov_write_tfdt_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:5875
static int mov_setup_track_ids(MOVMuxContext *mov, AVFormatContext *s)
Assign track ids.
Definition movenc.c:5267
static const struct @225371303101201053203360341351022255162073206032 mov_pix_fmt_tags[]
static int mov_write_string_data_tag(AVIOContext *pb, const char *data, int lang, int long_style)
Definition movenc.c:4600
static void mov_parse_vc1_frame(AVPacket *pkt, MOVTrack *trk)
Definition movenc.c:6494
static int mov_write_tfxd_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:5753
static int mov_flush_fragment(AVFormatContext *s, int force)
Definition movenc.c:6692
static int mov_write_single_packet(AVFormatContext *s, AVPacket *pkt)
Definition movenc.c:7410
static int mov_write_squashed_packets(AVFormatContext *s)
Definition movenc.c:6636
static int mov_write_eyes_tag(AVFormatContext *s, AVIOContext *pb, const AVStereo3D *stereo3d)
Definition movenc.c:2441
static unsigned int validate_codec_tag(const AVCodecTag *const *tags, unsigned int tag, int codec_id)
Definition movenc.c:2193
static void build_chunks(MOVTrack *trk)
Definition movenc.c:5231
static void get_pts_range(MOVMuxContext *mov, MOVTrack *track, int64_t *start, int64_t *end, int elst, int mdhd)
Definition movenc.c:3877
static int mov_write_mvex_tag(AVIOContext *pb, MOVMuxContext *mov)
Definition movenc.c:4508
static void mov_write_vexu_proj_tag(AVFormatContext *s, AVIOContext *pb, const AVSphericalMapping *spherical_mapping)
Definition movenc.c:2414
static int mov_write_st3d_tag(AVFormatContext *s, AVIOContext *pb, AVStereo3D *stereo_3d)
Definition movenc.c:2310
static unsigned int mov_get_codec_tag(AVFormatContext *s, MOVTrack *track)
Definition movenc.c:2131
static int mov_write_av1c_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:1592
static int mov_check_bitstream(AVFormatContext *s, AVStream *st, const AVPacket *pkt)
Definition movenc.c:9178
static int mov_write_source_reference_tag(AVIOContext *pb, MOVTrack *track, const char *reel_name)
Definition movenc.c:3104
static int get_cluster_duration(MOVTrack *track, int cluster_idx)
Definition movenc.c:1259
static int mov_write_enda_tag(AVIOContext *pb)
Definition movenc.c:696
static int64_t calc_samples_pts_duration(MOVMuxContext *mov, MOVTrack *track)
Definition movenc.c:3902
static int mov_write_fiel_tag(AVIOContext *pb, MOVTrack *track, int field_order)
Definition movenc.c:2252
static int mov_write_colr_tag(AVIOContext *pb, MOVTrack *track, int prefer_icc)
Definition movenc.c:2630
static int mov_write_mdta_ilst_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
Definition movenc.c:4946
static void mov_write_hfov_tag(AVFormatContext *s, AVIOContext *pb, const AVStereo3D *stereo3d)
Definition movenc.c:2403
static int mov_write_track_udta_tag(AVIOContext *pb, MOVMuxContext *mov, AVStream *st)
Definition movenc.c:4377
static int mov_parse_mpeg2_frame(AVPacket *pkt, uint32_t *flags)
Definition movenc.c:6473
static int mov_write_freeform_tag(AVIOContext *pb, const char *mean, const char *name, const char *data)
Definition movenc.c:4635
static int mov_write_SA3D_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
Definition movenc.c:958
static int mov_write_packet(AVFormatContext *s, AVPacket *pkt)
Definition movenc.c:7598
static int mov_write_meta_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
Definition movenc.c:4968
static int mov_write_mdcv_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:2698
static const AVCodecTag codec_mp4_tags[]
Definition movenc.c:9270
static int mov_get_apv_codec_tag(AVFormatContext *s, MOVTrack *track)
Definition movenc.c:2060
static int mov_write_subtitle_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
Definition movenc.c:2265
static int mov_write_uuidusmt_tag(AVIOContext *pb, AVFormatContext *s)
Definition movenc.c:5156
static int mov_write_isml_manifest(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
Definition movenc.c:5492
static int mov_get_dv_codec_tag(AVFormatContext *s, MOVTrack *track)
Definition movenc.c:1892
static int is_cover_image(const AVStream *st)
Definition movenc.c:184
static int mov_write_trun_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track, int moof_size, int first, int end)
Definition movenc.c:5697
static int mov_write_hvce_tag(AVIOContext *pb, const AVPacketSideData *sd)
Definition movenc.c:2559
static int mov_write_stss_tag(AVIOContext *pb, MOVTrack *track, uint32_t flag)
Definition movenc.c:292
static int mov_write_hmhd_tag(AVIOContext *pb)
Definition movenc.c:3825
#define FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS
Definition movenc.h:297
#define FF_MOV_FLAG_GLOBAL_SIDX
Definition movenc.h:292
int ff_mov_add_hinted_packet(AVFormatContext *s, AVPacket *pkt, int track_index, int sample, uint8_t *sample_data, int sample_size)
Definition movenchint.c:405
#define FF_MOV_FLAG_FRAG_EVERY_FRAME
Definition movenc.h:298
#define FF_MOV_FLAG_DASH
Definition movenc.h:289
#define FF_MOV_FLAG_DEFAULT_BASE_MOOF
Definition movenc.h:288
#define FF_MOV_FLAG_WRITE_GAMA
Definition movenc.h:294
#define FF_MOV_FLAG_WRITE_COLR
Definition movenc.h:293
#define MOV_TRACK_CTTS
Definition movenc.h:114
#define FF_MOV_FLAG_DISABLE_CHPL
Definition movenc.h:287
#define MODE_3GP
Definition movenc.h:40
#define MODE_3G2
Definition movenc.h:43
#define FF_MOV_FLAG_FRAG_DISCONT
Definition movenc.h:290
#define MOV_TIMESCALE_Q
Definition movenc.h:34
#define MOV_FRAG_INFO_ALLOC_INCREMENT
Definition movenc.h:31
int ff_mov_init_hinting(AVFormatContext *s, int index, int src_index)
Definition movenchint.c:30
#define MOV_DISPOSABLE_SAMPLE
Definition movenc.h:61
#define FF_MOV_FLAG_FASTSTART
Definition movenc.h:285
#define MOV_TRACK_STPS
Definition movenc.h:115
#define FF_MOV_FLAG_EMPTY_MOOV
Definition movenc.h:280
#define MODE_ISM
Definition movenc.h:45
#define FF_MOV_FLAG_SKIP_TRAILER
Definition movenc.h:296
#define MODE_MP4
Definition movenc.h:38
#define FF_MOV_FLAG_RTP_HINT
Definition movenc.h:278
#define FF_MOV_FLAG_PREFER_ICC
Definition movenc.h:301
@ MOV_ENC_CENC_AES_CTR
Definition movenc.h:201
@ MOV_ENC_NONE
Definition movenc.h:200
#define MODE_MOV
Definition movenc.h:39
void ff_mov_close_hinting(MOVTrack *track)
Definition movenchint.c:464
#define FF_MOV_FLAG_FRAG_KEYFRAME
Definition movenc.h:281
#define FF_MOV_FLAG_ISML
Definition movenc.h:284
#define MOV_TIMESCALE
Definition movenc.h:33
#define FF_MOV_FLAG_FRAG_CUSTOM
Definition movenc.h:283
#define FF_MOV_FLAG_USE_MDTA
Definition movenc.h:295
#define FF_MOV_FLAG_SKIP_SIDX
Definition movenc.h:299
#define FF_MOV_FLAG_DELAY_MOOV
Definition movenc.h:291
#define MODE_IPOD
Definition movenc.h:44
#define FF_MOV_FLAG_OMIT_TFHD_OFFSET
Definition movenc.h:286
#define FF_MOV_FLAG_FRAGMENT
Definition movenc.h:279
#define MODE_F4V
Definition movenc.h:46
#define FF_MOV_FLAG_HYBRID_FRAGMENTED
Definition movenc.h:302
@ MOV_PRFT_SRC_WALLCLOCK
Definition movenc.h:206
@ MOV_PRFT_NONE
Definition movenc.h:205
@ MOV_PRFT_SRC_PTS
Definition movenc.h:207
@ MOV_PRFT_NB
Definition movenc.h:208
#define FF_MOV_FLAG_SEPARATE_MOOF
Definition movenc.h:282
#define MOV_PARTIAL_SYNC_SAMPLE
Definition movenc.h:60
#define MOV_INDEX_CLUSTER_SIZE
Definition movenc.h:32
#define FF_MOV_FLAG_CMAF
Definition movenc.h:300
#define MODE_PSP
Definition movenc.h:41
#define MOV_TIMECODE_FLAG_DROPFRAME
Definition movenc.h:118
#define MOV_SYNC_SAMPLE
Definition movenc.h:59
#define MOV_TRACK_ENABLED
Definition movenc.h:116
#define MODE_AVIF
Definition movenc.h:47
int ff_mov_generate_squashed_ttml_packet(AVFormatContext *s, MOVTrack *track, AVPacket *pkt)
void ff_mov_cenc_flush(MOVMuxCencContext *ctx)
Clear subsample data.
Definition movenccenc.c:633
int ff_mov_cenc_av1_write_obus(AVFormatContext *s, MOVMuxCencContext *ctx, AVIOContext *pb, const AVPacket *pkt)
Definition movenccenc.c:387
int ff_mov_cenc_avc_parse_nal_units(MOVMuxCencContext *ctx, AVIOContext *pb, const uint8_t *buf_in, int size)
Parse AVC NAL units from annex B format, the nal size and type are written in the clear while the bod...
Definition movenccenc.c:198
int ff_mov_cenc_init(MOVMuxCencContext *ctx, uint8_t *encryption_key, int use_subsamples, enum AVCodecID codec_id, int bitexact)
Initialize a CENC context.
Definition movenccenc.c:600
void ff_mov_cenc_write_stbl_atoms(MOVMuxCencContext *ctx, AVIOContext *pb, int64_t moof_offset)
Write the cenc atoms that should reside inside stbl.
Definition movenccenc.c:542
int ff_mov_cenc_write_sinf_tag(MOVTrack *track, AVIOContext *pb, uint8_t *kid)
Write the sinf atom, contained inside stsd.
Definition movenccenc.c:568
void ff_mov_cenc_free(MOVMuxCencContext *ctx)
Free a CENC context.
Definition movenccenc.c:639
int ff_mov_cenc_avc_write_nal_units(AVFormatContext *s, MOVMuxCencContext *ctx, int nal_length_size, AVIOContext *pb, const uint8_t *buf_in, int size)
Write AVC NAL units that are in MP4 format, the nal size and type are written in the clear while the ...
Definition movenccenc.c:238
int ff_mov_cenc_write_packet(MOVMuxCencContext *ctx, AVIOContext *pb, const uint8_t *buf_in, int size)
Write a fully encrypted packet.
Definition movenccenc.c:173
#define CENC_KID_SIZE
Definition movenccenc.h:30
#define FF_OFMT_FLAG_ALLOW_FLUSH
This flag indicates that the muxer stores data internally and supports flushing it.
Definition mux.h:38
int ff_format_shift_data(AVFormatContext *s, int64_t read_start, int shift_size)
Make shift_size amount of space at read_start by shifting data in the output at read_start until the ...
Definition mux_utils.c:71
int ff_parse_creation_time_metadata(AVFormatContext *s, int64_t *timestamp, int return_seconds)
Parse creation_time in AVFormatContext metadata if exists and warn if the parsing fails.
Definition mux_utils.c:137
const char data[16]
Definition mxf.c:149
uint8_t interlaced
Definition mxfenc.c:2336
int profile
Definition mxfenc.c:2299
uint16_t cid
Definition mxfenc.c:2335
int ff_nal_parse_units(AVIOContext *pb, const uint8_t *buf_in, int size)
Definition nal.c:113
int ff_nal_parse_units_buf(const uint8_t *buf_in, uint8_t **buf, int *size)
Definition nal.c:133
IDirect3DDxgiInterfaceAccess _COM_Outptr_ void ** p
static float distance(float x, float y, int band)
#define OPUS_SEEK_PREROLL_MS
#define av_realloc(p, s)
Definition ops_static.c:54
#define av_malloc(s)
Definition ops_static.c:52
AVOptions.
const char * av_get_pix_fmt_name(enum AVPixelFormat pix_fmt)
Return the short name for a pixel format, NULL in case pix_fmt is unknown.
Definition pixdesc.c:3380
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3460
#define AV_PIX_FMT_YUV420P10
Definition pixfmt.h:545
@ AVCOL_RANGE_MPEG
Narrow or limited range content.
Definition pixfmt.h:766
@ AVCOL_RANGE_UNSPECIFIED
Definition pixfmt.h:749
@ AVCOL_RANGE_JPEG
Full range content.
Definition pixfmt.h:783
#define AV_PIX_FMT_YUV422P10
Definition pixfmt.h:546
AVPixelFormat
Pixel format.
Definition pixfmt.h:71
@ AV_PIX_FMT_UYVA
packed UYVA 4:4:4:4, 32bpp (1 Cr & Cb sample per 1x1 Y & A samples), UYVAUYVA...
Definition pixfmt.h:444
@ AV_PIX_FMT_GRAY16BE
Y , 16bpp, big-endian.
Definition pixfmt.h:104
@ AV_PIX_FMT_V30XLE
packed VYUX 4:4:4 like XV30, 32bpp, (msb)10V 10Y 10U 2X(lsb), little-endian
Definition pixfmt.h:449
@ AV_PIX_FMT_NONE
Definition pixfmt.h:72
@ AV_PIX_FMT_RGB24
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition pixfmt.h:75
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition pixfmt.h:73
@ AV_PIX_FMT_MONOBLACK
Y , 1bpp, 0 is black, 1 is white, in each byte pixels are ordered from the msb to the lsb.
Definition pixfmt.h:83
@ AV_PIX_FMT_YUV422P
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition pixfmt.h:77
@ AV_PIX_FMT_ARGB
packed ARGB 8:8:8:8, 32bpp, ARGBARGB...
Definition pixfmt.h:99
@ AV_PIX_FMT_RGB555BE
packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), big-endian , X=unused/undefined
Definition pixfmt.h:114
@ AV_PIX_FMT_BGRA
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition pixfmt.h:102
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition pixfmt.h:81
@ AV_PIX_FMT_UYVY422
packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
Definition pixfmt.h:88
@ AV_PIX_FMT_RGB48BE
packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as big...
Definition pixfmt.h:109
@ AV_PIX_FMT_ABGR
packed ABGR 8:8:8:8, 32bpp, ABGRABGR...
Definition pixfmt.h:101
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition pixfmt.h:100
@ AV_PIX_FMT_RGB565LE
packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), little-endian
Definition pixfmt.h:113
@ AV_PIX_FMT_RGB555LE
packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), little-endian, X=unused/undefined
Definition pixfmt.h:115
@ AV_PIX_FMT_RGB565BE
packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), big-endian
Definition pixfmt.h:112
@ AV_PIX_FMT_YUYV422
packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
Definition pixfmt.h:74
@ AV_PIX_FMT_PAL8
8 bits with AV_PIX_FMT_RGB32 palette
Definition pixfmt.h:84
@ AV_PIX_FMT_BGR24
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition pixfmt.h:76
@ AV_PIX_FMT_VYU444
packed VYU 4:4:4, 24bpp (1 Cr & Cb sample per 1x1 Y), VYUVYU...
Definition pixfmt.h:446
@ AV_PIX_FMT_MONOWHITE
Y , 1bpp, 0 is white, 1 is black, in each byte pixels are ordered from the msb to the lsb.
Definition pixfmt.h:82
@ AVCOL_PRI_UNSPECIFIED
Definition pixfmt.h:645
@ AVCOL_TRC_UNSPECIFIED
Definition pixfmt.h:675
@ AVCOL_SPC_UNSPECIFIED
Definition pixfmt.h:709
bitstream writer API
static void init_put_bits(PutBitContext *s, uint8_t *buffer, int buffer_size)
Initialize the PutBitContext s.
Definition put_bits.h:62
static void flush_put_bits(PutBitContext *s)
Pad the end of the output stream with zeros.
Definition put_bits.h:153
static int put_bytes_output(const PutBitContext *s)
Definition put_bits.h:99
static av_unused void put_bits32(PutBitContext *s, uint32_t value)
Write exactly 32 bits into a bitstream.
Definition put_bits.h:301
const char * name
Definition qsvenc.c:142
enum AVPixelFormat avpriv_pix_fmt_find(enum PixelFormatTagLists list, unsigned fourcc)
Definition raw.c:78
Raw Video Codec.
@ PIX_FMT_LIST_MOV
Definition raw.h:40
int ff_get_packet_palette(AVFormatContext *s, AVPacket *pkt, int ret, uint32_t *palette)
Retrieves the palette from a packet, either from side data, or appended to the video data in the pack...
Definition rawutils.c:77
int ff_reshuffle_raw_rgb(AVFormatContext *s, AVPacket **ppkt, AVCodecParameters *par, int expected_stride)
Reshuffles the lines to use the user specified stride.
Definition rawutils.c:27
const AVCodecTag ff_codec_bmp_tags[]
Definition riff.c:36
const AVCodecTag ff_codec_wav_tags[]
Definition riff.c:525
internal header for RIFF based (de)muxers do NOT include this in end user applications
#define FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX
Tell ff_put_wav_header() to use WAVEFORMATEX even for PCM codecs.
Definition riff.h:53
int ff_put_wav_header(AVFormatContext *s, AVIOContext *pb, AVCodecParameters *par, int flags)
Write WAVEFORMAT header structure.
Definition riffenc.c:54
#define av_bswap16
Definition bswap.h:28
#define FF_RTP_FLAG_OPTS(ctx, fieldname)
Definition rtpenc.h:74
#define FF_ARRAY_ELEMS(a)
#define snprintf
Definition snprintf.h:34
unsigned int pos
Definition spdifenc.c:431
double strtod(const char *, char **)
Coded AC-3 header values up to the lfeon element, plus derived values.
uint8_t complexity_index_type_a
int substreamid
substream identification
int num_blocks
number of audio blocks
Ambient viewing environment metadata as defined by H.274.
AVRational ambient_illuminance
Environmental illuminance of the ambient viewing environment in lux.
AVRational ambient_light_x
Normalized x chromaticity coordinate of the environmental ambient light in the nominal viewing enviro...
AVRational ambient_light_y
Normalized y chromaticity coordinate of the environmental ambient light in the nominal viewing enviro...
This structure describes the bitrate properties of an encoded bitstream.
Definition defs.h:282
int64_t avg_bitrate
Average bitrate of the stream, in bits per second.
Definition defs.h:297
int64_t max_bitrate
Maximum bitrate of the stream, in bits per second.
Definition defs.h:287
int64_t buffer_size
The size of the buffer to which the ratecontrol is applied, in bits.
Definition defs.h:303
An AVChannelLayout holds information about the channel layout of audio data.
int nb_channels
Number of channels in this layout.
Describe the class of an AVClass context structure.
Definition log.h:76
This struct describes the properties of an encoded stream.
Definition codec_par.h:49
enum AVColorSpace color_space
Definition codec_par.h:192
int extradata_size
Size of the extradata content in bytes.
Definition codec_par.h:75
int frame_size
Audio frame size, if known.
Definition codec_par.h:227
enum AVFieldOrder field_order
The order of the fields in interlaced video.
Definition codec_par.h:182
int height
The height of the video frame in pixels.
Definition codec_par.h:150
int nb_coded_side_data
Amount of entries in coded_side_data.
Definition codec_par.h:88
int bits_per_coded_sample
The number of bits per sample in the codedwords.
Definition codec_par.h:113
AVChannelLayout ch_layout
The channel layout and number of channels.
Definition codec_par.h:207
int width
The width of the video frame in pixels.
Definition codec_par.h:143
int64_t bit_rate
The average bitrate of the encoded data (in bits per second).
Definition codec_par.h:99
enum AVMediaType codec_type
General type of the encoded data.
Definition codec_par.h:53
int profile
Codec-specific bitstream restrictions that the stream conforms to.
Definition codec_par.h:135
int block_align
The number of bytes per coded audio frame, required by some formats.
Definition codec_par.h:221
int bits_per_raw_sample
The number of valid bits in each output sample.
Definition codec_par.h:130
AVRational sample_aspect_ratio
The aspect ratio (width/height) which a single pixel should have when displayed.
Definition codec_par.h:161
uint32_t codec_tag
Additional information about the codec (corresponds to the AVI FOURCC).
Definition codec_par.h:61
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
Definition codec_par.h:71
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition codec_par.h:57
enum AVColorPrimaries color_primaries
Definition codec_par.h:190
int sample_rate
The number of audio samples per second.
Definition codec_par.h:213
enum AVColorTransferCharacteristic color_trc
Definition codec_par.h:191
AVPacketSideData * coded_side_data
Additional data associated with the entire stream.
Definition codec_par.h:83
enum AVColorRange color_range
Additional colorspace characteristics.
Definition codec_par.h:189
enum AVCodecID id
Definition internal.h:43
unsigned int tag
Definition internal.h:44
int depth
Number of bits in the component.
Definition pixdesc.h:57
Content light level needed by to transmit HDR over HDMI (CTA-861.3).
unsigned MaxFALL
Max average light level per frame (cd/m^2).
unsigned MaxCLL
Max content light level (cd/m^2).
char * key
Definition dict.h:91
char * value
Definition dict.h:92
This describes info used to initialize an encryption key system.
Format I/O context.
Definition avformat.h:1333
int flags
Flags modifying the (de)muxer behaviour.
Definition avformat.h:1484
int strict_std_compliance
Allow non-standard and experimental extension.
Definition avformat.h:1707
Bytestream IO Context.
Definition avio.h:160
Mastering display metadata capable of representing the color volume of the display used to master the...
AVOption.
Definition opt.h:428
This structure stores auxiliary information for decoding, presenting, or otherwise processing the cod...
Definition packet.h:424
uint8_t * data
Definition packet.h:425
This structure stores compressed data.
Definition packet.h:580
int stream_index
Definition packet.h:605
int size
Definition packet.h:604
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
Definition packet.h:621
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition packet.h:596
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed.
Definition packet.h:602
uint8_t * data
Definition packet.h:603
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition pixdesc.h:69
AVComponentDescriptor comp[4]
Parameters that describe how pixels are packed.
Definition pixdesc.h:105
uint8_t log2_chroma_w
Amount to shift the luma width right to find the chroma width.
Definition pixdesc.h:80
uint8_t log2_chroma_h
Amount to shift the luma height right to find the chroma height.
Definition pixdesc.h:89
uint8_t nb_components
The number of components each pixel has, (1-4)
Definition pixdesc.h:71
This structure supplies correlation between a packet timestamp and a wall clock production time.
Definition defs.h:331
int64_t wallclock
A UTC timestamp, in microseconds, since Unix epoch (e.g, av_gettime()).
Definition defs.h:335
Rational number (pair of numerator and denominator).
Definition rational.h:58
int num
Numerator.
Definition rational.h:59
int den
Denominator.
Definition rational.h:60
This structure describes how to handle spherical videos, outlining information about projection,...
Definition spherical.h:100
uint32_t bound_left
Distance from the left edge.
Definition spherical.h:185
enum AVSphericalProjection projection
Projection type.
Definition spherical.h:104
uint32_t bound_top
Distance from the top edge.
Definition spherical.h:186
uint32_t bound_bottom
Distance from the bottom edge.
Definition spherical.h:188
uint32_t bound_right
Distance from the right edge.
Definition spherical.h:187
int32_t pitch
Rotation around the right vector [-90, 90].
Definition spherical.h:145
int32_t roll
Rotation around the forward vector [-180, 180].
Definition spherical.h:146
int32_t yaw
Rotation around the up vector [-180, 180].
Definition spherical.h:144
uint32_t padding
Number of pixels to pad from the edge of each cube face.
Definition spherical.h:200
Stereo 3D type: this structure describes how two videos are packed within a single video surface,...
Definition stereo3d.h:203
enum AVStereo3DType type
How views are packed within the video.
Definition stereo3d.h:207
uint32_t baseline
The distance between the centres of the lenses of the camera system, in micrometers.
Definition stereo3d.h:228
AVRational horizontal_disparity_adjustment
Relative shift of the left and right images, which changes the zero parallax plane.
Definition stereo3d.h:234
enum AVStereo3DPrimaryEye primary_eye
Which eye is the primary eye when rendering in 2D.
Definition stereo3d.h:222
int flags
Additional information about the frame packing.
Definition stereo3d.h:212
AVRational horizontal_field_of_view
Horizontal field of view, in degrees.
Definition stereo3d.h:239
enum AVStereo3DView view
Determines which views are packed.
Definition stereo3d.h:217
AVStreamGroupLayeredVideo is meant to define the relation between a base layer video stream and a sep...
Definition avformat.h:1093
int height
Height of the final image for presentation.
Definition avformat.h:1118
unsigned int el_index
Index of the enhancement layer stream in AVStreamGroup.
Definition avformat.h:1102
int width
Width of the final stream for presentation.
Definition avformat.h:1114
AVStreamGroupTREF is meant to define the relation between video, audio, or subtitle streams,...
Definition avformat.h:1137
unsigned int metadata_index
Index of the metadata stream in the AVStreamGroup.
Definition avformat.h:1143
union AVStreamGroup::@166361102046003066253145020066347265153020354020 params
Group type-specific parameters.
enum AVStreamGroupParamsType type
Group type.
Definition avformat.h:1186
unsigned int nb_streams
Number of elements in AVStreamGroup.streams.
Definition avformat.h:1221
struct AVStreamGroupTREF * tref
Definition avformat.h:1203
AVStream ** streams
A list of streams in the group.
Definition avformat.h:1234
struct AVStreamGroupLayeredVideo * layered_video
Definition avformat.h:1195
Stream structure.
Definition avformat.h:766
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition avformat.h:789
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown)
Definition avformat.h:844
int64_t nb_frames
number of frames in this stream if known or 0
Definition avformat.h:827
AVDictionary * metadata
Definition avformat.h:846
void * priv_data
Definition avformat.h:791
int id
Format-specific stream ID.
Definition avformat.h:778
int index
stream index in AVFormatContext
Definition avformat.h:772
AVRational avg_frame_rate
Average framerate.
Definition avformat.h:855
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented.
Definition avformat.h:805
int disposition
Stream disposition - a combination of AV_DISPOSITION_* flags.
Definition avformat.h:835
uint32_t flags
flags such as drop frame, +24 hours support, ...
Definition timecode.h:43
int start
timecode frame start (first base frame number)
Definition timecode.h:42
AVPacket * pkt
Used to hold temporary packets for the generic demuxing code.
Definition internal.h:111
Definition isom.h:68
unsigned int count
Definition isom.h:69
int offset
Definition isom.h:70
int64_t offset
Definition movenc.h:81
int64_t tfrf_offset
Definition movenc.h:84
int64_t time
Definition movenc.h:82
int64_t duration
Definition movenc.h:83
uint32_t flags
Definition movenc.h:62
unsigned int chunkNum
Chunk number if the current entry is a chunk start otherwise 0.
Definition movenc.h:56
int64_t pts
Definition movenc.h:52
int cts
Definition movenc.h:58
unsigned int samples_in_chunk
Definition movenc.h:55
unsigned int stsd_index
Definition movenc.h:54
unsigned int entries
Definition movenc.h:57
AVProducerReferenceTime prft
Definition movenc.h:63
int64_t dts
Definition movenc.h:51
uint64_t pos
Definition movenc.h:50
unsigned int size
Definition movenc.h:53
struct AVAESCTR * aes_ctr
Definition movenccenc.h:41
int reserved_moov_size
0 for disabled, -1 for automatic, size otherwise
Definition movenc.h:241
char * major_brand
Definition movenc.h:244
int64_t mdat_pos
Definition movenc.h:219
AVFormatContext * fc
Definition movenc.h:247
AVPacket * pkt
Definition movenc.h:249
int nb_tracks
Definition movenc.h:216
int iods_skip
Definition movenc.h:226
int chapter_track
qt chapter track number
Definition movenc.h:218
uint64_t mdat_size
Definition movenc.h:220
char * encryption_scheme_str
Definition movenc.h:257
int movie_timescale
Definition movenc.h:270
float gamma
Definition movenc.h:252
int avif_loop_count
Definition movenc.h:275
uint8_t * encryption_key
Definition movenc.h:259
int nb_streams
Definition movenc.h:215
int fragments
Definition movenc.h:231
int encryption_key_len
Definition movenc.h:260
int write_btrt
Definition movenc.h:266
int avif_extent_length[2]
Definition movenc.h:273
int empty_hdlr_name
Definition movenc.h:269
int missing_duration_warned
Definition movenc.h:255
AVIOContext * mdat_buf
Definition movenc.h:236
uint8_t * encryption_kid
Definition movenc.h:261
int min_fragment_duration
Definition movenc.h:233
MOVPrftBox write_prft
Definition movenc.h:268
int64_t reserved_header_pos
Definition movenc.h:242
int per_stream_grouping
Definition movenc.h:246
int iods_video_profile
Definition movenc.h:227
MOVTrack * tracks
Definition movenc.h:221
int frag_interleave
Definition movenc.h:254
int max_fragment_duration
Definition movenc.h:232
int track_ids_ok
Definition movenc.h:265
int video_track_timescale
Definition movenc.h:239
int max_fragment_size
Definition movenc.h:234
int use_editlist
Definition movenc.h:251
int nb_meta_tmcd
number of new created tmcd track based on metadata (aka not data copy)
Definition movenc.h:217
int moov_written
Definition movenc.h:230
int use_stream_ids_as_track_ids
Definition movenc.h:264
MOVEncryptionScheme encryption_scheme
Definition movenc.h:258
int first_trun
Definition movenc.h:237
int64_t avif_extent_pos[2]
Definition movenc.h:272
int iods_audio_profile
Definition movenc.h:228
int is_animated_avif
Definition movenc.h:274
int write_tmcd
Definition movenc.h:267
int64_t time
Definition movenc.h:214
int encryption_kid_len
Definition movenc.h:262
int ism_lookahead
Definition movenc.h:235
Definition isom.h:63
unsigned int count
Definition isom.h:64
unsigned int duration
Definition isom.h:65
int track_id
Definition movenc.h:123
int mono_as_fc
Definition movenc.h:127
int entry
Definition movenc.h:97
int64_t start_cts
Definition movenc.h:138
AVPacket * cover_image
Definition movenc.h:157
int * src_track
the tracks that this hint (or tmcd) track describes
Definition movenc.h:146
uint32_t default_size
Definition movenc.h:154
struct MOVTrack::@041066134315003153207320140045232207171303033040 vc1_info
int nb_src_track
Definition movenc.h:145
int first_iamf_idx
Definition movenc.h:192
int first_packet_seen
Definition movenc.h:171
int64_t dts_shift
Definition movenc.h:142
int last_iamf_idx
Definition movenc.h:193
int audio_vbr
Definition movenc.h:133
int tag
stsd fourcc
Definition movenc.h:124
uint32_t flags
Definition movenc.h:117
uint32_t timecode_flags
Definition movenc.h:121
int * extradata_size
Definition movenc.h:107
int64_t data_offset
Definition movenc.h:160
int nb_tref_tags
Definition movenc.h:135
int language
Definition movenc.h:122
PacketList squashed_packet_queue
Definition movenc.h:189
AVCodecParameters * par
Definition movenc.h:126
unsigned frag_info_capacity
Definition movenc.h:166
int nb_frag_info
Definition movenc.h:164
int multichannel_as_mono
Definition movenc.h:128
AVIOContext * mdat_buf
Definition movenc.h:159
uint64_t time
Definition movenc.h:99
AVIOContext * iamf_buf
Definition movenc.h:194
int entry_version
Definition movenc.h:96
int packet_entry
Definition movenc.h:174
int is_unaligned_qt_rgb
Definition movenc.h:185
long sample_count
Definition movenc.h:109
uint32_t palette[AVPALETTE_COUNT]
Definition movenc.h:182
int has_disposable
Definition movenc.h:113
struct IAMFContext * iamf
Definition movenc.h:191
void * eac3_priv
Definition movenc.h:178
int64_t elst_end_pts
Definition movenc.h:140
MOVIentry * cluster_written
Definition movenc.h:131
int64_t end_pts
Definition movenc.h:139
uint8_t ** extradata
Definition movenc.h:106
unsigned int squash_fragment_samples_to_one
Definition movenc.h:187
int last_sample_is_subtitle_end
Definition movenc.h:101
MOVFragmentInfo * frag_info
Definition movenc.h:165
int entries_flushed
Definition movenc.h:162
int frag_discont
Definition movenc.h:161
uint32_t default_sample_flags
Definition movenc.h:153
int pal_done
Definition movenc.h:183
MovTag * tref_tags
Definition movenc.h:136
MOVIentry * cluster
Definition movenc.h:130
uint32_t max_packet_size
Definition movenc.h:150
int hint_track
the track that hints this track, -1 if no hint track is set
Definition movenc.h:144
struct APVDecoderConfigurationRecord * apv
Definition movenc.h:196
int64_t default_duration
Definition movenc.h:152
AVStream * st
Definition movenc.h:125
MOVMuxCencContext cenc
Definition movenc.h:180
int has_keyframes
Definition movenc.h:112
long sample_size
Definition movenc.h:110
int first_packet_entry
Definition movenc.h:170
int slices
Definition movenc.h:175
int entry_written
Definition movenc.h:97
int stsd_count
Definition movenc.h:104
int64_t start_dts
Definition movenc.h:137
int first_frag_written
Definition movenc.h:172
int mode
Definition movenc.h:95
unsigned timescale
Definition movenc.h:98
int packet_seq
Definition movenc.h:173
int first_packet_seq
Definition movenc.h:169
int64_t track_duration
Definition movenc.h:100
long chunkCount
Definition movenc.h:111
AVFormatContext * rtp_ctx
the format context for the hinting rtp muxer
Definition movenc.h:147
unsigned cluster_capacity
Definition movenc.h:132
int last_stsd_index
Definition movenc.h:105
int height
active picture (w/o VBI) height for D-10/IMX
Definition movenc.h:134
int end_reliable
Definition movenc.h:141
const char * value
Definition isom.h:489
uint32_t * id
trackID of the referenced track
Definition movenc.h:91
PacketListEntry * head
uint8_t num_ind_sub
Definition movenc.c:394
uint8_t fscod
Definition movenc.c:397
uint16_t data_rate
Definition movenc.c:391
int8_t ac3_bit_rate_code
Definition movenc.c:392
uint8_t complexity_index_type_a
Definition movenc.c:416
uint8_t num_blocks
Definition movenc.c:387
struct eac3_info::@032224065145233261074362213314253377146303165010 substream[1]
uint8_t acmod
Definition movenc.c:405
uint8_t bsid
Definition movenc.c:399
AVPacket * pkt
Definition movenc.c:384
uint8_t eof
Definition movenc.c:385
uint16_t chan_loc
Definition movenc.c:412
uint8_t ec3_done
Definition movenc.c:386
uint8_t num_dep_sub
Definition movenc.c:410
uint8_t lfeon
Definition movenc.c:407
uint8_t bsmod
Definition movenc.c:403
uint32_t avg_bit_rate
Average rate in bits/second over the entire presentation.
Definition movenc.c:735
uint32_t max_bit_rate
Maximum rate in bits/second over any window of one second.
Definition movenc.c:734
uint32_t buffer_size
Size of the decoding buffer for the elementary stream in bytes.
Definition movenc.c:733
Definition rpzaenc.c:60
uint8_t level
Definition svq3.c:208
#define lrint
Definition tablegen.h:53
#define av_free(p)
#define av_malloc_array(a, b)
#define av_mallocz(s)
#define avpriv_request_sample(...)
#define av_freep(p)
#define av_log(a,...)
static uint8_t tmp[40]
Definition aes_ctr.c:52
static int ref[MAX_W *MAX_W]
#define height
Definition dsp.h:89
#define width
Definition dsp.h:89
int av_timecode_init_from_string(AVTimecode *tc, AVRational rate, const char *str, void *log_ctx)
Parse timecode representation (hh:mm:ss[:;.
Definition timecode.c:241
Timecode helpers header.
@ AV_TIMECODE_FLAG_DROPFRAME
timecode is drop frame
Definition timecode.h:36
static int64_t pts
int size
UUID parsing and serialization utilities.
#define AV_UUID_LEN
Definition uuid.h:57
uint8_t AVUUID[AV_UUID_LEN]
Definition uuid.h:60
static int write_trailer(AVFormatContext *s1)
Definition v4l2enc.c:101
enum AVCodecID codec_id
static av_always_inline int vc1_unescape_buffer(const uint8_t *src, int size, uint8_t *dst)
Definition vc1_common.h:70
static av_always_inline const uint8_t * find_next_marker(const uint8_t *src, const uint8_t *end)
Find VC-1 marker in buffer.
Definition vc1_common.h:59
@ PROFILE_ADVANCED
Definition vc1_common.h:52
@ VC1_CODE_SEQHDR
Definition vc1_common.h:40
@ VC1_CODE_SLICE
Definition vc1_common.h:36
@ VC1_CODE_ENTRYPOINT
Definition vc1_common.h:39
const char * g
Definition vf_curves.c:128
static double cr(void *priv, double x, double y)
Definition vf_geq.c:248
static double cb(void *priv, double x, double y)
Definition vf_geq.c:247
static float mean(const float *input, int size)
Definition vf_nnedi.c:861
static const Range full_range
static void copy(const float *p1, float *p2, const int length)
int len
int ff_isom_write_vpcc(void *logctx, AVIOContext *pb, const uint8_t *data, int len, const AVCodecParameters *par)
Writes VP codec configuration to the provided AVIOContext.
Definition vpcc.c:204
internal header for VPx codec configuration utilities.
static double c[64]
int ff_vvc_annexb2mp4_buf(const uint8_t *buf_in, uint8_t **buf_out, int *size, int filter_ps, int *ps_count)
Writes Annex B formatted H.266/VVC NAL units to a data buffer.
Definition vvc.c:858
int ff_isom_write_vvcc(AVIOContext *pb, const uint8_t *data, int size, int ps_array_completeness)
Writes H.266/VVC extradata (parameter sets, declarative SEI NAL units) to the provided AVIOContext.
Definition vvc.c:879
int ff_vvc_annexb2mp4(AVIOContext *pb, const uint8_t *buf_in, int size, int filter_ps, int *ps_count)
Writes Annex B formatted H.266/VVC NAL units to the provided AVIOContext.
Definition vvc.c:810