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
3587static uint16_t mov_graphics_mode(MOVTrack *track)
3588{
3589 if (track->mode != MODE_MOV)
3590 return 0; /* ISO/IEC 14496-12 doesn't define any other modes */
3591
3592 switch (track->par->alpha_mode) {
3593 default: return MOV_GRAPHICS_MODE_COPY;
3596 }
3597}
3598
3600{
3601 avio_wb32(pb, 0x14); /* size (always 0x14) */
3602 ffio_wfourcc(pb, "vmhd");
3603 avio_wb32(pb, 0x01); /* version & flags */
3604 avio_wb16(pb, mov_graphics_mode(track));
3605 for (int i = 0; i < 3; i++)
3606 avio_wb16(pb, 0); /* opcolor */
3607 return 0x14;
3608}
3609
3610static int is_clcp_track(MOVTrack *track)
3611{
3612 return track->tag == MKTAG('c','7','0','8') ||
3613 track->tag == MKTAG('c','6','0','8');
3614}
3615
3617{
3618 MOVMuxContext *mov = s->priv_data;
3619 const char *hdlr, *descr = NULL, *hdlr_type = NULL;
3620 int64_t pos = avio_tell(pb);
3621 size_t descr_len;
3622
3623 hdlr = "dhlr";
3624 hdlr_type = "url ";
3625 descr = "DataHandler";
3626
3627 if (track) {
3628 hdlr = (track->mode == MODE_MOV) ? "mhlr" : "\0\0\0\0";
3629 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
3630 if (track->mode == MODE_AVIF) {
3631 hdlr_type = (track == &mov->tracks[0]) ? "pict" : "auxv";
3632 descr = "PictureHandler";
3633 } else {
3634 hdlr_type = "vide";
3635 descr = "VideoHandler";
3636 }
3637 } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) {
3638 hdlr_type = "soun";
3639 descr = "SoundHandler";
3640 } else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE) {
3641 if (is_clcp_track(track)) {
3642 hdlr_type = "clcp";
3643 descr = "ClosedCaptionHandler";
3644 } else {
3645 if (track->tag == MKTAG('t','x','3','g')) {
3646 hdlr_type = "sbtl";
3647 } else if (track->tag == MKTAG('m','p','4','s')) {
3648 hdlr_type = "subp";
3649 } else if (track->tag == MOV_MP4_TTML_TAG) {
3650 hdlr_type = "subt";
3651 } else {
3652 hdlr_type = "text";
3653 }
3654 descr = "SubtitleHandler";
3655 }
3656 } else if (track->par->codec_tag == MKTAG('r','t','p',' ')) {
3657 hdlr_type = "hint";
3658 descr = "HintHandler";
3659 } else if (track->par->codec_tag == MKTAG('t','m','c','d')) {
3660 hdlr_type = "tmcd";
3661 descr = "TimeCodeHandler";
3662 } else if (track->par->codec_tag == MKTAG('g','p','m','d')) {
3663 hdlr_type = "meta";
3664 descr = "GoPro MET"; // GoPro Metadata
3665 } else {
3667 "Unknown hdlr_type for %s, writing dummy values\n",
3668 av_fourcc2str(track->par->codec_tag));
3669 }
3670 if (track->st) {
3671 // hdlr.name is used by some players to identify the content title
3672 // of the track. So if an alternate handler description is
3673 // specified, use it.
3675 t = av_dict_get(track->st->metadata, "handler_name", NULL, 0);
3676 if (t && utf8len(t->value))
3677 descr = t->value;
3678 }
3679 }
3680
3681 if (mov->empty_hdlr_name) /* expressly allowed by QTFF and not prohibited in ISO 14496-12 8.4.3.3 */
3682 descr = "";
3683
3684 avio_wb32(pb, 0); /* size */
3685 ffio_wfourcc(pb, "hdlr");
3686 avio_wb32(pb, 0); /* Version & flags */
3687 avio_write(pb, hdlr, 4); /* handler */
3688 ffio_wfourcc(pb, hdlr_type); /* handler type */
3689 avio_wb32(pb, 0); /* reserved */
3690 avio_wb32(pb, 0); /* reserved */
3691 avio_wb32(pb, 0); /* reserved */
3692 descr_len = strlen(descr);
3693 if (!track || track->mode == MODE_MOV)
3694 avio_w8(pb, descr_len); /* pascal string */
3695 avio_write(pb, descr, descr_len); /* handler description */
3696 if (track && track->mode != MODE_MOV)
3697 avio_w8(pb, 0); /* c string */
3698 return update_size(pb, pos);
3699}
3700
3701static int mov_write_pitm_tag(AVIOContext *pb, int item_id)
3702{
3703 int64_t pos = avio_tell(pb);
3704 avio_wb32(pb, 0); /* size */
3705 ffio_wfourcc(pb, "pitm");
3706 avio_wb32(pb, 0); /* Version & flags */
3707 avio_wb16(pb, item_id); /* item_id */
3708 return update_size(pb, pos);
3709}
3710
3712{
3713 int64_t pos = avio_tell(pb);
3714 avio_wb32(pb, 0); /* size */
3715 ffio_wfourcc(pb, "iloc");
3716 avio_wb32(pb, 0); /* Version & flags */
3717 avio_w8(pb, (4 << 4) + 4); /* offset_size(4) and length_size(4) */
3718 avio_w8(pb, 0); /* base_offset_size(4) and reserved(4) */
3719 avio_wb16(pb, mov->nb_streams); /* item_count */
3720
3721 for (int i = 0; i < mov->nb_streams; i++) {
3722 avio_wb16(pb, i + 1); /* item_id */
3723 avio_wb16(pb, 0); /* data_reference_index */
3724 avio_wb16(pb, 1); /* extent_count */
3725 mov->avif_extent_pos[i] = avio_tell(pb);
3726 avio_wb32(pb, 0); /* extent_offset (written later) */
3727 // For animated AVIF, we simply write the first packet's size.
3728 avio_wb32(pb, mov->avif_extent_length[i]); /* extent_length */
3729 }
3730
3731 return update_size(pb, pos);
3732}
3733
3735{
3736 int64_t iinf_pos = avio_tell(pb);
3737 avio_wb32(pb, 0); /* size */
3738 ffio_wfourcc(pb, "iinf");
3739 avio_wb32(pb, 0); /* Version & flags */
3740 avio_wb16(pb, mov->nb_streams); /* entry_count */
3741
3742 for (int i = 0; i < mov->nb_streams; i++) {
3743 int64_t infe_pos = avio_tell(pb);
3744 avio_wb32(pb, 0); /* size */
3745 ffio_wfourcc(pb, "infe");
3746 avio_w8(pb, 0x2); /* Version */
3747 avio_wb24(pb, 0); /* flags */
3748 avio_wb16(pb, i + 1); /* item_id */
3749 avio_wb16(pb, 0); /* item_protection_index */
3750 avio_write(pb, "av01", 4); /* item_type */
3751 avio_write(pb, !i ? "Color\0" : "Alpha\0", 6); /* item_name */
3752 update_size(pb, infe_pos);
3753 }
3754
3755 return update_size(pb, iinf_pos);
3756}
3757
3758
3760{
3761 int64_t auxl_pos;
3762 int64_t iref_pos = avio_tell(pb);
3763 avio_wb32(pb, 0); /* size */
3764 ffio_wfourcc(pb, "iref");
3765 avio_wb32(pb, 0); /* Version & flags */
3766
3767 auxl_pos = avio_tell(pb);
3768 avio_wb32(pb, 0); /* size */
3769 ffio_wfourcc(pb, "auxl");
3770 avio_wb16(pb, 2); /* from_item_ID */
3771 avio_wb16(pb, 1); /* reference_count */
3772 avio_wb16(pb, 1); /* to_item_ID */
3773 update_size(pb, auxl_pos);
3774
3775 return update_size(pb, iref_pos);
3776}
3777
3779 int stream_index)
3780{
3781 int64_t pos = avio_tell(pb);
3782 avio_wb32(pb, 0); /* size */
3783 ffio_wfourcc(pb, "ispe");
3784 avio_wb32(pb, 0); /* Version & flags */
3785 avio_wb32(pb, s->streams[stream_index]->codecpar->width); /* image_width */
3786 avio_wb32(pb, s->streams[stream_index]->codecpar->height); /* image_height */
3787 return update_size(pb, pos);
3788}
3789
3791 int stream_index)
3792{
3793 int64_t pos = avio_tell(pb);
3794 const AVPixFmtDescriptor *pixdesc =
3795 av_pix_fmt_desc_get(s->streams[stream_index]->codecpar->format);
3796 avio_wb32(pb, 0); /* size */
3797 ffio_wfourcc(pb, "pixi");
3798 avio_wb32(pb, 0); /* Version & flags */
3799 avio_w8(pb, pixdesc->nb_components); /* num_channels */
3800 for (int i = 0; i < pixdesc->nb_components; ++i) {
3801 avio_w8(pb, pixdesc->comp[i].depth); /* bits_per_channel */
3802 }
3803 return update_size(pb, pos);
3804}
3805
3807{
3808 int64_t pos = avio_tell(pb);
3809 avio_wb32(pb, 0); /* size */
3810 ffio_wfourcc(pb, "ipco");
3811 for (int i = 0; i < mov->nb_streams; i++) {
3812 mov_write_ispe_tag(pb, mov, s, i);
3813 mov_write_pixi_tag(pb, mov, s, i);
3814 mov_write_av1c_tag(pb, &mov->tracks[i]);
3815 if (!i)
3816 mov_write_colr_tag(pb, &mov->tracks[0], 0);
3817 else
3818 mov_write_aux_tag(pb, "auxC");
3819 }
3820 return update_size(pb, pos);
3821}
3822
3824{
3825 int64_t pos = avio_tell(pb);
3826 avio_wb32(pb, 0); /* size */
3827 ffio_wfourcc(pb, "ipma");
3828 avio_wb32(pb, 0); /* Version & flags */
3829 avio_wb32(pb, mov->nb_streams); /* entry_count */
3830
3831 for (int i = 0, index = 1; i < mov->nb_streams; i++) {
3832 avio_wb16(pb, i + 1); /* item_ID */
3833 avio_w8(pb, 4); /* association_count */
3834
3835 // ispe association.
3836 avio_w8(pb, index++); /* essential and property_index */
3837 // pixi association.
3838 avio_w8(pb, index++); /* essential and property_index */
3839 // av1C association.
3840 avio_w8(pb, 0x80 | index++); /* essential and property_index */
3841 // colr/auxC association.
3842 avio_w8(pb, index++); /* essential and property_index */
3843 }
3844 return update_size(pb, pos);
3845}
3846
3848{
3849 int64_t pos = avio_tell(pb);
3850 avio_wb32(pb, 0); /* size */
3851 ffio_wfourcc(pb, "iprp");
3852 mov_write_ipco_tag(pb, mov, s);
3853 mov_write_ipma_tag(pb, mov, s);
3854 return update_size(pb, pos);
3855}
3856
3858{
3859 /* This atom must be present, but leaving the values at zero
3860 * seems harmless. */
3861 avio_wb32(pb, 28); /* size */
3862 ffio_wfourcc(pb, "hmhd");
3863 avio_wb32(pb, 0); /* version, flags */
3864 avio_wb16(pb, 0); /* maxPDUsize */
3865 avio_wb16(pb, 0); /* avgPDUsize */
3866 avio_wb32(pb, 0); /* maxbitrate */
3867 avio_wb32(pb, 0); /* avgbitrate */
3868 avio_wb32(pb, 0); /* reserved */
3869 return 28;
3870}
3871
3873{
3874 int64_t pos = avio_tell(pb);
3875 int ret;
3876
3877 avio_wb32(pb, 0); /* size */
3878 ffio_wfourcc(pb, "minf");
3879 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO)
3880 mov_write_vmhd_tag(pb, track);
3881 else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO)
3883 else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE) {
3884 if (track->tag == MKTAG('t','e','x','t') || is_clcp_track(track)) {
3885 mov_write_gmhd_tag(pb, track);
3886 } else if (track->tag == MOV_MP4_TTML_TAG) {
3888 } else {
3890 }
3891 } else if (track->tag == MKTAG('r','t','p',' ')) {
3893 } else if (track->tag == MKTAG('t','m','c','d')) {
3894 if (track->mode != MODE_MOV)
3896 else
3897 mov_write_gmhd_tag(pb, track);
3898 } else if (track->tag == MKTAG('g','p','m','d')) {
3899 mov_write_gmhd_tag(pb, track);
3900 }
3901 if (track->mode == MODE_MOV) /* ISO 14496-12 8.4.3.1 specifies hdlr only within mdia or meta boxes */
3904 if ((ret = mov_write_stbl_tag(s, pb, mov, track)) < 0)
3905 return ret;
3906 return update_size(pb, pos);
3907}
3908
3909static void get_pts_range(MOVMuxContext *mov, MOVTrack *track,
3910 int64_t *start, int64_t *end, int elst, int mdhd)
3911{
3912 if (track->tag == MKTAG('t','m','c','d') && mov->nb_meta_tmcd && track->nb_src_track) {
3913 // tmcd tracks gets track_duration set in mov_write_moov_tag from
3914 // another track's duration, while the end_pts may be left at zero.
3915 // Calculate the pts duration for that track instead.
3916 get_pts_range(mov, &mov->tracks[*track->src_track], start, end, elst, mdhd);
3917 *start = av_rescale(*start, track->timescale,
3918 mov->tracks[*track->src_track].timescale);
3919 *end = av_rescale(*end, track->timescale,
3920 mov->tracks[*track->src_track].timescale);
3921 return;
3922 }
3923 if (!mdhd && track->end_pts != AV_NOPTS_VALUE &&
3924 track->start_dts != AV_NOPTS_VALUE &&
3925 track->start_cts != AV_NOPTS_VALUE) {
3926 *start = track->start_dts + track->start_cts;
3927 *end = elst ? track->elst_end_pts : track->end_pts;
3928 return;
3929 }
3930 *start = 0;
3931 *end = track->track_duration;
3932}
3933
3935{
3936 int64_t start, end;
3937 get_pts_range(mov, track, &start, &end, 0, 1);
3938 return end - start;
3939}
3940
3941// Calculate the actual duration of the track, after edits.
3942// If it starts with a pts < 0, that is removed by the edit list.
3943// If it starts with a pts > 0, the edit list adds a delay before that.
3944// Thus, with edit lists enabled, the post-edit output of the file is
3945// starting with pts=0.
3947{
3948 int64_t start, end;
3949 get_pts_range(mov, track, &start, &end, 0, 0);
3950 if (mov->use_editlist != 0)
3951 start = 0;
3952 return end - start;
3953}
3954
3956{
3957 int64_t start, end;
3958 get_pts_range(mov, track, &start, &end, 1, 0);
3959 return end - start;
3960}
3961
3963{
3964 if (track && track->mode == MODE_ISM)
3965 return 1;
3966 if (duration < INT32_MAX)
3967 return 0;
3968 return 1;
3969}
3970
3972 MOVTrack *track)
3973{
3975 int version = mov_mdhd_mvhd_tkhd_version(mov, track, duration);
3976
3977 (version == 1) ? avio_wb32(pb, 44) : avio_wb32(pb, 32); /* size */
3978 ffio_wfourcc(pb, "mdhd");
3979 avio_w8(pb, version);
3980 avio_wb24(pb, 0); /* flags */
3981 if (version == 1) {
3982 avio_wb64(pb, track->time);
3983 avio_wb64(pb, track->time);
3984 } else {
3985 avio_wb32(pb, track->time); /* creation time */
3986 avio_wb32(pb, track->time); /* modification time */
3987 }
3988 avio_wb32(pb, track->timescale); /* time scale (sample rate for audio) */
3989 if (!track->entry && mov->mode == MODE_ISM)
3990 (version == 1) ? avio_wb64(pb, UINT64_C(0xffffffffffffffff)) : avio_wb32(pb, 0xffffffff);
3991 else if (!track->entry)
3992 (version == 1) ? avio_wb64(pb, 0) : avio_wb32(pb, 0);
3993 else
3994 (version == 1) ? avio_wb64(pb, duration) : avio_wb32(pb, duration); /* duration */
3995 avio_wb16(pb, track->language); /* language */
3996 avio_wb16(pb, 0); /* reserved (quality) */
3997
3998 if (version != 0 && track->mode == MODE_MOV) {
4000 "FATAL error, file duration too long for timebase, this file will not be\n"
4001 "playable with QuickTime. Choose a different timebase with "
4002 "-video_track_timescale or a different container format\n");
4003 }
4004
4005 return 32;
4006}
4007
4009 MOVMuxContext *mov, MOVTrack *track)
4010{
4011 int64_t pos = avio_tell(pb);
4012 int ret;
4013
4014 avio_wb32(pb, 0); /* size */
4015 ffio_wfourcc(pb, "mdia");
4016 mov_write_mdhd_tag(pb, mov, track);
4017 mov_write_hdlr_tag(s, pb, track);
4018 if ((ret = mov_write_minf_tag(s, pb, mov, track)) < 0)
4019 return ret;
4020 return update_size(pb, pos);
4021}
4022
4023/* transformation matrix
4024 |a b u|
4025 |c d v|
4026 |tx ty w| */
4027static void write_matrix(AVIOContext *pb, int16_t a, int16_t b, int16_t c,
4028 int16_t d, int16_t tx, int16_t ty)
4029{
4030 avio_wb32(pb, a << 16); /* 16.16 format */
4031 avio_wb32(pb, b << 16); /* 16.16 format */
4032 avio_wb32(pb, 0); /* u in 2.30 format */
4033 avio_wb32(pb, c << 16); /* 16.16 format */
4034 avio_wb32(pb, d << 16); /* 16.16 format */
4035 avio_wb32(pb, 0); /* v in 2.30 format */
4036 avio_wb32(pb, tx << 16); /* 16.16 format */
4037 avio_wb32(pb, ty << 16); /* 16.16 format */
4038 avio_wb32(pb, 1 << 30); /* w in 2.30 format */
4039}
4040
4042 MOVTrack *track, AVStream *st)
4043{
4045 mov->movie_timescale, track->timescale,
4046 AV_ROUND_UP);
4047 int version;
4049 int group = 0;
4050
4051 uint32_t *display_matrix = NULL;
4052 int i;
4053
4054 if (mov->mode == MODE_AVIF)
4055 if (!mov->avif_loop_count)
4056 duration = INT64_MAX;
4057 else
4058 duration *= mov->avif_loop_count;
4059
4060 if (st) {
4061 const AVPacketSideData *sd;
4062 if (mov->per_stream_grouping)
4063 group = st->index;
4064 else
4065 group = st->codecpar->codec_type;
4066
4070 if (sd && sd->size == 9 * sizeof(*display_matrix))
4071 display_matrix = (uint32_t *)sd->data;
4072 }
4073
4074 if (track->flags & MOV_TRACK_ENABLED)
4076
4078
4079 (version == 1) ? avio_wb32(pb, 104) : avio_wb32(pb, 92); /* size */
4080 ffio_wfourcc(pb, "tkhd");
4081 avio_w8(pb, version);
4082 avio_wb24(pb, flags);
4083 if (version == 1) {
4084 avio_wb64(pb, track->time);
4085 avio_wb64(pb, track->time);
4086 } else {
4087 avio_wb32(pb, track->time); /* creation time */
4088 avio_wb32(pb, track->time); /* modification time */
4089 }
4090 avio_wb32(pb, track->track_id); /* track-id */
4091 avio_wb32(pb, 0); /* reserved */
4092 if (!track->entry && mov->mode == MODE_ISM)
4093 (version == 1) ? avio_wb64(pb, UINT64_C(0xffffffffffffffff)) : avio_wb32(pb, 0xffffffff);
4094 else if (!track->entry)
4095 (version == 1) ? avio_wb64(pb, 0) : avio_wb32(pb, 0);
4096 else
4097 (version == 1) ? avio_wb64(pb, duration) : avio_wb32(pb, duration);
4098
4099 avio_wb32(pb, 0); /* reserved */
4100 avio_wb32(pb, 0); /* reserved */
4101 avio_wb16(pb, 0); /* layer */
4102 avio_wb16(pb, group); /* alternate group) */
4103 /* Volume, only for audio */
4104 if (track->par->codec_type == AVMEDIA_TYPE_AUDIO)
4105 avio_wb16(pb, 0x0100);
4106 else
4107 avio_wb16(pb, 0);
4108 avio_wb16(pb, 0); /* reserved */
4109
4110 /* Matrix structure */
4111 if (display_matrix) {
4112 for (i = 0; i < 9; i++)
4113 avio_wb32(pb, display_matrix[i]);
4114 } else {
4115 write_matrix(pb, 1, 0, 0, 1, 0, 0);
4116 }
4117 /* Track width and height, for visual only */
4118 if (st && (track->par->codec_type == AVMEDIA_TYPE_VIDEO ||
4119 track->par->codec_type == AVMEDIA_TYPE_SUBTITLE)) {
4120 int64_t track_width_1616;
4121 if (track->mode == MODE_MOV || track->mode == MODE_AVIF) {
4122 track_width_1616 = track->par->width * 0x10000ULL;
4123 } else {
4124 track_width_1616 = av_rescale(st->sample_aspect_ratio.num,
4125 track->par->width * 0x10000LL,
4127 if (!track_width_1616 ||
4128 track->height != track->par->height ||
4129 track_width_1616 > UINT32_MAX)
4130 track_width_1616 = track->par->width * 0x10000ULL;
4131 }
4132 if (track_width_1616 > UINT32_MAX) {
4133 av_log(mov->fc, AV_LOG_WARNING, "track width is too large\n");
4134 track_width_1616 = 0;
4135 }
4136 avio_wb32(pb, track_width_1616);
4137 if (track->height > 0xFFFF) {
4138 av_log(mov->fc, AV_LOG_WARNING, "track height is too large\n");
4139 avio_wb32(pb, 0);
4140 } else
4141 avio_wb32(pb, track->height * 0x10000U);
4142 } else {
4143 avio_wb32(pb, 0);
4144 avio_wb32(pb, 0);
4145 }
4146 return 0x5c;
4147}
4148
4150{
4152 track->par->sample_aspect_ratio.den);
4153
4154 int64_t pos = avio_tell(pb);
4155
4156 avio_wb32(pb, 0); /* size */
4157 ffio_wfourcc(pb, "tapt");
4158
4159 avio_wb32(pb, 20);
4160 ffio_wfourcc(pb, "clef");
4161 avio_wb32(pb, 0);
4162 avio_wb32(pb, width << 16);
4163 avio_wb32(pb, track->par->height << 16);
4164
4165 avio_wb32(pb, 20);
4166 ffio_wfourcc(pb, "prof");
4167 avio_wb32(pb, 0);
4168 avio_wb32(pb, width << 16);
4169 avio_wb32(pb, track->par->height << 16);
4170
4171 avio_wb32(pb, 20);
4172 ffio_wfourcc(pb, "enof");
4173 avio_wb32(pb, 0);
4174 avio_wb32(pb, track->par->width << 16);
4175 avio_wb32(pb, track->par->height << 16);
4176
4177 return update_size(pb, pos);
4178}
4179
4180// This box is written in the following cases:
4181// * Seems important for the psp playback. Without it the movie seems to hang.
4182// * Used for specifying the looping behavior of animated AVIF (as specified
4183// in Section 9.6 of the HEIF specification ISO/IEC 23008-12).
4185 MOVTrack *track)
4186{
4188 mov->movie_timescale, track->timescale,
4189 AV_ROUND_UP);
4190 int version = duration < INT32_MAX ? 0 : 1;
4191 int entry_size, entry_count, size;
4192 int64_t delay, start_ct = track->start_cts;
4193 int64_t start_dts = track->start_dts;
4194 int flags = 0;
4195
4196 if (track->entry) {
4197 if (start_dts != track->cluster[0].dts || (start_ct != track->cluster[0].cts && track->cluster[0].dts >= 0)) {
4198
4199 av_log(mov->fc, AV_LOG_DEBUG,
4200 "EDTS using dts:%"PRId64" cts:%d instead of dts:%"PRId64" cts:%"PRId64" tid:%d\n",
4201 track->cluster[0].dts, track->cluster[0].cts,
4202 start_dts, start_ct, track->track_id);
4203 start_dts = track->cluster[0].dts;
4204 start_ct = track->cluster[0].cts;
4205 }
4206 }
4207
4208 delay = av_rescale_rnd(start_dts + start_ct, mov->movie_timescale,
4209 track->timescale, AV_ROUND_DOWN);
4210
4211 if (mov->mode == MODE_AVIF) {
4212 delay = 0;
4213 // Section 9.6.3 of ISO/IEC 23008-12: flags specifies repetition of the
4214 // edit list as follows: (flags & 1) equal to 0 specifies that the edit
4215 // list is not repeated, while (flags & 1) equal to 1 specifies that the
4216 // edit list is repeated.
4217 flags = mov->avif_loop_count != 1;
4218 start_ct = 0;
4219 }
4220
4221 version |= delay < INT32_MAX ? 0 : 1;
4222
4223 entry_size = (version == 1) ? 20 : 12;
4224 entry_count = 1 + (delay > 0);
4225 size = 24 + entry_count * entry_size;
4226
4227 /* write the atom data */
4228 avio_wb32(pb, size);
4229 ffio_wfourcc(pb, "edts");
4230 avio_wb32(pb, size - 8);
4231 ffio_wfourcc(pb, "elst");
4232 avio_w8(pb, version);
4233 avio_wb24(pb, flags); /* flags */
4234
4235 avio_wb32(pb, entry_count);
4236 if (delay > 0) { /* add an empty edit to delay presentation */
4237 /* In the positive delay case, the delay includes the cts
4238 * offset, and the second edit list entry below trims out
4239 * the same amount from the actual content. This makes sure
4240 * that the offset last sample is included in the edit
4241 * list duration as well. */
4242 if (version == 1) {
4243 avio_wb64(pb, delay);
4244 avio_wb64(pb, -1);
4245 } else {
4246 avio_wb32(pb, delay);
4247 avio_wb32(pb, -1);
4248 }
4249 avio_wb32(pb, 0x00010000);
4250 } else if (mov->mode != MODE_AVIF) {
4251 /* Avoid accidentally ending up with start_ct = -1 which has got a
4252 * special meaning. Normally start_ct should end up positive or zero
4253 * here, but use FFMIN in case dts is a small positive integer
4254 * rounded to 0 when represented in movie timescale units. */
4255 av_assert0(av_rescale_rnd(start_dts, mov->movie_timescale, track->timescale, AV_ROUND_DOWN) <= 0);
4256 start_ct = -FFMIN(start_dts, 0);
4257
4258#if CONFIG_IAMFENC
4259 if (track->iamf && track->par->codec_id == AV_CODEC_ID_OPUS)
4260 start_ct = av_rescale(start_ct, 48000, track->par->sample_rate);
4261#endif
4262 /* Note, this delay is calculated from the pts of the first sample,
4263 * ensuring that we don't reduce the duration for cases with
4264 * dts<0 pts=0. */
4265 duration += delay;
4266 }
4267
4268 /* For fragmented files, we don't know the full length yet. Setting
4269 * duration to 0 allows us to only specify the offset, including
4270 * the rest of the content (from all future fragments) without specifying
4271 * an explicit duration.
4272 *
4273 * For hybrid_fragmented during mov_write_trailer (mov->moov_written != 0),
4274 * don't reset duration to zero.
4275 */
4276 if (mov->flags & FF_MOV_FLAG_FRAGMENT &&
4278 duration = 0;
4279
4280 /* duration */
4281 if (version == 1) {
4282 avio_wb64(pb, duration);
4283 avio_wb64(pb, start_ct);
4284 } else {
4285 avio_wb32(pb, duration);
4286 avio_wb32(pb, start_ct);
4287 }
4288 avio_wb32(pb, 0x00010000);
4289 return size;
4290}
4291
4293{
4294 int64_t pos = avio_tell(pb);
4295 avio_wb32(pb, 0); // size placeholder
4296 ffio_wfourcc(pb, "tref");
4297
4298 for (int i = 0; i < track->nb_tref_tags; i++) {
4299 MovTag *tag = &track->tref_tags[i];
4300 avio_wb32(pb, 8 + tag->nb_id * sizeof(*tag->id)); // size (subatom)
4301 avio_wl32(pb, tag->name);
4302 for (int j = 0; j < tag->nb_id; j++)
4303 avio_wb32(pb, tag->id[j]);
4304 }
4305 return update_size(pb, pos);
4306}
4307
4308// goes at the end of each track! ... Critical for PSP playback ("Incompatible data" without it)
4310{
4311 avio_wb32(pb, 0x34); /* size ... reports as 28 in mp4box! */
4312 ffio_wfourcc(pb, "uuid");
4313 ffio_wfourcc(pb, "USMT");
4314 avio_wb32(pb, 0x21d24fce);
4315 avio_wb32(pb, 0xbb88695c);
4316 avio_wb32(pb, 0xfac9c740);
4317 avio_wb32(pb, 0x1c); // another size here!
4318 ffio_wfourcc(pb, "MTDT");
4319 avio_wb32(pb, 0x00010012);
4320 avio_wb32(pb, 0x0a);
4321 avio_wb32(pb, 0x55c40000);
4322 avio_wb32(pb, 0x1);
4323 avio_wb32(pb, 0x0);
4324 return 0x34;
4325}
4326
4328{
4329 AVFormatContext *ctx = track->rtp_ctx;
4330 char buf[1000] = "";
4331 int len;
4332
4333 av_assert0(track->nb_src_track);
4334 ff_sdp_write_media(buf, sizeof(buf), ctx->streams[0], *track->src_track,
4335 NULL, NULL, 0, 0, ctx);
4336 av_strlcatf(buf, sizeof(buf), "a=control:streamid=%d\r\n", track->track_id);
4337 len = strlen(buf);
4338
4339 avio_wb32(pb, len + 24);
4340 ffio_wfourcc(pb, "udta");
4341 avio_wb32(pb, len + 16);
4342 ffio_wfourcc(pb, "hnti");
4343 avio_wb32(pb, len + 8);
4344 ffio_wfourcc(pb, "sdp ");
4345 avio_write(pb, buf, len);
4346 return len + 24;
4347}
4348
4350 const char *tag, const char *str)
4351{
4352 int64_t pos = avio_tell(pb);
4353 AVDictionaryEntry *t = av_dict_get(st->metadata, str, NULL, 0);
4354 if (!t || !utf8len(t->value))
4355 return 0;
4356
4357 avio_wb32(pb, 0); /* size */
4358 ffio_wfourcc(pb, tag); /* type */
4359 avio_write(pb, t->value, strlen(t->value)); /* UTF8 string value */
4360 return update_size(pb, pos);
4361}
4362
4363static int mov_write_track_kind(AVIOContext *pb, const char *scheme_uri,
4364 const char *value)
4365{
4366 int64_t pos = avio_tell(pb);
4367
4368 /* Box|FullBox basics */
4369 avio_wb32(pb, 0); /* size placeholder */
4370 ffio_wfourcc(pb, (const unsigned char *)"kind");
4371 avio_w8(pb, 0); /* version = 0 */
4372 avio_wb24(pb, 0); /* flags = 0 */
4373
4374 /* Required null-terminated scheme URI */
4375 avio_write(pb, (const unsigned char *)scheme_uri,
4376 strlen(scheme_uri));
4377 avio_w8(pb, 0);
4378
4379 /* Optional value string */
4380 if (value && value[0])
4381 avio_write(pb, (const unsigned char *)value,
4382 strlen(value));
4383
4384 avio_w8(pb, 0);
4385
4386 return update_size(pb, pos);
4387}
4388
4390{
4391 int ret = AVERROR_BUG;
4392
4393 for (int i = 0; ff_mov_track_kind_table[i].scheme_uri; i++) {
4395
4396 for (int j = 0; map.value_maps[j].disposition; j++) {
4397 const struct MP4TrackKindValueMapping value_map = map.value_maps[j];
4398 if (!(st->disposition & value_map.disposition))
4399 continue;
4400
4401 if ((ret = mov_write_track_kind(pb, map.scheme_uri, value_map.value)) < 0)
4402 return ret;
4403 }
4404 }
4405
4406 return 0;
4407}
4408
4410 AVStream *st)
4411{
4412 AVIOContext *pb_buf;
4413 int ret, size;
4414 uint8_t *buf;
4415
4416 if (!st)
4417 return 0;
4418
4419 ret = avio_open_dyn_buf(&pb_buf);
4420 if (ret < 0)
4421 return ret;
4422
4423 if (mov->mode & (MODE_MP4|MODE_MOV))
4424 mov_write_track_metadata(pb_buf, st, "name", "title");
4425
4426 if (mov->mode & MODE_MP4) {
4427 if ((ret = mov_write_track_kinds(pb_buf, st)) < 0)
4428 goto end;
4429 }
4430
4431 if ((size = avio_get_dyn_buf(pb_buf, &buf)) > 0) {
4432 avio_wb32(pb, size + 8);
4433 ffio_wfourcc(pb, "udta");
4434 avio_write(pb, buf, size);
4435 }
4436end:
4437 ffio_free_dyn_buf(&pb_buf);
4438
4439 return ret;
4440}
4441
4443 MOVTrack *track, AVStream *st)
4444{
4445 int64_t pos = avio_tell(pb);
4446 int entry_backup = track->entry;
4447 int chunk_backup = track->chunkCount;
4448 int ret;
4449
4450 /* If we want to have an empty moov, but some samples already have been
4451 * buffered (delay_moov), pretend that no samples have been written yet. */
4452 if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV)
4453 track->chunkCount = track->entry = 0;
4454
4455 avio_wb32(pb, 0); /* size */
4456 ffio_wfourcc(pb, "trak");
4457 mov_write_tkhd_tag(pb, mov, track, st);
4458
4459 av_assert2(mov->use_editlist >= 0);
4460
4461 if (track->start_dts != AV_NOPTS_VALUE) {
4462 if (mov->use_editlist)
4463 mov_write_edts_tag(pb, mov, track); // PSP Movies and several other cases require edts box
4464 else if ((track->entry && track->cluster[0].dts) || track->mode == MODE_PSP || is_clcp_track(track))
4465 av_log(mov->fc, AV_LOG_WARNING,
4466 "Not writing any edit list even though one would have been required\n");
4467 }
4468
4469 if (mov->is_animated_avif)
4470 mov_write_edts_tag(pb, mov, track);
4471
4472 if (track->nb_tref_tags)
4473 mov_write_tref_tag(pb, track);
4474
4475 if ((ret = mov_write_mdia_tag(s, pb, mov, track)) < 0)
4476 return ret;
4477 if (track->mode == MODE_PSP)
4478 mov_write_uuid_tag_psp(pb, track); // PSP Movies require this uuid box
4479 if (track->tag == MKTAG('r','t','p',' '))
4480 mov_write_udta_sdp(pb, track);
4481 if (track->mode == MODE_MOV) {
4482 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
4483 double sample_aspect_ratio = av_q2d(st->sample_aspect_ratio);
4484 if (st->sample_aspect_ratio.num && 1.0 != sample_aspect_ratio) {
4485 mov_write_tapt_tag(pb, track);
4486 }
4487 }
4488 if (is_clcp_track(track) && st->sample_aspect_ratio.num) {
4489 mov_write_tapt_tag(pb, track);
4490 }
4491 }
4492 mov_write_track_udta_tag(pb, mov, st);
4493 track->entry = entry_backup;
4494 track->chunkCount = chunk_backup;
4495 return update_size(pb, pos);
4496}
4497
4499{
4500 int i, has_audio = 0, has_video = 0;
4501 int64_t pos = avio_tell(pb);
4502 int audio_profile = mov->iods_audio_profile;
4503 int video_profile = mov->iods_video_profile;
4504 for (i = 0; i < mov->nb_tracks; i++) {
4505 if (mov->tracks[i].entry > 0 || mov->flags & FF_MOV_FLAG_EMPTY_MOOV) {
4506 has_audio |= mov->tracks[i].par->codec_type == AVMEDIA_TYPE_AUDIO;
4507 has_video |= mov->tracks[i].par->codec_type == AVMEDIA_TYPE_VIDEO;
4508 }
4509 }
4510 if (audio_profile < 0)
4511 audio_profile = 0xFF - has_audio;
4512 if (video_profile < 0)
4513 video_profile = 0xFF - has_video;
4514 avio_wb32(pb, 0x0); /* size */
4515 ffio_wfourcc(pb, "iods");
4516 avio_wb32(pb, 0); /* version & flags */
4517 put_descr(pb, 0x10, 7);
4518 avio_wb16(pb, 0x004f);
4519 avio_w8(pb, 0xff);
4520 avio_w8(pb, 0xff);
4521 avio_w8(pb, audio_profile);
4522 avio_w8(pb, video_profile);
4523 avio_w8(pb, 0xff);
4524 return update_size(pb, pos);
4525}
4526
4528{
4529 avio_wb32(pb, 0x20); /* size */
4530 ffio_wfourcc(pb, "trex");
4531 avio_wb32(pb, 0); /* version & flags */
4532 avio_wb32(pb, track->track_id); /* track ID */
4533 avio_wb32(pb, 1); /* default sample description index */
4534 avio_wb32(pb, 0); /* default sample duration */
4535 avio_wb32(pb, 0); /* default sample size */
4536 avio_wb32(pb, 0); /* default sample flags */
4537 return 0;
4538}
4539
4541{
4542 int64_t pos = avio_tell(pb);
4543 int i;
4544 avio_wb32(pb, 0x0); /* size */
4545 ffio_wfourcc(pb, "mvex");
4546 for (i = 0; i < mov->nb_tracks; i++)
4547 mov_write_trex_tag(pb, &mov->tracks[i]);
4548 return update_size(pb, pos);
4549}
4550
4552{
4553 int max_track_id = 1, i;
4554 int64_t max_track_len = 0;
4555 int version;
4556 int timescale;
4557
4558 for (i = 0; i < mov->nb_tracks; i++) {
4559 if (mov->tracks[i].entry > 0 && mov->tracks[i].timescale) {
4560 int64_t max_track_len_temp = av_rescale_rnd(
4561 calc_pts_duration(mov, &mov->tracks[i]),
4562 mov->movie_timescale,
4563 mov->tracks[i].timescale,
4564 AV_ROUND_UP);
4565 if (max_track_len < max_track_len_temp)
4566 max_track_len = max_track_len_temp;
4567 if (max_track_id < mov->tracks[i].track_id)
4568 max_track_id = mov->tracks[i].track_id;
4569 }
4570 }
4571 /* If using delay_moov, make sure the output is the same as if no
4572 * samples had been written yet. */
4573 if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV) {
4574 max_track_len = 0;
4575 max_track_id = 1;
4576 }
4577
4578 version = mov_mdhd_mvhd_tkhd_version(mov, NULL, max_track_len);
4579 avio_wb32(pb, version == 1 ? 120 : 108); /* size */
4580
4581 ffio_wfourcc(pb, "mvhd");
4582 avio_w8(pb, version);
4583 avio_wb24(pb, 0); /* flags */
4584 if (version == 1) {
4585 avio_wb64(pb, mov->time);
4586 avio_wb64(pb, mov->time);
4587 } else {
4588 avio_wb32(pb, mov->time); /* creation time */
4589 avio_wb32(pb, mov->time); /* modification time */
4590 }
4591
4592 timescale = mov->movie_timescale;
4593 if (mov->mode == MODE_AVIF && !timescale)
4594 timescale = mov->tracks[0].timescale;
4595
4596 avio_wb32(pb, timescale);
4597 (version == 1) ? avio_wb64(pb, max_track_len) : avio_wb32(pb, max_track_len); /* duration of longest track */
4598
4599 avio_wb32(pb, 0x00010000); /* reserved (preferred rate) 1.0 = normal */
4600 avio_wb16(pb, 0x0100); /* reserved (preferred volume) 1.0 = normal */
4601 ffio_fill(pb, 0, 2 + 2 * 4); /* reserved */
4602
4603 /* Matrix structure */
4604 write_matrix(pb, 1, 0, 0, 1, 0, 0);
4605
4606 avio_wb32(pb, 0); /* reserved (preview time) */
4607 avio_wb32(pb, 0); /* reserved (preview duration) */
4608 avio_wb32(pb, 0); /* reserved (poster time) */
4609 avio_wb32(pb, 0); /* reserved (selection time) */
4610 avio_wb32(pb, 0); /* reserved (selection duration) */
4611 avio_wb32(pb, 0); /* reserved (current time) */
4612 avio_wb32(pb, max_track_id + 1); /* Next track id */
4613 return 0x6c;
4614}
4615
4618{
4619 avio_wb32(pb, 33); /* size */
4620 ffio_wfourcc(pb, "hdlr");
4621 avio_wb32(pb, 0);
4622 avio_wb32(pb, 0);
4623 ffio_wfourcc(pb, "mdir");
4624 ffio_wfourcc(pb, "appl");
4625 avio_wb32(pb, 0);
4626 avio_wb32(pb, 0);
4627 avio_w8(pb, 0);
4628 return 33;
4629}
4630
4631/* helper function to write a data tag with the specified string as data */
4632static int mov_write_string_data_tag(AVIOContext *pb, const char *data, int lang, int long_style)
4633{
4634 size_t data_len = strlen(data);
4635 if (long_style) {
4636 int size = 16 + data_len;
4637 avio_wb32(pb, size); /* size */
4638 ffio_wfourcc(pb, "data");
4639 avio_wb32(pb, 1);
4640 avio_wb32(pb, 0);
4641 avio_write(pb, data, data_len);
4642 return size;
4643 } else {
4644 avio_wb16(pb, data_len); /* string length */
4645 if (!lang)
4646 lang = ff_mov_iso639_to_lang("und", 1);
4647 avio_wb16(pb, lang);
4648 avio_write(pb, data, data_len);
4649 return data_len + 4;
4650 }
4651}
4652
4653static int mov_write_string_tag(AVIOContext *pb, const char *name,
4654 const char *value, int lang, int long_style)
4655{
4656 int size = 0;
4657 if (value && value[0]) {
4658 int64_t pos = avio_tell(pb);
4659 avio_wb32(pb, 0); /* size */
4660 ffio_wfourcc(pb, name);
4661 mov_write_string_data_tag(pb, value, lang, long_style);
4662 size = update_size(pb, pos);
4663 }
4664 return size;
4665}
4666
4667static int mov_write_freeform_tag(AVIOContext *pb, const char *mean,
4668 const char *name, const char *data)
4669{
4670 if (!data || !data[0])
4671 return 0;
4672
4673 static const char stub_flags[4] = {0, 0, 0, 0};
4674
4675 int64_t entry_pos = avio_tell(pb);
4676 avio_wb32(pb, 0); /* size */
4677 ffio_wfourcc(pb, "----"); /* freeform */
4678
4679 size_t mean_len = strlen(mean);
4680 avio_wb32(pb, 12 + mean_len);
4681 ffio_wfourcc(pb, "mean");
4682 avio_write(pb, &stub_flags[0], sizeof(stub_flags));
4683 avio_write(pb, mean, mean_len);
4684
4685 size_t name_len = strlen(name);
4686 avio_wb32(pb, 12 + name_len);
4687 ffio_wfourcc(pb, "name");
4688 avio_write(pb, &stub_flags[0], sizeof(stub_flags));
4689 avio_write(pb, name, name_len);
4690
4692
4693 return update_size(pb, entry_pos);
4694}
4695
4697 const char *tag, int *lang)
4698{
4699 int l, len, len2;
4700 AVDictionaryEntry *t, *t2 = NULL;
4701 char tag2[16];
4702
4703 *lang = 0;
4704
4705 if (!(t = av_dict_get(s->metadata, tag, NULL, 0)))
4706 return NULL;
4707
4708 len = strlen(t->key);
4709 snprintf(tag2, sizeof(tag2), "%s-", tag);
4710 while ((t2 = av_dict_get(s->metadata, tag2, t2, AV_DICT_IGNORE_SUFFIX))) {
4711 len2 = strlen(t2->key);
4712 if (len2 == len + 4 && !strcmp(t->value, t2->value)
4713 && (l = ff_mov_iso639_to_lang(&t2->key[len2 - 3], 1)) >= 0) {
4714 *lang = l;
4715 return t;
4716 }
4717 }
4718 return t;
4719}
4720
4722 const char *name, const char *tag,
4723 int long_style)
4724{
4725 int lang;
4727 if (!t)
4728 return 0;
4729 return mov_write_string_tag(pb, name, t->value, lang, long_style);
4730}
4731
4733 const char *mean, const char *name,
4734 const char *tag)
4735{
4736 AVDictionaryEntry *t = av_dict_get(s->metadata, tag, NULL, 0);
4737 if (!t)
4738 return 0;
4739 return mov_write_freeform_tag(pb, mean, name, t->value);
4740}
4741
4742/* iTunes bpm number */
4744{
4745 AVDictionaryEntry *t = av_dict_get(s->metadata, "tmpo", NULL, 0);
4746 int size = 0, tmpo = t ? atoi(t->value) : 0;
4747 if (tmpo) {
4748 size = 26;
4749 avio_wb32(pb, size);
4750 ffio_wfourcc(pb, "tmpo");
4751 avio_wb32(pb, size-8); /* size */
4752 ffio_wfourcc(pb, "data");
4753 avio_wb32(pb, 0x15); //type specifier
4754 avio_wb32(pb, 0);
4755 avio_wb16(pb, tmpo); // data
4756 }
4757 return size;
4758}
4759
4760/* 3GPP TS 26.244 */
4762{
4763 int lang;
4764 int64_t pos = avio_tell(pb);
4765 double latitude, longitude, altitude;
4766 int32_t latitude_fix, longitude_fix, altitude_fix;
4767 AVDictionaryEntry *t = get_metadata_lang(s, "location", &lang);
4768 const char *ptr, *place = "";
4769 char *end;
4770 static const char *astronomical_body = "earth";
4771 if (!t)
4772 return 0;
4773
4774 ptr = t->value;
4775 latitude = strtod(ptr, &end);
4776 if (end == ptr) {
4777 av_log(s, AV_LOG_WARNING, "malformed location metadata\n");
4778 return 0;
4779 }
4780 ptr = end;
4781 longitude = strtod(ptr, &end);
4782 if (end == ptr) {
4783 av_log(s, AV_LOG_WARNING, "malformed location metadata\n");
4784 return 0;
4785 }
4786 ptr = end;
4787 altitude = strtod(ptr, &end);
4788 /* If no altitude was present, the default 0 should be fine */
4789 if (*end == '/')
4790 place = end + 1;
4791
4792 latitude_fix = (int32_t) ((1 << 16) * latitude);
4793 longitude_fix = (int32_t) ((1 << 16) * longitude);
4794 altitude_fix = (int32_t) ((1 << 16) * altitude);
4795
4796 avio_wb32(pb, 0); /* size */
4797 ffio_wfourcc(pb, "loci"); /* type */
4798 avio_wb32(pb, 0); /* version + flags */
4799 avio_wb16(pb, lang);
4800 avio_write(pb, place, strlen(place) + 1);
4801 avio_w8(pb, 0); /* role of place (0 == shooting location, 1 == real location, 2 == fictional location) */
4802 avio_wb32(pb, longitude_fix);
4803 avio_wb32(pb, latitude_fix);
4804 avio_wb32(pb, altitude_fix);
4805 avio_write(pb, astronomical_body, strlen(astronomical_body) + 1);
4806 avio_w8(pb, 0); /* additional notes, null terminated string */
4807
4808 return update_size(pb, pos);
4809}
4810
4811/* iTunes track or disc number */
4813 AVFormatContext *s, int disc)
4814{
4815 AVDictionaryEntry *t = av_dict_get(s->metadata,
4816 disc ? "disc" : "track",
4817 NULL, 0);
4818 int size = 0, track = t ? atoi(t->value) : 0;
4819 if (track) {
4820 int tracks = 0;
4821 char *slash = strchr(t->value, '/');
4822 if (slash)
4823 tracks = atoi(slash + 1);
4824 avio_wb32(pb, 32); /* size */
4825 ffio_wfourcc(pb, disc ? "disk" : "trkn");
4826 avio_wb32(pb, 24); /* size */
4827 ffio_wfourcc(pb, "data");
4828 avio_wb32(pb, 0); // 8 bytes empty
4829 avio_wb32(pb, 0);
4830 avio_wb16(pb, 0); // empty
4831 avio_wb16(pb, track); // track / disc number
4832 avio_wb16(pb, tracks); // total track / disc number
4833 avio_wb16(pb, 0); // empty
4834 size = 32;
4835 }
4836 return size;
4837}
4838
4840 const char *name, const char *tag,
4841 int len)
4842{
4844 uint8_t num;
4845 int size = 24 + len;
4846
4847 if (len != 1 && len != 4)
4848 return -1;
4849
4850 if (!(t = av_dict_get(s->metadata, tag, NULL, 0)))
4851 return 0;
4852 num = atoi(t->value);
4853
4854 avio_wb32(pb, size);
4855 ffio_wfourcc(pb, name);
4856 avio_wb32(pb, size - 8);
4857 ffio_wfourcc(pb, "data");
4858 avio_wb32(pb, 0x15);
4859 avio_wb32(pb, 0);
4860 if (len==4) avio_wb32(pb, num);
4861 else avio_w8 (pb, num);
4862
4863 return size;
4864}
4865
4867{
4868 MOVMuxContext *mov = s->priv_data;
4869 int64_t pos = 0;
4870
4871 for (int i = 0; i < mov->nb_streams; i++) {
4872 MOVTrack *trk = &mov->tracks[i];
4873
4874 if (!is_cover_image(trk->st) || trk->cover_image->size <= 0)
4875 continue;
4876
4877 if (!pos) {
4878 pos = avio_tell(pb);
4879 avio_wb32(pb, 0);
4880 ffio_wfourcc(pb, "covr");
4881 }
4882 avio_wb32(pb, 16 + trk->cover_image->size);
4883 ffio_wfourcc(pb, "data");
4884 avio_wb32(pb, trk->tag);
4885 avio_wb32(pb , 0);
4886 avio_write(pb, trk->cover_image->data, trk->cover_image->size);
4887 }
4888
4889 return pos ? update_size(pb, pos) : 0;
4890}
4891
4892/* iTunes meta data list */
4895{
4896 int64_t pos = avio_tell(pb);
4897 avio_wb32(pb, 0); /* size */
4898 ffio_wfourcc(pb, "ilst");
4899 mov_write_string_metadata(s, pb, "\251nam", "title" , 1);
4900 mov_write_string_metadata(s, pb, "\251ART", "artist" , 1);
4901 mov_write_string_metadata(s, pb, "aART", "album_artist", 1);
4902 mov_write_string_metadata(s, pb, "\251wrt", "composer" , 1);
4903 mov_write_string_metadata(s, pb, "\251alb", "album" , 1);
4904 mov_write_string_metadata(s, pb, "\251day", "date" , 1);
4905 if (!mov_write_string_metadata(s, pb, "\251too", "encoding_tool", 1)) {
4906 if (!(s->flags & AVFMT_FLAG_BITEXACT))
4907 mov_write_string_tag(pb, "\251too", LIBAVFORMAT_IDENT, 0, 1);
4908 }
4909 mov_write_string_metadata(s, pb, "\251cmt", "comment" , 1);
4910 mov_write_string_metadata(s, pb, "\251gen", "genre" , 1);
4911 mov_write_string_metadata(s, pb, "cprt", "copyright", 1);
4912 mov_write_string_metadata(s, pb, "\251grp", "grouping" , 1);
4913 mov_write_string_metadata(s, pb, "\251lyr", "lyrics" , 1);
4914 mov_write_string_metadata(s, pb, "desc", "description",1);
4915 mov_write_string_metadata(s, pb, "ldes", "synopsis" , 1);
4916 mov_write_string_metadata(s, pb, "tvsh", "show" , 1);
4917 mov_write_string_metadata(s, pb, "tven", "episode_id",1);
4918 mov_write_string_metadata(s, pb, "tvnn", "network" , 1);
4919 mov_write_string_metadata(s, pb, "keyw", "keywords" , 1);
4920 mov_write_int8_metadata (s, pb, "tves", "episode_sort",4);
4921 mov_write_int8_metadata (s, pb, "tvsn", "season_number",4);
4922 mov_write_int8_metadata (s, pb, "stik", "media_type",1);
4923 mov_write_int8_metadata (s, pb, "hdvd", "hd_video", 1);
4924 mov_write_int8_metadata (s, pb, "pgap", "gapless_playback",1);
4925 mov_write_int8_metadata (s, pb, "cpil", "compilation", 1);
4926 mov_write_covr(pb, s);
4927 mov_write_trkn_tag(pb, mov, s, 0); // track number
4928 mov_write_trkn_tag(pb, mov, s, 1); // disc number
4929 mov_write_tmpo_tag(pb, s);
4930 mov_write_custom_metadata(s, pb, "com.apple.iTunes", "DISCSUBTITLE", "disc_subtitle");
4931 return update_size(pb, pos);
4932}
4933
4936{
4937 avio_wb32(pb, 33); /* size */
4938 ffio_wfourcc(pb, "hdlr");
4939 avio_wb32(pb, 0);
4940 avio_wb32(pb, 0);
4941 ffio_wfourcc(pb, "mdta");
4942 avio_wb32(pb, 0);
4943 avio_wb32(pb, 0);
4944 avio_wb32(pb, 0);
4945 avio_w8(pb, 0);
4946 return 33;
4947}
4948
4951{
4952 const AVDictionaryEntry *t = NULL;
4953 int64_t pos = avio_tell(pb);
4954 int64_t curpos, entry_pos;
4955 int count = 0;
4956
4957 avio_wb32(pb, 0); /* size */
4958 ffio_wfourcc(pb, "keys");
4959 avio_wb32(pb, 0);
4960 entry_pos = avio_tell(pb);
4961 avio_wb32(pb, 0); /* entry count */
4962
4963 while (t = av_dict_iterate(s->metadata, t)) {
4964 size_t key_len = strlen(t->key);
4965 avio_wb32(pb, key_len + 8);
4966 ffio_wfourcc(pb, "mdta");
4967 avio_write(pb, t->key, key_len);
4968 count += 1;
4969 }
4970 curpos = avio_tell(pb);
4971 avio_seek(pb, entry_pos, SEEK_SET);
4972 avio_wb32(pb, count); // rewrite entry count
4973 avio_seek(pb, curpos, SEEK_SET);
4974
4975 return update_size(pb, pos);
4976}
4977
4980{
4981 const AVDictionaryEntry *t = NULL;
4982 int64_t pos = avio_tell(pb);
4983 int count = 1; /* keys are 1-index based */
4984
4985 avio_wb32(pb, 0); /* size */
4986 ffio_wfourcc(pb, "ilst");
4987
4988 while (t = av_dict_iterate(s->metadata, t)) {
4989 int64_t entry_pos = avio_tell(pb);
4990 avio_wb32(pb, 0); /* size */
4991 avio_wb32(pb, count); /* key */
4992 mov_write_string_data_tag(pb, t->value, 0, 1);
4993 update_size(pb, entry_pos);
4994 count += 1;
4995 }
4996 return update_size(pb, pos);
4997}
4998
4999/* meta data tags */
5002{
5003 int size = 0;
5004 int64_t pos = avio_tell(pb);
5005 avio_wb32(pb, 0); /* size */
5006 ffio_wfourcc(pb, "meta");
5007 avio_wb32(pb, 0);
5008 if (mov->flags & FF_MOV_FLAG_USE_MDTA) {
5009 mov_write_mdta_hdlr_tag(pb, mov, s);
5010 mov_write_mdta_keys_tag(pb, mov, s);
5011 mov_write_mdta_ilst_tag(pb, mov, s);
5012 } else if (mov->mode == MODE_AVIF) {
5013 mov_write_hdlr_tag(s, pb, &mov->tracks[0]);
5014 // We always write the primary item id as 1 since only one track is
5015 // supported for AVIF.
5016 mov_write_pitm_tag(pb, 1);
5017 mov_write_iloc_tag(pb, mov, s);
5018 mov_write_iinf_tag(pb, mov, s);
5019 if (mov->nb_streams > 1)
5020 mov_write_iref_tag(pb, mov, s);
5021 mov_write_iprp_tag(pb, mov, s);
5022 } else {
5023 /* iTunes metadata tag */
5024 mov_write_itunes_hdlr_tag(pb, mov, s);
5025 mov_write_ilst_tag(pb, mov, s);
5026 }
5027 size = update_size(pb, pos);
5028 return size;
5029}
5030
5032 const char *name, const char *key)
5033{
5034 int len;
5036
5037 if (!(t = av_dict_get(s->metadata, key, NULL, 0)))
5038 return 0;
5039
5040 len = strlen(t->value);
5041 if (len > 0) {
5042 int size = len + 8;
5043 avio_wb32(pb, size);
5044 ffio_wfourcc(pb, name);
5045 avio_write(pb, t->value, len);
5046 return size;
5047 }
5048 return 0;
5049}
5050
5051static int ascii_to_wc(AVIOContext *pb, const uint8_t *b)
5052{
5053 int val;
5054 while (*b) {
5055 GET_UTF8(val, *b++, return -1;)
5056 avio_wb16(pb, val);
5057 }
5058 avio_wb16(pb, 0x00);
5059 return 0;
5060}
5061
5062static uint16_t language_code(const char *str)
5063{
5064 return (((str[0] - 0x60) & 0x1F) << 10) +
5065 (((str[1] - 0x60) & 0x1F) << 5) +
5066 (( str[2] - 0x60) & 0x1F);
5067}
5068
5070 const char *tag, const char *str)
5071{
5072 int64_t pos = avio_tell(pb);
5073 AVDictionaryEntry *t = av_dict_get(s->metadata, str, NULL, 0);
5074 if (!t || !utf8len(t->value))
5075 return 0;
5076 avio_wb32(pb, 0); /* size */
5077 ffio_wfourcc(pb, tag); /* type */
5078 avio_wb32(pb, 0); /* version + flags */
5079 if (!strcmp(tag, "yrrc"))
5080 avio_wb16(pb, atoi(t->value));
5081 else {
5082 avio_wb16(pb, language_code("eng")); /* language */
5083 avio_write(pb, t->value, strlen(t->value) + 1); /* UTF8 string value */
5084 if (!strcmp(tag, "albm") &&
5085 (t = av_dict_get(s->metadata, "track", NULL, 0)))
5086 avio_w8(pb, atoi(t->value));
5087 }
5088 return update_size(pb, pos);
5089}
5090
5092{
5093 int64_t pos = avio_tell(pb);
5094 int i, nb_chapters = FFMIN(s->nb_chapters, 255);
5095
5096 avio_wb32(pb, 0); // size
5097 ffio_wfourcc(pb, "chpl");
5098 avio_wb32(pb, 0x01000000); // version + flags
5099 avio_wb32(pb, 0); // unknown
5100 avio_w8(pb, nb_chapters);
5101
5102 for (i = 0; i < nb_chapters; i++) {
5103 AVChapter *c = s->chapters[i];
5105 avio_wb64(pb, av_rescale_q(c->start, c->time_base, (AVRational){1,10000000}));
5106
5107 if ((t = av_dict_get(c->metadata, "title", NULL, 0))) {
5108 int len = FFMIN(strlen(t->value), 255);
5109 avio_w8(pb, len);
5110 avio_write(pb, t->value, len);
5111 } else
5112 avio_w8(pb, 0);
5113 }
5114 return update_size(pb, pos);
5115}
5116
5119{
5120 AVIOContext *pb_buf;
5121 int ret, size;
5122 uint8_t *buf;
5123
5124 ret = avio_open_dyn_buf(&pb_buf);
5125 if (ret < 0)
5126 return ret;
5127
5128 if (mov->mode & MODE_3GP) {
5129 mov_write_3gp_udta_tag(pb_buf, s, "perf", "artist");
5130 mov_write_3gp_udta_tag(pb_buf, s, "titl", "title");
5131 mov_write_3gp_udta_tag(pb_buf, s, "auth", "author");
5132 mov_write_3gp_udta_tag(pb_buf, s, "gnre", "genre");
5133 mov_write_3gp_udta_tag(pb_buf, s, "dscp", "comment");
5134 mov_write_3gp_udta_tag(pb_buf, s, "albm", "album");
5135 mov_write_3gp_udta_tag(pb_buf, s, "cprt", "copyright");
5136 mov_write_3gp_udta_tag(pb_buf, s, "yrrc", "date");
5137 mov_write_loci_tag(s, pb_buf);
5138 } 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
5139 mov_write_string_metadata(s, pb_buf, "\251ART", "artist", 0);
5140 mov_write_string_metadata(s, pb_buf, "\251nam", "title", 0);
5141 mov_write_string_metadata(s, pb_buf, "\251aut", "author", 0);
5142 mov_write_string_metadata(s, pb_buf, "\251alb", "album", 0);
5143 mov_write_string_metadata(s, pb_buf, "\251day", "date", 0);
5144 mov_write_string_metadata(s, pb_buf, "\251swr", "encoder", 0);
5145 // currently ignored by mov.c
5146 mov_write_string_metadata(s, pb_buf, "\251des", "comment", 0);
5147 // add support for libquicktime, this atom is also actually read by mov.c
5148 mov_write_string_metadata(s, pb_buf, "\251cmt", "comment", 0);
5149 mov_write_string_metadata(s, pb_buf, "\251gen", "genre", 0);
5150 mov_write_string_metadata(s, pb_buf, "\251cpy", "copyright", 0);
5151 mov_write_string_metadata(s, pb_buf, "\251mak", "make", 0);
5152 mov_write_string_metadata(s, pb_buf, "\251mod", "model", 0);
5153 mov_write_string_metadata(s, pb_buf, "\251xyz", "location", 0);
5154 mov_write_string_metadata(s, pb_buf, "\251key", "keywords", 0);
5155 mov_write_raw_metadata_tag(s, pb_buf, "XMP_", "xmp");
5156 } else {
5157 /* iTunes meta data */
5158 mov_write_meta_tag(pb_buf, mov, s);
5159 mov_write_loci_tag(s, pb_buf);
5160 }
5161
5162 if (s->nb_chapters && !(mov->flags & FF_MOV_FLAG_DISABLE_CHPL))
5163 mov_write_chpl_tag(pb_buf, s);
5164
5165 if ((size = avio_get_dyn_buf(pb_buf, &buf)) > 0) {
5166 avio_wb32(pb, size + 8);
5167 ffio_wfourcc(pb, "udta");
5168 avio_write(pb, buf, size);
5169 }
5170 ffio_free_dyn_buf(&pb_buf);
5171
5172 return 0;
5173}
5174
5176 const char *str, const char *lang, int type)
5177{
5178 int len = utf8len(str) + 1;
5179 if (len <= 0)
5180 return;
5181 avio_wb16(pb, len * 2 + 10); /* size */
5182 avio_wb32(pb, type); /* type */
5183 avio_wb16(pb, language_code(lang)); /* language */
5184 avio_wb16(pb, 0x01); /* ? */
5185 ascii_to_wc(pb, str);
5186}
5187
5189{
5190 AVDictionaryEntry *title = av_dict_get(s->metadata, "title", NULL, 0);
5191 int64_t pos, pos2;
5192
5193 if (title) {
5194 pos = avio_tell(pb);
5195 avio_wb32(pb, 0); /* size placeholder*/
5196 ffio_wfourcc(pb, "uuid");
5197 ffio_wfourcc(pb, "USMT");
5198 avio_wb32(pb, 0x21d24fce); /* 96 bit UUID */
5199 avio_wb32(pb, 0xbb88695c);
5200 avio_wb32(pb, 0xfac9c740);
5201
5202 pos2 = avio_tell(pb);
5203 avio_wb32(pb, 0); /* size placeholder*/
5204 ffio_wfourcc(pb, "MTDT");
5205 avio_wb16(pb, 4);
5206
5207 // ?
5208 avio_wb16(pb, 0x0C); /* size */
5209 avio_wb32(pb, 0x0B); /* type */
5210 avio_wb16(pb, language_code("und")); /* language */
5211 avio_wb16(pb, 0x0); /* ? */
5212 avio_wb16(pb, 0x021C); /* data */
5213
5214 if (!(s->flags & AVFMT_FLAG_BITEXACT))
5215 mov_write_psp_udta_tag(pb, LIBAVFORMAT_IDENT, "eng", 0x04);
5216 mov_write_psp_udta_tag(pb, title->value, "eng", 0x01);
5217 mov_write_psp_udta_tag(pb, "2006/04/01 11:11:11", "und", 0x03);
5218
5219 update_size(pb, pos2);
5220 return update_size(pb, pos);
5221 }
5222
5223 return 0;
5224}
5225
5227{
5232 if (!sd)
5233 return 0;
5234
5236 for (AVEncryptionInitInfo *copy = info; copy; copy = copy->next) {
5237 int64_t pos;
5238
5239 if (!copy->data_size && !copy->num_key_ids)
5240 continue;
5241
5242 pos = avio_tell(pb);
5243 avio_wb32(pb, 0); /* size placeholder */
5244 ffio_wfourcc(pb, "pssh");
5245 avio_w8(pb, 1); /* version */
5246 avio_wb24(pb, 0);
5247 for (int i = 0; i < copy->system_id_size; i++)
5248 avio_w8(pb, copy->system_id[i]);
5249 avio_wb32(pb, copy->num_key_ids);
5250 for (int i = 0; i < copy->num_key_ids; i++)
5251 for (int j = 0; j < copy->key_id_size; j++)
5252 avio_w8(pb, copy->key_ids[i][j]);
5253 avio_wb32(pb, copy->data_size);
5254 avio_write(pb, copy->data, copy->data_size);
5255 update_size(pb, pos);
5256 }
5257
5259
5260 return 0;
5261}
5262
5263static void build_chunks(MOVTrack *trk)
5264{
5265 int i;
5266 MOVIentry *chunk = &trk->cluster[0];
5267 uint64_t chunkSize = chunk->size;
5268 chunk->chunkNum = 1;
5269 if (trk->chunkCount)
5270 return;
5271 trk->chunkCount = 1;
5272 for (i = 1; i<trk->entry; i++){
5273 if (chunk->pos + chunkSize == trk->cluster[i].pos &&
5274 chunk->stsd_index == trk->cluster[i].stsd_index &&
5275 chunkSize + trk->cluster[i].size < (1<<20)){
5276 chunkSize += trk->cluster[i].size;
5277 chunk->samples_in_chunk += trk->cluster[i].entries;
5278 } else {
5279 trk->cluster[i].chunkNum = chunk->chunkNum+1;
5280 chunk=&trk->cluster[i];
5281 chunkSize = chunk->size;
5282 trk->chunkCount++;
5283 }
5284 }
5285}
5286
5287/**
5288 * Assign track ids. If option "use_stream_ids_as_track_ids" is set,
5289 * the stream ids are used as track ids.
5290 *
5291 * This assumes mov->tracks and s->streams are in the same order and
5292 * there are no gaps in either of them (so mov->tracks[n] refers to
5293 * s->streams[n]).
5294 *
5295 * As an exception, there can be more entries in
5296 * s->streams than in mov->tracks, in which case new track ids are
5297 * generated (starting after the largest found stream id).
5298 */
5300{
5301 int i;
5302
5303 if (mov->track_ids_ok)
5304 return 0;
5305
5306 if (mov->use_stream_ids_as_track_ids) {
5307 int next_generated_track_id = 0;
5308 for (i = 0; i < mov->nb_streams; i++) {
5309 AVStream *st = mov->tracks[i].st;
5310 if (st->id > next_generated_track_id)
5311 next_generated_track_id = st->id;
5312 }
5313
5314 for (i = 0; i < mov->nb_tracks; i++) {
5315 if (mov->tracks[i].entry <= 0 && !(mov->flags & FF_MOV_FLAG_FRAGMENT))
5316 continue;
5317
5318 mov->tracks[i].track_id = i >= mov->nb_streams ? ++next_generated_track_id : mov->tracks[i].st->id;
5319 }
5320 } else {
5321 int last_track_id = 0;
5322 for (i = 0; i < mov->nb_tracks; i++) {
5323 if (mov->tracks[i].entry <= 0 && !(mov->flags & FF_MOV_FLAG_FRAGMENT))
5324 continue;
5325
5326 last_track_id =
5327 mov->tracks[i].track_id = (mov->tracks[i].st
5328 ? FFMAX(mov->tracks[i].st->index, last_track_id)
5329 : FFMAX(i, last_track_id)) + 1;
5330 }
5331 }
5332
5333 mov->track_ids_ok = 1;
5334
5335 return 0;
5336}
5337
5338static int mov_find_tref_id(MOVMuxContext *mov, const MovTag *tag, uint32_t id)
5339{
5340 for (int i = 0; i < tag->nb_id; i++) {
5341 if (tag->id[i] == id)
5342 return 1;
5343 }
5344 return 0;
5345}
5346
5347static int mov_add_tref_id(MOVMuxContext *mov, MovTag *tag, uint32_t id)
5348{
5349 int ret = mov_find_tref_id(mov, tag, id);
5350
5351 if (!ret) {
5352 uint32_t *tmp = av_realloc_array(tag->id, tag->nb_id + 1, sizeof(*tag->id));
5353 if (!tmp)
5354 return AVERROR(ENOMEM);
5355 tag->id = tmp;
5356 tag->id[tag->nb_id++] = id;
5357 }
5358
5359 return 0;
5360}
5361
5362static MovTag *mov_find_tref_tag(MOVMuxContext *mov, const MOVTrack *trk, uint32_t name)
5363{
5364 for (int i = 0; i < trk->nb_tref_tags; i++) {
5365 MovTag *entry = &trk->tref_tags[i];
5366
5367 if (entry->name == name)
5368 return entry;
5369 }
5370 return NULL;
5371}
5372
5374{
5375 MovTag *tag = mov_find_tref_tag(mov, trk, name);
5376
5377 if (!tag) {
5379 sizeof(*trk->tref_tags));
5380 if (!tmp)
5381 return NULL;
5382 trk->tref_tags = tmp;
5383 tag = &trk->tref_tags[trk->nb_tref_tags++];
5384 *tag = (MovTag){ .name = name };
5385 }
5386
5387 return tag;
5388}
5389
5392{
5393 int i;
5394 int64_t pos = avio_tell(pb);
5395 avio_wb32(pb, 0); /* size placeholder*/
5396 ffio_wfourcc(pb, "moov");
5397
5398 mov_setup_track_ids(mov, s);
5399
5400 for (i = 0; i < mov->nb_tracks; i++) {
5401 if (mov->tracks[i].entry <= 0 && !(mov->flags & FF_MOV_FLAG_FRAGMENT))
5402 continue;
5403
5404 mov->tracks[i].time = mov->time;
5405
5406 if (mov->tracks[i].entry)
5407 build_chunks(&mov->tracks[i]);
5408 }
5409
5410 if (mov->chapter_track)
5411 for (i = 0; i < mov->nb_streams; i++) {
5412 MovTag *tag = mov_add_tref_tag(mov, &mov->tracks[i], MKTAG('c','h','a','p'));
5413 if (!tag)
5414 return AVERROR(ENOMEM);
5415
5416 int ret = mov_add_tref_id(mov, tag, mov->tracks[mov->chapter_track].track_id);
5417 if (ret < 0)
5418 return ret;
5419 }
5420 for (i = 0; i < mov->nb_tracks; i++) {
5421 MOVTrack *track = &mov->tracks[i];
5422 if (track->tag == MKTAG('r','t','p',' ')) {
5423 MovTag *tag = mov_add_tref_tag(mov, track, MKTAG('h','i','n','t'));
5424 if (!tag)
5425 return AVERROR(ENOMEM);
5426
5427 av_assert0(track->nb_src_track);
5428 int ret = mov_add_tref_id(mov, tag, mov->tracks[*track->src_track].track_id);
5429 if (ret < 0)
5430 return ret;
5431 } else if (track->tag == MKTAG('l','v','c','1') && track->nb_src_track) {
5432 MovTag *tag = mov_add_tref_tag(mov, track, MKTAG('s','b','a','s'));
5433 if (!tag)
5434 return AVERROR(ENOMEM);
5435
5436 int ret = mov_add_tref_id(mov, tag, mov->tracks[*track->src_track].track_id);
5437 if (ret < 0)
5438 return ret;
5439 } else {
5440 if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) {
5444 if (sd && sd->size == sizeof(int)) {
5445 int *fallback = (int *)sd->data;
5446 if (*fallback >= 0 && *fallback < mov->nb_tracks) {
5447 MovTag *tag = mov_add_tref_tag(mov, track, MKTAG('f','a','l','l'));
5448 if (!tag)
5449 return AVERROR(ENOMEM);
5450
5451 int ret = mov_add_tref_id(mov, tag, mov->tracks[*fallback].track_id);
5452 if (ret < 0)
5453 return ret;
5454 }
5455 }
5456 }
5457 for (int j = 0; j < track->nb_src_track; j++) {
5458 int src_trk = track->src_track[j];
5459 MovTag *tag = mov_add_tref_tag(mov, &mov->tracks[src_trk], track->tag);
5460 if (!tag)
5461 return AVERROR(ENOMEM);
5462 int ret = mov_add_tref_id(mov, tag, track->track_id);
5463 if (ret < 0)
5464 return ret;
5465 }
5466 if (mov->nb_meta_tmcd && track->nb_src_track) {
5467 /* Derive the duration from the first source track, matching
5468 * the convention used by get_pts_range() and the rtp/lvc1
5469 * branches above. The source may use a different timescale. */
5470 int src_trk = track->src_track[0];
5471 track->track_duration = av_rescale(mov->tracks[src_trk].track_duration,
5472 track->timescale,
5473 mov->tracks[src_trk].timescale);
5474 }
5475 }
5476 }
5477
5478 mov_write_mvhd_tag(pb, mov);
5479 if (mov->mode != MODE_MOV && mov->mode != MODE_AVIF && !mov->iods_skip)
5480 mov_write_iods_tag(pb, mov);
5481 for (i = 0; i < mov->nb_tracks; i++) {
5482 if (mov->tracks[i].entry > 0 || mov->flags & FF_MOV_FLAG_FRAGMENT ||
5483 mov->mode == MODE_AVIF) {
5484 int ret = mov_write_trak_tag(s, pb, mov, &(mov->tracks[i]), i < mov->nb_streams ? mov->tracks[i].st : NULL);
5485 if (ret < 0)
5486 return ret;
5487 }
5488 }
5489 /* Don't write mvex for hybrid_fragmented during mov_write_trailer
5490 * (mov->moov_written != 0)
5491 */
5492 if (mov->flags & FF_MOV_FLAG_FRAGMENT &&
5494 mov_write_mvex_tag(pb, mov); /* QuickTime requires trak to precede this */
5495
5496 if (mov->mode == MODE_PSP)
5498 else if (mov->mode != MODE_AVIF)
5499 mov_write_udta_tag(pb, mov, s);
5500 for (i = 0; i < mov->nb_streams; i++)
5501 mov_write_pssh_tag(pb, mov->tracks[i].st);
5502
5503 return update_size(pb, pos);
5504}
5505
5506static void param_write_int(AVIOContext *pb, const char *name, int value)
5507{
5508 avio_printf(pb, "<param name=\"%s\" value=\"%d\" valuetype=\"data\"/>\n", name, value);
5509}
5510
5511static void param_write_string(AVIOContext *pb, const char *name, const char *value)
5512{
5513 avio_printf(pb, "<param name=\"%s\" value=\"%s\" valuetype=\"data\"/>\n", name, value);
5514}
5515
5516static void param_write_hex(AVIOContext *pb, const char *name, const uint8_t *value, int len)
5517{
5518 char buf[150];
5519 len = FFMIN(sizeof(buf) / 2 - 1, len);
5520 ff_data_to_hex(buf, value, len, 0);
5521 avio_printf(pb, "<param name=\"%s\" value=\"%s\" valuetype=\"data\"/>\n", name, buf);
5522}
5523
5525{
5526 int64_t pos = avio_tell(pb);
5527 int i;
5528
5529 static const AVUUID uuid = {
5530 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
5531 0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
5532 };
5533
5534 avio_wb32(pb, 0);
5535 ffio_wfourcc(pb, "uuid");
5536 avio_write(pb, uuid, AV_UUID_LEN);
5537 avio_wb32(pb, 0);
5538
5539 avio_printf(pb, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
5540 avio_printf(pb, "<smil xmlns=\"http://www.w3.org/2001/SMIL20/Language\">\n");
5541 avio_printf(pb, "<head>\n");
5542 if (!(mov->fc->flags & AVFMT_FLAG_BITEXACT))
5543 avio_printf(pb, "<meta name=\"creator\" content=\"%s\" />\n",
5545 avio_printf(pb, "</head>\n");
5546 avio_printf(pb, "<body>\n");
5547 avio_printf(pb, "<switch>\n");
5548
5549 mov_setup_track_ids(mov, s);
5550
5551 for (i = 0; i < mov->nb_tracks; i++) {
5552 MOVTrack *track = &mov->tracks[i];
5553 struct mpeg4_bit_rate_values bit_rates =
5555 const char *type;
5556 int track_id = track->track_id;
5557 char track_name_buf[32] = { 0 };
5558
5559 AVStream *st = track->st;
5560 AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL,0);
5561
5562 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO && !is_cover_image(st)) {
5563 type = "video";
5564 } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) {
5565 type = "audio";
5566 } else {
5567 continue;
5568 }
5569
5570 avio_printf(pb, "<%s systemBitrate=\"%"PRIu32"\">\n", type,
5571 bit_rates.avg_bit_rate);
5572 param_write_int(pb, "systemBitrate", bit_rates.avg_bit_rate);
5573 param_write_int(pb, "trackID", track_id);
5574 param_write_string(pb, "systemLanguage", lang ? lang->value : "und");
5575
5576 /* Build track name piece by piece: */
5577 /* 1. track type */
5578 av_strlcat(track_name_buf, type, sizeof(track_name_buf));
5579 /* 2. track language, if available */
5580 if (lang)
5581 av_strlcatf(track_name_buf, sizeof(track_name_buf),
5582 "_%s", lang->value);
5583 /* 3. special type suffix */
5584 /* "_cc" = closed captions, "_ad" = audio_description */
5586 av_strlcat(track_name_buf, "_cc", sizeof(track_name_buf));
5588 av_strlcat(track_name_buf, "_ad", sizeof(track_name_buf));
5589
5590 param_write_string(pb, "trackName", track_name_buf);
5591
5592 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
5593 if (track->par->codec_id == AV_CODEC_ID_H264) {
5594 uint8_t *ptr;
5595 int size = track->extradata_size[track->last_stsd_index];
5597 &size)) {
5598 param_write_hex(pb, "CodecPrivateData",
5599 ptr ? ptr : track->extradata[track->last_stsd_index],
5600 size);
5601 av_free(ptr);
5602 }
5603 param_write_string(pb, "FourCC", "H264");
5604 } else if (track->par->codec_id == AV_CODEC_ID_VC1) {
5605 param_write_string(pb, "FourCC", "WVC1");
5606 param_write_hex(pb, "CodecPrivateData", track->extradata[track->last_stsd_index],
5607 track->extradata_size[track->last_stsd_index]);
5608 }
5609 param_write_int(pb, "MaxWidth", track->par->width);
5610 param_write_int(pb, "MaxHeight", track->par->height);
5611 param_write_int(pb, "DisplayWidth", track->par->width);
5612 param_write_int(pb, "DisplayHeight", track->par->height);
5613 } else {
5614 if (track->par->codec_id == AV_CODEC_ID_AAC) {
5615 switch (track->par->profile) {
5617 param_write_string(pb, "FourCC", "AACP");
5618 break;
5619 case AV_PROFILE_AAC_HE:
5620 param_write_string(pb, "FourCC", "AACH");
5621 break;
5622 default:
5623 param_write_string(pb, "FourCC", "AACL");
5624 }
5625 } else if (track->par->codec_id == AV_CODEC_ID_WMAPRO) {
5626 param_write_string(pb, "FourCC", "WMAP");
5627 }
5628 param_write_hex(pb, "CodecPrivateData", track->extradata[track->last_stsd_index],
5629 track->extradata_size[track->last_stsd_index]);
5631 track->par->codec_id));
5632 param_write_int(pb, "Channels", track->par->ch_layout.nb_channels);
5633 param_write_int(pb, "SamplingRate", track->tag == MKTAG('i','a','m','f') ?
5634 0 : track->par->sample_rate);
5635 param_write_int(pb, "BitsPerSample", 16);
5636 param_write_int(pb, "PacketSize", track->par->block_align ?
5637 track->par->block_align : 4);
5638 }
5639 avio_printf(pb, "</%s>\n", type);
5640 }
5641 avio_printf(pb, "</switch>\n");
5642 avio_printf(pb, "</body>\n");
5643 avio_printf(pb, "</smil>\n");
5644
5645 return update_size(pb, pos);
5646}
5647
5649{
5650 avio_wb32(pb, 16);
5651 ffio_wfourcc(pb, "mfhd");
5652 avio_wb32(pb, 0);
5653 avio_wb32(pb, mov->fragments);
5654 return 0;
5655}
5656
5662
5664 MOVTrack *track, int64_t moof_offset)
5665{
5666 int64_t pos = avio_tell(pb);
5669 if (!track->entry) {
5671 } else {
5673 }
5679 }
5680 /* CMAF requires all values to be explicit in tfhd atoms */
5681 if (mov->flags & FF_MOV_FLAG_CMAF)
5683
5684 /* Don't set a default sample size, the silverlight player refuses
5685 * to play files with that set. Don't set a default sample duration,
5686 * WMP freaks out if it is set. Don't set a base data offset, PIFF
5687 * file format says it MUST NOT be set. */
5688 if (track->mode == MODE_ISM)
5691
5692 avio_wb32(pb, 0); /* size placeholder */
5693 ffio_wfourcc(pb, "tfhd");
5694 avio_w8(pb, 0); /* version */
5695 avio_wb24(pb, flags);
5696
5697 avio_wb32(pb, track->track_id); /* track-id */
5699 avio_wb64(pb, moof_offset);
5700 if (flags & MOV_TFHD_STSD_ID) {
5701 avio_wb32(pb, 1);
5702 }
5704 track->default_duration = get_cluster_duration(track, 0);
5705 avio_wb32(pb, track->default_duration);
5706 }
5708 track->default_size = track->entry ? track->cluster[0].size : 1;
5709 avio_wb32(pb, track->default_size);
5710 } else
5711 track->default_size = -1;
5712
5714 /* Set the default flags based on the second sample, if available.
5715 * If the first sample is different, that can be signaled via a separate field. */
5716 if (track->entry > 1)
5717 track->default_sample_flags = get_sample_flags(track, &track->cluster[1]);
5718 else
5719 track->default_sample_flags =
5720 track->par->codec_type == AVMEDIA_TYPE_VIDEO ?
5723 avio_wb32(pb, track->default_sample_flags);
5724 }
5725
5726 return update_size(pb, pos);
5727}
5728
5730 MOVTrack *track, int moof_size,
5731 int first, int end)
5732{
5733 int64_t pos = avio_tell(pb);
5734 uint32_t flags = MOV_TRUN_DATA_OFFSET;
5735 int i;
5736
5737 for (i = first; i < end; i++) {
5738 if (get_cluster_duration(track, i) != track->default_duration)
5740 if (track->cluster[i].size != track->default_size)
5742 if (i > first && get_sample_flags(track, &track->cluster[i]) != track->default_sample_flags)
5744 }
5745 if (!(flags & MOV_TRUN_SAMPLE_FLAGS) && track->entry > first &&
5746 get_sample_flags(track, &track->cluster[first]) != track->default_sample_flags)
5748 if (track->flags & MOV_TRACK_CTTS)
5750
5751 avio_wb32(pb, 0); /* size placeholder */
5752 ffio_wfourcc(pb, "trun");
5754 avio_w8(pb, 1); /* version */
5755 else
5756 avio_w8(pb, 0); /* version */
5757 avio_wb24(pb, flags);
5758
5759 avio_wb32(pb, end - first); /* sample count */
5762 !mov->first_trun)
5763 avio_wb32(pb, 0); /* Later tracks follow immediately after the previous one */
5764 else
5765 avio_wb32(pb, moof_size + 8 + track->data_offset +
5766 track->cluster[first].pos); /* data offset */
5768 avio_wb32(pb, get_sample_flags(track, &track->cluster[first]));
5769
5770 for (i = first; i < end; i++) {
5772 avio_wb32(pb, get_cluster_duration(track, i));
5774 avio_wb32(pb, track->cluster[i].size);
5776 avio_wb32(pb, get_sample_flags(track, &track->cluster[i]));
5778 avio_wb32(pb, track->cluster[i].cts);
5779 }
5780
5781 mov->first_trun = 0;
5782 return update_size(pb, pos);
5783}
5784
5786{
5787 int64_t pos = avio_tell(pb);
5788 static const uint8_t uuid[] = {
5789 0x6d, 0x1d, 0x9b, 0x05, 0x42, 0xd5, 0x44, 0xe6,
5790 0x80, 0xe2, 0x14, 0x1d, 0xaf, 0xf7, 0x57, 0xb2
5791 };
5792
5793 avio_wb32(pb, 0); /* size placeholder */
5794 ffio_wfourcc(pb, "uuid");
5795 avio_write(pb, uuid, AV_UUID_LEN);
5796 avio_w8(pb, 1);
5797 avio_wb24(pb, 0);
5798 avio_wb64(pb, track->cluster[0].dts + track->cluster[0].cts);
5799 avio_wb64(pb, track->end_pts -
5800 (track->cluster[0].dts + track->cluster[0].cts));
5801
5802 return update_size(pb, pos);
5803}
5804
5806 MOVTrack *track, int entry)
5807{
5808 int n = track->nb_frag_info - 1 - entry, i;
5809 int size = 8 + 16 + 4 + 1 + 16*n;
5810 static const uint8_t uuid[] = {
5811 0xd4, 0x80, 0x7e, 0xf2, 0xca, 0x39, 0x46, 0x95,
5812 0x8e, 0x54, 0x26, 0xcb, 0x9e, 0x46, 0xa7, 0x9f
5813 };
5814
5815 if (entry < 0)
5816 return 0;
5817
5818 avio_seek(pb, track->frag_info[entry].tfrf_offset, SEEK_SET);
5819 avio_wb32(pb, size);
5820 ffio_wfourcc(pb, "uuid");
5821 avio_write(pb, uuid, AV_UUID_LEN);
5822 avio_w8(pb, 1);
5823 avio_wb24(pb, 0);
5824 avio_w8(pb, n);
5825 for (i = 0; i < n; i++) {
5826 int index = entry + 1 + i;
5827 avio_wb64(pb, track->frag_info[index].time);
5828 avio_wb64(pb, track->frag_info[index].duration);
5829 }
5830 if (n < mov->ism_lookahead) {
5831 int free_size = 16 * (mov->ism_lookahead - n);
5832 avio_wb32(pb, free_size);
5833 ffio_wfourcc(pb, "free");
5834 ffio_fill(pb, 0, free_size - 8);
5835 }
5836
5837 return 0;
5838}
5839
5841 MOVTrack *track)
5842{
5843 int64_t pos = avio_tell(pb);
5844 int i;
5845 for (i = 0; i < mov->ism_lookahead; i++) {
5846 /* Update the tfrf tag for the last ism_lookahead fragments,
5847 * nb_frag_info - 1 is the next fragment to be written. */
5848 mov_write_tfrf_tag(pb, mov, track, track->nb_frag_info - 2 - i);
5849 }
5850 avio_seek(pb, pos, SEEK_SET);
5851 return 0;
5852}
5853
5854static int mov_add_tfra_entries(AVIOContext *pb, MOVMuxContext *mov, int tracks,
5855 int size)
5856{
5857 int i;
5858 for (i = 0; i < mov->nb_tracks; i++) {
5859 MOVTrack *track = &mov->tracks[i];
5860 MOVFragmentInfo *info;
5861 if ((tracks >= 0 && i != tracks) || !track->entry)
5862 continue;
5863 track->nb_frag_info++;
5864 if (track->nb_frag_info >= track->frag_info_capacity) {
5865 unsigned new_capacity = track->nb_frag_info + MOV_FRAG_INFO_ALLOC_INCREMENT;
5866 if (av_reallocp_array(&track->frag_info,
5867 new_capacity,
5868 sizeof(*track->frag_info)))
5869 return AVERROR(ENOMEM);
5870 track->frag_info_capacity = new_capacity;
5871 }
5872 info = &track->frag_info[track->nb_frag_info - 1];
5873 info->offset = avio_tell(pb);
5874 info->size = size;
5875 // Try to recreate the original pts for the first packet
5876 // from the fields we have stored
5877 info->time = track->cluster[0].dts + track->cluster[0].cts;
5878 info->duration = track->end_pts -
5879 (track->cluster[0].dts + track->cluster[0].cts);
5880 // If the pts is less than zero, we will have trimmed
5881 // away parts of the media track using an edit list,
5882 // and the corresponding start presentation time is zero.
5883 if (info->time < 0) {
5884 info->duration += info->time;
5885 info->time = 0;
5886 }
5887 info->tfrf_offset = 0;
5888 mov_write_tfrf_tags(pb, mov, track);
5889 }
5890 return 0;
5891}
5892
5893static void mov_prune_frag_info(MOVMuxContext *mov, int tracks, int max)
5894{
5895 int i;
5896 for (i = 0; i < mov->nb_tracks; i++) {
5897 MOVTrack *track = &mov->tracks[i];
5898 if ((tracks >= 0 && i != tracks) || !track->entry)
5899 continue;
5900 if (track->nb_frag_info > max) {
5901 memmove(track->frag_info, track->frag_info + (track->nb_frag_info - max), max * sizeof(*track->frag_info));
5902 track->nb_frag_info = max;
5903 }
5904 }
5905}
5906
5908{
5909 int64_t pos = avio_tell(pb);
5910
5911 avio_wb32(pb, 0); /* size */
5912 ffio_wfourcc(pb, "tfdt");
5913 avio_w8(pb, 1); /* version */
5914 avio_wb24(pb, 0);
5915 avio_wb64(pb, track->cluster[0].dts - track->start_dts);
5916 return update_size(pb, pos);
5917}
5918
5920 MOVTrack *track, int64_t moof_offset,
5921 int moof_size)
5922{
5923 int64_t pos = avio_tell(pb);
5924 int i, start = 0;
5925 avio_wb32(pb, 0); /* size placeholder */
5926 ffio_wfourcc(pb, "traf");
5927
5928 mov_write_tfhd_tag(pb, mov, track, moof_offset);
5929 if (mov->mode != MODE_ISM)
5930 mov_write_tfdt_tag(pb, track);
5931 for (i = 1; i < track->entry; i++) {
5932 if (track->cluster[i].pos != track->cluster[i - 1].pos + track->cluster[i - 1].size) {
5933 mov_write_trun_tag(pb, mov, track, moof_size, start, i);
5934 start = i;
5935 }
5936 }
5937 mov_write_trun_tag(pb, mov, track, moof_size, start, track->entry);
5938 if (mov->mode == MODE_ISM) {
5939 mov_write_tfxd_tag(pb, track);
5940
5941 if (mov->ism_lookahead) {
5942 int size = 16 + 4 + 1 + 16 * mov->ism_lookahead;
5943
5944 if (track->nb_frag_info > 0) {
5945 MOVFragmentInfo *info = &track->frag_info[track->nb_frag_info - 1];
5946 if (!info->tfrf_offset)
5947 info->tfrf_offset = avio_tell(pb);
5948 }
5949 avio_wb32(pb, 8 + size);
5950 ffio_wfourcc(pb, "free");
5951 ffio_fill(pb, 0, size);
5952 }
5953 }
5954
5955 if (track->cenc.aes_ctr && (mov->flags & FF_MOV_FLAG_FRAGMENT))
5956 ff_mov_cenc_write_stbl_atoms(&track->cenc, pb, moof_offset);
5957
5958 return update_size(pb, pos);
5959}
5960
5962 int tracks, int moof_size)
5963{
5964 int64_t pos = avio_tell(pb);
5965 int i;
5966
5967 avio_wb32(pb, 0); /* size placeholder */
5968 ffio_wfourcc(pb, "moof");
5969 mov->first_trun = 1;
5970
5971 mov_write_mfhd_tag(pb, mov);
5972 for (i = 0; i < mov->nb_tracks; i++) {
5973 MOVTrack *track = &mov->tracks[i];
5974 if (tracks >= 0 && i != tracks)
5975 continue;
5976 if (!track->entry)
5977 continue;
5978 if (track->cenc.aes_ctr && (mov->flags & FF_MOV_FLAG_FRAGMENT))
5979 mov_write_pssh_tag(pb, track->st);
5980 mov_write_traf_tag(pb, mov, track, pos, moof_size);
5981 }
5982
5983 return update_size(pb, pos);
5984}
5985
5987 MOVTrack *track, int ref_size, int total_sidx_size)
5988{
5989 int64_t pos = avio_tell(pb), offset_pos, end_pos;
5990 int64_t presentation_time, duration, offset;
5991 unsigned starts_with_SAP;
5992 int i, entries;
5993
5994 if (track->entry) {
5995 entries = 1;
5996 presentation_time = track->cluster[0].dts + track->cluster[0].cts;
5997 duration = track->end_pts -
5998 (track->cluster[0].dts + track->cluster[0].cts);
5999 starts_with_SAP = track->cluster[0].flags & MOV_SYNC_SAMPLE;
6000
6001 // pts<0 should be cut away using edts
6002 if (presentation_time < 0) {
6003 duration += presentation_time;
6004 presentation_time = 0;
6005 }
6006 } else {
6007 entries = track->nb_frag_info;
6008 if (entries <= 0)
6009 return 0;
6010 presentation_time = track->frag_info[0].time;
6011 }
6012
6013 avio_wb32(pb, 0); /* size */
6014 ffio_wfourcc(pb, "sidx");
6015 avio_w8(pb, 1); /* version */
6016 avio_wb24(pb, 0);
6017 avio_wb32(pb, track->track_id); /* reference_ID */
6018 avio_wb32(pb, track->timescale); /* timescale */
6019 avio_wb64(pb, presentation_time); /* earliest_presentation_time */
6020 offset_pos = avio_tell(pb);
6021 avio_wb64(pb, 0); /* first_offset (offset to referenced moof) */
6022 avio_wb16(pb, 0); /* reserved */
6023
6024 avio_wb16(pb, entries); /* reference_count */
6025 for (i = 0; i < entries; i++) {
6026 if (!track->entry) {
6027 if (i > 1 && track->frag_info[i].offset != track->frag_info[i - 1].offset + track->frag_info[i - 1].size) {
6028 av_log(NULL, AV_LOG_ERROR, "Non-consecutive fragments, writing incorrect sidx\n");
6029 }
6030 duration = track->frag_info[i].duration;
6031 ref_size = track->frag_info[i].size;
6032 starts_with_SAP = 1;
6033 }
6034 avio_wb32(pb, (0 << 31) | (ref_size & 0x7fffffff)); /* reference_type (0 = media) | referenced_size */
6035 avio_wb32(pb, duration); /* subsegment_duration */
6036 avio_wb32(pb, (starts_with_SAP << 31) | (0 << 28) | 0); /* starts_with_SAP | SAP_type | SAP_delta_time */
6037 }
6038
6039 end_pos = avio_tell(pb);
6040 offset = pos + total_sidx_size - end_pos;
6041 avio_seek(pb, offset_pos, SEEK_SET);
6042 avio_wb64(pb, offset);
6043 avio_seek(pb, end_pos, SEEK_SET);
6044 return update_size(pb, pos);
6045}
6046
6048 int tracks, int ref_size)
6049{
6050 int i, round, ret;
6051 AVIOContext *avio_buf;
6052 int total_size = 0;
6053 for (round = 0; round < 2; round++) {
6054 // First run one round to calculate the total size of all
6055 // sidx atoms.
6056 // This would be much simpler if we'd only write one sidx
6057 // atom, for the first track in the moof.
6058 if (round == 0) {
6059 if ((ret = ffio_open_null_buf(&avio_buf)) < 0)
6060 return ret;
6061 } else {
6062 avio_buf = pb;
6063 }
6064 for (i = 0; i < mov->nb_tracks; i++) {
6065 MOVTrack *track = &mov->tracks[i];
6066 if (tracks >= 0 && i != tracks)
6067 continue;
6068 // When writing a sidx for the full file, entry is 0, but
6069 // we want to include all tracks. ref_size is 0 in this case,
6070 // since we read it from frag_info instead.
6071 if (!track->entry && ref_size > 0)
6072 continue;
6073 total_size -= mov_write_sidx_tag(avio_buf, track, ref_size,
6074 total_size);
6075 }
6076 if (round == 0) {
6077 total_size = ffio_close_null_buf(avio_buf);
6078 if (total_size < 0)
6079 return total_size;
6080 }
6081 }
6082 return 0;
6083}
6084
6085static int mov_write_prft_tag(AVIOContext *pb, MOVMuxContext *mov, int tracks)
6086{
6087 int64_t pos = avio_tell(pb), pts_us, ntp_ts;
6088 MOVTrack *first_track;
6089 int flags = 24;
6090
6091 /* PRFT should be associated with at most one track. So, choosing only the
6092 * first track. */
6093 if (tracks > 0)
6094 return 0;
6095 first_track = &(mov->tracks[0]);
6096
6097 if (!first_track->entry) {
6098 av_log(mov->fc, AV_LOG_WARNING, "Unable to write PRFT, no entries in the track\n");
6099 return 0;
6100 }
6101
6102 if (first_track->cluster[0].pts == AV_NOPTS_VALUE) {
6103 av_log(mov->fc, AV_LOG_WARNING, "Unable to write PRFT, first PTS is invalid\n");
6104 return 0;
6105 }
6106
6107 if (mov->write_prft == MOV_PRFT_SRC_WALLCLOCK) {
6108 if (first_track->cluster[0].prft.wallclock) {
6109 /* Round the NTP time to whole milliseconds. */
6110 ntp_ts = ff_get_formatted_ntp_time((first_track->cluster[0].prft.wallclock / 1000) * 1000 +
6112 flags = first_track->cluster[0].prft.flags;
6113 } else
6115 } else if (mov->write_prft == MOV_PRFT_SRC_PTS) {
6116 pts_us = av_rescale_q(first_track->cluster[0].pts,
6117 first_track->st->time_base, AV_TIME_BASE_Q);
6118 ntp_ts = ff_get_formatted_ntp_time(pts_us + NTP_OFFSET_US);
6119 } else {
6120 av_log(mov->fc, AV_LOG_WARNING, "Unsupported PRFT box configuration: %d\n",
6121 mov->write_prft);
6122 return 0;
6123 }
6124
6125 avio_wb32(pb, 0); // Size place holder
6126 ffio_wfourcc(pb, "prft"); // Type
6127 avio_w8(pb, 1); // Version
6128 avio_wb24(pb, flags); // Flags
6129 avio_wb32(pb, first_track->track_id); // reference track ID
6130 avio_wb64(pb, ntp_ts); // NTP time stamp
6131 avio_wb64(pb, first_track->cluster[0].pts); //media time
6132 return update_size(pb, pos);
6133}
6134
6135static int mov_write_moof_tag(AVIOContext *pb, MOVMuxContext *mov, int tracks,
6136 int64_t mdat_size)
6137{
6138 AVIOContext *avio_buf;
6139 int ret, moof_size;
6140
6141 if ((ret = ffio_open_null_buf(&avio_buf)) < 0)
6142 return ret;
6143 mov_write_moof_tag_internal(avio_buf, mov, tracks, 0);
6144 moof_size = ffio_close_null_buf(avio_buf);
6145 if (moof_size < 0)
6146 return moof_size;
6147
6148 if (mov->flags & FF_MOV_FLAG_DASH &&
6150 mov_write_sidx_tags(pb, mov, tracks, moof_size + 8 + mdat_size);
6151
6152 if (mov->write_prft > MOV_PRFT_NONE && mov->write_prft < MOV_PRFT_NB)
6153 mov_write_prft_tag(pb, mov, tracks);
6154
6155 if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX ||
6156 !(mov->flags & FF_MOV_FLAG_SKIP_TRAILER) ||
6157 mov->ism_lookahead) {
6158 if ((ret = mov_add_tfra_entries(pb, mov, tracks, moof_size + 8 + mdat_size)) < 0)
6159 return ret;
6160 if (!(mov->flags & FF_MOV_FLAG_GLOBAL_SIDX) &&
6162 mov_prune_frag_info(mov, tracks, mov->ism_lookahead + 1);
6163 }
6164 }
6165
6166 return mov_write_moof_tag_internal(pb, mov, tracks, moof_size);
6167}
6168
6170{
6171 int64_t pos = avio_tell(pb);
6172 int i;
6173
6174 avio_wb32(pb, 0); /* size placeholder */
6175 ffio_wfourcc(pb, "tfra");
6176 avio_w8(pb, 1); /* version */
6177 avio_wb24(pb, 0);
6178
6179 avio_wb32(pb, track->track_id);
6180 avio_wb32(pb, 0); /* length of traf/trun/sample num */
6181 avio_wb32(pb, track->nb_frag_info);
6182 for (i = 0; i < track->nb_frag_info; i++) {
6183 avio_wb64(pb, track->frag_info[i].time);
6184 avio_wb64(pb, track->frag_info[i].offset + track->data_offset);
6185 avio_w8(pb, 1); /* traf number */
6186 avio_w8(pb, 1); /* trun number */
6187 avio_w8(pb, 1); /* sample number */
6188 }
6189
6190 return update_size(pb, pos);
6191}
6192
6194{
6195 AVIOContext *mfra_pb;
6196 int i, ret, sz;
6197 uint8_t *buf;
6198
6199 ret = avio_open_dyn_buf(&mfra_pb);
6200 if (ret < 0)
6201 return ret;
6202
6203 avio_wb32(mfra_pb, 0); /* size placeholder */
6204 ffio_wfourcc(mfra_pb, "mfra");
6205 /* An empty mfra atom is enough to indicate to the publishing point that
6206 * the stream has ended. */
6207 if (mov->flags & FF_MOV_FLAG_ISML)
6208 goto done_mfra;
6209
6210 for (i = 0; i < mov->nb_tracks; i++) {
6211 MOVTrack *track = &mov->tracks[i];
6212 if (track->nb_frag_info)
6213 mov_write_tfra_tag(mfra_pb, track);
6214 }
6215
6216 avio_wb32(mfra_pb, 16);
6217 ffio_wfourcc(mfra_pb, "mfro");
6218 avio_wb32(mfra_pb, 0); /* version + flags */
6219 avio_wb32(mfra_pb, avio_tell(mfra_pb) + 4);
6220
6221done_mfra:
6222
6223 sz = update_size(mfra_pb, 0);
6224 ret = avio_get_dyn_buf(mfra_pb, &buf);
6225 avio_write(pb, buf, ret);
6226 ffio_free_dyn_buf(&mfra_pb);
6227
6228 return sz;
6229}
6230
6232{
6233 avio_wb32(pb, 8); // placeholder for extended size field (64 bit)
6234 ffio_wfourcc(pb, mov->mode == MODE_MOV ? "wide" : "free");
6235
6236 mov->mdat_pos = avio_tell(pb);
6237 avio_wb32(pb, 0); /* size placeholder*/
6238 ffio_wfourcc(pb, "mdat");
6239 return 0;
6240}
6241
6243 int has_h264, int has_video, int write_minor)
6244{
6245 MOVMuxContext *mov = s->priv_data;
6246 int minor = 0x200;
6247
6248 if (mov->major_brand && strlen(mov->major_brand) >= 4)
6249 ffio_wfourcc(pb, mov->major_brand);
6250 else if (mov->mode == MODE_3GP) {
6251 ffio_wfourcc(pb, has_h264 ? "3gp6" : "3gp4");
6252 minor = has_h264 ? 0x100 : 0x200;
6253 } else if (mov->mode == MODE_AVIF) {
6254 ffio_wfourcc(pb, mov->is_animated_avif ? "avis" : "avif");
6255 minor = 0;
6256 } else if (mov->mode & MODE_3G2) {
6257 ffio_wfourcc(pb, has_h264 ? "3g2b" : "3g2a");
6258 minor = has_h264 ? 0x20000 : 0x10000;
6259 } else if (mov->mode == MODE_PSP)
6260 ffio_wfourcc(pb, "MSNV");
6261 else if (mov->mode == MODE_MP4 && mov->flags & FF_MOV_FLAG_FRAGMENT &&
6263 ffio_wfourcc(pb, "iso6"); // Required when using signed CTS offsets in trun boxes
6264 else if (mov->mode == MODE_MP4 && mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF)
6265 ffio_wfourcc(pb, "iso5"); // Required when using default-base-is-moof
6266 else if (mov->mode == MODE_MP4 && mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS)
6267 ffio_wfourcc(pb, "iso4");
6268 else if (mov->mode == MODE_MP4)
6269 ffio_wfourcc(pb, "isom");
6270 else if (mov->mode == MODE_IPOD)
6271 ffio_wfourcc(pb, has_video ? "M4V ":"M4A ");
6272 else if (mov->mode == MODE_ISM)
6273 ffio_wfourcc(pb, "isml");
6274 else if (mov->mode == MODE_F4V)
6275 ffio_wfourcc(pb, "f4v ");
6276 else
6277 ffio_wfourcc(pb, "qt ");
6278
6279 if (write_minor)
6280 avio_wb32(pb, minor);
6281}
6282
6284{
6285 MOVMuxContext *mov = s->priv_data;
6286 int64_t pos = avio_tell(pb);
6287 int has_h264 = 0, has_av1 = 0, has_video = 0, has_dolby = 0, has_id3 = 0;
6288 int has_iamf = 0;
6289
6290#if CONFIG_IAMFENC
6291 for (int i = 0; i < s->nb_stream_groups; i++) {
6292 const AVStreamGroup *stg = s->stream_groups[i];
6293
6296 has_iamf = 1;
6297 break;
6298 }
6299 }
6300#endif
6301 for (int i = 0; i < mov->nb_streams; i++) {
6302 AVStream *st = mov->tracks[i].st;
6303 if (is_cover_image(st))
6304 continue;
6306 has_video = 1;
6308 has_h264 = 1;
6309 if (st->codecpar->codec_id == AV_CODEC_ID_AV1)
6310 has_av1 = 1;
6311 if (st->codecpar->codec_id == AV_CODEC_ID_AC3 ||
6317 has_dolby = 1;
6319 has_id3 = 1;
6320 }
6321
6322 avio_wb32(pb, 0); /* size */
6323 ffio_wfourcc(pb, "ftyp");
6324
6325 // Write major brand
6326 mov_write_ftyp_tag_internal(pb, s, has_h264, has_video, 1);
6327 // Write the major brand as the first compatible brand as well
6328 mov_write_ftyp_tag_internal(pb, s, has_h264, has_video, 0);
6329
6330 // Write compatible brands, ensuring that we don't write the major brand as a
6331 // compatible brand a second time.
6332 if (mov->mode == MODE_ISM) {
6333 ffio_wfourcc(pb, "piff");
6334 } else if (mov->mode == MODE_AVIF) {
6335 const AVPixFmtDescriptor *pix_fmt_desc =
6336 av_pix_fmt_desc_get(s->streams[0]->codecpar->format);
6337 const int depth = pix_fmt_desc->comp[0].depth;
6338 if (mov->is_animated_avif) {
6339 // For animated AVIF, major brand is "avis". Add "avif" as a
6340 // compatible brand.
6341 ffio_wfourcc(pb, "avif");
6342 ffio_wfourcc(pb, "msf1");
6343 ffio_wfourcc(pb, "iso8");
6344 }
6345 ffio_wfourcc(pb, "mif1");
6346 ffio_wfourcc(pb, "miaf");
6347 if (depth == 8 || depth == 10) {
6348 // MA1B and MA1A brands are based on AV1 profile. Short hand for
6349 // computing that is based on chroma subsampling type. 420 chroma
6350 // subsampling is MA1B. 444 chroma subsampling is MA1A.
6351 if (!pix_fmt_desc->log2_chroma_w && !pix_fmt_desc->log2_chroma_h) {
6352 // 444 chroma subsampling.
6353 ffio_wfourcc(pb, "MA1A");
6354 } else {
6355 // 420 chroma subsampling.
6356 ffio_wfourcc(pb, "MA1B");
6357 }
6358 }
6359 } else if (mov->mode != MODE_MOV) {
6360 // We add tfdt atoms when fragmenting, signal this with the iso6 compatible
6361 // brand, if not already the major brand. This is compatible with users that
6362 // don't understand tfdt.
6363 if (mov->mode == MODE_MP4) {
6364 if (mov->flags & FF_MOV_FLAG_CMAF)
6365 ffio_wfourcc(pb, "cmfc");
6367 ffio_wfourcc(pb, "iso6");
6368 if (has_av1)
6369 ffio_wfourcc(pb, "av01");
6370 if (has_dolby)
6371 ffio_wfourcc(pb, "dby1");
6372 if (has_iamf)
6373 ffio_wfourcc(pb, "iamf");
6374 } else {
6375 if (mov->flags & FF_MOV_FLAG_FRAGMENT)
6376 ffio_wfourcc(pb, "iso6");
6378 ffio_wfourcc(pb, "iso5");
6380 ffio_wfourcc(pb, "iso4");
6381 }
6382 // Brands prior to iso5 can't be signaled when using default-base-is-moof
6383 if (!(mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF)) {
6384 // write isom for mp4 only if it it's not the major brand already.
6386 ffio_wfourcc(pb, "isom");
6387 ffio_wfourcc(pb, "iso2");
6388 if (has_h264)
6389 ffio_wfourcc(pb, "avc1");
6390 }
6391 }
6392
6393 if (mov->mode == MODE_MP4)
6394 ffio_wfourcc(pb, "mp41");
6395
6397 ffio_wfourcc(pb, "dash");
6398
6399 if (has_id3)
6400 ffio_wfourcc(pb, "aid3");
6401
6402 return update_size(pb, pos);
6403}
6404
6406{
6407 AVStream *video_st = s->streams[0];
6408 AVCodecParameters *video_par = s->streams[0]->codecpar;
6409 AVCodecParameters *audio_par = s->streams[1]->codecpar;
6410 int audio_rate = audio_par->sample_rate;
6411 int64_t frame_rate = video_st->avg_frame_rate.den ?
6412 (video_st->avg_frame_rate.num * 0x10000LL) / video_st->avg_frame_rate.den :
6413 0;
6414 int audio_kbitrate = audio_par->bit_rate / 1000;
6415 int video_kbitrate = FFMIN(video_par->bit_rate / 1000, 800 - audio_kbitrate);
6416
6417 if (frame_rate < 0 || frame_rate > INT32_MAX) {
6418 av_log(s, AV_LOG_ERROR, "Frame rate %f outside supported range\n", frame_rate / (double)0x10000);
6419 return AVERROR(EINVAL);
6420 }
6421
6422 avio_wb32(pb, 0x94); /* size */
6423 ffio_wfourcc(pb, "uuid");
6424 ffio_wfourcc(pb, "PROF");
6425
6426 avio_wb32(pb, 0x21d24fce); /* 96 bit UUID */
6427 avio_wb32(pb, 0xbb88695c);
6428 avio_wb32(pb, 0xfac9c740);
6429
6430 avio_wb32(pb, 0x0); /* ? */
6431 avio_wb32(pb, 0x3); /* 3 sections ? */
6432
6433 avio_wb32(pb, 0x14); /* size */
6434 ffio_wfourcc(pb, "FPRF");
6435 avio_wb32(pb, 0x0); /* ? */
6436 avio_wb32(pb, 0x0); /* ? */
6437 avio_wb32(pb, 0x0); /* ? */
6438
6439 avio_wb32(pb, 0x2c); /* size */
6440 ffio_wfourcc(pb, "APRF"); /* audio */
6441 avio_wb32(pb, 0x0);
6442 avio_wb32(pb, 0x2); /* TrackID */
6443 ffio_wfourcc(pb, "mp4a");
6444 avio_wb32(pb, 0x20f);
6445 avio_wb32(pb, 0x0);
6446 avio_wb32(pb, audio_kbitrate);
6447 avio_wb32(pb, audio_kbitrate);
6448 avio_wb32(pb, audio_rate);
6449 avio_wb32(pb, audio_par->ch_layout.nb_channels);
6450
6451 avio_wb32(pb, 0x34); /* size */
6452 ffio_wfourcc(pb, "VPRF"); /* video */
6453 avio_wb32(pb, 0x0);
6454 avio_wb32(pb, 0x1); /* TrackID */
6455 if (video_par->codec_id == AV_CODEC_ID_H264) {
6456 ffio_wfourcc(pb, "avc1");
6457 avio_wb16(pb, 0x014D);
6458 avio_wb16(pb, 0x0015);
6459 } else {
6460 ffio_wfourcc(pb, "mp4v");
6461 avio_wb16(pb, 0x0000);
6462 avio_wb16(pb, 0x0103);
6463 }
6464 avio_wb32(pb, 0x0);
6465 avio_wb32(pb, video_kbitrate);
6466 avio_wb32(pb, video_kbitrate);
6467 avio_wb32(pb, frame_rate);
6468 avio_wb32(pb, frame_rate);
6469 avio_wb16(pb, video_par->width);
6470 avio_wb16(pb, video_par->height);
6471 avio_wb32(pb, 0x010001); /* ? */
6472
6473 return 0;
6474}
6475
6477{
6478 MOVMuxContext *mov = s->priv_data;
6479 int i;
6480
6482 if (mov->mode == MODE_PSP) {
6483 int video_streams_nb = 0, audio_streams_nb = 0, other_streams_nb = 0;
6484 for (i = 0; i < mov->nb_streams; i++) {
6485 AVStream *st = mov->tracks[i].st;
6486 if (is_cover_image(st))
6487 continue;
6489 video_streams_nb++;
6490 else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
6491 audio_streams_nb++;
6492 else
6493 other_streams_nb++;
6494 }
6495
6496 if (video_streams_nb != 1 || audio_streams_nb != 1 || other_streams_nb) {
6497 av_log(s, AV_LOG_ERROR, "PSP mode need one video and one audio stream\n");
6498 return AVERROR(EINVAL);
6499 }
6500 return mov_write_uuidprof_tag(pb, s);
6501 }
6502 return 0;
6503}
6504
6506{
6507 uint32_t c = -1;
6508 int i, closed_gop = 0;
6509
6510 for (i = 0; i < pkt->size - 4; i++) {
6511 c = (c << 8) + pkt->data[i];
6512 if (c == 0x1b8) { // gop
6513 closed_gop = pkt->data[i + 4] >> 6 & 0x01;
6514 } else if (c == 0x100) { // pic
6515 int temp_ref = (pkt->data[i + 1] << 2) | (pkt->data[i + 2] >> 6);
6516 if (!temp_ref || closed_gop) // I picture is not reordered
6518 else
6520 break;
6521 }
6522 }
6523 return 0;
6524}
6525
6527{
6528 const uint8_t *start, *next, *end = pkt->data + pkt->size;
6529 int seq = 0, entry = 0;
6530 int key = pkt->flags & AV_PKT_FLAG_KEY;
6531 start = find_next_marker(pkt->data, end);
6532 for (next = start; next < end; start = next) {
6533 next = find_next_marker(start + 4, end);
6534 switch (AV_RB32(start)) {
6535 case VC1_CODE_SEQHDR:
6536 seq = 1;
6537 break;
6539 entry = 1;
6540 break;
6541 case VC1_CODE_SLICE:
6542 trk->vc1_info.slices = 1;
6543 break;
6544 }
6545 }
6546 if (!trk->entry && trk->vc1_info.first_packet_seen)
6548 if (!trk->entry && !trk->vc1_info.first_frag_written) {
6549 /* First packet in first fragment */
6550 trk->vc1_info.first_packet_seq = seq;
6552 trk->vc1_info.first_packet_seen = 1;
6553 } else if ((seq && !trk->vc1_info.packet_seq) ||
6554 (entry && !trk->vc1_info.packet_entry)) {
6555 int i;
6556 for (i = 0; i < trk->entry; i++)
6557 trk->cluster[i].flags &= ~MOV_SYNC_SAMPLE;
6558 trk->has_keyframes = 0;
6559 if (seq)
6560 trk->vc1_info.packet_seq = 1;
6561 if (entry)
6562 trk->vc1_info.packet_entry = 1;
6563 if (!trk->vc1_info.first_frag_written) {
6564 /* First fragment */
6565 if ((!seq || trk->vc1_info.first_packet_seq) &&
6566 (!entry || trk->vc1_info.first_packet_entry)) {
6567 /* First packet had the same headers as this one, readd the
6568 * sync sample flag. */
6569 trk->cluster[0].flags |= MOV_SYNC_SAMPLE;
6570 trk->has_keyframes = 1;
6571 }
6572 }
6573 }
6574 if (trk->vc1_info.packet_seq && trk->vc1_info.packet_entry)
6575 key = seq && entry;
6576 else if (trk->vc1_info.packet_seq)
6577 key = seq;
6578 else if (trk->vc1_info.packet_entry)
6579 key = entry;
6580 if (key) {
6581 trk->cluster[trk->entry].flags |= MOV_SYNC_SAMPLE;
6582 trk->has_keyframes++;
6583 }
6584}
6585
6587{
6588 int length;
6589
6590 if (pkt->size < 8)
6591 return;
6592
6593 length = (AV_RB16(pkt->data) & 0xFFF) * 2;
6594 if (length < 8 || length > pkt->size)
6595 return;
6596
6597 if (AV_RB32(pkt->data + 4) == 0xF8726FBA) {
6598 trk->cluster[trk->entry].flags |= MOV_SYNC_SAMPLE;
6599 trk->has_keyframes++;
6600 }
6601
6602 return;
6603}
6604
6606{
6607 MOVMuxContext *mov = s->priv_data;
6608 int ret, buf_size;
6609 uint8_t *buf;
6610 int i, offset;
6611
6612 if (!track->mdat_buf)
6613 return 0;
6614 if (!mov->mdat_buf) {
6615 if ((ret = avio_open_dyn_buf(&mov->mdat_buf)) < 0)
6616 return ret;
6617 }
6618 buf_size = avio_get_dyn_buf(track->mdat_buf, &buf);
6619
6620 offset = avio_tell(mov->mdat_buf);
6621 avio_write(mov->mdat_buf, buf, buf_size);
6623
6624 for (i = track->entries_flushed; i < track->entry; i++)
6625 track->cluster[i].pos += offset;
6626 track->entries_flushed = track->entry;
6627 return 0;
6628}
6629
6631{
6632 MOVMuxContext *mov = s->priv_data;
6633 AVPacket *squashed_packet = mov->pkt;
6634 int ret = AVERROR_BUG;
6635
6636 switch (track->st->codecpar->codec_id) {
6637 case AV_CODEC_ID_TTML: {
6638 int had_packets = !!track->squashed_packet_queue.head;
6639
6640 if ((ret = ff_mov_generate_squashed_ttml_packet(s, track, squashed_packet)) < 0) {
6641 goto finish_squash;
6642 }
6643
6644 // We have generated a padding packet (no actual input packets in
6645 // queue) and its duration is zero. Skipping writing it.
6646 if (!had_packets && squashed_packet->duration == 0) {
6647 goto finish_squash;
6648 }
6649
6650 track->end_reliable = 1;
6651 break;
6652 }
6653 default:
6654 ret = AVERROR(EINVAL);
6655 goto finish_squash;
6656 }
6657
6658 squashed_packet->stream_index = track->st->index;
6659
6660 ret = mov_write_single_packet(s, squashed_packet);
6661
6662finish_squash:
6663 av_packet_unref(squashed_packet);
6664
6665 return ret;
6666}
6667
6669{
6670 MOVMuxContext *mov = s->priv_data;
6671
6672 for (int i = 0; i < mov->nb_streams; i++) {
6673 MOVTrack *track = &mov->tracks[i];
6674 int ret = AVERROR_BUG;
6675
6676 if (track->squash_fragment_samples_to_one && !track->entry) {
6677 if ((ret = mov_write_squashed_packet(s, track)) < 0) {
6679 "Failed to write squashed packet for %s stream with "
6680 "index %d and track id %d. Error: %s\n",
6682 track->st->index, track->track_id,
6683 av_err2str(ret));
6684 return ret;
6685 }
6686 }
6687 }
6688
6689 return 0;
6690}
6691
6693 int64_t ref_pos)
6694{
6695 int i;
6696 if (!track->entry)
6697 return 0;
6699 for (i = 0; i < track->entry; i++)
6700 track->cluster[i].pos += ref_pos + track->data_offset;
6701 if (track->cluster_written == 0) {
6702 // First flush. Chunking for this fragment may already have been
6703 // done, either if we didn't use empty_moov, or if we did use
6704 // delay_moov. In either case, reset chunking here.
6705 for (i = 0; i < track->entry; i++) {
6706 track->cluster[i].chunkNum = 0;
6707 track->cluster[i].samples_in_chunk = track->cluster[i].entries;
6708 }
6709 }
6711 track->entry_written + track->entry,
6712 sizeof(*track->cluster)))
6713 return AVERROR(ENOMEM);
6714 memcpy(&track->cluster_written[track->entry_written],
6715 track->cluster, track->entry * sizeof(*track->cluster));
6716 track->entry_written += track->entry;
6717 }
6718 track->entry = 0;
6719 track->entries_flushed = 0;
6720 track->end_reliable = 0;
6721 return 0;
6722}
6723
6724static int mov_flush_fragment(AVFormatContext *s, int force)
6725{
6726 MOVMuxContext *mov = s->priv_data;
6727 int i, first_track = -1;
6728 int64_t mdat_size = 0, mdat_start = 0;
6729 int ret;
6730 int has_video = 0, starts_with_key = 0, first_video_track = 1;
6731
6732 if (!(mov->flags & FF_MOV_FLAG_FRAGMENT))
6733 return 0;
6734
6735 // Check if we have any tracks that require squashing.
6736 // In that case, we'll have to write the packet here.
6737 if ((ret = mov_write_squashed_packets(s)) < 0)
6738 return ret;
6739
6740 // Try to fill in the duration of the last packet in each stream
6741 // from queued packets in the interleave queues. If the flushing
6742 // of fragments was triggered automatically by an AVPacket, we
6743 // already have reliable info for the end of that track, but other
6744 // tracks may need to be filled in.
6745 for (i = 0; i < mov->nb_streams; i++) {
6746 MOVTrack *track = &mov->tracks[i];
6747 if (!track->end_reliable) {
6748 const AVPacket *pkt = ff_interleaved_peek(s, i);
6749 if (pkt) {
6750 int64_t offset, dts, pts;
6752 pts = pkt->pts + offset;
6753 dts = pkt->dts + offset;
6754 if (track->dts_shift != AV_NOPTS_VALUE)
6755 dts += track->dts_shift;
6756 track->track_duration = dts - track->start_dts;
6757 if (pts != AV_NOPTS_VALUE)
6758 track->end_pts = pts;
6759 else
6760 track->end_pts = dts;
6761 if (!(pkt->flags & AV_PKT_FLAG_DISCARD))
6762 track->elst_end_pts = track->end_pts;
6763 }
6764 }
6765 }
6766
6767 for (i = 0; i < mov->nb_tracks; i++) {
6768 MOVTrack *track = &mov->tracks[i];
6769 if (track->entry <= 1)
6770 continue;
6771 // Sample durations are calculated as the diff of dts values,
6772 // but for the last sample in a fragment, we don't know the dts
6773 // of the first sample in the next fragment, so we have to rely
6774 // on what was set as duration in the AVPacket. Not all callers
6775 // set this though, so we might want to replace it with an
6776 // estimate if it currently is zero.
6777 if (get_cluster_duration(track, track->entry - 1) != 0)
6778 continue;
6779 // Use the duration (i.e. dts diff) of the second last sample for
6780 // the last one. This is a wild guess (and fatal if it turns out
6781 // to be too long), but probably the best we can do - having a zero
6782 // duration is bad as well.
6783 track->track_duration += get_cluster_duration(track, track->entry - 2);
6784 track->end_pts += get_cluster_duration(track, track->entry - 2);
6785 if (!mov->missing_duration_warned) {
6787 "Estimating the duration of the last packet in a "
6788 "fragment, consider setting the duration field in "
6789 "AVPacket instead.\n");
6790 mov->missing_duration_warned = 1;
6791 }
6792 }
6793
6794 if (!mov->moov_written) {
6795 int64_t pos = avio_tell(s->pb);
6796 uint8_t *buf;
6797 int buf_size, moov_size;
6798
6799 for (i = 0; i < mov->nb_tracks; i++)
6800 if (!mov->tracks[i].entry && !is_cover_image(mov->tracks[i].st))
6801 break;
6802 /* Don't write the initial moov unless all tracks have data */
6803 if (i < mov->nb_tracks && !force)
6804 return 0;
6805
6806 moov_size = get_moov_size(s);
6807 for (i = 0; i < mov->nb_tracks; i++)
6808 mov->tracks[i].data_offset = pos + moov_size + 8;
6809
6811 if (mov->flags & FF_MOV_FLAG_DELAY_MOOV &&
6814 if ((ret = mov_write_moov_tag(s->pb, mov, s)) < 0)
6815 return ret;
6816
6817 if (mov->flags & FF_MOV_FLAG_DELAY_MOOV) {
6818 if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX)
6819 mov->reserved_header_pos = avio_tell(s->pb);
6821 mov->moov_written = 1;
6822 return 0;
6823 }
6824
6825 if (mov->mdat_buf) {
6826 buf_size = avio_get_dyn_buf(mov->mdat_buf, &buf);
6827 avio_wb32(s->pb, buf_size + 8);
6828 ffio_wfourcc(s->pb, "mdat");
6829 avio_write(s->pb, buf, buf_size);
6831 }
6832
6833 if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX)
6834 mov->reserved_header_pos = avio_tell(s->pb);
6835
6836 mov->moov_written = 1;
6837 mov->mdat_size = 0;
6838 for (i = 0; i < mov->nb_tracks; i++)
6839 mov_finish_fragment(mov, &mov->tracks[i], 0);
6841 return 0;
6842 }
6843
6844 if (mov->frag_interleave) {
6845 for (i = 0; i < mov->nb_tracks; i++) {
6846 MOVTrack *track = &mov->tracks[i];
6847 int ret;
6848 if ((ret = mov_flush_fragment_interleaving(s, track)) < 0)
6849 return ret;
6850 }
6851
6852 if (!mov->mdat_buf)
6853 return 0;
6854 mdat_size = avio_tell(mov->mdat_buf);
6855 }
6856
6857 for (i = 0; i < mov->nb_tracks; i++) {
6858 MOVTrack *track = &mov->tracks[i];
6860 track->data_offset = 0;
6861 else
6862 track->data_offset = mdat_size;
6863 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
6864 has_video = 1;
6865 if (first_video_track) {
6866 if (track->entry)
6867 starts_with_key = track->cluster[0].flags & MOV_SYNC_SAMPLE;
6868 first_video_track = 0;
6869 }
6870 }
6871 if (!track->entry)
6872 continue;
6873 if (track->mdat_buf)
6874 mdat_size += avio_tell(track->mdat_buf);
6875 if (first_track < 0)
6876 first_track = i;
6877 }
6878
6879 if (!mdat_size)
6880 return 0;
6881
6882 avio_write_marker(s->pb,
6883 av_rescale(mov->tracks[first_track].cluster[0].dts, AV_TIME_BASE, mov->tracks[first_track].timescale),
6884 (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);
6885
6886 for (i = first_track; i < mov->nb_tracks; i++) {
6887 MOVTrack *track = &mov->tracks[i];
6888 int buf_size, write_moof = 1, moof_tracks = -1;
6889 uint8_t *buf;
6890
6891 if (!track->entry)
6892 continue;
6893 if (mov->flags & FF_MOV_FLAG_SEPARATE_MOOF) {
6894 mdat_size = avio_tell(track->mdat_buf);
6895 moof_tracks = i;
6896 } else {
6897 write_moof = i == first_track;
6898 }
6899
6900 if (write_moof) {
6902
6903 mov_write_moof_tag(s->pb, mov, moof_tracks, mdat_size);
6904 mov->fragments++;
6905
6906 if (track->cenc.aes_ctr)
6907 ff_mov_cenc_flush(&track->cenc);
6908
6909 avio_wb32(s->pb, mdat_size + 8);
6910 ffio_wfourcc(s->pb, "mdat");
6911 mdat_start = avio_tell(s->pb);
6912 }
6913
6914 mov_finish_fragment(mov, &mov->tracks[i], mdat_start);
6915 if (!mov->frag_interleave) {
6916 if (!track->mdat_buf)
6917 continue;
6918 buf_size = avio_get_dyn_buf(track->mdat_buf, &buf);
6919 avio_write(s->pb, buf, buf_size);
6921 } else {
6922 if (!mov->mdat_buf)
6923 continue;
6924 buf_size = avio_get_dyn_buf(mov->mdat_buf, &buf);
6925 avio_write(s->pb, buf, buf_size);
6927 }
6928 }
6929
6930 mov->mdat_size = 0;
6931
6933 return 0;
6934}
6935
6937{
6938 MOVMuxContext *mov = s->priv_data;
6939 int had_moov = mov->moov_written;
6940 int ret = mov_flush_fragment(s, force);
6941 if (ret < 0)
6942 return ret;
6943 // If using delay_moov, the first flush only wrote the moov,
6944 // not the actual moof+mdat pair, thus flush once again.
6945 if (!had_moov && mov->flags & FF_MOV_FLAG_DELAY_MOOV)
6946 ret = mov_flush_fragment(s, force);
6947 return ret;
6948}
6949
6951{
6952 int64_t ref;
6953 uint64_t duration;
6954
6955 if (trk->entry) {
6956 ref = trk->cluster[trk->entry - 1].dts;
6957 } else if ( trk->start_dts != AV_NOPTS_VALUE
6958 && !trk->frag_discont) {
6959 ref = trk->start_dts + trk->track_duration;
6960 } else
6961 ref = pkt->dts; // Skip tests for the first packet
6962
6963 if (trk->dts_shift != AV_NOPTS_VALUE) {
6964 /* With negative CTS offsets we have set an offset to the DTS,
6965 * reverse this for the check. */
6966 ref -= trk->dts_shift;
6967 }
6968
6969 duration = pkt->dts - ref;
6970 if (pkt->dts < ref || duration >= INT_MAX) {
6971 av_log(s, AV_LOG_WARNING, "Packet duration: %"PRId64" / dts: %"PRId64" in stream %d is out of range\n",
6972 duration, pkt->dts, pkt->stream_index);
6973
6974 pkt->dts = ref + 1;
6975 pkt->pts = AV_NOPTS_VALUE;
6976 }
6977
6978 if (pkt->duration < 0 || pkt->duration > INT_MAX) {
6979 av_log(s, AV_LOG_ERROR, "Application provided duration: %"PRId64" in stream %d is invalid\n", pkt->duration, pkt->stream_index);
6980 return AVERROR(EINVAL);
6981 }
6982 return 0;
6983}
6984
6986 const AVPacket *pkt, AVRational src_time_base)
6987{
6988 MOVMuxContext *mov = s->priv_data;
6989 AVStream *st;
6990 MOVTrack *track;
6991 int64_t offset, dts, pts, candidate_duration;
6992
6993 if (!(mov->flags & FF_MOV_FLAG_FRAGMENT) ||
6994 stream_index < 0 || stream_index >= s->nb_streams ||
6995 pkt->dts == AV_NOPTS_VALUE)
6996 return 0;
6997
6998 st = s->streams[stream_index];
6999 track = st->priv_data;
7000 if (!track->entry || track->start_dts == AV_NOPTS_VALUE)
7001 return 0;
7002
7003 if (ff_get_muxer_ts_offset(s, stream_index, &offset) < 0)
7004 return 0;
7005
7006 dts = av_rescale_q(pkt->dts, src_time_base, st->time_base) + offset;
7007 pts = pkt->pts == AV_NOPTS_VALUE
7009 : av_rescale_q(pkt->pts, src_time_base, st->time_base) + offset;
7010 if (track->dts_shift != AV_NOPTS_VALUE)
7011 dts += track->dts_shift;
7012
7013 candidate_duration = dts - track->start_dts;
7014 if (dts <= track->cluster[track->entry - 1].dts ||
7015 candidate_duration < 0 || candidate_duration >= track->track_duration)
7016 return 0;
7017
7018 track->track_duration = candidate_duration;
7019 track->end_pts = pts != AV_NOPTS_VALUE ? pts : dts;
7020 if (!(pkt->flags & AV_PKT_FLAG_DISCARD))
7021 track->elst_end_pts = track->end_pts;
7022 track->end_reliable = 1;
7023
7024 return 1;
7025}
7026
7028{
7029 MOVMuxContext *mov = s->priv_data;
7030 AVIOContext *pb = s->pb;
7031 MOVTrack *trk;
7032 AVCodecParameters *par;
7034 unsigned int samples_in_chunk = 0;
7036 int size = pkt->size, ret = 0, offset = 0;
7037 size_t prft_size;
7038 uint8_t *reformatted_data = NULL;
7039
7040 if (pkt->stream_index < s->nb_streams)
7041 trk = s->streams[pkt->stream_index]->priv_data;
7042 else // Timecode or chapter
7043 trk = &mov->tracks[pkt->stream_index];
7044 par = trk->par;
7045
7046 ret = check_pkt(s, trk, pkt);
7047 if (ret < 0)
7048 return ret;
7049
7050 if (pkt->pts != AV_NOPTS_VALUE &&
7051 (uint64_t)pkt->dts - pkt->pts != (int32_t)((uint64_t)pkt->dts - pkt->pts)) {
7052 av_log(s, AV_LOG_WARNING, "pts/dts pair unsupported\n");
7053 return AVERROR_PATCHWELCOME;
7054 }
7055
7056 if (mov->flags & FF_MOV_FLAG_FRAGMENT || mov->mode == MODE_AVIF) {
7057 int ret;
7058 if (mov->moov_written || mov->flags & FF_MOV_FLAG_EMPTY_MOOV) {
7059 if (mov->frag_interleave && mov->fragments > 0) {
7060 if (trk->entry - trk->entries_flushed >= mov->frag_interleave) {
7061 if ((ret = mov_flush_fragment_interleaving(s, trk)) < 0)
7062 return ret;
7063 }
7064 }
7065
7066 if (!trk->mdat_buf) {
7067 if ((ret = avio_open_dyn_buf(&trk->mdat_buf)) < 0)
7068 return ret;
7069 }
7070 pb = trk->mdat_buf;
7071 } else {
7072 if (!mov->mdat_buf) {
7073 if ((ret = avio_open_dyn_buf(&mov->mdat_buf)) < 0)
7074 return ret;
7075 }
7076 pb = mov->mdat_buf;
7077 }
7078 }
7079
7080 if (par->codec_id == AV_CODEC_ID_AMR_NB) {
7081 /* We must find out how many AMR blocks there are in one packet */
7082 static const uint16_t packed_size[16] =
7083 {13, 14, 16, 18, 20, 21, 27, 32, 6, 0, 0, 0, 0, 0, 0, 1};
7084 int len = 0;
7085
7086 while (len < size && samples_in_chunk < 100) {
7087 len += packed_size[(pkt->data[len] >> 3) & 0x0F];
7088 samples_in_chunk++;
7089 }
7090 if (samples_in_chunk > 1) {
7091 av_log(s, AV_LOG_ERROR, "fatal error, input is not a single packet, implement a AVParser for it\n");
7092 return -1;
7093 }
7094 } else if (par->codec_id == AV_CODEC_ID_ADPCM_MS ||
7096 samples_in_chunk = trk->par->frame_size;
7097 } else if (trk->sample_size)
7098 samples_in_chunk = size / trk->sample_size;
7099 else
7100 samples_in_chunk = 1;
7101
7102 if (samples_in_chunk < 1) {
7103 av_log(s, AV_LOG_ERROR, "fatal error, input packet contains no samples\n");
7104 return AVERROR_PATCHWELCOME;
7105 }
7106
7107 /* copy extradata if it exists */
7108 if (trk->extradata_size[0] == 0 && par->extradata_size > 0 &&
7109 !TAG_IS_AVCI(trk->tag) &&
7110 (par->codec_id != AV_CODEC_ID_DNXHD)) {
7111 trk->extradata[0] = av_memdup(par->extradata, par->extradata_size);
7112 if (!trk->extradata[0]) {
7113 ret = AVERROR(ENOMEM);
7114 goto err;
7115 }
7116 trk->extradata_size[0] = par->extradata_size;
7117 }
7118
7119 if ((par->codec_id == AV_CODEC_ID_DNXHD ||
7120 par->codec_id == AV_CODEC_ID_H264 ||
7121 par->codec_id == AV_CODEC_ID_HEVC ||
7122 par->codec_id == AV_CODEC_ID_VVC ||
7123 par->codec_id == AV_CODEC_ID_VP9 ||
7124 par->codec_id == AV_CODEC_ID_EVC ||
7125 par->codec_id == AV_CODEC_ID_LCEVC ||
7126 par->codec_id == AV_CODEC_ID_TRUEHD) && !trk->extradata_size[0] &&
7127 !TAG_IS_AVCI(trk->tag)) {
7128 /* copy frame to create needed atoms */
7129 trk->extradata_size[0] = size;
7131 if (!trk->extradata[0]) {
7132 ret = AVERROR(ENOMEM);
7133 goto err;
7134 }
7135 memcpy(trk->extradata[0], pkt->data, size);
7136 memset(trk->extradata[0] + size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
7137 }
7138
7139 const AVPacketSideData *sd = av_packet_side_data_get(pkt->side_data, pkt->side_data_elems, AV_PKT_DATA_NEW_EXTRADATA);
7140 if (pkt->size && sd && sd->size > 0) {
7141 int i;
7142 for (i = 0; i < trk->stsd_count; i++) {
7143 if (trk->extradata_size[i] == sd->size && !memcmp(trk->extradata[i], sd->data, sd->size))
7144 break;
7145 }
7146
7147 if (i < trk->stsd_count)
7148 trk->last_stsd_index = i;
7149 else if (trk->stsd_count <= INT_MAX - 1) {
7150 int new_count = trk->stsd_count + 1;
7151 uint8_t **extradata = av_realloc_array(trk->extradata, new_count, sizeof(*trk->extradata));
7152 if (!extradata)
7153 return AVERROR(ENOMEM);
7154 trk->extradata = extradata;
7155
7156 int *extradata_size = av_realloc_array(trk->extradata_size, new_count, sizeof(*trk->extradata_size));
7157 if (!extradata_size)
7158 return AVERROR(ENOMEM);
7159 trk->extradata_size = extradata_size;
7160
7161 trk->extradata[trk->stsd_count] = av_memdup(sd->data, sd->size);
7162 if (!trk->extradata[trk->stsd_count])
7163 return AVERROR(ENOMEM);
7164
7165 trk->extradata_size[trk->stsd_count] = sd->size;
7166 trk->last_stsd_index = trk->stsd_count;
7167 trk->stsd_count = new_count;
7168 } else
7169 return AVERROR(ENOMEM);
7170 }
7171
7172 if (par->codec_id == AV_CODEC_ID_AAC && pkt->size > 2 &&
7173 (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) {
7174 if (!trk->st->nb_frames) {
7175 av_log(s, AV_LOG_ERROR, "Malformed AAC bitstream detected: "
7176 "use the audio bitstream filter 'aac_adtstoasc' to fix it "
7177 "('-bsf:a aac_adtstoasc' option with ffmpeg)\n");
7178 return -1;
7179 }
7180 av_log(s, AV_LOG_WARNING, "aac bitstream error\n");
7181 }
7182 if (par->codec_id == AV_CODEC_ID_H264 && trk->extradata_size[trk->last_stsd_index] > 0 &&
7183 *(uint8_t *)trk->extradata[trk->last_stsd_index] != 1 && !TAG_IS_AVCI(trk->tag)) {
7184 /* from x264 or from bytestream H.264 */
7185 /* NAL reformatting needed */
7186 if (trk->hint_track >= 0 && trk->hint_track < mov->nb_tracks) {
7187 ret = ff_nal_parse_units_buf(pkt->data, &reformatted_data,
7188 &size);
7189 if (ret < 0)
7190 return ret;
7191 avio_write(pb, reformatted_data, size);
7192 } else {
7193 if (trk->cenc.aes_ctr) {
7194 size = ff_mov_cenc_avc_parse_nal_units(&trk->cenc, pb, pkt->data, size);
7195 if (size < 0) {
7196 ret = size;
7197 goto err;
7198 }
7199 } else {
7200 size = ff_nal_parse_units(pb, pkt->data, pkt->size);
7201 }
7202 }
7203 } else if (par->codec_id == AV_CODEC_ID_HEVC && trk->extradata_size[trk->last_stsd_index] > 6 &&
7204 (AV_RB24(trk->extradata[trk->last_stsd_index]) == 1 || AV_RB32(trk->extradata[trk->last_stsd_index]) == 1)) {
7205 /* extradata is Annex B, assume the bitstream is too and convert it */
7206 int filter_ps = (trk->tag == MKTAG('h','v','c','1'));
7207 if (trk->hint_track >= 0 && trk->hint_track < mov->nb_tracks) {
7208 ret = ff_hevc_annexb2mp4_buf(pkt->data, &reformatted_data,
7209 &size, filter_ps, NULL);
7210 if (ret < 0)
7211 return ret;
7212 avio_write(pb, reformatted_data, size);
7213 } else {
7214 if (trk->cenc.aes_ctr) {
7215 size = ff_mov_cenc_avc_parse_nal_units(&trk->cenc, pb, pkt->data, size);
7216 if (size < 0) {
7217 ret = size;
7218 goto err;
7219 }
7220 } else {
7221 size = ff_hevc_annexb2mp4(pb, pkt->data, pkt->size, filter_ps, NULL);
7222 }
7223 }
7224 } else if (par->codec_id == AV_CODEC_ID_VVC && trk->extradata_size[trk->last_stsd_index] > 6 &&
7225 (AV_RB24(trk->extradata[trk->last_stsd_index]) == 1 || AV_RB32(trk->extradata[trk->last_stsd_index]) == 1)) {
7226 /* extradata is Annex B, assume the bitstream is too and convert it */
7227 if (trk->hint_track >= 0 && trk->hint_track < mov->nb_tracks) {
7228 ret = ff_vvc_annexb2mp4_buf(pkt->data, &reformatted_data,
7229 &size, 0, NULL);
7230 if (ret < 0)
7231 return ret;
7232 avio_write(pb, reformatted_data, size);
7233 } else {
7234 size = ff_vvc_annexb2mp4(pb, pkt->data, pkt->size, 0, NULL);
7235 }
7236 } else if (par->codec_id == AV_CODEC_ID_LCEVC && trk->extradata_size[trk->last_stsd_index] > 0 &&
7237 *(uint8_t *)trk->extradata[trk->last_stsd_index] != 1) {
7238 /* extradata is Annex B, assume the bitstream is too and convert it */
7239 if (trk->hint_track >= 0 && trk->hint_track < mov->nb_tracks) {
7240 ret = ff_nal_parse_units_buf(pkt->data, &reformatted_data, &size);
7241 if (ret < 0)
7242 return ret;
7243 avio_write(pb, reformatted_data, size);
7244 } else {
7245 if (trk->cenc.aes_ctr) {
7246 size = ff_mov_cenc_avc_parse_nal_units(&trk->cenc, pb, pkt->data, size);
7247 if (size < 0) {
7248 ret = size;
7249 goto err;
7250 }
7251 } else {
7252 size = ff_nal_parse_units(pb, pkt->data, pkt->size);
7253 }
7254 }
7255 } else if (par->codec_id == AV_CODEC_ID_AV1 && !trk->cenc.aes_ctr) {
7256 if (trk->hint_track >= 0 && trk->hint_track < mov->nb_tracks) {
7257 ret = ff_av1_filter_obus_buf(pkt->data, &reformatted_data,
7258 &size, &offset);
7259 if (ret < 0)
7260 return ret;
7261 avio_write(pb, reformatted_data, size);
7262 } else {
7263 size = ff_av1_filter_obus(pb, pkt->data, pkt->size);
7264 if (trk->mode == MODE_AVIF && !mov->avif_extent_length[pkt->stream_index]) {
7265 mov->avif_extent_length[pkt->stream_index] = size;
7266 }
7267 }
7268
7269 } else if (par->codec_id == AV_CODEC_ID_AC3 ||
7270 par->codec_id == AV_CODEC_ID_EAC3) {
7271 size = handle_eac3(mov, pkt, trk);
7272 if (size < 0)
7273 return size;
7274 else if (!size)
7275 goto end;
7276 avio_write(pb, pkt->data, size);
7277 } else if (par->codec_id == AV_CODEC_ID_EIA_608) {
7278 size = 8;
7279
7280 for (int i = 0; i < pkt->size; i += 3) {
7281 if (pkt->data[i] == 0xFC) {
7282 size += 2;
7283 }
7284 }
7285 avio_wb32(pb, size);
7286 ffio_wfourcc(pb, "cdat");
7287 for (int i = 0; i < pkt->size; i += 3) {
7288 if (pkt->data[i] == 0xFC) {
7289 avio_w8(pb, pkt->data[i + 1]);
7290 avio_w8(pb, pkt->data[i + 2]);
7291 }
7292 }
7293 } else if (par->codec_id == AV_CODEC_ID_APV) {
7294 ff_isom_parse_apvc(trk->apv, pkt, s);
7295 avio_wb32(s->pb, pkt->size);
7296 size += 4;
7297
7298 avio_write(s->pb, pkt->data, pkt->size);
7299 } else {
7300 if (trk->cenc.aes_ctr) {
7301 uint8_t *extradata = trk->extradata[trk->last_stsd_index];
7302 int extradata_size = trk->extradata_size[trk->last_stsd_index];
7303 if (par->codec_id == AV_CODEC_ID_H264 && extradata_size > 4) {
7304 int nal_size_length = (extradata[4] & 0x3) + 1;
7305 ret = ff_mov_cenc_avc_write_nal_units(s, &trk->cenc, nal_size_length, pb, pkt->data, size);
7306 } else if(par->codec_id == AV_CODEC_ID_HEVC && extradata_size > 21) {
7307 int nal_size_length = (extradata[21] & 0x3) + 1;
7308 ret = ff_mov_cenc_avc_write_nal_units(s, &trk->cenc, nal_size_length, pb, pkt->data, size);
7309 } else if(par->codec_id == AV_CODEC_ID_VVC) {
7311 } else if(par->codec_id == AV_CODEC_ID_AV1) {
7312 av_assert0(size == pkt->size);
7313 ret = ff_mov_cenc_av1_write_obus(s, &trk->cenc, pb, pkt);
7314 if (ret > 0) {
7315 size = ret;
7316 ret = 0;
7317 }
7318 } else {
7319 ret = ff_mov_cenc_write_packet(&trk->cenc, pb, pkt->data, size);
7320 }
7321
7322 if (ret) {
7323 goto err;
7324 }
7325 } else {
7326 avio_write(pb, pkt->data, size);
7327 }
7328 }
7329
7330 if (trk->entry >= trk->cluster_capacity) {
7331 unsigned new_capacity = trk->entry + MOV_INDEX_CLUSTER_SIZE;
7332 void *cluster = av_realloc_array(trk->cluster, new_capacity, sizeof(*trk->cluster));
7333 if (!cluster) {
7334 ret = AVERROR(ENOMEM);
7335 goto err;
7336 }
7337 trk->cluster = cluster;
7338 trk->cluster_capacity = new_capacity;
7339 }
7340
7341 trk->cluster[trk->entry].pos = avio_tell(pb) - size;
7342 trk->cluster[trk->entry].stsd_index = trk->last_stsd_index;
7343 trk->cluster[trk->entry].samples_in_chunk = samples_in_chunk;
7344 trk->cluster[trk->entry].chunkNum = 0;
7345 trk->cluster[trk->entry].size = size;
7346 trk->cluster[trk->entry].entries = samples_in_chunk;
7347 trk->cluster[trk->entry].dts = pkt->dts;
7348 trk->cluster[trk->entry].pts = pkt->pts;
7350 !trk->entry && trk->start_dts != AV_NOPTS_VALUE) {
7351 if (!trk->frag_discont) {
7352 /* First packet of a new fragment. We already wrote the duration
7353 * of the last packet of the previous fragment based on track_duration,
7354 * which might not exactly match our dts. Therefore adjust the dts
7355 * of this packet to be what the previous packets duration implies. */
7356 trk->cluster[trk->entry].dts = trk->start_dts + trk->track_duration;
7357 /* We also may have written the pts and the corresponding duration
7358 * in sidx/tfrf/tfxd tags; make sure the sidx pts and duration match up with
7359 * the next fragment. This means the cts of the first sample must
7360 * be the same in all fragments, unless end_pts was updated by
7361 * the packet causing the fragment to be written. */
7362 if ((mov->flags & FF_MOV_FLAG_DASH &&
7364 mov->mode == MODE_ISM)
7365 pkt->pts = pkt->dts + trk->end_pts - trk->cluster[trk->entry].dts;
7366 } else {
7367 /* New fragment, but discontinuous from previous fragments.
7368 * Pretend the duration sum of the earlier fragments is
7369 * pkt->dts - trk->start_dts. */
7370 trk->end_pts = trk->elst_end_pts = AV_NOPTS_VALUE;
7371 trk->frag_discont = 0;
7372 }
7373 }
7374
7375 if (!trk->entry && trk->start_dts == AV_NOPTS_VALUE && !mov->use_editlist &&
7376 s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO) {
7377 /* Not using edit lists and shifting the first track to start from zero.
7378 * If the other streams start from a later timestamp, we won't be able
7379 * to signal the difference in starting time without an edit list.
7380 * Thus move the timestamp for this first sample to 0, increasing
7381 * its duration instead. */
7382 trk->cluster[trk->entry].dts = trk->start_dts = 0;
7383 }
7384 if (trk->start_dts == AV_NOPTS_VALUE) {
7385 trk->start_dts = pkt->dts;
7386 if (trk->frag_discont) {
7387 if (mov->use_editlist) {
7388 /* Pretend the whole stream started at pts=0, with earlier fragments
7389 * already written. If the stream started at pts=0, the duration sum
7390 * of earlier fragments would have been pkt->pts. */
7391 trk->start_dts = pkt->dts - pkt->pts;
7392 } else {
7393 /* Pretend the whole stream started at dts=0, with earlier fragments
7394 * already written, with a duration summing up to pkt->dts. */
7395 trk->start_dts = 0;
7396 }
7397 trk->frag_discont = 0;
7398 } else if (pkt->dts && mov->moov_written)
7400 "Track %d starts with a nonzero dts %"PRId64", while the moov "
7401 "already has been written. Set the delay_moov flag to handle "
7402 "this case.\n",
7403 pkt->stream_index, pkt->dts);
7404 }
7405
7406 sd = av_packet_side_data_get(pkt->side_data, pkt->side_data_elems, AV_PKT_DATA_SKIP_SAMPLES);
7407 if (sd && sd->size >= 10 && trk->par->frame_size) {
7408 duration = FFMAX(av_rescale_q(trk->par->frame_size, (AVRational){ 1, trk->par->sample_rate },
7409 trk->st->time_base), pkt->duration);
7410 if (mov->use_editlist)
7411 pkt->duration = duration;
7412 duration -= av_rescale_q(AV_RL32(sd->data + 4), (AVRational){ 1, trk->par->sample_rate },
7413 trk->st->time_base);
7414 if (duration < 0)
7415 return AVERROR_INVALIDDATA;
7416 } else
7417 duration = pkt->duration;
7418
7419 trk->track_duration = pkt->dts - trk->start_dts + pkt->duration;
7421
7422 if (pkt->pts == AV_NOPTS_VALUE) {
7423 av_log(s, AV_LOG_WARNING, "pts has no value\n");
7424 pkt->pts = pkt->dts;
7425 }
7426 if (pkt->dts != pkt->pts)
7427 trk->flags |= MOV_TRACK_CTTS;
7428 trk->cluster[trk->entry].cts = pkt->pts - pkt->dts;
7429 trk->cluster[trk->entry].flags = 0;
7430 if (trk->start_cts == AV_NOPTS_VALUE || (pkt->dts <= 0 && trk->start_cts > pkt->pts - pkt->dts))
7431 trk->start_cts = pkt->pts - pkt->dts;
7432 if (trk->end_pts == AV_NOPTS_VALUE)
7433 trk->end_pts = trk->cluster[trk->entry].dts +
7434 trk->cluster[trk->entry].cts + duration;
7435 else
7436 trk->end_pts = FFMAX(trk->end_pts, trk->cluster[trk->entry].dts +
7437 trk->cluster[trk->entry].cts +
7438 duration);
7439 if (!(pkt->flags & AV_PKT_FLAG_DISCARD))
7440 trk->elst_end_pts = trk->end_pts;
7441
7442 if (par->codec_id == AV_CODEC_ID_VC1) {
7444 } else if (par->codec_id == AV_CODEC_ID_TRUEHD) {
7446 } else if (pkt->flags & AV_PKT_FLAG_KEY) {
7447 if (mov->mode == MODE_MOV && par->codec_id == AV_CODEC_ID_MPEG2VIDEO &&
7448 trk->entry > 0) { // force sync sample for the first key frame
7450 if (trk->cluster[trk->entry].flags & MOV_PARTIAL_SYNC_SAMPLE)
7451 trk->flags |= MOV_TRACK_STPS;
7452 } else {
7453 trk->cluster[trk->entry].flags = MOV_SYNC_SAMPLE;
7454 }
7455 if (trk->cluster[trk->entry].flags & MOV_SYNC_SAMPLE)
7456 trk->has_keyframes++;
7457 }
7458 if (pkt->flags & AV_PKT_FLAG_DISPOSABLE) {
7460 trk->has_disposable++;
7461 }
7462
7464 if (prft && prft_size == sizeof(AVProducerReferenceTime))
7465 memcpy(&trk->cluster[trk->entry].prft, prft, prft_size);
7466 else
7467 memset(&trk->cluster[trk->entry].prft, 0, sizeof(AVProducerReferenceTime));
7468
7469 trk->entry++;
7470 trk->sample_count += samples_in_chunk;
7471 mov->mdat_size += size;
7472
7473 if (trk->hint_track >= 0 && trk->hint_track < mov->nb_tracks)
7475 reformatted_data ? reformatted_data + offset
7476 : NULL, size);
7477
7478end:
7479err:
7480
7481 if (pkt->data != reformatted_data)
7482 av_free(reformatted_data);
7483 return ret;
7484}
7485
7487{
7488 MOVMuxContext *mov = s->priv_data;
7489 MOVTrack *trk = s->streams[pkt->stream_index]->priv_data;
7490 AVCodecParameters *par = trk->par;
7491 int64_t frag_duration = 0;
7492 int size = pkt->size;
7493
7494 int ret = check_pkt(s, trk, pkt);
7495 if (ret < 0)
7496 return ret;
7497
7498 if (mov->flags & FF_MOV_FLAG_FRAG_DISCONT) {
7499 for (int i = 0; i < mov->nb_streams; i++)
7500 mov->tracks[i].frag_discont = 1;
7502 }
7503
7505 if (trk->dts_shift == AV_NOPTS_VALUE)
7506 trk->dts_shift = pkt->pts - pkt->dts;
7507 pkt->dts += trk->dts_shift;
7508 }
7509
7510 if (trk->par->codec_id == AV_CODEC_ID_MP4ALS ||
7511 trk->par->codec_id == AV_CODEC_ID_AAC ||
7512 trk->par->codec_id == AV_CODEC_ID_AV1 ||
7513 trk->par->codec_id == AV_CODEC_ID_FLAC) {
7514 size_t side_size;
7515 uint8_t *side = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size);
7516 /* Overwrite extradata only on flush packets or when no extradata was available during init */
7517 if (side_size > 0 && (!pkt->size || !trk->extradata_size[trk->last_stsd_index])) {
7518 void *newextra = av_malloc(side_size + AV_INPUT_BUFFER_PADDING_SIZE);
7519 if (!newextra)
7520 return AVERROR(ENOMEM);
7521 memset((uint8_t*)newextra + side_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
7522 memcpy(newextra, side, side_size);
7523 av_free(trk->extradata[trk->last_stsd_index]);
7524 trk->extradata[trk->last_stsd_index] = newextra;
7525 trk->extradata_size[trk->last_stsd_index] = side_size;
7526 }
7527 }
7528
7529 if (!pkt->size) {
7530 if (trk->start_dts == AV_NOPTS_VALUE && trk->frag_discont) {
7531 trk->start_dts = pkt->dts;
7532 if (pkt->pts != AV_NOPTS_VALUE)
7533 trk->start_cts = pkt->pts - pkt->dts;
7534 else
7535 trk->start_cts = 0;
7536 }
7537
7538 return 0; /* Discard 0 sized packets */
7539 }
7540
7541 if (trk->entry && pkt->stream_index < mov->nb_streams)
7542 frag_duration = av_rescale_q(pkt->dts - trk->cluster[0].dts,
7543 s->streams[pkt->stream_index]->time_base,
7545 if ((mov->max_fragment_duration &&
7546 frag_duration >= mov->max_fragment_duration) ||
7547 (mov->max_fragment_size && mov->mdat_size + size >= mov->max_fragment_size) ||
7550 trk->entry && pkt->flags & AV_PKT_FLAG_KEY) ||
7552 if (frag_duration >= mov->min_fragment_duration) {
7553 if (trk->entry) {
7554 // Set the duration of this track to line up with the next
7555 // sample in this track. This avoids relying on AVPacket
7556 // duration, but only helps for this particular track, not
7557 // for the other ones that are flushed at the same time.
7558 //
7559 // If we have trk->entry == 0, no fragment will be written
7560 // for this track, and we can't adjust the track end here.
7561 trk->track_duration = pkt->dts - trk->start_dts;
7562 if (pkt->pts != AV_NOPTS_VALUE)
7563 trk->end_pts = pkt->pts;
7564 else
7565 trk->end_pts = pkt->dts;
7566 if (!(pkt->flags & AV_PKT_FLAG_DISCARD))
7567 trk->elst_end_pts = trk->end_pts;
7568 trk->end_reliable = 1;
7569 }
7571 }
7572 }
7573
7574 return ff_mov_write_packet(s, pkt);
7575}
7576
7578 int stream_index,
7579 int64_t dts) {
7580 MOVMuxContext *mov = s->priv_data;
7581 AVPacket *end = mov->pkt;
7582 uint8_t data[2] = {0};
7583 int ret;
7584
7585 end->size = sizeof(data);
7586 end->data = data;
7587 end->pts = dts;
7588 end->dts = dts;
7589 end->duration = 0;
7590 end->stream_index = stream_index;
7591
7592 ret = mov_write_single_packet(s, end);
7593 av_packet_unref(end);
7594
7595 return ret;
7596}
7597
7598#if CONFIG_IAMFENC
7599static int mov_build_iamf_packet(AVFormatContext *s, MOVTrack *trk, AVPacket *pkt)
7600{
7601 uint8_t *data;
7602 int ret;
7603
7604 if (pkt->stream_index == trk->first_iamf_idx) {
7605 ret = ff_iamf_write_parameter_blocks(trk->iamf, trk->iamf_buf, pkt, s);
7606 if (ret < 0)
7607 return ret;
7608 }
7609
7610 ret = ff_iamf_write_audio_frame(trk->iamf, trk->iamf_buf,
7611 s->streams[pkt->stream_index]->id, pkt);
7612 if (ret < 0)
7613 return ret;
7614
7615 if (pkt->stream_index != trk->last_iamf_idx)
7616 return AVERROR(EAGAIN);
7617
7618 ret = avio_close_dyn_buf(trk->iamf_buf, &data);
7619 trk->iamf_buf = NULL;
7620 if (!ret) {
7621 if (pkt->size) {
7622 // Either all or none of the packets for a single
7623 // IA Sample may be empty.
7624 av_log(s, AV_LOG_ERROR, "Unexpected packet from "
7625 "stream #%d\n", pkt->stream_index);
7626 ret = AVERROR_INVALIDDATA;
7627 }
7628 av_free(data);
7629 return ret;
7630 }
7631
7632 av_buffer_unref(&pkt->buf);
7633 pkt->buf = av_buffer_create(data, ret, NULL, NULL, 0);
7634 if (!pkt->buf) {
7635 av_free(data);
7636 return AVERROR(ENOMEM);
7637 }
7638 pkt->data = data;
7639 pkt->size = ret;
7640 pkt->stream_index = trk->first_iamf_idx;
7641
7642 return avio_open_dyn_buf(&trk->iamf_buf);
7643}
7644#endif
7645
7647{
7648 int64_t pos = avio_tell(pb);
7649 const char *scheme_id_uri = "https://aomedia.org/emsg/ID3";
7650 const char *value = "";
7651
7652 av_assert0(st->time_base.num == 1);
7653
7657
7658 avio_wb32(pb, 0); /* size */
7659 ffio_wfourcc(pb, "emsg");
7660 avio_w8(pb, 1); /* version */
7661 avio_wb24(pb, 0);
7662 avio_wb32(pb, st->time_base.den); /* timescale */
7663 avio_wb64(pb, pkt->pts); /* presentation_time */
7664 avio_wb32(pb, 0xFFFFFFFFU); /* event_duration */
7665 avio_wb32(pb, 0); /* id */
7666 /* null terminated UTF8 strings */
7667 avio_write(pb, scheme_id_uri, strlen(scheme_id_uri) + 1);
7668 avio_write(pb, value, strlen(value) + 1);
7669 avio_write(pb, pkt->data, pkt->size);
7670
7671 return update_size(pb, pos);
7672}
7673
7675{
7676 MOVMuxContext *mov = s->priv_data;
7677 MOVTrack *trk;
7678
7679 if (!pkt) {
7681 return 1;
7682 }
7683
7684 if (s->streams[pkt->stream_index]->codecpar->codec_id == AV_CODEC_ID_TIMED_ID3) {
7685 mov_write_emsg_tag(s->pb, s->streams[pkt->stream_index], pkt);
7686 return 0;
7687 }
7688
7689 trk = s->streams[pkt->stream_index]->priv_data;
7690
7691#if CONFIG_IAMFENC
7692 if (trk->iamf) {
7693 int ret = mov_build_iamf_packet(s, trk, pkt);
7694 if (ret < 0) {
7695 if (ret == AVERROR(EAGAIN))
7696 return 0;
7697 av_log(s, AV_LOG_ERROR, "Error assembling an IAMF packet "
7698 "for stream #%d\n", trk->st->index);
7699 return ret;
7700 }
7701 }
7702#endif
7703
7704 if (is_cover_image(trk->st)) {
7705 int ret;
7706
7707 if (trk->st->nb_frames >= 1) {
7708 if (trk->st->nb_frames == 1)
7709 av_log(s, AV_LOG_WARNING, "Got more than one picture in stream %d,"
7710 " ignoring.\n", pkt->stream_index);
7711 return 0;
7712 }
7713
7714 if ((ret = av_packet_ref(trk->cover_image, pkt)) < 0)
7715 return ret;
7716
7717 return 0;
7718 } else {
7719 int i;
7720
7721 if (!pkt->size)
7722 return mov_write_single_packet(s, pkt); /* Passthrough. */
7723
7724 /*
7725 * Subtitles require special handling.
7726 *
7727 * 1) For full compliance, every track must have a sample at
7728 * dts == 0, which is rarely true for subtitles. So, as soon
7729 * as we see any packet with dts > 0, write an empty subtitle
7730 * at dts == 0 for any subtitle track with no samples in it.
7731 *
7732 * 2) For each subtitle track, check if the current packet's
7733 * dts is past the duration of the last subtitle sample. If
7734 * so, we now need to write an end sample for that subtitle.
7735 *
7736 * This must be done conditionally to allow for subtitles that
7737 * immediately replace each other, in which case an end sample
7738 * is not needed, and is, in fact, actively harmful.
7739 *
7740 * 3) See mov_write_trailer for how the final end sample is
7741 * handled.
7742 */
7743 for (i = 0; i < mov->nb_tracks; i++) {
7744 MOVTrack *trk = &mov->tracks[i];
7745 int ret;
7746
7747 if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT &&
7748 trk->track_duration < pkt->dts &&
7749 (trk->entry == 0 || !trk->last_sample_is_subtitle_end)) {
7751 if (ret < 0) return ret;
7753 }
7754 }
7755
7757 /*
7758 * If the track has to have its samples squashed into one sample,
7759 * we just take it into the track's queue.
7760 * This will then be utilized as the samples get written in either
7761 * mov_flush_fragment or when the mux is finalized in
7762 * mov_write_trailer.
7763 */
7764 int ret = AVERROR_BUG;
7765
7766 if (pkt->pts == AV_NOPTS_VALUE) {
7768 "Packets without a valid presentation timestamp are "
7769 "not supported with packet squashing!\n");
7770 return AVERROR(EINVAL);
7771 }
7772
7773 /* The following will reset pkt and is only allowed to be used
7774 * because we return immediately. afterwards. */
7776 pkt, NULL, 0)) < 0) {
7777 return ret;
7778 }
7779
7780 return 0;
7781 }
7782
7783
7784 if (trk->mode == MODE_MOV && trk->par->codec_type == AVMEDIA_TYPE_VIDEO) {
7785 AVPacket *opkt = pkt;
7786 int reshuffle_ret, ret;
7787 if (trk->is_unaligned_qt_rgb) {
7788 int64_t bpc = trk->par->bits_per_coded_sample != 15 ? trk->par->bits_per_coded_sample : 16;
7789 int expected_stride = ((trk->par->width * bpc + 15) >> 4)*2;
7790 reshuffle_ret = ff_reshuffle_raw_rgb(s, &pkt, trk->par, expected_stride);
7791 if (reshuffle_ret < 0)
7792 return reshuffle_ret;
7793 } else
7794 reshuffle_ret = 0;
7795 if (trk->par->format == AV_PIX_FMT_PAL8 && !trk->pal_done) {
7796 ret = ff_get_packet_palette(s, opkt, reshuffle_ret, trk->palette);
7797 if (ret < 0)
7798 goto fail;
7799 if (ret)
7800 trk->pal_done++;
7801 } else if (trk->par->codec_id == AV_CODEC_ID_RAWVIDEO &&
7802 (trk->par->format == AV_PIX_FMT_GRAY8 ||
7803 trk->par->format == AV_PIX_FMT_MONOBLACK)) {
7805 if (ret < 0)
7806 goto fail;
7807 for (i = 0; i < pkt->size; i++)
7808 pkt->data[i] = ~pkt->data[i];
7809 }
7810 if (reshuffle_ret) {
7812fail:
7813 if (reshuffle_ret)
7815 return ret;
7816 }
7817 }
7818
7819 return mov_write_single_packet(s, pkt);
7820 }
7821}
7822
7823// QuickTime chapters involve an additional text track with the chapter names
7824// as samples, and a tref pointing from the other tracks to the chapter one.
7826{
7827 static const uint8_t stub_header[] = {
7828 // TextSampleEntry
7829 0x00, 0x00, 0x00, 0x01, // displayFlags
7830 0x00, 0x00, // horizontal + vertical justification
7831 0x00, 0x00, 0x00, 0x00, // bgColourRed/Green/Blue/Alpha
7832 // BoxRecord
7833 0x00, 0x00, 0x00, 0x00, // defTextBoxTop/Left
7834 0x00, 0x00, 0x00, 0x00, // defTextBoxBottom/Right
7835 // StyleRecord
7836 0x00, 0x00, 0x00, 0x00, // startChar + endChar
7837 0x00, 0x01, // fontID
7838 0x00, 0x00, // fontStyleFlags + fontSize
7839 0x00, 0x00, 0x00, 0x00, // fgColourRed/Green/Blue/Alpha
7840 // FontTableBox
7841 0x00, 0x00, 0x00, 0x0D, // box size
7842 'f', 't', 'a', 'b', // box atom name
7843 0x00, 0x01, // entry count
7844 // FontRecord
7845 0x00, 0x01, // font ID
7846 0x00, // font name length
7847 };
7848 MOVMuxContext *mov = s->priv_data;
7849 MOVTrack *track = &mov->tracks[tracknum];
7850 AVPacket *pkt = mov->pkt;
7851 int i, len;
7852 int ret;
7853
7854 track->mode = mov->mode;
7855 track->tag = MKTAG('t','e','x','t');
7856 track->timescale = mov->movie_timescale;
7857 track->par = avcodec_parameters_alloc();
7858 if (!track->par)
7859 return AVERROR(ENOMEM);
7861 ret = ff_alloc_extradata(track->par, sizeof(stub_header));
7862 if (ret < 0)
7863 return ret;
7864 memcpy(track->par->extradata, stub_header, sizeof(stub_header));
7865
7866 if (track->extradata == NULL) {
7867 track->stsd_count = 1;
7868 track->extradata = av_calloc(1, sizeof(*track->extradata));
7869 track->extradata_size = av_calloc(1, sizeof(*track->extradata_size));
7870 if (!track->extradata || !track->extradata_size)
7871 return AVERROR(ENOMEM);
7872 }
7873
7874 track->extradata[0] = av_memdup(stub_header, sizeof(stub_header));
7875 if (!track->extradata[0])
7876 return AVERROR(ENOMEM);
7877 track->extradata_size[0] = sizeof(stub_header);
7878
7879 pkt->stream_index = tracknum;
7880 pkt->flags = AV_PKT_FLAG_KEY;
7881
7882 for (i = 0; i < s->nb_chapters; i++) {
7883 AVChapter *c = s->chapters[i];
7885
7886 int64_t end = av_rescale_q(c->end, c->time_base, (AVRational){1,mov->movie_timescale});
7887 pkt->pts = pkt->dts = av_rescale_q(c->start, c->time_base, (AVRational){1,mov->movie_timescale});
7888 pkt->duration = end - pkt->dts;
7889
7890 if ((t = av_dict_get(c->metadata, "title", NULL, 0))) {
7891 static const char encd[12] = {
7892 0x00, 0x00, 0x00, 0x0C,
7893 'e', 'n', 'c', 'd',
7894 0x00, 0x00, 0x01, 0x00 };
7895 len = strlen(t->value);
7896 pkt->size = len + 2 + 12;
7897 pkt->data = av_malloc(pkt->size);
7898 if (!pkt->data) {
7900 return AVERROR(ENOMEM);
7901 }
7902 AV_WB16(pkt->data, len);
7903 memcpy(pkt->data + 2, t->value, len);
7904 memcpy(pkt->data + len + 2, encd, sizeof(encd));
7906 av_freep(&pkt->data);
7907 }
7908 }
7909
7910 av_packet_unref(mov->pkt);
7911
7912 return 0;
7913}
7914
7915
7916static int mov_check_timecode_track(AVFormatContext *s, AVTimecode *tc, AVStream *src_st, const char *tcstr)
7917{
7918 int ret;
7919
7920 /* compute the frame number */
7921 ret = av_timecode_init_from_string(tc, src_st->avg_frame_rate, tcstr, s);
7922 return ret;
7923}
7924
7925static int mov_create_timecode_track(AVFormatContext *s, int index, int src_index, AVTimecode tc)
7926{
7927 MOVMuxContext *mov = s->priv_data;
7928 MOVTrack *track = &mov->tracks[index];
7929 AVStream *src_st = mov->tracks[src_index].st;
7930 uint8_t data[4];
7931 AVPacket *pkt = mov->pkt;
7932 AVRational rate = src_st->avg_frame_rate;
7933 int ret;
7934
7935 /* tmcd track based on video stream */
7936 track->mode = mov->mode;
7937 track->tag = MKTAG('t','m','c','d');
7938 track->src_track = av_malloc(sizeof(*track->src_track));
7939 if (!track->src_track)
7940 return AVERROR(ENOMEM);
7941 *track->src_track = src_index;
7942 track->nb_src_track = 1;
7944 track->timescale = tc.fps * 1000;
7945 else if (tc.rate.den == 1001)
7946 track->timescale = tc.rate.num;
7947 else
7948 track->timescale = tc.fps;
7951
7952 /* set st to src_st for metadata access*/
7953 track->st = src_st;
7954
7955 /* encode context: tmcd data stream */
7956 track->par = avcodec_parameters_alloc();
7957 if (!track->par)
7958 return AVERROR(ENOMEM);
7960 track->par->codec_tag = track->tag;
7961 track->st->avg_frame_rate = rate;
7962
7963 /* the tmcd track just contains one packet with the frame number */
7964 pkt->data = data;
7965 pkt->stream_index = index;
7966 pkt->flags = AV_PKT_FLAG_KEY;
7967 pkt->pts = pkt->dts = av_rescale_q(tc.start, av_inv_q(rate), (AVRational){ 1, track->timescale });
7968 pkt->size = 4;
7969 AV_WB32(pkt->data, tc.start);
7970 ret = ff_mov_write_packet(s, pkt);
7972 return ret;
7973}
7974
7975/*
7976 * st->disposition controls the "enabled" flag in the tkhd tag.
7977 * QuickTime will not play a track if it is not enabled. So make sure
7978 * that one track of each type (audio, video, subtitle) is enabled.
7979 *
7980 * Subtitles are special. For audio and video, setting "enabled" also
7981 * makes the track "default" (i.e. it is rendered when played). For
7982 * subtitles, an "enabled" subtitle is not rendered by default, but
7983 * if no subtitle is enabled, the subtitle menu in QuickTime will be
7984 * empty!
7985 */
7987{
7988 MOVMuxContext *mov = s->priv_data;
7989 int i;
7990 int enabled[AVMEDIA_TYPE_NB];
7991 int first[AVMEDIA_TYPE_NB];
7992
7993 for (i = 0; i < AVMEDIA_TYPE_NB; i++) {
7994 enabled[i] = 0;
7995 first[i] = -1;
7996 }
7997
7998 for (i = 0; i < mov->nb_streams; i++) {
7999 AVStream *st = mov->tracks[i].st;
8000
8003 is_cover_image(st))
8004 continue;
8005
8006 if (first[st->codecpar->codec_type] < 0)
8007 first[st->codecpar->codec_type] = i;
8010 enabled[st->codecpar->codec_type]++;
8011 }
8012 }
8013
8014 for (i = 0; i < AVMEDIA_TYPE_NB; i++) {
8015 switch (i) {
8016 case AVMEDIA_TYPE_VIDEO:
8017 case AVMEDIA_TYPE_AUDIO:
8019 if (enabled[i] > 1)
8020 mov->per_stream_grouping = 1;
8021 if (!enabled[i] && first[i] >= 0)
8022 mov->tracks[first[i]].flags |= MOV_TRACK_ENABLED;
8023 break;
8024 }
8025 }
8026}
8027
8029{
8030 MOVMuxContext *mov = s->priv_data;
8031
8032 for (int i = 0; i < s->nb_streams; i++)
8033 s->streams[i]->priv_data = NULL;
8034
8035 if (!mov->tracks)
8036 return;
8037
8038 if (mov->chapter_track) {
8040 }
8041
8042 for (int i = 0; i < mov->nb_tracks; i++) {
8043 MOVTrack *const track = &mov->tracks[i];
8044
8045 if (track->tag == MKTAG('r','t','p',' '))
8046 ff_mov_close_hinting(track);
8047 else if (track->tag == MKTAG('t','m','c','d') && mov->nb_meta_tmcd)
8048 av_freep(&track->par);
8049 av_freep(&track->cluster);
8050 av_freep(&track->cluster_written);
8051 av_freep(&track->frag_info);
8052 av_packet_free(&track->cover_image);
8053
8054 if (track->eac3_priv) {
8055 struct eac3_info *info = track->eac3_priv;
8056 av_packet_free(&info->pkt);
8057 av_freep(&track->eac3_priv);
8058 }
8059 for (int j = 0; j < track->stsd_count; j++)
8060 av_freep(&track->extradata[j]);
8061 av_freep(&track->extradata);
8062 av_freep(&track->extradata_size);
8063
8064 for (int i = 0; i < track->nb_tref_tags; i++)
8065 av_freep(&track->tref_tags[i].id);
8066 av_freep(&track->tref_tags);
8067 av_freep(&track->src_track);
8068
8069 ff_mov_cenc_free(&track->cenc);
8070 ffio_free_dyn_buf(&track->mdat_buf);
8071
8072#if CONFIG_IAMFENC
8073 ffio_free_dyn_buf(&track->iamf_buf);
8074 if (track->iamf)
8076 av_freep(&track->iamf);
8077#endif
8078 ff_isom_close_apvc(&track->apv);
8079
8081 }
8082
8083 av_freep(&mov->tracks);
8085}
8086
8087static uint32_t rgb_to_yuv(uint32_t rgb)
8088{
8089 uint8_t r, g, b;
8090 int y, cb, cr;
8091
8092 r = (rgb >> 16) & 0xFF;
8093 g = (rgb >> 8) & 0xFF;
8094 b = (rgb ) & 0xFF;
8095
8096 y = av_clip_uint8(( 16000 + 257 * r + 504 * g + 98 * b)/1000);
8097 cb = av_clip_uint8((128000 - 148 * r - 291 * g + 439 * b)/1000);
8098 cr = av_clip_uint8((128000 + 439 * r - 368 * g - 71 * b)/1000);
8099
8100 return (y << 16) | (cr << 8) | cb;
8101}
8102
8104 AVStream *st)
8105{
8106 int i, width = 720, height = 480;
8107 int have_palette = 0, have_size = 0;
8108 uint32_t palette[16];
8109 char *cur = st->codecpar->extradata;
8110
8111 while (cur && *cur) {
8112 if (strncmp("palette:", cur, 8) == 0) {
8113 int i, count;
8114 count = sscanf(cur + 8,
8115 "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32", "
8116 "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32", "
8117 "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32", "
8118 "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32"",
8119 &palette[ 0], &palette[ 1], &palette[ 2], &palette[ 3],
8120 &palette[ 4], &palette[ 5], &palette[ 6], &palette[ 7],
8121 &palette[ 8], &palette[ 9], &palette[10], &palette[11],
8122 &palette[12], &palette[13], &palette[14], &palette[15]);
8123
8124 for (i = 0; i < count; i++) {
8125 palette[i] = rgb_to_yuv(palette[i]);
8126 }
8127 have_palette = 1;
8128 } else if (!strncmp("size:", cur, 5)) {
8129 sscanf(cur + 5, "%dx%d", &width, &height);
8130 have_size = 1;
8131 }
8132 if (have_palette && have_size)
8133 break;
8134 cur += strcspn(cur, "\n\r");
8135 cur += strspn(cur, "\n\r");
8136 }
8137 if (have_palette) {
8139 if (!track->extradata[track->last_stsd_index])
8140 return AVERROR(ENOMEM);
8141 for (i = 0; i < 16; i++) {
8142 AV_WB32(track->extradata[track->last_stsd_index] + i * 4, palette[i]);
8143 }
8144 memset(track->extradata[track->last_stsd_index] + 16*4, 0, AV_INPUT_BUFFER_PADDING_SIZE);
8145 track->extradata_size[track->last_stsd_index] = 16 * 4;
8146 }
8147 st->codecpar->width = width;
8148 st->codecpar->height = track->height = height;
8149
8150 return 0;
8151}
8152
8153#if CONFIG_IAMFENC
8154static int mov_init_iamf_track(AVFormatContext *s)
8155{
8156 MOVMuxContext *mov = s->priv_data;
8157 MOVTrack *track;
8158 IAMFContext *iamf;
8159 int first_iamf_idx = INT_MAX, last_iamf_idx = 0;
8160 int nb_audio_elements = 0, nb_mix_presentations = 0;
8161 int ret;
8162
8163 for (int i = 0; i < s->nb_stream_groups; i++) {
8164 const AVStreamGroup *stg = s->stream_groups[i];
8165
8167 nb_audio_elements++;
8169 nb_mix_presentations++;
8170 }
8171
8172 if (!nb_audio_elements && !nb_mix_presentations)
8173 return 0;
8174
8175 if (nb_audio_elements < 1 || nb_audio_elements > 2 || nb_mix_presentations < 1) {
8176 av_log(s, AV_LOG_ERROR, "There must be >= 1 and <= 2 IAMF_AUDIO_ELEMENT and at least "
8177 "one IAMF_MIX_PRESENTATION stream groups to write a IMAF track\n");
8178 return AVERROR(EINVAL);
8179 }
8180
8181 iamf = av_mallocz(sizeof(*iamf));
8182 if (!iamf)
8183 return AVERROR(ENOMEM);
8184
8185
8186 for (int i = 0; i < s->nb_stream_groups; i++) {
8187 const AVStreamGroup *stg = s->stream_groups[i];
8188 switch(stg->type) {
8190 for (int j = 0; j < stg->nb_streams; j++) {
8191 first_iamf_idx = FFMIN(stg->streams[j]->index, first_iamf_idx);
8192 last_iamf_idx = FFMAX(stg->streams[j]->index, last_iamf_idx);
8193 }
8194
8195 ret = ff_iamf_add_audio_element(iamf, stg, s);
8196 break;
8198 ret = ff_iamf_add_mix_presentation(iamf, stg, s);
8199 break;
8200 default:
8201 av_assert0(0);
8202 }
8203 if (ret < 0) {
8205 av_free(iamf);
8206 return ret;
8207 }
8208 }
8209
8210 track = &mov->tracks[first_iamf_idx];
8211 track->iamf = iamf;
8212 track->first_iamf_idx = first_iamf_idx;
8213 track->last_iamf_idx = last_iamf_idx;
8214 track->tag = MKTAG('i','a','m','f');
8215
8216 for (int i = 0; i < s->nb_stream_groups; i++) {
8217 AVStreamGroup *stg = s->stream_groups[i];
8219 continue;
8220 for (int j = 0; j < stg->nb_streams; j++)
8221 stg->streams[j]->priv_data = track;
8222 }
8223
8224 ret = avio_open_dyn_buf(&track->iamf_buf);
8225 if (ret < 0)
8226 return ret;
8227
8228 return 0;
8229}
8230#endif
8231
8233{
8234 MOVMuxContext *mov = s->priv_data;
8235 int has_iamf = 0;
8236 int i, ret;
8237
8238 mov->fc = s;
8239 mov->pkt = ffformatcontext(s)->pkt;
8240
8241 /* Default mode == MP4 */
8242 mov->mode = MODE_MP4;
8243
8244#define IS_MODE(muxer, config) (CONFIG_ ## config ## _MUXER && !strcmp(#muxer, s->oformat->name))
8245 if (IS_MODE(3gp, TGP)) mov->mode = MODE_3GP;
8246 else if (IS_MODE(3g2, TG2)) mov->mode = MODE_3GP|MODE_3G2;
8247 else if (IS_MODE(mov, MOV)) mov->mode = MODE_MOV;
8248 else if (IS_MODE(psp, PSP)) mov->mode = MODE_PSP;
8249 else if (IS_MODE(ipod, IPOD)) mov->mode = MODE_IPOD;
8250 else if (IS_MODE(ismv, ISMV)) mov->mode = MODE_ISM;
8251 else if (IS_MODE(f4v, F4V)) mov->mode = MODE_F4V;
8252 else if (IS_MODE(avif, AVIF)) mov->mode = MODE_AVIF;
8253#undef IS_MODE
8254
8255 if (mov->flags & FF_MOV_FLAG_DELAY_MOOV)
8257
8258 if (mov->mode == MODE_AVIF)
8260
8261 /* Set the FRAGMENT flag if any of the fragmentation methods are
8262 * enabled. */
8263 if (mov->max_fragment_duration || mov->max_fragment_size ||
8269
8272 av_log(s, AV_LOG_ERROR, "Setting both hybrid_fragmented and faststart is not supported.\n");
8273 return AVERROR(EINVAL);
8274 }
8275
8276 /* Set other implicit flags immediately */
8279
8280 if (mov->mode == MODE_ISM)
8283 if (mov->flags & FF_MOV_FLAG_DASH)
8286 if (mov->flags & FF_MOV_FLAG_CMAF)
8289
8290 if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV && s->flags & AVFMT_FLAG_AUTO_BSF) {
8291 av_log(s, AV_LOG_VERBOSE, "Empty MOOV enabled; disabling automatic bitstream filtering\n");
8292 s->flags &= ~AVFMT_FLAG_AUTO_BSF;
8293 }
8294
8296 av_log(s, AV_LOG_WARNING, "Global SIDX enabled; Ignoring skip_sidx option\n");
8298 }
8299
8300 if (mov->flags & FF_MOV_FLAG_FASTSTART) {
8301 mov->reserved_moov_size = -1;
8302 }
8303
8304 if (mov->use_editlist < 0) {
8305 mov->use_editlist = 1;
8306 if (mov->flags & FF_MOV_FLAG_FRAGMENT &&
8307 !(mov->flags & FF_MOV_FLAG_DELAY_MOOV)) {
8308 // If we can avoid needing an edit list by shifting the
8309 // tracks, prefer that over (trying to) write edit lists
8310 // in fragmented output.
8311 if (s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO ||
8312 s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO)
8313 mov->use_editlist = 0;
8314 }
8315 }
8316 if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV &&
8317 !(mov->flags & FF_MOV_FLAG_DELAY_MOOV) && mov->use_editlist)
8318 av_log(s, AV_LOG_WARNING, "No meaningful edit list will be written when using empty_moov without delay_moov\n");
8319
8320 if (mov->flags & FF_MOV_FLAG_CMAF && mov->use_editlist)
8322
8323 if (!mov->use_editlist && s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO &&
8325 s->avoid_negative_ts = AVFMT_AVOID_NEG_TS_MAKE_ZERO;
8326
8327 /* Clear the omit_tfhd_offset flag if default_base_moof is set;
8328 * if the latter is set that's enough and omit_tfhd_offset doesn't
8329 * add anything extra on top of that. */
8333
8334 if (mov->frag_interleave &&
8337 "Sample interleaving in fragments is mutually exclusive with "
8338 "omit_tfhd_offset and separate_moof\n");
8339 return AVERROR(EINVAL);
8340 }
8341
8342 /* Non-seekable output is ok if using fragmentation. If ism_lookahead
8343 * is enabled, we don't support non-seekable output at all. */
8344 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL) &&
8345 (!(mov->flags & FF_MOV_FLAG_FRAGMENT) || mov->ism_lookahead ||
8346 mov->mode == MODE_AVIF)) {
8347 av_log(s, AV_LOG_ERROR, "muxer does not support non seekable output\n");
8348 return AVERROR(EINVAL);
8349 }
8350
8351 /* AVIF output must have at most two video streams (one for YUV and one for
8352 * alpha). */
8353 if (mov->mode == MODE_AVIF) {
8354 if (s->nb_streams > 2) {
8355 av_log(s, AV_LOG_ERROR, "AVIF output requires exactly one or two streams\n");
8356 return AVERROR(EINVAL);
8357 }
8358 if (s->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO &&
8359 (s->nb_streams > 1 && s->streams[1]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO)) {
8360 av_log(s, AV_LOG_ERROR, "AVIF output supports only video streams\n");
8361 return AVERROR(EINVAL);
8362 }
8363 if (s->nb_streams > 1) {
8364 const AVPixFmtDescriptor *pixdesc =
8365 av_pix_fmt_desc_get(s->streams[1]->codecpar->format);
8366 if (pixdesc->nb_components != 1) {
8367 av_log(s, AV_LOG_ERROR, "Second stream for AVIF (alpha) output must have exactly one plane\n");
8368 return AVERROR(EINVAL);
8369 }
8370 }
8371 s->streams[0]->disposition |= AV_DISPOSITION_DEFAULT;
8372 }
8373
8374 for (i = 0; i < s->nb_stream_groups; i++) {
8375 AVStreamGroup *stg = s->stream_groups[i];
8376
8377 if (stg->type == AV_STREAM_GROUP_PARAMS_LCEVC) {
8378 if (stg->nb_streams != 2) {
8379 av_log(s, AV_LOG_ERROR, "Exactly two Streams are supported for Stream Groups of type LCEVC\n");
8380 return AVERROR(EINVAL);
8381 }
8383 if (lcevc->el_index > 1)
8384 return AVERROR(EINVAL);
8385 AVStream *st = stg->streams[lcevc->el_index];
8386 if (st->codecpar->codec_id != AV_CODEC_ID_LCEVC) {
8387 av_log(s, AV_LOG_ERROR, "Stream #%u is not an LCEVC stream\n", lcevc->el_index);
8388 return AVERROR(EINVAL);
8389 }
8390 }
8391
8392#if CONFIG_IAMFENC
8394 continue;
8395
8396 for (int j = 0; j < stg->nb_streams; j++) {
8397 AVStream *st = stg->streams[j];
8398
8399 if (st->priv_data) {
8400 av_log(s, AV_LOG_ERROR, "Stream %d is present in more than one Stream Group of type "
8401 "IAMF Audio Element\n", j);
8402 return AVERROR(EINVAL);
8403 }
8404 st->priv_data = st;
8405 }
8406 has_iamf = 1;
8407
8408 if (!mov->nb_tracks) // We support one track for the entire IAMF structure
8409 mov->nb_tracks++;
8410#endif
8411 }
8412
8413 for (i = 0; i < s->nb_streams; i++) {
8414 AVStream *st = s->streams[i];
8415 if (st->priv_data)
8416 continue;
8417 // Don't produce a track in the output file for timed ID3 streams.
8419 // Leave priv_data set to NULL for these AVStreams that don't
8420 // have a corresponding track.
8421 continue;
8422 }
8423 st->priv_data = st;
8424 mov->nb_tracks++;
8425 }
8426
8427 mov->nb_streams = mov->nb_tracks;
8428
8429 if (mov->mode & (MODE_MP4|MODE_MOV|MODE_IPOD) && s->nb_chapters)
8430 mov->chapter_track = mov->nb_tracks++;
8431
8432 if (mov->flags & FF_MOV_FLAG_RTP_HINT) {
8433 for (i = 0; i < s->nb_streams; i++)
8434 if (rtp_hinting_needed(s->streams[i]))
8435 mov->nb_tracks++;
8436 }
8437
8438 if (mov->write_btrt < 0) {
8439 mov->write_btrt = mov->mode == MODE_MP4;
8440 }
8441
8442 if ( mov->write_tmcd == -1 && (mov->mode == MODE_MOV || mov->mode == MODE_MP4)
8443 || mov->write_tmcd == 1) {
8444 AVDictionaryEntry *global_tcr = av_dict_get(s->metadata, "timecode",
8445 NULL, 0);
8446
8447 /* +1 tmcd track for each video stream with a timecode */
8448 for (i = 0; i < s->nb_streams; i++) {
8449 AVStream *st = s->streams[i];
8450 AVDictionaryEntry *t = global_tcr;
8452 (t || (t=av_dict_get(st->metadata, "timecode", NULL, 0)))) {
8453 AVTimecode tc;
8454 ret = mov_check_timecode_track(s, &tc, st, t->value);
8455 if (ret >= 0)
8456 mov->nb_meta_tmcd++;
8457 }
8458 }
8459
8460 /* check if there is already a tmcd track to remux */
8461 if (mov->nb_meta_tmcd) {
8462 for (i = 0; i < s->nb_streams; i++) {
8463 AVStream *st = s->streams[i];
8464 if (st->codecpar->codec_tag == MKTAG('t','m','c','d')) {
8465 av_log(s, AV_LOG_WARNING, "You requested a copy of the original timecode track "
8466 "so timecode metadata are now ignored\n");
8467 mov->nb_meta_tmcd = 0;
8468 }
8469 }
8470 }
8471
8472 mov->nb_tracks += mov->nb_meta_tmcd;
8473 }
8474
8475 // Reserve an extra stream for chapters for the case where chapters
8476 // are written in the trailer
8477 mov->tracks = av_calloc(mov->nb_tracks + 1, sizeof(*mov->tracks));
8478 if (!mov->tracks)
8479 return AVERROR(ENOMEM);
8480
8481 for (i = 0; i < mov->nb_tracks; i++) {
8482 MOVTrack *track = &mov->tracks[i];
8483
8484 track->stsd_count = 1;
8485 track->extradata = av_calloc(track->stsd_count, sizeof(*track->extradata));
8486 track->extradata_size = av_calloc(track->stsd_count, sizeof(*track->extradata_size));
8487 if (!track->extradata || !track->extradata_size)
8488 return AVERROR(ENOMEM);
8489 }
8490
8491 if (mov->encryption_scheme_str != NULL && strcmp(mov->encryption_scheme_str, "none") != 0) {
8492 if (strcmp(mov->encryption_scheme_str, "cenc-aes-ctr") == 0) {
8494
8496 av_log(s, AV_LOG_ERROR, "Invalid encryption key len %d expected %d\n",
8498 return AVERROR(EINVAL);
8499 }
8500
8501 if (mov->encryption_kid_len != CENC_KID_SIZE) {
8502 av_log(s, AV_LOG_ERROR, "Invalid encryption kid len %d expected %d\n",
8504 return AVERROR(EINVAL);
8505 }
8506 } else {
8507 av_log(s, AV_LOG_ERROR, "unsupported encryption scheme %s\n",
8509 return AVERROR(EINVAL);
8510 }
8511 }
8512
8513#if CONFIG_IAMFENC
8514 ret = mov_init_iamf_track(s);
8515 if (ret < 0)
8516 return ret;
8517#endif
8518
8519 for (int j = 0, i = 0; j < s->nb_streams; j++) {
8520 AVStream *st = s->streams[j];
8521
8522 if (st != st->priv_data) {
8523 if (has_iamf)
8524 i += has_iamf--;
8525 continue;
8526 }
8527 st->priv_data = &mov->tracks[i++];
8528 }
8529
8530 AVRational movie_timescale = (AVRational) { 0, 1 };
8531 for (i = 0; i < s->nb_streams; i++) {
8532 AVStream *st= s->streams[i];
8533 MOVTrack *track = st->priv_data;
8534
8535 if (!track)
8536 continue;
8537
8538 if (!track->st) {
8539 track->st = st;
8540 track->par = st->codecpar;
8541 }
8542
8543 movie_timescale = av_gcd_q(movie_timescale, st->time_base, INT_MAX, (AVRational){1,0});
8544 }
8545 if (!movie_timescale.den)
8546 movie_timescale = MOV_TIMESCALE_Q;
8547
8548 if (!mov->movie_timescale)
8549 mov->movie_timescale = FFMAX(movie_timescale.den, MOV_TIMESCALE);
8550
8551 for (i = 0; i < s->nb_streams; i++) {
8552 AVStream *st= s->streams[i];
8553 MOVTrack *track = st->priv_data;
8554 AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL,0);
8555
8556 if (!track)
8557 continue;
8558
8559 track->language = ff_mov_iso639_to_lang(lang?lang->value:"und", mov->mode!=MODE_MOV);
8560 if (track->language < 0)
8561 track->language = 32767; // Unspecified Macintosh language code
8562 track->mode = mov->mode;
8563 if (!track->tag)
8564 track->tag = mov_find_codec_tag(s, track);
8565 if (!track->tag) {
8566 av_log(s, AV_LOG_ERROR, "Could not find tag for codec %s in stream #%d, "
8567 "codec not currently supported in container\n",
8569 return AVERROR(EINVAL);
8570 }
8571 /* If hinting of this track is enabled by a later hint track,
8572 * this is updated. */
8573 track->hint_track = -1;
8574 track->start_dts = AV_NOPTS_VALUE;
8575 track->start_cts = AV_NOPTS_VALUE;
8576 track->end_pts = AV_NOPTS_VALUE;
8577 track->dts_shift = AV_NOPTS_VALUE;
8579 if (track->tag == MKTAG('m','x','3','p') || track->tag == MKTAG('m','x','3','n') ||
8580 track->tag == MKTAG('m','x','4','p') || track->tag == MKTAG('m','x','4','n') ||
8581 track->tag == MKTAG('m','x','5','p') || track->tag == MKTAG('m','x','5','n')) {
8582 if (st->codecpar->width != 720 || (st->codecpar->height != 608 && st->codecpar->height != 512)) {
8583 av_log(s, AV_LOG_ERROR, "D-10/IMX must use 720x608 or 720x512 video resolution\n");
8584 return AVERROR(EINVAL);
8585 }
8586 track->height = track->tag >> 24 == 'n' ? 486 : 576;
8587 }
8588 if (mov->video_track_timescale) {
8589 track->timescale = mov->video_track_timescale;
8590 if (mov->mode == MODE_ISM && mov->video_track_timescale != 10000000)
8591 av_log(s, AV_LOG_WARNING, "Warning: some tools, like mp4split, assume a timescale of 10000000 for ISMV.\n");
8592 } else {
8593 track->timescale = st->time_base.den;
8594 while(track->timescale < 10000)
8595 track->timescale *= 2;
8596 }
8597 if (st->codecpar->width > 65535 || st->codecpar->height > 65535) {
8598 av_log(s, AV_LOG_ERROR, "Resolution %dx%d too large for mov/mp4\n", st->codecpar->width, st->codecpar->height);
8599 return AVERROR(EINVAL);
8600 }
8601 if (track->mode == MODE_MOV && track->timescale > 100000)
8603 "WARNING codec timebase is very high. If duration is too long,\n"
8604 "file may not be playable by quicktime. Specify a shorter timebase\n"
8605 "or choose different container.\n");
8606 if (track->mode == MODE_MOV &&
8607 track->par->codec_id == AV_CODEC_ID_RAWVIDEO &&
8608 track->tag == MKTAG('r','a','w',' ')) {
8609 enum AVPixelFormat pix_fmt = track->par->format;
8610 if (pix_fmt == AV_PIX_FMT_NONE && track->par->bits_per_coded_sample == 1)
8612 track->is_unaligned_qt_rgb =
8619 }
8620 if (track->par->codec_id == AV_CODEC_ID_VP9 && track->mode != MODE_MP4) {
8621 av_log(s, AV_LOG_ERROR, "%s only supported in MP4.\n", avcodec_get_name(track->par->codec_id));
8622 return AVERROR(EINVAL);
8623 } else if (track->par->codec_id == AV_CODEC_ID_AV1 &&
8624 track->mode != MODE_MP4 && track->mode != MODE_AVIF) {
8625 av_log(s, AV_LOG_ERROR, "%s only supported in MP4 and AVIF.\n", avcodec_get_name(track->par->codec_id));
8626 return AVERROR(EINVAL);
8627 } else if (track->par->codec_id == AV_CODEC_ID_VP8) {
8628 /* altref frames handling is not defined in the spec as of version v1.0,
8629 * so just forbid muxing VP8 streams altogether until a new version does */
8630 av_log(s, AV_LOG_ERROR, "VP8 muxing is currently not supported.\n");
8631 return AVERROR_PATCHWELCOME;
8632 } else if (track->par->codec_id == AV_CODEC_ID_APV) {
8633 ret = ff_isom_init_apvc(&track->apv, s);
8634 if (ret < 0)
8635 return ret;
8636 }
8637 if (is_cover_image(st)) {
8638 track->cover_image = av_packet_alloc();
8639 if (!track->cover_image)
8640 return AVERROR(ENOMEM);
8641 }
8642 } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
8643 track->timescale = st->codecpar->sample_rate;
8645 av_log(s, AV_LOG_WARNING, "track %d: codec frame size is not set\n", i);
8646 track->audio_vbr = 1;
8647 }else if (st->codecpar->codec_id == AV_CODEC_ID_ADPCM_MS ||
8650 if (!st->codecpar->block_align) {
8651 av_log(s, AV_LOG_ERROR, "track %d: codec block align is not set for adpcm\n", i);
8652 return AVERROR(EINVAL);
8653 }
8654 track->sample_size = st->codecpar->block_align;
8655 }else if (st->codecpar->frame_size > 1){ /* assume compressed audio */
8656 track->audio_vbr = 1;
8657 }else{
8658 track->sample_size = (av_get_bits_per_sample(st->codecpar->codec_id) >> 3) *
8660 }
8661 if (st->codecpar->codec_id == AV_CODEC_ID_ILBC ||
8663 track->audio_vbr = 1;
8664 }
8665 if (track->mode != MODE_MOV &&
8666 track->par->codec_id == AV_CODEC_ID_MP3 && track->timescale < 16000) {
8667 if (s->strict_std_compliance >= FF_COMPLIANCE_NORMAL) {
8668 av_log(s, AV_LOG_ERROR, "track %d: muxing mp3 at %dhz is not standard, to mux anyway set strict to -1\n",
8669 i, track->par->sample_rate);
8670 return AVERROR(EINVAL);
8671 } else {
8672 av_log(s, AV_LOG_WARNING, "track %d: muxing mp3 at %dhz is not standard in MP4\n",
8673 i, track->par->sample_rate);
8674 }
8675 }
8676 if (track->par->codec_id == AV_CODEC_ID_FLAC ||
8677 track->par->codec_id == AV_CODEC_ID_TRUEHD ||
8678 track->par->codec_id == AV_CODEC_ID_OPUS) {
8679 if (track->mode != MODE_MP4) {
8680 av_log(s, AV_LOG_ERROR, "%s only supported in MP4.\n", avcodec_get_name(track->par->codec_id));
8681 return AVERROR(EINVAL);
8682 }
8683 if (track->par->codec_id == AV_CODEC_ID_TRUEHD &&
8684 s->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) {
8686 "%s in MP4 support is experimental, add "
8687 "'-strict %d' if you want to use it.\n",
8689 return AVERROR_EXPERIMENTAL;
8690 }
8691 }
8692 } else if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
8693 track->timescale = st->time_base.den;
8694
8695 if (track->par->codec_id == AV_CODEC_ID_TTML) {
8696 /* 14496-30 requires us to use a single sample per fragment
8697 for TTML, for which we define a per-track flag.
8698
8699 We set the flag in case we are receiving TTML paragraphs
8700 from the input, in other words in case we are not doing
8701 stream copy. */
8704
8705 if (track->mode != MODE_ISM &&
8706 track->par->codec_tag == MOV_ISMV_TTML_TAG &&
8707 s->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL) {
8709 "ISMV style TTML support with the 'dfxp' tag in "
8710 "non-ISMV formats is not officially supported. Add "
8711 "'-strict unofficial' if you want to use it.\n");
8712 return AVERROR_EXPERIMENTAL;
8713 }
8714 }
8715 } else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA) {
8716 track->timescale = st->time_base.den;
8717 if (track->tag == MKTAG('t','m','c','d') &&
8718 st->codecpar->extradata_size >= 8)
8719 track->timecode_flags = AV_RB32(st->codecpar->extradata + 4);
8720 } else {
8721 track->timescale = mov->movie_timescale;
8722 }
8723 if (!track->height)
8724 track->height = st->codecpar->height;
8725 /* The Protected Interoperable File Format (PIFF) standard, used by ISMV recommends but
8726 doesn't mandate a track timescale of 10,000,000. The muxer allows a custom timescale
8727 for video tracks, so if user-set, it isn't overwritten */
8728 if (mov->mode == MODE_ISM &&
8731 track->timescale = 10000000;
8732 }
8733
8734 avpriv_set_pts_info(st, 64, 1, track->timescale);
8735
8737 ret = ff_mov_cenc_init(&track->cenc, mov->encryption_key,
8738 (track->par->codec_id == AV_CODEC_ID_H264 || track->par->codec_id == AV_CODEC_ID_HEVC ||
8739 track->par->codec_id == AV_CODEC_ID_VVC || track->par->codec_id == AV_CODEC_ID_AV1),
8740 track->par->codec_id, s->flags & AVFMT_FLAG_BITEXACT);
8741 if (ret)
8742 return ret;
8743 }
8744 }
8745
8746 for (i = 0; i < s->nb_stream_groups; i++) {
8747 AVStreamGroup *stg = s->stream_groups[i];
8748
8749 switch (stg->type) {
8752 AVStream *st = stg->streams[lcevc->el_index];
8753 MOVTrack *track = st->priv_data;
8754
8755 for (int j = 0; j < mov->nb_tracks; j++) {
8756 MOVTrack *trk = &mov->tracks[j];
8757
8758 if (trk->st == stg->streams[!lcevc->el_index]) {
8759 track->src_track = av_malloc(sizeof(*track->src_track));
8760 if (!track->src_track)
8761 return AVERROR(ENOMEM);
8762 *track->src_track = j;
8763 track->nb_src_track = 1;
8764 break;
8765 }
8766 }
8767
8768 track->par->width = lcevc->width;
8769 track->par->height = track->height = lcevc->height;
8770 break;
8771 }
8773 const AVStreamGroupTREF *tref = stg->params.tref;
8774 MOVTrack *track;
8775
8776 if (tref->metadata_index >= stg->nb_streams)
8777 return AVERROR(EINVAL);
8778
8779 track = stg->streams[tref->metadata_index]->priv_data;
8780 for (int j = 0; j < stg->nb_streams; j++) {
8781 const AVStream *st2 = stg->streams[j];
8782 int index = -1;
8783
8784 if (j == tref->metadata_index)
8785 continue;
8786
8787 for (int k = 0; k < mov->nb_tracks; k++) {
8788 if (mov->tracks[k].st != st2)
8789 continue;
8790 index = k;
8791 break;
8792 }
8793 if (index < 0)
8794 return AVERROR(EINVAL);
8795
8796 int *tmp = av_realloc(track->src_track,
8797 (track->nb_src_track + 1) * sizeof(*track->src_track));
8798 if (!tmp)
8799 return AVERROR(ENOMEM);
8800 track->src_track = tmp;
8801 track->src_track[track->nb_src_track++] = index;
8802 }
8803 break;
8804 }
8805 default:
8806 break;
8807 }
8808 }
8809
8810 /* fill src_track for tmcd tracks not covered by stream groups or
8811 * created by this muxer, retaining the old behavior of src_track
8812 * being arbitrarily 0. */
8813 for (i = 0; i < s->nb_streams; i++) {
8814 AVStream *st = s->streams[i];
8815 MOVTrack *track = st->priv_data;
8816 if (st->codecpar->codec_tag != MKTAG('t','m','c','d') ||
8817 track->nb_src_track)
8818 continue;
8819
8820 track->src_track = av_malloc(sizeof(*track->src_track));
8821 if (!track->src_track)
8822 return AVERROR(ENOMEM);
8823 *track->src_track = 0;
8824 track->nb_src_track = 1;
8825 }
8826
8828 return 0;
8829}
8830
8832{
8833 AVIOContext *pb = s->pb;
8834 MOVMuxContext *mov = s->priv_data;
8835 int ret, hint_track = 0, tmcd_track = 0, nb_tracks = mov->nb_streams;
8836
8837 if (mov->mode & (MODE_MP4|MODE_MOV|MODE_IPOD) && s->nb_chapters)
8838 nb_tracks++;
8839
8840 if (mov->flags & FF_MOV_FLAG_RTP_HINT) {
8841 hint_track = nb_tracks;
8842 for (int i = 0; i < mov->nb_streams; i++) {
8843 if (rtp_hinting_needed(mov->tracks[i].st))
8844 nb_tracks++;
8845 }
8846 }
8847
8848 if (mov->nb_meta_tmcd)
8849 tmcd_track = nb_tracks;
8850
8851 for (int i = 0; i < mov->nb_streams; i++) {
8852 MOVTrack *track = &mov->tracks[i];
8853 AVStream *st = track->st;
8854
8855 /* copy extradata if it exists */
8856 if (st->codecpar->extradata_size) {
8859 else if (!TAG_IS_AVCI(track->tag) && st->codecpar->codec_id != AV_CODEC_ID_DNXHD) {
8861 track->extradata[track->last_stsd_index] =
8863 if (!track->extradata[track->last_stsd_index]) {
8864 return AVERROR(ENOMEM);
8865 }
8866 memcpy(track->extradata[track->last_stsd_index],
8867 st->codecpar->extradata, track->extradata_size[track->last_stsd_index]);
8868 memset(track->extradata[track->last_stsd_index] + track->extradata_size[track->last_stsd_index],
8870 }
8871 }
8872
8876 continue;
8877
8878 for (int j = 0; j < mov->nb_streams; j++) {
8879 AVStream *stj= mov->tracks[j].st;
8880 MOVTrack *trackj= &mov->tracks[j];
8881 if (j == i)
8882 continue;
8883
8884 if (stj->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
8885 (trackj->par->ch_layout.nb_channels != 1 ||
8888 )
8889 track->mono_as_fc = -1;
8890
8891 if (stj->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
8894 trackj->par->ch_layout.nb_channels == 1 && track->mono_as_fc >= 0
8895 )
8896 track->mono_as_fc++;
8897
8898 if (stj->codecpar->codec_type != AVMEDIA_TYPE_AUDIO ||
8901 trackj->language != track->language ||
8902 trackj->tag != track->tag
8903 )
8904 continue;
8905 track->multichannel_as_mono++;
8906 }
8907 }
8908
8909 if (!(mov->flags & FF_MOV_FLAG_DELAY_MOOV) ||
8911 if ((ret = mov_write_identification(pb, s)) < 0)
8912 return ret;
8913 }
8914
8915 if (mov->reserved_moov_size){
8916 mov->reserved_header_pos = avio_tell(pb);
8917 if (mov->reserved_moov_size > 0)
8918 avio_skip(pb, mov->reserved_moov_size);
8919 }
8920
8921 if (mov->flags & FF_MOV_FLAG_FRAGMENT) {
8922 /* If no fragmentation options have been set, set a default. */
8923 if (!(mov->flags & (FF_MOV_FLAG_FRAG_KEYFRAME |
8929 avio_wb32(pb, 8); // placeholder for extended size field (64 bit)
8930 ffio_wfourcc(pb, mov->mode == MODE_MOV ? "wide" : "free");
8931 mov->mdat_pos = avio_tell(pb);
8932 // The free/wide header that later will be converted into an
8933 // mdat, covering the initial moov and all the fragments.
8934 avio_wb32(pb, 0);
8935 ffio_wfourcc(pb, mov->mode == MODE_MOV ? "wide" : "free");
8936 // Write an ftyp atom, hidden in a free/wide. This is neither
8937 // exposed while the file is written, as fragmented, nor when the
8938 // file is finalized into non-fragmented form. However, this allows
8939 // accessing a pristine, sequential ftyp+moov init segment, even
8940 // after the file is finalized. It also allows dumping the whole
8941 // contents of the mdat box, to get the fragmented form of the
8942 // file.
8943 if ((ret = mov_write_identification(pb, s)) < 0)
8944 return ret;
8945 update_size(pb, mov->mdat_pos);
8946 }
8947 } else if (mov->mode != MODE_AVIF) {
8948 if (mov->flags & FF_MOV_FLAG_FASTSTART)
8949 mov->reserved_header_pos = avio_tell(pb);
8950 mov_write_mdat_tag(pb, mov);
8951 }
8952
8954 if (mov->time)
8955 mov->time += 0x7C25B080; // 1970 based -> 1904 based
8956
8957 if (mov->chapter_track)
8958 if ((ret = mov_create_chapter_track(s, mov->chapter_track)) < 0)
8959 return ret;
8960
8961 if (mov->flags & FF_MOV_FLAG_RTP_HINT) {
8962 for (int i = 0; i < mov->nb_streams; i++) {
8963 if (rtp_hinting_needed(mov->tracks[i].st)) {
8964 if ((ret = ff_mov_init_hinting(s, hint_track, i)) < 0)
8965 return ret;
8966 hint_track++;
8967 }
8968 }
8969 }
8970
8971 if (mov->nb_meta_tmcd) {
8972 const AVDictionaryEntry *t, *global_tcr = av_dict_get(s->metadata,
8973 "timecode", NULL, 0);
8974 /* Initialize the tmcd tracks */
8975 for (int i = 0; i < mov->nb_streams; i++) {
8976 AVStream *st = mov->tracks[i].st;
8977 t = global_tcr;
8978
8980 AVTimecode tc;
8981 if (!t)
8982 t = av_dict_get(st->metadata, "timecode", NULL, 0);
8983 if (!t)
8984 continue;
8985 if (mov_check_timecode_track(s, &tc, st, t->value) < 0)
8986 continue;
8987 if ((ret = mov_create_timecode_track(s, tmcd_track, i, tc)) < 0)
8988 return ret;
8989 tmcd_track++;
8990 }
8991 }
8992 }
8993
8994 avio_flush(pb);
8995
8996 if (mov->flags & FF_MOV_FLAG_ISML)
8997 mov_write_isml_manifest(pb, mov, s);
8998
8999 if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV &&
9000 !(mov->flags & FF_MOV_FLAG_DELAY_MOOV)) {
9001 if ((ret = mov_write_moov_tag(pb, mov, s)) < 0)
9002 return ret;
9003 mov->moov_written = 1;
9004 if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX)
9005 mov->reserved_header_pos = avio_tell(pb);
9006 }
9007
9008 return 0;
9009}
9010
9012{
9013 int ret;
9014 AVIOContext *moov_buf;
9015 MOVMuxContext *mov = s->priv_data;
9016
9017 if ((ret = ffio_open_null_buf(&moov_buf)) < 0)
9018 return ret;
9019 if ((ret = mov_write_moov_tag(moov_buf, mov, s)) < 0)
9020 return ret;
9021 return ffio_close_null_buf(moov_buf);
9022}
9023
9025{
9026 int ret;
9027 AVIOContext *buf;
9028 MOVMuxContext *mov = s->priv_data;
9029
9030 if ((ret = ffio_open_null_buf(&buf)) < 0)
9031 return ret;
9032 mov_write_sidx_tags(buf, mov, -1, 0);
9033 return ffio_close_null_buf(buf);
9034}
9035
9036/*
9037 * This function gets the moov size if moved to the top of the file: the chunk
9038 * offset table can switch between stco (32-bit entries) to co64 (64-bit
9039 * entries) when the moov is moved to the beginning, so the size of the moov
9040 * would change. It also updates the chunk offset tables.
9041 */
9043{
9044 int i, moov_size, moov_size2;
9045 MOVMuxContext *mov = s->priv_data;
9046
9047 moov_size = get_moov_size(s);
9048 if (moov_size < 0)
9049 return moov_size;
9050
9051 for (i = 0; i < mov->nb_tracks; i++)
9052 mov->tracks[i].data_offset += moov_size;
9053
9054 moov_size2 = get_moov_size(s);
9055 if (moov_size2 < 0)
9056 return moov_size2;
9057
9058 /* if the size changed, we just switched from stco to co64 and need to
9059 * update the offsets */
9060 if (moov_size2 != moov_size)
9061 for (i = 0; i < mov->nb_tracks; i++)
9062 mov->tracks[i].data_offset += moov_size2 - moov_size;
9063
9064 return moov_size2;
9065}
9066
9068{
9069 int i, sidx_size;
9070 MOVMuxContext *mov = s->priv_data;
9071
9072 sidx_size = get_sidx_size(s);
9073 if (sidx_size < 0)
9074 return sidx_size;
9075
9076 for (i = 0; i < mov->nb_tracks; i++)
9077 mov->tracks[i].data_offset += sidx_size;
9078
9079 return sidx_size;
9080}
9081
9083{
9084 int moov_size;
9085 MOVMuxContext *mov = s->priv_data;
9086
9087 if (mov->flags & FF_MOV_FLAG_FRAGMENT)
9088 moov_size = compute_sidx_size(s);
9089 else
9090 moov_size = compute_moov_size(s);
9091 if (moov_size < 0)
9092 return moov_size;
9093
9094 return ff_format_shift_data(s, mov->reserved_header_pos, moov_size);
9095}
9096
9098{
9099 MOVMuxContext *mov = s->priv_data;
9100 AVIOContext *pb = s->pb;
9101
9102 /* Write size of mdat tag */
9103 if (mov->mdat_size + 8 <= UINT32_MAX) {
9104 avio_seek(pb, mov->mdat_pos, SEEK_SET);
9105 avio_wb32(pb, mov->mdat_size + 8);
9107 ffio_wfourcc(pb, "mdat"); // overwrite the original free/wide into a mdat
9108 } else {
9109 /* overwrite 'wide' placeholder atom */
9110 avio_seek(pb, mov->mdat_pos - 8, SEEK_SET);
9111 /* special value: real atom size will be 64 bit value after
9112 * tag field */
9113 avio_wb32(pb, 1);
9114 ffio_wfourcc(pb, "mdat");
9115 avio_wb64(pb, mov->mdat_size + 16);
9116 }
9117}
9118
9120{
9121 MOVMuxContext *mov = s->priv_data;
9122 AVIOContext *pb = s->pb;
9123 int res = 0;
9124 int i;
9125 int64_t moov_pos;
9126
9127 /*
9128 * Before actually writing the trailer, make sure that there are no
9129 * dangling subtitles, that need a terminating sample.
9130 */
9131 for (i = 0; i < mov->nb_tracks; i++) {
9132 MOVTrack *trk = &mov->tracks[i];
9133 if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT &&
9137 }
9138 }
9139
9140 //Also check for a buffered EAC3 packet
9141 for (i = 0; i < mov->nb_tracks; i++) {
9142 MOVTrack *trk = &mov->tracks[i];
9143 if (trk->par->codec_id != AV_CODEC_ID_EAC3)
9144 continue;
9145 struct eac3_info *info = trk->eac3_priv;
9146 if (!info || !info->pkt || !info->pkt->size)
9147 continue;
9148
9149 av_packet_move_ref(mov->pkt, info->pkt);
9150 info->eof = 1;
9151 res = mov_write_single_packet(s, mov->pkt);
9152 if (res < 0)
9153 return res;
9154
9155 av_packet_unref(mov->pkt);
9156 }
9157
9158 // Check if we have any tracks that require squashing.
9159 // In that case, we'll have to write the packet here.
9160 if ((res = mov_write_squashed_packets(s)) < 0)
9161 return res;
9162
9163 // If there were no chapters when the header was written, but there
9164 // are chapters now, write them in the trailer. This only works
9165 // when we are not doing fragments.
9166 if (!mov->chapter_track && !(mov->flags & FF_MOV_FLAG_FRAGMENT)) {
9167 if (mov->mode & (MODE_MP4|MODE_MOV|MODE_IPOD) && s->nb_chapters) {
9168 mov->chapter_track = mov->nb_tracks++;
9169 if ((res = mov_create_chapter_track(s, mov->chapter_track)) < 0)
9170 return res;
9171 }
9172 }
9173
9174 if (!(mov->flags & FF_MOV_FLAG_FRAGMENT) ||
9178 mov->mdat_size = avio_tell(pb) - mov->mdat_pos - 8;
9179 for (i = 0; i < mov->nb_tracks; i++) {
9180 MOVTrack *track = &mov->tracks[i];
9181 track->data_offset = 0;
9182 av_free(track->cluster);
9183 track->cluster = track->cluster_written;
9184 track->entry = track->entry_written;
9185 track->cluster_written = NULL;
9186 track->entry_written = 0;
9187 track->chunkCount = 0; // Force build_chunks to rebuild the list of chunks
9188 }
9189 // Clear the empty_moov flag, as we do want the moov to include
9190 // all the samples at this point.
9192 }
9193
9194 moov_pos = avio_tell(pb);
9195
9198
9199 avio_seek(pb, mov->reserved_moov_size > 0 ? mov->reserved_header_pos : moov_pos, SEEK_SET);
9200
9201 if (mov->flags & FF_MOV_FLAG_FASTSTART) {
9202 av_log(s, AV_LOG_INFO, "Starting second pass: moving the moov atom to the beginning of the file\n");
9203 res = shift_data(s);
9204 if (res < 0)
9205 return res;
9206 avio_seek(pb, mov->reserved_header_pos, SEEK_SET);
9207 if ((res = mov_write_moov_tag(pb, mov, s)) < 0)
9208 return res;
9209 } else if (mov->reserved_moov_size > 0) {
9210 int64_t size;
9211 if ((res = mov_write_moov_tag(pb, mov, s)) < 0)
9212 return res;
9214 if (size < 8){
9215 av_log(s, AV_LOG_ERROR, "reserved_moov_size is too small, needed %"PRId64" additional\n", 8-size);
9216 return AVERROR(EINVAL);
9217 }
9218 avio_wb32(pb, size);
9219 ffio_wfourcc(pb, "free");
9220 ffio_fill(pb, 0, size - 8);
9221 avio_seek(pb, moov_pos, SEEK_SET);
9222 } else {
9223 if ((res = mov_write_moov_tag(pb, mov, s)) < 0)
9224 return res;
9225 }
9226
9228 // With hybrid fragmentation, only write the mdat size (hiding
9229 // the original moov and all the fragments within the mdat)
9230 // after we've successfully written the complete moov, to avoid
9231 // risk for an unreadable file if writing the final moov fails.
9233 }
9234
9235 res = 0;
9236 } else {
9238 for (i = 0; i < mov->nb_tracks; i++)
9239 mov->tracks[i].data_offset = 0;
9240 if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX) {
9241 int64_t end;
9242 av_log(s, AV_LOG_INFO, "Starting second pass: inserting sidx atoms\n");
9243 res = shift_data(s);
9244 if (res < 0)
9245 return res;
9246 end = avio_tell(pb);
9247 avio_seek(pb, mov->reserved_header_pos, SEEK_SET);
9248 mov_write_sidx_tags(pb, mov, -1, 0);
9249 avio_seek(pb, end, SEEK_SET);
9250 }
9251 if (!(mov->flags & FF_MOV_FLAG_SKIP_TRAILER)) {
9253 res = mov_write_mfra_tag(pb, mov);
9254 if (res < 0)
9255 return res;
9256 }
9257 }
9258
9259 return res;
9260}
9261
9263 const AVPacket *pkt)
9264{
9265 int ret = 1;
9266
9267 if (st->codecpar->codec_id == AV_CODEC_ID_AAC) {
9268 if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0)
9269 ret = ff_stream_add_bitstream_filter(st, "aac_adtstoasc", NULL);
9270 } else if (st->codecpar->codec_id == AV_CODEC_ID_VP9) {
9271 ret = ff_stream_add_bitstream_filter(st, "vp9_superframe", NULL);
9272 }
9273
9274 return ret;
9275}
9276
9277#if CONFIG_AVIF_MUXER
9278static int avif_write_trailer(AVFormatContext *s)
9279{
9280 AVIOContext *pb = s->pb;
9281 MOVMuxContext *mov = s->priv_data;
9282 int64_t pos_backup, extent_offsets[2];
9283 uint8_t *buf;
9284 int buf_size, moov_size;
9285
9286 if (mov->moov_written) return 0;
9287
9288 mov->is_animated_avif = s->streams[0]->nb_frames > 1;
9289 if (mov->is_animated_avif && mov->nb_streams > 1) {
9290 // For animated avif with alpha channel, we need to write a tref tag
9291 // with type "auxl".
9292 MovTag *tag = mov_add_tref_tag(mov, &mov->tracks[1], MKTAG('a', 'u', 'x', 'l'));
9293 if (!tag)
9294 return AVERROR(ENOMEM);
9295
9296 int ret = mov_add_tref_id(mov, tag, 1);
9297 if (ret < 0)
9298 return ret;
9299 }
9301 mov_write_meta_tag(pb, mov, s);
9302
9303 moov_size = get_moov_size(s);
9304 for (int i = 0; i < mov->nb_tracks; i++)
9305 mov->tracks[i].data_offset = avio_tell(pb) + moov_size + 8;
9306
9307 if (mov->is_animated_avif) {
9308 int ret;
9309 if ((ret = mov_write_moov_tag(pb, mov, s)) < 0)
9310 return ret;
9311 }
9312
9313 buf_size = avio_get_dyn_buf(mov->mdat_buf, &buf);
9314 avio_wb32(pb, buf_size + 8);
9315 ffio_wfourcc(pb, "mdat");
9316
9317 // The offset for the YUV planes is the starting position of mdat.
9318 extent_offsets[0] = avio_tell(pb);
9319 // The offset for alpha plane is YUV offset + YUV size.
9320 extent_offsets[1] = extent_offsets[0] + mov->avif_extent_length[0];
9321
9322 avio_write(pb, buf, buf_size);
9323
9324 // write extent offsets.
9325 pos_backup = avio_tell(pb);
9326 for (int i = 0; i < mov->nb_streams; i++) {
9327 if (extent_offsets[i] != (uint32_t)extent_offsets[i]) {
9328 av_log(s, AV_LOG_ERROR, "extent offset does not fit in 32 bits\n");
9329 return AVERROR_INVALIDDATA;
9330 }
9331 avio_seek(pb, mov->avif_extent_pos[i], SEEK_SET);
9332 avio_wb32(pb, extent_offsets[i]); /* rewrite offset */
9333 }
9334 avio_seek(pb, pos_backup, SEEK_SET);
9335
9336 return 0;
9337}
9338#endif
9339
9340#if CONFIG_TGP_MUXER || CONFIG_TG2_MUXER
9341static const AVCodecTag codec_3gp_tags[] = {
9342 { AV_CODEC_ID_H263, MKTAG('s','2','6','3') },
9343 { AV_CODEC_ID_H264, MKTAG('a','v','c','1') },
9344 { AV_CODEC_ID_MPEG4, MKTAG('m','p','4','v') },
9345 { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') },
9346 { AV_CODEC_ID_AMR_NB, MKTAG('s','a','m','r') },
9347 { AV_CODEC_ID_AMR_WB, MKTAG('s','a','w','b') },
9348 { AV_CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') },
9349 { AV_CODEC_ID_NONE, 0 },
9350};
9351static const AVCodecTag *const codec_3gp_tags_list[] = { codec_3gp_tags, NULL };
9352#endif
9353
9354static const AVCodecTag codec_mp4_tags[] = {
9355 { AV_CODEC_ID_MPEG4, MKTAG('m', 'p', '4', 'v') },
9356 { AV_CODEC_ID_H264, MKTAG('a', 'v', 'c', '1') },
9357 { AV_CODEC_ID_H264, MKTAG('a', 'v', 'c', '3') },
9358 { AV_CODEC_ID_HEVC, MKTAG('h', 'e', 'v', '1') },
9359 { AV_CODEC_ID_HEVC, MKTAG('h', 'v', 'c', '1') },
9360 { AV_CODEC_ID_HEVC, MKTAG('d', 'v', 'h', '1') },
9361 { AV_CODEC_ID_VVC, MKTAG('v', 'v', 'c', '1') },
9362 { AV_CODEC_ID_VVC, MKTAG('v', 'v', 'i', '1') },
9363 { AV_CODEC_ID_EVC, MKTAG('e', 'v', 'c', '1') },
9364 { AV_CODEC_ID_LCEVC, MKTAG('l', 'v', 'c', '1') },
9365 { AV_CODEC_ID_APV, MKTAG('a', 'p', 'v', '1') },
9366 { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'p', '4', 'v') },
9367 { AV_CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', '4', 'v') },
9368 { AV_CODEC_ID_MJPEG, MKTAG('m', 'p', '4', 'v') },
9369 { AV_CODEC_ID_PNG, MKTAG('m', 'p', '4', 'v') },
9370 { AV_CODEC_ID_JPEG2000, MKTAG('m', 'p', '4', 'v') },
9371 { AV_CODEC_ID_VC1, MKTAG('v', 'c', '-', '1') },
9372 { AV_CODEC_ID_DIRAC, MKTAG('d', 'r', 'a', 'c') },
9373 { AV_CODEC_ID_TSCC2, MKTAG('m', 'p', '4', 'v') },
9374 { AV_CODEC_ID_VP9, MKTAG('v', 'p', '0', '9') },
9375 { AV_CODEC_ID_AV1, MKTAG('a', 'v', '0', '1') },
9376 { AV_CODEC_ID_AV1, MKTAG('d', 'a', 'v', '1') },
9377 { AV_CODEC_ID_AAC, MKTAG('m', 'p', '4', 'a') },
9378 { AV_CODEC_ID_APPLE_APAC, MKTAG('a', 'p', 'a', 'c') },
9379 { AV_CODEC_ID_ALAC, MKTAG('a', 'l', 'a', 'c') },
9380 { AV_CODEC_ID_MP4ALS, MKTAG('m', 'p', '4', 'a') },
9381 { AV_CODEC_ID_MP3, MKTAG('m', 'p', '4', 'a') },
9382 { AV_CODEC_ID_MP2, MKTAG('m', 'p', '4', 'a') },
9383 { AV_CODEC_ID_AC3, MKTAG('a', 'c', '-', '3') },
9384 { AV_CODEC_ID_EAC3, MKTAG('e', 'c', '-', '3') },
9385 { AV_CODEC_ID_DTS, MKTAG('m', 'p', '4', 'a') },
9386 { AV_CODEC_ID_TRUEHD, MKTAG('m', 'l', 'p', 'a') },
9387 { AV_CODEC_ID_FLAC, MKTAG('f', 'L', 'a', 'C') },
9388 { AV_CODEC_ID_OPUS, MKTAG('O', 'p', 'u', 's') },
9389 { AV_CODEC_ID_VORBIS, MKTAG('m', 'p', '4', 'a') },
9390 { AV_CODEC_ID_QCELP, MKTAG('m', 'p', '4', 'a') },
9391 { AV_CODEC_ID_EVRC, MKTAG('m', 'p', '4', 'a') },
9392 { AV_CODEC_ID_DVD_SUBTITLE, MKTAG('m', 'p', '4', 's') },
9393 { AV_CODEC_ID_MOV_TEXT, MKTAG('t', 'x', '3', 'g') },
9394 { AV_CODEC_ID_BIN_DATA, MKTAG('g', 'p', 'm', 'd') },
9395 { AV_CODEC_ID_MPEGH_3D_AUDIO, MKTAG('m', 'h', 'm', '1') },
9398 { AV_CODEC_ID_FFV1, MKTAG('F', 'F', 'V', '1') },
9399
9400 /* ISO/IEC 23003-5 integer formats */
9407 /* ISO/IEC 23003-5 floating-point formats */
9412
9413 { AV_CODEC_ID_AVS3, MKTAG('a', 'v', 's', '3') },
9414
9415 { AV_CODEC_ID_NONE, 0 },
9416};
9417#if CONFIG_MP4_MUXER || CONFIG_PSP_MUXER
9418static const AVCodecTag *const mp4_codec_tags_list[] = { codec_mp4_tags, NULL };
9419#endif
9420
9421static const AVCodecTag codec_ism_tags[] = {
9422 { AV_CODEC_ID_WMAPRO , MKTAG('w', 'm', 'a', ' ') },
9424 { AV_CODEC_ID_NONE , 0 },
9425};
9426
9427static const AVCodecTag codec_ipod_tags[] = {
9428 { AV_CODEC_ID_H264, MKTAG('a','v','c','1') },
9429 { AV_CODEC_ID_MPEG4, MKTAG('m','p','4','v') },
9430 { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') },
9431 { AV_CODEC_ID_ALAC, MKTAG('a','l','a','c') },
9432 { AV_CODEC_ID_AC3, MKTAG('a','c','-','3') },
9433 { AV_CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') },
9434 { AV_CODEC_ID_MOV_TEXT, MKTAG('t','e','x','t') },
9435 { AV_CODEC_ID_NONE, 0 },
9436};
9437
9438static const AVCodecTag codec_f4v_tags[] = {
9439 { AV_CODEC_ID_MP3, MKTAG('.','m','p','3') },
9440 { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') },
9441 { AV_CODEC_ID_H264, MKTAG('a','v','c','1') },
9442 { AV_CODEC_ID_VP6A, MKTAG('V','P','6','A') },
9443 { AV_CODEC_ID_VP6F, MKTAG('V','P','6','F') },
9444 { AV_CODEC_ID_NONE, 0 },
9445};
9446
9447#if CONFIG_AVIF_MUXER
9448
9449static const AVOption avif_options[] = {
9450 { "movie_timescale", "set movie timescale", offsetof(MOVMuxContext, movie_timescale), AV_OPT_TYPE_INT, {.i64 = MOV_TIMESCALE}, 1, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
9451 { "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 },
9452 { NULL },
9453};
9454static const AVCodecTag codec_avif_tags[] = {
9455 { AV_CODEC_ID_AV1, MKTAG('a','v','0','1') },
9456 { AV_CODEC_ID_NONE, 0 },
9457};
9458static const AVCodecTag *const codec_avif_tags_list[] = { codec_avif_tags, NULL };
9459
9460static const AVClass mov_avif_muxer_class = {
9461 .class_name = "avif muxer",
9462 .item_name = av_default_item_name,
9463 .option = avif_options,
9464 .version = LIBAVUTIL_VERSION_INT,
9465};
9466#endif
9467
9468#if CONFIG_MOV_MUXER
9470 .p.name = "mov",
9471 .p.long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
9472 .p.extensions = "mov",
9473 .priv_data_size = sizeof(MOVMuxContext),
9474 .p.audio_codec = AV_CODEC_ID_AAC,
9475 .p.video_codec = CONFIG_LIBX264_ENCODER ?
9477 .init = mov_init,
9481 .deinit = mov_free,
9483 .p.codec_tag = (const AVCodecTag* const []){
9485 },
9486 .check_bitstream = mov_check_bitstream,
9487 .p.priv_class = &mov_isobmff_muxer_class,
9488 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
9489};
9490#endif
9491#if CONFIG_TGP_MUXER
9493 .p.name = "3gp",
9494 .p.long_name = NULL_IF_CONFIG_SMALL("3GP (3GPP file format)"),
9495 .p.extensions = "3gp",
9496 .priv_data_size = sizeof(MOVMuxContext),
9497 .p.audio_codec = AV_CODEC_ID_AMR_NB,
9498 .p.video_codec = AV_CODEC_ID_H263,
9499 .init = mov_init,
9500 .write_header = mov_write_header,
9501 .write_packet = mov_write_packet,
9502 .write_trailer = mov_write_trailer,
9503 .deinit = mov_free,
9505 .p.codec_tag = codec_3gp_tags_list,
9506 .check_bitstream = mov_check_bitstream,
9507 .p.priv_class = &mov_isobmff_muxer_class,
9508 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
9509};
9510#endif
9511#if CONFIG_MP4_MUXER
9513 .p.name = "mp4",
9514 .p.long_name = NULL_IF_CONFIG_SMALL("MP4 (MPEG-4 Part 14)"),
9515 .p.mime_type = "video/mp4",
9516 .p.extensions = "mp4",
9517 .priv_data_size = sizeof(MOVMuxContext),
9518 .p.audio_codec = AV_CODEC_ID_AAC,
9519 .p.video_codec = CONFIG_LIBX264_ENCODER ?
9521 .init = mov_init,
9525 .deinit = mov_free,
9527 .p.codec_tag = mp4_codec_tags_list,
9529 .p.priv_class = &mov_isobmff_muxer_class,
9530 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
9531};
9532#endif
9533#if CONFIG_PSP_MUXER
9535 .p.name = "psp",
9536 .p.long_name = NULL_IF_CONFIG_SMALL("PSP MP4 (MPEG-4 Part 14)"),
9537 .p.extensions = "mp4,psp",
9538 .priv_data_size = sizeof(MOVMuxContext),
9539 .p.audio_codec = AV_CODEC_ID_AAC,
9540 .p.video_codec = CONFIG_LIBX264_ENCODER ?
9542 .init = mov_init,
9546 .deinit = mov_free,
9548 .p.codec_tag = mp4_codec_tags_list,
9550 .p.priv_class = &mov_isobmff_muxer_class,
9551 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
9552};
9553#endif
9554#if CONFIG_TG2_MUXER
9556 .p.name = "3g2",
9557 .p.long_name = NULL_IF_CONFIG_SMALL("3GP2 (3GPP2 file format)"),
9558 .p.extensions = "3g2",
9559 .priv_data_size = sizeof(MOVMuxContext),
9560 .p.audio_codec = AV_CODEC_ID_AMR_NB,
9561 .p.video_codec = AV_CODEC_ID_H263,
9562 .init = mov_init,
9563 .write_header = mov_write_header,
9564 .write_packet = mov_write_packet,
9565 .write_trailer = mov_write_trailer,
9566 .deinit = mov_free,
9568 .p.codec_tag = codec_3gp_tags_list,
9569 .check_bitstream = mov_check_bitstream,
9570 .p.priv_class = &mov_isobmff_muxer_class,
9571 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
9572};
9573#endif
9574#if CONFIG_IPOD_MUXER
9576 .p.name = "ipod",
9577 .p.long_name = NULL_IF_CONFIG_SMALL("iPod H.264 MP4 (MPEG-4 Part 14)"),
9578 .p.mime_type = "video/mp4",
9579 .p.extensions = "m4v,m4a,m4b",
9580 .priv_data_size = sizeof(MOVMuxContext),
9581 .p.audio_codec = AV_CODEC_ID_AAC,
9582 .p.video_codec = AV_CODEC_ID_H264,
9583 .init = mov_init,
9584 .write_header = mov_write_header,
9585 .write_packet = mov_write_packet,
9586 .write_trailer = mov_write_trailer,
9587 .deinit = mov_free,
9589 .p.codec_tag = (const AVCodecTag* const []){ codec_ipod_tags, 0 },
9590 .check_bitstream = mov_check_bitstream,
9591 .p.priv_class = &mov_isobmff_muxer_class,
9592 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
9593};
9594#endif
9595#if CONFIG_ISMV_MUXER
9597 .p.name = "ismv",
9598 .p.long_name = NULL_IF_CONFIG_SMALL("ISMV/ISMA (Smooth Streaming)"),
9599 .p.mime_type = "video/mp4",
9600 .p.extensions = "ismv,isma",
9601 .priv_data_size = sizeof(MOVMuxContext),
9602 .p.audio_codec = AV_CODEC_ID_AAC,
9603 .p.video_codec = AV_CODEC_ID_H264,
9604 .init = mov_init,
9605 .write_header = mov_write_header,
9606 .write_packet = mov_write_packet,
9607 .write_trailer = mov_write_trailer,
9608 .deinit = mov_free,
9610 .p.codec_tag = (const AVCodecTag* const []){
9612 .check_bitstream = mov_check_bitstream,
9613 .p.priv_class = &mov_isobmff_muxer_class,
9614 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
9615};
9616#endif
9617#if CONFIG_F4V_MUXER
9619 .p.name = "f4v",
9620 .p.long_name = NULL_IF_CONFIG_SMALL("F4V Adobe Flash Video"),
9621 .p.mime_type = "application/f4v",
9622 .p.extensions = "f4v",
9623 .priv_data_size = sizeof(MOVMuxContext),
9624 .p.audio_codec = AV_CODEC_ID_AAC,
9625 .p.video_codec = AV_CODEC_ID_H264,
9626 .init = mov_init,
9627 .write_header = mov_write_header,
9628 .write_packet = mov_write_packet,
9629 .write_trailer = mov_write_trailer,
9630 .deinit = mov_free,
9631 .p.flags = AVFMT_GLOBALHEADER,
9632 .p.codec_tag = (const AVCodecTag* const []){ codec_f4v_tags, 0 },
9633 .check_bitstream = mov_check_bitstream,
9634 .p.priv_class = &mov_isobmff_muxer_class,
9635 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
9636};
9637#endif
9638#if CONFIG_AVIF_MUXER
9640 .p.name = "avif",
9641 .p.long_name = NULL_IF_CONFIG_SMALL("AVIF"),
9642 .p.mime_type = "image/avif",
9643 .p.extensions = "avif",
9644 .priv_data_size = sizeof(MOVMuxContext),
9645 .p.video_codec = AV_CODEC_ID_AV1,
9646 .init = mov_init,
9647 .write_header = mov_write_header,
9648 .write_packet = mov_write_packet,
9649 .write_trailer = avif_write_trailer,
9650 .deinit = mov_free,
9651 .p.flags = AVFMT_GLOBALHEADER,
9652 .p.codec_tag = codec_avif_tags_list,
9653 .p.priv_class = &mov_avif_muxer_class,
9654 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
9655};
9656#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:837
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 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:399
static unsigned int nb_streams
Definition ffprobe.c:353
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:140
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:56
AVDictionaryEntry * av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
Definition dict.c:60
#define AV_DICT_IGNORE_SUFFIX
Return first entry in a dictionary whose first part corresponds to the search key,...
Definition dict.h:75
const AVDictionaryEntry * av_dict_iterate(const AVDictionary *m, const AVDictionaryEntry *prev)
Iterate over a dictionary.
Definition dict.c:42
#define AVERROR_EXPERIMENTAL
Requested feature is flagged experimental. Set strict_std_compliance if you really want to use it.
Definition error.h:74
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition error.h:64
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition error.h:52
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition error.h:61
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition error.h:122
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition log.h:231
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition log.h:216
#define AV_LOG_VERBOSE
Detailed information.
Definition log.h:226
#define AV_LOG_INFO
Standard information.
Definition log.h:221
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
const char * av_default_item_name(void *ptr)
Return the context name.
Definition log.c:241
double av_csp_approximate_eotf_gamma(enum AVColorTransferCharacteristic trc)
Determine a suitable EOTF 'gamma' value to match the supplied AVColorTransferCharacteristic.
Definition csp.c:187
int av_reduce(int *dst_num, int *dst_den, int64_t num, int64_t den, int64_t max)
Reduce a fraction.
Definition rational.c:35
AVRational av_gcd_q(AVRational a, AVRational b, int max_den, AVRational def)
Return the best rational so that a and b are multiple of it.
Definition rational.c:188
static double av_q2d(AVRational a)
Convert an AVRational to a double.
Definition rational.h:104
static av_always_inline AVRational av_inv_q(AVRational q)
Invert a rational.
Definition rational.h:159
AVRational av_sub_q(AVRational b, AVRational c)
Subtract one rational from another.
Definition rational.c:101
int64_t av_rescale(int64_t a, int64_t b, int64_t c)
Rescale a 64-bit integer with rounding to nearest.
int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding rnd)
Rescale a 64-bit integer with specified rounding.
Definition mathematics.c:58
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
@ AV_ROUND_DOWN
Round toward -infinity.
@ AV_ROUND_UP
Round toward +infinity.
void * av_realloc_array(void *ptr, size_t nmemb, size_t size)
Definition mem.c:318
void * av_memdup(const void *p, size_t size)
Duplicate a buffer with av_malloc().
Definition mem.c:408
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:326
#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_GRAPHICS_MODE_COPY
Definition isom.h:443
#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:307
#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:493
#define MOV_FRAG_SAMPLE_FLAG_DEPENDS_NO
Definition isom.h:430
#define TAG_IS_AVCI(tag)
Definition isom.h:453
#define MOV_TRUN_FIRST_SAMPLE_FLAGS
Definition isom.h:417
#define MOV_GRAPHICS_MODE_PREMUL_BLACK_ALPHA
Definition isom.h:449
#define MOV_MP4_FPCM_TAG
Definition isom.h:495
#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:494
#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:496
#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_GRAPHICS_MODE_STRAIGHT_ALPHA
Definition isom.h:447
#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
void * av_calloc(size_t nmemb, size_t size)
Definition mem.c:370
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_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:4527
static int get_moov_size(AVFormatContext *s)
Definition movenc.c:9011
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:5986
static const AVCodecTag codec_cover_image_tags[]
Definition movenc.c:2200
static int mov_write_header(AVFormatContext *s)
Definition movenc.c:8831
static int mov_write_sdtp_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:316
static const AVCodecTag codec_ism_tags[]
Definition movenc.c:9421
static MovTag * mov_add_tref_tag(MOVMuxContext *mov, MOVTrack *trk, uint32_t name)
Definition movenc.c:5373
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:4696
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:6985
static int mov_write_iref_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
Definition movenc.c:3759
static uint16_t mov_graphics_mode(MOVTrack *track)
Definition movenc.c:3587
static int mov_write_uuid_tag_psp(AVIOContext *pb, MOVTrack *mov)
Definition movenc.c:4309
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:5031
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:4027
static int mov_write_traf_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track, int64_t moof_offset, int moof_size)
Definition movenc.c:5919
uint32_t tag
Definition movenc.c:2087
static int mov_write_emsg_tag(AVIOContext *pb, AVStream *st, AVPacket *pkt)
Definition movenc.c:7646
static int mov_flush_fragment_interleaving(AVFormatContext *s, MOVTrack *track)
Definition movenc.c:6605
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:3734
static int mov_write_mdhd_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
Definition movenc.c:3971
static int mov_create_chapter_track(AVFormatContext *s, int tracknum)
Definition movenc.c:7825
static int mov_mdhd_mvhd_tkhd_version(MOVMuxContext *mov, MOVTrack *track, int64_t duration)
Definition movenc.c:3962
static int mov_add_tfra_entries(AVIOContext *pb, MOVMuxContext *mov, int tracks, int size)
Definition movenc.c:5854
static int shift_data(AVFormatContext *s)
Definition movenc.c:9082
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:9427
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:9042
static int mov_write_loci_tag(AVFormatContext *s, AVIOContext *pb)
Definition movenc.c:4761
static int mov_write_tfra_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:6169
static int ascii_to_wc(AVIOContext *pb, const uint8_t *b)
Definition movenc.c:5051
static int mov_write_sidx_tags(AVIOContext *pb, MOVMuxContext *mov, int tracks, int ref_size)
Definition movenc.c:6047
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:5362
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:6242
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:3847
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:7925
static int mov_create_dvd_sub_decoder_specific_info(MOVTrack *track, AVStream *st)
Definition movenc.c:8103
static int mov_write_prft_tag(AVIOContext *pb, MOVMuxContext *mov, int tracks)
Definition movenc.c:6085
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:3806
static void mov_write_mdat_size(AVFormatContext *s)
Definition movenc.c:9097
static uint32_t get_sample_flags(MOVTrack *track, MOVIentry *entry)
Definition movenc.c:5657
static void enable_tracks(AVFormatContext *s)
Definition movenc.c:7986
static int mov_write_minf_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
Definition movenc.c:3872
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:5805
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:4866
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:6692
static int mov_write_mdta_keys_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
Definition movenc.c:4949
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:6586
static int mov_write_tkhd_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track, AVStream *st)
Definition movenc.c:4041
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:8087
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:6936
static int mov_write_moof_tag(AVIOContext *pb, MOVMuxContext *mov, int tracks, int64_t mdat_size)
Definition movenc.c:6135
static int mov_write_moof_tag_internal(AVIOContext *pb, MOVMuxContext *mov, int tracks, int moof_size)
Definition movenc.c:5961
static int mov_write_edts_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
Definition movenc.c:4184
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:4349
static void param_write_hex(AVIOContext *pb, const char *name, const uint8_t *value, int len)
Definition movenc.c:5516
static int mov_write_ilst_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
Definition movenc.c:4893
static void mov_prune_frag_info(MOVMuxContext *mov, int tracks, int max)
Definition movenc.c:5893
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:4743
static int mov_write_iloc_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
Definition movenc.c:3711
static int mov_write_int8_metadata(AVFormatContext *s, AVIOContext *pb, const char *name, const char *tag, int len)
Definition movenc.c:4839
static int mov_check_timecode_track(AVFormatContext *s, AVTimecode *tc, AVStream *src_st, const char *tcstr)
Definition movenc.c:7916
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:5062
static int mov_write_custom_metadata(AVFormatContext *s, AVIOContext *pb, const char *mean, const char *name, const char *tag)
Definition movenc.c:4732
static int mov_write_tref_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:4292
static void param_write_string(AVIOContext *pb, const char *name, const char *value)
Definition movenc.c:5511
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:3778
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:3823
static int64_t calc_elst_duration(MOVMuxContext *mov, MOVTrack *track)
Definition movenc.c:3955
static int mov_add_tref_id(MOVMuxContext *mov, MovTag *tag, uint32_t id)
Definition movenc.c:5347
static int mov_write_moov_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
Definition movenc.c:5390
static int64_t calc_pts_duration(MOVMuxContext *mov, MOVTrack *track)
Definition movenc.c:3946
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:5840
static int mov_write_chpl_tag(AVIOContext *pb, AVFormatContext *s)
Definition movenc.c:5091
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:4653
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:3616
static int mov_write_iods_tag(AVIOContext *pb, MOVMuxContext *mov)
Definition movenc.c:4498
static int mov_write_3gp_udta_tag(AVIOContext *pb, AVFormatContext *s, const char *tag, const char *str)
Definition movenc.c:5069
static int mov_find_tref_id(MOVMuxContext *mov, const MovTag *tag, uint32_t id)
Definition movenc.c:5338
static int mov_write_subtitle_end_packet(AVFormatContext *s, int stream_index, int64_t dts)
Definition movenc.c:7577
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:5226
static int mov_init(AVFormatContext *s)
Definition movenc.c:8232
static void param_write_int(AVIOContext *pb, const char *name, int value)
Definition movenc.c:5506
static int mov_write_string_metadata(AVFormatContext *s, AVIOContext *pb, const char *name, const char *tag, int long_style)
Definition movenc.c:4721
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:4934
static int mov_write_mvhd_tag(AVIOContext *pb, MOVMuxContext *mov)
Definition movenc.c:4551
static int mov_write_track_kind(AVIOContext *pb, const char *scheme_uri, const char *value)
Definition movenc.c:4363
static void mov_write_psp_udta_tag(AVIOContext *pb, const char *str, const char *lang, int type)
Definition movenc.c:5175
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:5648
static int mov_write_tfhd_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track, int64_t moof_offset)
Definition movenc.c:5663
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:6193
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:6231
static int mov_write_chnl_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
Definition movenc.c:1331
static int mov_write_vmhd_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:3599
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:6950
static int mov_write_uuidprof_tag(AVIOContext *pb, AVFormatContext *s)
Definition movenc.c:6405
static int mov_write_pitm_tag(AVIOContext *pb, int item_id)
Definition movenc.c:3701
static int mov_write_identification(AVIOContext *pb, AVFormatContext *s)
Definition movenc.c:6476
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:4812
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:4327
static int mov_write_mdia_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
Definition movenc.c:4008
static const AVCodecTag codec_f4v_tags[]
Definition movenc.c:9438
static int is_clcp_track(MOVTrack *track)
Definition movenc.c:3610
static int mov_write_trak_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track, AVStream *st)
Definition movenc.c:4442
static int compute_sidx_size(AVFormatContext *s)
Definition movenc.c:9067
static int mov_write_itunes_hdlr_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
Definition movenc.c:4616
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:4389
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:6283
static int get_sidx_size(AVFormatContext *s)
Definition movenc.c:9024
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:5117
static int mov_pcm_be_gt16(enum AVCodecID codec_id)
Definition movenc.c:858
static int mov_write_trailer(AVFormatContext *s)
Definition movenc.c:9119
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:3790
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:6630
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:4149
static int defined_frame_rate(AVFormatContext *s, AVStream *st)
Definition movenc.c:1931
static void mov_free(AVFormatContext *s)
Definition movenc.c:8028
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:7027
static int mov_write_tfdt_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:5907
static int mov_setup_track_ids(MOVMuxContext *mov, AVFormatContext *s)
Assign track ids.
Definition movenc.c:5299
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:4632
static void mov_parse_vc1_frame(AVPacket *pkt, MOVTrack *trk)
Definition movenc.c:6526
static int mov_write_tfxd_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:5785
static int mov_flush_fragment(AVFormatContext *s, int force)
Definition movenc.c:6724
static int mov_write_single_packet(AVFormatContext *s, AVPacket *pkt)
Definition movenc.c:7486
static int mov_write_squashed_packets(AVFormatContext *s)
Definition movenc.c:6668
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:5263
static void get_pts_range(MOVMuxContext *mov, MOVTrack *track, int64_t *start, int64_t *end, int elst, int mdhd)
Definition movenc.c:3909
static int mov_write_mvex_tag(AVIOContext *pb, MOVMuxContext *mov)
Definition movenc.c:4540
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:9262
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:3934
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:4978
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:4409
static int mov_parse_mpeg2_frame(AVPacket *pkt, uint32_t *flags)
Definition movenc.c:6505
static int mov_write_freeform_tag(AVIOContext *pb, const char *mean, const char *name, const char *data)
Definition movenc.c:4667
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:7674
static int mov_write_meta_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
Definition movenc.c:5000
static int mov_write_mdcv_tag(AVIOContext *pb, MOVTrack *track)
Definition movenc.c:2712
static const AVCodecTag codec_mp4_tags[]
Definition movenc.c:9354
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:5188
static int mov_write_isml_manifest(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
Definition movenc.c:5524
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:5729
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:3857
#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
@ AVALPHA_MODE_STRAIGHT
Alpha channel is independent of color values.
Definition pixfmt.h:819
@ AVALPHA_MODE_PREMULTIPLIED
Alpha channel is multiplied into color values.
Definition pixfmt.h:818
#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
enum AVAlphaMode alpha_mode
Video with alpha channel only.
Definition codec_par.h:261
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:500
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