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