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