FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/movenc.c
Date: 2026-10-30 23:38:52
Exec Total Coverage
Lines: 4215 5903 71.4%
Functions: 201 243 82.7%
Branches: 2497 4075 61.3%

Line Branch Exec Source
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"
43 #include "libavcodec/ac3_parser_internal.h"
44 #include "libavcodec/dnxhddata.h"
45 #include "libavcodec/flac.h"
46 #include "libavcodec/mpegaudiodata.h"
47 #include "libavcodec/get_bits.h"
48
49 #include "libavcodec/internal.h"
50 #include "libavcodec/put_bits.h"
51 #include "libavcodec/vc1_common.h"
52 #include "libavcodec/raw.h"
53 #include "internal.h"
54 #include "libavutil/avstring.h"
55 #include "libavutil/channel_layout.h"
56 #include "libavutil/csp.h"
57 #include "libavutil/intfloat.h"
58 #include "libavutil/mathematics.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
79 static 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},
121 FF_RTP_FLAG_OPTS(MOVMuxContext, rtp_flags),
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
134 static const AVClass mov_isobmff_muxer_class = {
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
141 static int get_moov_size(AVFormatContext *s);
142 static int mov_write_single_packet(AVFormatContext *s, AVPacket *pkt);
143
144 33 static int utf8len(const uint8_t *b)
145 {
146 33 int len = 0;
147 int val;
148
2/2
✓ Branch 0 taken 613 times.
✓ Branch 1 taken 33 times.
646 while (*b) {
149
3/8
✓ Branch 0 taken 613 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 613 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 613 times.
613 GET_UTF8(val, *b++, return -1;)
150 613 len++;
151 }
152 33 return len;
153 }
154
155 //FIXME support 64 bit variant with wide placeholders
156 12138 static int64_t update_size(AVIOContext *pb, int64_t pos)
157 {
158 12138 int64_t curpos = avio_tell(pb);
159 12138 avio_seek(pb, pos, SEEK_SET);
160 12138 avio_wb32(pb, curpos - pos); /* rewrite size */
161 12138 avio_seek(pb, curpos, SEEK_SET);
162
163 12138 return curpos - pos;
164 }
165
166 598 static int64_t update_size_and_version(AVIOContext *pb, int64_t pos, int version)
167 {
168 598 int64_t curpos = avio_tell(pb);
169 598 avio_seek(pb, pos, SEEK_SET);
170 598 avio_wb32(pb, curpos - pos); /* rewrite size */
171 598 avio_skip(pb, 4);
172 598 avio_w8(pb, version); /* rewrite version */
173 598 avio_seek(pb, curpos, SEEK_SET);
174
175 598 return curpos - pos;
176 }
177
178 598 static int co64_required(const MOVTrack *track)
179 {
180
3/4
✓ Branch 0 taken 286 times.
✓ Branch 1 taken 312 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 286 times.
598 if (track->entry > 0 && track->cluster[track->entry - 1].pos + track->data_offset > UINT32_MAX)
181 ✗ return 1;
182 598 return 0;
183 }
184
185 29019 static 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
3/4
✓ Branch 0 taken 29019 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 29007 times.
29019 return st && st->disposition == AV_DISPOSITION_ATTACHED_PIC;
190 }
191
192 6 static int rtp_hinting_needed(const AVStream *st)
193 {
194 /* Add hint tracks for each real audio and video stream */
195
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if (is_cover_image(st))
196 ✗ return 0;
197
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
9 return st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ||
198
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO;
199 }
200
201 /* Chunk offset atom */
202 598 static int mov_write_stco_tag(AVIOContext *pb, MOVTrack *track)
203 {
204 int i;
205 598 int mode64 = co64_required(track); // use 32 bit size variant if possible
206 598 int64_t pos = avio_tell(pb);
207 598 avio_wb32(pb, 0); /* size */
208
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 if (mode64)
209 ✗ ffio_wfourcc(pb, "co64");
210 else
211 598 ffio_wfourcc(pb, "stco");
212 598 avio_wb32(pb, 0); /* version & flags */
213 598 avio_wb32(pb, track->chunkCount); /* entry count */
214
2/2
✓ Branch 0 taken 18455 times.
✓ Branch 1 taken 598 times.
19053 for (i = 0; i < track->entry; i++) {
215
2/2
✓ Branch 0 taken 15298 times.
✓ Branch 1 taken 3157 times.
18455 if (!track->cluster[i].chunkNum)
216 15298 continue;
217
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3157 times.
3157 if (mode64 == 1)
218 ✗ avio_wb64(pb, track->cluster[i].pos + track->data_offset);
219 else
220 3157 avio_wb32(pb, track->cluster[i].pos + track->data_offset);
221 }
222 598 return update_size(pb, pos);
223 }
224
225 /* Sample size atom */
226 598 static int mov_write_stsz_tag(AVIOContext *pb, MOVTrack *track)
227 {
228 598 int equalChunks = 1;
229 598 int i, j, entries = 0, tst = -1, oldtst = -1;
230
231 598 int64_t pos = avio_tell(pb);
232 598 avio_wb32(pb, 0); /* size */
233 598 ffio_wfourcc(pb, "stsz");
234 598 avio_wb32(pb, 0); /* version & flags */
235
236
2/2
✓ Branch 0 taken 18455 times.
✓ Branch 1 taken 598 times.
19053 for (i = 0; i < track->entry; i++) {
237 18455 tst = track->cluster[i].size / track->cluster[i].entries;
238
4/4
✓ Branch 0 taken 18169 times.
✓ Branch 1 taken 286 times.
✓ Branch 2 taken 12932 times.
✓ Branch 3 taken 5237 times.
18455 if (oldtst != -1 && tst != oldtst)
239 12932 equalChunks = 0;
240 18455 oldtst = tst;
241 18455 entries += track->cluster[i].entries;
242 }
243
4/4
✓ Branch 0 taken 433 times.
✓ Branch 1 taken 165 times.
✓ Branch 2 taken 121 times.
✓ Branch 3 taken 312 times.
719 if (equalChunks && track->entry) {
244
1/2
✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
121 int sSize = track->entry ? track->cluster[0].size / track->cluster[0].entries : 0;
245 121 sSize = FFMAX(1, sSize); // adpcm mono case could make sSize == 0
246 121 avio_wb32(pb, sSize); // sample size
247 121 avio_wb32(pb, entries); // sample count
248 } else {
249 477 avio_wb32(pb, 0); // sample size
250 477 avio_wb32(pb, entries); // sample count
251
2/2
✓ Branch 0 taken 14389 times.
✓ Branch 1 taken 477 times.
14866 for (i = 0; i < track->entry; i++) {
252
2/2
✓ Branch 0 taken 14389 times.
✓ Branch 1 taken 14389 times.
28778 for (j = 0; j < track->cluster[i].entries; j++) {
253 14389 avio_wb32(pb, track->cluster[i].size /
254 14389 track->cluster[i].entries);
255 }
256 }
257 }
258 598 return update_size(pb, pos);
259 }
260
261 /* Sample to chunk atom */
262 598 static int mov_write_stsc_tag(AVIOContext *pb, MOVTrack *track)
263 {
264 598 int index = 0, oldidx = -1, oldval = -1, i;
265 int64_t entryPos, curpos;
266
267 598 int64_t pos = avio_tell(pb);
268 598 avio_wb32(pb, 0); /* size */
269 598 ffio_wfourcc(pb, "stsc");
270 598 avio_wb32(pb, 0); // version & flags
271 598 entryPos = avio_tell(pb);
272 598 avio_wb32(pb, track->chunkCount); // entry count
273
2/2
✓ Branch 0 taken 18455 times.
✓ Branch 1 taken 598 times.
19053 for (i = 0; i < track->entry; i++) {
274
2/2
✓ Branch 0 taken 2307 times.
✓ Branch 1 taken 16148 times.
18455 if ((oldval != track->cluster[i].samples_in_chunk ||
275
4/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2305 times.
✓ Branch 2 taken 852 times.
✓ Branch 3 taken 15298 times.
18455 oldidx != track->cluster[i].stsd_index) && track->cluster[i].chunkNum) {
276 852 avio_wb32(pb, track->cluster[i].chunkNum); // first chunk
277 852 avio_wb32(pb, track->cluster[i].samples_in_chunk); // samples per chunk
278 852 avio_wb32(pb, track->cluster[i].stsd_index + 1); // sample description index
279 852 oldval = track->cluster[i].samples_in_chunk;
280 852 oldidx = track->cluster[i].stsd_index;
281 852 index++;
282 }
283 }
284 598 curpos = avio_tell(pb);
285 598 avio_seek(pb, entryPos, SEEK_SET);
286 598 avio_wb32(pb, index); // rewrite size
287 598 avio_seek(pb, curpos, SEEK_SET);
288
289 598 return update_size(pb, pos);
290 }
291
292 /* Sync sample atom */
293 73 static int mov_write_stss_tag(AVIOContext *pb, MOVTrack *track, uint32_t flag)
294 {
295 int64_t curpos, entryPos;
296 73 int i, index = 0;
297 73 int64_t pos = avio_tell(pb);
298 73 avio_wb32(pb, 0); // size
299
1/2
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
73 ffio_wfourcc(pb, flag == MOV_SYNC_SAMPLE ? "stss" : "stps");
300 73 avio_wb32(pb, 0); // version & flags
301 73 entryPos = avio_tell(pb);
302 73 avio_wb32(pb, track->entry); // entry count
303
2/2
✓ Branch 0 taken 3572 times.
✓ Branch 1 taken 73 times.
3645 for (i = 0; i < track->entry; i++) {
304
2/2
✓ Branch 0 taken 230 times.
✓ Branch 1 taken 3342 times.
3572 if (track->cluster[i].flags & flag) {
305 230 avio_wb32(pb, i + 1);
306 230 index++;
307 }
308 }
309 73 curpos = avio_tell(pb);
310 73 avio_seek(pb, entryPos, SEEK_SET);
311 73 avio_wb32(pb, index); // rewrite size
312 73 avio_seek(pb, curpos, SEEK_SET);
313 73 return update_size(pb, pos);
314 }
315
316 /* Sample dependency atom */
317 3 static int mov_write_sdtp_tag(AVIOContext *pb, MOVTrack *track)
318 {
319 int i;
320 uint8_t leading, dependent, reference, redundancy;
321 3 int64_t pos = avio_tell(pb);
322 3 avio_wb32(pb, 0); // size
323 3 ffio_wfourcc(pb, "sdtp");
324 3 avio_wb32(pb, 0); // version & flags
325
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 3 times.
16 for (i = 0; i < track->entry; i++) {
326 13 dependent = MOV_SAMPLE_DEPENDENCY_YES;
327 13 leading = reference = redundancy = MOV_SAMPLE_DEPENDENCY_UNKNOWN;
328
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 6 times.
13 if (track->cluster[i].flags & MOV_DISPOSABLE_SAMPLE) {
329 7 reference = MOV_SAMPLE_DEPENDENCY_NO;
330 }
331
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 10 times.
13 if (track->cluster[i].flags & MOV_SYNC_SAMPLE) {
332 3 dependent = MOV_SAMPLE_DEPENDENCY_NO;
333 }
334 13 avio_w8(pb, (leading << 6) | (dependent << 4) |
335 13 (reference << 2) | redundancy);
336 }
337 3 return update_size(pb, pos);
338 }
339
340 #if CONFIG_IAMFENC
341 6 static int mov_write_iacb_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
342 {
343 AVIOContext *dyn_bc;
344 6 int64_t pos = avio_tell(pb);
345 6 uint8_t *dyn_buf = NULL;
346 int dyn_size;
347 6 int ret = avio_open_dyn_buf(&dyn_bc);
348
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (ret < 0)
349 ✗ return ret;
350
351 6 avio_wb32(pb, 0);
352 6 ffio_wfourcc(pb, "iacb");
353 6 avio_w8(pb, 1); // configurationVersion
354
355 6 ret = ff_iamf_write_descriptors(track->iamf, dyn_bc, s);
356
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (ret < 0) {
357 ✗ ffio_free_dyn_buf(&dyn_bc);
358 ✗ return ret;
359 }
360
361 6 dyn_size = avio_close_dyn_buf(dyn_bc, &dyn_buf);
362 6 ffio_write_leb(pb, dyn_size);
363 6 avio_write(pb, dyn_buf, dyn_size);
364 6 av_free(dyn_buf);
365
366 6 return update_size(pb, pos);
367 }
368 #endif
369
370 ✗ static int mov_write_amr_tag(AVIOContext *pb, MOVTrack *track)
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
384 struct eac3_info {
385 AVPacket *pkt;
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;
393 int8_t ac3_bit_rate_code;
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 */
417 uint8_t complexity_index_type_a;
418 };
419
420 7 static int mov_write_ac3_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
421 {
422 7 struct eac3_info *info = track->eac3_priv;
423 PutBitContext pbc;
424 uint8_t buf[3];
425
426
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
7 if (!info || !info->ec3_done) {
427 ✗ av_log(s, AV_LOG_ERROR,
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
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (info->substream[0].bsid > 8) {
434 ✗ av_log(s, AV_LOG_ERROR,
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
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (info->ac3_bit_rate_code < 0) {
442 ✗ av_log(s, AV_LOG_ERROR,
443 "No valid AC3 bit rate code for data rate of %d!\n",
444 ✗ info->data_rate);
445 ✗ return AVERROR(EINVAL);
446 }
447
448 7 avio_wb32(pb, 11);
449 7 ffio_wfourcc(pb, "dac3");
450
451 7 init_put_bits(&pbc, buf, sizeof(buf));
452 7 put_bits(&pbc, 2, info->substream[0].fscod);
453 7 put_bits(&pbc, 5, info->substream[0].bsid);
454 7 put_bits(&pbc, 3, info->substream[0].bsmod);
455 7 put_bits(&pbc, 3, info->substream[0].acmod);
456 7 put_bits(&pbc, 1, info->substream[0].lfeon);
457 7 put_bits(&pbc, 5, info->ac3_bit_rate_code); // bit_rate_code
458 7 put_bits(&pbc, 5, 0); // reserved
459
460 7 flush_put_bits(&pbc);
461 7 avio_write(pb, buf, sizeof(buf));
462
463 7 return 11;
464 }
465
466 1737 static int handle_eac3(MOVMuxContext *mov, AVPacket *pkt, MOVTrack *track)
467 {
468 1737 AC3HeaderInfo *hdr = NULL;
469 struct eac3_info *info;
470 int num_blocks, ret;
471
472
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 1727 times.
1737 if (!track->eac3_priv) {
473
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
10 if (!(track->eac3_priv = av_mallocz(sizeof(*info))))
474 ✗ return AVERROR(ENOMEM);
475
476 10 ((struct eac3_info *)track->eac3_priv)->ac3_bit_rate_code = -1;
477 }
478 1737 info = track->eac3_priv;
479
480
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 1727 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10 times.
1737 if (!info->pkt && !(info->pkt = av_packet_alloc()))
481 ✗ return AVERROR(ENOMEM);
482
483
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1737 times.
1737 if (info->eof) {
484 av_assert1(!info->pkt->size);
485 ✗ ret = pkt->size;
486 ✗ goto end;
487 }
488
489
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1736 times.
1737 if ((ret = avpriv_ac3_parse_header(&hdr, pkt->data, pkt->size)) < 0) {
490
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret == AVERROR(ENOMEM))
491 ✗ goto end;
492
493 /* drop the packets until we see a good one */
494
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (!track->entry) {
495 1 av_log(mov->fc, AV_LOG_WARNING, "Dropping invalid packet from start of the stream\n");
496 1 ret = 0;
497 } else
498 ✗ ret = AVERROR_INVALIDDATA;
499 1 goto end;
500 }
501
502 1736 info->data_rate = FFMAX(info->data_rate, hdr->bit_rate / 1000);
503 1736 info->ac3_bit_rate_code = FFMAX(info->ac3_bit_rate_code,
504 hdr->ac3_bit_rate_code);
505 1736 info->complexity_index_type_a = hdr->complexity_index_type_a;
506
507 1736 num_blocks = hdr->num_blocks;
508
509
2/2
✓ Branch 0 taken 1722 times.
✓ Branch 1 taken 14 times.
1736 if (!info->ec3_done) {
510 /* AC-3 substream must be the first one */
511
3/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
14 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 */
518
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 6 times.
14 if (hdr->frame_type == EAC3_FRAME_TYPE_INDEPENDENT ||
519
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 hdr->frame_type == EAC3_FRAME_TYPE_AC3_CONVERT) {
520 /* substream ids must be incremental */
521
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (hdr->substreamid > info->num_ind_sub + 1) {
522 ✗ ret = AVERROR(EINVAL);
523 ✗ goto end;
524 }
525
526
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (hdr->substreamid == info->num_ind_sub + 1) {
527 //info->num_ind_sub++;
528 ✗ avpriv_request_sample(mov->fc, "Multiple independent substreams");
529 ✗ ret = AVERROR_PATCHWELCOME;
530 ✗ goto end;
531
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 } else if (hdr->substreamid < info->num_ind_sub ||
532
3/4
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 10 times.
14 hdr->substreamid == 0 && info->substream[0].bsid) {
533 4 info->ec3_done = 1;
534 4 goto concatenate;
535 }
536 } else {
537 ✗ if (hdr->substreamid != 0) {
538 ✗ avpriv_request_sample(mov->fc, "Multiple non EAC3 independent substreams");
539 ✗ ret = AVERROR_PATCHWELCOME;
540 ✗ goto end;
541 }
542 }
543
544 /* fill the info needed for the "dec3" atom */
545 10 info->substream[hdr->substreamid].fscod = hdr->sr_code;
546 10 info->substream[hdr->substreamid].bsid = hdr->bitstream_id;
547 10 info->substream[hdr->substreamid].bsmod = hdr->bitstream_mode;
548 10 info->substream[hdr->substreamid].acmod = hdr->channel_mode;
549 10 info->substream[hdr->substreamid].lfeon = hdr->lfe_on;
550
551
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 4 times.
10 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 6 info->ec3_done = 1;
556 6 goto concatenate;
557 }
558
559 /* Parse dependent substream(s), if any */
560
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 if (pkt->size != hdr->frame_size) {
561 1 int cumul_size = hdr->frame_size;
562 1 int parent = hdr->substreamid;
563
564
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 while (cumul_size != pkt->size) {
565 1 ret = avpriv_ac3_parse_header(&hdr, pkt->data + cumul_size, pkt->size - cumul_size);
566
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
567 ✗ goto end;
568
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (hdr->frame_type != EAC3_FRAME_TYPE_DEPENDENT) {
569 ✗ ret = AVERROR(EINVAL);
570 ✗ goto end;
571 }
572 1 info->substream[parent].num_dep_sub++;
573 1 ret /= 8;
574
575 /* get the dependent stream channel map, if exists */
576
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 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
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
9 for (int j = 0; j < 8; j++) {
586
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
8 if ((hdr->channel_map >> (10 - j)) & 1)
587 1 info->substream[parent].chan_loc |= 1 << j;
588 }
589
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 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 1 cumul_size += hdr->frame_size;
595 }
596 }
597 }
598
599 1726 concatenate:
600
2/4
✓ Branch 0 taken 1736 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1736 times.
✗ Branch 3 not taken.
1736 if (!info->num_blocks && num_blocks == 6) {
601 1736 ret = pkt->size;
602 1736 goto end;
603 }
604 ✗ else if (info->num_blocks + num_blocks > 6) {
605 ✗ ret = AVERROR_INVALIDDATA;
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;
633 ✗ av_packet_unref(pkt);
634 ✗ av_packet_move_ref(pkt, info->pkt);
635 ✗ info->num_blocks = 0;
636 }
637 ✗ ret = pkt->size;
638
639 1737 end:
640 1737 av_free(hdr);
641
642 1737 return ret;
643 }
644
645 4 static int mov_write_eac3_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
646 {
647 PutBitContext pbc;
648 uint8_t *buf;
649 struct eac3_info *info;
650 int size, i;
651
652
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!track->eac3_priv) {
653 ✗ av_log(s, AV_LOG_ERROR,
654 "Cannot write moov atom before EAC3 packets parsed.\n");
655 ✗ return AVERROR(EINVAL);
656 }
657
658 4 info = track->eac3_priv;
659
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 size = 2 + (4 * (info->num_ind_sub + 1)) + (2 * !!info->complexity_index_type_a);
660 4 buf = av_malloc(size);
661
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!buf) {
662 ✗ return AVERROR(ENOMEM);
663 }
664
665 4 init_put_bits(&pbc, buf, size);
666 4 put_bits(&pbc, 13, info->data_rate);
667 4 put_bits(&pbc, 3, info->num_ind_sub);
668
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 for (i = 0; i <= info->num_ind_sub; i++) {
669 4 put_bits(&pbc, 2, info->substream[i].fscod);
670 4 put_bits(&pbc, 5, info->substream[i].bsid);
671 4 put_bits(&pbc, 1, 0); /* reserved */
672 4 put_bits(&pbc, 1, 0); /* asvc */
673 4 put_bits(&pbc, 3, info->substream[i].bsmod);
674 4 put_bits(&pbc, 3, info->substream[i].acmod);
675 4 put_bits(&pbc, 1, info->substream[i].lfeon);
676 4 put_bits(&pbc, 3, 0); /* reserved */
677 4 put_bits(&pbc, 4, info->substream[i].num_dep_sub);
678
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 if (!info->substream[i].num_dep_sub) {
679 3 put_bits(&pbc, 1, 0); /* reserved */
680 } else {
681 1 put_bits(&pbc, 9, info->substream[i].chan_loc);
682 }
683 }
684
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 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 4 flush_put_bits(&pbc);
690 4 size = put_bytes_output(&pbc);
691
692 4 avio_wb32(pb, size + 8);
693 4 ffio_wfourcc(pb, "dec3");
694 4 avio_write(pb, buf, size);
695
696 4 av_free(buf);
697
698 4 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 */
705 12 static int mov_write_extradata_tag(AVIOContext *pb, MOVTrack *track)
706 {
707 12 avio_write(pb, track->extradata[track->last_stsd_index], track->extradata_size[track->last_stsd_index]);
708 12 return track->extradata_size[track->last_stsd_index];
709 }
710
711 ✗ static int mov_write_enda_tag(AVIOContext *pb)
712 {
713 ✗ avio_wb32(pb, 10);
714 ✗ ffio_wfourcc(pb, "enda");
715 ✗ avio_wb16(pb, 1); /* little endian */
716 ✗ return 10;
717 }
718
719 2 static int mov_write_enda_tag_be(AVIOContext *pb)
720 {
721 2 avio_wb32(pb, 10);
722 2 ffio_wfourcc(pb, "enda");
723 2 avio_wb16(pb, 0); /* big endian */
724 2 return 10;
725 }
726
727 1025 static void put_descr(AVIOContext *pb, int tag, unsigned int size)
728 {
729 1025 int i = 3;
730 1025 avio_w8(pb, tag);
731
2/2
✓ Branch 0 taken 3075 times.
✓ Branch 1 taken 1025 times.
4100 for (; i > 0; i--)
732 3075 avio_w8(pb, (size >> (7 * i)) | 0x80);
733 1025 avio_w8(pb, size & 0x7F);
734 1025 }
735
736 690 static unsigned compute_avg_bitrate(MOVTrack *track)
737 {
738 690 uint64_t size = 0;
739 int i;
740
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 636 times.
690 if (!track->track_duration)
741 54 return 0;
742
2/2
✓ Branch 0 taken 17182 times.
✓ Branch 1 taken 636 times.
17818 for (i = 0; i < track->entry; i++)
743 17182 size += track->cluster[i].size;
744 636 return size * 8 * track->timescale / track->track_duration;
745 }
746
747 struct mpeg4_bit_rate_values {
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
753 690 static struct mpeg4_bit_rate_values calculate_mpeg4_bit_rates(MOVTrack *track)
754 {
755 1380 const AVPacketSideData *sd = track->st ?
756 689 av_packet_side_data_get(track->st->codecpar->coded_side_data,
757 689 track->st->codecpar->nb_coded_side_data,
758
2/2
✓ Branch 0 taken 689 times.
✓ Branch 1 taken 1 times.
690 AV_PKT_DATA_CPB_PROPERTIES) : NULL;
759
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 638 times.
690 AVCPBProperties *props = sd ? (AVCPBProperties *)sd->data : NULL;
760 690 struct mpeg4_bit_rate_values bit_rates = { 0 };
761
762 690 bit_rates.avg_bit_rate = compute_avg_bitrate(track);
763
2/2
✓ Branch 0 taken 556 times.
✓ Branch 1 taken 134 times.
690 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
3/4
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 538 times.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
556 if (props && props->avg_bitrate) {
773 18 bit_rates.avg_bit_rate = props->avg_bitrate;
774
2/2
✓ Branch 0 taken 409 times.
✓ Branch 1 taken 129 times.
538 } else if (track->par->bit_rate) {
775 409 bit_rates.avg_bit_rate = track->par->bit_rate;
776
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 129 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
129 } 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 690 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
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 638 times.
690 if (props) {
787 // no avg_bitrate signals that the track is VBR
788
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 if (!props->avg_bitrate)
789 ✗ bit_rates.avg_bit_rate = props->avg_bitrate;
790 52 bit_rates.max_bit_rate = FFMAX(bit_rates.max_bit_rate,
791 props->max_bitrate);
792 52 bit_rates.buffer_size = props->buffer_size / 8;
793 }
794
795 690 return bit_rates;
796 }
797
798 308 static int mov_write_esds_tag(AVIOContext *pb, MOVTrack *track) // Basic
799 {
800 308 struct mpeg4_bit_rate_values bit_rates = calculate_mpeg4_bit_rates(track);
801 308 int64_t pos = avio_tell(pb);
802 616 int decoder_specific_info_len = track->extradata_size[track->last_stsd_index] ?
803
2/2
✓ Branch 0 taken 101 times.
✓ Branch 1 taken 207 times.
308 5 + track->extradata_size[track->last_stsd_index] : 0;
804
805 308 avio_wb32(pb, 0); // size
806 308 ffio_wfourcc(pb, "esds");
807 308 avio_wb32(pb, 0); // Version
808
809 // ES descriptor
810 308 put_descr(pb, 0x03, 3 + 5+13 + decoder_specific_info_len + 5+1);
811 308 avio_wb16(pb, track->track_id);
812 308 avio_w8(pb, 0x00); // flags (= no flags)
813
814 // DecoderConfig descriptor
815 308 put_descr(pb, 0x04, 13 + decoder_specific_info_len);
816
817 // Object type indication
818
2/2
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 200 times.
308 if ((track->par->codec_id == AV_CODEC_ID_MP2 ||
819
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 107 times.
108 track->par->codec_id == AV_CODEC_ID_MP3) &&
820
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 200 times.
201 track->par->sample_rate > 24000)
821 1 avio_w8(pb, 0x6B); // 11172-3
822 else
823 307 avio_w8(pb, ff_codec_get_tag(ff_mp4_obj_type, track->par->codec_id));
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)
827
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 308 times.
308 if (track->par->codec_id == AV_CODEC_ID_DVD_SUBTITLE)
828 ✗ avio_w8(pb, (0x38 << 2) | 1); // flags (= NeroSubpicStream)
829
2/2
✓ Branch 0 taken 271 times.
✓ Branch 1 taken 37 times.
308 else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO)
830 271 avio_w8(pb, 0x15); // flags (= Audiostream)
831 else
832 37 avio_w8(pb, 0x11); // flags (= Visualstream)
833
834 308 avio_wb24(pb, bit_rates.buffer_size); // Buffersize DB
835 308 avio_wb32(pb, bit_rates.max_bit_rate); // maxbitrate
836 308 avio_wb32(pb, bit_rates.avg_bit_rate);
837
838
2/2
✓ Branch 0 taken 101 times.
✓ Branch 1 taken 207 times.
308 if (track->extradata_size[track->last_stsd_index]) {
839 // DecoderSpecific info descriptor
840 101 put_descr(pb, 0x05, track->extradata_size[track->last_stsd_index]);
841 101 avio_write(pb, track->extradata[track->last_stsd_index],
842 101 track->extradata_size[track->last_stsd_index]);
843 }
844
845 // SL descriptor
846 308 put_descr(pb, 0x06, 1);
847 308 avio_w8(pb, 0x02);
848 308 return update_size(pb, pos);
849 }
850
851 81 static int mov_pcm_le_gt16(enum AVCodecID codec_id)
852 {
853
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 return codec_id == AV_CODEC_ID_PCM_S24LE ||
854
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 codec_id == AV_CODEC_ID_PCM_S32LE ||
855
2/4
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 81 times.
162 codec_id == AV_CODEC_ID_PCM_F32LE ||
856 codec_id == AV_CODEC_ID_PCM_F64LE;
857 }
858
859 81 static int mov_pcm_be_gt16(enum AVCodecID codec_id)
860 {
861
2/2
✓ Branch 0 taken 73 times.
✓ Branch 1 taken 4 times.
77 return codec_id == AV_CODEC_ID_PCM_S24BE ||
862
1/2
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
73 codec_id == AV_CODEC_ID_PCM_S32BE ||
863
3/4
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 73 times.
158 codec_id == AV_CODEC_ID_PCM_F32BE ||
864 codec_id == AV_CODEC_ID_PCM_F64BE;
865 }
866
867 ✗ static int mov_write_ms_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
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
879 ✗ static int mov_write_wfex_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
880 {
881 int ret;
882 ✗ int64_t pos = avio_tell(pb);
883 ✗ avio_wb32(pb, 0);
884 ✗ ffio_wfourcc(pb, "wfex");
885 ✗ if ((ret = ff_put_wav_header(s, pb, track->st->codecpar, FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX)) < 0)
886 ✗ return ret;
887 ✗ return update_size(pb, pos);
888 }
889
890 ✗ static int mov_write_dfla_tag(AVIOContext *pb, MOVTrack *track)
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. */
899 ✗ if (track->extradata_size[track->last_stsd_index] != FLAC_STREAMINFO_SIZE)
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
910 ✗ static int mov_write_dops_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
911 {
912 ✗ int64_t pos = avio_tell(pb);
913 int channels, channel_map;
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
944 ✗ static int mov_write_dmlp_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
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) {
952 ✗ av_log(s, AV_LOG_ERROR,
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
973 1 static int mov_write_mhac_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
974 {
975 1 int64_t pos = avio_tell(pb);
976 1 int layout = 0;
977
978
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (!track->extradata_size[track->last_stsd_index] ||
979
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 track->extradata_size[track->last_stsd_index] > UINT16_MAX) {
980 ✗ av_log(s, AV_LOG_ERROR,
981 "Invalid extradata size %d for MPEGH-H stream.\n",
982 ✗ track->extradata_size[track->last_stsd_index]);
983 ✗ return AVERROR(EINVAL);
984 }
985
986 1 avio_wb32(pb, 0);
987 1 ffio_wfourcc(pb, "mhaC");
988
989 1 avio_w8(pb, 1); // ConfigurationVersion
990 1 avio_w8(pb, track->par->profile * 5 + track->par->level);
991
992
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 for (size_t i = 0; i < FF_ARRAY_ELEMS(ff_mpa_cicp_channel_layout_masks); i++) {
993
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 2 times.
17 if (ff_mpa_cicp_channel_layout_masks[i]) {
994 AVChannelLayout ch_layout;
995 15 av_channel_layout_from_mask(&ch_layout, ff_mpa_cicp_channel_layout_masks[i]);
996
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 14 times.
15 if (!av_channel_layout_compare(&track->par->ch_layout, &ch_layout)) {
997 1 layout = i;
998 1 break;
999 }
1000 }
1001 }
1002
1003 1 avio_w8(pb, layout);
1004 1 avio_wb16(pb, track->extradata_size[track->last_stsd_index]);
1005 1 avio_write(pb, track->extradata[track->last_stsd_index],
1006 1 track->extradata_size[track->last_stsd_index]);
1007
1008 1 return update_size(pb, pos);
1009 }
1010
1011 290 static int mov_write_SA3D_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
1012 {
1013 290 const AVDictionaryEntry *str = av_dict_get(track->st->metadata, "SA3D", NULL, 0);
1014 290 AVChannelLayout ch_layout = { 0 };
1015 int64_t pos;
1016 int ambisonic_order, ambi_channels, non_diegetic_channels;
1017 int i, ret;
1018
1019
1/2
✓ Branch 0 taken 290 times.
✗ Branch 1 not taken.
290 if (!str)
1020 290 return 0;
1021
1022 ✗ ret = av_channel_layout_from_string(&ch_layout, str->value);
1023 ✗ if (ret < 0) {
1024 ✗ if (ret == AVERROR(EINVAL)) {
1025 ✗ invalid:
1026 ✗ av_log(s, AV_LOG_ERROR, "Invalid SA3D layout: \"%s\"\n", str->value);
1027 ✗ ret = 0;
1028 }
1029 ✗ av_channel_layout_uninit(&ch_layout);
1030 ✗ return ret;
1031 }
1032
1033 ✗ if (track->st->codecpar->ch_layout.nb_channels != ch_layout.nb_channels)
1034 ✗ goto invalid;
1035
1036 ✗ ambisonic_order = av_channel_layout_ambisonic_order(&ch_layout);
1037 ✗ if (ambisonic_order < 0)
1038 ✗ goto invalid;
1039
1040 ✗ ambi_channels = (ambisonic_order + 1LL) * (ambisonic_order + 1LL);
1041 ✗ non_diegetic_channels = ch_layout.nb_channels - ambi_channels;
1042 ✗ if (non_diegetic_channels &&
1043 ✗ (non_diegetic_channels != 2 ||
1044 ✗ av_channel_layout_subset(&ch_layout, AV_CH_LAYOUT_STEREO) != AV_CH_LAYOUT_STEREO))
1045 ✗ goto invalid;
1046
1047 ✗ av_log(s, AV_LOG_VERBOSE, "Inserting SA3D box with layout: \"%s\"\n", str->value);
1048
1049 ✗ pos = avio_tell(pb);
1050
1051 ✗ avio_wb32(pb, 0); // Size
1052 ✗ ffio_wfourcc(pb, "SA3D");
1053 ✗ avio_w8(pb, 0); // version
1054 ✗ avio_w8(pb, (!!non_diegetic_channels) << 7); // head_locked_stereo and ambisonic_type
1055 ✗ avio_wb32(pb, ambisonic_order); // ambisonic_order
1056 ✗ avio_w8(pb, 0); // ambisonic_channel_ordering
1057 ✗ avio_w8(pb, 0); // ambisonic_normalization
1058 ✗ avio_wb32(pb, ch_layout.nb_channels); // num_channels
1059 ✗ for (i = 0; i < ambi_channels; i++)
1060 ✗ avio_wb32(pb, av_channel_layout_channel_from_index(&ch_layout, i) - AV_CHAN_AMBISONIC_BASE);
1061 ✗ for (; i < ch_layout.nb_channels; i++)
1062 ✗ avio_wb32(pb, av_channel_layout_channel_from_index(&ch_layout, i) + ambi_channels);
1063
1064 ✗ av_channel_layout_uninit(&ch_layout);
1065
1066 ✗ return update_size(pb, pos);
1067 }
1068
1069 45 static int mov_write_chan_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
1070 {
1071 uint32_t layout_tag, bitmap, *channel_desc;
1072 45 int64_t pos = avio_tell(pb);
1073 int num_desc, ret;
1074
1075
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 if (track->multichannel_as_mono)
1076 ✗ return 0;
1077
1078 45 ret = ff_mov_get_channel_layout_tag(track->par, &layout_tag,
1079 &bitmap, &channel_desc);
1080
1081
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 if (ret < 0) {
1082 ✗ if (ret == AVERROR(ENOSYS)) {
1083 ✗ av_log(s, AV_LOG_WARNING, "not writing 'chan' tag due to "
1084 "lack of channel information\n");
1085 ✗ ret = 0;
1086 }
1087
1088 ✗ return ret;
1089 }
1090
1091 /* no predefined tag found + ch_layout in AV_CHANNEL_ORDER_NATIVE
1092 * but bitstream channels not actually in native order */
1093
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 if (layout_tag == MOV_CH_LAYOUT_UNKNOWN)
1094 ✗ return 0;
1095
1096
4/4
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 16 times.
45 if (layout_tag == MOV_CH_LAYOUT_MONO && track->mono_as_fc > 0) {
1097
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 av_assert0(!channel_desc);
1098 1 channel_desc = av_malloc(sizeof(*channel_desc));
1099
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!channel_desc)
1100 ✗ return AVERROR(ENOMEM);
1101
1102 1 layout_tag = 0;
1103 1 bitmap = 0;
1104 1 *channel_desc = 3; // channel label "Center"
1105 }
1106
1107
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 42 times.
45 num_desc = layout_tag ? 0 : track->par->ch_layout.nb_channels;
1108
1109 45 avio_wb32(pb, 0); // Size
1110 45 ffio_wfourcc(pb, "chan"); // Type
1111 45 avio_w8(pb, 0); // Version
1112 45 avio_wb24(pb, 0); // Flags
1113 45 avio_wb32(pb, layout_tag); // mChannelLayoutTag
1114 45 avio_wb32(pb, bitmap); // mChannelBitmap
1115 45 avio_wb32(pb, num_desc); // mNumberChannelDescriptions
1116
1117
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 45 times.
48 for (int i = 0; i < num_desc; i++) {
1118 3 avio_wb32(pb, channel_desc[i]); // mChannelLabel
1119 3 avio_wb32(pb, 0); // mChannelFlags
1120 3 avio_wl32(pb, 0); // mCoordinates[0]
1121 3 avio_wl32(pb, 0); // mCoordinates[1]
1122 3 avio_wl32(pb, 0); // mCoordinates[2]
1123 }
1124
1125 45 av_free(channel_desc);
1126
1127 45 return update_size(pb, pos);
1128 }
1129
1130 16 static int mov_write_wave_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
1131 {
1132 16 int64_t pos = avio_tell(pb);
1133
1134 16 avio_wb32(pb, 0); /* size */
1135 16 ffio_wfourcc(pb, "wave");
1136
1137
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (track->par->codec_id != AV_CODEC_ID_QDM2) {
1138 16 avio_wb32(pb, 12); /* size */
1139 16 ffio_wfourcc(pb, "frma");
1140 16 avio_wl32(pb, track->tag);
1141 }
1142
1143
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 11 times.
16 if (track->par->codec_id == AV_CODEC_ID_AAC) {
1144 /* useless atom needed by mplayer, ipod, not needed by quicktime */
1145 5 avio_wb32(pb, 12); /* size */
1146 5 ffio_wfourcc(pb, "mp4a");
1147 5 avio_wb32(pb, 0);
1148 5 mov_write_esds_tag(pb, track);
1149
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
11 } else if (mov_pcm_le_gt16(track->par->codec_id)) {
1150 ✗ mov_write_enda_tag(pb);
1151
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 9 times.
11 } else if (mov_pcm_be_gt16(track->par->codec_id)) {
1152 2 mov_write_enda_tag_be(pb);
1153
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 } else if (track->par->codec_id == AV_CODEC_ID_AMR_NB) {
1154 ✗ mov_write_amr_tag(pb, track);
1155
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 } else if (track->par->codec_id == AV_CODEC_ID_AC3) {
1156 ✗ mov_write_ac3_tag(s, pb, track);
1157
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 } else if (track->par->codec_id == AV_CODEC_ID_EAC3) {
1158 ✗ mov_write_eac3_tag(s, pb, track);
1159
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 } else if (track->par->codec_id == AV_CODEC_ID_ALAC ||
1160 ✗ track->par->codec_id == AV_CODEC_ID_QDM2) {
1161 9 mov_write_extradata_tag(pb, track);
1162 ✗ } else if (track->par->codec_id == AV_CODEC_ID_ADPCM_MS ||
1163 ✗ track->par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) {
1164 ✗ mov_write_ms_tag(s, pb, track);
1165 }
1166
1167 16 avio_wb32(pb, 8); /* size */
1168 16 avio_wb32(pb, 0); /* null tag */
1169
1170 16 return update_size(pb, pos);
1171 }
1172
1173 ✗ static int mov_write_dvc1_structs(MOVTrack *track, uint8_t *buf)
1174 {
1175 uint8_t *unescaped;
1176 ✗ const uint8_t *start, *next, *end = track->extradata[track->last_stsd_index] +
1177 ✗ track->extradata_size[track->last_stsd_index];
1178 ✗ int unescaped_size, seq_found = 0;
1179 ✗ int level = 0, interlace = 0;
1180 ✗ int packet_seq = track->vc1_info.packet_seq;
1181 ✗ int packet_entry = track->vc1_info.packet_entry;
1182 ✗ int slices = track->vc1_info.slices;
1183 PutBitContext pbc;
1184
1185 ✗ if (track->start_dts == AV_NOPTS_VALUE) {
1186 /* No packets written yet, vc1_info isn't authoritative yet. */
1187 /* Assume inline sequence and entry headers. */
1188 ✗ packet_seq = packet_entry = 1;
1189 ✗ av_log(NULL, AV_LOG_WARNING,
1190 "moov atom written before any packets, unable to write correct "
1191 "dvc1 atom. Set the delay_moov flag to fix this.\n");
1192 }
1193
1194 ✗ unescaped = av_mallocz(track->extradata_size[track->last_stsd_index] + AV_INPUT_BUFFER_PADDING_SIZE);
1195 ✗ if (!unescaped)
1196 ✗ return AVERROR(ENOMEM);
1197 ✗ start = find_next_marker(track->extradata[track->last_stsd_index], end);
1198 ✗ for (next = start; next < end; start = next) {
1199 GetBitContext gb;
1200 int size;
1201 ✗ next = find_next_marker(start + 4, end);
1202 ✗ size = next - start - 4;
1203 ✗ if (size <= 0)
1204 ✗ continue;
1205 ✗ unescaped_size = vc1_unescape_buffer(start + 4, size, unescaped);
1206 ✗ init_get_bits(&gb, unescaped, 8 * unescaped_size);
1207 ✗ if (AV_RB32(start) == VC1_CODE_SEQHDR) {
1208 ✗ int profile = get_bits(&gb, 2);
1209 ✗ if (profile != PROFILE_ADVANCED) {
1210 ✗ av_free(unescaped);
1211 ✗ return AVERROR(ENOSYS);
1212 }
1213 ✗ seq_found = 1;
1214 ✗ level = get_bits(&gb, 3);
1215 /* chromaformat, frmrtq_postproc, bitrtq_postproc, postprocflag,
1216 * width, height */
1217 ✗ skip_bits_long(&gb, 2 + 3 + 5 + 1 + 2*12);
1218 ✗ skip_bits(&gb, 1); /* broadcast */
1219 ✗ interlace = get_bits1(&gb);
1220 ✗ skip_bits(&gb, 4); /* tfcntrflag, finterpflag, reserved, psf */
1221 }
1222 }
1223 ✗ if (!seq_found) {
1224 ✗ av_free(unescaped);
1225 ✗ return AVERROR(ENOSYS);
1226 }
1227
1228 ✗ init_put_bits(&pbc, buf, 7);
1229 /* VC1DecSpecStruc */
1230 ✗ put_bits(&pbc, 4, 12); /* profile - advanced */
1231 ✗ put_bits(&pbc, 3, level);
1232 ✗ put_bits(&pbc, 1, 0); /* reserved */
1233 /* VC1AdvDecSpecStruc */
1234 ✗ put_bits(&pbc, 3, level);
1235 ✗ put_bits(&pbc, 1, 0); /* cbr */
1236 ✗ put_bits(&pbc, 6, 0); /* reserved */
1237 ✗ put_bits(&pbc, 1, !interlace); /* no interlace */
1238 ✗ put_bits(&pbc, 1, !packet_seq); /* no multiple seq */
1239 ✗ put_bits(&pbc, 1, !packet_entry); /* no multiple entry */
1240 ✗ put_bits(&pbc, 1, !slices); /* no slice code */
1241 ✗ put_bits(&pbc, 1, 0); /* no bframe */
1242 ✗ put_bits(&pbc, 1, 0); /* reserved */
1243
1244 /* framerate */
1245 ✗ if (track->st->avg_frame_rate.num > 0 && track->st->avg_frame_rate.den > 0)
1246 ✗ put_bits32(&pbc, track->st->avg_frame_rate.num / track->st->avg_frame_rate.den);
1247 else
1248 ✗ put_bits32(&pbc, 0xffffffff);
1249
1250 ✗ flush_put_bits(&pbc);
1251
1252 ✗ av_free(unescaped);
1253
1254 ✗ return 0;
1255 }
1256
1257 ✗ static int mov_write_dvc1_tag(AVIOContext *pb, MOVTrack *track)
1258 {
1259 ✗ uint8_t buf[7] = { 0 };
1260 int ret;
1261
1262 ✗ if ((ret = mov_write_dvc1_structs(track, buf)) < 0)
1263 ✗ return ret;
1264
1265 ✗ avio_wb32(pb, track->extradata_size[track->last_stsd_index] + 8 + sizeof(buf));
1266 ✗ ffio_wfourcc(pb, "dvc1");
1267 ✗ avio_write(pb, buf, sizeof(buf));
1268 ✗ avio_write(pb, track->extradata[track->last_stsd_index],
1269 ✗ track->extradata_size[track->last_stsd_index]);
1270
1271 ✗ return 0;
1272 }
1273
1274 4 static int mov_write_glbl_tag(AVIOContext *pb, MOVTrack *track)
1275 {
1276 4 avio_wb32(pb, track->extradata_size[track->last_stsd_index] + 8);
1277 4 ffio_wfourcc(pb, "glbl");
1278 4 avio_write(pb, track->extradata[track->last_stsd_index],
1279 4 track->extradata_size[track->last_stsd_index]);
1280 4 return 8 + track->extradata_size[track->last_stsd_index];
1281 }
1282
1283 /**
1284 * Compute flags for 'lpcm' tag.
1285 * See CoreAudioTypes and AudioStreamBasicDescription at Apple.
1286 */
1287 16 static int mov_get_lpcm_flags(enum AVCodecID codec_id)
1288 {
1289
2/6
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 8 times.
16 switch (codec_id) {
1290 ✗ case AV_CODEC_ID_PCM_F32BE:
1291 case AV_CODEC_ID_PCM_F64BE:
1292 ✗ return 11;
1293 ✗ case AV_CODEC_ID_PCM_F32LE:
1294 case AV_CODEC_ID_PCM_F64LE:
1295 ✗ return 9;
1296 ✗ case AV_CODEC_ID_PCM_U8:
1297 ✗ return 10;
1298 8 case AV_CODEC_ID_PCM_S16BE:
1299 case AV_CODEC_ID_PCM_S24BE:
1300 case AV_CODEC_ID_PCM_S32BE:
1301 8 return 14;
1302 ✗ case AV_CODEC_ID_PCM_S8:
1303 case AV_CODEC_ID_PCM_S16LE:
1304 case AV_CODEC_ID_PCM_S24LE:
1305 case AV_CODEC_ID_PCM_S32LE:
1306 ✗ return 12;
1307 8 default:
1308 8 return 0;
1309 }
1310 }
1311
1312 40440 static int get_cluster_duration(MOVTrack *track, int cluster_idx)
1313 {
1314 int64_t next_dts;
1315
1316
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40440 times.
40440 if (cluster_idx >= track->entry)
1317 ✗ return 0;
1318
1319
2/2
✓ Branch 0 taken 1665 times.
✓ Branch 1 taken 38775 times.
40440 if (cluster_idx + 1 == track->entry)
1320 1665 next_dts = track->track_duration + track->start_dts;
1321 else
1322 38775 next_dts = track->cluster[cluster_idx + 1].dts;
1323
1324 40440 next_dts -= track->cluster[cluster_idx].dts;
1325
1326
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40440 times.
40440 av_assert0(next_dts >= 0);
1327
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40440 times.
40440 av_assert0(next_dts <= INT_MAX);
1328
1329 40440 return next_dts;
1330 }
1331
1332 8 static int get_samples_per_packet(MOVTrack *track)
1333 {
1334 int i, first_duration;
1335
1336 /* use 1 for raw PCM */
1337
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 if (!track->audio_vbr)
1338 4 return 1;
1339
1340 /* check to see if duration is constant for all clusters */
1341
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!track->entry)
1342 ✗ return 0;
1343 4 first_duration = get_cluster_duration(track, 0);
1344
1/2
✓ Branch 0 taken 1872 times.
✗ Branch 1 not taken.
1872 for (i = 1; i < track->entry; i++) {
1345
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1868 times.
1872 if (get_cluster_duration(track, i) != first_duration)
1346 4 return 0;
1347 }
1348 ✗ return first_duration;
1349 }
1350
1351 382 static int mov_write_btrt_tag(AVIOContext *pb, MOVTrack *track)
1352 {
1353 382 int64_t pos = avio_tell(pb);
1354 382 struct mpeg4_bit_rate_values bit_rates = calculate_mpeg4_bit_rates(track);
1355
3/4
✓ Branch 0 taken 86 times.
✓ Branch 1 taken 296 times.
✓ Branch 2 taken 86 times.
✗ Branch 3 not taken.
382 if (!bit_rates.max_bit_rate && !bit_rates.avg_bit_rate &&
1356
1/2
✓ Branch 0 taken 86 times.
✗ Branch 1 not taken.
86 !bit_rates.buffer_size)
1357 // no useful data to be written, skip
1358 86 return 0;
1359
1360 296 avio_wb32(pb, 0); /* size */
1361 296 ffio_wfourcc(pb, "btrt");
1362
1363 296 avio_wb32(pb, bit_rates.buffer_size);
1364 296 avio_wb32(pb, bit_rates.max_bit_rate);
1365 296 avio_wb32(pb, bit_rates.avg_bit_rate);
1366
1367 296 return update_size(pb, pos);
1368 }
1369
1370 7 static int mov_write_chnl_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
1371 {
1372 7 int64_t pos = avio_tell(pb);
1373 7 int config = 0;
1374 int ret;
1375 7 uint8_t *speaker_pos = NULL;
1376 7 const AVChannelLayout *layout = &track->par->ch_layout;
1377
1378 7 ret = ff_mov_get_channel_config_from_layout(layout, &config);
1379
3/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 3 times.
7 if (ret || !config) {
1380 4 config = 0;
1381 4 speaker_pos = av_malloc(layout->nb_channels);
1382
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!speaker_pos)
1383 ✗ return AVERROR(ENOMEM);
1384 4 ret = ff_mov_get_channel_positions_from_layout(layout,
1385 4 speaker_pos, layout->nb_channels);
1386
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret) {
1387 ✗ char buf[128] = {0};
1388
1389 ✗ av_freep(&speaker_pos);
1390 ✗ av_channel_layout_describe(layout, buf, sizeof(buf));
1391 ✗ av_log(s, AV_LOG_ERROR, "unsupported channel layout %s\n", buf);
1392 ✗ return ret;
1393 }
1394 }
1395
1396 7 avio_wb32(pb, 0); /* size */
1397 7 ffio_wfourcc(pb, "chnl");
1398 7 avio_wb32(pb, 0); /* version & flags */
1399
1400 7 avio_w8(pb, 1); /* stream_structure */
1401 7 avio_w8(pb, config);
1402
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 4 times.
7 if (config) {
1403 3 avio_wb64(pb, 0);
1404 } else {
1405 4 avio_write(pb, speaker_pos, layout->nb_channels);
1406 4 av_freep(&speaker_pos);
1407 }
1408
1409 7 return update_size(pb, pos);
1410 }
1411
1412 9 static int mov_write_pcmc_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
1413 {
1414 9 int64_t pos = avio_tell(pb);
1415 int format_flags;
1416 int sample_size;
1417
1418 9 avio_wb32(pb, 0); /* size */
1419 9 ffio_wfourcc(pb, "pcmC");
1420 9 avio_wb32(pb, 0); /* version & flags */
1421
1422 /* 0x01: indicates little-endian format */
1423 26 format_flags = (track->par->codec_id == AV_CODEC_ID_PCM_F32LE ||
1424
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 track->par->codec_id == AV_CODEC_ID_PCM_F64LE ||
1425
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 track->par->codec_id == AV_CODEC_ID_PCM_S16LE ||
1426
2/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
17 track->par->codec_id == AV_CODEC_ID_PCM_S24LE ||
1427 ✗ track->par->codec_id == AV_CODEC_ID_PCM_S32LE);
1428 9 avio_w8(pb, format_flags);
1429 9 sample_size = track->par->bits_per_raw_sample;
1430
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8 times.
9 if (!sample_size)
1431 1 sample_size = av_get_exact_bits_per_sample(track->par->codec_id);
1432
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 av_assert0(sample_size);
1433 9 avio_w8(pb, sample_size);
1434
1435 9 return update_size(pb, pos);
1436 }
1437
1438 5 static int mov_write_srat_tag(AVIOContext *pb, MOVTrack *track)
1439 {
1440 5 int64_t pos = avio_tell(pb);
1441 5 avio_wb32(pb, 0); /* size */
1442 5 ffio_wfourcc(pb, "srat");
1443 5 avio_wb32(pb, 0); /* version & flags */
1444
1445 5 avio_wb32(pb, track->par->sample_rate);
1446
1447 5 return update_size(pb, pos);
1448 }
1449
1450 338 static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
1451 {
1452 338 int64_t pos = avio_tell(pb);
1453 338 int version = 0;
1454 338 uint32_t tag = track->tag;
1455 338 int ret = 0;
1456
1457
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 293 times.
338 if (track->mode == MODE_MOV) {
1458
3/4
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 37 times.
✗ Branch 3 not taken.
45 if (track->par->sample_rate > UINT16_MAX || !track->par->ch_layout.nb_channels ||
1459
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 track->par->codec_id == AV_CODEC_ID_EAC3 ||
1460
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
37 track->par->ch_layout.nb_channels > 2) {
1461
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 4 times.
8 if (mov_get_lpcm_flags(track->par->codec_id))
1462 4 tag = AV_RL32("lpcm");
1463 8 version = 2;
1464
5/6
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 11 times.
✓ Branch 3 taken 26 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 24 times.
✓ Branch 6 taken 2 times.
63 } else if (track->audio_vbr || mov_pcm_le_gt16(track->par->codec_id) ||
1465 26 mov_pcm_be_gt16(track->par->codec_id) ||
1466
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 track->par->codec_id == AV_CODEC_ID_ADPCM_MS ||
1467
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 track->par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV ||
1468
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 track->par->codec_id == AV_CODEC_ID_QDM2) {
1469 13 version = 1;
1470 }
1471
2/2
✓ Branch 0 taken 290 times.
✓ Branch 1 taken 3 times.
293 } else if (track->mode == MODE_MP4) {
1472
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 285 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
290 if (track->par->sample_rate > UINT16_MAX &&
1473 ✗ (tag == MOV_MP4_IPCM_TAG || tag == MOV_MP4_FPCM_TAG))
1474 5 version = 1;
1475 }
1476
1477 338 avio_wb32(pb, 0); /* size */
1478
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 338 times.
338 if (mov->encryption_scheme != MOV_ENC_NONE) {
1479 ✗ ffio_wfourcc(pb, "enca");
1480 } else {
1481 338 avio_wl32(pb, tag); // store it byteswapped
1482 }
1483 338 avio_wb32(pb, 0); /* Reserved */
1484 338 avio_wb16(pb, 0); /* Reserved */
1485 338 avio_wb16(pb, 1); /* Data-reference index, XXX == 1 */
1486
1487 /* SoundDescription */
1488 338 avio_wb16(pb, version); /* Version */
1489 338 avio_wb16(pb, 0); /* Revision level */
1490 338 avio_wb32(pb, 0); /* Reserved */
1491
1492
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 330 times.
338 if (version == 2) {
1493 8 avio_wb16(pb, 3);
1494 8 avio_wb16(pb, 16);
1495 8 avio_wb16(pb, 0xfffe);
1496 8 avio_wb16(pb, 0);
1497 8 avio_wb32(pb, 0x00010000);
1498 8 avio_wb32(pb, 72);
1499 8 avio_wb64(pb, av_double2int(track->par->sample_rate));
1500 8 avio_wb32(pb, track->par->ch_layout.nb_channels);
1501 8 avio_wb32(pb, 0x7F000000);
1502 8 avio_wb32(pb, av_get_bits_per_sample(track->par->codec_id));
1503 8 avio_wb32(pb, mov_get_lpcm_flags(track->par->codec_id));
1504 8 avio_wb32(pb, track->sample_size);
1505 8 avio_wb32(pb, get_samples_per_packet(track));
1506 } else {
1507 330 unsigned sample_rate = track->par->sample_rate;
1508
1509
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 293 times.
330 if (track->mode == MODE_MOV) {
1510 37 avio_wb16(pb, track->par->ch_layout.nb_channels);
1511
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 if (track->par->codec_id == AV_CODEC_ID_PCM_U8 ||
1512
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 36 times.
37 track->par->codec_id == AV_CODEC_ID_PCM_S8)
1513 1 avio_wb16(pb, 8); /* bits per sample */
1514
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 else if (track->par->codec_id == AV_CODEC_ID_ADPCM_G726)
1515 ✗ avio_wb16(pb, track->par->bits_per_coded_sample);
1516 else
1517 36 avio_wb16(pb, 16);
1518
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 26 times.
37 avio_wb16(pb, track->audio_vbr ? -2 : 0); /* compression ID */
1519 } else { /* reserved for mp4/3gp */
1520
2/2
✓ Branch 0 taken 287 times.
✓ Branch 1 taken 6 times.
580 avio_wb16(pb, track->tag == MKTAG('i', 'a', 'm', 'f') ?
1521 287 0 : track->par->ch_layout.nb_channels);
1522
2/2
✓ Branch 0 taken 287 times.
✓ Branch 1 taken 6 times.
293 if (track->par->codec_id == AV_CODEC_ID_FLAC ||
1523
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 287 times.
287 track->par->codec_id == AV_CODEC_ID_ALAC) {
1524 6 avio_wb16(pb, track->par->bits_per_raw_sample);
1525 } else {
1526 287 avio_wb16(pb, 16);
1527 }
1528 293 avio_wb16(pb, 0);
1529
1530
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 293 times.
298 while (sample_rate > UINT16_MAX)
1531 5 sample_rate >>= 1;
1532 }
1533
1534 330 avio_wb16(pb, 0); /* packet size (= 0) */
1535
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 324 times.
330 if (track->tag == MKTAG('i','a','m','f'))
1536 6 avio_wb16(pb, 0); /* samplerate must be 0 for IAMF */
1537
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 324 times.
324 else if (track->par->codec_id == AV_CODEC_ID_OPUS)
1538 ✗ avio_wb16(pb, 48000);
1539
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 324 times.
324 else if (track->par->codec_id == AV_CODEC_ID_TRUEHD)
1540 ✗ avio_wb32(pb, track->par->sample_rate);
1541 else
1542 324 avio_wb16(pb, sample_rate);
1543
1544
1/2
✓ Branch 0 taken 330 times.
✗ Branch 1 not taken.
330 if (track->par->codec_id != AV_CODEC_ID_TRUEHD)
1545 330 avio_wb16(pb, 0); /* Reserved */
1546 }
1547
1548
4/4
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 293 times.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 32 times.
338 if (track->mode == MODE_MOV && version == 1) { /* SoundDescription V1 extended info */
1549
3/4
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 11 times.
26 if (mov_pcm_le_gt16(track->par->codec_id) ||
1550 13 mov_pcm_be_gt16(track->par->codec_id))
1551 2 avio_wb32(pb, 1); /* must be 1 for uncompressed formats */
1552 else
1553 11 avio_wb32(pb, track->par->frame_size); /* Samples per packet */
1554 13 avio_wb32(pb, track->sample_size / track->par->ch_layout.nb_channels); /* Bytes per packet */
1555 13 avio_wb32(pb, track->sample_size); /* Bytes per frame */
1556 13 avio_wb32(pb, 2); /* Bytes per sample */
1557 }
1558
1559
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 293 times.
338 if (track->mode == MODE_MOV &&
1560
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 5 times.
45 (track->par->codec_id == AV_CODEC_ID_AAC ||
1561
1/2
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
40 track->par->codec_id == AV_CODEC_ID_AC3 ||
1562
1/2
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
40 track->par->codec_id == AV_CODEC_ID_EAC3 ||
1563
1/2
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
40 track->par->codec_id == AV_CODEC_ID_AMR_NB ||
1564
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 9 times.
40 track->par->codec_id == AV_CODEC_ID_ALAC ||
1565
1/2
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
31 track->par->codec_id == AV_CODEC_ID_ADPCM_MS ||
1566
1/2
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
31 track->par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV ||
1567
2/4
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 31 times.
62 track->par->codec_id == AV_CODEC_ID_QDM2 ||
1568
2/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 29 times.
62 (mov_pcm_le_gt16(track->par->codec_id) && version==1) ||
1569
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
33 (mov_pcm_be_gt16(track->par->codec_id) && version==1)))
1570 16 ret = mov_write_wave_tag(s, pb, track);
1571
2/2
✓ Branch 0 taken 266 times.
✓ Branch 1 taken 56 times.
322 else if (track->tag == MKTAG('m','p','4','a'))
1572 266 ret = mov_write_esds_tag(pb, track);
1573 #if CONFIG_IAMFENC
1574
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 50 times.
56 else if (track->tag == MKTAG('i','a','m','f'))
1575 6 ret = mov_write_iacb_tag(mov->fc, pb, track);
1576 #endif
1577
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 else if (track->par->codec_id == AV_CODEC_ID_AMR_NB)
1578 ✗ ret = mov_write_amr_tag(pb, track);
1579
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 43 times.
50 else if (track->par->codec_id == AV_CODEC_ID_AC3)
1580 7 ret = mov_write_ac3_tag(s, pb, track);
1581
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 39 times.
43 else if (track->par->codec_id == AV_CODEC_ID_EAC3)
1582 4 ret = mov_write_eac3_tag(s, pb, track);
1583
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 else if (track->par->codec_id == AV_CODEC_ID_ALAC)
1584 ✗ ret = mov_write_extradata_tag(pb, track);
1585
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 else if (track->par->codec_id == AV_CODEC_ID_WMAPRO)
1586 ✗ ret = mov_write_wfex_tag(s, pb, track);
1587
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 else if (track->par->codec_id == AV_CODEC_ID_FLAC)
1588 ✗ ret = mov_write_dfla_tag(pb, track);
1589
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 else if (track->par->codec_id == AV_CODEC_ID_OPUS)
1590 ✗ ret = mov_write_dops_tag(s, pb, track);
1591
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 else if (track->par->codec_id == AV_CODEC_ID_TRUEHD)
1592 ✗ ret = mov_write_dmlp_tag(s, pb, track);
1593
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 38 times.
39 else if (track->par->codec_id == AV_CODEC_ID_MPEGH_3D_AUDIO)
1594 1 ret = mov_write_mhac_tag(s, pb, track);
1595
4/4
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 29 times.
38 else if (tag == MOV_MP4_IPCM_TAG || tag == MOV_MP4_FPCM_TAG) {
1596
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4 times.
9 if (track->par->sample_rate > UINT16_MAX)
1597 5 mov_write_srat_tag(pb, track);
1598
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 2 times.
9 if (track->par->ch_layout.nb_channels > 1)
1599 7 ret = mov_write_chnl_tag(s, pb, track);
1600
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (ret < 0)
1601 ✗ return ret;
1602 9 ret = mov_write_pcmc_tag(s, pb, track);
1603
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 } else if (track->extradata_size[track->last_stsd_index] > 0)
1604 ✗ ret = mov_write_glbl_tag(pb, track);
1605
1606
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 338 times.
338 if (ret < 0)
1607 ✗ return ret;
1608
1609
3/4
✓ Branch 0 taken 290 times.
✓ Branch 1 taken 48 times.
✓ Branch 2 taken 290 times.
✗ Branch 3 not taken.
338 if (track->mode == MODE_MP4 && track->par->codec_type == AVMEDIA_TYPE_AUDIO
1610
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 290 times.
290 && ((ret = mov_write_SA3D_tag(s, pb, track)) < 0)) {
1611 ✗ return ret;
1612 }
1613
1614
3/4
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 293 times.
✓ Branch 2 taken 45 times.
✗ Branch 3 not taken.
338 if (track->mode == MODE_MOV && track->par->codec_type == AVMEDIA_TYPE_AUDIO
1615
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 45 times.
45 && ((ret = mov_write_chan_tag(s, pb, track)) < 0)) {
1616 ✗ return ret;
1617 }
1618
1619
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 338 times.
338 if (mov->encryption_scheme != MOV_ENC_NONE
1620 ✗ && ((ret = ff_mov_cenc_write_sinf_tag(track, pb, mov->encryption_kid)) < 0)) {
1621 ✗ return ret;
1622 }
1623
1624
3/4
✓ Branch 0 taken 290 times.
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 290 times.
628 if (mov->write_btrt &&
1625 290 ((ret = mov_write_btrt_tag(pb, track)) < 0))
1626 ✗ return ret;
1627
1628
2/2
✓ Branch 0 taken 290 times.
✓ Branch 1 taken 48 times.
338 if (track->mode == MODE_MP4)
1629 290 track->entry_version = version;
1630
1631 338 ret = update_size(pb, pos);
1632 338 return ret;
1633 }
1634
1635 ✗ static int mov_write_d263_tag(AVIOContext *pb)
1636 {
1637 ✗ avio_wb32(pb, 0xf); /* size */
1638 ✗ ffio_wfourcc(pb, "d263");
1639 ✗ ffio_wfourcc(pb, "FFMP");
1640 ✗ avio_w8(pb, 0); /* decoder version */
1641 /* FIXME use AVCodecContext level/profile, when encoder will set values */
1642 ✗ avio_w8(pb, 0xa); /* level */
1643 ✗ avio_w8(pb, 0); /* profile */
1644 ✗ return 0xf;
1645 }
1646
1647 4 static int mov_write_av1c_tag(AVIOContext *pb, MOVTrack *track)
1648 {
1649 4 int64_t pos = avio_tell(pb);
1650
1651 4 avio_wb32(pb, 0);
1652 4 ffio_wfourcc(pb, "av1C");
1653 4 ff_isom_write_av1c(pb, track->extradata[track->last_stsd_index],
1654 4 track->extradata_size[track->last_stsd_index], track->mode != MODE_AVIF);
1655 4 return update_size(pb, pos);
1656 }
1657
1658 62 static int mov_write_avcc_tag(AVIOContext *pb, MOVTrack *track)
1659 {
1660 62 int64_t pos = avio_tell(pb);
1661
1662 62 avio_wb32(pb, 0);
1663 62 ffio_wfourcc(pb, "avcC");
1664 62 ff_isom_write_avcc(pb, track->extradata[track->last_stsd_index],
1665 62 track->extradata_size[track->last_stsd_index]);
1666 62 return update_size(pb, pos);
1667 }
1668
1669 /* AVS3 Intelligent Media Coding
1670 * Information Technology - Intelligent Media Coding
1671 * Part 6: Intelligent Media Format
1672 */
1673 ✗ static int mov_write_av3c(AVIOContext *pb, const uint8_t *data, int len)
1674 {
1675 ✗ if (len < 4)
1676 ✗ return AVERROR_INVALIDDATA;
1677
1678 ✗ if (data[0] == 1) {
1679 // In Avs3DecoderConfigurationRecord format
1680 ✗ avio_write(pb, data, len);
1681 ✗ return 0;
1682 }
1683
1684 ✗ avio_w8(pb, 1); // version
1685 ✗ avio_wb16(pb, len); // sequence_header_length
1686 ✗ avio_write(pb, data, len); // sequence_header
1687 ✗ avio_w8(pb, 0xFC); // Only support library_dependency_idc = 0
1688
1689 ✗ return 0;
1690 }
1691
1692 ✗ static int mov_write_av3c_tag(AVIOContext *pb, MOVTrack *track)
1693 {
1694 ✗ int64_t pos = avio_tell(pb);
1695 ✗ avio_wb32(pb, 0);
1696 ✗ ffio_wfourcc(pb, "av3c");
1697 ✗ mov_write_av3c(pb, track->extradata[track->last_stsd_index],
1698 ✗ track->extradata_size[track->last_stsd_index]);
1699 ✗ return update_size(pb, pos);
1700 }
1701
1702 ✗ static int mov_write_vpcc_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
1703 {
1704 ✗ int64_t pos = avio_tell(pb);
1705
1706 ✗ avio_wb32(pb, 0);
1707 ✗ ffio_wfourcc(pb, "vpcC");
1708 ✗ ff_isom_write_vpcc(s, pb, track->extradata[track->last_stsd_index],
1709 ✗ track->extradata_size[track->last_stsd_index], track->par);
1710 ✗ return update_size(pb, pos);
1711 }
1712
1713 11 static int mov_write_hvcc_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
1714 {
1715 11 int64_t pos = avio_tell(pb);
1716
1717 11 avio_wb32(pb, 0);
1718 11 ffio_wfourcc(pb, "hvcC");
1719
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 8 times.
11 if (track->tag == MKTAG('h','v','c','1'))
1720 3 ff_isom_write_hvcc(pb, track->extradata[track->last_stsd_index],
1721 3 track->extradata_size[track->last_stsd_index], 1, s);
1722 else
1723 8 ff_isom_write_hvcc(pb, track->extradata[track->last_stsd_index],
1724 8 track->extradata_size[track->last_stsd_index], 0, s);
1725 11 return update_size(pb, pos);
1726 }
1727
1728 1 static int mov_write_lhvc_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
1729 {
1730 1 int64_t pos = avio_tell(pb);
1731 int ret;
1732
1733 1 avio_wb32(pb, 0);
1734 1 ffio_wfourcc(pb, "lhvC");
1735
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (track->tag == MKTAG('h','v','c','1'))
1736 1 ret = ff_isom_write_lhvc(pb, track->extradata[track->last_stsd_index],
1737 1 track->extradata_size[track->last_stsd_index], 1, s);
1738 else
1739 ✗ ret = ff_isom_write_lhvc(pb, track->extradata[track->last_stsd_index],
1740 ✗ track->extradata_size[track->last_stsd_index], 0, s);
1741
1742
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0) {
1743 ✗ avio_seek(pb, pos, SEEK_SET);
1744 ✗ return ret;
1745 }
1746
1747 1 return update_size(pb, pos);
1748 }
1749
1750 1 static int mov_write_evcc_tag(AVIOContext *pb, MOVTrack *track)
1751 {
1752 1 int64_t pos = avio_tell(pb);
1753
1754 1 avio_wb32(pb, 0);
1755 1 ffio_wfourcc(pb, "evcC");
1756
1757
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (track->tag == MKTAG('e','v','c','1'))
1758 1 ff_isom_write_evcc(pb, track->extradata[track->last_stsd_index],
1759 1 track->extradata_size[track->last_stsd_index], 1);
1760 else
1761 ✗ ff_isom_write_evcc(pb, track->extradata[track->last_stsd_index],
1762 ✗ track->extradata_size[track->last_stsd_index], 0);
1763
1764 1 return update_size(pb, pos);
1765 }
1766
1767 1 static int mov_write_lvcc_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
1768 {
1769 1 int64_t pos = avio_tell(pb);
1770
1771 1 avio_wb32(pb, 0);
1772 1 ffio_wfourcc(pb, "lvcC");
1773
1774 1 ff_isom_write_lvcc(pb, track->extradata[track->last_stsd_index],
1775 1 track->extradata_size[track->last_stsd_index], s);
1776
1777 1 return update_size(pb, pos);
1778 }
1779
1780 1 static int mov_write_vvcc_tag(AVIOContext *pb, MOVTrack *track)
1781 {
1782 1 int64_t pos = avio_tell(pb);
1783
1784 1 avio_wb32(pb, 0);
1785 1 ffio_wfourcc(pb, "vvcC");
1786
1787 1 avio_w8 (pb, 0); /* version */
1788 1 avio_wb24(pb, 0); /* flags */
1789
1790
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (track->tag == MKTAG('v','v','c','1'))
1791 1 ff_isom_write_vvcc(pb, track->extradata[track->last_stsd_index],
1792 1 track->extradata_size[track->last_stsd_index], 1);
1793 else
1794 ✗ ff_isom_write_vvcc(pb, track->extradata[track->last_stsd_index],
1795 ✗ track->extradata_size[track->last_stsd_index], 0);
1796 1 return update_size(pb, pos);
1797 }
1798
1799 1 static int mov_write_apvc_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
1800 {
1801 1 int64_t pos = avio_tell(pb);
1802
1803 1 avio_wb32(pb, 0);
1804 1 ffio_wfourcc(pb, "apvC");
1805
1806 1 avio_w8 (pb, 0); /* version */
1807 1 avio_wb24(pb, 0); /* flags */
1808
1809 1 ff_isom_write_apvc(pb, track->apv, s);
1810
1811 1 return update_size(pb, pos);
1812 }
1813
1814 /* also used by all avid codecs (dv, imx, meridien) and their variants */
1815 /* https://community.avid.com/forums/t/136517.aspx */
1816 23 static int mov_write_avid_tag(AVIOContext *pb, MOVTrack *track)
1817 {
1818 int interlaced;
1819 int cid;
1820 23 int display_width = track->par->width;
1821 const uint8_t *extradata;
1822
1823
2/4
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23 times.
✗ Branch 3 not taken.
23 if (track->extradata[track->last_stsd_index] && track->extradata_size[track->last_stsd_index] > 0x29) {
1824
1/2
✓ Branch 1 taken 23 times.
✗ Branch 2 not taken.
46 if (ff_dnxhd_parse_header_prefix(track->extradata[track->last_stsd_index]) != 0) {
1825 /* looks like a DNxHD bit stream */
1826 23 extradata = track->extradata[track->last_stsd_index];
1827 } else {
1828 ✗ av_log(NULL, AV_LOG_WARNING, "Could not locate DNxHD bit stream in vos_data\n");
1829 ✗ return 0;
1830 }
1831 } else {
1832 ✗ av_log(NULL, AV_LOG_WARNING, "Could not locate DNxHD bit stream, vos_data too small\n");
1833 ✗ return 0;
1834 }
1835
1836 23 cid = AV_RB32(extradata + 0x28);
1837
1838 23 avio_wb32(pb, 24); /* size */
1839 23 ffio_wfourcc(pb, "ACLR");
1840 23 ffio_wfourcc(pb, "ACLR");
1841 23 ffio_wfourcc(pb, "0001");
1842 // 1: CCIR (supercolors will be dropped, 16 will be displayed as black)
1843 // 2: FullRange (0 will be displayed as black, 16 will be displayed as dark grey)
1844
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (track->par->color_range == AVCOL_RANGE_MPEG || /* Legal range (16-235) */
1845 ✗ track->par->color_range == AVCOL_RANGE_UNSPECIFIED) {
1846 23 avio_wb32(pb, 1);
1847 } else {
1848 ✗ avio_wb32(pb, 2);
1849 }
1850 23 avio_wb32(pb, 0); /* reserved */
1851
1852
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 11 times.
23 if (track->tag == MKTAG('A','V','d','h')) {
1853 12 int alp = extradata[0x07] & 1;
1854 12 int pma = (extradata[0x07] >> 2) & 1;
1855 12 int sbd = (extradata[0x21] >> 5) & 3;
1856 12 int ssc = (extradata[0x2C] >> 5) & 3;
1857 12 int clv = (extradata[0x2C] >> 1) & 3;
1858 12 int clf = extradata[0x2C] & 1;
1859
1860 12 avio_wb32(pb, 32);
1861 12 ffio_wfourcc(pb, "ADHR");
1862 12 ffio_wfourcc(pb, "0001");
1863 12 avio_wb32(pb, cid); // Compression ID
1864 // 0: 4:2:2 Sub Sampling
1865 // 1: 4:2:0 Sub Sampling
1866 // 2: 4:4:4 Sub Sampling
1867 12 avio_wb32(pb, ssc); // Sub Sampling Control
1868 // 1: 8-bits per sample
1869 // 2: 10-bits per sample
1870 // 3: 12-bits per sample
1871 12 avio_wb32(pb, sbd); // Sample Bit Depth
1872 // 0: Bitstream is encoded using the YCBCR format rules and tables
1873 // 1: Bitstream is encoded using the RGB format rules and tables – only Compression IDs 1256, 1270
1874 12 avio_wb16(pb, clf); // Color Format
1875 // 0: ITU-R BT.709
1876 // 1: ITU-R BT.2020
1877 // 2: ITU-R BT.2020 C
1878 // 3: Out-of-band
1879 12 avio_wb16(pb, clv); // Color Volume
1880 // 0: Alpha channel not present
1881 // 1: Alpha channel present
1882 12 avio_wb16(pb, alp); // Alpha Present
1883 // 0: Alpha has not been applied to video channels
1884 // 1: Alpha has been applied to the video channels prior to encoding
1885 12 avio_wb16(pb, pma); // Pre-Multiplied Alpha
1886 12 return 0;
1887 }
1888
1889 11 interlaced = extradata[5] & 2;
1890
1891 11 avio_wb32(pb, 24); /* size */
1892 11 ffio_wfourcc(pb, "APRG");
1893 11 ffio_wfourcc(pb, "APRG");
1894 11 ffio_wfourcc(pb, "0001");
1895 // 1 for progressive or 2 for interlaced
1896
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (interlaced)
1897 11 avio_wb32(pb, 2);
1898 else
1899 ✗ avio_wb32(pb, 1);
1900 11 avio_wb32(pb, 0); /* reserved */
1901
1902 11 avio_wb32(pb, 120); /* size */
1903 11 ffio_wfourcc(pb, "ARES");
1904 11 ffio_wfourcc(pb, "ARES");
1905 11 ffio_wfourcc(pb, "0001");
1906 11 avio_wb32(pb, cid); /* cid */
1907
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if ( track->par->sample_aspect_ratio.num > 0
1908 ✗ && track->par->sample_aspect_ratio.den > 0)
1909 ✗ display_width = display_width * track->par->sample_aspect_ratio.num / track->par->sample_aspect_ratio.den;
1910 11 avio_wb32(pb, display_width); // field width
1911
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (interlaced) {
1912 11 avio_wb32(pb, track->par->height / 2); // field height
1913 11 avio_wb32(pb, 2); // num fields
1914 11 avio_wb32(pb, 0); // num black lines (must be 0)
1915 // 4: HD1080i
1916 // 5: HD1080P
1917 // 6: HD720P
1918 11 avio_wb32(pb, 4); // video format
1919 } else {
1920 ✗ avio_wb32(pb, track->par->height);
1921 ✗ avio_wb32(pb, 1); // num fields
1922 ✗ avio_wb32(pb, 0);
1923 ✗ if (track->par->height == 1080)
1924 ✗ avio_wb32(pb, 5);
1925 else
1926 ✗ avio_wb32(pb, 6);
1927 }
1928 /* padding */
1929 11 ffio_fill(pb, 0, 10 * 8);
1930
1931 11 return 0;
1932 }
1933
1934 ✗ static int mov_write_dpxe_tag(AVIOContext *pb, MOVTrack *track)
1935 {
1936 ✗ avio_wb32(pb, 12);
1937 ✗ ffio_wfourcc(pb, "DpxE");
1938 ✗ if (track->extradata_size[track->last_stsd_index] >= 12 &&
1939 ✗ !memcmp(&track->extradata[track->last_stsd_index][4], "DpxE", 4)) {
1940 ✗ avio_wb32(pb, track->extradata[track->last_stsd_index][11]);
1941 } else {
1942 ✗ avio_wb32(pb, 1);
1943 }
1944 ✗ return 0;
1945 }
1946
1947 1 static int mov_get_dv_codec_tag(AVFormatContext *s, MOVTrack *track)
1948 {
1949 int tag;
1950
1951
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (track->par->width == 720) { /* SD */
1952
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (track->par->height == 480) { /* NTSC */
1953
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (track->par->format == AV_PIX_FMT_YUV422P) tag = MKTAG('d','v','5','n');
1954 1 else tag = MKTAG('d','v','c',' ');
1955 ✗ }else if (track->par->format == AV_PIX_FMT_YUV422P) tag = MKTAG('d','v','5','p');
1956 ✗ else if (track->par->format == AV_PIX_FMT_YUV420P) tag = MKTAG('d','v','c','p');
1957 ✗ else tag = MKTAG('d','v','p','p');
1958 ✗ } else if (track->par->height == 720) { /* HD 720 line */
1959 ✗ if (track->st->time_base.den == 50) tag = MKTAG('d','v','h','q');
1960 ✗ else tag = MKTAG('d','v','h','p');
1961 ✗ } else if (track->par->height == 1080) { /* HD 1080 line */
1962 ✗ if (track->st->time_base.den == 25) tag = MKTAG('d','v','h','5');
1963 ✗ else tag = MKTAG('d','v','h','6');
1964 } else {
1965 ✗ av_log(s, AV_LOG_ERROR, "unsupported height for dv codec\n");
1966 ✗ return 0;
1967 }
1968
1969 1 return tag;
1970 }
1971
1972 5 static int defined_frame_rate(AVFormatContext *s, AVStream *st)
1973 {
1974 5 AVRational rational_framerate = st->avg_frame_rate;
1975 5 int rate = 0;
1976
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (rational_framerate.den != 0)
1977 5 rate = av_q2d(rational_framerate);
1978 5 return rate;
1979 }
1980
1981 1 static int mov_get_mpeg2_xdcam_codec_tag(AVFormatContext *s, MOVTrack *track)
1982 {
1983 1 int tag = track->par->codec_tag;
1984 1 int interlaced = track->par->field_order > AV_FIELD_PROGRESSIVE;
1985 1 AVStream *st = track->st;
1986 1 int rate = defined_frame_rate(s, st);
1987
1988
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!tag)
1989 ✗ tag = MKTAG('m', '2', 'v', '1'); //fallback tag
1990
1991
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (track->par->format == AV_PIX_FMT_YUV420P) {
1992
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 if (track->par->width == 1280 && track->par->height == 720) {
1993 ✗ if (!interlaced) {
1994 ✗ if (rate == 24) tag = MKTAG('x','d','v','4');
1995 ✗ else if (rate == 25) tag = MKTAG('x','d','v','5');
1996 ✗ else if (rate == 30) tag = MKTAG('x','d','v','1');
1997 ✗ else if (rate == 50) tag = MKTAG('x','d','v','a');
1998 ✗ else if (rate == 60) tag = MKTAG('x','d','v','9');
1999 }
2000
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 } else if (track->par->width == 1440 && track->par->height == 1080) {
2001 ✗ if (!interlaced) {
2002 ✗ if (rate == 24) tag = MKTAG('x','d','v','6');
2003 ✗ else if (rate == 25) tag = MKTAG('x','d','v','7');
2004 ✗ else if (rate == 30) tag = MKTAG('x','d','v','8');
2005 } else {
2006 ✗ if (rate == 25) tag = MKTAG('x','d','v','3');
2007 ✗ else if (rate == 30) tag = MKTAG('x','d','v','2');
2008 }
2009
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 } else if (track->par->width == 1920 && track->par->height == 1080) {
2010 ✗ if (!interlaced) {
2011 ✗ if (rate == 24) tag = MKTAG('x','d','v','d');
2012 ✗ else if (rate == 25) tag = MKTAG('x','d','v','e');
2013 ✗ else if (rate == 30) tag = MKTAG('x','d','v','f');
2014 } else {
2015 ✗ if (rate == 25) tag = MKTAG('x','d','v','c');
2016 ✗ else if (rate == 30) tag = MKTAG('x','d','v','b');
2017 }
2018 }
2019 ✗ } else if (track->par->format == AV_PIX_FMT_YUV422P) {
2020 ✗ if (track->par->width == 1280 && track->par->height == 720) {
2021 ✗ if (!interlaced) {
2022 ✗ if (rate == 24) tag = MKTAG('x','d','5','4');
2023 ✗ else if (rate == 25) tag = MKTAG('x','d','5','5');
2024 ✗ else if (rate == 30) tag = MKTAG('x','d','5','1');
2025 ✗ else if (rate == 50) tag = MKTAG('x','d','5','a');
2026 ✗ else if (rate == 60) tag = MKTAG('x','d','5','9');
2027 }
2028 ✗ } else if (track->par->width == 1920 && track->par->height == 1080) {
2029 ✗ if (!interlaced) {
2030 ✗ if (rate == 24) tag = MKTAG('x','d','5','d');
2031 ✗ else if (rate == 25) tag = MKTAG('x','d','5','e');
2032 ✗ else if (rate == 30) tag = MKTAG('x','d','5','f');
2033 } else {
2034 ✗ if (rate == 25) tag = MKTAG('x','d','5','c');
2035 ✗ else if (rate == 30) tag = MKTAG('x','d','5','b');
2036 }
2037 }
2038 }
2039
2040 1 return tag;
2041 }
2042
2043 4 static int mov_get_h264_codec_tag(AVFormatContext *s, MOVTrack *track)
2044 {
2045 4 int tag = track->par->codec_tag;
2046 4 int interlaced = track->par->field_order > AV_FIELD_PROGRESSIVE;
2047 4 AVStream *st = track->st;
2048 4 int rate = defined_frame_rate(s, st);
2049
2050
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!tag)
2051 ✗ tag = MKTAG('a', 'v', 'c', 'i'); //fallback tag
2052
2053
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (track->par->profile == AV_PROFILE_UNKNOWN ||
2054
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 !(track->par->profile & AV_PROFILE_H264_INTRA))
2055 4 return tag;
2056
2057 ✗ if (track->par->format == AV_PIX_FMT_YUV420P10) {
2058 ✗ if (track->par->width == 960 && track->par->height == 720) {
2059 ✗ if (!interlaced) {
2060 ✗ if (rate == 24) tag = MKTAG('a','i','5','p');
2061 ✗ else if (rate == 25) tag = MKTAG('a','i','5','q');
2062 ✗ else if (rate == 30) tag = MKTAG('a','i','5','p');
2063 ✗ else if (rate == 50) tag = MKTAG('a','i','5','q');
2064 ✗ else if (rate == 60) tag = MKTAG('a','i','5','p');
2065 }
2066 ✗ } else if (track->par->width == 1440 && track->par->height == 1080) {
2067 ✗ if (!interlaced) {
2068 ✗ if (rate == 24) tag = MKTAG('a','i','5','3');
2069 ✗ else if (rate == 25) tag = MKTAG('a','i','5','2');
2070 ✗ else if (rate == 30) tag = MKTAG('a','i','5','3');
2071 } else {
2072 ✗ if (rate == 50) tag = MKTAG('a','i','5','5');
2073 ✗ else if (rate == 60) tag = MKTAG('a','i','5','6');
2074 }
2075 }
2076 ✗ } else if (track->par->format == AV_PIX_FMT_YUV422P10) {
2077 ✗ if (track->par->width == 1280 && track->par->height == 720) {
2078 ✗ if (!interlaced) {
2079 ✗ if (rate == 24) tag = MKTAG('a','i','1','p');
2080 ✗ else if (rate == 25) tag = MKTAG('a','i','1','q');
2081 ✗ else if (rate == 30) tag = MKTAG('a','i','1','p');
2082 ✗ else if (rate == 50) tag = MKTAG('a','i','1','q');
2083 ✗ else if (rate == 60) tag = MKTAG('a','i','1','p');
2084 }
2085 ✗ } else if (track->par->width == 1920 && track->par->height == 1080) {
2086 ✗ if (!interlaced) {
2087 ✗ if (rate == 24) tag = MKTAG('a','i','1','3');
2088 ✗ else if (rate == 25) tag = MKTAG('a','i','1','2');
2089 ✗ else if (rate == 30) tag = MKTAG('a','i','1','3');
2090 } else {
2091 ✗ if (rate == 25) tag = MKTAG('a','i','1','5');
2092 ✗ else if (rate == 50) tag = MKTAG('a','i','1','5');
2093 ✗ else if (rate == 60) tag = MKTAG('a','i','1','6');
2094 }
2095 ✗ } else if ( track->par->width == 4096 && track->par->height == 2160
2096 ✗ || track->par->width == 3840 && track->par->height == 2160
2097 ✗ || track->par->width == 2048 && track->par->height == 1080) {
2098 ✗ tag = MKTAG('a','i','v','x');
2099 }
2100 }
2101
2102 ✗ return tag;
2103 }
2104
2105 ✗ static int mov_get_evc_codec_tag(AVFormatContext *s, MOVTrack *track)
2106 {
2107 ✗ int tag = track->par->codec_tag;
2108
2109 ✗ if (!tag)
2110 ✗ tag = MKTAG('e', 'v', 'c', '1');
2111
2112 ✗ return tag;
2113 }
2114
2115 ✗ static int mov_get_apv_codec_tag(AVFormatContext *s, MOVTrack *track)
2116 {
2117 ✗ int tag = track->par->codec_tag;
2118
2119 ✗ if (!tag)
2120 ✗ tag = MKTAG('a', 'p', 'v', '1');
2121
2122 ✗ return tag;
2123 }
2124
2125
2126 static const struct {
2127 enum AVPixelFormat pix_fmt;
2128 uint32_t tag;
2129 unsigned bps;
2130 } mov_pix_fmt_tags[] = {
2131 { AV_PIX_FMT_YUYV422, MKTAG('y','u','v','2'), 0 },
2132 { AV_PIX_FMT_YUYV422, MKTAG('y','u','v','s'), 0 },
2133 { AV_PIX_FMT_UYVY422, MKTAG('2','v','u','y'), 0 },
2134 { AV_PIX_FMT_VYU444, MKTAG('v','3','0','8'), 0 },
2135 { AV_PIX_FMT_UYVA, MKTAG('v','4','0','8'), 0 },
2136 { AV_PIX_FMT_V30XLE, MKTAG('v','4','1','0'), 0 },
2137 { AV_PIX_FMT_RGB555BE,MKTAG('r','a','w',' '), 16 },
2138 { AV_PIX_FMT_RGB555LE,MKTAG('L','5','5','5'), 16 },
2139 { AV_PIX_FMT_RGB565LE,MKTAG('L','5','6','5'), 16 },
2140 { AV_PIX_FMT_RGB565BE,MKTAG('B','5','6','5'), 16 },
2141 { AV_PIX_FMT_GRAY16BE,MKTAG('b','1','6','g'), 16 },
2142 { AV_PIX_FMT_RGB24, MKTAG('r','a','w',' '), 24 },
2143 { AV_PIX_FMT_BGR24, MKTAG('2','4','B','G'), 24 },
2144 { AV_PIX_FMT_ARGB, MKTAG('r','a','w',' '), 32 },
2145 { AV_PIX_FMT_BGRA, MKTAG('B','G','R','A'), 32 },
2146 { AV_PIX_FMT_RGBA, MKTAG('R','G','B','A'), 32 },
2147 { AV_PIX_FMT_ABGR, MKTAG('A','B','G','R'), 32 },
2148 { AV_PIX_FMT_RGB48BE, MKTAG('b','4','8','r'), 48 },
2149 };
2150
2151 23 static int mov_get_dnxhd_codec_tag(AVFormatContext *s, MOVTrack *track)
2152 {
2153 23 int tag = MKTAG('A','V','d','n');
2154
1/2
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
23 if (track->par->profile != AV_PROFILE_UNKNOWN &&
2155
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 11 times.
23 track->par->profile != AV_PROFILE_DNXHD)
2156 12 tag = MKTAG('A','V','d','h');
2157 23 return tag;
2158 }
2159
2160 17 static int mov_get_rawvideo_codec_tag(AVFormatContext *s, MOVTrack *track)
2161 {
2162 17 int tag = track->par->codec_tag;
2163 int i;
2164 enum AVPixelFormat pix_fmt;
2165
2166
2/2
✓ Branch 0 taken 252 times.
✓ Branch 1 taken 12 times.
264 for (i = 0; i < FF_ARRAY_ELEMS(mov_pix_fmt_tags); i++) {
2167
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 235 times.
252 if (track->par->format == mov_pix_fmt_tags[i].pix_fmt) {
2168 17 tag = mov_pix_fmt_tags[i].tag;
2169 17 track->par->bits_per_coded_sample = mov_pix_fmt_tags[i].bps;
2170
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 12 times.
17 if (track->par->codec_tag == mov_pix_fmt_tags[i].tag)
2171 5 break;
2172 }
2173 }
2174
2175 17 pix_fmt = avpriv_pix_fmt_find(PIX_FMT_LIST_MOV,
2176 17 track->par->bits_per_coded_sample);
2177
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 16 times.
17 if (tag == MKTAG('r','a','w',' ') &&
2178
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 track->par->format != pix_fmt &&
2179 ✗ track->par->format != AV_PIX_FMT_GRAY8 &&
2180 ✗ track->par->format != AV_PIX_FMT_NONE)
2181 ✗ av_log(s, AV_LOG_ERROR, "%s rawvideo cannot be written to mov, output file will be unreadable\n",
2182 ✗ av_get_pix_fmt_name(track->par->format));
2183 17 return tag;
2184 }
2185
2186 178 static unsigned int mov_get_codec_tag(AVFormatContext *s, MOVTrack *track)
2187 {
2188 178 unsigned int tag = track->par->codec_tag;
2189
2190 // "rtp " is used to distinguish internally created RTP-hint tracks
2191 // (with rtp_ctx) from other tracks.
2192
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 178 times.
178 if (tag == MKTAG('r','t','p',' '))
2193 ✗ tag = 0;
2194
3/4
✓ Branch 0 taken 178 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 142 times.
✓ Branch 3 taken 36 times.
178 if (!tag || (s->strict_std_compliance >= FF_COMPLIANCE_NORMAL &&
2195
2/2
✓ Branch 0 taken 141 times.
✓ Branch 1 taken 1 times.
142 (track->par->codec_id == AV_CODEC_ID_DVVIDEO ||
2196
2/2
✓ Branch 0 taken 124 times.
✓ Branch 1 taken 17 times.
141 track->par->codec_id == AV_CODEC_ID_RAWVIDEO ||
2197
1/2
✓ Branch 0 taken 124 times.
✗ Branch 1 not taken.
124 track->par->codec_id == AV_CODEC_ID_H263 ||
2198
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 4 times.
124 track->par->codec_id == AV_CODEC_ID_H264 ||
2199
2/2
✓ Branch 0 taken 97 times.
✓ Branch 1 taken 23 times.
120 track->par->codec_id == AV_CODEC_ID_DNXHD ||
2200
4/4
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 22 times.
✓ Branch 3 taken 74 times.
193 track->par->codec_id == AV_CODEC_ID_MPEG2VIDEO ||
2201 96 av_get_bits_per_sample(track->par->codec_id)))) { // pcm audio
2202
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 67 times.
68 if (track->par->codec_id == AV_CODEC_ID_DVVIDEO)
2203 1 tag = mov_get_dv_codec_tag(s, track);
2204
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 50 times.
67 else if (track->par->codec_id == AV_CODEC_ID_RAWVIDEO)
2205 17 tag = mov_get_rawvideo_codec_tag(s, track);
2206
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 49 times.
50 else if (track->par->codec_id == AV_CODEC_ID_MPEG2VIDEO)
2207 1 tag = mov_get_mpeg2_xdcam_codec_tag(s, track);
2208
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 45 times.
49 else if (track->par->codec_id == AV_CODEC_ID_H264)
2209 4 tag = mov_get_h264_codec_tag(s, track);
2210
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 else if (track->par->codec_id == AV_CODEC_ID_EVC)
2211 ✗ tag = mov_get_evc_codec_tag(s, track);
2212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 else if (track->par->codec_id == AV_CODEC_ID_APV)
2213 ✗ tag = mov_get_apv_codec_tag(s, track);
2214
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 22 times.
45 else if (track->par->codec_id == AV_CODEC_ID_DNXHD)
2215 23 tag = mov_get_dnxhd_codec_tag(s, track);
2216
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 else if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
2217 ✗ tag = ff_codec_get_tag(ff_codec_movvideo_tags, track->par->codec_id);
2218 ✗ if (!tag) { // if no mac fcc found, try with Microsoft tags
2219 ✗ tag = ff_codec_get_tag(ff_codec_bmp_tags, track->par->codec_id);
2220 ✗ if (tag)
2221 ✗ av_log(s, AV_LOG_WARNING, "Using MS style video codec tag, "
2222 "the file may be unplayable!\n");
2223 }
2224
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) {
2225 22 tag = ff_codec_get_tag(ff_codec_movaudio_tags, track->par->codec_id);
2226
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 if (!tag) { // if no mac fcc found, try with Microsoft tags
2227 ✗ int ms_tag = ff_codec_get_tag(ff_codec_wav_tags, track->par->codec_id);
2228 ✗ if (ms_tag) {
2229 ✗ tag = MKTAG('m', 's', ((ms_tag >> 8) & 0xff), (ms_tag & 0xff));
2230 ✗ av_log(s, AV_LOG_WARNING, "Using MS style audio codec tag, "
2231 "the file may be unplayable!\n");
2232 }
2233 }
2234 ✗ } else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE)
2235 ✗ tag = ff_codec_get_tag(ff_codec_movsubtitle_tags, track->par->codec_id);
2236 }
2237
2238 178 return tag;
2239 }
2240
2241 static const AVCodecTag codec_cover_image_tags[] = {
2242 { AV_CODEC_ID_MJPEG, 0xD },
2243 { AV_CODEC_ID_PNG, 0xE },
2244 { AV_CODEC_ID_BMP, 0x1B },
2245 { AV_CODEC_ID_NONE, 0 },
2246 };
2247
2248 239 static unsigned int validate_codec_tag(const AVCodecTag *const *tags,
2249 unsigned int tag, int codec_id)
2250 {
2251 int i;
2252
2253 /**
2254 * Check that tag + id is in the table
2255 */
2256
2/4
✓ Branch 0 taken 239 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 239 times.
✗ Branch 3 not taken.
239 for (i = 0; tags && tags[i]; i++) {
2257 239 const AVCodecTag *codec_tags = tags[i];
2258
1/2
✓ Branch 0 taken 5031 times.
✗ Branch 1 not taken.
5031 while (codec_tags->id != AV_CODEC_ID_NONE) {
2259
2/2
✓ Branch 2 taken 561 times.
✓ Branch 3 taken 4470 times.
5031 if (ff_toupper4(codec_tags->tag) == ff_toupper4(tag) &&
2260
2/2
✓ Branch 0 taken 239 times.
✓ Branch 1 taken 322 times.
561 codec_tags->id == codec_id)
2261 239 return codec_tags->tag;
2262 4792 codec_tags++;
2263 }
2264 }
2265 ✗ return 0;
2266 }
2267
2268 419 static unsigned int mov_find_codec_tag(AVFormatContext *s, MOVTrack *track)
2269 {
2270
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 417 times.
419 if (is_cover_image(track->st))
2271 2 return ff_codec_get_tag(codec_cover_image_tags, track->par->codec_id);
2272
2273
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 416 times.
417 if (track->mode == MODE_IPOD)
2274
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
2 if (!av_match_ext(s->url, "m4a") &&
2275
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 !av_match_ext(s->url, "m4v") &&
2276 1 !av_match_ext(s->url, "m4b"))
2277 1 av_log(s, AV_LOG_WARNING, "Warning, extension is not .m4a nor .m4v "
2278 "Quicktime/Ipod might not play the file\n");
2279
2280
2/2
✓ Branch 0 taken 178 times.
✓ Branch 1 taken 239 times.
417 if (track->mode == MODE_MOV) {
2281 178 return mov_get_codec_tag(s, track);
2282 } else
2283 239 return validate_codec_tag(s->oformat->codec_tag, track->par->codec_tag,
2284 239 track->par->codec_id);
2285 }
2286
2287 /** Write uuid atom.
2288 * Needed to make file play in iPods running newest firmware
2289 * goes after avcC atom in moov.trak.mdia.minf.stbl.stsd.avc1
2290 */
2291 ✗ static int mov_write_uuid_tag_ipod(AVIOContext *pb)
2292 {
2293 ✗ avio_wb32(pb, 28);
2294 ✗ ffio_wfourcc(pb, "uuid");
2295 ✗ avio_wb32(pb, 0x6b6840f2);
2296 ✗ avio_wb32(pb, 0x5f244fc5);
2297 ✗ avio_wb32(pb, 0xba39a51b);
2298 ✗ avio_wb32(pb, 0xcf0323f3);
2299 ✗ avio_wb32(pb, 0x0);
2300 ✗ return 28;
2301 }
2302
2303 static const uint16_t fiel_data[] = {
2304 0x0000, 0x0100, 0x0201, 0x0206, 0x0209, 0x020e
2305 };
2306
2307 101 static int mov_write_fiel_tag(AVIOContext *pb, MOVTrack *track, int field_order)
2308 {
2309 101 unsigned mov_field_order = 0;
2310
1/2
✓ Branch 0 taken 101 times.
✗ Branch 1 not taken.
101 if (field_order < FF_ARRAY_ELEMS(fiel_data))
2311 101 mov_field_order = fiel_data[field_order];
2312 else
2313 ✗ return 0;
2314 101 avio_wb32(pb, 10);
2315 101 ffio_wfourcc(pb, "fiel");
2316 101 avio_wb16(pb, mov_field_order);
2317 101 return 10;
2318 }
2319
2320 6 static int mov_write_subtitle_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
2321 {
2322 6 MOVMuxContext *mov = s->priv_data;
2323 6 int ret = AVERROR_BUG;
2324 6 int64_t pos = avio_tell(pb);
2325 6 avio_wb32(pb, 0); /* size */
2326 6 avio_wl32(pb, track->tag); // store it byteswapped
2327 6 avio_wb32(pb, 0); /* Reserved */
2328 6 avio_wb16(pb, 0); /* Reserved */
2329 6 avio_wb16(pb, 1); /* Data-reference index */
2330
2331
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (track->par->codec_id == AV_CODEC_ID_DVD_SUBTITLE)
2332 ✗ mov_write_esds_tag(pb, track);
2333
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 else if (track->par->codec_id == AV_CODEC_ID_TTML) {
2334
2/3
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 switch (track->par->codec_tag) {
2335 2 case MOV_ISMV_TTML_TAG:
2336 // ISMV dfxp requires no extradata.
2337 4 break;
2338 2 case MOV_MP4_TTML_TAG:
2339 // As specified in 14496-30, XMLSubtitleSampleEntry
2340 // Namespace
2341 2 avio_put_str(pb, "http://www.w3.org/ns/ttml");
2342 // Empty schema_location
2343 2 avio_w8(pb, 0);
2344 // Empty auxiliary_mime_types
2345 2 avio_w8(pb, 0);
2346 2 break;
2347 ✗ default:
2348 ✗ av_log(NULL, AV_LOG_ERROR,
2349 "Unknown codec tag '%s' utilized for TTML stream with "
2350 "index %d (track id %d)!\n",
2351 ✗ av_fourcc2str(track->par->codec_tag), track->st->index,
2352 track->track_id);
2353 ✗ return AVERROR(EINVAL);
2354 }
2355
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 } else if (track->extradata_size[track->last_stsd_index])
2356 2 avio_write(pb, track->extradata[track->last_stsd_index], track->extradata_size[track->last_stsd_index]);
2357
2358
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
11 if (mov->write_btrt &&
2359 5 ((ret = mov_write_btrt_tag(pb, track)) < 0))
2360 ✗ return ret;
2361
2362 6 return update_size(pb, pos);
2363 }
2364
2365 1 static int mov_write_st3d_tag(AVFormatContext *s, AVIOContext *pb, AVStereo3D *stereo_3d)
2366 {
2367 int8_t stereo_mode;
2368
2369
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (stereo_3d->flags != 0) {
2370 ✗ av_log(s, AV_LOG_WARNING, "Unsupported stereo_3d flags %x. st3d not written.\n", stereo_3d->flags);
2371 ✗ return 0;
2372 }
2373
2374
1/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 switch (stereo_3d->type) {
2375 ✗ case AV_STEREO3D_2D:
2376 ✗ stereo_mode = 0;
2377 ✗ break;
2378 ✗ case AV_STEREO3D_TOPBOTTOM:
2379 ✗ stereo_mode = 1;
2380 ✗ break;
2381 1 case AV_STEREO3D_SIDEBYSIDE:
2382 1 stereo_mode = 2;
2383 1 break;
2384 ✗ default:
2385 ✗ av_log(s, AV_LOG_WARNING, "Unsupported stereo_3d type %s. st3d not written.\n", av_stereo3d_type_name(stereo_3d->type));
2386 ✗ return 0;
2387 }
2388 1 avio_wb32(pb, 13); /* size */
2389 1 ffio_wfourcc(pb, "st3d");
2390 1 avio_wb32(pb, 0); /* version = 0 & flags = 0 */
2391 1 avio_w8(pb, stereo_mode);
2392 1 return 13;
2393 }
2394
2395 ✗ static int mov_write_sv3d_tag(AVFormatContext *s, AVIOContext *pb, AVSphericalMapping *spherical_mapping)
2396 {
2397 int64_t sv3d_pos, svhd_pos, proj_pos;
2398 ✗ const char* metadata_source = s->flags & AVFMT_FLAG_BITEXACT ? "Lavf" : LIBAVFORMAT_IDENT;
2399
2400 ✗ if (spherical_mapping->projection != AV_SPHERICAL_EQUIRECTANGULAR &&
2401 ✗ spherical_mapping->projection != AV_SPHERICAL_EQUIRECTANGULAR_TILE &&
2402 ✗ spherical_mapping->projection != AV_SPHERICAL_CUBEMAP) {
2403 ✗ av_log(s, AV_LOG_WARNING, "Unsupported projection %d. sv3d not written.\n", spherical_mapping->projection);
2404 ✗ return 0;
2405 }
2406
2407 ✗ sv3d_pos = avio_tell(pb);
2408 ✗ avio_wb32(pb, 0); /* size */
2409 ✗ ffio_wfourcc(pb, "sv3d");
2410
2411 ✗ svhd_pos = avio_tell(pb);
2412 ✗ avio_wb32(pb, 0); /* size */
2413 ✗ ffio_wfourcc(pb, "svhd");
2414 ✗ avio_wb32(pb, 0); /* version = 0 & flags = 0 */
2415 ✗ avio_put_str(pb, metadata_source);
2416 ✗ update_size(pb, svhd_pos);
2417
2418 ✗ proj_pos = avio_tell(pb);
2419 ✗ avio_wb32(pb, 0); /* size */
2420 ✗ ffio_wfourcc(pb, "proj");
2421
2422 ✗ avio_wb32(pb, 24); /* size */
2423 ✗ ffio_wfourcc(pb, "prhd");
2424 ✗ avio_wb32(pb, 0); /* version = 0 & flags = 0 */
2425 ✗ avio_wb32(pb, spherical_mapping->yaw);
2426 ✗ avio_wb32(pb, spherical_mapping->pitch);
2427 ✗ avio_wb32(pb, spherical_mapping->roll);
2428
2429 ✗ switch (spherical_mapping->projection) {
2430 ✗ case AV_SPHERICAL_EQUIRECTANGULAR:
2431 case AV_SPHERICAL_EQUIRECTANGULAR_TILE:
2432 ✗ avio_wb32(pb, 28); /* size */
2433 ✗ ffio_wfourcc(pb, "equi");
2434 ✗ avio_wb32(pb, 0); /* version = 0 & flags = 0 */
2435 ✗ avio_wb32(pb, spherical_mapping->bound_top);
2436 ✗ avio_wb32(pb, spherical_mapping->bound_bottom);
2437 ✗ avio_wb32(pb, spherical_mapping->bound_left);
2438 ✗ avio_wb32(pb, spherical_mapping->bound_right);
2439 ✗ break;
2440 ✗ case AV_SPHERICAL_CUBEMAP:
2441 ✗ avio_wb32(pb, 20); /* size */
2442 ✗ ffio_wfourcc(pb, "cbmp");
2443 ✗ avio_wb32(pb, 0); /* version = 0 & flags = 0 */
2444 ✗ avio_wb32(pb, 0); /* layout */
2445 ✗ avio_wb32(pb, spherical_mapping->padding); /* padding */
2446 ✗ break;
2447 }
2448 ✗ update_size(pb, proj_pos);
2449
2450 ✗ return update_size(pb, sv3d_pos);
2451 }
2452
2453 5 static inline int64_t rescale_rational(AVRational q, int b)
2454 {
2455 5 return av_rescale(q.num, b, q.den);
2456 }
2457
2458 2 static void mov_write_hfov_tag(AVFormatContext *s, AVIOContext *pb,
2459 const AVStereo3D *stereo3d)
2460 {
2461
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (!stereo3d->horizontal_field_of_view.num)
2462 1 return;
2463
2464 1 avio_wb32(pb, 12); /* size */
2465 1 ffio_wfourcc(pb, "hfov");
2466 1 avio_wb32(pb, rescale_rational(stereo3d->horizontal_field_of_view, 1000));
2467 }
2468
2469 1 static void mov_write_vexu_proj_tag(AVFormatContext *s, AVIOContext *pb,
2470 const AVSphericalMapping *spherical_mapping)
2471 {
2472 1 avio_wb32(pb, 24); /* size */
2473 1 ffio_wfourcc(pb, "proj");
2474 1 avio_wb32(pb, 16); /* size */
2475 1 ffio_wfourcc(pb, "prji");
2476 1 avio_wb32(pb, 0); /* version + flags */
2477
2478
1/5
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 switch (spherical_mapping->projection) {
2479 1 case AV_SPHERICAL_RECTILINEAR:
2480 1 ffio_wfourcc(pb, "rect");
2481 1 break;
2482 ✗ case AV_SPHERICAL_EQUIRECTANGULAR:
2483 ✗ ffio_wfourcc(pb, "equi");
2484 ✗ break;
2485 ✗ case AV_SPHERICAL_HALF_EQUIRECTANGULAR:
2486 ✗ ffio_wfourcc(pb, "hequ");
2487 ✗ break;
2488 ✗ case AV_SPHERICAL_FISHEYE:
2489 ✗ ffio_wfourcc(pb, "fish");
2490 ✗ break;
2491 ✗ default:
2492 ✗ av_assert0(0);
2493 }
2494 1 }
2495
2496 2 static int mov_write_eyes_tag(AVFormatContext *s, AVIOContext *pb,
2497 const AVStereo3D *stereo3d)
2498 {
2499 2 int64_t pos = avio_tell(pb);
2500 2 int view = 0;
2501
2502 2 avio_wb32(pb, 0); /* size */
2503 2 ffio_wfourcc(pb, "eyes");
2504
2505 // stri is mandatory
2506 2 avio_wb32(pb, 13); /* size */
2507 2 ffio_wfourcc(pb, "stri");
2508 2 avio_wb32(pb, 0); /* version + flags */
2509
1/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 switch (stereo3d->view) {
2510 ✗ case AV_STEREO3D_VIEW_LEFT:
2511 ✗ view |= 1 << 0;
2512 ✗ break;
2513 ✗ case AV_STEREO3D_VIEW_RIGHT:
2514 ✗ view |= 1 << 1;
2515 ✗ break;
2516 2 case AV_STEREO3D_VIEW_PACKED:
2517 2 view |= (1 << 0) | (1 << 1);
2518 2 break;
2519 }
2520 2 view |= !!(stereo3d->flags & AV_STEREO3D_FLAG_INVERT) << 3;
2521 2 avio_w8(pb, view);
2522
2523 // hero is optional
2524
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (stereo3d->primary_eye != AV_PRIMARY_EYE_NONE) {
2525 ✗ avio_wb32(pb, 13); /* size */
2526 ✗ ffio_wfourcc(pb, "hero");
2527 ✗ avio_wb32(pb, 0); /* version + flags */
2528 ✗ avio_w8(pb, stereo3d->primary_eye);
2529 }
2530
2531 // it's not clear if cams is mandatory or optional
2532
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (stereo3d->baseline) {
2533 1 avio_wb32(pb, 24); /* size */
2534 1 ffio_wfourcc(pb, "cams");
2535 1 avio_wb32(pb, 16); /* size */
2536 1 ffio_wfourcc(pb, "blin");
2537 1 avio_wb32(pb, 0); /* version + flags */
2538 1 avio_wb32(pb, stereo3d->baseline);
2539 }
2540
2541 // it's not clear if cmfy is mandatory or optional
2542
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (stereo3d->horizontal_disparity_adjustment.num) {
2543 1 avio_wb32(pb, 24); /* size */
2544 1 ffio_wfourcc(pb, "cmfy");
2545 1 avio_wb32(pb, 16); /* size */
2546 1 ffio_wfourcc(pb, "dadj");
2547 1 avio_wb32(pb, 0); /* version + flags */
2548 1 avio_wb32(pb, rescale_rational(stereo3d->horizontal_disparity_adjustment, 10000));
2549 }
2550
2551 2 return update_size(pb, pos);
2552 }
2553
2554 2 static int mov_write_vexu_tag(AVFormatContext *s, AVIOContext *pb,
2555 const AVStereo3D *stereo3d,
2556 const AVSphericalMapping *spherical_mapping)
2557 {
2558 int64_t pos;
2559
2560
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (spherical_mapping &&
2561
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 spherical_mapping->projection != AV_SPHERICAL_RECTILINEAR &&
2562 ✗ spherical_mapping->projection != AV_SPHERICAL_EQUIRECTANGULAR &&
2563 ✗ spherical_mapping->projection != AV_SPHERICAL_HALF_EQUIRECTANGULAR &&
2564 ✗ spherical_mapping->projection != AV_SPHERICAL_FISHEYE) {
2565 ✗ av_log(s, AV_LOG_WARNING, "Unsupported projection %d. proj not written.\n",
2566 ✗ spherical_mapping->projection);
2567 ✗ spherical_mapping = NULL;
2568 }
2569
2570
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 if (stereo3d && (stereo3d->type == AV_STEREO3D_2D ||
2571
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 (!(stereo3d->flags & AV_STEREO3D_FLAG_INVERT) &&
2572
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 stereo3d->view == AV_STEREO3D_VIEW_UNSPEC &&
2573 ✗ stereo3d->primary_eye == AV_PRIMARY_EYE_NONE &&
2574 ✗ !stereo3d->baseline &&
2575 ✗ !stereo3d->horizontal_disparity_adjustment.num))) {
2576 ✗ av_log(s, AV_LOG_WARNING, "Unsupported stereo 3d metadata. eyes not written.\n");
2577 ✗ stereo3d = NULL;
2578 }
2579
2580
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
2 if (!spherical_mapping && !stereo3d)
2581 ✗ return 0;
2582
2583 2 pos = avio_tell(pb);
2584 2 avio_wb32(pb, 0); /* size */
2585 2 ffio_wfourcc(pb, "vexu");
2586
2587
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (spherical_mapping)
2588 1 mov_write_vexu_proj_tag(s, pb, spherical_mapping);
2589
2590
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (stereo3d)
2591 2 mov_write_eyes_tag(s, pb, stereo3d);
2592
2593 2 return update_size(pb, pos);
2594 }
2595
2596 2 static int mov_write_dvcc_dvvc_tag(AVFormatContext *s, AVIOContext *pb, AVDOVIDecoderConfigurationRecord *dovi)
2597 {
2598 uint8_t buf[ISOM_DVCC_DVVC_SIZE];
2599
2600 2 avio_wb32(pb, 32); /* size = 8 + 24 */
2601
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (dovi->dv_profile > 10)
2602 ✗ ffio_wfourcc(pb, "dvwC");
2603
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (dovi->dv_profile > 7)
2604 ✗ ffio_wfourcc(pb, "dvvC");
2605 else
2606 2 ffio_wfourcc(pb, "dvcC");
2607
2608 2 ff_isom_put_dvcc_dvvc(s, buf, dovi);
2609 2 avio_write(pb, buf, sizeof(buf));
2610
2611 2 return 32; /* 8 + 24 */
2612 }
2613
2614 2 static int mov_write_hvce_tag(AVIOContext *pb, const AVPacketSideData *sd)
2615 {
2616 2 avio_wb32(pb, 8 + sd->size);
2617 2 ffio_wfourcc(pb, "hvcE");
2618 2 avio_write(pb, sd->data, sd->size);
2619 2 return 8 + sd->size;
2620 }
2621
2622 5 static int mov_write_clap_tag(AVIOContext *pb, MOVTrack *track,
2623 uint32_t top, uint32_t bottom,
2624 uint32_t left, uint32_t right)
2625 {
2626 5 uint32_t cropped_width = track->par->width - left - right;
2627 5 uint32_t cropped_height = track->height - top - bottom;
2628 AVRational horizOff =
2629 5 av_sub_q((AVRational) { track->par->width - cropped_width, 2 },
2630 5 (AVRational) { left, 1 });
2631 AVRational vertOff =
2632 5 av_sub_q((AVRational) { track->height - cropped_height, 2 },
2633 5 (AVRational) { top, 1 });
2634
2635 5 avio_wb32(pb, 40);
2636 5 ffio_wfourcc(pb, "clap");
2637 5 avio_wb32(pb, cropped_width); /* apertureWidthN */
2638 5 avio_wb32(pb, 1); /* apertureWidthD */
2639 5 avio_wb32(pb, cropped_height); /* apertureHeightN */
2640 5 avio_wb32(pb, 1); /* apertureHeightD */
2641
2642 5 avio_wb32(pb, -horizOff.num);
2643 5 avio_wb32(pb, horizOff.den);
2644 5 avio_wb32(pb, -vertOff.num);
2645 5 avio_wb32(pb, vertOff.den);
2646
2647 5 return 40;
2648 }
2649
2650 29 static int mov_write_pasp_tag(AVIOContext *pb, MOVTrack *track)
2651 {
2652 AVRational sar;
2653 29 av_reduce(&sar.num, &sar.den, track->par->sample_aspect_ratio.num,
2654 29 track->par->sample_aspect_ratio.den, INT_MAX);
2655
2656 29 avio_wb32(pb, 16);
2657 29 ffio_wfourcc(pb, "pasp");
2658 29 avio_wb32(pb, sar.num);
2659 29 avio_wb32(pb, sar.den);
2660 29 return 16;
2661 }
2662
2663 ✗ static int mov_write_gama_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track, double gamma)
2664 {
2665 ✗ uint32_t gama = 0;
2666 ✗ if (gamma <= 0.0)
2667 ✗ gamma = av_csp_approximate_eotf_gamma(track->par->color_trc);
2668 ✗ av_log(s, AV_LOG_DEBUG, "gamma value %g\n", gamma);
2669
2670 ✗ if (gamma > 1e-6) {
2671 ✗ gama = (uint32_t)lrint((double)(1<<16) * gamma);
2672 ✗ av_log(s, AV_LOG_DEBUG, "writing gama value %"PRId32"\n", gama);
2673
2674 ✗ av_assert0(track->mode == MODE_MOV);
2675 ✗ avio_wb32(pb, 12);
2676 ✗ ffio_wfourcc(pb, "gama");
2677 ✗ avio_wb32(pb, gama);
2678 ✗ return 12;
2679 } else {
2680 ✗ av_log(s, AV_LOG_WARNING, "gamma value unknown, unable to write gama atom\n");
2681 }
2682 ✗ return 0;
2683 }
2684
2685 16 static int mov_write_colr_tag(AVIOContext *pb, MOVTrack *track, int prefer_icc)
2686 {
2687 16 int64_t pos = avio_tell(pb);
2688
2689 // Ref (MOV): https://developer.apple.com/library/mac/technotes/tn2162/_index.html#//apple_ref/doc/uid/DTS40013070-CH1-TNTAG9
2690 // Ref (MP4): ISO/IEC 14496-12:2012
2691
2692
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 12 times.
16 if (prefer_icc) {
2693 4 const AVPacketSideData *sd = av_packet_side_data_get(track->st->codecpar->coded_side_data,
2694 4 track->st->codecpar->nb_coded_side_data,
2695 AV_PKT_DATA_ICC_PROFILE);
2696
2697
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (sd) {
2698 ✗ avio_wb32(pb, 12 + sd->size);
2699 ✗ ffio_wfourcc(pb, "colr");
2700 ✗ ffio_wfourcc(pb, "prof");
2701 ✗ avio_write(pb, sd->data, sd->size);
2702 ✗ return 12 + sd->size;
2703 }
2704 else {
2705 4 av_log(NULL, AV_LOG_INFO, "no ICC profile found, will write nclx/nclc colour info instead\n");
2706 }
2707 }
2708
2709 /* We should only ever be called for MOV, MP4 and AVIF. */
2710
5/6
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
16 av_assert0(track->mode == MODE_MOV || track->mode == MODE_MP4 ||
2711 track->mode == MODE_AVIF);
2712
2713 16 avio_wb32(pb, 0); /* size */
2714 16 ffio_wfourcc(pb, "colr");
2715
4/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 10 times.
16 if (track->mode == MODE_MP4 || track->mode == MODE_AVIF)
2716 6 ffio_wfourcc(pb, "nclx");
2717 else
2718 10 ffio_wfourcc(pb, "nclc");
2719 // Do not try to guess the color info if it is AVCOL_PRI_UNSPECIFIED.
2720 // e.g., Dolby Vision for Apple devices should be set to AVCOL_PRI_UNSPECIFIED. See
2721 // https://developer.apple.com/av-foundation/High-Dynamic-Range-Metadata-for-Apple-Devices.pdf
2722 16 avio_wb16(pb, track->par->color_primaries);
2723 16 avio_wb16(pb, track->par->color_trc);
2724 16 avio_wb16(pb, track->par->color_space);
2725
4/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 10 times.
16 if (track->mode == MODE_MP4 || track->mode == MODE_AVIF) {
2726 6 int full_range = track->par->color_range == AVCOL_RANGE_JPEG;
2727 6 avio_w8(pb, full_range << 7);
2728 }
2729
2730 16 return update_size(pb, pos);
2731 }
2732
2733 233 static int mov_write_clli_tag(AVIOContext *pb, MOVTrack *track)
2734 {
2735 const AVPacketSideData *side_data;
2736 const AVContentLightMetadata *content_light_metadata;
2737
2738 233 side_data = av_packet_side_data_get(track->st->codecpar->coded_side_data,
2739 233 track->st->codecpar->nb_coded_side_data,
2740 AV_PKT_DATA_CONTENT_LIGHT_LEVEL);
2741
1/2
✓ Branch 0 taken 233 times.
✗ Branch 1 not taken.
233 if (!side_data) {
2742 233 return 0;
2743 }
2744 ✗ content_light_metadata = (const AVContentLightMetadata*)side_data->data;
2745
2746 ✗ avio_wb32(pb, 12); // size
2747 ✗ ffio_wfourcc(pb, "clli");
2748 ✗ avio_wb16(pb, content_light_metadata->MaxCLL);
2749 ✗ avio_wb16(pb, content_light_metadata->MaxFALL);
2750 ✗ return 12;
2751 }
2752
2753 233 static int mov_write_mdcv_tag(AVIOContext *pb, MOVTrack *track)
2754 {
2755 233 const int chroma_den = 50000;
2756 233 const int luma_den = 10000;
2757 const AVPacketSideData *side_data;
2758 233 const AVMasteringDisplayMetadata *metadata = NULL;
2759
2760 233 side_data = av_packet_side_data_get(track->st->codecpar->coded_side_data,
2761 233 track->st->codecpar->nb_coded_side_data,
2762 AV_PKT_DATA_MASTERING_DISPLAY_METADATA);
2763
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 233 times.
233 if (side_data)
2764 ✗ metadata = (const AVMasteringDisplayMetadata*)side_data->data;
2765
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 233 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
233 if (!metadata || !metadata->has_primaries || !metadata->has_luminance) {
2766 233 return 0;
2767 }
2768
2769 ✗ avio_wb32(pb, 32); // size
2770 ✗ ffio_wfourcc(pb, "mdcv");
2771 ✗ avio_wb16(pb, rescale_rational(metadata->display_primaries[1][0], chroma_den));
2772 ✗ avio_wb16(pb, rescale_rational(metadata->display_primaries[1][1], chroma_den));
2773 ✗ avio_wb16(pb, rescale_rational(metadata->display_primaries[2][0], chroma_den));
2774 ✗ avio_wb16(pb, rescale_rational(metadata->display_primaries[2][1], chroma_den));
2775 ✗ avio_wb16(pb, rescale_rational(metadata->display_primaries[0][0], chroma_den));
2776 ✗ avio_wb16(pb, rescale_rational(metadata->display_primaries[0][1], chroma_den));
2777 ✗ avio_wb16(pb, rescale_rational(metadata->white_point[0], chroma_den));
2778 ✗ avio_wb16(pb, rescale_rational(metadata->white_point[1], chroma_den));
2779 ✗ avio_wb32(pb, rescale_rational(metadata->max_luminance, luma_den));
2780 ✗ avio_wb32(pb, rescale_rational(metadata->min_luminance, luma_den));
2781 ✗ return 32;
2782 }
2783
2784 233 static int mov_write_amve_tag(AVIOContext *pb, MOVTrack *track)
2785 {
2786 233 const int illuminance_den = 10000;
2787 233 const int ambient_den = 50000;
2788 const AVPacketSideData *side_data;
2789 const AVAmbientViewingEnvironment *ambient;
2790
2791
2792 233 side_data = av_packet_side_data_get(track->st->codecpar->coded_side_data,
2793 233 track->st->codecpar->nb_coded_side_data,
2794 AV_PKT_DATA_AMBIENT_VIEWING_ENVIRONMENT);
2795
2796
2/2
✓ Branch 0 taken 232 times.
✓ Branch 1 taken 1 times.
233 if (!side_data)
2797 232 return 0;
2798
2799 1 ambient = (const AVAmbientViewingEnvironment*)side_data->data;
2800
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (!ambient || !ambient->ambient_illuminance.num)
2801 ✗ return 0;
2802
2803 1 avio_wb32(pb, 16); // size
2804 1 ffio_wfourcc(pb, "amve");
2805 1 avio_wb32(pb, rescale_rational(ambient->ambient_illuminance, illuminance_den));
2806 1 avio_wb16(pb, rescale_rational(ambient->ambient_light_x, ambient_den));
2807 1 avio_wb16(pb, rescale_rational(ambient->ambient_light_y, ambient_den));
2808 1 return 16;
2809 }
2810
2811 240 static void find_compressor(char * compressor_name, int len, MOVTrack *track)
2812 {
2813 AVDictionaryEntry *encoder;
2814
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 int xdcam_res = (track->par->width == 1280 && track->par->height == 720)
2815
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 239 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
239 || (track->par->width == 1440 && track->par->height == 1080)
2816
5/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 239 times.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 226 times.
✓ Branch 4 taken 13 times.
✗ Branch 5 not taken.
480 || (track->par->width == 1920 && track->par->height == 1080);
2817
2818
2/2
✓ Branch 0 taken 239 times.
✓ Branch 1 taken 1 times.
240 if ((track->mode == MODE_AVIF ||
2819
2/2
✓ Branch 0 taken 93 times.
✓ Branch 1 taken 146 times.
239 track->mode == MODE_MOV ||
2820
4/4
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 162 times.
✓ Branch 3 taken 72 times.
327 track->mode == MODE_MP4) &&
2821 234 (encoder = av_dict_get(track->st->metadata, "encoder", NULL, 0))) {
2822 162 av_strlcpy(compressor_name, encoder->value, 32);
2823
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 77 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
78 } else if (track->par->codec_id == AV_CODEC_ID_MPEG2VIDEO && xdcam_res) {
2824 ✗ int interlaced = track->par->field_order > AV_FIELD_PROGRESSIVE;
2825 ✗ AVStream *st = track->st;
2826 ✗ int rate = defined_frame_rate(NULL, st);
2827 ✗ av_strlcatf(compressor_name, len, "XDCAM");
2828 ✗ if (track->par->format == AV_PIX_FMT_YUV422P) {
2829 ✗ av_strlcatf(compressor_name, len, " HD422");
2830 ✗ } else if(track->par->width == 1440) {
2831 ✗ av_strlcatf(compressor_name, len, " HD");
2832 } else
2833 ✗ av_strlcatf(compressor_name, len, " EX");
2834
2835 ✗ av_strlcatf(compressor_name, len, " %d%c", track->par->height, interlaced ? 'i' : 'p');
2836
2837 ✗ av_strlcatf(compressor_name, len, "%d", rate * (interlaced + 1));
2838 }
2839 240 }
2840
2841 #if CONFIG_AVIF_MUXER
2842 1 static int mov_write_ccst_tag(AVIOContext *pb)
2843 {
2844 1 int64_t pos = avio_tell(pb);
2845 // Write sane defaults:
2846 // all_ref_pics_intra = 0 : all samples can use any type of reference.
2847 // intra_pred_used = 1 : intra prediction may or may not be used.
2848 // max_ref_per_pic = 15 : reserved value to indicate that any number of
2849 // reference images can be used.
2850 1 uint8_t ccstValue = (0 << 7) | /* all_ref_pics_intra */
2851 (1 << 6) | /* intra_pred_used */
2852 (15 << 2); /* max_ref_per_pic */
2853 1 avio_wb32(pb, 0); /* size */
2854 1 ffio_wfourcc(pb, "ccst");
2855 1 avio_wb32(pb, 0); /* Version & flags */
2856 1 avio_w8(pb, ccstValue);
2857 1 avio_wb24(pb, 0); /* reserved */
2858 1 return update_size(pb, pos);
2859 }
2860
2861 ✗ static int mov_write_aux_tag(AVIOContext *pb, const char *aux_type)
2862 {
2863 ✗ int64_t pos = avio_tell(pb);
2864 ✗ avio_wb32(pb, 0); /* size */
2865 ✗ ffio_wfourcc(pb, aux_type);
2866 ✗ avio_wb32(pb, 0); /* Version & flags */
2867 ✗ avio_write(pb, "urn:mpeg:mpegB:cicp:systems:auxiliary:alpha\0", 44);
2868 ✗ return update_size(pb, pos);
2869 }
2870 #endif
2871
2872 240 static int mov_write_video_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
2873 {
2874 240 int ret = AVERROR_BUG;
2875 240 int64_t pos = avio_tell(pb);
2876 const AVPacketSideData *sd;
2877 240 char compressor_name[32] = { 0 };
2878 240 int avid = 0;
2879
2880
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 int uncompressed_ycbcr = ((track->par->codec_id == AV_CODEC_ID_RAWVIDEO && track->par->format == AV_PIX_FMT_UYVY422)
2881
3/4
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 223 times.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
240 || (track->par->codec_id == AV_CODEC_ID_RAWVIDEO && track->par->format == AV_PIX_FMT_YUYV422)
2882
3/4
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 223 times.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
240 || (track->par->codec_id == AV_CODEC_ID_RAWVIDEO && track->par->format == AV_PIX_FMT_VYU444)
2883
3/4
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 223 times.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
240 || (track->par->codec_id == AV_CODEC_ID_RAWVIDEO && track->par->format == AV_PIX_FMT_UYVA)
2884
4/4
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 223 times.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 4 times.
240 || (track->par->codec_id == AV_CODEC_ID_RAWVIDEO && track->par->format == AV_PIX_FMT_V30XLE)
2885
3/4
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 223 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 236 times.
480 || track->par->codec_id == AV_CODEC_ID_V210);
2886
2887 240 avio_wb32(pb, 0); /* size */
2888
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 234 times.
240 if (mov->encryption_scheme != MOV_ENC_NONE) {
2889 6 ffio_wfourcc(pb, "encv");
2890 } else {
2891 234 avio_wl32(pb, track->tag); // store it byteswapped
2892 }
2893 240 avio_wb32(pb, 0); /* Reserved */
2894 240 avio_wb16(pb, 0); /* Reserved */
2895 240 avio_wb16(pb, 1); /* Data-reference index */
2896
2897
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 236 times.
240 if (uncompressed_ycbcr) {
2898 4 avio_wb16(pb, 2); /* Codec stream version */
2899 } else {
2900 236 avio_wb16(pb, 0); /* Codec stream version */
2901 }
2902 240 avio_wb16(pb, 0); /* Codec stream revision (=0) */
2903
2/2
✓ Branch 0 taken 146 times.
✓ Branch 1 taken 94 times.
240 if (track->mode == MODE_MOV) {
2904 146 ffio_wfourcc(pb, "FFMP"); /* Vendor */
2905
3/4
✓ Branch 0 taken 129 times.
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 129 times.
146 if (track->par->codec_id == AV_CODEC_ID_RAWVIDEO || uncompressed_ycbcr) {
2906 17 avio_wb32(pb, 0); /* Temporal Quality */
2907 17 avio_wb32(pb, 0x400); /* Spatial Quality = lossless*/
2908 } else {
2909 129 avio_wb32(pb, 0x200); /* Temporal Quality = normal */
2910 129 avio_wb32(pb, 0x200); /* Spatial Quality = normal */
2911 }
2912 } else {
2913 94 ffio_fill(pb, 0, 3 * 4); /* Reserved */
2914 }
2915 240 avio_wb16(pb, track->par->width); /* Video width */
2916 240 avio_wb16(pb, track->height); /* Video height */
2917 240 avio_wb32(pb, 0x00480000); /* Horizontal resolution 72dpi */
2918 240 avio_wb32(pb, 0x00480000); /* Vertical resolution 72dpi */
2919 240 avio_wb32(pb, 0); /* Data size (= 0) */
2920 240 avio_wb16(pb, 1); /* Frame count (= 1) */
2921
2922 240 find_compressor(compressor_name, 32, track);
2923 240 avio_w8(pb, strlen(compressor_name));
2924 240 avio_write(pb, compressor_name, 31);
2925
2926
3/4
✓ Branch 0 taken 146 times.
✓ Branch 1 taken 94 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 146 times.
240 if (track->mode == MODE_MOV && track->par->codec_id == AV_CODEC_ID_V210)
2927 ✗ avio_wb16(pb, 0x18);
2928
4/4
✓ Branch 0 taken 146 times.
✓ Branch 1 taken 94 times.
✓ Branch 2 taken 35 times.
✓ Branch 3 taken 111 times.
240 else if (track->mode == MODE_MOV && track->par->bits_per_coded_sample)
2929 35 avio_wb16(pb, track->par->bits_per_coded_sample |
2930
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 32 times.
35 (track->par->format == AV_PIX_FMT_GRAY8 ? 0x20 : 0));
2931 else
2932 205 avio_wb16(pb, 0x18); /* Reserved */
2933
2934
4/4
✓ Branch 0 taken 146 times.
✓ Branch 1 taken 94 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 141 times.
245 if (track->mode == MODE_MOV && track->par->format == AV_PIX_FMT_PAL8) {
2935 int pal_size, i;
2936 5 avio_wb16(pb, 0); /* Color table ID */
2937 5 avio_wb32(pb, 0); /* Color table seed */
2938 5 avio_wb16(pb, 0x8000); /* Color table flags */
2939
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (track->par->bits_per_coded_sample < 0 || track->par->bits_per_coded_sample > 8)
2940 ✗ return AVERROR(EINVAL);
2941 5 pal_size = 1 << track->par->bits_per_coded_sample;
2942 5 avio_wb16(pb, pal_size - 1); /* Color table size (zero-relative) */
2943
2/2
✓ Branch 0 taken 1040 times.
✓ Branch 1 taken 5 times.
1045 for (i = 0; i < pal_size; i++) {
2944 1040 uint32_t rgb = track->palette[i];
2945 1040 uint16_t r = (rgb >> 16) & 0xff;
2946 1040 uint16_t g = (rgb >> 8) & 0xff;
2947 1040 uint16_t b = rgb & 0xff;
2948 1040 avio_wb16(pb, 0);
2949 1040 avio_wb16(pb, (r << 8) | r);
2950 1040 avio_wb16(pb, (g << 8) | g);
2951 1040 avio_wb16(pb, (b << 8) | b);
2952 }
2953 } else
2954 235 avio_wb16(pb, 0xffff); /* Reserved */
2955
2956
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 203 times.
240 if (track->tag == MKTAG('m','p','4','v'))
2957 37 mov_write_esds_tag(pb, track);
2958
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 203 times.
203 else if (track->par->codec_id == AV_CODEC_ID_H263)
2959 ✗ mov_write_d263_tag(pb);
2960
2/2
✓ Branch 0 taken 200 times.
✓ Branch 1 taken 3 times.
203 else if (track->par->codec_id == AV_CODEC_ID_AVUI ||
2961
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 200 times.
200 track->par->codec_id == AV_CODEC_ID_SVQ3) {
2962 3 mov_write_extradata_tag(pb, track);
2963 3 avio_wb32(pb, 0);
2964
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 177 times.
200 } else if (track->par->codec_id == AV_CODEC_ID_DNXHD) {
2965 23 mov_write_avid_tag(pb, track);
2966 23 avid = 1;
2967
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 166 times.
177 } else if (track->par->codec_id == AV_CODEC_ID_HEVC) {
2968 11 mov_write_hvcc_tag(mov->fc, pb, track);
2969
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10 times.
11 if (track->st->disposition & AV_DISPOSITION_MULTILAYER) {
2970 1 ret = mov_write_lhvc_tag(mov->fc, pb, track);
2971
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
2972 ✗ av_log(mov->fc, AV_LOG_WARNING, "Not writing 'lhvC' atom for multilayer stream.\n");
2973 }
2974
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 165 times.
166 } else if (track->par->codec_id == AV_CODEC_ID_VVC)
2975 1 mov_write_vvcc_tag(pb, track);
2976
16/30
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 103 times.
✓ Branch 2 taken 62 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 62 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 62 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 62 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 62 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 62 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 62 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 62 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 62 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 62 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 62 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 62 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 62 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 62 times.
✗ Branch 29 not taken.
165 else if (track->par->codec_id == AV_CODEC_ID_H264 && !TAG_IS_AVCI(track->tag)) {
2977 62 mov_write_avcc_tag(pb, track);
2978
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 62 times.
62 if (track->mode == MODE_IPOD)
2979 ✗ mov_write_uuid_tag_ipod(pb);
2980 }
2981
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 102 times.
103 else if (track->par->codec_id ==AV_CODEC_ID_EVC) {
2982 1 mov_write_evcc_tag(pb, track);
2983
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 101 times.
102 } else if (track->par->codec_id == AV_CODEC_ID_LCEVC) {
2984 1 mov_write_lvcc_tag(mov->fc, pb, track);
2985
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 100 times.
101 } else if (track->par->codec_id ==AV_CODEC_ID_APV) {
2986 1 mov_write_apvc_tag(mov->fc, pb, track);
2987
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 100 times.
100 } else if (track->par->codec_id == AV_CODEC_ID_VP9) {
2988 ✗ mov_write_vpcc_tag(mov->fc, pb, track);
2989
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 97 times.
100 } else if (track->par->codec_id == AV_CODEC_ID_AV1) {
2990 3 mov_write_av1c_tag(pb, track);
2991
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 97 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
97 } else if (track->par->codec_id == AV_CODEC_ID_VC1 && track->extradata_size[track->last_stsd_index] > 0)
2992 ✗ mov_write_dvc1_tag(pb, track);
2993
1/2
✓ Branch 0 taken 97 times.
✗ Branch 1 not taken.
97 else if (track->par->codec_id == AV_CODEC_ID_VP6F ||
2994
1/2
✓ Branch 0 taken 97 times.
✗ Branch 1 not taken.
97 track->par->codec_id == AV_CODEC_ID_VP6A) {
2995 /* Don't write any potential extradata here - the cropping
2996 * is signalled via the normal width/height fields. */
2997
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 97 times.
97 } else if (track->par->codec_id == AV_CODEC_ID_R10K) {
2998 ✗ if (track->par->codec_tag == MKTAG('R','1','0','k'))
2999 ✗ mov_write_dpxe_tag(pb, track);
3000
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 97 times.
97 } else if (track->par->codec_id == AV_CODEC_ID_AVS3) {
3001 ✗ mov_write_av3c_tag(pb, track);
3002
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 93 times.
97 } else if (track->extradata_size[track->last_stsd_index] > 0)
3003 4 mov_write_glbl_tag(pb, track);
3004
3005
2/2
✓ Branch 0 taken 178 times.
✓ Branch 1 taken 62 times.
240 if (track->par->codec_id != AV_CODEC_ID_H264 &&
3006
2/2
✓ Branch 0 taken 147 times.
✓ Branch 1 taken 31 times.
178 track->par->codec_id != AV_CODEC_ID_MPEG4 &&
3007
2/2
✓ Branch 0 taken 124 times.
✓ Branch 1 taken 23 times.
147 track->par->codec_id != AV_CODEC_ID_DNXHD) {
3008 124 int field_order = track->par->field_order;
3009
3010
2/2
✓ Branch 0 taken 101 times.
✓ Branch 1 taken 23 times.
124 if (field_order != AV_FIELD_UNKNOWN)
3011 101 mov_write_fiel_tag(pb, track, field_order);
3012 }
3013
3014
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 240 times.
240 if (mov->flags & FF_MOV_FLAG_WRITE_GAMA) {
3015 ✗ if (track->mode == MODE_MOV)
3016 ✗ mov_write_gama_tag(s, pb, track, mov->gamma);
3017 else
3018 ✗ av_log(mov->fc, AV_LOG_WARNING, "Not writing 'gama' atom. Format is not MOV.\n");
3019 }
3020
6/6
✓ Branch 0 taken 94 times.
✓ Branch 1 taken 146 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 87 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 6 times.
474 if (track->mode == MODE_MOV || track->mode == MODE_MP4 || track->mode == MODE_AVIF) {
3021 479 int has_color_info = track->par->color_primaries != AVCOL_PRI_UNSPECIFIED &&
3022
3/4
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 223 times.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
245 track->par->color_trc != AVCOL_TRC_UNSPECIFIED &&
3023
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 track->par->color_space != AVCOL_SPC_UNSPECIFIED;
3024
5/6
✓ Branch 0 taken 223 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 219 times.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 219 times.
453 if (has_color_info || mov->flags & FF_MOV_FLAG_WRITE_COLR ||
3025 219 av_packet_side_data_get(track->st->codecpar->coded_side_data, track->st->codecpar->nb_coded_side_data,
3026 AV_PKT_DATA_ICC_PROFILE)) {
3027
3/4
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 11 times.
15 int prefer_icc = mov->flags & FF_MOV_FLAG_PREFER_ICC || !has_color_info;
3028 15 mov_write_colr_tag(pb, track, prefer_icc);
3029 }
3030
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 } else if (mov->flags & FF_MOV_FLAG_WRITE_COLR) {
3031 ✗ av_log(mov->fc, AV_LOG_WARNING, "Not writing 'colr' atom. Format is not MOV or MP4 or AVIF.\n");
3032 }
3033
3034
4/4
✓ Branch 0 taken 94 times.
✓ Branch 1 taken 146 times.
✓ Branch 2 taken 87 times.
✓ Branch 3 taken 7 times.
240 if (track->mode == MODE_MOV || track->mode == MODE_MP4) {
3035 233 mov_write_clli_tag(pb, track);
3036 233 mov_write_mdcv_tag(pb, track);
3037 233 mov_write_amve_tag(pb, track);
3038 }
3039
3040
2/2
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 153 times.
240 if (track->mode == MODE_MP4) {
3041 87 const AVPacketSideData *stereo_3d = av_packet_side_data_get(track->st->codecpar->coded_side_data,
3042 87 track->st->codecpar->nb_coded_side_data,
3043 AV_PKT_DATA_STEREO3D);
3044 87 const AVPacketSideData *spherical_mapping = av_packet_side_data_get(track->st->codecpar->coded_side_data,
3045 87 track->st->codecpar->nb_coded_side_data,
3046 AV_PKT_DATA_SPHERICAL);
3047
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 86 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
87 if (stereo_3d && mov->fc->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL)
3048 1 mov_write_st3d_tag(s, pb, (AVStereo3D*)stereo_3d->data);
3049
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 86 times.
86 else if (stereo_3d)
3050 ✗ av_log(s, AV_LOG_WARNING, "Writing supported 'st3d' metadata requires -strict unofficial.\n");
3051
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 87 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
87 if (spherical_mapping && mov->fc->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL)
3052 ✗ mov_write_sv3d_tag(mov->fc, pb, (AVSphericalMapping*)spherical_mapping->data);
3053
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 87 times.
87 else if (spherical_mapping)
3054 ✗ av_log(s, AV_LOG_WARNING, "Writing supported 'sv3d' metadata requires -strict unofficial.\n");
3055 }
3056
3057
4/4
✓ Branch 0 taken 94 times.
✓ Branch 1 taken 146 times.
✓ Branch 2 taken 87 times.
✓ Branch 3 taken 7 times.
240 if (track->mode == MODE_MOV || (track->mode == MODE_MP4 &&
3058
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 84 times.
87 mov->fc->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL)) {
3059 149 const AVStereo3D *stereo3d = NULL;
3060 149 const AVSphericalMapping *spherical_mapping = NULL;
3061
3062 149 sd = av_packet_side_data_get(track->st->codecpar->coded_side_data,
3063 149 track->st->codecpar->nb_coded_side_data,
3064 AV_PKT_DATA_STEREO3D);
3065
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 147 times.
149 if (sd)
3066 2 stereo3d = (AVStereo3D *)sd->data;
3067
3068 149 sd = av_packet_side_data_get(track->st->codecpar->coded_side_data,
3069 149 track->st->codecpar->nb_coded_side_data,
3070 AV_PKT_DATA_SPHERICAL);
3071
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 148 times.
149 if (sd)
3072 1 spherical_mapping = (AVSphericalMapping *)sd->data;
3073
3074
3/4
✓ Branch 0 taken 147 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 147 times.
149 if (stereo3d || spherical_mapping)
3075 2 mov_write_vexu_tag(s, pb, stereo3d, spherical_mapping);
3076
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 147 times.
149 if (stereo3d)
3077 2 mov_write_hfov_tag(s, pb, stereo3d);
3078 }
3079
3080
2/2
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 153 times.
240 if (track->mode == MODE_MP4) {
3081 87 const AVPacketSideData *dovi = av_packet_side_data_get(track->st->codecpar->coded_side_data,
3082 87 track->st->codecpar->nb_coded_side_data,
3083 AV_PKT_DATA_DOVI_CONF);
3084
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 85 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
87 if (dovi && mov->fc->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL) {
3085 2 mov_write_dvcc_dvvc_tag(s, pb, (AVDOVIDecoderConfigurationRecord *)dovi->data);
3086
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 85 times.
85 } else if (dovi) {
3087 ✗ av_log(mov->fc, AV_LOG_WARNING, "Not writing 'dvcC'/'dvvC' box. Requires -strict unofficial.\n");
3088 }
3089
3090 87 const AVPacketSideData *hvce = av_packet_side_data_get(track->st->codecpar->coded_side_data,
3091 87 track->st->codecpar->nb_coded_side_data,
3092 AV_PKT_DATA_HEVC_CONF);
3093
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 85 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
87 if (hvce && mov->fc->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL) {
3094 2 mov_write_hvce_tag(pb, hvce);
3095
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 85 times.
85 } else if (hvce) {
3096 ✗ av_log(mov->fc, AV_LOG_WARNING, "Not writing 'hvcE' box. Requires -strict unofficial.\n");
3097 }
3098 }
3099
3100
3/4
✓ Branch 0 taken 240 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
✓ Branch 3 taken 211 times.
240 if (track->par->sample_aspect_ratio.den && track->par->sample_aspect_ratio.num) {
3101 29 mov_write_pasp_tag(pb, track);
3102 }
3103
3104 240 sd = av_packet_side_data_get(track->st->codecpar->coded_side_data,
3105 240 track->st->codecpar->nb_coded_side_data,
3106 AV_PKT_DATA_FRAME_CROPPING);
3107
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 239 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
241 if (sd && sd->size >= sizeof(uint32_t) * 4) {
3108 1 uint64_t top = AV_RL32(sd->data + 0);
3109 1 uint64_t bottom = AV_RL32(sd->data + 4);
3110 1 uint64_t left = AV_RL32(sd->data + 8);
3111 1 uint64_t right = AV_RL32(sd->data + 12);
3112
3113
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if ((left + right) >= track->par->width ||
3114
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 (top + bottom) >= track->height) {
3115 ✗ av_log(s, AV_LOG_ERROR, "Invalid cropping dimensions in stream side data\n");
3116 ✗ return AVERROR(EINVAL);
3117 }
3118
3/8
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1 if (top || bottom || left || right)
3119 1 mov_write_clap_tag(pb, track, top, bottom, left, right);
3120
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 235 times.
239 } else if (uncompressed_ycbcr)
3121 4 mov_write_clap_tag(pb, track, 0, 0, 0, 0);
3122
3123
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 234 times.
240 if (mov->encryption_scheme != MOV_ENC_NONE) {
3124 6 ff_mov_cenc_write_sinf_tag(track, pb, mov->encryption_kid);
3125 }
3126
3127
3/4
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 153 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 87 times.
327 if (mov->write_btrt &&
3128 87 ((ret = mov_write_btrt_tag(pb, track)) < 0))
3129 ✗ return ret;
3130
3131 /* extra padding for avid stsd */
3132 /* https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/QTFFChap2/qtff2.html#//apple_ref/doc/uid/TP40000939-CH204-61112 */
3133
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 217 times.
240 if (avid)
3134 23 avio_wb32(pb, 0);
3135
3136 #if CONFIG_AVIF_MUXER
3137
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 239 times.
240 if (track->mode == MODE_AVIF) {
3138 1 mov_write_ccst_tag(pb);
3139
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (mov->nb_streams > 0 && track == &mov->tracks[1])
3140 ✗ mov_write_aux_tag(pb, "auxi");
3141 }
3142 #endif
3143
3144 240 return update_size(pb, pos);
3145 }
3146
3147 2 static int mov_write_rtp_tag(AVIOContext *pb, MOVTrack *track)
3148 {
3149 2 int64_t pos = avio_tell(pb);
3150 2 avio_wb32(pb, 0); /* size */
3151 2 ffio_wfourcc(pb, "rtp ");
3152 2 avio_wb32(pb, 0); /* Reserved */
3153 2 avio_wb16(pb, 0); /* Reserved */
3154 2 avio_wb16(pb, 1); /* Data-reference index */
3155
3156 2 avio_wb16(pb, 1); /* Hint track version */
3157 2 avio_wb16(pb, 1); /* Highest compatible version */
3158 2 avio_wb32(pb, track->max_packet_size); /* Max packet size */
3159
3160 2 avio_wb32(pb, 12); /* size */
3161 2 ffio_wfourcc(pb, "tims");
3162 2 avio_wb32(pb, track->timescale);
3163
3164 2 return update_size(pb, pos);
3165 }
3166
3167 2 static int mov_write_source_reference_tag(AVIOContext *pb, MOVTrack *track, const char *reel_name)
3168 {
3169 2 uint64_t str_size =strlen(reel_name);
3170 2 int64_t pos = avio_tell(pb);
3171
3172
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (str_size >= UINT16_MAX){
3173 ✗ av_log(NULL, AV_LOG_ERROR, "reel_name length %"PRIu64" is too large\n", str_size);
3174 ✗ avio_wb16(pb, 0);
3175 ✗ return AVERROR(EINVAL);
3176 }
3177
3178 2 avio_wb32(pb, 0); /* size */
3179 2 ffio_wfourcc(pb, "name"); /* Data format */
3180 2 avio_wb16(pb, str_size); /* string size */
3181 2 avio_wb16(pb, track->language); /* langcode */
3182 2 avio_write(pb, reel_name, str_size); /* reel name */
3183 2 return update_size(pb,pos);
3184 }
3185
3186 13 static int mov_write_tmcd_tag(AVIOContext *pb, MOVTrack *track)
3187 {
3188 13 int64_t pos = avio_tell(pb);
3189 #if 1
3190 int frame_duration;
3191 int nb_frames;
3192 13 AVDictionaryEntry *t = NULL;
3193
3194
2/4
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
13 if (!track->st->avg_frame_rate.num || !track->st->avg_frame_rate.den) {
3195 ✗ av_log(NULL, AV_LOG_ERROR, "avg_frame_rate not set for tmcd track.\n");
3196 ✗ return AVERROR(EINVAL);
3197 } else {
3198 13 frame_duration = av_rescale(track->timescale, track->st->avg_frame_rate.den, track->st->avg_frame_rate.num);
3199
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 nb_frames = ROUNDED_DIV(track->st->avg_frame_rate.num, track->st->avg_frame_rate.den);
3200 }
3201
3202
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (nb_frames > 255) {
3203 ✗ av_log(NULL, AV_LOG_ERROR, "fps %d is too large\n", nb_frames);
3204 ✗ return AVERROR(EINVAL);
3205 }
3206
3207 13 avio_wb32(pb, 0); /* size */
3208 13 ffio_wfourcc(pb, "tmcd"); /* Data format */
3209 13 avio_wb32(pb, 0); /* Reserved */
3210 13 avio_wb32(pb, 1); /* Data reference index */
3211 13 avio_wb32(pb, 0); /* Flags */
3212 13 avio_wb32(pb, track->timecode_flags); /* Flags (timecode) */
3213 13 avio_wb32(pb, track->timescale); /* Timescale */
3214 13 avio_wb32(pb, frame_duration); /* Frame duration */
3215 13 avio_w8(pb, nb_frames); /* Number of frames */
3216 13 avio_w8(pb, 0); /* Reserved */
3217
3218 13 t = av_dict_get(track->st->metadata, "reel_name", NULL, 0);
3219
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 11 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
13 if (t && utf8len(t->value) && track->mode != MODE_MP4)
3220 2 mov_write_source_reference_tag(pb, track, t->value);
3221 else
3222 11 avio_wb16(pb, 0); /* zero size */
3223 #else
3224
3225 avio_wb32(pb, 0); /* size */
3226 ffio_wfourcc(pb, "tmcd"); /* Data format */
3227 avio_wb32(pb, 0); /* Reserved */
3228 avio_wb32(pb, 1); /* Data reference index */
3229 if (track->par->extradata_size)
3230 avio_write(pb, track->par->extradata, track->par->extradata_size);
3231 #endif
3232 13 return update_size(pb, pos);
3233 }
3234
3235 1 static int mov_write_gpmd_tag(AVIOContext *pb, const MOVTrack *track)
3236 {
3237 1 int64_t pos = avio_tell(pb);
3238 1 avio_wb32(pb, 0); /* size */
3239 1 ffio_wfourcc(pb, "gpmd");
3240 1 avio_wb32(pb, 0); /* Reserved */
3241 1 avio_wb16(pb, 0); /* Reserved */
3242 1 avio_wb16(pb, 1); /* Data-reference index */
3243 1 avio_wb32(pb, 0); /* Reserved */
3244 1 return update_size(pb, pos);
3245 }
3246
3247 598 static int mov_write_stsd_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
3248 {
3249 598 int64_t pos = avio_tell(pb);
3250 598 int ret = 0;
3251 598 avio_wb32(pb, 0); /* size */
3252 598 ffio_wfourcc(pb, "stsd");
3253 598 avio_wb32(pb, 0); /* version & flags */
3254 598 avio_wb32(pb, track->stsd_count);
3255
3256 598 int stsd_index_back = track->last_stsd_index;
3257 598 for (track->last_stsd_index = 0;
3258
2/2
✓ Branch 0 taken 600 times.
✓ Branch 1 taken 598 times.
1198 track->last_stsd_index < track->stsd_count;
3259 600 track->last_stsd_index++) {
3260
2/2
✓ Branch 0 taken 240 times.
✓ Branch 1 taken 360 times.
600 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO)
3261 240 ret = mov_write_video_tag(s, pb, mov, track);
3262
2/2
✓ Branch 0 taken 338 times.
✓ Branch 1 taken 22 times.
360 else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO)
3263 338 ret = mov_write_audio_tag(s, pb, mov, track);
3264
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 16 times.
22 else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE)
3265 6 ret = mov_write_subtitle_tag(s, pb, track);
3266
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 14 times.
16 else if (track->par->codec_tag == MKTAG('r','t','p',' '))
3267 2 ret = mov_write_rtp_tag(pb, track);
3268
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 1 times.
14 else if (track->par->codec_tag == MKTAG('t','m','c','d'))
3269 13 ret = mov_write_tmcd_tag(pb, track);
3270
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 else if (track->par->codec_tag == MKTAG('g','p','m','d'))
3271 1 ret = mov_write_gpmd_tag(pb, track);
3272
3273
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 600 times.
600 if (ret < 0)
3274 ✗ return ret;
3275 }
3276
3277 598 track->last_stsd_index = stsd_index_back;
3278
3279 598 return update_size_and_version(pb, pos, track->entry_version);
3280 }
3281
3282 17 static int mov_write_ctts_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
3283 {
3284 17 MOVMuxContext *mov = s->priv_data;
3285 MOVCtts *ctts_entries;
3286 17 uint32_t entries = 0;
3287 uint32_t atom_size;
3288 int i;
3289
3290 17 ctts_entries = av_malloc_array((track->entry + 1), sizeof(*ctts_entries)); /* worst case */
3291
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if (!ctts_entries)
3292 ✗ return AVERROR(ENOMEM);
3293 17 ctts_entries[0].count = 1;
3294 17 ctts_entries[0].offset = track->cluster[0].cts;
3295
2/2
✓ Branch 0 taken 818 times.
✓ Branch 1 taken 17 times.
835 for (i = 1; i < track->entry; i++) {
3296
2/2
✓ Branch 0 taken 141 times.
✓ Branch 1 taken 677 times.
818 if (track->cluster[i].cts == ctts_entries[entries].offset) {
3297 141 ctts_entries[entries].count++; /* compress */
3298 } else {
3299 677 entries++;
3300 677 ctts_entries[entries].offset = track->cluster[i].cts;
3301 677 ctts_entries[entries].count = 1;
3302 }
3303 }
3304 17 entries++; /* last one */
3305 17 atom_size = 16 + (entries * 8);
3306 17 avio_wb32(pb, atom_size); /* size */
3307 17 ffio_wfourcc(pb, "ctts");
3308
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if (mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS)
3309 ✗ avio_w8(pb, 1); /* version */
3310 else
3311 17 avio_w8(pb, 0); /* version */
3312 17 avio_wb24(pb, 0); /* flags */
3313 17 avio_wb32(pb, entries); /* entry count */
3314
2/2
✓ Branch 0 taken 694 times.
✓ Branch 1 taken 17 times.
711 for (i = 0; i < entries; i++) {
3315 694 avio_wb32(pb, ctts_entries[i].count);
3316 694 avio_wb32(pb, ctts_entries[i].offset);
3317 }
3318 17 av_free(ctts_entries);
3319 17 return atom_size;
3320 }
3321
3322 /* Time to sample atom */
3323 598 static int mov_write_stts_tag(AVIOContext *pb, MOVTrack *track)
3324 {
3325 598 MOVStts *stts_entries = NULL;
3326 598 uint32_t entries = -1;
3327 uint32_t atom_size;
3328 int i;
3329
3330
4/4
✓ Branch 0 taken 338 times.
✓ Branch 1 taken 260 times.
✓ Branch 2 taken 39 times.
✓ Branch 3 taken 299 times.
598 if (track->par->codec_type == AVMEDIA_TYPE_AUDIO && !track->audio_vbr) {
3331 39 stts_entries = av_malloc(sizeof(*stts_entries)); /* one entry */
3332
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (!stts_entries)
3333 ✗ return AVERROR(ENOMEM);
3334 39 stts_entries[0].count = track->sample_count;
3335 39 stts_entries[0].duration = 1;
3336 39 entries = 1;
3337 } else {
3338
2/2
✓ Branch 0 taken 252 times.
✓ Branch 1 taken 307 times.
559 if (track->entry) {
3339 252 stts_entries = av_malloc_array(track->entry, sizeof(*stts_entries)); /* worst case */
3340
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 252 times.
252 if (!stts_entries)
3341 ✗ return AVERROR(ENOMEM);
3342 }
3343
2/2
✓ Branch 0 taken 16963 times.
✓ Branch 1 taken 559 times.
17522 for (i = 0; i < track->entry; i++) {
3344 16963 int duration = get_cluster_duration(track, i);
3345 #if CONFIG_IAMFENC
3346
3/4
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 16897 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 66 times.
16963 if (track->iamf && track->par->codec_id == AV_CODEC_ID_OPUS)
3347 ✗ duration = av_rescale(duration, 48000, track->par->sample_rate);
3348 #endif
3349
4/4
✓ Branch 0 taken 16711 times.
✓ Branch 1 taken 252 times.
✓ Branch 2 taken 16281 times.
✓ Branch 3 taken 430 times.
16963 if (i && duration == stts_entries[entries].duration) {
3350 16281 stts_entries[entries].count++; /* compress */
3351 } else {
3352 682 entries++;
3353 682 stts_entries[entries].duration = duration;
3354 682 stts_entries[entries].count = 1;
3355 }
3356 }
3357 559 entries++; /* last one */
3358 }
3359 598 atom_size = 16 + (entries * 8);
3360 598 avio_wb32(pb, atom_size); /* size */
3361 598 ffio_wfourcc(pb, "stts");
3362 598 avio_wb32(pb, 0); /* version & flags */
3363 598 avio_wb32(pb, entries); /* entry count */
3364
2/2
✓ Branch 0 taken 721 times.
✓ Branch 1 taken 598 times.
1319 for (i = 0; i < entries; i++) {
3365 721 avio_wb32(pb, stts_entries[i].count);
3366 721 avio_wb32(pb, stts_entries[i].duration);
3367 }
3368 598 av_free(stts_entries);
3369 598 return atom_size;
3370 }
3371
3372 598 static int mov_write_dref_tag(AVIOContext *pb)
3373 {
3374 598 avio_wb32(pb, 28); /* size */
3375 598 ffio_wfourcc(pb, "dref");
3376 598 avio_wb32(pb, 0); /* version & flags */
3377 598 avio_wb32(pb, 1); /* entry count */
3378
3379 598 avio_wb32(pb, 0xc); /* size */
3380 //FIXME add the alis and rsrc atom
3381 598 ffio_wfourcc(pb, "url ");
3382 598 avio_wb32(pb, 1); /* version & flags */
3383
3384 598 return 28;
3385 }
3386
3387 69 static int mov_preroll_write_stbl_atoms(AVIOContext *pb, MOVTrack *track)
3388 {
3389 struct sgpd_entry {
3390 int count;
3391 int16_t roll_distance;
3392 int group_description_index;
3393 };
3394
3395 69 struct sgpd_entry *sgpd_entries = NULL;
3396 69 int entries = -1;
3397 69 int group = 0;
3398 int i, j;
3399
3400 69 const int OPUS_SEEK_PREROLL_MS = 80;
3401 69 int roll_samples = av_rescale_q(OPUS_SEEK_PREROLL_MS,
3402 69 (AVRational){1, 1000},
3403 69 (AVRational){1, 48000});
3404
3405
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 24 times.
69 if (!track->entry)
3406 45 return 0;
3407
3408 24 sgpd_entries = av_malloc_array(track->entry, sizeof(*sgpd_entries));
3409
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (!sgpd_entries)
3410 ✗ return AVERROR(ENOMEM);
3411
3412
2/4
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 24 times.
24 av_assert0(track->par->codec_id == AV_CODEC_ID_OPUS || track->par->codec_id == AV_CODEC_ID_AAC);
3413
3414
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (track->par->codec_id == AV_CODEC_ID_OPUS) {
3415 ✗ for (i = 0; i < track->entry; i++) {
3416 ✗ int roll_samples_remaining = roll_samples;
3417 ✗ int distance = 0;
3418 ✗ for (j = i - 1; j >= 0; j--) {
3419 ✗ roll_samples_remaining -= get_cluster_duration(track, j);
3420 ✗ distance++;
3421 ✗ if (roll_samples_remaining <= 0)
3422 ✗ break;
3423 }
3424 /* We don't have enough preceding samples to compute a valid
3425 roll_distance here, so this sample can't be independently
3426 decoded. */
3427 ✗ if (roll_samples_remaining > 0)
3428 ✗ distance = 0;
3429 /* Verify distance is a maximum of 32 (2.5ms) packets. */
3430 ✗ if (distance > 32) {
3431 ✗ av_freep(&sgpd_entries);
3432 ✗ return AVERROR_INVALIDDATA;
3433 }
3434 ✗ if (i && distance == sgpd_entries[entries].roll_distance) {
3435 ✗ sgpd_entries[entries].count++;
3436 } else {
3437 ✗ entries++;
3438 ✗ sgpd_entries[entries].count = 1;
3439 ✗ sgpd_entries[entries].roll_distance = distance;
3440 ✗ sgpd_entries[entries].group_description_index = distance ? ++group : 0;
3441 }
3442 }
3443 } else {
3444 24 entries++;
3445 24 sgpd_entries[entries].count = track->sample_count;
3446 24 sgpd_entries[entries].roll_distance = 1;
3447 24 sgpd_entries[entries].group_description_index = ++group;
3448 }
3449 24 entries++;
3450
3451
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (!group) {
3452 ✗ av_free(sgpd_entries);
3453 ✗ return 0;
3454 }
3455
3456 /* Write sgpd tag */
3457 24 avio_wb32(pb, 24 + (group * 2)); /* size */
3458 24 ffio_wfourcc(pb, "sgpd");
3459 24 avio_wb32(pb, 1 << 24); /* fullbox */
3460 24 ffio_wfourcc(pb, "roll");
3461 24 avio_wb32(pb, 2); /* default_length */
3462 24 avio_wb32(pb, group); /* entry_count */
3463
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 24 times.
48 for (i = 0; i < entries; i++) {
3464
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 if (sgpd_entries[i].group_description_index) {
3465 24 avio_wb16(pb, -sgpd_entries[i].roll_distance); /* roll_distance */
3466 }
3467 }
3468
3469 /* Write sbgp tag */
3470 24 avio_wb32(pb, 20 + (entries * 8)); /* size */
3471 24 ffio_wfourcc(pb, "sbgp");
3472 24 avio_wb32(pb, 0); /* fullbox */
3473 24 ffio_wfourcc(pb, "roll");
3474 24 avio_wb32(pb, entries); /* entry_count */
3475
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 24 times.
48 for (i = 0; i < entries; i++) {
3476 24 avio_wb32(pb, sgpd_entries[i].count); /* sample_count */
3477 24 avio_wb32(pb, sgpd_entries[i].group_description_index); /* group_description_index */
3478 }
3479
3480 24 av_free(sgpd_entries);
3481 24 return 0;
3482 }
3483
3484 598 static int mov_write_stbl_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
3485 {
3486 598 int64_t pos = avio_tell(pb);
3487 598 int ret = 0;
3488
3489 598 avio_wb32(pb, 0); /* size */
3490 598 ffio_wfourcc(pb, "stbl");
3491
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 598 times.
598 if ((ret = mov_write_stsd_tag(s, pb, mov, track)) < 0)
3492 ✗ return ret;
3493 598 mov_write_stts_tag(pb, track);
3494
2/2
✓ Branch 0 taken 360 times.
✓ Branch 1 taken 238 times.
598 if ((track->par->codec_type == AVMEDIA_TYPE_VIDEO ||
3495
1/2
✓ Branch 0 taken 360 times.
✗ Branch 1 not taken.
360 track->par->codec_id == AV_CODEC_ID_TRUEHD ||
3496
2/2
✓ Branch 0 taken 359 times.
✓ Branch 1 taken 1 times.
360 track->par->codec_id == AV_CODEC_ID_MPEGH_3D_AUDIO ||
3497
3/4
✓ Branch 0 taken 69 times.
✓ Branch 1 taken 290 times.
✓ Branch 2 taken 69 times.
✗ Branch 3 not taken.
359 (track->par->codec_id == AV_CODEC_ID_AAC && track->par->profile == AV_PROFILE_AAC_USAC) ||
3498
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 357 times.
359 track->par->codec_tag == MKTAG('r','t','p',' ')) &&
3499
4/4
✓ Branch 0 taken 185 times.
✓ Branch 1 taken 56 times.
✓ Branch 2 taken 73 times.
✓ Branch 3 taken 112 times.
241 track->has_keyframes && track->has_keyframes < track->entry)
3500 73 mov_write_stss_tag(pb, track, MOV_SYNC_SAMPLE);
3501
5/6
✓ Branch 0 taken 238 times.
✓ Branch 1 taken 360 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 235 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
598 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO && track->has_disposable && track->entry)
3502 3 mov_write_sdtp_tag(pb, track);
3503
3/4
✓ Branch 0 taken 200 times.
✓ Branch 1 taken 398 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 200 times.
598 if (track->mode == MODE_MOV && track->flags & MOV_TRACK_STPS)
3504 ✗ mov_write_stss_tag(pb, track, MOV_PARTIAL_SYNC_SAMPLE);
3505
2/2
✓ Branch 0 taken 238 times.
✓ Branch 1 taken 360 times.
598 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO &&
3506
4/4
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 197 times.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 24 times.
238 track->flags & MOV_TRACK_CTTS && track->entry) {
3507
3508
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
17 if ((ret = mov_write_ctts_tag(s, pb, track)) < 0)
3509 ✗ return ret;
3510 }
3511 598 mov_write_stsc_tag(pb, track);
3512 598 mov_write_stsz_tag(pb, track);
3513 598 mov_write_stco_tag(pb, track);
3514
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 593 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
598 if (track->cenc.aes_ctr && !(mov->flags & FF_MOV_FLAG_FRAGMENT)) {
3515 5 ff_mov_cenc_write_stbl_atoms(&track->cenc, pb, 0);
3516 }
3517
3/4
✓ Branch 0 taken 598 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 69 times.
✓ Branch 3 taken 529 times.
598 if (track->par->codec_id == AV_CODEC_ID_OPUS || track->par->codec_id == AV_CODEC_ID_AAC) {
3518 69 mov_preroll_write_stbl_atoms(pb, track);
3519 }
3520 598 return update_size(pb, pos);
3521 }
3522
3523 598 static int mov_write_dinf_tag(AVIOContext *pb)
3524 {
3525 598 int64_t pos = avio_tell(pb);
3526 598 avio_wb32(pb, 0); /* size */
3527 598 ffio_wfourcc(pb, "dinf");
3528 598 mov_write_dref_tag(pb);
3529 598 return update_size(pb, pos);
3530 }
3531
3532 7 static int mov_write_nmhd_tag(AVIOContext *pb)
3533 {
3534 7 avio_wb32(pb, 12);
3535 7 ffio_wfourcc(pb, "nmhd");
3536 7 avio_wb32(pb, 0);
3537 7 return 12;
3538 }
3539
3540 2 static int mov_write_sthd_tag(AVIOContext *pb)
3541 {
3542 2 avio_wb32(pb, 12);
3543 2 ffio_wfourcc(pb, "sthd");
3544 2 avio_wb32(pb, 0);
3545 2 return 12;
3546 }
3547
3548 9 static int mov_write_tcmi_tag(AVIOContext *pb, MOVTrack *track)
3549 {
3550 9 int64_t pos = avio_tell(pb);
3551 9 const char *font = "Lucida Grande";
3552 9 avio_wb32(pb, 0); /* size */
3553 9 ffio_wfourcc(pb, "tcmi"); /* timecode media information atom */
3554 9 avio_wb32(pb, 0); /* version & flags */
3555 9 avio_wb16(pb, 0); /* text font */
3556 9 avio_wb16(pb, 0); /* text face */
3557 9 avio_wb16(pb, 12); /* text size */
3558 9 avio_wb16(pb, 0); /* (unknown, not in the QT specs...) */
3559 9 avio_wb16(pb, 0x0000); /* text color (red) */
3560 9 avio_wb16(pb, 0x0000); /* text color (green) */
3561 9 avio_wb16(pb, 0x0000); /* text color (blue) */
3562 9 avio_wb16(pb, 0xffff); /* background color (red) */
3563 9 avio_wb16(pb, 0xffff); /* background color (green) */
3564 9 avio_wb16(pb, 0xffff); /* background color (blue) */
3565 9 avio_w8(pb, strlen(font)); /* font len (part of the pascal string) */
3566 9 avio_write(pb, font, strlen(font)); /* font name */
3567 9 return update_size(pb, pos);
3568 }
3569
3570 11 static int mov_write_gmhd_tag(AVIOContext *pb, MOVTrack *track)
3571 {
3572 11 int64_t pos = avio_tell(pb);
3573 11 avio_wb32(pb, 0); /* size */
3574 11 ffio_wfourcc(pb, "gmhd");
3575 11 avio_wb32(pb, 0x18); /* gmin size */
3576 11 ffio_wfourcc(pb, "gmin");/* generic media info */
3577 11 avio_wb32(pb, 0); /* version & flags */
3578 11 avio_wb16(pb, 0x40); /* graphics mode = */
3579 11 avio_wb16(pb, 0x8000); /* opColor (r?) */
3580 11 avio_wb16(pb, 0x8000); /* opColor (g?) */
3581 11 avio_wb16(pb, 0x8000); /* opColor (b?) */
3582 11 avio_wb16(pb, 0); /* balance */
3583 11 avio_wb16(pb, 0); /* reserved */
3584
3585 /*
3586 * This special text atom is required for
3587 * Apple Quicktime chapters. The contents
3588 * don't appear to be documented, so the
3589 * bytes are copied verbatim.
3590 */
3591
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (track->tag != MKTAG('c','6','0','8')) {
3592 11 avio_wb32(pb, 0x2C); /* size */
3593 11 ffio_wfourcc(pb, "text");
3594 11 avio_wb16(pb, 0x01);
3595 11 avio_wb32(pb, 0x00);
3596 11 avio_wb32(pb, 0x00);
3597 11 avio_wb32(pb, 0x00);
3598 11 avio_wb32(pb, 0x01);
3599 11 avio_wb32(pb, 0x00);
3600 11 avio_wb32(pb, 0x00);
3601 11 avio_wb32(pb, 0x00);
3602 11 avio_wb32(pb, 0x00004000);
3603 11 avio_wb16(pb, 0x0000);
3604 }
3605
3606
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2 times.
11 if (track->par->codec_tag == MKTAG('t','m','c','d')) {
3607 9 int64_t tmcd_pos = avio_tell(pb);
3608 9 avio_wb32(pb, 0); /* size */
3609 9 ffio_wfourcc(pb, "tmcd");
3610 9 mov_write_tcmi_tag(pb, track);
3611 9 update_size(pb, tmcd_pos);
3612
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 } else if (track->par->codec_tag == MKTAG('g','p','m','d')) {
3613 1 int64_t gpmd_pos = avio_tell(pb);
3614 1 avio_wb32(pb, 0); /* size */
3615 1 ffio_wfourcc(pb, "gpmd");
3616 1 avio_wb32(pb, 0); /* version */
3617 1 update_size(pb, gpmd_pos);
3618 }
3619 11 return update_size(pb, pos);
3620 }
3621
3622 338 static int mov_write_smhd_tag(AVIOContext *pb)
3623 {
3624 338 avio_wb32(pb, 16); /* size */
3625 338 ffio_wfourcc(pb, "smhd");
3626 338 avio_wb32(pb, 0); /* version & flags */
3627 338 avio_wb16(pb, 0); /* reserved (balance, normally = 0) */
3628 338 avio_wb16(pb, 0); /* reserved */
3629 338 return 16;
3630 }
3631
3632 238 static uint16_t mov_graphics_mode(MOVTrack *track)
3633 {
3634
2/2
✓ Branch 0 taken 92 times.
✓ Branch 1 taken 146 times.
238 if (track->mode != MODE_MOV)
3635 92 return 0; /* ISO/IEC 14496-12 doesn't define any other modes */
3636
3637
1/3
✓ Branch 0 taken 146 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
146 switch (track->par->alpha_mode) {
3638 146 default: return MOV_GRAPHICS_MODE_COPY;
3639 ✗ case AVALPHA_MODE_STRAIGHT: return MOV_GRAPHICS_MODE_STRAIGHT_ALPHA;
3640 ✗ case AVALPHA_MODE_PREMULTIPLIED: return MOV_GRAPHICS_MODE_PREMUL_BLACK_ALPHA;
3641 }
3642 }
3643
3644 238 static int mov_write_vmhd_tag(AVIOContext *pb, MOVTrack *track)
3645 {
3646 238 avio_wb32(pb, 0x14); /* size (always 0x14) */
3647 238 ffio_wfourcc(pb, "vmhd");
3648 238 avio_wb32(pb, 0x01); /* version & flags */
3649 238 avio_wb16(pb, mov_graphics_mode(track));
3650
2/2
✓ Branch 0 taken 714 times.
✓ Branch 1 taken 238 times.
952 for (int i = 0; i < 3; i++)
3651 714 avio_wb16(pb, 0); /* opcolor */
3652 238 return 0x14;
3653 }
3654
3655 238 static int is_clcp_track(MOVTrack *track)
3656 {
3657
1/2
✓ Branch 0 taken 238 times.
✗ Branch 1 not taken.
476 return track->tag == MKTAG('c','7','0','8') ||
3658
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 238 times.
238 track->tag == MKTAG('c','6','0','8');
3659 }
3660
3661 799 static int mov_write_hdlr_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
3662 {
3663 799 MOVMuxContext *mov = s->priv_data;
3664 799 const char *hdlr, *descr = NULL, *hdlr_type = NULL;
3665 799 int64_t pos = avio_tell(pb);
3666 size_t descr_len;
3667
3668 799 hdlr = "dhlr";
3669 799 hdlr_type = "url ";
3670 799 descr = "DataHandler";
3671
3672
2/2
✓ Branch 0 taken 599 times.
✓ Branch 1 taken 200 times.
799 if (track) {
3673
2/2
✓ Branch 0 taken 200 times.
✓ Branch 1 taken 399 times.
599 hdlr = (track->mode == MODE_MOV) ? "mhlr" : "\0\0\0\0";
3674
2/2
✓ Branch 0 taken 239 times.
✓ Branch 1 taken 360 times.
599 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
3675
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 237 times.
239 if (track->mode == MODE_AVIF) {
3676
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 hdlr_type = (track == &mov->tracks[0]) ? "pict" : "auxv";
3677 2 descr = "PictureHandler";
3678 } else {
3679 237 hdlr_type = "vide";
3680 237 descr = "VideoHandler";
3681 }
3682
2/2
✓ Branch 0 taken 338 times.
✓ Branch 1 taken 22 times.
360 } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) {
3683 338 hdlr_type = "soun";
3684 338 descr = "SoundHandler";
3685
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 16 times.
22 } else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE) {
3686
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if (is_clcp_track(track)) {
3687 ✗ hdlr_type = "clcp";
3688 ✗ descr = "ClosedCaptionHandler";
3689 } else {
3690
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 if (track->tag == MKTAG('t','x','3','g')) {
3691 1 hdlr_type = "sbtl";
3692
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 } else if (track->tag == MKTAG('m','p','4','s')) {
3693 ✗ hdlr_type = "subp";
3694
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
5 } else if (track->tag == MOV_MP4_TTML_TAG) {
3695 2 hdlr_type = "subt";
3696 } else {
3697 3 hdlr_type = "text";
3698 }
3699 6 descr = "SubtitleHandler";
3700 }
3701
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 14 times.
16 } else if (track->par->codec_tag == MKTAG('r','t','p',' ')) {
3702 2 hdlr_type = "hint";
3703 2 descr = "HintHandler";
3704
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 1 times.
14 } else if (track->par->codec_tag == MKTAG('t','m','c','d')) {
3705 13 hdlr_type = "tmcd";
3706 13 descr = "TimeCodeHandler";
3707
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 } else if (track->par->codec_tag == MKTAG('g','p','m','d')) {
3708 1 hdlr_type = "meta";
3709 1 descr = "GoPro MET"; // GoPro Metadata
3710 } else {
3711 ✗ av_log(s, AV_LOG_WARNING,
3712 "Unknown hdlr_type for %s, writing dummy values\n",
3713 ✗ av_fourcc2str(track->par->codec_tag));
3714 }
3715
2/2
✓ Branch 0 taken 596 times.
✓ Branch 1 taken 3 times.
599 if (track->st) {
3716 // hdlr.name is used by some players to identify the content title
3717 // of the track. So if an alternate handler description is
3718 // specified, use it.
3719 AVDictionaryEntry *t;
3720 596 t = av_dict_get(track->st->metadata, "handler_name", NULL, 0);
3721
3/4
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 566 times.
✓ Branch 3 taken 30 times.
✗ Branch 4 not taken.
596 if (t && utf8len(t->value))
3722 30 descr = t->value;
3723 }
3724 }
3725
3726
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 799 times.
799 if (mov->empty_hdlr_name) /* expressly allowed by QTFF and not prohibited in ISO 14496-12 8.4.3.3 */
3727 ✗ descr = "";
3728
3729 799 avio_wb32(pb, 0); /* size */
3730 799 ffio_wfourcc(pb, "hdlr");
3731 799 avio_wb32(pb, 0); /* Version & flags */
3732 799 avio_write(pb, hdlr, 4); /* handler */
3733 799 ffio_wfourcc(pb, hdlr_type); /* handler type */
3734 799 avio_wb32(pb, 0); /* reserved */
3735 799 avio_wb32(pb, 0); /* reserved */
3736 799 avio_wb32(pb, 0); /* reserved */
3737 799 descr_len = strlen(descr);
3738
4/4
✓ Branch 0 taken 599 times.
✓ Branch 1 taken 200 times.
✓ Branch 2 taken 200 times.
✓ Branch 3 taken 399 times.
799 if (!track || track->mode == MODE_MOV)
3739 400 avio_w8(pb, descr_len); /* pascal string */
3740 799 avio_write(pb, descr, descr_len); /* handler description */
3741
4/4
✓ Branch 0 taken 599 times.
✓ Branch 1 taken 200 times.
✓ Branch 2 taken 399 times.
✓ Branch 3 taken 200 times.
799 if (track && track->mode != MODE_MOV)
3742 399 avio_w8(pb, 0); /* c string */
3743 799 return update_size(pb, pos);
3744 }
3745
3746 #if CONFIG_AVIF_MUXER
3747 1 static int mov_write_pitm_tag(AVIOContext *pb, int item_id)
3748 {
3749 1 int64_t pos = avio_tell(pb);
3750 1 avio_wb32(pb, 0); /* size */
3751 1 ffio_wfourcc(pb, "pitm");
3752 1 avio_wb32(pb, 0); /* Version & flags */
3753 1 avio_wb16(pb, item_id); /* item_id */
3754 1 return update_size(pb, pos);
3755 }
3756
3757 1 static int mov_write_iloc_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
3758 {
3759 1 int64_t pos = avio_tell(pb);
3760 1 avio_wb32(pb, 0); /* size */
3761 1 ffio_wfourcc(pb, "iloc");
3762 1 avio_wb32(pb, 0); /* Version & flags */
3763 1 avio_w8(pb, (4 << 4) + 4); /* offset_size(4) and length_size(4) */
3764 1 avio_w8(pb, 0); /* base_offset_size(4) and reserved(4) */
3765 1 avio_wb16(pb, mov->nb_streams); /* item_count */
3766
3767
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 for (int i = 0; i < mov->nb_streams; i++) {
3768 1 avio_wb16(pb, i + 1); /* item_id */
3769 1 avio_wb16(pb, 0); /* data_reference_index */
3770 1 avio_wb16(pb, 1); /* extent_count */
3771 1 mov->avif_extent_pos[i] = avio_tell(pb);
3772 1 avio_wb32(pb, 0); /* extent_offset (written later) */
3773 // For animated AVIF, we simply write the first packet's size.
3774 1 avio_wb32(pb, mov->avif_extent_length[i]); /* extent_length */
3775 }
3776
3777 1 return update_size(pb, pos);
3778 }
3779
3780 1 static int mov_write_iinf_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
3781 {
3782 1 int64_t iinf_pos = avio_tell(pb);
3783 1 avio_wb32(pb, 0); /* size */
3784 1 ffio_wfourcc(pb, "iinf");
3785 1 avio_wb32(pb, 0); /* Version & flags */
3786 1 avio_wb16(pb, mov->nb_streams); /* entry_count */
3787
3788 av_assert2(mov->nb_streams <= 2);
3789
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 for (int i = 0; i < mov->nb_streams; i++) {
3790 1 int64_t infe_pos = avio_tell(pb);
3791 1 avio_wb32(pb, 0); /* size */
3792 1 ffio_wfourcc(pb, "infe");
3793 1 avio_w8(pb, 0x2); /* Version */
3794 1 avio_wb24(pb, !!i); /* flags (0x1 == hidden) */
3795 1 avio_wb16(pb, i + 1); /* item_id */
3796 1 avio_wb16(pb, 0); /* item_protection_index */
3797 1 avio_write(pb, "av01", 4); /* item_type */
3798
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 avio_write(pb, !i ? "Color\0" : "Alpha\0", 6); /* item_name */
3799 1 update_size(pb, infe_pos);
3800 }
3801
3802 1 return update_size(pb, iinf_pos);
3803 }
3804
3805
3806 ✗ static int mov_write_iref_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
3807 {
3808 int64_t auxl_pos;
3809 ✗ int64_t iref_pos = avio_tell(pb);
3810 ✗ avio_wb32(pb, 0); /* size */
3811 ✗ ffio_wfourcc(pb, "iref");
3812 ✗ avio_wb32(pb, 0); /* Version & flags */
3813
3814 ✗ auxl_pos = avio_tell(pb);
3815 ✗ avio_wb32(pb, 0); /* size */
3816 ✗ ffio_wfourcc(pb, "auxl");
3817 ✗ avio_wb16(pb, 2); /* from_item_ID */
3818 ✗ avio_wb16(pb, 1); /* reference_count */
3819 ✗ avio_wb16(pb, 1); /* to_item_ID */
3820 ✗ update_size(pb, auxl_pos);
3821
3822 ✗ return update_size(pb, iref_pos);
3823 }
3824
3825 1 static int mov_write_ispe_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s,
3826 int stream_index)
3827 {
3828 1 int64_t pos = avio_tell(pb);
3829 1 avio_wb32(pb, 0); /* size */
3830 1 ffio_wfourcc(pb, "ispe");
3831 1 avio_wb32(pb, 0); /* Version & flags */
3832 1 avio_wb32(pb, s->streams[stream_index]->codecpar->width); /* image_width */
3833 1 avio_wb32(pb, s->streams[stream_index]->codecpar->height); /* image_height */
3834 1 return update_size(pb, pos);
3835 }
3836
3837 1 static int mov_write_pixi_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s,
3838 int stream_index)
3839 {
3840 1 MOVTrack *trk = &mov->tracks[stream_index];
3841 1 int64_t pos = avio_tell(pb);
3842 const AVPixFmtDescriptor *pixdesc =
3843 1 av_pix_fmt_desc_get(s->streams[stream_index]->codecpar->format);
3844 int depth, nb_components;
3845
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (pixdesc->nb_components > 0) {
3846 1 depth = pixdesc->comp[0].depth;
3847 1 nb_components = pixdesc->nb_components;
3848 } else {
3849 AV1SequenceParameters seq;
3850 ✗ int ret = ff_av1_parse_seq_header(&seq, trk->extradata[trk->last_stsd_index],
3851 ✗ trk->extradata_size[trk->last_stsd_index]);
3852 ✗ if (ret < 0)
3853 ✗ return ret;
3854 ✗ depth = seq.bitdepth;
3855 ✗ nb_components = seq.monochrome ? 1 : 3;
3856 }
3857 1 avio_wb32(pb, 0); /* size */
3858 1 ffio_wfourcc(pb, "pixi");
3859 1 avio_wb32(pb, 0); /* Version & flags */
3860 1 avio_w8(pb, nb_components); /* num_channels */
3861
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 for (int i = 0; i < nb_components; ++i)
3862 3 avio_w8(pb, depth); /* bits_per_channel */
3863 1 return update_size(pb, pos);
3864 }
3865
3866 1 static int mov_write_ipco_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
3867 {
3868 1 int64_t pos = avio_tell(pb);
3869 1 avio_wb32(pb, 0); /* size */
3870 1 ffio_wfourcc(pb, "ipco");
3871
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 for (int i = 0; i < mov->nb_streams; i++) {
3872 1 mov_write_ispe_tag(pb, mov, s, i);
3873 1 mov_write_pixi_tag(pb, mov, s, i);
3874 1 mov_write_av1c_tag(pb, &mov->tracks[i]);
3875
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (!i)
3876 1 mov_write_colr_tag(pb, &mov->tracks[0], 0);
3877 else
3878 ✗ mov_write_aux_tag(pb, "auxC");
3879 }
3880 1 return update_size(pb, pos);
3881 }
3882
3883 1 static int mov_write_ipma_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
3884 {
3885 1 int64_t pos = avio_tell(pb);
3886 1 avio_wb32(pb, 0); /* size */
3887 1 ffio_wfourcc(pb, "ipma");
3888 1 avio_wb32(pb, 0); /* Version & flags */
3889 1 avio_wb32(pb, mov->nb_streams); /* entry_count */
3890
3891
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 for (int i = 0, index = 1; i < mov->nb_streams; i++) {
3892 1 avio_wb16(pb, i + 1); /* item_ID */
3893 1 avio_w8(pb, 4); /* association_count */
3894
3895 // ispe association.
3896 1 avio_w8(pb, index++); /* essential and property_index */
3897 // pixi association.
3898 1 avio_w8(pb, index++); /* essential and property_index */
3899 // av1C association.
3900 1 avio_w8(pb, 0x80 | index++); /* essential and property_index */
3901 // colr/auxC association.
3902 1 avio_w8(pb, index++); /* essential and property_index */
3903 }
3904 1 return update_size(pb, pos);
3905 }
3906
3907 1 static int mov_write_iprp_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
3908 {
3909 1 int64_t pos = avio_tell(pb);
3910 1 avio_wb32(pb, 0); /* size */
3911 1 ffio_wfourcc(pb, "iprp");
3912 1 mov_write_ipco_tag(pb, mov, s);
3913 1 mov_write_ipma_tag(pb, mov, s);
3914 1 return update_size(pb, pos);
3915 }
3916 #endif
3917
3918 2 static int mov_write_hmhd_tag(AVIOContext *pb)
3919 {
3920 /* This atom must be present, but leaving the values at zero
3921 * seems harmless. */
3922 2 avio_wb32(pb, 28); /* size */
3923 2 ffio_wfourcc(pb, "hmhd");
3924 2 avio_wb32(pb, 0); /* version, flags */
3925 2 avio_wb16(pb, 0); /* maxPDUsize */
3926 2 avio_wb16(pb, 0); /* avgPDUsize */
3927 2 avio_wb32(pb, 0); /* maxbitrate */
3928 2 avio_wb32(pb, 0); /* avgbitrate */
3929 2 avio_wb32(pb, 0); /* reserved */
3930 2 return 28;
3931 }
3932
3933 598 static int mov_write_minf_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
3934 {
3935 598 int64_t pos = avio_tell(pb);
3936 int ret;
3937
3938 598 avio_wb32(pb, 0); /* size */
3939 598 ffio_wfourcc(pb, "minf");
3940
2/2
✓ Branch 0 taken 238 times.
✓ Branch 1 taken 360 times.
598 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO)
3941 238 mov_write_vmhd_tag(pb, track);
3942
2/2
✓ Branch 0 taken 338 times.
✓ Branch 1 taken 22 times.
360 else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO)
3943 338 mov_write_smhd_tag(pb);
3944
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 16 times.
22 else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE) {
3945
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
6 if (track->tag == MKTAG('t','e','x','t') || is_clcp_track(track)) {
3946 1 mov_write_gmhd_tag(pb, track);
3947
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
5 } else if (track->tag == MOV_MP4_TTML_TAG) {
3948 2 mov_write_sthd_tag(pb);
3949 } else {
3950 3 mov_write_nmhd_tag(pb);
3951 }
3952
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 14 times.
16 } else if (track->tag == MKTAG('r','t','p',' ')) {
3953 2 mov_write_hmhd_tag(pb);
3954
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 1 times.
14 } else if (track->tag == MKTAG('t','m','c','d')) {
3955
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 9 times.
13 if (track->mode != MODE_MOV)
3956 4 mov_write_nmhd_tag(pb);
3957 else
3958 9 mov_write_gmhd_tag(pb, track);
3959
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 } else if (track->tag == MKTAG('g','p','m','d')) {
3960 1 mov_write_gmhd_tag(pb, track);
3961 }
3962
2/2
✓ Branch 0 taken 200 times.
✓ Branch 1 taken 398 times.
598 if (track->mode == MODE_MOV) /* ISO 14496-12 8.4.3.1 specifies hdlr only within mdia or meta boxes */
3963 200 mov_write_hdlr_tag(s, pb, NULL);
3964 598 mov_write_dinf_tag(pb);
3965
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 598 times.
598 if ((ret = mov_write_stbl_tag(s, pb, mov, track)) < 0)
3966 ✗ return ret;
3967 598 return update_size(pb, pos);
3968 }
3969
3970 2319 static void get_pts_range(MOVMuxContext *mov, MOVTrack *track,
3971 int64_t *start, int64_t *end, int elst, int mdhd)
3972 {
3973
5/6
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 2269 times.
✓ Branch 2 taken 38 times.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 38 times.
✗ Branch 5 not taken.
2319 if (track->tag == MKTAG('t','m','c','d') && mov->nb_meta_tmcd && track->nb_src_track) {
3974 // tmcd tracks gets track_duration set in mov_write_moov_tag from
3975 // another track's duration, while the end_pts may be left at zero.
3976 // Calculate the pts duration for that track instead.
3977 38 get_pts_range(mov, &mov->tracks[*track->src_track], start, end, elst, mdhd);
3978 38 *start = av_rescale(*start, track->timescale,
3979 38 mov->tracks[*track->src_track].timescale);
3980 38 *end = av_rescale(*end, track->timescale,
3981 38 mov->tracks[*track->src_track].timescale);
3982 38 return;
3983 }
3984
4/4
✓ Branch 0 taken 1683 times.
✓ Branch 1 taken 598 times.
✓ Branch 2 taken 1637 times.
✓ Branch 3 taken 46 times.
2281 if (!mdhd && track->end_pts != AV_NOPTS_VALUE &&
3985
1/2
✓ Branch 0 taken 1637 times.
✗ Branch 1 not taken.
1637 track->start_dts != AV_NOPTS_VALUE &&
3986
1/2
✓ Branch 0 taken 1637 times.
✗ Branch 1 not taken.
1637 track->start_cts != AV_NOPTS_VALUE) {
3987 1637 *start = track->start_dts + track->start_cts;
3988
2/2
✓ Branch 0 taken 529 times.
✓ Branch 1 taken 1108 times.
1637 *end = elst ? track->elst_end_pts : track->end_pts;
3989 1637 return;
3990 }
3991 644 *start = 0;
3992 644 *end = track->track_duration;
3993 }
3994
3995 598 static int64_t calc_samples_pts_duration(MOVMuxContext *mov, MOVTrack *track)
3996 {
3997 int64_t start, end;
3998 598 get_pts_range(mov, track, &start, &end, 0, 1);
3999 598 return end - start;
4000 }
4001
4002 // Calculate the actual duration of the track, after edits.
4003 // If it starts with a pts < 0, that is removed by the edit list.
4004 // If it starts with a pts > 0, the edit list adds a delay before that.
4005 // Thus, with edit lists enabled, the post-edit output of the file is
4006 // starting with pts=0.
4007 1154 static int64_t calc_pts_duration(MOVMuxContext *mov, MOVTrack *track)
4008 {
4009 int64_t start, end;
4010 1154 get_pts_range(mov, track, &start, &end, 0, 0);
4011
2/2
✓ Branch 0 taken 1064 times.
✓ Branch 1 taken 90 times.
1154 if (mov->use_editlist != 0)
4012 1064 start = 0;
4013 1154 return end - start;
4014 }
4015
4016 529 static int64_t calc_elst_duration(MOVMuxContext *mov, MOVTrack *track)
4017 {
4018 int64_t start, end;
4019 529 get_pts_range(mov, track, &start, &end, 1, 0);
4020 529 return end - start;
4021 }
4022
4023 1492 static int mov_mdhd_mvhd_tkhd_version(MOVMuxContext *mov, MOVTrack *track, int64_t duration)
4024 {
4025
4/4
✓ Branch 0 taken 1196 times.
✓ Branch 1 taken 296 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 1178 times.
1492 if (track && track->mode == MODE_ISM)
4026 18 return 1;
4027
2/2
✓ Branch 0 taken 1465 times.
✓ Branch 1 taken 9 times.
1474 if (duration < INT32_MAX)
4028 1465 return 0;
4029 9 return 1;
4030 }
4031
4032 598 static int mov_write_mdhd_tag(AVIOContext *pb, MOVMuxContext *mov,
4033 MOVTrack *track)
4034 {
4035 598 int64_t duration = calc_samples_pts_duration(mov, track);
4036 598 int version = mov_mdhd_mvhd_tkhd_version(mov, track, duration);
4037
4038
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 585 times.
598 (version == 1) ? avio_wb32(pb, 44) : avio_wb32(pb, 32); /* size */
4039 598 ffio_wfourcc(pb, "mdhd");
4040 598 avio_w8(pb, version);
4041 598 avio_wb24(pb, 0); /* flags */
4042
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 585 times.
598 if (version == 1) {
4043 13 avio_wb64(pb, track->time);
4044 13 avio_wb64(pb, track->time);
4045 } else {
4046 585 avio_wb32(pb, track->time); /* creation time */
4047 585 avio_wb32(pb, track->time); /* modification time */
4048 }
4049 598 avio_wb32(pb, track->timescale); /* time scale (sample rate for audio) */
4050
4/4
✓ Branch 0 taken 312 times.
✓ Branch 1 taken 286 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 303 times.
598 if (!track->entry && mov->mode == MODE_ISM)
4051
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 (version == 1) ? avio_wb64(pb, UINT64_C(0xffffffffffffffff)) : avio_wb32(pb, 0xffffffff);
4052
2/2
✓ Branch 0 taken 303 times.
✓ Branch 1 taken 286 times.
589 else if (!track->entry)
4053
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 299 times.
303 (version == 1) ? avio_wb64(pb, 0) : avio_wb32(pb, 0);
4054 else
4055
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 286 times.
286 (version == 1) ? avio_wb64(pb, duration) : avio_wb32(pb, duration); /* duration */
4056 598 avio_wb16(pb, track->language); /* language */
4057 598 avio_wb16(pb, 0); /* reserved (quality) */
4058
4059
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 585 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
598 if (version != 0 && track->mode == MODE_MOV) {
4060 ✗ av_log(NULL, AV_LOG_ERROR,
4061 "FATAL error, file duration too long for timebase, this file will not be\n"
4062 "playable with QuickTime. Choose a different timebase with "
4063 "-video_track_timescale or a different container format\n");
4064 }
4065
4066 598 return 32;
4067 }
4068
4069 598 static int mov_write_mdia_tag(AVFormatContext *s, AVIOContext *pb,
4070 MOVMuxContext *mov, MOVTrack *track)
4071 {
4072 598 int64_t pos = avio_tell(pb);
4073 int ret;
4074
4075 598 avio_wb32(pb, 0); /* size */
4076 598 ffio_wfourcc(pb, "mdia");
4077 598 mov_write_mdhd_tag(pb, mov, track);
4078 598 mov_write_hdlr_tag(s, pb, track);
4079
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 598 times.
598 if ((ret = mov_write_minf_tag(s, pb, mov, track)) < 0)
4080 ✗ return ret;
4081 598 return update_size(pb, pos);
4082 }
4083
4084 /* transformation matrix
4085 |a b u|
4086 |c d v|
4087 |tx ty w| */
4088 892 static void write_matrix(AVIOContext *pb, int16_t a, int16_t b, int16_t c,
4089 int16_t d, int16_t tx, int16_t ty)
4090 {
4091 892 avio_wb32(pb, a << 16); /* 16.16 format */
4092 892 avio_wb32(pb, b << 16); /* 16.16 format */
4093 892 avio_wb32(pb, 0); /* u in 2.30 format */
4094 892 avio_wb32(pb, c << 16); /* 16.16 format */
4095 892 avio_wb32(pb, d << 16); /* 16.16 format */
4096 892 avio_wb32(pb, 0); /* v in 2.30 format */
4097 892 avio_wb32(pb, tx << 16); /* 16.16 format */
4098 892 avio_wb32(pb, ty << 16); /* 16.16 format */
4099 892 avio_wb32(pb, 1 << 30); /* w in 2.30 format */
4100 892 }
4101
4102 598 static int mov_write_tkhd_tag(AVIOContext *pb, MOVMuxContext *mov,
4103 MOVTrack *track, AVStream *st)
4104 {
4105 1196 int64_t duration = av_rescale_rnd(calc_pts_duration(mov, track),
4106 598 mov->movie_timescale, track->timescale,
4107 AV_ROUND_UP);
4108 int version;
4109 598 int flags = MOV_TKHD_FLAG_IN_MOVIE;
4110 598 int group = 0;
4111
4112 598 uint32_t *display_matrix = NULL;
4113 int i;
4114
4115 #if CONFIG_AVIF_MUXER
4116
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 597 times.
598 if (mov->mode == MODE_AVIF)
4117
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (!mov->avif_loop_count)
4118 1 duration = INT64_MAX;
4119 else
4120 ✗ duration *= mov->avif_loop_count;
4121 #endif
4122
4123
2/2
✓ Branch 0 taken 585 times.
✓ Branch 1 taken 13 times.
598 if (st) {
4124 const AVPacketSideData *sd;
4125
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 581 times.
585 if (mov->per_stream_grouping)
4126 4 group = st->index;
4127 else
4128 581 group = st->codecpar->codec_type;
4129
4130 585 sd = av_packet_side_data_get(st->codecpar->coded_side_data,
4131 585 st->codecpar->nb_coded_side_data,
4132 AV_PKT_DATA_DISPLAYMATRIX);
4133
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 583 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
585 if (sd && sd->size == 9 * sizeof(*display_matrix))
4134 2 display_matrix = (uint32_t *)sd->data;
4135 }
4136
4137
2/2
✓ Branch 0 taken 374 times.
✓ Branch 1 taken 224 times.
598 if (track->flags & MOV_TRACK_ENABLED)
4138 374 flags |= MOV_TKHD_FLAG_ENABLED;
4139
4140 598 version = mov_mdhd_mvhd_tkhd_version(mov, track, duration);
4141
4142
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 584 times.
598 (version == 1) ? avio_wb32(pb, 104) : avio_wb32(pb, 92); /* size */
4143 598 ffio_wfourcc(pb, "tkhd");
4144 598 avio_w8(pb, version);
4145 598 avio_wb24(pb, flags);
4146
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 584 times.
598 if (version == 1) {
4147 14 avio_wb64(pb, track->time);
4148 14 avio_wb64(pb, track->time);
4149 } else {
4150 584 avio_wb32(pb, track->time); /* creation time */
4151 584 avio_wb32(pb, track->time); /* modification time */
4152 }
4153 598 avio_wb32(pb, track->track_id); /* track-id */
4154 598 avio_wb32(pb, 0); /* reserved */
4155
4/4
✓ Branch 0 taken 312 times.
✓ Branch 1 taken 286 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 303 times.
598 if (!track->entry && mov->mode == MODE_ISM)
4156
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 (version == 1) ? avio_wb64(pb, UINT64_C(0xffffffffffffffff)) : avio_wb32(pb, 0xffffffff);
4157
2/2
✓ Branch 0 taken 303 times.
✓ Branch 1 taken 286 times.
589 else if (!track->entry)
4158
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 299 times.
303 (version == 1) ? avio_wb64(pb, 0) : avio_wb32(pb, 0);
4159 else
4160
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 285 times.
286 (version == 1) ? avio_wb64(pb, duration) : avio_wb32(pb, duration);
4161
4162 598 avio_wb32(pb, 0); /* reserved */
4163 598 avio_wb32(pb, 0); /* reserved */
4164 598 avio_wb16(pb, 0); /* layer */
4165 598 avio_wb16(pb, group); /* alternate group) */
4166 /* Volume, only for audio */
4167
2/2
✓ Branch 0 taken 338 times.
✓ Branch 1 taken 260 times.
598 if (track->par->codec_type == AVMEDIA_TYPE_AUDIO)
4168 338 avio_wb16(pb, 0x0100);
4169 else
4170 260 avio_wb16(pb, 0);
4171 598 avio_wb16(pb, 0); /* reserved */
4172
4173 /* Matrix structure */
4174
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 596 times.
598 if (display_matrix) {
4175
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 2 times.
20 for (i = 0; i < 9; i++)
4176 18 avio_wb32(pb, display_matrix[i]);
4177 } else {
4178 596 write_matrix(pb, 1, 0, 0, 1, 0, 0);
4179 }
4180 /* Track width and height, for visual only */
4181
4/4
✓ Branch 0 taken 585 times.
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 347 times.
✓ Branch 3 taken 238 times.
598 if (st && (track->par->codec_type == AVMEDIA_TYPE_VIDEO ||
4182
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 342 times.
590 track->par->codec_type == AVMEDIA_TYPE_SUBTITLE)) {
4183 int64_t track_width_1616;
4184
4/4
✓ Branch 0 taken 97 times.
✓ Branch 1 taken 146 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 96 times.
243 if (track->mode == MODE_MOV || track->mode == MODE_AVIF) {
4185 147 track_width_1616 = track->par->width * 0x10000ULL;
4186 } else {
4187 96 track_width_1616 = av_rescale(st->sample_aspect_ratio.num,
4188 96 track->par->width * 0x10000LL,
4189 96 st->sample_aspect_ratio.den);
4190
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 75 times.
96 if (!track_width_1616 ||
4191
2/4
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 21 times.
21 track->height != track->par->height ||
4192 track_width_1616 > UINT32_MAX)
4193 75 track_width_1616 = track->par->width * 0x10000ULL;
4194 }
4195
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 243 times.
243 if (track_width_1616 > UINT32_MAX) {
4196 ✗ av_log(mov->fc, AV_LOG_WARNING, "track width is too large\n");
4197 ✗ track_width_1616 = 0;
4198 }
4199 243 avio_wb32(pb, track_width_1616);
4200
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 243 times.
243 if (track->height > 0xFFFF) {
4201 ✗ av_log(mov->fc, AV_LOG_WARNING, "track height is too large\n");
4202 ✗ avio_wb32(pb, 0);
4203 } else
4204 243 avio_wb32(pb, track->height * 0x10000U);
4205 } else {
4206 355 avio_wb32(pb, 0);
4207 355 avio_wb32(pb, 0);
4208 }
4209 598 return 0x5c;
4210 }
4211
4212 1 static int mov_write_tapt_tag(AVIOContext *pb, MOVTrack *track)
4213 {
4214 1 int32_t width = av_rescale(track->par->sample_aspect_ratio.num, track->par->width,
4215 1 track->par->sample_aspect_ratio.den);
4216
4217 1 int64_t pos = avio_tell(pb);
4218
4219 1 avio_wb32(pb, 0); /* size */
4220 1 ffio_wfourcc(pb, "tapt");
4221
4222 1 avio_wb32(pb, 20);
4223 1 ffio_wfourcc(pb, "clef");
4224 1 avio_wb32(pb, 0);
4225 1 avio_wb32(pb, width << 16);
4226 1 avio_wb32(pb, track->par->height << 16);
4227
4228 1 avio_wb32(pb, 20);
4229 1 ffio_wfourcc(pb, "prof");
4230 1 avio_wb32(pb, 0);
4231 1 avio_wb32(pb, width << 16);
4232 1 avio_wb32(pb, track->par->height << 16);
4233
4234 1 avio_wb32(pb, 20);
4235 1 ffio_wfourcc(pb, "enof");
4236 1 avio_wb32(pb, 0);
4237 1 avio_wb32(pb, track->par->width << 16);
4238 1 avio_wb32(pb, track->par->height << 16);
4239
4240 1 return update_size(pb, pos);
4241 }
4242
4243 // This box is written in the following cases:
4244 // * Seems important for the psp playback. Without it the movie seems to hang.
4245 // * Used for specifying the looping behavior of animated AVIF (as specified
4246 // in Section 9.6 of the HEIF specification ISO/IEC 23008-12).
4247 529 static int mov_write_edts_tag(AVIOContext *pb, MOVMuxContext *mov,
4248 MOVTrack *track)
4249 {
4250 1058 int64_t duration = av_rescale_rnd(calc_elst_duration(mov, track),
4251 529 mov->movie_timescale, track->timescale,
4252 AV_ROUND_UP);
4253 529 int version = duration < INT32_MAX ? 0 : 1;
4254 int entry_size, entry_count, size;
4255 529 int64_t delay, start_ct = track->start_cts;
4256 529 int64_t start_dts = track->start_dts;
4257 529 int flags = 0;
4258
4259
2/2
✓ Branch 0 taken 269 times.
✓ Branch 1 taken 260 times.
529 if (track->entry) {
4260
4/6
✓ Branch 0 taken 269 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 266 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
269 if (start_dts != track->cluster[0].dts || (start_ct != track->cluster[0].cts && track->cluster[0].dts >= 0)) {
4261
4262 ✗ av_log(mov->fc, AV_LOG_DEBUG,
4263 "EDTS using dts:%"PRId64" cts:%d instead of dts:%"PRId64" cts:%"PRId64" tid:%d\n",
4264 ✗ track->cluster[0].dts, track->cluster[0].cts,
4265 start_dts, start_ct, track->track_id);
4266 ✗ start_dts = track->cluster[0].dts;
4267 ✗ start_ct = track->cluster[0].cts;
4268 }
4269 }
4270
4271 529 delay = av_rescale_rnd(start_dts + start_ct, mov->movie_timescale,
4272 529 track->timescale, AV_ROUND_DOWN);
4273
4274 #if CONFIG_AVIF_MUXER
4275
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 529 times.
529 if (mov->mode == MODE_AVIF) {
4276 ✗ delay = 0;
4277 // Section 9.6.3 of ISO/IEC 23008-12: flags specifies repetition of the
4278 // edit list as follows: (flags & 1) equal to 0 specifies that the edit
4279 // list is not repeated, while (flags & 1) equal to 1 specifies that the
4280 // edit list is repeated.
4281 ✗ flags = mov->avif_loop_count != 1;
4282 ✗ start_ct = 0;
4283 }
4284 #endif
4285
4286 529 version |= delay < INT32_MAX ? 0 : 1;
4287
4288
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 525 times.
529 entry_size = (version == 1) ? 20 : 12;
4289
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 524 times.
529 entry_count = 1 + (delay > 0);
4290 529 size = 24 + entry_count * entry_size;
4291
4292 /* write the atom data */
4293 529 avio_wb32(pb, size);
4294 529 ffio_wfourcc(pb, "edts");
4295 529 avio_wb32(pb, size - 8);
4296 529 ffio_wfourcc(pb, "elst");
4297 529 avio_w8(pb, version);
4298 529 avio_wb24(pb, flags); /* flags */
4299
4300 529 avio_wb32(pb, entry_count);
4301
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 524 times.
529 if (delay > 0) { /* add an empty edit to delay presentation */
4302 /* In the positive delay case, the delay includes the cts
4303 * offset, and the second edit list entry below trims out
4304 * the same amount from the actual content. This makes sure
4305 * that the offset last sample is included in the edit
4306 * list duration as well. */
4307
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (version == 1) {
4308 ✗ avio_wb64(pb, delay);
4309 ✗ avio_wb64(pb, -1);
4310 } else {
4311 5 avio_wb32(pb, delay);
4312 5 avio_wb32(pb, -1);
4313 }
4314 5 avio_wb32(pb, 0x00010000);
4315
1/2
✓ Branch 0 taken 524 times.
✗ Branch 1 not taken.
524 } else if (mov->mode != MODE_AVIF) {
4316 /* Avoid accidentally ending up with start_ct = -1 which has got a
4317 * special meaning. Normally start_ct should end up positive or zero
4318 * here, but use FFMIN in case dts is a small positive integer
4319 * rounded to 0 when represented in movie timescale units. */
4320
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 524 times.
524 av_assert0(av_rescale_rnd(start_dts, mov->movie_timescale, track->timescale, AV_ROUND_DOWN) <= 0);
4321 524 start_ct = -FFMIN(start_dts, 0);
4322
4323 #if CONFIG_IAMFENC
4324
3/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 518 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
524 if (track->iamf && track->par->codec_id == AV_CODEC_ID_OPUS)
4325 ✗ start_ct = av_rescale(start_ct, 48000, track->par->sample_rate);
4326 #endif
4327 /* Note, this delay is calculated from the pts of the first sample,
4328 * ensuring that we don't reduce the duration for cases with
4329 * dts<0 pts=0. */
4330 524 duration += delay;
4331 }
4332
4333 /* For fragmented files, we don't know the full length yet. Setting
4334 * duration to 0 allows us to only specify the offset, including
4335 * the rest of the content (from all future fragments) without specifying
4336 * an explicit duration.
4337 *
4338 * For hybrid_fragmented during mov_write_trailer (mov->moov_written != 0),
4339 * don't reset duration to zero.
4340 */
4341
2/2
✓ Branch 0 taken 264 times.
✓ Branch 1 taken 265 times.
529 if (mov->flags & FF_MOV_FLAG_FRAGMENT &&
4342
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 264 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
264 !(mov->flags & FF_MOV_FLAG_HYBRID_FRAGMENTED && mov->moov_written))
4343 264 duration = 0;
4344
4345 /* duration */
4346
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 525 times.
529 if (version == 1) {
4347 4 avio_wb64(pb, duration);
4348 4 avio_wb64(pb, start_ct);
4349 } else {
4350 525 avio_wb32(pb, duration);
4351 525 avio_wb32(pb, start_ct);
4352 }
4353 529 avio_wb32(pb, 0x00010000);
4354 529 return size;
4355 }
4356
4357 15 static int mov_write_tref_tag(AVIOContext *pb, MOVTrack *track)
4358 {
4359 15 int64_t pos = avio_tell(pb);
4360 15 avio_wb32(pb, 0); // size placeholder
4361 15 ffio_wfourcc(pb, "tref");
4362
4363
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 15 times.
30 for (int i = 0; i < track->nb_tref_tags; i++) {
4364 15 MovTag *tag = &track->tref_tags[i];
4365 15 avio_wb32(pb, 8 + tag->nb_id * sizeof(*tag->id)); // size (subatom)
4366 15 avio_wl32(pb, tag->name);
4367
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 15 times.
32 for (int j = 0; j < tag->nb_id; j++)
4368 17 avio_wb32(pb, tag->id[j]);
4369 }
4370 15 return update_size(pb, pos);
4371 }
4372
4373 // goes at the end of each track! ... Critical for PSP playback ("Incompatible data" without it)
4374 2 static int mov_write_uuid_tag_psp(AVIOContext *pb, MOVTrack *mov)
4375 {
4376 2 avio_wb32(pb, 0x34); /* size ... reports as 28 in mp4box! */
4377 2 ffio_wfourcc(pb, "uuid");
4378 2 ffio_wfourcc(pb, "USMT");
4379 2 avio_wb32(pb, 0x21d24fce);
4380 2 avio_wb32(pb, 0xbb88695c);
4381 2 avio_wb32(pb, 0xfac9c740);
4382 2 avio_wb32(pb, 0x1c); // another size here!
4383 2 ffio_wfourcc(pb, "MTDT");
4384 2 avio_wb32(pb, 0x00010012);
4385 2 avio_wb32(pb, 0x0a);
4386 2 avio_wb32(pb, 0x55c40000);
4387 2 avio_wb32(pb, 0x1);
4388 2 avio_wb32(pb, 0x0);
4389 2 return 0x34;
4390 }
4391
4392 2 static int mov_write_udta_sdp(AVIOContext *pb, MOVTrack *track)
4393 {
4394 2 AVFormatContext *ctx = track->rtp_ctx;
4395 2 char buf[1000] = "";
4396 int len;
4397
4398
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 av_assert0(track->nb_src_track);
4399 2 ff_sdp_write_media(buf, sizeof(buf), ctx->streams[0], *track->src_track,
4400 NULL, NULL, 0, 0, ctx);
4401 2 av_strlcatf(buf, sizeof(buf), "a=control:streamid=%d\r\n", track->track_id);
4402 2 len = strlen(buf);
4403
4404 2 avio_wb32(pb, len + 24);
4405 2 ffio_wfourcc(pb, "udta");
4406 2 avio_wb32(pb, len + 16);
4407 2 ffio_wfourcc(pb, "hnti");
4408 2 avio_wb32(pb, len + 8);
4409 2 ffio_wfourcc(pb, "sdp ");
4410 2 avio_write(pb, buf, len);
4411 2 return len + 24;
4412 }
4413
4414 574 static int mov_write_track_metadata(AVIOContext *pb, AVStream *st,
4415 const char *tag, const char *str)
4416 {
4417 574 int64_t pos = avio_tell(pb);
4418 574 AVDictionaryEntry *t = av_dict_get(st->metadata, str, NULL, 0);
4419
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 573 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
574 if (!t || !utf8len(t->value))
4420 573 return 0;
4421
4422 1 avio_wb32(pb, 0); /* size */
4423 1 ffio_wfourcc(pb, tag); /* type */
4424 1 avio_write(pb, t->value, strlen(t->value)); /* UTF8 string value */
4425 1 return update_size(pb, pos);
4426 }
4427
4428 2 static int mov_write_track_kind(AVIOContext *pb, const char *scheme_uri,
4429 const char *value)
4430 {
4431 2 int64_t pos = avio_tell(pb);
4432
4433 /* Box|FullBox basics */
4434 2 avio_wb32(pb, 0); /* size placeholder */
4435 2 ffio_wfourcc(pb, (const unsigned char *)"kind");
4436 2 avio_w8(pb, 0); /* version = 0 */
4437 2 avio_wb24(pb, 0); /* flags = 0 */
4438
4439 /* Required null-terminated scheme URI */
4440 2 avio_write(pb, (const unsigned char *)scheme_uri,
4441 2 strlen(scheme_uri));
4442 2 avio_w8(pb, 0);
4443
4444 /* Optional value string */
4445
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 if (value && value[0])
4446 2 avio_write(pb, (const unsigned char *)value,
4447 2 strlen(value));
4448
4449 2 avio_w8(pb, 0);
4450
4451 2 return update_size(pb, pos);
4452 }
4453
4454 380 static int mov_write_track_kinds(AVIOContext *pb, AVStream *st)
4455 {
4456 380 int ret = AVERROR_BUG;
4457
4458
2/2
✓ Branch 0 taken 380 times.
✓ Branch 1 taken 380 times.
760 for (int i = 0; ff_mov_track_kind_table[i].scheme_uri; i++) {
4459 380 const struct MP4TrackKindMapping map = ff_mov_track_kind_table[i];
4460
4461
2/2
✓ Branch 0 taken 1900 times.
✓ Branch 1 taken 380 times.
2280 for (int j = 0; map.value_maps[j].disposition; j++) {
4462 1900 const struct MP4TrackKindValueMapping value_map = map.value_maps[j];
4463
2/2
✓ Branch 0 taken 1898 times.
✓ Branch 1 taken 2 times.
1900 if (!(st->disposition & value_map.disposition))
4464 1898 continue;
4465
4466
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if ((ret = mov_write_track_kind(pb, map.scheme_uri, value_map.value)) < 0)
4467 ✗ return ret;
4468 }
4469 }
4470
4471 380 return 0;
4472 }
4473
4474 598 static int mov_write_track_udta_tag(AVIOContext *pb, MOVMuxContext *mov,
4475 AVStream *st)
4476 {
4477 AVIOContext *pb_buf;
4478 int ret, size;
4479 uint8_t *buf;
4480
4481
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 585 times.
598 if (!st)
4482 13 return 0;
4483
4484 585 ret = avio_open_dyn_buf(&pb_buf);
4485
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 585 times.
585 if (ret < 0)
4486 ✗ return ret;
4487
4488
2/2
✓ Branch 0 taken 574 times.
✓ Branch 1 taken 11 times.
585 if (mov->mode & (MODE_MP4|MODE_MOV))
4489 574 mov_write_track_metadata(pb_buf, st, "name", "title");
4490
4491
2/2
✓ Branch 0 taken 380 times.
✓ Branch 1 taken 205 times.
585 if (mov->mode & MODE_MP4) {
4492
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 380 times.
380 if ((ret = mov_write_track_kinds(pb_buf, st)) < 0)
4493 ✗ goto end;
4494 }
4495
4496
2/2
✓ Branch 1 taken 582 times.
✓ Branch 2 taken 3 times.
585 if ((size = avio_get_dyn_buf(pb_buf, &buf)) > 0) {
4497 3 avio_wb32(pb, size + 8);
4498 3 ffio_wfourcc(pb, "udta");
4499 3 avio_write(pb, buf, size);
4500 }
4501 582 end:
4502 585 ffio_free_dyn_buf(&pb_buf);
4503
4504 585 return ret;
4505 }
4506
4507 598 static int mov_write_trak_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov,
4508 MOVTrack *track, AVStream *st)
4509 {
4510 598 int64_t pos = avio_tell(pb);
4511 598 int entry_backup = track->entry;
4512 598 int chunk_backup = track->chunkCount;
4513 int ret;
4514
4515 /* If we want to have an empty moov, but some samples already have been
4516 * buffered (delay_moov), pretend that no samples have been written yet. */
4517
2/2
✓ Branch 0 taken 308 times.
✓ Branch 1 taken 290 times.
598 if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV)
4518 308 track->chunkCount = track->entry = 0;
4519
4520 598 avio_wb32(pb, 0); /* size */
4521 598 ffio_wfourcc(pb, "trak");
4522 598 mov_write_tkhd_tag(pb, mov, track, st);
4523
4524 av_assert2(mov->use_editlist >= 0);
4525
4526
2/2
✓ Branch 0 taken 556 times.
✓ Branch 1 taken 42 times.
598 if (track->start_dts != AV_NOPTS_VALUE) {
4527
2/2
✓ Branch 0 taken 529 times.
✓ Branch 1 taken 27 times.
556 if (mov->use_editlist)
4528 529 mov_write_edts_tag(pb, mov, track); // PSP Movies and several other cases require edts box
4529
5/8
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 27 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 27 times.
27 else if ((track->entry && track->cluster[0].dts) || track->mode == MODE_PSP || is_clcp_track(track))
4530 ✗ av_log(mov->fc, AV_LOG_WARNING,
4531 "Not writing any edit list even though one would have been required\n");
4532 }
4533
4534
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 if (mov->is_animated_avif)
4535 ✗ mov_write_edts_tag(pb, mov, track);
4536
4537
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 583 times.
598 if (track->nb_tref_tags)
4538 15 mov_write_tref_tag(pb, track);
4539
4540
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 598 times.
598 if ((ret = mov_write_mdia_tag(s, pb, mov, track)) < 0)
4541 ✗ return ret;
4542
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 596 times.
598 if (track->mode == MODE_PSP)
4543 2 mov_write_uuid_tag_psp(pb, track); // PSP Movies require this uuid box
4544
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 596 times.
598 if (track->tag == MKTAG('r','t','p',' '))
4545 2 mov_write_udta_sdp(pb, track);
4546
2/2
✓ Branch 0 taken 200 times.
✓ Branch 1 taken 398 times.
598 if (track->mode == MODE_MOV) {
4547
2/2
✓ Branch 0 taken 146 times.
✓ Branch 1 taken 54 times.
200 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
4548 146 double sample_aspect_ratio = av_q2d(st->sample_aspect_ratio);
4549
4/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 141 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 4 times.
146 if (st->sample_aspect_ratio.num && 1.0 != sample_aspect_ratio) {
4550 1 mov_write_tapt_tag(pb, track);
4551 }
4552 }
4553
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 200 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
200 if (is_clcp_track(track) && st->sample_aspect_ratio.num) {
4554 ✗ mov_write_tapt_tag(pb, track);
4555 }
4556 }
4557 598 mov_write_track_udta_tag(pb, mov, st);
4558 598 track->entry = entry_backup;
4559 598 track->chunkCount = chunk_backup;
4560 598 return update_size(pb, pos);
4561 }
4562
4563 ✗ static int mov_write_iods_tag(AVIOContext *pb, MOVMuxContext *mov)
4564 {
4565 ✗ int i, has_audio = 0, has_video = 0;
4566 ✗ int64_t pos = avio_tell(pb);
4567 ✗ int audio_profile = mov->iods_audio_profile;
4568 ✗ int video_profile = mov->iods_video_profile;
4569 ✗ for (i = 0; i < mov->nb_tracks; i++) {
4570 ✗ if (mov->tracks[i].entry > 0 || mov->flags & FF_MOV_FLAG_EMPTY_MOOV) {
4571 ✗ has_audio |= mov->tracks[i].par->codec_type == AVMEDIA_TYPE_AUDIO;
4572 ✗ has_video |= mov->tracks[i].par->codec_type == AVMEDIA_TYPE_VIDEO;
4573 }
4574 }
4575 ✗ if (audio_profile < 0)
4576 ✗ audio_profile = 0xFF - has_audio;
4577 ✗ if (video_profile < 0)
4578 ✗ video_profile = 0xFF - has_video;
4579 ✗ avio_wb32(pb, 0x0); /* size */
4580 ✗ ffio_wfourcc(pb, "iods");
4581 ✗ avio_wb32(pb, 0); /* version & flags */
4582 ✗ put_descr(pb, 0x10, 7);
4583 ✗ avio_wb16(pb, 0x004f);
4584 ✗ avio_w8(pb, 0xff);
4585 ✗ avio_w8(pb, 0xff);
4586 ✗ avio_w8(pb, audio_profile);
4587 ✗ avio_w8(pb, video_profile);
4588 ✗ avio_w8(pb, 0xff);
4589 ✗ return update_size(pb, pos);
4590 }
4591
4592 328 static int mov_write_trex_tag(AVIOContext *pb, MOVTrack *track)
4593 {
4594 328 avio_wb32(pb, 0x20); /* size */
4595 328 ffio_wfourcc(pb, "trex");
4596 328 avio_wb32(pb, 0); /* version & flags */
4597 328 avio_wb32(pb, track->track_id); /* track ID */
4598 328 avio_wb32(pb, 1); /* default sample description index */
4599 328 avio_wb32(pb, 0); /* default sample duration */
4600 328 avio_wb32(pb, 0); /* default sample size */
4601 328 avio_wb32(pb, 0); /* default sample flags */
4602 328 return 0;
4603 }
4604
4605 74 static int mov_write_mvex_tag(AVIOContext *pb, MOVMuxContext *mov)
4606 {
4607 74 int64_t pos = avio_tell(pb);
4608 int i;
4609 74 avio_wb32(pb, 0x0); /* size */
4610 74 ffio_wfourcc(pb, "mvex");
4611
2/2
✓ Branch 0 taken 328 times.
✓ Branch 1 taken 74 times.
402 for (i = 0; i < mov->nb_tracks; i++)
4612 328 mov_write_trex_tag(pb, &mov->tracks[i]);
4613 74 return update_size(pb, pos);
4614 }
4615
4616 296 static int mov_write_mvhd_tag(AVIOContext *pb, MOVMuxContext *mov)
4617 {
4618 296 int max_track_id = 1, i;
4619 296 int64_t max_track_len = 0;
4620 int version;
4621 int timescale;
4622
4623
2/2
✓ Branch 0 taken 600 times.
✓ Branch 1 taken 296 times.
896 for (i = 0; i < mov->nb_tracks; i++) {
4624
3/4
✓ Branch 0 taken 556 times.
✓ Branch 1 taken 44 times.
✓ Branch 2 taken 556 times.
✗ Branch 3 not taken.
600 if (mov->tracks[i].entry > 0 && mov->tracks[i].timescale) {
4625 1112 int64_t max_track_len_temp = av_rescale_rnd(
4626 556 calc_pts_duration(mov, &mov->tracks[i]),
4627 556 mov->movie_timescale,
4628 556 mov->tracks[i].timescale,
4629 AV_ROUND_UP);
4630
2/2
✓ Branch 0 taken 287 times.
✓ Branch 1 taken 269 times.
556 if (max_track_len < max_track_len_temp)
4631 287 max_track_len = max_track_len_temp;
4632
2/2
✓ Branch 0 taken 284 times.
✓ Branch 1 taken 272 times.
556 if (max_track_id < mov->tracks[i].track_id)
4633 284 max_track_id = mov->tracks[i].track_id;
4634 }
4635 }
4636 /* If using delay_moov, make sure the output is the same as if no
4637 * samples had been written yet. */
4638
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 232 times.
296 if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV) {
4639 64 max_track_len = 0;
4640 64 max_track_id = 1;
4641 }
4642
4643 296 version = mov_mdhd_mvhd_tkhd_version(mov, NULL, max_track_len);
4644
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 296 times.
296 avio_wb32(pb, version == 1 ? 120 : 108); /* size */
4645
4646 296 ffio_wfourcc(pb, "mvhd");
4647 296 avio_w8(pb, version);
4648 296 avio_wb24(pb, 0); /* flags */
4649
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 296 times.
296 if (version == 1) {
4650 ✗ avio_wb64(pb, mov->time);
4651 ✗ avio_wb64(pb, mov->time);
4652 } else {
4653 296 avio_wb32(pb, mov->time); /* creation time */
4654 296 avio_wb32(pb, mov->time); /* modification time */
4655 }
4656
4657 296 timescale = mov->movie_timescale;
4658
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 295 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
296 if (mov->mode == MODE_AVIF && !timescale)
4659 ✗ timescale = mov->tracks[0].timescale;
4660
4661 296 avio_wb32(pb, timescale);
4662
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 296 times.
296 (version == 1) ? avio_wb64(pb, max_track_len) : avio_wb32(pb, max_track_len); /* duration of longest track */
4663
4664 296 avio_wb32(pb, 0x00010000); /* reserved (preferred rate) 1.0 = normal */
4665 296 avio_wb16(pb, 0x0100); /* reserved (preferred volume) 1.0 = normal */
4666 296 ffio_fill(pb, 0, 2 + 2 * 4); /* reserved */
4667
4668 /* Matrix structure */
4669 296 write_matrix(pb, 1, 0, 0, 1, 0, 0);
4670
4671 296 avio_wb32(pb, 0); /* reserved (preview time) */
4672 296 avio_wb32(pb, 0); /* reserved (preview duration) */
4673 296 avio_wb32(pb, 0); /* reserved (poster time) */
4674 296 avio_wb32(pb, 0); /* reserved (selection time) */
4675 296 avio_wb32(pb, 0); /* reserved (selection duration) */
4676 296 avio_wb32(pb, 0); /* reserved (current time) */
4677 296 avio_wb32(pb, max_track_id + 1); /* Next track id */
4678 296 return 0x6c;
4679 }
4680
4681 128 static int mov_write_itunes_hdlr_tag(AVIOContext *pb, MOVMuxContext *mov,
4682 AVFormatContext *s)
4683 {
4684 128 avio_wb32(pb, 33); /* size */
4685 128 ffio_wfourcc(pb, "hdlr");
4686 128 avio_wb32(pb, 0);
4687 128 avio_wb32(pb, 0);
4688 128 ffio_wfourcc(pb, "mdir");
4689 128 ffio_wfourcc(pb, "appl");
4690 128 avio_wb32(pb, 0);
4691 128 avio_wb32(pb, 0);
4692 128 avio_w8(pb, 0);
4693 128 return 33;
4694 }
4695
4696 /* helper function to write a data tag with the specified string as data */
4697 84 static int mov_write_string_data_tag(AVIOContext *pb, const char *data, int lang, int long_style)
4698 {
4699 84 size_t data_len = strlen(data);
4700
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 42 times.
84 if (long_style) {
4701 42 int size = 16 + data_len;
4702 42 avio_wb32(pb, size); /* size */
4703 42 ffio_wfourcc(pb, "data");
4704 42 avio_wb32(pb, 1);
4705 42 avio_wb32(pb, 0);
4706 42 avio_write(pb, data, data_len);
4707 42 return size;
4708 } else {
4709 42 avio_wb16(pb, data_len); /* string length */
4710
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 16 times.
42 if (!lang)
4711 26 lang = ff_mov_iso639_to_lang("und", 1);
4712 42 avio_wb16(pb, lang);
4713 42 avio_write(pb, data, data_len);
4714 42 return data_len + 4;
4715 }
4716 }
4717
4718 83 static int mov_write_string_tag(AVIOContext *pb, const char *name,
4719 const char *value, int lang, int long_style)
4720 {
4721 83 int size = 0;
4722
2/4
✓ Branch 0 taken 83 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 83 times.
✗ Branch 3 not taken.
83 if (value && value[0]) {
4723 83 int64_t pos = avio_tell(pb);
4724 83 avio_wb32(pb, 0); /* size */
4725 83 ffio_wfourcc(pb, name);
4726 83 mov_write_string_data_tag(pb, value, lang, long_style);
4727 83 size = update_size(pb, pos);
4728 }
4729 83 return size;
4730 }
4731
4732 1 static int mov_write_freeform_tag(AVIOContext *pb, const char *mean,
4733 const char *name, const char *data)
4734 {
4735
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (!data || !data[0])
4736 ✗ return 0;
4737
4738 static const char stub_flags[4] = {0, 0, 0, 0};
4739
4740 1 int64_t entry_pos = avio_tell(pb);
4741 1 avio_wb32(pb, 0); /* size */
4742 1 ffio_wfourcc(pb, "----"); /* freeform */
4743
4744 1 size_t mean_len = strlen(mean);
4745 1 avio_wb32(pb, 12 + mean_len);
4746 1 ffio_wfourcc(pb, "mean");
4747 1 avio_write(pb, &stub_flags[0], sizeof(stub_flags));
4748 1 avio_write(pb, mean, mean_len);
4749
4750 1 size_t name_len = strlen(name);
4751 1 avio_wb32(pb, 12 + name_len);
4752 1 ffio_wfourcc(pb, "name");
4753 1 avio_write(pb, &stub_flags[0], sizeof(stub_flags));
4754 1 avio_write(pb, name, name_len);
4755
4756 1 mov_write_string_data_tag(pb, data, 0, 1);
4757
4758 1 return update_size(pb, entry_pos);
4759 }
4760
4761 4756 static AVDictionaryEntry *get_metadata_lang(AVFormatContext *s,
4762 const char *tag, int *lang)
4763 {
4764 int l, len, len2;
4765 4756 AVDictionaryEntry *t, *t2 = NULL;
4766 char tag2[16];
4767
4768 4756 *lang = 0;
4769
4770
2/2
✓ Branch 1 taken 4684 times.
✓ Branch 2 taken 72 times.
4756 if (!(t = av_dict_get(s->metadata, tag, NULL, 0)))
4771 4684 return NULL;
4772
4773 72 len = strlen(t->key);
4774 72 snprintf(tag2, sizeof(tag2), "%s-", tag);
4775
2/2
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 56 times.
72 while ((t2 = av_dict_get(s->metadata, tag2, t2, AV_DICT_IGNORE_SUFFIX))) {
4776 16 len2 = strlen(t2->key);
4777
2/4
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
16 if (len2 == len + 4 && !strcmp(t->value, t2->value)
4778
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 && (l = ff_mov_iso639_to_lang(&t2->key[len2 - 3], 1)) >= 0) {
4779 16 *lang = l;
4780 16 return t;
4781 }
4782 }
4783 56 return t;
4784 }
4785
4786 4628 static int mov_write_string_metadata(AVFormatContext *s, AVIOContext *pb,
4787 const char *name, const char *tag,
4788 int long_style)
4789 {
4790 int lang;
4791 4628 AVDictionaryEntry *t = get_metadata_lang(s, tag, &lang);
4792
2/2
✓ Branch 0 taken 4556 times.
✓ Branch 1 taken 72 times.
4628 if (!t)
4793 4556 return 0;
4794 72 return mov_write_string_tag(pb, name, t->value, lang, long_style);
4795 }
4796
4797 128 static int mov_write_custom_metadata(AVFormatContext *s, AVIOContext *pb,
4798 const char *mean, const char *name,
4799 const char *tag)
4800 {
4801 128 AVDictionaryEntry *t = av_dict_get(s->metadata, tag, NULL, 0);
4802
2/2
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 1 times.
128 if (!t)
4803 127 return 0;
4804 1 return mov_write_freeform_tag(pb, mean, name, t->value);
4805 }
4806
4807 /* iTunes bpm number */
4808 128 static int mov_write_tmpo_tag(AVIOContext *pb, AVFormatContext *s)
4809 {
4810 128 AVDictionaryEntry *t = av_dict_get(s->metadata, "tmpo", NULL, 0);
4811
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 128 times.
128 int size = 0, tmpo = t ? atoi(t->value) : 0;
4812
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 128 times.
128 if (tmpo) {
4813 ✗ size = 26;
4814 ✗ avio_wb32(pb, size);
4815 ✗ ffio_wfourcc(pb, "tmpo");
4816 ✗ avio_wb32(pb, size-8); /* size */
4817 ✗ ffio_wfourcc(pb, "data");
4818 ✗ avio_wb32(pb, 0x15); //type specifier
4819 ✗ avio_wb32(pb, 0);
4820 ✗ avio_wb16(pb, tmpo); // data
4821 }
4822 128 return size;
4823 }
4824
4825 /* 3GPP TS 26.244 */
4826 128 static int mov_write_loci_tag(AVFormatContext *s, AVIOContext *pb)
4827 {
4828 int lang;
4829 128 int64_t pos = avio_tell(pb);
4830 double latitude, longitude, altitude;
4831 int32_t latitude_fix, longitude_fix, altitude_fix;
4832 128 AVDictionaryEntry *t = get_metadata_lang(s, "location", &lang);
4833 128 const char *ptr, *place = "";
4834 char *end;
4835 static const char *astronomical_body = "earth";
4836
1/2
✓ Branch 0 taken 128 times.
✗ Branch 1 not taken.
128 if (!t)
4837 128 return 0;
4838
4839 ✗ ptr = t->value;
4840 ✗ latitude = strtod(ptr, &end);
4841 ✗ if (end == ptr) {
4842 ✗ av_log(s, AV_LOG_WARNING, "malformed location metadata\n");
4843 ✗ return 0;
4844 }
4845 ✗ ptr = end;
4846 ✗ longitude = strtod(ptr, &end);
4847 ✗ if (end == ptr) {
4848 ✗ av_log(s, AV_LOG_WARNING, "malformed location metadata\n");
4849 ✗ return 0;
4850 }
4851 ✗ ptr = end;
4852 ✗ altitude = strtod(ptr, &end);
4853 /* If no altitude was present, the default 0 should be fine */
4854 ✗ if (*end == '/')
4855 ✗ place = end + 1;
4856
4857 ✗ latitude_fix = (int32_t) ((1 << 16) * latitude);
4858 ✗ longitude_fix = (int32_t) ((1 << 16) * longitude);
4859 ✗ altitude_fix = (int32_t) ((1 << 16) * altitude);
4860
4861 ✗ avio_wb32(pb, 0); /* size */
4862 ✗ ffio_wfourcc(pb, "loci"); /* type */
4863 ✗ avio_wb32(pb, 0); /* version + flags */
4864 ✗ avio_wb16(pb, lang);
4865 ✗ avio_write(pb, place, strlen(place) + 1);
4866 ✗ avio_w8(pb, 0); /* role of place (0 == shooting location, 1 == real location, 2 == fictional location) */
4867 ✗ avio_wb32(pb, longitude_fix);
4868 ✗ avio_wb32(pb, latitude_fix);
4869 ✗ avio_wb32(pb, altitude_fix);
4870 ✗ avio_write(pb, astronomical_body, strlen(astronomical_body) + 1);
4871 ✗ avio_w8(pb, 0); /* additional notes, null terminated string */
4872
4873 ✗ return update_size(pb, pos);
4874 }
4875
4876 /* iTunes track or disc number */
4877 256 static int mov_write_trkn_tag(AVIOContext *pb, MOVMuxContext *mov,
4878 AVFormatContext *s, int disc)
4879 {
4880
2/2
✓ Branch 0 taken 128 times.
✓ Branch 1 taken 128 times.
256 AVDictionaryEntry *t = av_dict_get(s->metadata,
4881 disc ? "disc" : "track",
4882 NULL, 0);
4883
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 252 times.
256 int size = 0, track = t ? atoi(t->value) : 0;
4884
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 252 times.
256 if (track) {
4885 4 int tracks = 0;
4886 4 char *slash = strchr(t->value, '/');
4887
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 if (slash)
4888 3 tracks = atoi(slash + 1);
4889 4 avio_wb32(pb, 32); /* size */
4890
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 ffio_wfourcc(pb, disc ? "disk" : "trkn");
4891 4 avio_wb32(pb, 24); /* size */
4892 4 ffio_wfourcc(pb, "data");
4893 4 avio_wb32(pb, 0); // 8 bytes empty
4894 4 avio_wb32(pb, 0);
4895 4 avio_wb16(pb, 0); // empty
4896 4 avio_wb16(pb, track); // track / disc number
4897 4 avio_wb16(pb, tracks); // total track / disc number
4898 4 avio_wb16(pb, 0); // empty
4899 4 size = 32;
4900 }
4901 256 return size;
4902 }
4903
4904 768 static int mov_write_int8_metadata(AVFormatContext *s, AVIOContext *pb,
4905 const char *name, const char *tag,
4906 int len)
4907 {
4908 768 AVDictionaryEntry *t = NULL;
4909 uint8_t num;
4910 768 int size = 24 + len;
4911
4912
3/4
✓ Branch 0 taken 256 times.
✓ Branch 1 taken 512 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 256 times.
768 if (len != 1 && len != 4)
4913 ✗ return -1;
4914
4915
2/2
✓ Branch 1 taken 766 times.
✓ Branch 2 taken 2 times.
768 if (!(t = av_dict_get(s->metadata, tag, NULL, 0)))
4916 766 return 0;
4917 2 num = atoi(t->value);
4918
4919 2 avio_wb32(pb, size);
4920 2 ffio_wfourcc(pb, name);
4921 2 avio_wb32(pb, size - 8);
4922 2 ffio_wfourcc(pb, "data");
4923 2 avio_wb32(pb, 0x15);
4924 2 avio_wb32(pb, 0);
4925
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (len==4) avio_wb32(pb, num);
4926 2 else avio_w8 (pb, num);
4927
4928 2 return size;
4929 }
4930
4931 128 static int mov_write_covr(AVIOContext *pb, AVFormatContext *s)
4932 {
4933 128 MOVMuxContext *mov = s->priv_data;
4934 128 int64_t pos = 0;
4935
4936
2/2
✓ Branch 0 taken 390 times.
✓ Branch 1 taken 128 times.
518 for (int i = 0; i < mov->nb_streams; i++) {
4937 390 MOVTrack *trk = &mov->tracks[i];
4938
4939
3/4
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 388 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
390 if (!is_cover_image(trk->st) || trk->cover_image->size <= 0)
4940 388 continue;
4941
4942
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (!pos) {
4943 1 pos = avio_tell(pb);
4944 1 avio_wb32(pb, 0);
4945 1 ffio_wfourcc(pb, "covr");
4946 }
4947 2 avio_wb32(pb, 16 + trk->cover_image->size);
4948 2 ffio_wfourcc(pb, "data");
4949 2 avio_wb32(pb, trk->tag);
4950 2 avio_wb32(pb , 0);
4951 2 avio_write(pb, trk->cover_image->data, trk->cover_image->size);
4952 }
4953
4954
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 127 times.
128 return pos ? update_size(pb, pos) : 0;
4955 }
4956
4957 /* iTunes meta data list */
4958 128 static int mov_write_ilst_tag(AVIOContext *pb, MOVMuxContext *mov,
4959 AVFormatContext *s)
4960 {
4961 128 int64_t pos = avio_tell(pb);
4962 128 avio_wb32(pb, 0); /* size */
4963 128 ffio_wfourcc(pb, "ilst");
4964 128 mov_write_string_metadata(s, pb, "\251nam", "title" , 1);
4965 128 mov_write_string_metadata(s, pb, "\251ART", "artist" , 1);
4966 128 mov_write_string_metadata(s, pb, "aART", "album_artist", 1);
4967 128 mov_write_string_metadata(s, pb, "\251wrt", "composer" , 1);
4968 128 mov_write_string_metadata(s, pb, "\251alb", "album" , 1);
4969 128 mov_write_string_metadata(s, pb, "\251day", "date" , 1);
4970
1/2
✓ Branch 1 taken 128 times.
✗ Branch 2 not taken.
128 if (!mov_write_string_metadata(s, pb, "\251too", "encoding_tool", 1)) {
4971
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 117 times.
128 if (!(s->flags & AVFMT_FLAG_BITEXACT))
4972 11 mov_write_string_tag(pb, "\251too", LIBAVFORMAT_IDENT, 0, 1);
4973 }
4974 128 mov_write_string_metadata(s, pb, "\251cmt", "comment" , 1);
4975 128 mov_write_string_metadata(s, pb, "\251gen", "genre" , 1);
4976 128 mov_write_string_metadata(s, pb, "cprt", "copyright", 1);
4977 128 mov_write_string_metadata(s, pb, "\251grp", "grouping" , 1);
4978 128 mov_write_string_metadata(s, pb, "\251lyr", "lyrics" , 1);
4979 128 mov_write_string_metadata(s, pb, "desc", "description",1);
4980 128 mov_write_string_metadata(s, pb, "ldes", "synopsis" , 1);
4981 128 mov_write_string_metadata(s, pb, "tvsh", "show" , 1);
4982 128 mov_write_string_metadata(s, pb, "tven", "episode_id",1);
4983 128 mov_write_string_metadata(s, pb, "tvnn", "network" , 1);
4984 128 mov_write_string_metadata(s, pb, "keyw", "keywords" , 1);
4985 128 mov_write_int8_metadata (s, pb, "tves", "episode_sort",4);
4986 128 mov_write_int8_metadata (s, pb, "tvsn", "season_number",4);
4987 128 mov_write_int8_metadata (s, pb, "stik", "media_type",1);
4988 128 mov_write_int8_metadata (s, pb, "hdvd", "hd_video", 1);
4989 128 mov_write_int8_metadata (s, pb, "pgap", "gapless_playback",1);
4990 128 mov_write_int8_metadata (s, pb, "cpil", "compilation", 1);
4991 128 mov_write_covr(pb, s);
4992 128 mov_write_trkn_tag(pb, mov, s, 0); // track number
4993 128 mov_write_trkn_tag(pb, mov, s, 1); // disc number
4994 128 mov_write_tmpo_tag(pb, s);
4995 128 mov_write_custom_metadata(s, pb, "com.apple.iTunes", "DISCSUBTITLE", "disc_subtitle");
4996 128 return update_size(pb, pos);
4997 }
4998
4999 ✗ static int mov_write_mdta_hdlr_tag(AVIOContext *pb, MOVMuxContext *mov,
5000 AVFormatContext *s)
5001 {
5002 ✗ avio_wb32(pb, 33); /* size */
5003 ✗ ffio_wfourcc(pb, "hdlr");
5004 ✗ avio_wb32(pb, 0);
5005 ✗ avio_wb32(pb, 0);
5006 ✗ ffio_wfourcc(pb, "mdta");
5007 ✗ avio_wb32(pb, 0);
5008 ✗ avio_wb32(pb, 0);
5009 ✗ avio_wb32(pb, 0);
5010 ✗ avio_w8(pb, 0);
5011 ✗ return 33;
5012 }
5013
5014 ✗ static int mov_write_mdta_keys_tag(AVIOContext *pb, MOVMuxContext *mov,
5015 AVFormatContext *s)
5016 {
5017 ✗ const AVDictionaryEntry *t = NULL;
5018 ✗ int64_t pos = avio_tell(pb);
5019 int64_t curpos, entry_pos;
5020 ✗ int count = 0;
5021
5022 ✗ avio_wb32(pb, 0); /* size */
5023 ✗ ffio_wfourcc(pb, "keys");
5024 ✗ avio_wb32(pb, 0);
5025 ✗ entry_pos = avio_tell(pb);
5026 ✗ avio_wb32(pb, 0); /* entry count */
5027
5028 ✗ while (t = av_dict_iterate(s->metadata, t)) {
5029 ✗ size_t key_len = strlen(t->key);
5030 ✗ avio_wb32(pb, key_len + 8);
5031 ✗ ffio_wfourcc(pb, "mdta");
5032 ✗ avio_write(pb, t->key, key_len);
5033 ✗ count += 1;
5034 }
5035 ✗ curpos = avio_tell(pb);
5036 ✗ avio_seek(pb, entry_pos, SEEK_SET);
5037 ✗ avio_wb32(pb, count); // rewrite entry count
5038 ✗ avio_seek(pb, curpos, SEEK_SET);
5039
5040 ✗ return update_size(pb, pos);
5041 }
5042
5043 ✗ static int mov_write_mdta_ilst_tag(AVIOContext *pb, MOVMuxContext *mov,
5044 AVFormatContext *s)
5045 {
5046 ✗ const AVDictionaryEntry *t = NULL;
5047 ✗ int64_t pos = avio_tell(pb);
5048 ✗ int count = 1; /* keys are 1-index based */
5049
5050 ✗ avio_wb32(pb, 0); /* size */
5051 ✗ ffio_wfourcc(pb, "ilst");
5052
5053 ✗ while (t = av_dict_iterate(s->metadata, t)) {
5054 ✗ int64_t entry_pos = avio_tell(pb);
5055 ✗ avio_wb32(pb, 0); /* size */
5056 ✗ avio_wb32(pb, count); /* key */
5057 ✗ mov_write_string_data_tag(pb, t->value, 0, 1);
5058 ✗ update_size(pb, entry_pos);
5059 ✗ count += 1;
5060 }
5061 ✗ return update_size(pb, pos);
5062 }
5063
5064 /* meta data tags */
5065 129 static int mov_write_meta_tag(AVIOContext *pb, MOVMuxContext *mov,
5066 AVFormatContext *s)
5067 {
5068 129 int size = 0;
5069 129 int64_t pos = avio_tell(pb);
5070 129 avio_wb32(pb, 0); /* size */
5071 129 ffio_wfourcc(pb, "meta");
5072 129 avio_wb32(pb, 0);
5073
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 129 times.
129 if (mov->flags & FF_MOV_FLAG_USE_MDTA) {
5074 ✗ mov_write_mdta_hdlr_tag(pb, mov, s);
5075 ✗ mov_write_mdta_keys_tag(pb, mov, s);
5076 ✗ mov_write_mdta_ilst_tag(pb, mov, s);
5077 #if CONFIG_AVIF_MUXER
5078
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 128 times.
129 } else if (mov->mode == MODE_AVIF) {
5079 1 mov_write_hdlr_tag(s, pb, &mov->tracks[0]);
5080 // We always write the primary item id as 1 since only one track is
5081 // supported for AVIF.
5082 1 mov_write_pitm_tag(pb, 1);
5083 1 mov_write_iloc_tag(pb, mov, s);
5084 1 mov_write_iinf_tag(pb, mov, s);
5085
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (mov->nb_streams > 1)
5086 ✗ mov_write_iref_tag(pb, mov, s);
5087 1 mov_write_iprp_tag(pb, mov, s);
5088 #endif
5089 } else {
5090 /* iTunes metadata tag */
5091 128 mov_write_itunes_hdlr_tag(pb, mov, s);
5092 128 mov_write_ilst_tag(pb, mov, s);
5093 }
5094 129 size = update_size(pb, pos);
5095 129 return size;
5096 }
5097
5098 166 static int mov_write_raw_metadata_tag(AVFormatContext *s, AVIOContext *pb,
5099 const char *name, const char *key)
5100 {
5101 int len;
5102 AVDictionaryEntry *t;
5103
5104
1/2
✓ Branch 1 taken 166 times.
✗ Branch 2 not taken.
166 if (!(t = av_dict_get(s->metadata, key, NULL, 0)))
5105 166 return 0;
5106
5107 ✗ len = strlen(t->value);
5108 ✗ if (len > 0) {
5109 ✗ int size = len + 8;
5110 ✗ avio_wb32(pb, size);
5111 ✗ ffio_wfourcc(pb, name);
5112 ✗ avio_write(pb, t->value, len);
5113 ✗ return size;
5114 }
5115 ✗ return 0;
5116 }
5117
5118 ✗ static int ascii_to_wc(AVIOContext *pb, const uint8_t *b)
5119 {
5120 int val;
5121 ✗ while (*b) {
5122 ✗ GET_UTF8(val, *b++, return -1;)
5123 ✗ avio_wb16(pb, val);
5124 }
5125 ✗ avio_wb16(pb, 0x00);
5126 ✗ return 0;
5127 }
5128
5129 ✗ static uint16_t language_code(const char *str)
5130 {
5131 ✗ return (((str[0] - 0x60) & 0x1F) << 10) +
5132 ✗ (((str[1] - 0x60) & 0x1F) << 5) +
5133 ✗ (( str[2] - 0x60) & 0x1F);
5134 }
5135
5136 ✗ static int mov_write_3gp_udta_tag(AVIOContext *pb, AVFormatContext *s,
5137 const char *tag, const char *str)
5138 {
5139 ✗ int64_t pos = avio_tell(pb);
5140 ✗ AVDictionaryEntry *t = av_dict_get(s->metadata, str, NULL, 0);
5141 ✗ if (!t || !utf8len(t->value))
5142 ✗ return 0;
5143 ✗ avio_wb32(pb, 0); /* size */
5144 ✗ ffio_wfourcc(pb, tag); /* type */
5145 ✗ avio_wb32(pb, 0); /* version + flags */
5146 ✗ if (!strcmp(tag, "yrrc"))
5147 ✗ avio_wb16(pb, atoi(t->value));
5148 else {
5149 ✗ avio_wb16(pb, language_code("eng")); /* language */
5150 ✗ avio_write(pb, t->value, strlen(t->value) + 1); /* UTF8 string value */
5151 ✗ if (!strcmp(tag, "albm") &&
5152 ✗ (t = av_dict_get(s->metadata, "track", NULL, 0)))
5153 ✗ avio_w8(pb, atoi(t->value));
5154 }
5155 ✗ return update_size(pb, pos);
5156 }
5157
5158 1 static int mov_write_chpl_tag(AVIOContext *pb, AVFormatContext *s)
5159 {
5160 1 int64_t pos = avio_tell(pb);
5161 1 int i, nb_chapters = FFMIN(s->nb_chapters, 255);
5162
5163 1 avio_wb32(pb, 0); // size
5164 1 ffio_wfourcc(pb, "chpl");
5165 1 avio_wb32(pb, 0x01000000); // version + flags
5166 1 avio_wb32(pb, 0); // unknown
5167 1 avio_w8(pb, nb_chapters);
5168
5169
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
5 for (i = 0; i < nb_chapters; i++) {
5170 4 AVChapter *c = s->chapters[i];
5171 AVDictionaryEntry *t;
5172 4 avio_wb64(pb, av_rescale_q(c->start, c->time_base, (AVRational){1,10000000}));
5173
5174
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 if ((t = av_dict_get(c->metadata, "title", NULL, 0))) {
5175
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 int len = FFMIN(strlen(t->value), 255);
5176 4 avio_w8(pb, len);
5177 4 avio_write(pb, t->value, len);
5178 } else
5179 ✗ avio_w8(pb, 0);
5180 }
5181 1 return update_size(pb, pos);
5182 }
5183
5184 294 static int mov_write_udta_tag(AVIOContext *pb, MOVMuxContext *mov,
5185 AVFormatContext *s)
5186 {
5187 AVIOContext *pb_buf;
5188 int ret, size;
5189 uint8_t *buf;
5190
5191 294 ret = avio_open_dyn_buf(&pb_buf);
5192
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 294 times.
294 if (ret < 0)
5193 ✗ return ret;
5194
5195
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 294 times.
294 if (mov->mode & MODE_3GP) {
5196 ✗ mov_write_3gp_udta_tag(pb_buf, s, "perf", "artist");
5197 ✗ mov_write_3gp_udta_tag(pb_buf, s, "titl", "title");
5198 ✗ mov_write_3gp_udta_tag(pb_buf, s, "auth", "author");
5199 ✗ mov_write_3gp_udta_tag(pb_buf, s, "gnre", "genre");
5200 ✗ mov_write_3gp_udta_tag(pb_buf, s, "dscp", "comment");
5201 ✗ mov_write_3gp_udta_tag(pb_buf, s, "albm", "album");
5202 ✗ mov_write_3gp_udta_tag(pb_buf, s, "cprt", "copyright");
5203 ✗ mov_write_3gp_udta_tag(pb_buf, s, "yrrc", "date");
5204 ✗ mov_write_loci_tag(s, pb_buf);
5205
3/4
✓ Branch 0 taken 166 times.
✓ Branch 1 taken 128 times.
✓ Branch 2 taken 166 times.
✗ Branch 3 not taken.
294 } 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
5206 166 mov_write_string_metadata(s, pb_buf, "\251ART", "artist", 0);
5207 166 mov_write_string_metadata(s, pb_buf, "\251nam", "title", 0);
5208 166 mov_write_string_metadata(s, pb_buf, "\251aut", "author", 0);
5209 166 mov_write_string_metadata(s, pb_buf, "\251alb", "album", 0);
5210 166 mov_write_string_metadata(s, pb_buf, "\251day", "date", 0);
5211 166 mov_write_string_metadata(s, pb_buf, "\251swr", "encoder", 0);
5212 // currently ignored by mov.c
5213 166 mov_write_string_metadata(s, pb_buf, "\251des", "comment", 0);
5214 // add support for libquicktime, this atom is also actually read by mov.c
5215 166 mov_write_string_metadata(s, pb_buf, "\251cmt", "comment", 0);
5216 166 mov_write_string_metadata(s, pb_buf, "\251gen", "genre", 0);
5217 166 mov_write_string_metadata(s, pb_buf, "\251cpy", "copyright", 0);
5218 166 mov_write_string_metadata(s, pb_buf, "\251mak", "make", 0);
5219 166 mov_write_string_metadata(s, pb_buf, "\251mod", "model", 0);
5220 166 mov_write_string_metadata(s, pb_buf, "\251xyz", "location", 0);
5221 166 mov_write_string_metadata(s, pb_buf, "\251key", "keywords", 0);
5222 166 mov_write_raw_metadata_tag(s, pb_buf, "XMP_", "xmp");
5223 } else {
5224 /* iTunes meta data */
5225 128 mov_write_meta_tag(pb_buf, mov, s);
5226 128 mov_write_loci_tag(s, pb_buf);
5227 }
5228
5229
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 293 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
294 if (s->nb_chapters && !(mov->flags & FF_MOV_FLAG_DISABLE_CHPL))
5230 1 mov_write_chpl_tag(pb_buf, s);
5231
5232
2/2
✓ Branch 1 taken 158 times.
✓ Branch 2 taken 136 times.
294 if ((size = avio_get_dyn_buf(pb_buf, &buf)) > 0) {
5233 158 avio_wb32(pb, size + 8);
5234 158 ffio_wfourcc(pb, "udta");
5235 158 avio_write(pb, buf, size);
5236 }
5237 294 ffio_free_dyn_buf(&pb_buf);
5238
5239 294 return 0;
5240 }
5241
5242 ✗ static void mov_write_psp_udta_tag(AVIOContext *pb,
5243 const char *str, const char *lang, int type)
5244 {
5245 ✗ int len = utf8len(str) + 1;
5246 ✗ if (len <= 0)
5247 ✗ return;
5248 ✗ avio_wb16(pb, len * 2 + 10); /* size */
5249 ✗ avio_wb32(pb, type); /* type */
5250 ✗ avio_wb16(pb, language_code(lang)); /* language */
5251 ✗ avio_wb16(pb, 0x01); /* ? */
5252 ✗ ascii_to_wc(pb, str);
5253 }
5254
5255 1 static int mov_write_uuidusmt_tag(AVIOContext *pb, AVFormatContext *s)
5256 {
5257 1 AVDictionaryEntry *title = av_dict_get(s->metadata, "title", NULL, 0);
5258 int64_t pos, pos2;
5259
5260
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (title) {
5261 ✗ pos = avio_tell(pb);
5262 ✗ avio_wb32(pb, 0); /* size placeholder*/
5263 ✗ ffio_wfourcc(pb, "uuid");
5264 ✗ ffio_wfourcc(pb, "USMT");
5265 ✗ avio_wb32(pb, 0x21d24fce); /* 96 bit UUID */
5266 ✗ avio_wb32(pb, 0xbb88695c);
5267 ✗ avio_wb32(pb, 0xfac9c740);
5268
5269 ✗ pos2 = avio_tell(pb);
5270 ✗ avio_wb32(pb, 0); /* size placeholder*/
5271 ✗ ffio_wfourcc(pb, "MTDT");
5272 ✗ avio_wb16(pb, 4);
5273
5274 // ?
5275 ✗ avio_wb16(pb, 0x0C); /* size */
5276 ✗ avio_wb32(pb, 0x0B); /* type */
5277 ✗ avio_wb16(pb, language_code("und")); /* language */
5278 ✗ avio_wb16(pb, 0x0); /* ? */
5279 ✗ avio_wb16(pb, 0x021C); /* data */
5280
5281 ✗ if (!(s->flags & AVFMT_FLAG_BITEXACT))
5282 ✗ mov_write_psp_udta_tag(pb, LIBAVFORMAT_IDENT, "eng", 0x04);
5283 ✗ mov_write_psp_udta_tag(pb, title->value, "eng", 0x01);
5284 ✗ mov_write_psp_udta_tag(pb, "2006/04/01 11:11:11", "und", 0x03);
5285
5286 ✗ update_size(pb, pos2);
5287 ✗ return update_size(pb, pos);
5288 }
5289
5290 1 return 0;
5291 }
5292
5293 587 static int mov_write_pssh_tag(AVIOContext *pb, AVStream *st)
5294 {
5295 AVEncryptionInitInfo *info;
5296 587 const AVPacketSideData *sd = av_packet_side_data_get(st->codecpar->coded_side_data,
5297 587 st->codecpar->nb_coded_side_data,
5298 AV_PKT_DATA_ENCRYPTION_INIT_INFO);
5299
1/2
✓ Branch 0 taken 587 times.
✗ Branch 1 not taken.
587 if (!sd)
5300 587 return 0;
5301
5302 ✗ info = av_encryption_init_info_get_side_data(sd->data, sd->size);
5303 ✗ for (AVEncryptionInitInfo *copy = info; copy; copy = copy->next) {
5304 int64_t pos;
5305
5306 ✗ if (!copy->data_size && !copy->num_key_ids)
5307 ✗ continue;
5308
5309 ✗ pos = avio_tell(pb);
5310 ✗ avio_wb32(pb, 0); /* size placeholder */
5311 ✗ ffio_wfourcc(pb, "pssh");
5312 ✗ avio_w8(pb, 1); /* version */
5313 ✗ avio_wb24(pb, 0);
5314 ✗ for (int i = 0; i < copy->system_id_size; i++)
5315 ✗ avio_w8(pb, copy->system_id[i]);
5316 ✗ avio_wb32(pb, copy->num_key_ids);
5317 ✗ for (int i = 0; i < copy->num_key_ids; i++)
5318 ✗ for (int j = 0; j < copy->key_id_size; j++)
5319 ✗ avio_w8(pb, copy->key_ids[i][j]);
5320 ✗ avio_wb32(pb, copy->data_size);
5321 ✗ avio_write(pb, copy->data, copy->data_size);
5322 ✗ update_size(pb, pos);
5323 }
5324
5325 ✗ av_encryption_init_info_free(info);
5326
5327 ✗ return 0;
5328 }
5329
5330 556 static void build_chunks(MOVTrack *trk)
5331 {
5332 int i;
5333 556 MOVIentry *chunk = &trk->cluster[0];
5334 556 uint64_t chunkSize = chunk->size;
5335 556 chunk->chunkNum = 1;
5336
2/2
✓ Branch 0 taken 158 times.
✓ Branch 1 taken 398 times.
556 if (trk->chunkCount)
5337 158 return;
5338 398 trk->chunkCount = 1;
5339
2/2
✓ Branch 0 taken 20927 times.
✓ Branch 1 taken 398 times.
21325 for (i = 1; i<trk->entry; i++){
5340
2/2
✓ Branch 0 taken 19012 times.
✓ Branch 1 taken 1915 times.
20927 if (chunk->pos + chunkSize == trk->cluster[i].pos &&
5341
2/2
✓ Branch 0 taken 19010 times.
✓ Branch 1 taken 2 times.
19012 chunk->stsd_index == trk->cluster[i].stsd_index &&
5342
2/2
✓ Branch 0 taken 18365 times.
✓ Branch 1 taken 645 times.
19010 chunkSize + trk->cluster[i].size < (1<<20)){
5343 18365 chunkSize += trk->cluster[i].size;
5344 18365 chunk->samples_in_chunk += trk->cluster[i].entries;
5345 } else {
5346 2562 trk->cluster[i].chunkNum = chunk->chunkNum+1;
5347 2562 chunk=&trk->cluster[i];
5348 2562 chunkSize = chunk->size;
5349 2562 trk->chunkCount++;
5350 }
5351 }
5352 }
5353
5354 /**
5355 * Assign track ids. If option "use_stream_ids_as_track_ids" is set,
5356 * the stream ids are used as track ids.
5357 *
5358 * This assumes mov->tracks and s->streams are in the same order and
5359 * there are no gaps in either of them (so mov->tracks[n] refers to
5360 * s->streams[n]).
5361 *
5362 * As an exception, there can be more entries in
5363 * s->streams than in mov->tracks, in which case new track ids are
5364 * generated (starting after the largest found stream id).
5365 */
5366 296 static int mov_setup_track_ids(MOVMuxContext *mov, AVFormatContext *s)
5367 {
5368 int i;
5369
5370
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 262 times.
296 if (mov->track_ids_ok)
5371 34 return 0;
5372
5373
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 261 times.
262 if (mov->use_stream_ids_as_track_ids) {
5374 1 int next_generated_track_id = 0;
5375
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 for (i = 0; i < mov->nb_streams; i++) {
5376 2 AVStream *st = mov->tracks[i].st;
5377
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (st->id > next_generated_track_id)
5378 2 next_generated_track_id = st->id;
5379 }
5380
5381
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 for (i = 0; i < mov->nb_tracks; i++) {
5382
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2 if (mov->tracks[i].entry <= 0 && !(mov->flags & FF_MOV_FLAG_FRAGMENT))
5383 ✗ continue;
5384
5385
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 mov->tracks[i].track_id = i >= mov->nb_streams ? ++next_generated_track_id : mov->tracks[i].st->id;
5386 }
5387 } else {
5388 261 int last_track_id = 0;
5389
2/2
✓ Branch 0 taken 432 times.
✓ Branch 1 taken 261 times.
693 for (i = 0; i < mov->nb_tracks; i++) {
5390
4/4
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 392 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 38 times.
432 if (mov->tracks[i].entry <= 0 && !(mov->flags & FF_MOV_FLAG_FRAGMENT))
5391 2 continue;
5392
5393 430 last_track_id =
5394 430 mov->tracks[i].track_id = (mov->tracks[i].st
5395 427 ? FFMAX(mov->tracks[i].st->index, last_track_id)
5396
2/2
✓ Branch 0 taken 427 times.
✓ Branch 1 taken 3 times.
430 : FFMAX(i, last_track_id)) + 1;
5397 }
5398 }
5399
5400 262 mov->track_ids_ok = 1;
5401
5402 262 return 0;
5403 }
5404
5405 17 static int mov_find_tref_id(MOVMuxContext *mov, const MovTag *tag, uint32_t id)
5406 {
5407
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 13 times.
20 for (int i = 0; i < tag->nb_id; i++) {
5408
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
7 if (tag->id[i] == id)
5409 4 return 1;
5410 }
5411 13 return 0;
5412 }
5413
5414 17 static int mov_add_tref_id(MOVMuxContext *mov, MovTag *tag, uint32_t id)
5415 {
5416 17 int ret = mov_find_tref_id(mov, tag, id);
5417
5418
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 4 times.
17 if (!ret) {
5419 13 uint32_t *tmp = av_realloc_array(tag->id, tag->nb_id + 1, sizeof(*tag->id));
5420
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (!tmp)
5421 ✗ return AVERROR(ENOMEM);
5422 13 tag->id = tmp;
5423 13 tag->id[tag->nb_id++] = id;
5424 }
5425
5426 17 return 0;
5427 }
5428
5429 17 static MovTag *mov_find_tref_tag(MOVMuxContext *mov, const MOVTrack *trk, uint32_t name)
5430 {
5431
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 11 times.
17 for (int i = 0; i < trk->nb_tref_tags; i++) {
5432 6 MovTag *entry = &trk->tref_tags[i];
5433
5434
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (entry->name == name)
5435 6 return entry;
5436 }
5437 11 return NULL;
5438 }
5439
5440 17 static MovTag *mov_add_tref_tag(MOVMuxContext *mov, MOVTrack *trk, uint32_t name)
5441 {
5442 17 MovTag *tag = mov_find_tref_tag(mov, trk, name);
5443
5444
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 6 times.
17 if (!tag) {
5445 11 MovTag *tmp = av_realloc_array(trk->tref_tags, trk->nb_tref_tags + 1,
5446 sizeof(*trk->tref_tags));
5447
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!tmp)
5448 ✗ return NULL;
5449 11 trk->tref_tags = tmp;
5450 11 tag = &trk->tref_tags[trk->nb_tref_tags++];
5451 11 *tag = (MovTag){ .name = name };
5452 }
5453
5454 17 return tag;
5455 }
5456
5457 296 static int mov_write_moov_tag(AVIOContext *pb, MOVMuxContext *mov,
5458 AVFormatContext *s)
5459 {
5460 int i;
5461 296 int64_t pos = avio_tell(pb);
5462 296 avio_wb32(pb, 0); /* size placeholder*/
5463 296 ffio_wfourcc(pb, "moov");
5464
5465 296 mov_setup_track_ids(mov, s);
5466
5467
2/2
✓ Branch 0 taken 600 times.
✓ Branch 1 taken 296 times.
896 for (i = 0; i < mov->nb_tracks; i++) {
5468
4/4
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 556 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 42 times.
600 if (mov->tracks[i].entry <= 0 && !(mov->flags & FF_MOV_FLAG_FRAGMENT))
5469 2 continue;
5470
5471 598 mov->tracks[i].time = mov->time;
5472
5473
2/2
✓ Branch 0 taken 556 times.
✓ Branch 1 taken 42 times.
598 if (mov->tracks[i].entry)
5474 556 build_chunks(&mov->tracks[i]);
5475 }
5476
5477
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 295 times.
296 if (mov->chapter_track)
5478
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 for (i = 0; i < mov->nb_streams; i++) {
5479 1 MovTag *tag = mov_add_tref_tag(mov, &mov->tracks[i], MKTAG('c','h','a','p'));
5480
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!tag)
5481 ✗ return AVERROR(ENOMEM);
5482
5483 1 int ret = mov_add_tref_id(mov, tag, mov->tracks[mov->chapter_track].track_id);
5484
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
5485 ✗ return ret;
5486 }
5487
2/2
✓ Branch 0 taken 600 times.
✓ Branch 1 taken 296 times.
896 for (i = 0; i < mov->nb_tracks; i++) {
5488 600 MOVTrack *track = &mov->tracks[i];
5489
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 598 times.
600 if (track->tag == MKTAG('r','t','p',' ')) {
5490 2 MovTag *tag = mov_add_tref_tag(mov, track, MKTAG('h','i','n','t'));
5491
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!tag)
5492 ✗ return AVERROR(ENOMEM);
5493
5494
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 av_assert0(track->nb_src_track);
5495 2 int ret = mov_add_tref_id(mov, tag, mov->tracks[*track->src_track].track_id);
5496
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
5497 ✗ return ret;
5498
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 597 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
599 } else if (track->tag == MKTAG('l','v','c','1') && track->nb_src_track) {
5499 1 MovTag *tag = mov_add_tref_tag(mov, track, MKTAG('s','b','a','s'));
5500
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!tag)
5501 ✗ return AVERROR(ENOMEM);
5502
5503 1 int ret = mov_add_tref_id(mov, tag, mov->tracks[*track->src_track].track_id);
5504
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
5505 ✗ return ret;
5506 } else {
5507
2/2
✓ Branch 0 taken 338 times.
✓ Branch 1 taken 259 times.
597 if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) {
5508 338 const AVPacketSideData *sd = av_packet_side_data_get(track->st->codecpar->coded_side_data,
5509 338 track->st->codecpar->nb_coded_side_data,
5510 AV_PKT_DATA_FALLBACK_TRACK );
5511
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 338 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
338 if (sd && sd->size == sizeof(int)) {
5512 ✗ int *fallback = (int *)sd->data;
5513 ✗ if (*fallback >= 0 && *fallback < mov->nb_tracks) {
5514 ✗ MovTag *tag = mov_add_tref_tag(mov, track, MKTAG('f','a','l','l'));
5515 ✗ if (!tag)
5516 ✗ return AVERROR(ENOMEM);
5517
5518 ✗ int ret = mov_add_tref_id(mov, tag, mov->tracks[*fallback].track_id);
5519 ✗ if (ret < 0)
5520 ✗ return ret;
5521 }
5522 }
5523 }
5524
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 597 times.
610 for (int j = 0; j < track->nb_src_track; j++) {
5525 13 int src_trk = track->src_track[j];
5526 13 MovTag *tag = mov_add_tref_tag(mov, &mov->tracks[src_trk], track->tag);
5527
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (!tag)
5528 ✗ return AVERROR(ENOMEM);
5529 13 int ret = mov_add_tref_id(mov, tag, track->track_id);
5530
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (ret < 0)
5531 ✗ return ret;
5532 }
5533
4/4
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 571 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 16 times.
597 if (mov->nb_meta_tmcd && track->nb_src_track) {
5534 /* Derive the duration from the first source track, matching
5535 * the convention used by get_pts_range() and the rtp/lvc1
5536 * branches above. The source may use a different timescale. */
5537 10 int src_trk = track->src_track[0];
5538 10 track->track_duration = av_rescale(mov->tracks[src_trk].track_duration,
5539 10 track->timescale,
5540 10 mov->tracks[src_trk].timescale);
5541 }
5542 }
5543 }
5544
5545 296 mov_write_mvhd_tag(pb, mov);
5546
5/6
✓ Branch 0 taken 130 times.
✓ Branch 1 taken 166 times.
✓ Branch 2 taken 129 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 129 times.
296 if (mov->mode != MODE_MOV && mov->mode != MODE_AVIF && !mov->iods_skip)
5547 ✗ mov_write_iods_tag(pb, mov);
5548
2/2
✓ Branch 0 taken 600 times.
✓ Branch 1 taken 296 times.
896 for (i = 0; i < mov->nb_tracks; i++) {
5549
4/4
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 556 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 42 times.
600 if (mov->tracks[i].entry > 0 || mov->flags & FF_MOV_FLAG_FRAGMENT ||
5550
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 mov->mode == MODE_AVIF) {
5551
2/2
✓ Branch 0 taken 585 times.
✓ Branch 1 taken 13 times.
598 int ret = mov_write_trak_tag(s, pb, mov, &(mov->tracks[i]), i < mov->nb_streams ? mov->tracks[i].st : NULL);
5552
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 if (ret < 0)
5553 ✗ return ret;
5554 }
5555 }
5556 /* Don't write mvex for hybrid_fragmented during mov_write_trailer
5557 * (mov->moov_written != 0)
5558 */
5559
2/2
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 220 times.
296 if (mov->flags & FF_MOV_FLAG_FRAGMENT &&
5560
4/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 71 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 2 times.
76 !(mov->flags & FF_MOV_FLAG_HYBRID_FRAGMENTED && mov->moov_written))
5561 74 mov_write_mvex_tag(pb, mov); /* QuickTime requires trak to precede this */
5562
5563
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 295 times.
296 if (mov->mode == MODE_PSP)
5564 1 mov_write_uuidusmt_tag(pb, s);
5565
2/2
✓ Branch 0 taken 294 times.
✓ Branch 1 taken 1 times.
295 else if (mov->mode != MODE_AVIF)
5566 294 mov_write_udta_tag(pb, mov, s);
5567
2/2
✓ Branch 0 taken 587 times.
✓ Branch 1 taken 296 times.
883 for (i = 0; i < mov->nb_streams; i++)
5568 587 mov_write_pssh_tag(pb, mov->tracks[i].st);
5569
5570 296 return update_size(pb, pos);
5571 }
5572
5573 ✗ static void param_write_int(AVIOContext *pb, const char *name, int value)
5574 {
5575 ✗ avio_printf(pb, "<param name=\"%s\" value=\"%d\" valuetype=\"data\"/>\n", name, value);
5576 ✗ }
5577
5578 ✗ static void param_write_string(AVIOContext *pb, const char *name, const char *value)
5579 {
5580 ✗ avio_printf(pb, "<param name=\"%s\" value=\"%s\" valuetype=\"data\"/>\n", name, value);
5581 ✗ }
5582
5583 ✗ static void param_write_hex(AVIOContext *pb, const char *name, const uint8_t *value, int len)
5584 {
5585 char buf[150];
5586 ✗ len = FFMIN(sizeof(buf) / 2 - 1, len);
5587 ✗ ff_data_to_hex(buf, value, len, 0);
5588 ✗ avio_printf(pb, "<param name=\"%s\" value=\"%s\" valuetype=\"data\"/>\n", name, buf);
5589 ✗ }
5590
5591 ✗ static int mov_write_isml_manifest(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
5592 {
5593 ✗ int64_t pos = avio_tell(pb);
5594 int i;
5595
5596 static const AVUUID uuid = {
5597 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
5598 0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
5599 };
5600
5601 ✗ avio_wb32(pb, 0);
5602 ✗ ffio_wfourcc(pb, "uuid");
5603 ✗ avio_write(pb, uuid, AV_UUID_LEN);
5604 ✗ avio_wb32(pb, 0);
5605
5606 ✗ avio_printf(pb, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
5607 ✗ avio_printf(pb, "<smil xmlns=\"http://www.w3.org/2001/SMIL20/Language\">\n");
5608 ✗ avio_printf(pb, "<head>\n");
5609 ✗ if (!(mov->fc->flags & AVFMT_FLAG_BITEXACT))
5610 ✗ avio_printf(pb, "<meta name=\"creator\" content=\"%s\" />\n",
5611 LIBAVFORMAT_IDENT);
5612 ✗ avio_printf(pb, "</head>\n");
5613 ✗ avio_printf(pb, "<body>\n");
5614 ✗ avio_printf(pb, "<switch>\n");
5615
5616 ✗ mov_setup_track_ids(mov, s);
5617
5618 ✗ for (i = 0; i < mov->nb_tracks; i++) {
5619 ✗ MOVTrack *track = &mov->tracks[i];
5620 struct mpeg4_bit_rate_values bit_rates =
5621 ✗ calculate_mpeg4_bit_rates(track);
5622 const char *type;
5623 ✗ int track_id = track->track_id;
5624 ✗ char track_name_buf[32] = { 0 };
5625
5626 ✗ AVStream *st = track->st;
5627 ✗ AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL,0);
5628
5629 ✗ if (track->par->codec_type == AVMEDIA_TYPE_VIDEO && !is_cover_image(st)) {
5630 ✗ type = "video";
5631 ✗ } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) {
5632 ✗ type = "audio";
5633 } else {
5634 ✗ continue;
5635 }
5636
5637 ✗ avio_printf(pb, "<%s systemBitrate=\"%"PRIu32"\">\n", type,
5638 bit_rates.avg_bit_rate);
5639 ✗ param_write_int(pb, "systemBitrate", bit_rates.avg_bit_rate);
5640 ✗ param_write_int(pb, "trackID", track_id);
5641 ✗ param_write_string(pb, "systemLanguage", lang ? lang->value : "und");
5642
5643 /* Build track name piece by piece: */
5644 /* 1. track type */
5645 ✗ av_strlcat(track_name_buf, type, sizeof(track_name_buf));
5646 /* 2. track language, if available */
5647 ✗ if (lang)
5648 ✗ av_strlcatf(track_name_buf, sizeof(track_name_buf),
5649 "_%s", lang->value);
5650 /* 3. special type suffix */
5651 /* "_cc" = closed captions, "_ad" = audio_description */
5652 ✗ if (st->disposition & AV_DISPOSITION_HEARING_IMPAIRED)
5653 ✗ av_strlcat(track_name_buf, "_cc", sizeof(track_name_buf));
5654 ✗ else if (st->disposition & AV_DISPOSITION_VISUAL_IMPAIRED)
5655 ✗ av_strlcat(track_name_buf, "_ad", sizeof(track_name_buf));
5656
5657 ✗ param_write_string(pb, "trackName", track_name_buf);
5658
5659 ✗ if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
5660 ✗ if (track->par->codec_id == AV_CODEC_ID_H264) {
5661 uint8_t *ptr;
5662 ✗ int size = track->extradata_size[track->last_stsd_index];
5663 ✗ if (!ff_avc_write_annexb_extradata(track->extradata[track->last_stsd_index], &ptr,
5664 &size)) {
5665 ✗ param_write_hex(pb, "CodecPrivateData",
5666 ✗ ptr ? ptr : track->extradata[track->last_stsd_index],
5667 size);
5668 ✗ av_free(ptr);
5669 }
5670 ✗ param_write_string(pb, "FourCC", "H264");
5671 ✗ } else if (track->par->codec_id == AV_CODEC_ID_VC1) {
5672 ✗ param_write_string(pb, "FourCC", "WVC1");
5673 ✗ param_write_hex(pb, "CodecPrivateData", track->extradata[track->last_stsd_index],
5674 ✗ track->extradata_size[track->last_stsd_index]);
5675 }
5676 ✗ param_write_int(pb, "MaxWidth", track->par->width);
5677 ✗ param_write_int(pb, "MaxHeight", track->par->height);
5678 ✗ param_write_int(pb, "DisplayWidth", track->par->width);
5679 ✗ param_write_int(pb, "DisplayHeight", track->par->height);
5680 } else {
5681 ✗ if (track->par->codec_id == AV_CODEC_ID_AAC) {
5682 ✗ switch (track->par->profile) {
5683 ✗ case AV_PROFILE_AAC_HE_V2:
5684 ✗ param_write_string(pb, "FourCC", "AACP");
5685 ✗ break;
5686 ✗ case AV_PROFILE_AAC_HE:
5687 ✗ param_write_string(pb, "FourCC", "AACH");
5688 ✗ break;
5689 ✗ default:
5690 ✗ param_write_string(pb, "FourCC", "AACL");
5691 }
5692 ✗ } else if (track->par->codec_id == AV_CODEC_ID_WMAPRO) {
5693 ✗ param_write_string(pb, "FourCC", "WMAP");
5694 }
5695 ✗ param_write_hex(pb, "CodecPrivateData", track->extradata[track->last_stsd_index],
5696 ✗ track->extradata_size[track->last_stsd_index]);
5697 ✗ param_write_int(pb, "AudioTag", ff_codec_get_tag(ff_codec_wav_tags,
5698 ✗ track->par->codec_id));
5699 ✗ param_write_int(pb, "Channels", track->par->ch_layout.nb_channels);
5700 ✗ param_write_int(pb, "SamplingRate", track->tag == MKTAG('i','a','m','f') ?
5701 ✗ 0 : track->par->sample_rate);
5702 ✗ param_write_int(pb, "BitsPerSample", 16);
5703 ✗ param_write_int(pb, "PacketSize", track->par->block_align ?
5704 ✗ track->par->block_align : 4);
5705 }
5706 ✗ avio_printf(pb, "</%s>\n", type);
5707 }
5708 ✗ avio_printf(pb, "</switch>\n");
5709 ✗ avio_printf(pb, "</body>\n");
5710 ✗ avio_printf(pb, "</smil>\n");
5711
5712 ✗ return update_size(pb, pos);
5713 }
5714
5715 256 static int mov_write_mfhd_tag(AVIOContext *pb, MOVMuxContext *mov)
5716 {
5717 256 avio_wb32(pb, 16);
5718 256 ffio_wfourcc(pb, "mfhd");
5719 256 avio_wb32(pb, 0);
5720 256 avio_wb32(pb, mov->fragments);
5721 256 return 0;
5722 }
5723
5724 19606 static uint32_t get_sample_flags(MOVTrack *track, MOVIentry *entry)
5725 {
5726
2/2
✓ Branch 0 taken 13672 times.
✓ Branch 1 taken 5934 times.
19606 return entry->flags & MOV_SYNC_SAMPLE ? MOV_FRAG_SAMPLE_FLAG_DEPENDS_NO :
5727 (MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES | MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC);
5728 }
5729
5730 772 static int mov_write_tfhd_tag(AVIOContext *pb, MOVMuxContext *mov,
5731 MOVTrack *track, int64_t moof_offset)
5732 {
5733 772 int64_t pos = avio_tell(pb);
5734 772 uint32_t flags = MOV_TFHD_DEFAULT_SIZE | MOV_TFHD_DEFAULT_DURATION |
5735 MOV_TFHD_BASE_DATA_OFFSET;
5736
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 772 times.
772 if (!track->entry) {
5737 ✗ flags |= MOV_TFHD_DURATION_IS_EMPTY;
5738 } else {
5739 772 flags |= MOV_TFHD_DEFAULT_FLAGS;
5740 }
5741
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 772 times.
772 if (mov->flags & FF_MOV_FLAG_OMIT_TFHD_OFFSET)
5742 ✗ flags &= ~MOV_TFHD_BASE_DATA_OFFSET;
5743
2/2
✓ Branch 0 taken 550 times.
✓ Branch 1 taken 222 times.
772 if (mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF) {
5744 550 flags &= ~MOV_TFHD_BASE_DATA_OFFSET;
5745 550 flags |= MOV_TFHD_DEFAULT_BASE_IS_MOOF;
5746 }
5747 /* CMAF requires all values to be explicit in tfhd atoms */
5748
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 712 times.
772 if (mov->flags & FF_MOV_FLAG_CMAF)
5749 60 flags |= MOV_TFHD_STSD_ID;
5750
5751 /* Don't set a default sample size, the silverlight player refuses
5752 * to play files with that set. Don't set a default sample duration,
5753 * WMP freaks out if it is set. Don't set a base data offset, PIFF
5754 * file format says it MUST NOT be set. */
5755
2/2
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 690 times.
772 if (track->mode == MODE_ISM)
5756 82 flags &= ~(MOV_TFHD_DEFAULT_SIZE | MOV_TFHD_DEFAULT_DURATION |
5757 MOV_TFHD_BASE_DATA_OFFSET | MOV_TFHD_STSD_ID);
5758
5759 772 avio_wb32(pb, 0); /* size placeholder */
5760 772 ffio_wfourcc(pb, "tfhd");
5761 772 avio_w8(pb, 0); /* version */
5762 772 avio_wb24(pb, flags);
5763
5764 772 avio_wb32(pb, track->track_id); /* track-id */
5765
2/2
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 632 times.
772 if (flags & MOV_TFHD_BASE_DATA_OFFSET)
5766 140 avio_wb64(pb, moof_offset);
5767
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 712 times.
772 if (flags & MOV_TFHD_STSD_ID) {
5768 60 avio_wb32(pb, 1);
5769 }
5770
2/2
✓ Branch 0 taken 690 times.
✓ Branch 1 taken 82 times.
772 if (flags & MOV_TFHD_DEFAULT_DURATION) {
5771 690 track->default_duration = get_cluster_duration(track, 0);
5772 690 avio_wb32(pb, track->default_duration);
5773 }
5774
2/2
✓ Branch 0 taken 690 times.
✓ Branch 1 taken 82 times.
772 if (flags & MOV_TFHD_DEFAULT_SIZE) {
5775
1/2
✓ Branch 0 taken 690 times.
✗ Branch 1 not taken.
690 track->default_size = track->entry ? track->cluster[0].size : 1;
5776 690 avio_wb32(pb, track->default_size);
5777 } else
5778 82 track->default_size = -1;
5779
5780
1/2
✓ Branch 0 taken 772 times.
✗ Branch 1 not taken.
772 if (flags & MOV_TFHD_DEFAULT_FLAGS) {
5781 /* Set the default flags based on the second sample, if available.
5782 * If the first sample is different, that can be signaled via a separate field. */
5783
2/2
✓ Branch 0 taken 690 times.
✓ Branch 1 taken 82 times.
772 if (track->entry > 1)
5784 690 track->default_sample_flags = get_sample_flags(track, &track->cluster[1]);
5785 else
5786 82 track->default_sample_flags =
5787 82 track->par->codec_type == AVMEDIA_TYPE_VIDEO ?
5788
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 64 times.
82 (MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES | MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC) :
5789 MOV_FRAG_SAMPLE_FLAG_DEPENDS_NO;
5790 772 avio_wb32(pb, track->default_sample_flags);
5791 }
5792
5793 772 return update_size(pb, pos);
5794 }
5795
5796 774 static int mov_write_trun_tag(AVIOContext *pb, MOVMuxContext *mov,
5797 MOVTrack *track, int moof_size,
5798 int first, int end)
5799 {
5800 774 int64_t pos = avio_tell(pb);
5801 774 uint32_t flags = MOV_TRUN_DATA_OFFSET;
5802 int i;
5803
5804
2/2
✓ Branch 0 taken 18370 times.
✓ Branch 1 taken 774 times.
19144 for (i = first; i < end; i++) {
5805
2/2
✓ Branch 1 taken 1854 times.
✓ Branch 2 taken 16516 times.
18370 if (get_cluster_duration(track, i) != track->default_duration)
5806 1854 flags |= MOV_TRUN_SAMPLE_DURATION;
5807
2/2
✓ Branch 0 taken 2972 times.
✓ Branch 1 taken 15398 times.
18370 if (track->cluster[i].size != track->default_size)
5808 2972 flags |= MOV_TRUN_SAMPLE_SIZE;
5809
4/4
✓ Branch 0 taken 17596 times.
✓ Branch 1 taken 774 times.
✓ Branch 3 taken 10 times.
✓ Branch 4 taken 17586 times.
18370 if (i > first && get_sample_flags(track, &track->cluster[i]) != track->default_sample_flags)
5810 10 flags |= MOV_TRUN_SAMPLE_FLAGS;
5811 }
5812
3/4
✓ Branch 0 taken 766 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 766 times.
✗ Branch 3 not taken.
774 if (!(flags & MOV_TRUN_SAMPLE_FLAGS) && track->entry > first &&
5813
2/2
✓ Branch 1 taken 182 times.
✓ Branch 2 taken 584 times.
766 get_sample_flags(track, &track->cluster[first]) != track->default_sample_flags)
5814 182 flags |= MOV_TRUN_FIRST_SAMPLE_FLAGS;
5815
2/2
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 674 times.
774 if (track->flags & MOV_TRACK_CTTS)
5816 100 flags |= MOV_TRUN_SAMPLE_CTS;
5817
5818 774 avio_wb32(pb, 0); /* size placeholder */
5819 774 ffio_wfourcc(pb, "trun");
5820
2/2
✓ Branch 0 taken 158 times.
✓ Branch 1 taken 616 times.
774 if (mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS)
5821 158 avio_w8(pb, 1); /* version */
5822 else
5823 616 avio_w8(pb, 0); /* version */
5824 774 avio_wb24(pb, flags);
5825
5826 774 avio_wb32(pb, end - first); /* sample count */
5827
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 774 times.
774 if (mov->flags & FF_MOV_FLAG_OMIT_TFHD_OFFSET &&
5828 ✗ !(mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF) &&
5829 ✗ !mov->first_trun)
5830 ✗ avio_wb32(pb, 0); /* Later tracks follow immediately after the previous one */
5831 else
5832 774 avio_wb32(pb, moof_size + 8 + track->data_offset +
5833 774 track->cluster[first].pos); /* data offset */
5834
2/2
✓ Branch 0 taken 182 times.
✓ Branch 1 taken 592 times.
774 if (flags & MOV_TRUN_FIRST_SAMPLE_FLAGS)
5835 182 avio_wb32(pb, get_sample_flags(track, &track->cluster[first]));
5836
5837
2/2
✓ Branch 0 taken 18370 times.
✓ Branch 1 taken 774 times.
19144 for (i = first; i < end; i++) {
5838
2/2
✓ Branch 0 taken 2050 times.
✓ Branch 1 taken 16320 times.
18370 if (flags & MOV_TRUN_SAMPLE_DURATION)
5839 2050 avio_wb32(pb, get_cluster_duration(track, i));
5840
2/2
✓ Branch 0 taken 3656 times.
✓ Branch 1 taken 14714 times.
18370 if (flags & MOV_TRUN_SAMPLE_SIZE)
5841 3656 avio_wb32(pb, track->cluster[i].size);
5842
2/2
✓ Branch 0 taken 372 times.
✓ Branch 1 taken 17998 times.
18370 if (flags & MOV_TRUN_SAMPLE_FLAGS)
5843 372 avio_wb32(pb, get_sample_flags(track, &track->cluster[i]));
5844
2/2
✓ Branch 0 taken 3162 times.
✓ Branch 1 taken 15208 times.
18370 if (flags & MOV_TRUN_SAMPLE_CTS)
5845 3162 avio_wb32(pb, track->cluster[i].cts);
5846 }
5847
5848 774 mov->first_trun = 0;
5849 774 return update_size(pb, pos);
5850 }
5851
5852 82 static int mov_write_tfxd_tag(AVIOContext *pb, MOVTrack *track)
5853 {
5854 82 int64_t pos = avio_tell(pb);
5855 static const uint8_t uuid[] = {
5856 0x6d, 0x1d, 0x9b, 0x05, 0x42, 0xd5, 0x44, 0xe6,
5857 0x80, 0xe2, 0x14, 0x1d, 0xaf, 0xf7, 0x57, 0xb2
5858 };
5859
5860 82 avio_wb32(pb, 0); /* size placeholder */
5861 82 ffio_wfourcc(pb, "uuid");
5862 82 avio_write(pb, uuid, AV_UUID_LEN);
5863 82 avio_w8(pb, 1);
5864 82 avio_wb24(pb, 0);
5865 82 avio_wb64(pb, track->cluster[0].dts + track->cluster[0].cts);
5866 82 avio_wb64(pb, track->end_pts -
5867 82 (track->cluster[0].dts + track->cluster[0].cts));
5868
5869 82 return update_size(pb, pos);
5870 }
5871
5872 ✗ static int mov_write_tfrf_tag(AVIOContext *pb, MOVMuxContext *mov,
5873 MOVTrack *track, int entry)
5874 {
5875 ✗ int n = track->nb_frag_info - 1 - entry, i;
5876 ✗ int size = 8 + 16 + 4 + 1 + 16*n;
5877 static const uint8_t uuid[] = {
5878 0xd4, 0x80, 0x7e, 0xf2, 0xca, 0x39, 0x46, 0x95,
5879 0x8e, 0x54, 0x26, 0xcb, 0x9e, 0x46, 0xa7, 0x9f
5880 };
5881
5882 ✗ if (entry < 0)
5883 ✗ return 0;
5884
5885 ✗ avio_seek(pb, track->frag_info[entry].tfrf_offset, SEEK_SET);
5886 ✗ avio_wb32(pb, size);
5887 ✗ ffio_wfourcc(pb, "uuid");
5888 ✗ avio_write(pb, uuid, AV_UUID_LEN);
5889 ✗ avio_w8(pb, 1);
5890 ✗ avio_wb24(pb, 0);
5891 ✗ avio_w8(pb, n);
5892 ✗ for (i = 0; i < n; i++) {
5893 ✗ int index = entry + 1 + i;
5894 ✗ avio_wb64(pb, track->frag_info[index].time);
5895 ✗ avio_wb64(pb, track->frag_info[index].duration);
5896 }
5897 ✗ if (n < mov->ism_lookahead) {
5898 ✗ int free_size = 16 * (mov->ism_lookahead - n);
5899 ✗ avio_wb32(pb, free_size);
5900 ✗ ffio_wfourcc(pb, "free");
5901 ✗ ffio_fill(pb, 0, free_size - 8);
5902 }
5903
5904 ✗ return 0;
5905 }
5906
5907 384 static int mov_write_tfrf_tags(AVIOContext *pb, MOVMuxContext *mov,
5908 MOVTrack *track)
5909 {
5910 384 int64_t pos = avio_tell(pb);
5911 int i;
5912
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 384 times.
384 for (i = 0; i < mov->ism_lookahead; i++) {
5913 /* Update the tfrf tag for the last ism_lookahead fragments,
5914 * nb_frag_info - 1 is the next fragment to be written. */
5915 ✗ mov_write_tfrf_tag(pb, mov, track, track->nb_frag_info - 2 - i);
5916 }
5917 384 avio_seek(pb, pos, SEEK_SET);
5918 384 return 0;
5919 }
5920
5921 126 static int mov_add_tfra_entries(AVIOContext *pb, MOVMuxContext *mov, int tracks,
5922 int size)
5923 {
5924 int i;
5925
2/2
✓ Branch 0 taken 427 times.
✓ Branch 1 taken 126 times.
553 for (i = 0; i < mov->nb_tracks; i++) {
5926 427 MOVTrack *track = &mov->tracks[i];
5927 MOVFragmentInfo *info;
5928
6/6
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 348 times.
✓ Branch 2 taken 41 times.
✓ Branch 3 taken 38 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 384 times.
427 if ((tracks >= 0 && i != tracks) || !track->entry)
5929 43 continue;
5930 384 track->nb_frag_info++;
5931
2/2
✓ Branch 0 taken 177 times.
✓ Branch 1 taken 207 times.
384 if (track->nb_frag_info >= track->frag_info_capacity) {
5932 177 unsigned new_capacity = track->nb_frag_info + MOV_FRAG_INFO_ALLOC_INCREMENT;
5933
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 177 times.
177 if (av_reallocp_array(&track->frag_info,
5934 new_capacity,
5935 sizeof(*track->frag_info)))
5936 ✗ return AVERROR(ENOMEM);
5937 177 track->frag_info_capacity = new_capacity;
5938 }
5939 384 info = &track->frag_info[track->nb_frag_info - 1];
5940 384 info->offset = avio_tell(pb);
5941 384 info->size = size;
5942 // Try to recreate the original pts for the first packet
5943 // from the fields we have stored
5944 384 info->time = track->cluster[0].dts + track->cluster[0].cts;
5945 384 info->duration = track->end_pts -
5946 384 (track->cluster[0].dts + track->cluster[0].cts);
5947 // If the pts is less than zero, we will have trimmed
5948 // away parts of the media track using an edit list,
5949 // and the corresponding start presentation time is zero.
5950
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 376 times.
384 if (info->time < 0) {
5951 8 info->duration += info->time;
5952 8 info->time = 0;
5953 }
5954 384 info->tfrf_offset = 0;
5955 384 mov_write_tfrf_tags(pb, mov, track);
5956 }
5957 126 return 0;
5958 }
5959
5960 ✗ static void mov_prune_frag_info(MOVMuxContext *mov, int tracks, int max)
5961 {
5962 int i;
5963 ✗ for (i = 0; i < mov->nb_tracks; i++) {
5964 ✗ MOVTrack *track = &mov->tracks[i];
5965 ✗ if ((tracks >= 0 && i != tracks) || !track->entry)
5966 ✗ continue;
5967 ✗ if (track->nb_frag_info > max) {
5968 ✗ memmove(track->frag_info, track->frag_info + (track->nb_frag_info - max), max * sizeof(*track->frag_info));
5969 ✗ track->nb_frag_info = max;
5970 }
5971 }
5972 ✗ }
5973
5974 690 static int mov_write_tfdt_tag(AVIOContext *pb, MOVTrack *track)
5975 {
5976 690 int64_t pos = avio_tell(pb);
5977
5978 690 avio_wb32(pb, 0); /* size */
5979 690 ffio_wfourcc(pb, "tfdt");
5980 690 avio_w8(pb, 1); /* version */
5981 690 avio_wb24(pb, 0);
5982 690 avio_wb64(pb, track->cluster[0].dts - track->start_dts);
5983 690 return update_size(pb, pos);
5984 }
5985
5986 772 static int mov_write_traf_tag(AVIOContext *pb, MOVMuxContext *mov,
5987 MOVTrack *track, int64_t moof_offset,
5988 int moof_size)
5989 {
5990 772 int64_t pos = avio_tell(pb);
5991 772 int i, start = 0;
5992 772 avio_wb32(pb, 0); /* size placeholder */
5993 772 ffio_wfourcc(pb, "traf");
5994
5995 772 mov_write_tfhd_tag(pb, mov, track, moof_offset);
5996
2/2
✓ Branch 0 taken 690 times.
✓ Branch 1 taken 82 times.
772 if (mov->mode != MODE_ISM)
5997 690 mov_write_tfdt_tag(pb, track);
5998
2/2
✓ Branch 0 taken 17598 times.
✓ Branch 1 taken 772 times.
18370 for (i = 1; i < track->entry; i++) {
5999
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 17596 times.
17598 if (track->cluster[i].pos != track->cluster[i - 1].pos + track->cluster[i - 1].size) {
6000 2 mov_write_trun_tag(pb, mov, track, moof_size, start, i);
6001 2 start = i;
6002 }
6003 }
6004 772 mov_write_trun_tag(pb, mov, track, moof_size, start, track->entry);
6005
2/2
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 690 times.
772 if (mov->mode == MODE_ISM) {
6006 82 mov_write_tfxd_tag(pb, track);
6007
6008
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 82 times.
82 if (mov->ism_lookahead) {
6009 ✗ int size = 16 + 4 + 1 + 16 * mov->ism_lookahead;
6010
6011 ✗ if (track->nb_frag_info > 0) {
6012 ✗ MOVFragmentInfo *info = &track->frag_info[track->nb_frag_info - 1];
6013 ✗ if (!info->tfrf_offset)
6014 ✗ info->tfrf_offset = avio_tell(pb);
6015 }
6016 ✗ avio_wb32(pb, 8 + size);
6017 ✗ ffio_wfourcc(pb, "free");
6018 ✗ ffio_fill(pb, 0, size);
6019 }
6020 }
6021
6022
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 772 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
772 if (track->cenc.aes_ctr && (mov->flags & FF_MOV_FLAG_FRAGMENT))
6023 ✗ ff_mov_cenc_write_stbl_atoms(&track->cenc, pb, moof_offset);
6024
6025 772 return update_size(pb, pos);
6026 }
6027
6028 256 static int mov_write_moof_tag_internal(AVIOContext *pb, MOVMuxContext *mov,
6029 int tracks, int moof_size)
6030 {
6031 256 int64_t pos = avio_tell(pb);
6032 int i;
6033
6034 256 avio_wb32(pb, 0); /* size placeholder */
6035 256 ffio_wfourcc(pb, "moof");
6036 256 mov->first_trun = 1;
6037
6038 256 mov_write_mfhd_tag(pb, mov);
6039
2/2
✓ Branch 0 taken 858 times.
✓ Branch 1 taken 256 times.
1114 for (i = 0; i < mov->nb_tracks; i++) {
6040 858 MOVTrack *track = &mov->tracks[i];
6041
4/4
✓ Branch 0 taken 158 times.
✓ Branch 1 taken 700 times.
✓ Branch 2 taken 76 times.
✓ Branch 3 taken 82 times.
858 if (tracks >= 0 && i != tracks)
6042 76 continue;
6043
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 772 times.
782 if (!track->entry)
6044 10 continue;
6045
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 772 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
772 if (track->cenc.aes_ctr && (mov->flags & FF_MOV_FLAG_FRAGMENT))
6046 ✗ mov_write_pssh_tag(pb, track->st);
6047 772 mov_write_traf_tag(pb, mov, track, pos, moof_size);
6048 }
6049
6050 256 return update_size(pb, pos);
6051 }
6052
6053 478 static int mov_write_sidx_tag(AVIOContext *pb,
6054 MOVTrack *track, int ref_size, int total_sidx_size)
6055 {
6056 478 int64_t pos = avio_tell(pb), offset_pos, end_pos;
6057 int64_t presentation_time, duration, offset;
6058 unsigned starts_with_SAP;
6059 int i, entries;
6060
6061
1/2
✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
478 if (track->entry) {
6062 478 entries = 1;
6063 478 presentation_time = track->cluster[0].dts + track->cluster[0].cts;
6064 478 duration = track->end_pts -
6065 478 (track->cluster[0].dts + track->cluster[0].cts);
6066 478 starts_with_SAP = track->cluster[0].flags & MOV_SYNC_SAMPLE;
6067
6068 // pts<0 should be cut away using edts
6069
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 472 times.
478 if (presentation_time < 0) {
6070 6 duration += presentation_time;
6071 6 presentation_time = 0;
6072 }
6073 } else {
6074 ✗ entries = track->nb_frag_info;
6075 ✗ if (entries <= 0)
6076 ✗ return 0;
6077 ✗ presentation_time = track->frag_info[0].time;
6078 }
6079
6080 478 avio_wb32(pb, 0); /* size */
6081 478 ffio_wfourcc(pb, "sidx");
6082 478 avio_w8(pb, 1); /* version */
6083 478 avio_wb24(pb, 0);
6084 478 avio_wb32(pb, track->track_id); /* reference_ID */
6085 478 avio_wb32(pb, track->timescale); /* timescale */
6086 478 avio_wb64(pb, presentation_time); /* earliest_presentation_time */
6087 478 offset_pos = avio_tell(pb);
6088 478 avio_wb64(pb, 0); /* first_offset (offset to referenced moof) */
6089 478 avio_wb16(pb, 0); /* reserved */
6090
6091 478 avio_wb16(pb, entries); /* reference_count */
6092
2/2
✓ Branch 0 taken 478 times.
✓ Branch 1 taken 478 times.
956 for (i = 0; i < entries; i++) {
6093
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 478 times.
478 if (!track->entry) {
6094 ✗ if (i > 1 && track->frag_info[i].offset != track->frag_info[i - 1].offset + track->frag_info[i - 1].size) {
6095 ✗ av_log(NULL, AV_LOG_ERROR, "Non-consecutive fragments, writing incorrect sidx\n");
6096 }
6097 ✗ duration = track->frag_info[i].duration;
6098 ✗ ref_size = track->frag_info[i].size;
6099 ✗ starts_with_SAP = 1;
6100 }
6101 478 avio_wb32(pb, (0 << 31) | (ref_size & 0x7fffffff)); /* reference_type (0 = media) | referenced_size */
6102 478 avio_wb32(pb, duration); /* subsegment_duration */
6103 478 avio_wb32(pb, (starts_with_SAP << 31) | (0 << 28) | 0); /* starts_with_SAP | SAP_type | SAP_delta_time */
6104 }
6105
6106 478 end_pos = avio_tell(pb);
6107 478 offset = pos + total_sidx_size - end_pos;
6108 478 avio_seek(pb, offset_pos, SEEK_SET);
6109 478 avio_wb64(pb, offset);
6110 478 avio_seek(pb, end_pos, SEEK_SET);
6111 478 return update_size(pb, pos);
6112 }
6113
6114 26 static int mov_write_sidx_tags(AVIOContext *pb, MOVMuxContext *mov,
6115 int tracks, int ref_size)
6116 {
6117 int i, round, ret;
6118 AVIOContext *avio_buf;
6119 26 int total_size = 0;
6120
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 26 times.
78 for (round = 0; round < 2; round++) {
6121 // First run one round to calculate the total size of all
6122 // sidx atoms.
6123 // This would be much simpler if we'd only write one sidx
6124 // atom, for the first track in the moof.
6125
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 26 times.
52 if (round == 0) {
6126
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
26 if ((ret = ffio_open_null_buf(&avio_buf)) < 0)
6127 ✗ return ret;
6128 } else {
6129 26 avio_buf = pb;
6130 }
6131
2/2
✓ Branch 0 taken 478 times.
✓ Branch 1 taken 52 times.
530 for (i = 0; i < mov->nb_tracks; i++) {
6132 478 MOVTrack *track = &mov->tracks[i];
6133
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 478 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
478 if (tracks >= 0 && i != tracks)
6134 ✗ continue;
6135 // When writing a sidx for the full file, entry is 0, but
6136 // we want to include all tracks. ref_size is 0 in this case,
6137 // since we read it from frag_info instead.
6138
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 478 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
478 if (!track->entry && ref_size > 0)
6139 ✗ continue;
6140 478 total_size -= mov_write_sidx_tag(avio_buf, track, ref_size,
6141 total_size);
6142 }
6143
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 26 times.
52 if (round == 0) {
6144 26 total_size = ffio_close_null_buf(avio_buf);
6145
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (total_size < 0)
6146 ✗ return total_size;
6147 }
6148 }
6149 26 return 0;
6150 }
6151
6152 ✗ static int mov_write_prft_tag(AVIOContext *pb, MOVMuxContext *mov, int tracks)
6153 {
6154 ✗ int64_t pos = avio_tell(pb), pts_us, ntp_ts;
6155 MOVTrack *first_track;
6156 ✗ int flags = 24;
6157
6158 /* PRFT should be associated with at most one track. So, choosing only the
6159 * first track. */
6160 ✗ if (tracks > 0)
6161 ✗ return 0;
6162 ✗ first_track = &(mov->tracks[0]);
6163
6164 ✗ if (!first_track->entry) {
6165 ✗ av_log(mov->fc, AV_LOG_WARNING, "Unable to write PRFT, no entries in the track\n");
6166 ✗ return 0;
6167 }
6168
6169 ✗ if (first_track->cluster[0].pts == AV_NOPTS_VALUE) {
6170 ✗ av_log(mov->fc, AV_LOG_WARNING, "Unable to write PRFT, first PTS is invalid\n");
6171 ✗ return 0;
6172 }
6173
6174 ✗ if (mov->write_prft == MOV_PRFT_SRC_WALLCLOCK) {
6175 ✗ if (first_track->cluster[0].prft.wallclock) {
6176 /* Round the NTP time to whole milliseconds. */
6177 ✗ ntp_ts = ff_get_formatted_ntp_time((first_track->cluster[0].prft.wallclock / 1000) * 1000 +
6178 NTP_OFFSET_US);
6179 ✗ flags = first_track->cluster[0].prft.flags;
6180 } else
6181 ✗ ntp_ts = ff_get_formatted_ntp_time(ff_ntp_time());
6182 ✗ } else if (mov->write_prft == MOV_PRFT_SRC_PTS) {
6183 ✗ pts_us = av_rescale_q(first_track->cluster[0].pts,
6184 ✗ first_track->st->time_base, AV_TIME_BASE_Q);
6185 ✗ ntp_ts = ff_get_formatted_ntp_time(pts_us + NTP_OFFSET_US);
6186 } else {
6187 ✗ av_log(mov->fc, AV_LOG_WARNING, "Unsupported PRFT box configuration: %d\n",
6188 ✗ mov->write_prft);
6189 ✗ return 0;
6190 }
6191
6192 ✗ avio_wb32(pb, 0); // Size place holder
6193 ✗ ffio_wfourcc(pb, "prft"); // Type
6194 ✗ avio_w8(pb, 1); // Version
6195 ✗ avio_wb24(pb, flags); // Flags
6196 ✗ avio_wb32(pb, first_track->track_id); // reference track ID
6197 ✗ avio_wb64(pb, ntp_ts); // NTP time stamp
6198 ✗ avio_wb64(pb, first_track->cluster[0].pts); //media time
6199 ✗ return update_size(pb, pos);
6200 }
6201
6202 128 static int mov_write_moof_tag(AVIOContext *pb, MOVMuxContext *mov, int tracks,
6203 int64_t mdat_size)
6204 {
6205 AVIOContext *avio_buf;
6206 int ret, moof_size;
6207
6208
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 128 times.
128 if ((ret = ffio_open_null_buf(&avio_buf)) < 0)
6209 ✗ return ret;
6210 128 mov_write_moof_tag_internal(avio_buf, mov, tracks, 0);
6211 128 moof_size = ffio_close_null_buf(avio_buf);
6212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 128 times.
128 if (moof_size < 0)
6213 ✗ return moof_size;
6214
6215
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 100 times.
128 if (mov->flags & FF_MOV_FLAG_DASH &&
6216
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 2 times.
28 !(mov->flags & (FF_MOV_FLAG_GLOBAL_SIDX | FF_MOV_FLAG_SKIP_SIDX)))
6217 26 mov_write_sidx_tags(pb, mov, tracks, moof_size + 8 + mdat_size);
6218
6219
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 128 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
128 if (mov->write_prft > MOV_PRFT_NONE && mov->write_prft < MOV_PRFT_NB)
6220 ✗ mov_write_prft_tag(pb, mov, tracks);
6221
6222
1/2
✓ Branch 0 taken 128 times.
✗ Branch 1 not taken.
128 if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX ||
6223
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 126 times.
128 !(mov->flags & FF_MOV_FLAG_SKIP_TRAILER) ||
6224
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 mov->ism_lookahead) {
6225
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 126 times.
126 if ((ret = mov_add_tfra_entries(pb, mov, tracks, moof_size + 8 + mdat_size)) < 0)
6226 ✗ return ret;
6227
1/2
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
126 if (!(mov->flags & FF_MOV_FLAG_GLOBAL_SIDX) &&
6228
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 126 times.
126 mov->flags & FF_MOV_FLAG_SKIP_TRAILER) {
6229 ✗ mov_prune_frag_info(mov, tracks, mov->ism_lookahead + 1);
6230 }
6231 }
6232
6233 128 return mov_write_moof_tag_internal(pb, mov, tracks, moof_size);
6234 }
6235
6236 173 static int mov_write_tfra_tag(AVIOContext *pb, MOVTrack *track)
6237 {
6238 173 int64_t pos = avio_tell(pb);
6239 int i;
6240
6241 173 avio_wb32(pb, 0); /* size placeholder */
6242 173 ffio_wfourcc(pb, "tfra");
6243 173 avio_w8(pb, 1); /* version */
6244 173 avio_wb24(pb, 0);
6245
6246 173 avio_wb32(pb, track->track_id);
6247 173 avio_wb32(pb, 0); /* length of traf/trun/sample num */
6248 173 avio_wb32(pb, track->nb_frag_info);
6249
2/2
✓ Branch 0 taken 378 times.
✓ Branch 1 taken 173 times.
551 for (i = 0; i < track->nb_frag_info; i++) {
6250 378 avio_wb64(pb, track->frag_info[i].time);
6251 378 avio_wb64(pb, track->frag_info[i].offset + track->data_offset);
6252 378 avio_w8(pb, 1); /* traf number */
6253 378 avio_w8(pb, 1); /* trun number */
6254 378 avio_w8(pb, 1); /* sample number */
6255 }
6256
6257 173 return update_size(pb, pos);
6258 }
6259
6260 45 static int mov_write_mfra_tag(AVIOContext *pb, MOVMuxContext *mov)
6261 {
6262 AVIOContext *mfra_pb;
6263 int i, ret, sz;
6264 uint8_t *buf;
6265
6266 45 ret = avio_open_dyn_buf(&mfra_pb);
6267
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 if (ret < 0)
6268 ✗ return ret;
6269
6270 45 avio_wb32(mfra_pb, 0); /* size placeholder */
6271 45 ffio_wfourcc(mfra_pb, "mfra");
6272 /* An empty mfra atom is enough to indicate to the publishing point that
6273 * the stream has ended. */
6274
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 if (mov->flags & FF_MOV_FLAG_ISML)
6275 ✗ goto done_mfra;
6276
6277
2/2
✓ Branch 0 taken 177 times.
✓ Branch 1 taken 45 times.
222 for (i = 0; i < mov->nb_tracks; i++) {
6278 177 MOVTrack *track = &mov->tracks[i];
6279
2/2
✓ Branch 0 taken 173 times.
✓ Branch 1 taken 4 times.
177 if (track->nb_frag_info)
6280 173 mov_write_tfra_tag(mfra_pb, track);
6281 }
6282
6283 45 avio_wb32(mfra_pb, 16);
6284 45 ffio_wfourcc(mfra_pb, "mfro");
6285 45 avio_wb32(mfra_pb, 0); /* version + flags */
6286 45 avio_wb32(mfra_pb, avio_tell(mfra_pb) + 4);
6287
6288 45 done_mfra:
6289
6290 45 sz = update_size(mfra_pb, 0);
6291 45 ret = avio_get_dyn_buf(mfra_pb, &buf);
6292 45 avio_write(pb, buf, ret);
6293 45 ffio_free_dyn_buf(&mfra_pb);
6294
6295 45 return sz;
6296 }
6297
6298 213 static int mov_write_mdat_tag(AVIOContext *pb, MOVMuxContext *mov)
6299 {
6300 213 avio_wb32(pb, 8); // placeholder for extended size field (64 bit)
6301
2/2
✓ Branch 0 taken 153 times.
✓ Branch 1 taken 60 times.
213 ffio_wfourcc(pb, mov->mode == MODE_MOV ? "wide" : "free");
6302
6303 213 mov->mdat_pos = avio_tell(pb);
6304 213 avio_wb32(pb, 0); /* size placeholder*/
6305 213 ffio_wfourcc(pb, "mdat");
6306 213 return 0;
6307 }
6308
6309 528 static void mov_write_ftyp_tag_internal(AVIOContext *pb, AVFormatContext *s,
6310 int has_h264, int has_video, int write_minor)
6311 {
6312 528 MOVMuxContext *mov = s->priv_data;
6313 528 int minor = 0x200;
6314
6315
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 528 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
528 if (mov->major_brand && strlen(mov->major_brand) >= 4)
6316 ✗ ffio_wfourcc(pb, mov->major_brand);
6317
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 528 times.
528 else if (mov->mode == MODE_3GP) {
6318 ✗ ffio_wfourcc(pb, has_h264 ? "3gp6" : "3gp4");
6319 ✗ minor = has_h264 ? 0x100 : 0x200;
6320
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 526 times.
528 } else if (mov->mode == MODE_AVIF) {
6321
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 ffio_wfourcc(pb, mov->is_animated_avif ? "avis" : "avif");
6322 2 minor = 0;
6323
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 526 times.
526 } else if (mov->mode & MODE_3G2) {
6324 ✗ ffio_wfourcc(pb, has_h264 ? "3g2b" : "3g2a");
6325 ✗ minor = has_h264 ? 0x20000 : 0x10000;
6326
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 524 times.
526 } else if (mov->mode == MODE_PSP)
6327 2 ffio_wfourcc(pb, "MSNV");
6328
4/4
✓ Branch 0 taken 194 times.
✓ Branch 1 taken 330 times.
✓ Branch 2 taken 78 times.
✓ Branch 3 taken 116 times.
524 else if (mov->mode == MODE_MP4 && mov->flags & FF_MOV_FLAG_FRAGMENT &&
6329
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 70 times.
78 mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS)
6330 8 ffio_wfourcc(pb, "iso6"); // Required when using signed CTS offsets in trun boxes
6331
4/4
✓ Branch 0 taken 186 times.
✓ Branch 1 taken 330 times.
✓ Branch 2 taken 34 times.
✓ Branch 3 taken 152 times.
516 else if (mov->mode == MODE_MP4 && mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF)
6332 34 ffio_wfourcc(pb, "iso5"); // Required when using default-base-is-moof
6333
3/4
✓ Branch 0 taken 152 times.
✓ Branch 1 taken 330 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 152 times.
482 else if (mov->mode == MODE_MP4 && mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS)
6334 ✗ ffio_wfourcc(pb, "iso4");
6335
2/2
✓ Branch 0 taken 152 times.
✓ Branch 1 taken 330 times.
482 else if (mov->mode == MODE_MP4)
6336 152 ffio_wfourcc(pb, "isom");
6337
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 328 times.
330 else if (mov->mode == MODE_IPOD)
6338
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 ffio_wfourcc(pb, has_video ? "M4V ":"M4A ");
6339
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 318 times.
328 else if (mov->mode == MODE_ISM)
6340 10 ffio_wfourcc(pb, "isml");
6341
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 318 times.
318 else if (mov->mode == MODE_F4V)
6342 ✗ ffio_wfourcc(pb, "f4v ");
6343 else
6344 318 ffio_wfourcc(pb, "qt ");
6345
6346
2/2
✓ Branch 0 taken 264 times.
✓ Branch 1 taken 264 times.
528 if (write_minor)
6347 264 avio_wb32(pb, minor);
6348 528 }
6349
6350 264 static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s)
6351 {
6352 264 MOVMuxContext *mov = s->priv_data;
6353 264 int64_t pos = avio_tell(pb);
6354 264 int has_h264 = 0, has_av1 = 0, has_video = 0, has_dolby = 0, has_id3 = 0;
6355 264 int has_iamf = 0;
6356
6357 #if CONFIG_IAMFENC
6358
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 258 times.
265 for (int i = 0; i < s->nb_stream_groups; i++) {
6359 7 const AVStreamGroup *stg = s->stream_groups[i];
6360
6361
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
7 if (stg->type == AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT ||
6362
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 stg->type == AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION) {
6363 6 has_iamf = 1;
6364 6 break;
6365 }
6366 }
6367 #endif
6368
2/2
✓ Branch 0 taken 429 times.
✓ Branch 1 taken 264 times.
693 for (int i = 0; i < mov->nb_streams; i++) {
6369 429 AVStream *st = mov->tracks[i].st;
6370
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 427 times.
429 if (is_cover_image(st))
6371 2 continue;
6372
2/2
✓ Branch 0 taken 209 times.
✓ Branch 1 taken 218 times.
427 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
6373 209 has_video = 1;
6374
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 386 times.
427 if (st->codecpar->codec_id == AV_CODEC_ID_H264)
6375 41 has_h264 = 1;
6376
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 424 times.
427 if (st->codecpar->codec_id == AV_CODEC_ID_AV1)
6377 3 has_av1 = 1;
6378
2/2
✓ Branch 0 taken 421 times.
✓ Branch 1 taken 6 times.
427 if (st->codecpar->codec_id == AV_CODEC_ID_AC3 ||
6379
2/2
✓ Branch 0 taken 417 times.
✓ Branch 1 taken 4 times.
421 st->codecpar->codec_id == AV_CODEC_ID_EAC3 ||
6380
3/4
✓ Branch 0 taken 417 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 415 times.
834 st->codecpar->codec_id == AV_CODEC_ID_TRUEHD ||
6381 417 av_packet_side_data_get(st->codecpar->coded_side_data,
6382 417 st->codecpar->nb_coded_side_data,
6383 AV_PKT_DATA_DOVI_CONF))
6384 12 has_dolby = 1;
6385
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 427 times.
427 if (st->codecpar->codec_id == AV_CODEC_ID_TIMED_ID3)
6386 ✗ has_id3 = 1;
6387 }
6388
6389 264 avio_wb32(pb, 0); /* size */
6390 264 ffio_wfourcc(pb, "ftyp");
6391
6392 // Write major brand
6393 264 mov_write_ftyp_tag_internal(pb, s, has_h264, has_video, 1);
6394 // Write the major brand as the first compatible brand as well
6395 264 mov_write_ftyp_tag_internal(pb, s, has_h264, has_video, 0);
6396
6397 // Write compatible brands, ensuring that we don't write the major brand as a
6398 // compatible brand a second time.
6399
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 259 times.
264 if (mov->mode == MODE_ISM) {
6400 5 ffio_wfourcc(pb, "piff");
6401 #if CONFIG_AVIF_MUXER
6402
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 258 times.
259 } else if (mov->mode == MODE_AVIF) {
6403 1 const MOVTrack *trk = &mov->tracks[0];
6404 const AVPixFmtDescriptor *pix_fmt_desc =
6405 1 av_pix_fmt_desc_get(s->streams[0]->codecpar->format);
6406 1 int depth = 0, log2_chroma_w, log2_chroma_h;
6407
6408
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (pix_fmt_desc->nb_components > 0) {
6409 1 depth = pix_fmt_desc->comp[0].depth;
6410 1 log2_chroma_w = pix_fmt_desc->log2_chroma_w;
6411 1 log2_chroma_h = pix_fmt_desc->log2_chroma_h;
6412 } else {
6413 AV1SequenceParameters seq;
6414 ✗ int ret = ff_av1_parse_seq_header(&seq, trk->extradata[trk->last_stsd_index],
6415 ✗ trk->extradata_size[trk->last_stsd_index]);
6416 ✗ if (!ret) {
6417 ✗ depth = seq.bitdepth;
6418 ✗ log2_chroma_w = seq.chroma_subsampling_x;
6419 ✗ log2_chroma_h = seq.chroma_subsampling_y;
6420 }
6421 }
6422
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (mov->is_animated_avif) {
6423 // For animated AVIF, major brand is "avis". Add "avif" as a
6424 // compatible brand.
6425 ✗ ffio_wfourcc(pb, "avif");
6426 ✗ ffio_wfourcc(pb, "msf1");
6427 ✗ ffio_wfourcc(pb, "iso8");
6428 }
6429 1 ffio_wfourcc(pb, "mif1");
6430 1 ffio_wfourcc(pb, "miaf");
6431
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 if (depth == 8 || depth == 10) {
6432 // MA1B and MA1A brands are based on AV1 profile. Short hand for
6433 // computing that is based on chroma subsampling type. 420 chroma
6434 // subsampling is MA1B. 444 chroma subsampling is MA1A.
6435
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 if (!log2_chroma_w && !log2_chroma_h) {
6436 // 444 chroma subsampling.
6437 1 ffio_wfourcc(pb, "MA1A");
6438 } else {
6439 // 420 chroma subsampling.
6440 ✗ ffio_wfourcc(pb, "MA1B");
6441 }
6442 }
6443 #endif
6444
2/2
✓ Branch 0 taken 99 times.
✓ Branch 1 taken 159 times.
258 } else if (mov->mode != MODE_MOV) {
6445 // We add tfdt atoms when fragmenting, signal this with the iso6 compatible
6446 // brand, if not already the major brand. This is compatible with users that
6447 // don't understand tfdt.
6448
2/2
✓ Branch 0 taken 97 times.
✓ Branch 1 taken 2 times.
99 if (mov->mode == MODE_MP4) {
6449
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 95 times.
97 if (mov->flags & FF_MOV_FLAG_CMAF)
6450 2 ffio_wfourcc(pb, "cmfc");
6451
4/4
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 58 times.
✓ Branch 2 taken 35 times.
✓ Branch 3 taken 4 times.
97 if (mov->flags & FF_MOV_FLAG_FRAGMENT && !(mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS))
6452 35 ffio_wfourcc(pb, "iso6");
6453
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 95 times.
97 if (has_av1)
6454 2 ffio_wfourcc(pb, "av01");
6455
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 86 times.
97 if (has_dolby)
6456 11 ffio_wfourcc(pb, "dby1");
6457
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 91 times.
97 if (has_iamf)
6458 6 ffio_wfourcc(pb, "iamf");
6459 } else {
6460
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (mov->flags & FF_MOV_FLAG_FRAGMENT)
6461 ✗ ffio_wfourcc(pb, "iso6");
6462
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF)
6463 ✗ ffio_wfourcc(pb, "iso5");
6464
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS)
6465 ✗ ffio_wfourcc(pb, "iso4");
6466 }
6467 // Brands prior to iso5 can't be signaled when using default-base-is-moof
6468
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 19 times.
99 if (!(mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF)) {
6469 // write isom for mp4 only if it it's not the major brand already.
6470
4/4
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 76 times.
80 if (mov->mode != MODE_MP4 || mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS)
6471 4 ffio_wfourcc(pb, "isom");
6472 80 ffio_wfourcc(pb, "iso2");
6473
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 55 times.
80 if (has_h264)
6474 25 ffio_wfourcc(pb, "avc1");
6475 }
6476 }
6477
6478
2/2
✓ Branch 0 taken 97 times.
✓ Branch 1 taken 167 times.
264 if (mov->mode == MODE_MP4)
6479 97 ffio_wfourcc(pb, "mp41");
6480
6481
3/4
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 249 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
264 if (mov->flags & FF_MOV_FLAG_DASH && mov->flags & FF_MOV_FLAG_GLOBAL_SIDX)
6482 ✗ ffio_wfourcc(pb, "dash");
6483
6484
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 264 times.
264 if (has_id3)
6485 ✗ ffio_wfourcc(pb, "aid3");
6486
6487 264 return update_size(pb, pos);
6488 }
6489
6490 1 static int mov_write_uuidprof_tag(AVIOContext *pb, AVFormatContext *s)
6491 {
6492 1 AVStream *video_st = s->streams[0];
6493 1 AVCodecParameters *video_par = s->streams[0]->codecpar;
6494 1 AVCodecParameters *audio_par = s->streams[1]->codecpar;
6495 1 int audio_rate = audio_par->sample_rate;
6496 2 int64_t frame_rate = video_st->avg_frame_rate.den ?
6497
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 (video_st->avg_frame_rate.num * 0x10000LL) / video_st->avg_frame_rate.den :
6498 0;
6499 1 int audio_kbitrate = audio_par->bit_rate / 1000;
6500 1 int video_kbitrate = FFMIN(video_par->bit_rate / 1000, 800 - audio_kbitrate);
6501
6502
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (frame_rate < 0 || frame_rate > INT32_MAX) {
6503 ✗ av_log(s, AV_LOG_ERROR, "Frame rate %f outside supported range\n", frame_rate / (double)0x10000);
6504 ✗ return AVERROR(EINVAL);
6505 }
6506
6507 1 avio_wb32(pb, 0x94); /* size */
6508 1 ffio_wfourcc(pb, "uuid");
6509 1 ffio_wfourcc(pb, "PROF");
6510
6511 1 avio_wb32(pb, 0x21d24fce); /* 96 bit UUID */
6512 1 avio_wb32(pb, 0xbb88695c);
6513 1 avio_wb32(pb, 0xfac9c740);
6514
6515 1 avio_wb32(pb, 0x0); /* ? */
6516 1 avio_wb32(pb, 0x3); /* 3 sections ? */
6517
6518 1 avio_wb32(pb, 0x14); /* size */
6519 1 ffio_wfourcc(pb, "FPRF");
6520 1 avio_wb32(pb, 0x0); /* ? */
6521 1 avio_wb32(pb, 0x0); /* ? */
6522 1 avio_wb32(pb, 0x0); /* ? */
6523
6524 1 avio_wb32(pb, 0x2c); /* size */
6525 1 ffio_wfourcc(pb, "APRF"); /* audio */
6526 1 avio_wb32(pb, 0x0);
6527 1 avio_wb32(pb, 0x2); /* TrackID */
6528 1 ffio_wfourcc(pb, "mp4a");
6529 1 avio_wb32(pb, 0x20f);
6530 1 avio_wb32(pb, 0x0);
6531 1 avio_wb32(pb, audio_kbitrate);
6532 1 avio_wb32(pb, audio_kbitrate);
6533 1 avio_wb32(pb, audio_rate);
6534 1 avio_wb32(pb, audio_par->ch_layout.nb_channels);
6535
6536 1 avio_wb32(pb, 0x34); /* size */
6537 1 ffio_wfourcc(pb, "VPRF"); /* video */
6538 1 avio_wb32(pb, 0x0);
6539 1 avio_wb32(pb, 0x1); /* TrackID */
6540
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (video_par->codec_id == AV_CODEC_ID_H264) {
6541 1 ffio_wfourcc(pb, "avc1");
6542 1 avio_wb16(pb, 0x014D);
6543 1 avio_wb16(pb, 0x0015);
6544 } else {
6545 ✗ ffio_wfourcc(pb, "mp4v");
6546 ✗ avio_wb16(pb, 0x0000);
6547 ✗ avio_wb16(pb, 0x0103);
6548 }
6549 1 avio_wb32(pb, 0x0);
6550 1 avio_wb32(pb, video_kbitrate);
6551 1 avio_wb32(pb, video_kbitrate);
6552 1 avio_wb32(pb, frame_rate);
6553 1 avio_wb32(pb, frame_rate);
6554 1 avio_wb16(pb, video_par->width);
6555 1 avio_wb16(pb, video_par->height);
6556 1 avio_wb32(pb, 0x010001); /* ? */
6557
6558 1 return 0;
6559 }
6560
6561 264 static int mov_write_identification(AVIOContext *pb, AVFormatContext *s)
6562 {
6563 264 MOVMuxContext *mov = s->priv_data;
6564 int i;
6565
6566 264 mov_write_ftyp_tag(pb,s);
6567
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 263 times.
264 if (mov->mode == MODE_PSP) {
6568 1 int video_streams_nb = 0, audio_streams_nb = 0, other_streams_nb = 0;
6569
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 for (i = 0; i < mov->nb_streams; i++) {
6570 2 AVStream *st = mov->tracks[i].st;
6571
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (is_cover_image(st))
6572 ✗ continue;
6573
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
6574 1 video_streams_nb++;
6575
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
6576 1 audio_streams_nb++;
6577 else
6578 ✗ other_streams_nb++;
6579 }
6580
6581
3/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
1 if (video_streams_nb != 1 || audio_streams_nb != 1 || other_streams_nb) {
6582 ✗ av_log(s, AV_LOG_ERROR, "PSP mode need one video and one audio stream\n");
6583 ✗ return AVERROR(EINVAL);
6584 }
6585 1 return mov_write_uuidprof_tag(pb, s);
6586 }
6587 263 return 0;
6588 }
6589
6590 8 static int mov_parse_mpeg2_frame(AVPacket *pkt, uint32_t *flags)
6591 {
6592 8 uint32_t c = -1;
6593 8 int i, closed_gop = 0;
6594
6595
1/2
✓ Branch 0 taken 368 times.
✗ Branch 1 not taken.
368 for (i = 0; i < pkt->size - 4; i++) {
6596 368 c = (c << 8) + pkt->data[i];
6597
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 360 times.
368 if (c == 0x1b8) { // gop
6598 8 closed_gop = pkt->data[i + 4] >> 6 & 0x01;
6599
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 352 times.
360 } else if (c == 0x100) { // pic
6600 8 int temp_ref = (pkt->data[i + 1] << 2) | (pkt->data[i + 2] >> 6);
6601
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8 if (!temp_ref || closed_gop) // I picture is not reordered
6602 8 *flags = MOV_SYNC_SAMPLE;
6603 else
6604 ✗ *flags = MOV_PARTIAL_SYNC_SAMPLE;
6605 8 break;
6606 }
6607 }
6608 8 return 0;
6609 }
6610
6611 ✗ static void mov_parse_vc1_frame(AVPacket *pkt, MOVTrack *trk)
6612 {
6613 ✗ const uint8_t *start, *next, *end = pkt->data + pkt->size;
6614 ✗ int seq = 0, entry = 0;
6615 ✗ int key = pkt->flags & AV_PKT_FLAG_KEY;
6616 ✗ start = find_next_marker(pkt->data, end);
6617 ✗ for (next = start; next < end; start = next) {
6618 ✗ next = find_next_marker(start + 4, end);
6619 ✗ switch (AV_RB32(start)) {
6620 ✗ case VC1_CODE_SEQHDR:
6621 ✗ seq = 1;
6622 ✗ break;
6623 ✗ case VC1_CODE_ENTRYPOINT:
6624 ✗ entry = 1;
6625 ✗ break;
6626 ✗ case VC1_CODE_SLICE:
6627 ✗ trk->vc1_info.slices = 1;
6628 ✗ break;
6629 }
6630 }
6631 ✗ if (!trk->entry && trk->vc1_info.first_packet_seen)
6632 ✗ trk->vc1_info.first_frag_written = 1;
6633 ✗ if (!trk->entry && !trk->vc1_info.first_frag_written) {
6634 /* First packet in first fragment */
6635 ✗ trk->vc1_info.first_packet_seq = seq;
6636 ✗ trk->vc1_info.first_packet_entry = entry;
6637 ✗ trk->vc1_info.first_packet_seen = 1;
6638 ✗ } else if ((seq && !trk->vc1_info.packet_seq) ||
6639 ✗ (entry && !trk->vc1_info.packet_entry)) {
6640 int i;
6641 ✗ for (i = 0; i < trk->entry; i++)
6642 ✗ trk->cluster[i].flags &= ~MOV_SYNC_SAMPLE;
6643 ✗ trk->has_keyframes = 0;
6644 ✗ if (seq)
6645 ✗ trk->vc1_info.packet_seq = 1;
6646 ✗ if (entry)
6647 ✗ trk->vc1_info.packet_entry = 1;
6648 ✗ if (!trk->vc1_info.first_frag_written) {
6649 /* First fragment */
6650 ✗ if ((!seq || trk->vc1_info.first_packet_seq) &&
6651 ✗ (!entry || trk->vc1_info.first_packet_entry)) {
6652 /* First packet had the same headers as this one, readd the
6653 * sync sample flag. */
6654 ✗ trk->cluster[0].flags |= MOV_SYNC_SAMPLE;
6655 ✗ trk->has_keyframes = 1;
6656 }
6657 }
6658 }
6659 ✗ if (trk->vc1_info.packet_seq && trk->vc1_info.packet_entry)
6660 ✗ key = seq && entry;
6661 ✗ else if (trk->vc1_info.packet_seq)
6662 ✗ key = seq;
6663 ✗ else if (trk->vc1_info.packet_entry)
6664 ✗ key = entry;
6665 ✗ if (key) {
6666 ✗ trk->cluster[trk->entry].flags |= MOV_SYNC_SAMPLE;
6667 ✗ trk->has_keyframes++;
6668 }
6669 ✗ }
6670
6671 ✗ static void mov_parse_truehd_frame(AVPacket *pkt, MOVTrack *trk)
6672 {
6673 int length;
6674
6675 ✗ if (pkt->size < 8)
6676 ✗ return;
6677
6678 ✗ length = (AV_RB16(pkt->data) & 0xFFF) * 2;
6679 ✗ if (length < 8 || length > pkt->size)
6680 ✗ return;
6681
6682 ✗ if (AV_RB32(pkt->data + 4) == 0xF8726FBA) {
6683 ✗ trk->cluster[trk->entry].flags |= MOV_SYNC_SAMPLE;
6684 ✗ trk->has_keyframes++;
6685 }
6686
6687 ✗ return;
6688 }
6689
6690 89 static int mov_flush_fragment_interleaving(AVFormatContext *s, MOVTrack *track)
6691 {
6692 89 MOVMuxContext *mov = s->priv_data;
6693 int ret, buf_size;
6694 uint8_t *buf;
6695 int i, offset;
6696
6697
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 89 times.
89 if (!track->mdat_buf)
6698 ✗ return 0;
6699
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 88 times.
89 if (!mov->mdat_buf) {
6700
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if ((ret = avio_open_dyn_buf(&mov->mdat_buf)) < 0)
6701 ✗ return ret;
6702 }
6703 89 buf_size = avio_get_dyn_buf(track->mdat_buf, &buf);
6704
6705 89 offset = avio_tell(mov->mdat_buf);
6706 89 avio_write(mov->mdat_buf, buf, buf_size);
6707 89 ffio_reset_dyn_buf(track->mdat_buf);
6708
6709
2/2
✓ Branch 0 taken 88 times.
✓ Branch 1 taken 89 times.
177 for (i = track->entries_flushed; i < track->entry; i++)
6710 88 track->cluster[i].pos += offset;
6711 89 track->entries_flushed = track->entry;
6712 89 return 0;
6713 }
6714
6715 28 static int mov_write_squashed_packet(AVFormatContext *s, MOVTrack *track)
6716 {
6717 28 MOVMuxContext *mov = s->priv_data;
6718 28 AVPacket *squashed_packet = mov->pkt;
6719 28 int ret = AVERROR_BUG;
6720
6721
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 switch (track->st->codecpar->codec_id) {
6722 28 case AV_CODEC_ID_TTML: {
6723 28 int had_packets = !!track->squashed_packet_queue.head;
6724
6725
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
28 if ((ret = ff_mov_generate_squashed_ttml_packet(s, track, squashed_packet)) < 0) {
6726 ✗ goto finish_squash;
6727 }
6728
6729 // We have generated a padding packet (no actual input packets in
6730 // queue) and its duration is zero. Skipping writing it.
6731
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
28 if (!had_packets && squashed_packet->duration == 0) {
6732 ✗ goto finish_squash;
6733 }
6734
6735 28 track->end_reliable = 1;
6736 28 break;
6737 }
6738 ✗ default:
6739 ✗ ret = AVERROR(EINVAL);
6740 ✗ goto finish_squash;
6741 }
6742
6743 28 squashed_packet->stream_index = track->st->index;
6744
6745 28 ret = mov_write_single_packet(s, squashed_packet);
6746
6747 28 finish_squash:
6748 28 av_packet_unref(squashed_packet);
6749
6750 28 return ret;
6751 }
6752
6753 423 static int mov_write_squashed_packets(AVFormatContext *s)
6754 {
6755 423 MOVMuxContext *mov = s->priv_data;
6756
6757
2/2
✓ Branch 0 taken 1097 times.
✓ Branch 1 taken 423 times.
1520 for (int i = 0; i < mov->nb_streams; i++) {
6758 1097 MOVTrack *track = &mov->tracks[i];
6759 1097 int ret = AVERROR_BUG;
6760
6761
4/4
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 1067 times.
✓ Branch 2 taken 28 times.
✓ Branch 3 taken 2 times.
1097 if (track->squash_fragment_samples_to_one && !track->entry) {
6762
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
28 if ((ret = mov_write_squashed_packet(s, track)) < 0) {
6763 ✗ av_log(s, AV_LOG_ERROR,
6764 "Failed to write squashed packet for %s stream with "
6765 "index %d and track id %d. Error: %s\n",
6766 ✗ avcodec_get_name(track->st->codecpar->codec_id),
6767 ✗ track->st->index, track->track_id,
6768 ✗ av_err2str(ret));
6769 ✗ return ret;
6770 }
6771 }
6772 }
6773
6774 423 return 0;
6775 }
6776
6777 396 static int mov_finish_fragment(MOVMuxContext *mov, MOVTrack *track,
6778 int64_t ref_pos)
6779 {
6780 int i;
6781
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 394 times.
396 if (!track->entry)
6782 2 return 0;
6783
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 386 times.
394 if (mov->flags & FF_MOV_FLAG_HYBRID_FRAGMENTED) {
6784
2/2
✓ Branch 0 taken 124 times.
✓ Branch 1 taken 8 times.
132 for (i = 0; i < track->entry; i++)
6785 124 track->cluster[i].pos += ref_pos + track->data_offset;
6786
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 if (track->cluster_written == 0) {
6787 // First flush. Chunking for this fragment may already have been
6788 // done, either if we didn't use empty_moov, or if we did use
6789 // delay_moov. In either case, reset chunking here.
6790
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 4 times.
67 for (i = 0; i < track->entry; i++) {
6791 63 track->cluster[i].chunkNum = 0;
6792 63 track->cluster[i].samples_in_chunk = track->cluster[i].entries;
6793 }
6794 }
6795
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (av_reallocp_array(&track->cluster_written,
6796 8 track->entry_written + track->entry,
6797 sizeof(*track->cluster)))
6798 ✗ return AVERROR(ENOMEM);
6799 8 memcpy(&track->cluster_written[track->entry_written],
6800 8 track->cluster, track->entry * sizeof(*track->cluster));
6801 8 track->entry_written += track->entry;
6802 }
6803 394 track->entry = 0;
6804 394 track->entries_flushed = 0;
6805 394 track->end_reliable = 0;
6806 394 return 0;
6807 }
6808
6809 162 static int mov_flush_fragment(AVFormatContext *s, int force)
6810 {
6811 162 MOVMuxContext *mov = s->priv_data;
6812 162 int i, first_track = -1;
6813 162 int64_t mdat_size = 0, mdat_start = 0;
6814 int ret;
6815 162 int has_video = 0, starts_with_key = 0, first_video_track = 1;
6816
6817
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 162 times.
162 if (!(mov->flags & FF_MOV_FLAG_FRAGMENT))
6818 ✗ return 0;
6819
6820 // Check if we have any tracks that require squashing.
6821 // In that case, we'll have to write the packet here.
6822
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 162 times.
162 if ((ret = mov_write_squashed_packets(s)) < 0)
6823 ✗ return ret;
6824
6825 // Try to fill in the duration of the last packet in each stream
6826 // from queued packets in the interleave queues. If the flushing
6827 // of fragments was triggered automatically by an AVPacket, we
6828 // already have reliable info for the end of that track, but other
6829 // tracks may need to be filled in.
6830
2/2
✓ Branch 0 taken 673 times.
✓ Branch 1 taken 162 times.
835 for (i = 0; i < mov->nb_streams; i++) {
6831 673 MOVTrack *track = &mov->tracks[i];
6832
2/2
✓ Branch 0 taken 581 times.
✓ Branch 1 taken 92 times.
673 if (!track->end_reliable) {
6833 581 const AVPacket *pkt = ff_interleaved_peek(s, i);
6834
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 575 times.
581 if (pkt) {
6835 int64_t offset, dts, pts;
6836 6 ff_get_muxer_ts_offset(s, i, &offset);
6837 6 pts = pkt->pts + offset;
6838 6 dts = pkt->dts + offset;
6839
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (track->dts_shift != AV_NOPTS_VALUE)
6840 ✗ dts += track->dts_shift;
6841 6 track->track_duration = dts - track->start_dts;
6842
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (pts != AV_NOPTS_VALUE)
6843 6 track->end_pts = pts;
6844 else
6845 ✗ track->end_pts = dts;
6846
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (!(pkt->flags & AV_PKT_FLAG_DISCARD))
6847 6 track->elst_end_pts = track->end_pts;
6848 }
6849 }
6850 }
6851
6852
2/2
✓ Branch 0 taken 679 times.
✓ Branch 1 taken 162 times.
841 for (i = 0; i < mov->nb_tracks; i++) {
6853 679 MOVTrack *track = &mov->tracks[i];
6854
2/2
✓ Branch 0 taken 192 times.
✓ Branch 1 taken 487 times.
679 if (track->entry <= 1)
6855 192 continue;
6856 // Sample durations are calculated as the diff of dts values,
6857 // but for the last sample in a fragment, we don't know the dts
6858 // of the first sample in the next fragment, so we have to rely
6859 // on what was set as duration in the AVPacket. Not all callers
6860 // set this though, so we might want to replace it with an
6861 // estimate if it currently is zero.
6862
2/2
✓ Branch 1 taken 485 times.
✓ Branch 2 taken 2 times.
487 if (get_cluster_duration(track, track->entry - 1) != 0)
6863 485 continue;
6864 // Use the duration (i.e. dts diff) of the second last sample for
6865 // the last one. This is a wild guess (and fatal if it turns out
6866 // to be too long), but probably the best we can do - having a zero
6867 // duration is bad as well.
6868 2 track->track_duration += get_cluster_duration(track, track->entry - 2);
6869 2 track->end_pts += get_cluster_duration(track, track->entry - 2);
6870
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!mov->missing_duration_warned) {
6871 2 av_log(s, AV_LOG_WARNING,
6872 "Estimating the duration of the last packet in a "
6873 "fragment, consider setting the duration field in "
6874 "AVPacket instead.\n");
6875 2 mov->missing_duration_warned = 1;
6876 }
6877 }
6878
6879
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 132 times.
162 if (!mov->moov_written) {
6880 30 int64_t pos = avio_tell(s->pb);
6881 uint8_t *buf;
6882 int buf_size, moov_size;
6883
6884
2/2
✓ Branch 0 taken 151 times.
✓ Branch 1 taken 23 times.
174 for (i = 0; i < mov->nb_tracks; i++)
6885
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 144 times.
✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
151 if (!mov->tracks[i].entry && !is_cover_image(mov->tracks[i].st))
6886 7 break;
6887 /* Don't write the initial moov unless all tracks have data */
6888
4/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 23 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 3 times.
30 if (i < mov->nb_tracks && !force)
6889 4 return 0;
6890
6891 26 moov_size = get_moov_size(s);
6892
2/2
✓ Branch 0 taken 146 times.
✓ Branch 1 taken 26 times.
172 for (i = 0; i < mov->nb_tracks; i++)
6893 146 mov->tracks[i].data_offset = pos + moov_size + 8;
6894
6895 26 avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_HEADER);
6896
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 5 times.
26 if (mov->flags & FF_MOV_FLAG_DELAY_MOOV &&
6897
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 !(mov->flags & FF_MOV_FLAG_HYBRID_FRAGMENTED))
6898 21 mov_write_identification(s->pb, s);
6899
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
26 if ((ret = mov_write_moov_tag(s->pb, mov, s)) < 0)
6900 ✗ return ret;
6901
6902
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 5 times.
26 if (mov->flags & FF_MOV_FLAG_DELAY_MOOV) {
6903
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX)
6904 ✗ mov->reserved_header_pos = avio_tell(s->pb);
6905 21 avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT);
6906 21 mov->moov_written = 1;
6907 21 return 0;
6908 }
6909
6910
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
5 if (mov->mdat_buf) {
6911 4 buf_size = avio_get_dyn_buf(mov->mdat_buf, &buf);
6912 4 avio_wb32(s->pb, buf_size + 8);
6913 4 ffio_wfourcc(s->pb, "mdat");
6914 4 avio_write(s->pb, buf, buf_size);
6915 4 ffio_reset_dyn_buf(mov->mdat_buf);
6916 }
6917
6918
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX)
6919 ✗ mov->reserved_header_pos = avio_tell(s->pb);
6920
6921 5 mov->moov_written = 1;
6922 5 mov->mdat_size = 0;
6923
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 5 times.
15 for (i = 0; i < mov->nb_tracks; i++)
6924 10 mov_finish_fragment(mov, &mov->tracks[i], 0);
6925 5 avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT);
6926 5 return 0;
6927 }
6928
6929
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 130 times.
132 if (mov->frag_interleave) {
6930
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (i = 0; i < mov->nb_tracks; i++) {
6931 4 MOVTrack *track = &mov->tracks[i];
6932 int ret;
6933
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((ret = mov_flush_fragment_interleaving(s, track)) < 0)
6934 ✗ return ret;
6935 }
6936
6937
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!mov->mdat_buf)
6938 ✗ return 0;
6939 2 mdat_size = avio_tell(mov->mdat_buf);
6940 }
6941
6942
2/2
✓ Branch 0 taken 527 times.
✓ Branch 1 taken 132 times.
659 for (i = 0; i < mov->nb_tracks; i++) {
6943 527 MOVTrack *track = &mov->tracks[i];
6944
4/4
✓ Branch 0 taken 482 times.
✓ Branch 1 taken 45 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 478 times.
527 if (mov->flags & FF_MOV_FLAG_SEPARATE_MOOF || mov->frag_interleave)
6945 49 track->data_offset = 0;
6946 else
6947 478 track->data_offset = mdat_size;
6948
2/2
✓ Branch 0 taken 113 times.
✓ Branch 1 taken 414 times.
527 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
6949 113 has_video = 1;
6950
1/2
✓ Branch 0 taken 113 times.
✗ Branch 1 not taken.
113 if (first_video_track) {
6951
2/2
✓ Branch 0 taken 97 times.
✓ Branch 1 taken 16 times.
113 if (track->entry)
6952 97 starts_with_key = track->cluster[0].flags & MOV_SYNC_SAMPLE;
6953 113 first_video_track = 0;
6954 }
6955 }
6956
2/2
✓ Branch 0 taken 141 times.
✓ Branch 1 taken 386 times.
527 if (!track->entry)
6957 141 continue;
6958
1/2
✓ Branch 0 taken 386 times.
✗ Branch 1 not taken.
386 if (track->mdat_buf)
6959 386 mdat_size += avio_tell(track->mdat_buf);
6960
2/2
✓ Branch 0 taken 111 times.
✓ Branch 1 taken 275 times.
386 if (first_track < 0)
6961 111 first_track = i;
6962 }
6963
6964
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 111 times.
132 if (!mdat_size)
6965 21 return 0;
6966
6967
2/2
✓ Branch 0 taken 107 times.
✓ Branch 1 taken 4 times.
111 avio_write_marker(s->pb,
6968 111 av_rescale(mov->tracks[first_track].cluster[0].dts, AV_TIME_BASE, mov->tracks[first_track].timescale),
6969
2/2
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 13 times.
111 (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);
6970
6971
2/2
✓ Branch 0 taken 394 times.
✓ Branch 1 taken 111 times.
505 for (i = first_track; i < mov->nb_tracks; i++) {
6972 394 MOVTrack *track = &mov->tracks[i];
6973 394 int buf_size, write_moof = 1, moof_tracks = -1;
6974 uint8_t *buf;
6975
6976
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 386 times.
394 if (!track->entry)
6977 8 continue;
6978
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 345 times.
386 if (mov->flags & FF_MOV_FLAG_SEPARATE_MOOF) {
6979 41 mdat_size = avio_tell(track->mdat_buf);
6980 41 moof_tracks = i;
6981 } else {
6982 345 write_moof = i == first_track;
6983 }
6984
6985
2/2
✓ Branch 0 taken 128 times.
✓ Branch 1 taken 258 times.
386 if (write_moof) {
6986 128 avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT);
6987
6988 128 mov_write_moof_tag(s->pb, mov, moof_tracks, mdat_size);
6989 128 mov->fragments++;
6990
6991
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 128 times.
128 if (track->cenc.aes_ctr)
6992 ✗ ff_mov_cenc_flush(&track->cenc);
6993
6994 128 avio_wb32(s->pb, mdat_size + 8);
6995 128 ffio_wfourcc(s->pb, "mdat");
6996 128 mdat_start = avio_tell(s->pb);
6997 }
6998
6999 386 mov_finish_fragment(mov, &mov->tracks[i], mdat_start);
7000
2/2
✓ Branch 0 taken 383 times.
✓ Branch 1 taken 3 times.
386 if (!mov->frag_interleave) {
7001
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 383 times.
383 if (!track->mdat_buf)
7002 ✗ continue;
7003 383 buf_size = avio_get_dyn_buf(track->mdat_buf, &buf);
7004 383 avio_write(s->pb, buf, buf_size);
7005 383 ffio_reset_dyn_buf(track->mdat_buf);
7006 } else {
7007
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!mov->mdat_buf)
7008 ✗ continue;
7009 3 buf_size = avio_get_dyn_buf(mov->mdat_buf, &buf);
7010 3 avio_write(s->pb, buf, buf_size);
7011 3 ffio_reset_dyn_buf(mov->mdat_buf);
7012 }
7013 }
7014
7015 111 mov->mdat_size = 0;
7016
7017 111 avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT);
7018 111 return 0;
7019 }
7020
7021 105 static int mov_auto_flush_fragment(AVFormatContext *s, int force)
7022 {
7023 105 MOVMuxContext *mov = s->priv_data;
7024 105 int had_moov = mov->moov_written;
7025 105 int ret = mov_flush_fragment(s, force);
7026
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 105 times.
105 if (ret < 0)
7027 ✗ return ret;
7028 // If using delay_moov, the first flush only wrote the moov,
7029 // not the actual moof+mdat pair, thus flush once again.
7030
4/4
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 90 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 5 times.
105 if (!had_moov && mov->flags & FF_MOV_FLAG_DELAY_MOOV)
7031 10 ret = mov_flush_fragment(s, force);
7032 105 return ret;
7033 }
7034
7035 54062 static int check_pkt(AVFormatContext *s, MOVTrack *trk, AVPacket *pkt)
7036 {
7037 int64_t ref;
7038 uint64_t duration;
7039
7040
2/2
✓ Branch 0 taken 52832 times.
✓ Branch 1 taken 1230 times.
54062 if (trk->entry) {
7041 52832 ref = trk->cluster[trk->entry - 1].dts;
7042
2/2
✓ Branch 0 taken 394 times.
✓ Branch 1 taken 836 times.
1230 } else if ( trk->start_dts != AV_NOPTS_VALUE
7043
2/2
✓ Branch 0 taken 386 times.
✓ Branch 1 taken 8 times.
394 && !trk->frag_discont) {
7044 386 ref = trk->start_dts + trk->track_duration;
7045 } else
7046 844 ref = pkt->dts; // Skip tests for the first packet
7047
7048
2/2
✓ Branch 0 taken 4055 times.
✓ Branch 1 taken 50007 times.
54062 if (trk->dts_shift != AV_NOPTS_VALUE) {
7049 /* With negative CTS offsets we have set an offset to the DTS,
7050 * reverse this for the check. */
7051 4055 ref -= trk->dts_shift;
7052 }
7053
7054 54062 duration = pkt->dts - ref;
7055
2/4
✓ Branch 0 taken 54062 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 54062 times.
54062 if (pkt->dts < ref || duration >= INT_MAX) {
7056 ✗ av_log(s, AV_LOG_WARNING, "Packet duration: %"PRId64" / dts: %"PRId64" in stream %d is out of range\n",
7057 duration, pkt->dts, pkt->stream_index);
7058
7059 ✗ pkt->dts = ref + 1;
7060 ✗ pkt->pts = AV_NOPTS_VALUE;
7061 }
7062
7063
2/4
✓ Branch 0 taken 54062 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 54062 times.
54062 if (pkt->duration < 0 || pkt->duration > INT_MAX) {
7064 ✗ av_log(s, AV_LOG_ERROR, "Application provided duration: %"PRId64" in stream %d is invalid\n", pkt->duration, pkt->stream_index);
7065 ✗ return AVERROR(EINVAL);
7066 }
7067 54062 return 0;
7068 }
7069
7070 7 int ff_mov_set_fragment_end_hint(AVFormatContext *s, int stream_index,
7071 const AVPacket *pkt, AVRational src_time_base)
7072 {
7073 7 MOVMuxContext *mov = s->priv_data;
7074 AVStream *st;
7075 MOVTrack *track;
7076 int64_t offset, dts, pts, candidate_duration;
7077
7078
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
7 if (!(mov->flags & FF_MOV_FLAG_FRAGMENT) ||
7079
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 stream_index < 0 || stream_index >= s->nb_streams ||
7080
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 pkt->dts == AV_NOPTS_VALUE)
7081 ✗ return 0;
7082
7083 7 st = s->streams[stream_index];
7084 7 track = st->priv_data;
7085
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
7 if (!track->entry || track->start_dts == AV_NOPTS_VALUE)
7086 ✗ return 0;
7087
7088
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (ff_get_muxer_ts_offset(s, stream_index, &offset) < 0)
7089 ✗ return 0;
7090
7091 7 dts = av_rescale_q(pkt->dts, src_time_base, st->time_base) + offset;
7092 14 pts = pkt->pts == AV_NOPTS_VALUE
7093 ? AV_NOPTS_VALUE
7094
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 : av_rescale_q(pkt->pts, src_time_base, st->time_base) + offset;
7095
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (track->dts_shift != AV_NOPTS_VALUE)
7096 ✗ dts += track->dts_shift;
7097
7098 7 candidate_duration = dts - track->start_dts;
7099
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
7 if (dts <= track->cluster[track->entry - 1].dts ||
7100
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 candidate_duration < 0 || candidate_duration >= track->track_duration)
7101 7 return 0;
7102
7103 ✗ track->track_duration = candidate_duration;
7104 ✗ track->end_pts = pts != AV_NOPTS_VALUE ? pts : dts;
7105 ✗ if (!(pkt->flags & AV_PKT_FLAG_DISCARD))
7106 ✗ track->elst_end_pts = track->end_pts;
7107 ✗ track->end_reliable = 1;
7108
7109 ✗ return 1;
7110 }
7111
7112 27049 int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
7113 {
7114 27049 MOVMuxContext *mov = s->priv_data;
7115 27049 AVIOContext *pb = s->pb;
7116 MOVTrack *trk;
7117 AVCodecParameters *par;
7118 AVProducerReferenceTime *prft;
7119 27049 unsigned int samples_in_chunk = 0;
7120 int64_t duration;
7121 27049 int size = pkt->size, ret = 0, offset = 0;
7122 size_t prft_size;
7123 27049 uint8_t *reformatted_data = NULL;
7124
7125
2/2
✓ Branch 0 taken 27003 times.
✓ Branch 1 taken 46 times.
27049 if (pkt->stream_index < s->nb_streams)
7126 27003 trk = s->streams[pkt->stream_index]->priv_data;
7127 else // Timecode or chapter
7128 46 trk = &mov->tracks[pkt->stream_index];
7129 27049 par = trk->par;
7130
7131 27049 ret = check_pkt(s, trk, pkt);
7132
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27049 times.
27049 if (ret < 0)
7133 ✗ return ret;
7134
7135
2/2
✓ Branch 0 taken 26428 times.
✓ Branch 1 taken 621 times.
27049 if (pkt->pts != AV_NOPTS_VALUE &&
7136
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26428 times.
26428 (uint64_t)pkt->dts - pkt->pts != (int32_t)((uint64_t)pkt->dts - pkt->pts)) {
7137 ✗ av_log(s, AV_LOG_WARNING, "pts/dts pair unsupported\n");
7138 ✗ return AVERROR_PATCHWELCOME;
7139 }
7140
7141
4/4
✓ Branch 0 taken 17626 times.
✓ Branch 1 taken 9423 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 17625 times.
27049 if (mov->flags & FF_MOV_FLAG_FRAGMENT || mov->mode == MODE_AVIF) {
7142 int ret;
7143
4/4
✓ Branch 0 taken 3577 times.
✓ Branch 1 taken 5847 times.
✓ Branch 2 taken 3338 times.
✓ Branch 3 taken 239 times.
9424 if (mov->moov_written || mov->flags & FF_MOV_FLAG_EMPTY_MOOV) {
7144
3/4
✓ Branch 0 taken 88 times.
✓ Branch 1 taken 9097 times.
✓ Branch 2 taken 88 times.
✗ Branch 3 not taken.
9185 if (mov->frag_interleave && mov->fragments > 0) {
7145
2/2
✓ Branch 0 taken 85 times.
✓ Branch 1 taken 3 times.
88 if (trk->entry - trk->entries_flushed >= mov->frag_interleave) {
7146
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 85 times.
85 if ((ret = mov_flush_fragment_interleaving(s, trk)) < 0)
7147 ✗ return ret;
7148 }
7149 }
7150
7151
2/2
✓ Branch 0 taken 178 times.
✓ Branch 1 taken 9007 times.
9185 if (!trk->mdat_buf) {
7152
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 178 times.
178 if ((ret = avio_open_dyn_buf(&trk->mdat_buf)) < 0)
7153 ✗ return ret;
7154 }
7155 9185 pb = trk->mdat_buf;
7156 } else {
7157
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 234 times.
239 if (!mov->mdat_buf) {
7158
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 if ((ret = avio_open_dyn_buf(&mov->mdat_buf)) < 0)
7159 ✗ return ret;
7160 }
7161 239 pb = mov->mdat_buf;
7162 }
7163 }
7164
7165
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27049 times.
27049 if (par->codec_id == AV_CODEC_ID_AMR_NB) {
7166 /* We must find out how many AMR blocks there are in one packet */
7167 static const uint16_t packed_size[16] =
7168 {13, 14, 16, 18, 20, 21, 27, 32, 6, 0, 0, 0, 0, 0, 0, 1};
7169 ✗ int len = 0;
7170
7171 ✗ while (len < size && samples_in_chunk < 100) {
7172 ✗ len += packed_size[(pkt->data[len] >> 3) & 0x0F];
7173 ✗ samples_in_chunk++;
7174 }
7175 ✗ if (samples_in_chunk > 1) {
7176 ✗ av_log(s, AV_LOG_ERROR, "fatal error, input is not a single packet, implement a AVParser for it\n");
7177 ✗ return -1;
7178 }
7179
1/2
✓ Branch 0 taken 27049 times.
✗ Branch 1 not taken.
27049 } else if (par->codec_id == AV_CODEC_ID_ADPCM_MS ||
7180
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27049 times.
27049 par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) {
7181 ✗ samples_in_chunk = trk->par->frame_size;
7182
2/2
✓ Branch 0 taken 1418 times.
✓ Branch 1 taken 25631 times.
27049 } else if (trk->sample_size)
7183 1418 samples_in_chunk = size / trk->sample_size;
7184 else
7185 25631 samples_in_chunk = 1;
7186
7187
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27049 times.
27049 if (samples_in_chunk < 1) {
7188 ✗ av_log(s, AV_LOG_ERROR, "fatal error, input packet contains no samples\n");
7189 ✗ return AVERROR_PATCHWELCOME;
7190 }
7191
7192 /* copy extradata if it exists */
7193
3/4
✓ Branch 0 taken 10217 times.
✓ Branch 1 taken 16832 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 10217 times.
27049 if (trk->extradata_size[0] == 0 && par->extradata_size > 0 &&
7194 ✗ !TAG_IS_AVCI(trk->tag) &&
7195 ✗ (par->codec_id != AV_CODEC_ID_DNXHD)) {
7196 ✗ trk->extradata[0] = av_memdup(par->extradata, par->extradata_size);
7197 ✗ if (!trk->extradata[0]) {
7198 ✗ ret = AVERROR(ENOMEM);
7199 ✗ goto err;
7200 }
7201 ✗ trk->extradata_size[0] = par->extradata_size;
7202 }
7203
7204
2/2
✓ Branch 0 taken 26934 times.
✓ Branch 1 taken 115 times.
27049 if ((par->codec_id == AV_CODEC_ID_DNXHD ||
7205
2/2
✓ Branch 0 taken 24260 times.
✓ Branch 1 taken 2674 times.
26934 par->codec_id == AV_CODEC_ID_H264 ||
7206
2/2
✓ Branch 0 taken 23888 times.
✓ Branch 1 taken 372 times.
24260 par->codec_id == AV_CODEC_ID_HEVC ||
7207
2/2
✓ Branch 0 taken 23878 times.
✓ Branch 1 taken 10 times.
23888 par->codec_id == AV_CODEC_ID_VVC ||
7208
1/2
✓ Branch 0 taken 23878 times.
✗ Branch 1 not taken.
23878 par->codec_id == AV_CODEC_ID_VP9 ||
7209
2/2
✓ Branch 0 taken 23578 times.
✓ Branch 1 taken 300 times.
23878 par->codec_id == AV_CODEC_ID_EVC ||
7210
2/2
✓ Branch 0 taken 23548 times.
✓ Branch 1 taken 30 times.
23578 par->codec_id == AV_CODEC_ID_LCEVC ||
7211
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 23548 times.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 3477 times.
27049 par->codec_id == AV_CODEC_ID_TRUEHD) && !trk->extradata_size[0] &&
7212
14/28
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 24 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 24 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 24 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 24 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 24 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 24 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 24 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 24 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 24 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 24 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 24 times.
✗ Branch 27 not taken.
24 !TAG_IS_AVCI(trk->tag)) {
7213 /* copy frame to create needed atoms */
7214 24 trk->extradata_size[0] = size;
7215 24 trk->extradata[0] = av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
7216
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (!trk->extradata[0]) {
7217 ✗ ret = AVERROR(ENOMEM);
7218 ✗ goto err;
7219 }
7220 24 memcpy(trk->extradata[0], pkt->data, size);
7221 24 memset(trk->extradata[0] + size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
7222 }
7223
7224 27049 const AVPacketSideData *sd = av_packet_side_data_get(pkt->side_data, pkt->side_data_elems, AV_PKT_DATA_NEW_EXTRADATA);
7225
4/6
✓ Branch 0 taken 27049 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 27046 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
27049 if (pkt->size && sd && sd->size > 0) {
7226 int i;
7227
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
5 for (i = 0; i < trk->stsd_count; i++) {
7228
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
3 if (trk->extradata_size[i] == sd->size && !memcmp(trk->extradata[i], sd->data, sd->size))
7229 1 break;
7230 }
7231
7232
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (i < trk->stsd_count)
7233 1 trk->last_stsd_index = i;
7234
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 else if (trk->stsd_count <= INT_MAX - 1) {
7235 2 int new_count = trk->stsd_count + 1;
7236 2 uint8_t **extradata = av_realloc_array(trk->extradata, new_count, sizeof(*trk->extradata));
7237
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!extradata)
7238 ✗ return AVERROR(ENOMEM);
7239 2 trk->extradata = extradata;
7240
7241 2 int *extradata_size = av_realloc_array(trk->extradata_size, new_count, sizeof(*trk->extradata_size));
7242
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!extradata_size)
7243 ✗ return AVERROR(ENOMEM);
7244 2 trk->extradata_size = extradata_size;
7245
7246 2 trk->extradata[trk->stsd_count] = av_memdup(sd->data, sd->size);
7247
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!trk->extradata[trk->stsd_count])
7248 ✗ return AVERROR(ENOMEM);
7249
7250 2 trk->extradata_size[trk->stsd_count] = sd->size;
7251 2 trk->last_stsd_index = trk->stsd_count;
7252 2 trk->stsd_count = new_count;
7253 } else
7254 ✗ return AVERROR(ENOMEM);
7255 }
7256
7257
3/4
✓ Branch 0 taken 9214 times.
✓ Branch 1 taken 17835 times.
✓ Branch 2 taken 9214 times.
✗ Branch 3 not taken.
27049 if (par->codec_id == AV_CODEC_ID_AAC && pkt->size > 2 &&
7258
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9214 times.
9214 (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) {
7259 ✗ if (!trk->st->nb_frames) {
7260 ✗ av_log(s, AV_LOG_ERROR, "Malformed AAC bitstream detected: "
7261 "use the audio bitstream filter 'aac_adtstoasc' to fix it "
7262 "('-bsf:a aac_adtstoasc' option with ffmpeg)\n");
7263 ✗ return -1;
7264 }
7265 ✗ av_log(s, AV_LOG_WARNING, "aac bitstream error\n");
7266 }
7267
3/4
✓ Branch 0 taken 2674 times.
✓ Branch 1 taken 24375 times.
✓ Branch 2 taken 2674 times.
✗ Branch 3 not taken.
27049 if (par->codec_id == AV_CODEC_ID_H264 && trk->extradata_size[trk->last_stsd_index] > 0 &&
7268
16/30
✓ Branch 0 taken 545 times.
✓ Branch 1 taken 2129 times.
✓ Branch 2 taken 545 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 545 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 545 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 545 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 545 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 545 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 545 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 545 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 545 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 545 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 545 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 545 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 545 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 545 times.
✗ Branch 29 not taken.
2674 *(uint8_t *)trk->extradata[trk->last_stsd_index] != 1 && !TAG_IS_AVCI(trk->tag)) {
7269 /* from x264 or from bytestream H.264 */
7270 /* NAL reformatting needed */
7271
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 545 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
545 if (trk->hint_track >= 0 && trk->hint_track < mov->nb_tracks) {
7272 ✗ ret = ff_nal_parse_units_buf(pkt->data, &reformatted_data,
7273 &size);
7274 ✗ if (ret < 0)
7275 ✗ return ret;
7276 ✗ avio_write(pb, reformatted_data, size);
7277 } else {
7278
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 528 times.
545 if (trk->cenc.aes_ctr) {
7279 17 size = ff_mov_cenc_avc_parse_nal_units(&trk->cenc, pb, pkt->data, size);
7280
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if (size < 0) {
7281 ✗ ret = size;
7282 ✗ goto err;
7283 }
7284 } else {
7285 528 size = ff_nal_parse_units(pb, pkt->data, pkt->size);
7286 }
7287 }
7288
3/4
✓ Branch 0 taken 372 times.
✓ Branch 1 taken 26132 times.
✓ Branch 2 taken 372 times.
✗ Branch 3 not taken.
26504 } else if (par->codec_id == AV_CODEC_ID_HEVC && trk->extradata_size[trk->last_stsd_index] > 6 &&
7289
3/4
✓ Branch 0 taken 372 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 355 times.
✓ Branch 3 taken 17 times.
727 (AV_RB24(trk->extradata[trk->last_stsd_index]) == 1 || AV_RB32(trk->extradata[trk->last_stsd_index]) == 1)) {
7290 /* extradata is Annex B, assume the bitstream is too and convert it */
7291 355 int filter_ps = (trk->tag == MKTAG('h','v','c','1'));
7292
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 355 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
355 if (trk->hint_track >= 0 && trk->hint_track < mov->nb_tracks) {
7293 ✗ ret = ff_hevc_annexb2mp4_buf(pkt->data, &reformatted_data,
7294 &size, filter_ps, NULL);
7295 ✗ if (ret < 0)
7296 ✗ return ret;
7297 ✗ avio_write(pb, reformatted_data, size);
7298 } else {
7299
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 354 times.
355 if (trk->cenc.aes_ctr) {
7300 1 size = ff_mov_cenc_avc_parse_nal_units(&trk->cenc, pb, pkt->data, size);
7301
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size < 0) {
7302 ✗ ret = size;
7303 ✗ goto err;
7304 }
7305 } else {
7306 354 size = ff_hevc_annexb2mp4(pb, pkt->data, pkt->size, filter_ps, NULL);
7307 }
7308 }
7309
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 26139 times.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
26149 } else if (par->codec_id == AV_CODEC_ID_VVC && trk->extradata_size[trk->last_stsd_index] > 6 &&
7310
2/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
10 (AV_RB24(trk->extradata[trk->last_stsd_index]) == 1 || AV_RB32(trk->extradata[trk->last_stsd_index]) == 1)) {
7311 /* extradata is Annex B, assume the bitstream is too and convert it */
7312
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
10 if (trk->hint_track >= 0 && trk->hint_track < mov->nb_tracks) {
7313 ✗ ret = ff_vvc_annexb2mp4_buf(pkt->data, &reformatted_data,
7314 &size, 0, NULL);
7315 ✗ if (ret < 0)
7316 ✗ return ret;
7317 ✗ avio_write(pb, reformatted_data, size);
7318 } else {
7319 10 size = ff_vvc_annexb2mp4(pb, pkt->data, pkt->size, 0, NULL);
7320 }
7321
3/4
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 26109 times.
✓ Branch 2 taken 30 times.
✗ Branch 3 not taken.
26139 } else if (par->codec_id == AV_CODEC_ID_LCEVC && trk->extradata_size[trk->last_stsd_index] > 0 &&
7322
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 *(uint8_t *)trk->extradata[trk->last_stsd_index] != 1) {
7323 /* extradata is Annex B, assume the bitstream is too and convert it */
7324
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
30 if (trk->hint_track >= 0 && trk->hint_track < mov->nb_tracks) {
7325 ✗ ret = ff_nal_parse_units_buf(pkt->data, &reformatted_data, &size);
7326 ✗ if (ret < 0)
7327 ✗ return ret;
7328 ✗ avio_write(pb, reformatted_data, size);
7329 } else {
7330
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (trk->cenc.aes_ctr) {
7331 ✗ size = ff_mov_cenc_avc_parse_nal_units(&trk->cenc, pb, pkt->data, size);
7332 ✗ if (size < 0) {
7333 ✗ ret = size;
7334 ✗ goto err;
7335 }
7336 } else {
7337 30 size = ff_nal_parse_units(pb, pkt->data, pkt->size);
7338 }
7339 }
7340
4/4
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 26080 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 24 times.
26109 } else if (par->codec_id == AV_CODEC_ID_AV1 && !trk->cenc.aes_ctr) {
7341
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
5 if (trk->hint_track >= 0 && trk->hint_track < mov->nb_tracks) {
7342 ✗ ret = ff_av1_filter_obus_buf(pkt->data, &reformatted_data,
7343 &size, &offset);
7344 ✗ if (ret < 0)
7345 ✗ return ret;
7346 ✗ avio_write(pb, reformatted_data, size);
7347 } else {
7348 5 size = ff_av1_filter_obus(pb, pkt->data, pkt->size);
7349
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
5 if (trk->mode == MODE_AVIF && !mov->avif_extent_length[pkt->stream_index]) {
7350 1 mov->avif_extent_length[pkt->stream_index] = size;
7351 }
7352 }
7353
7354
2/2
✓ Branch 0 taken 25481 times.
✓ Branch 1 taken 623 times.
26104 } else if (par->codec_id == AV_CODEC_ID_AC3 ||
7355
2/2
✓ Branch 0 taken 1114 times.
✓ Branch 1 taken 24367 times.
25481 par->codec_id == AV_CODEC_ID_EAC3) {
7356 1737 size = handle_eac3(mov, pkt, trk);
7357
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1737 times.
1737 if (size < 0)
7358 ✗ return size;
7359
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1736 times.
1737 else if (!size)
7360 1 goto end;
7361 1736 avio_write(pb, pkt->data, size);
7362
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24367 times.
24367 } else if (par->codec_id == AV_CODEC_ID_EIA_608) {
7363 ✗ size = 8;
7364
7365 ✗ for (int i = 0; i < pkt->size; i += 3) {
7366 ✗ if (pkt->data[i] == 0xFC) {
7367 ✗ size += 2;
7368 }
7369 }
7370 ✗ avio_wb32(pb, size);
7371 ✗ ffio_wfourcc(pb, "cdat");
7372 ✗ for (int i = 0; i < pkt->size; i += 3) {
7373 ✗ if (pkt->data[i] == 0xFC) {
7374 ✗ avio_w8(pb, pkt->data[i + 1]);
7375 ✗ avio_w8(pb, pkt->data[i + 2]);
7376 }
7377 }
7378
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 24364 times.
24367 } else if (par->codec_id == AV_CODEC_ID_APV) {
7379 3 ff_isom_parse_apvc(trk->apv, pkt, s);
7380 3 avio_wb32(s->pb, pkt->size);
7381 3 size += 4;
7382
7383 3 avio_write(s->pb, pkt->data, pkt->size);
7384 } else {
7385
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 24331 times.
24364 if (trk->cenc.aes_ctr) {
7386 33 uint8_t *extradata = trk->extradata[trk->last_stsd_index];
7387 33 int extradata_size = trk->extradata_size[trk->last_stsd_index];
7388
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
38 if (par->codec_id == AV_CODEC_ID_H264 && extradata_size > 4) {
7389 5 int nal_size_length = (extradata[4] & 0x3) + 1;
7390 5 ret = ff_mov_cenc_avc_write_nal_units(s, &trk->cenc, nal_size_length, pb, pkt->data, size);
7391
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
32 } else if(par->codec_id == AV_CODEC_ID_HEVC && extradata_size > 21) {
7392 4 int nal_size_length = (extradata[21] & 0x3) + 1;
7393 4 ret = ff_mov_cenc_avc_write_nal_units(s, &trk->cenc, nal_size_length, pb, pkt->data, size);
7394
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 } else if(par->codec_id == AV_CODEC_ID_VVC) {
7395 ✗ ret = AVERROR_PATCHWELCOME;
7396
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 } else if(par->codec_id == AV_CODEC_ID_AV1) {
7397
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 av_assert0(size == pkt->size);
7398 24 ret = ff_mov_cenc_av1_write_obus(s, &trk->cenc, pb, pkt);
7399
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 if (ret > 0) {
7400 24 size = ret;
7401 24 ret = 0;
7402 }
7403 } else {
7404 ✗ ret = ff_mov_cenc_write_packet(&trk->cenc, pb, pkt->data, size);
7405 }
7406
7407
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 if (ret) {
7408 ✗ goto err;
7409 }
7410 } else {
7411 24331 avio_write(pb, pkt->data, size);
7412 }
7413 }
7414
7415
2/2
✓ Branch 0 taken 429 times.
✓ Branch 1 taken 26619 times.
27048 if (trk->entry >= trk->cluster_capacity) {
7416 429 unsigned new_capacity = trk->entry + MOV_INDEX_CLUSTER_SIZE;
7417 429 void *cluster = av_realloc_array(trk->cluster, new_capacity, sizeof(*trk->cluster));
7418
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 429 times.
429 if (!cluster) {
7419 ✗ ret = AVERROR(ENOMEM);
7420 ✗ goto err;
7421 }
7422 429 trk->cluster = cluster;
7423 429 trk->cluster_capacity = new_capacity;
7424 }
7425
7426 27048 trk->cluster[trk->entry].pos = avio_tell(pb) - size;
7427 27048 trk->cluster[trk->entry].stsd_index = trk->last_stsd_index;
7428 27048 trk->cluster[trk->entry].samples_in_chunk = samples_in_chunk;
7429 27048 trk->cluster[trk->entry].chunkNum = 0;
7430 27048 trk->cluster[trk->entry].size = size;
7431 27048 trk->cluster[trk->entry].entries = samples_in_chunk;
7432 27048 trk->cluster[trk->entry].dts = pkt->dts;
7433 27048 trk->cluster[trk->entry].pts = pkt->pts;
7434
2/2
✓ Branch 0 taken 27020 times.
✓ Branch 1 taken 28 times.
27048 if (!trk->squash_fragment_samples_to_one &&
7435
4/4
✓ Branch 0 taken 616 times.
✓ Branch 1 taken 26404 times.
✓ Branch 2 taken 205 times.
✓ Branch 3 taken 411 times.
27020 !trk->entry && trk->start_dts != AV_NOPTS_VALUE) {
7436
2/2
✓ Branch 0 taken 201 times.
✓ Branch 1 taken 4 times.
205 if (!trk->frag_discont) {
7437 /* First packet of a new fragment. We already wrote the duration
7438 * of the last packet of the previous fragment based on track_duration,
7439 * which might not exactly match our dts. Therefore adjust the dts
7440 * of this packet to be what the previous packets duration implies. */
7441 201 trk->cluster[trk->entry].dts = trk->start_dts + trk->track_duration;
7442 /* We also may have written the pts and the corresponding duration
7443 * in sidx/tfrf/tfxd tags; make sure the sidx pts and duration match up with
7444 * the next fragment. This means the cts of the first sample must
7445 * be the same in all fragments, unless end_pts was updated by
7446 * the packet causing the fragment to be written. */
7447
2/2
✓ Branch 0 taken 117 times.
✓ Branch 1 taken 84 times.
201 if ((mov->flags & FF_MOV_FLAG_DASH &&
7448
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 116 times.
117 !(mov->flags & (FF_MOV_FLAG_GLOBAL_SIDX | FF_MOV_FLAG_SKIP_SIDX))) ||
7449
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 63 times.
85 mov->mode == MODE_ISM)
7450 138 pkt->pts = pkt->dts + trk->end_pts - trk->cluster[trk->entry].dts;
7451 } else {
7452 /* New fragment, but discontinuous from previous fragments.
7453 * Pretend the duration sum of the earlier fragments is
7454 * pkt->dts - trk->start_dts. */
7455 4 trk->end_pts = trk->elst_end_pts = AV_NOPTS_VALUE;
7456 4 trk->frag_discont = 0;
7457 }
7458 }
7459
7460
6/6
✓ Branch 0 taken 644 times.
✓ Branch 1 taken 26404 times.
✓ Branch 2 taken 415 times.
✓ Branch 3 taken 229 times.
✓ Branch 4 taken 43 times.
✓ Branch 5 taken 372 times.
27048 if (!trk->entry && trk->start_dts == AV_NOPTS_VALUE && !mov->use_editlist &&
7461
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 15 times.
43 s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO) {
7462 /* Not using edit lists and shifting the first track to start from zero.
7463 * If the other streams start from a later timestamp, we won't be able
7464 * to signal the difference in starting time without an edit list.
7465 * Thus move the timestamp for this first sample to 0, increasing
7466 * its duration instead. */
7467 28 trk->cluster[trk->entry].dts = trk->start_dts = 0;
7468 }
7469
2/2
✓ Branch 0 taken 387 times.
✓ Branch 1 taken 26661 times.
27048 if (trk->start_dts == AV_NOPTS_VALUE) {
7470 387 trk->start_dts = pkt->dts;
7471
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 381 times.
387 if (trk->frag_discont) {
7472
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 if (mov->use_editlist) {
7473 /* Pretend the whole stream started at pts=0, with earlier fragments
7474 * already written. If the stream started at pts=0, the duration sum
7475 * of earlier fragments would have been pkt->pts. */
7476 4 trk->start_dts = pkt->dts - pkt->pts;
7477 } else {
7478 /* Pretend the whole stream started at dts=0, with earlier fragments
7479 * already written, with a duration summing up to pkt->dts. */
7480 2 trk->start_dts = 0;
7481 }
7482 6 trk->frag_discont = 0;
7483
4/4
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 322 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 57 times.
381 } else if (pkt->dts && mov->moov_written)
7484 2 av_log(s, AV_LOG_WARNING,
7485 "Track %d starts with a nonzero dts %"PRId64", while the moov "
7486 "already has been written. Set the delay_moov flag to handle "
7487 "this case.\n",
7488 pkt->stream_index, pkt->dts);
7489 }
7490
7491 27048 sd = av_packet_side_data_get(pkt->side_data, pkt->side_data_elems, AV_PKT_DATA_SKIP_SAMPLES);
7492
5/6
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 26999 times.
✓ Branch 2 taken 49 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 48 times.
✓ Branch 5 taken 1 times.
27096 if (sd && sd->size >= 10 && trk->par->frame_size) {
7493
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 27 times.
48 duration = FFMAX(av_rescale_q(trk->par->frame_size, (AVRational){ 1, trk->par->sample_rate },
7494 trk->st->time_base), pkt->duration);
7495
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 if (mov->use_editlist)
7496 48 pkt->duration = duration;
7497 48 duration -= av_rescale_q(AV_RL32(sd->data + 4), (AVRational){ 1, trk->par->sample_rate },
7498 48 trk->st->time_base);
7499
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (duration < 0)
7500 ✗ return AVERROR_INVALIDDATA;
7501 } else
7502 27000 duration = pkt->duration;
7503
7504 27048 trk->track_duration = pkt->dts - trk->start_dts + pkt->duration;
7505 27048 trk->last_sample_is_subtitle_end = 0;
7506
7507
2/2
✓ Branch 0 taken 621 times.
✓ Branch 1 taken 26427 times.
27048 if (pkt->pts == AV_NOPTS_VALUE) {
7508 621 av_log(s, AV_LOG_WARNING, "pts has no value\n");
7509 621 pkt->pts = pkt->dts;
7510 }
7511
2/2
✓ Branch 0 taken 1449 times.
✓ Branch 1 taken 25599 times.
27048 if (pkt->dts != pkt->pts)
7512 1449 trk->flags |= MOV_TRACK_CTTS;
7513 27048 trk->cluster[trk->entry].cts = pkt->pts - pkt->dts;
7514 27048 trk->cluster[trk->entry].flags = 0;
7515
6/6
✓ Branch 0 taken 26633 times.
✓ Branch 1 taken 415 times.
✓ Branch 2 taken 78 times.
✓ Branch 3 taken 26555 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 73 times.
27048 if (trk->start_cts == AV_NOPTS_VALUE || (pkt->dts <= 0 && trk->start_cts > pkt->pts - pkt->dts))
7516 420 trk->start_cts = pkt->pts - pkt->dts;
7517
2/2
✓ Branch 0 taken 419 times.
✓ Branch 1 taken 26629 times.
27048 if (trk->end_pts == AV_NOPTS_VALUE)
7518 419 trk->end_pts = trk->cluster[trk->entry].dts +
7519 419 trk->cluster[trk->entry].cts + duration;
7520 else
7521 26629 trk->end_pts = FFMAX(trk->end_pts, trk->cluster[trk->entry].dts +
7522 trk->cluster[trk->entry].cts +
7523 duration);
7524
2/2
✓ Branch 0 taken 27045 times.
✓ Branch 1 taken 3 times.
27048 if (!(pkt->flags & AV_PKT_FLAG_DISCARD))
7525 27045 trk->elst_end_pts = trk->end_pts;
7526
7527
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27048 times.
27048 if (par->codec_id == AV_CODEC_ID_VC1) {
7528 ✗ mov_parse_vc1_frame(pkt, trk);
7529
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27048 times.
27048 } else if (par->codec_id == AV_CODEC_ID_TRUEHD) {
7530 ✗ mov_parse_truehd_frame(pkt, trk);
7531
2/2
✓ Branch 0 taken 20902 times.
✓ Branch 1 taken 6146 times.
27048 } else if (pkt->flags & AV_PKT_FLAG_KEY) {
7532
4/4
✓ Branch 0 taken 6479 times.
✓ Branch 1 taken 14423 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 6470 times.
20902 if (mov->mode == MODE_MOV && par->codec_id == AV_CODEC_ID_MPEG2VIDEO &&
7533
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
9 trk->entry > 0) { // force sync sample for the first key frame
7534 8 mov_parse_mpeg2_frame(pkt, &trk->cluster[trk->entry].flags);
7535
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (trk->cluster[trk->entry].flags & MOV_PARTIAL_SYNC_SAMPLE)
7536 ✗ trk->flags |= MOV_TRACK_STPS;
7537 } else {
7538 20894 trk->cluster[trk->entry].flags = MOV_SYNC_SAMPLE;
7539 }
7540
1/2
✓ Branch 0 taken 20902 times.
✗ Branch 1 not taken.
20902 if (trk->cluster[trk->entry].flags & MOV_SYNC_SAMPLE)
7541 20902 trk->has_keyframes++;
7542 }
7543
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 27041 times.
27048 if (pkt->flags & AV_PKT_FLAG_DISPOSABLE) {
7544 7 trk->cluster[trk->entry].flags |= MOV_DISPOSABLE_SAMPLE;
7545 7 trk->has_disposable++;
7546 }
7547
7548 27048 prft = (AVProducerReferenceTime *)av_packet_get_side_data(pkt, AV_PKT_DATA_PRFT, &prft_size);
7549
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 27048 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
27048 if (prft && prft_size == sizeof(AVProducerReferenceTime))
7550 ✗ memcpy(&trk->cluster[trk->entry].prft, prft, prft_size);
7551 else
7552 27048 memset(&trk->cluster[trk->entry].prft, 0, sizeof(AVProducerReferenceTime));
7553
7554 27048 trk->entry++;
7555 27048 trk->sample_count += samples_in_chunk;
7556 27048 mov->mdat_size += size;
7557
7558
3/4
✓ Branch 0 taken 26966 times.
✓ Branch 1 taken 82 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 82 times.
27048 if (trk->hint_track >= 0 && trk->hint_track < mov->nb_tracks)
7559 82 ff_mov_add_hinted_packet(s, pkt, trk->hint_track, trk->entry,
7560
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 82 times.
82 reformatted_data ? reformatted_data + offset
7561 : NULL, size);
7562
7563 27049 end:
7564 27049 err:
7565
7566
1/2
✓ Branch 0 taken 27049 times.
✗ Branch 1 not taken.
27049 if (pkt->data != reformatted_data)
7567 27049 av_free(reformatted_data);
7568 27049 return ret;
7569 }
7570
7571 27013 static int mov_write_single_packet(AVFormatContext *s, AVPacket *pkt)
7572 {
7573 27013 MOVMuxContext *mov = s->priv_data;
7574 27013 MOVTrack *trk = s->streams[pkt->stream_index]->priv_data;
7575 27013 AVCodecParameters *par = trk->par;
7576 27013 int64_t frag_duration = 0;
7577 27013 int size = pkt->size;
7578
7579 27013 int ret = check_pkt(s, trk, pkt);
7580
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27013 times.
27013 if (ret < 0)
7581 ✗ return ret;
7582
7583
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 27008 times.
27013 if (mov->flags & FF_MOV_FLAG_FRAG_DISCONT) {
7584
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 5 times.
15 for (int i = 0; i < mov->nb_streams; i++)
7585 10 mov->tracks[i].frag_discont = 1;
7586 5 mov->flags &= ~FF_MOV_FLAG_FRAG_DISCONT;
7587 }
7588
7589
2/2
✓ Branch 0 taken 2012 times.
✓ Branch 1 taken 25001 times.
27013 if (mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS) {
7590
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 1997 times.
2012 if (trk->dts_shift == AV_NOPTS_VALUE)
7591 15 trk->dts_shift = pkt->pts - pkt->dts;
7592 2012 pkt->dts += trk->dts_shift;
7593 }
7594
7595
1/2
✓ Branch 0 taken 27013 times.
✗ Branch 1 not taken.
27013 if (trk->par->codec_id == AV_CODEC_ID_MP4ALS ||
7596
2/2
✓ Branch 0 taken 17797 times.
✓ Branch 1 taken 9216 times.
27013 trk->par->codec_id == AV_CODEC_ID_AAC ||
7597
2/2
✓ Branch 0 taken 17768 times.
✓ Branch 1 taken 29 times.
17797 trk->par->codec_id == AV_CODEC_ID_AV1 ||
7598
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 17696 times.
17768 trk->par->codec_id == AV_CODEC_ID_FLAC) {
7599 size_t side_size;
7600 9317 uint8_t *side = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size);
7601 /* Overwrite extradata only on flush packets or when no extradata was available during init */
7602
5/6
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 9310 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
9317 if (side_size > 0 && (!pkt->size || !trk->extradata_size[trk->last_stsd_index])) {
7603 7 void *newextra = av_malloc(side_size + AV_INPUT_BUFFER_PADDING_SIZE);
7604
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!newextra)
7605 ✗ return AVERROR(ENOMEM);
7606 7 memset((uint8_t*)newextra + side_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
7607 7 memcpy(newextra, side, side_size);
7608 7 av_free(trk->extradata[trk->last_stsd_index]);
7609 7 trk->extradata[trk->last_stsd_index] = newextra;
7610 7 trk->extradata_size[trk->last_stsd_index] = side_size;
7611 }
7612 }
7613
7614
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 27003 times.
27013 if (!pkt->size) {
7615
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
10 if (trk->start_dts == AV_NOPTS_VALUE && trk->frag_discont) {
7616 4 trk->start_dts = pkt->dts;
7617
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (pkt->pts != AV_NOPTS_VALUE)
7618 4 trk->start_cts = pkt->pts - pkt->dts;
7619 else
7620 ✗ trk->start_cts = 0;
7621 }
7622
7623 10 return 0; /* Discard 0 sized packets */
7624 }
7625
7626
4/4
✓ Branch 0 taken 26422 times.
✓ Branch 1 taken 581 times.
✓ Branch 2 taken 26398 times.
✓ Branch 3 taken 24 times.
27003 if (trk->entry && pkt->stream_index < mov->nb_streams)
7627 26398 frag_duration = av_rescale_q(pkt->dts - trk->cluster[0].dts,
7628 26398 s->streams[pkt->stream_index]->time_base,
7629 26398 AV_TIME_BASE_Q);
7630
2/2
✓ Branch 0 taken 261 times.
✓ Branch 1 taken 26742 times.
27003 if ((mov->max_fragment_duration &&
7631
2/2
✓ Branch 0 taken 257 times.
✓ Branch 1 taken 4 times.
261 frag_duration >= mov->max_fragment_duration) ||
7632
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 26999 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
26999 (mov->max_fragment_size && mov->mdat_size + size >= mov->max_fragment_size) ||
7633
2/2
✓ Branch 0 taken 4899 times.
✓ Branch 1 taken 22100 times.
26999 (mov->flags & FF_MOV_FLAG_FRAG_KEYFRAME &&
7634
2/2
✓ Branch 0 taken 2321 times.
✓ Branch 1 taken 2578 times.
4899 par->codec_type == AVMEDIA_TYPE_VIDEO &&
7635
4/4
✓ Branch 0 taken 2293 times.
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 2242 times.
✓ Branch 3 taken 51 times.
2321 trk->entry && pkt->flags & AV_PKT_FLAG_KEY) ||
7636
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 26946 times.
26948 (mov->flags & FF_MOV_FLAG_FRAG_EVERY_FRAME)) {
7637
1/2
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
57 if (frag_duration >= mov->min_fragment_duration) {
7638
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 1 times.
57 if (trk->entry) {
7639 // Set the duration of this track to line up with the next
7640 // sample in this track. This avoids relying on AVPacket
7641 // duration, but only helps for this particular track, not
7642 // for the other ones that are flushed at the same time.
7643 //
7644 // If we have trk->entry == 0, no fragment will be written
7645 // for this track, and we can't adjust the track end here.
7646 56 trk->track_duration = pkt->dts - trk->start_dts;
7647
1/2
✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
56 if (pkt->pts != AV_NOPTS_VALUE)
7648 56 trk->end_pts = pkt->pts;
7649 else
7650 ✗ trk->end_pts = pkt->dts;
7651
1/2
✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
56 if (!(pkt->flags & AV_PKT_FLAG_DISCARD))
7652 56 trk->elst_end_pts = trk->end_pts;
7653 56 trk->end_reliable = 1;
7654 }
7655 57 mov_auto_flush_fragment(s, 0);
7656 }
7657 }
7658
7659 27003 return ff_mov_write_packet(s, pkt);
7660 }
7661
7662 3 static int mov_write_subtitle_end_packet(AVFormatContext *s,
7663 int stream_index,
7664 int64_t dts) {
7665 3 MOVMuxContext *mov = s->priv_data;
7666 3 AVPacket *end = mov->pkt;
7667 3 uint8_t data[2] = {0};
7668 int ret;
7669
7670 3 end->size = sizeof(data);
7671 3 end->data = data;
7672 3 end->pts = dts;
7673 3 end->dts = dts;
7674 3 end->duration = 0;
7675 3 end->stream_index = stream_index;
7676
7677 3 ret = mov_write_single_packet(s, end);
7678 3 av_packet_unref(end);
7679
7680 3 return ret;
7681 }
7682
7683 #if CONFIG_IAMFENC
7684 324 static int mov_build_iamf_packet(AVFormatContext *s, MOVTrack *trk, AVPacket *pkt)
7685 {
7686 uint8_t *data;
7687 int ret;
7688
7689
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 252 times.
324 if (pkt->stream_index == trk->first_iamf_idx) {
7690 72 ret = ff_iamf_write_parameter_blocks(trk->iamf, trk->iamf_buf, pkt, s);
7691
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (ret < 0)
7692 ✗ return ret;
7693 }
7694
7695 324 ret = ff_iamf_write_audio_frame(trk->iamf, trk->iamf_buf,
7696 324 s->streams[pkt->stream_index]->id, pkt);
7697
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 324 times.
324 if (ret < 0)
7698 ✗ return ret;
7699
7700
2/2
✓ Branch 0 taken 252 times.
✓ Branch 1 taken 72 times.
324 if (pkt->stream_index != trk->last_iamf_idx)
7701 252 return AVERROR(EAGAIN);
7702
7703 72 ret = avio_close_dyn_buf(trk->iamf_buf, &data);
7704 72 trk->iamf_buf = NULL;
7705
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 66 times.
72 if (!ret) {
7706
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (pkt->size) {
7707 // Either all or none of the packets for a single
7708 // IA Sample may be empty.
7709 ✗ av_log(s, AV_LOG_ERROR, "Unexpected packet from "
7710 "stream #%d\n", pkt->stream_index);
7711 ✗ ret = AVERROR_INVALIDDATA;
7712 }
7713 6 av_free(data);
7714 6 return ret;
7715 }
7716
7717 66 av_buffer_unref(&pkt->buf);
7718 66 pkt->buf = av_buffer_create(data, ret, NULL, NULL, 0);
7719
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (!pkt->buf) {
7720 ✗ av_free(data);
7721 ✗ return AVERROR(ENOMEM);
7722 }
7723 66 pkt->data = data;
7724 66 pkt->size = ret;
7725 66 pkt->stream_index = trk->first_iamf_idx;
7726
7727 66 return avio_open_dyn_buf(&trk->iamf_buf);
7728 }
7729 #endif
7730
7731 2 static int mov_write_emsg_tag(AVIOContext *pb, AVStream *st, AVPacket *pkt)
7732 {
7733 2 int64_t pos = avio_tell(pb);
7734 2 const char *scheme_id_uri = "https://aomedia.org/emsg/ID3";
7735 2 const char *value = "";
7736
7737
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 av_assert0(st->time_base.num == 1);
7738
7739 2 avio_write_marker(pb,
7740 2 av_rescale_q(pkt->pts, st->time_base, AV_TIME_BASE_Q),
7741 AVIO_DATA_MARKER_BOUNDARY_POINT);
7742
7743 2 avio_wb32(pb, 0); /* size */
7744 2 ffio_wfourcc(pb, "emsg");
7745 2 avio_w8(pb, 1); /* version */
7746 2 avio_wb24(pb, 0);
7747 2 avio_wb32(pb, st->time_base.den); /* timescale */
7748 2 avio_wb64(pb, pkt->pts); /* presentation_time */
7749 2 avio_wb32(pb, 0xFFFFFFFFU); /* event_duration */
7750 2 avio_wb32(pb, 0); /* id */
7751 /* null terminated UTF8 strings */
7752 2 avio_write(pb, scheme_id_uri, strlen(scheme_id_uri) + 1);
7753 2 avio_write(pb, value, strlen(value) + 1);
7754 2 avio_write(pb, pkt->data, pkt->size);
7755
7756 2 return update_size(pb, pos);
7757 }
7758
7759 27433 static int mov_write_packet(AVFormatContext *s, AVPacket *pkt)
7760 {
7761 27433 MOVMuxContext *mov = s->priv_data;
7762 MOVTrack *trk;
7763
7764
2/2
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 27386 times.
27433 if (!pkt) {
7765 47 mov_flush_fragment(s, 1);
7766 47 return 1;
7767 }
7768
7769
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 27384 times.
27386 if (s->streams[pkt->stream_index]->codecpar->codec_id == AV_CODEC_ID_TIMED_ID3) {
7770 2 mov_write_emsg_tag(s->pb, s->streams[pkt->stream_index], pkt);
7771 2 return 0;
7772 }
7773
7774 27384 trk = s->streams[pkt->stream_index]->priv_data;
7775
7776 #if CONFIG_IAMFENC
7777
2/2
✓ Branch 0 taken 324 times.
✓ Branch 1 taken 27060 times.
27384 if (trk->iamf) {
7778 324 int ret = mov_build_iamf_packet(s, trk, pkt);
7779
2/2
✓ Branch 0 taken 252 times.
✓ Branch 1 taken 72 times.
324 if (ret < 0) {
7780
1/2
✓ Branch 0 taken 252 times.
✗ Branch 1 not taken.
252 if (ret == AVERROR(EAGAIN))
7781 252 return 0;
7782 ✗ av_log(s, AV_LOG_ERROR, "Error assembling an IAMF packet "
7783 ✗ "for stream #%d\n", trk->st->index);
7784 ✗ return ret;
7785 }
7786 }
7787 #endif
7788
7789
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 27130 times.
27132 if (is_cover_image(trk->st)) {
7790 int ret;
7791
7792
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (trk->st->nb_frames >= 1) {
7793 ✗ if (trk->st->nb_frames == 1)
7794 ✗ av_log(s, AV_LOG_WARNING, "Got more than one picture in stream %d,"
7795 ✗ " ignoring.\n", pkt->stream_index);
7796 ✗ return 0;
7797 }
7798
7799
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if ((ret = av_packet_ref(trk->cover_image, pkt)) < 0)
7800 ✗ return ret;
7801
7802 2 return 0;
7803 } else {
7804 int i;
7805
7806
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 27120 times.
27130 if (!pkt->size)
7807 10 return mov_write_single_packet(s, pkt); /* Passthrough. */
7808
7809 /*
7810 * Subtitles require special handling.
7811 *
7812 * 1) For full compliance, every track must have a sample at
7813 * dts == 0, which is rarely true for subtitles. So, as soon
7814 * as we see any packet with dts > 0, write an empty subtitle
7815 * at dts == 0 for any subtitle track with no samples in it.
7816 *
7817 * 2) For each subtitle track, check if the current packet's
7818 * dts is past the duration of the last subtitle sample. If
7819 * so, we now need to write an end sample for that subtitle.
7820 *
7821 * This must be done conditionally to allow for subtitles that
7822 * immediately replace each other, in which case an end sample
7823 * is not needed, and is, in fact, actively harmful.
7824 *
7825 * 3) See mov_write_trailer for how the final end sample is
7826 * handled.
7827 */
7828
2/2
✓ Branch 0 taken 320580 times.
✓ Branch 1 taken 27120 times.
347700 for (i = 0; i < mov->nb_tracks; i++) {
7829 320580 MOVTrack *trk = &mov->tracks[i];
7830 int ret;
7831
7832
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 320577 times.
320580 if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT &&
7833
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 trk->track_duration < pkt->dts &&
7834
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 (trk->entry == 0 || !trk->last_sample_is_subtitle_end)) {
7835 2 ret = mov_write_subtitle_end_packet(s, i, trk->track_duration);
7836
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0) return ret;
7837 2 trk->last_sample_is_subtitle_end = 1;
7838 }
7839 }
7840
7841
2/2
✓ Branch 0 taken 148 times.
✓ Branch 1 taken 26972 times.
27120 if (trk->squash_fragment_samples_to_one) {
7842 /*
7843 * If the track has to have its samples squashed into one sample,
7844 * we just take it into the track's queue.
7845 * This will then be utilized as the samples get written in either
7846 * mov_flush_fragment or when the mux is finalized in
7847 * mov_write_trailer.
7848 */
7849 148 int ret = AVERROR_BUG;
7850
7851
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 148 times.
148 if (pkt->pts == AV_NOPTS_VALUE) {
7852 ✗ av_log(s, AV_LOG_ERROR,
7853 "Packets without a valid presentation timestamp are "
7854 "not supported with packet squashing!\n");
7855 ✗ return AVERROR(EINVAL);
7856 }
7857
7858 /* The following will reset pkt and is only allowed to be used
7859 * because we return immediately. afterwards. */
7860
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 148 times.
148 if ((ret = ff_packet_list_put(&trk->squashed_packet_queue,
7861 pkt, NULL, 0)) < 0) {
7862 ✗ return ret;
7863 }
7864
7865 148 return 0;
7866 }
7867
7868
7869
4/4
✓ Branch 0 taken 8179 times.
✓ Branch 1 taken 18793 times.
✓ Branch 2 taken 3947 times.
✓ Branch 3 taken 4232 times.
26972 if (trk->mode == MODE_MOV && trk->par->codec_type == AVMEDIA_TYPE_VIDEO) {
7870 3947 AVPacket *opkt = pkt;
7871 int reshuffle_ret, ret;
7872
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 3922 times.
3947 if (trk->is_unaligned_qt_rgb) {
7873
1/2
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
25 int64_t bpc = trk->par->bits_per_coded_sample != 15 ? trk->par->bits_per_coded_sample : 16;
7874 25 int expected_stride = ((trk->par->width * bpc + 15) >> 4)*2;
7875 25 reshuffle_ret = ff_reshuffle_raw_rgb(s, &pkt, trk->par, expected_stride);
7876
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (reshuffle_ret < 0)
7877 ✗ return reshuffle_ret;
7878 } else
7879 3922 reshuffle_ret = 0;
7880
4/4
✓ Branch 0 taken 238 times.
✓ Branch 1 taken 3709 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 233 times.
3947 if (trk->par->format == AV_PIX_FMT_PAL8 && !trk->pal_done) {
7881 5 ret = ff_get_packet_palette(s, opkt, reshuffle_ret, trk->palette);
7882
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (ret < 0)
7883 ✗ goto fail;
7884
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (ret)
7885 5 trk->pal_done++;
7886
2/2
✓ Branch 0 taken 825 times.
✓ Branch 1 taken 3117 times.
3942 } else if (trk->par->codec_id == AV_CODEC_ID_RAWVIDEO &&
7887
1/2
✓ Branch 0 taken 825 times.
✗ Branch 1 not taken.
825 (trk->par->format == AV_PIX_FMT_GRAY8 ||
7888
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 825 times.
825 trk->par->format == AV_PIX_FMT_MONOBLACK)) {
7889 ✗ ret = av_packet_make_writable(pkt);
7890 ✗ if (ret < 0)
7891 ✗ goto fail;
7892 ✗ for (i = 0; i < pkt->size; i++)
7893 ✗ pkt->data[i] = ~pkt->data[i];
7894 }
7895
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3947 times.
3947 if (reshuffle_ret) {
7896 ✗ ret = mov_write_single_packet(s, pkt);
7897 ✗ fail:
7898 ✗ if (reshuffle_ret)
7899 ✗ av_packet_free(&pkt);
7900 ✗ return ret;
7901 }
7902 }
7903
7904 26972 return mov_write_single_packet(s, pkt);
7905 }
7906 }
7907
7908 // QuickTime chapters involve an additional text track with the chapter names
7909 // as samples, and a tref pointing from the other tracks to the chapter one.
7910 1 static int mov_create_chapter_track(AVFormatContext *s, int tracknum)
7911 {
7912 static const uint8_t stub_header[] = {
7913 // TextSampleEntry
7914 0x00, 0x00, 0x00, 0x01, // displayFlags
7915 0x00, 0x00, // horizontal + vertical justification
7916 0x00, 0x00, 0x00, 0x00, // bgColourRed/Green/Blue/Alpha
7917 // BoxRecord
7918 0x00, 0x00, 0x00, 0x00, // defTextBoxTop/Left
7919 0x00, 0x00, 0x00, 0x00, // defTextBoxBottom/Right
7920 // StyleRecord
7921 0x00, 0x00, 0x00, 0x00, // startChar + endChar
7922 0x00, 0x01, // fontID
7923 0x00, 0x00, // fontStyleFlags + fontSize
7924 0x00, 0x00, 0x00, 0x00, // fgColourRed/Green/Blue/Alpha
7925 // FontTableBox
7926 0x00, 0x00, 0x00, 0x0D, // box size
7927 'f', 't', 'a', 'b', // box atom name
7928 0x00, 0x01, // entry count
7929 // FontRecord
7930 0x00, 0x01, // font ID
7931 0x00, // font name length
7932 };
7933 1 MOVMuxContext *mov = s->priv_data;
7934 1 MOVTrack *track = &mov->tracks[tracknum];
7935 1 AVPacket *pkt = mov->pkt;
7936 int i, len;
7937 int ret;
7938
7939 1 track->mode = mov->mode;
7940 1 track->tag = MKTAG('t','e','x','t');
7941 1 track->timescale = mov->movie_timescale;
7942 1 track->par = avcodec_parameters_alloc();
7943
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!track->par)
7944 ✗ return AVERROR(ENOMEM);
7945 1 track->par->codec_type = AVMEDIA_TYPE_SUBTITLE;
7946 1 ret = ff_alloc_extradata(track->par, sizeof(stub_header));
7947
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
7948 ✗ return ret;
7949 1 memcpy(track->par->extradata, stub_header, sizeof(stub_header));
7950
7951
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (track->extradata == NULL) {
7952 ✗ track->stsd_count = 1;
7953 ✗ track->extradata = av_calloc(1, sizeof(*track->extradata));
7954 ✗ track->extradata_size = av_calloc(1, sizeof(*track->extradata_size));
7955 ✗ if (!track->extradata || !track->extradata_size)
7956 ✗ return AVERROR(ENOMEM);
7957 }
7958
7959 1 track->extradata[0] = av_memdup(stub_header, sizeof(stub_header));
7960
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!track->extradata[0])
7961 ✗ return AVERROR(ENOMEM);
7962 1 track->extradata_size[0] = sizeof(stub_header);
7963
7964 1 pkt->stream_index = tracknum;
7965 1 pkt->flags = AV_PKT_FLAG_KEY;
7966
7967
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
5 for (i = 0; i < s->nb_chapters; i++) {
7968 4 AVChapter *c = s->chapters[i];
7969 AVDictionaryEntry *t;
7970
7971 4 int64_t end = av_rescale_q(c->end, c->time_base, (AVRational){1,mov->movie_timescale});
7972 4 pkt->pts = pkt->dts = av_rescale_q(c->start, c->time_base, (AVRational){1,mov->movie_timescale});
7973 4 pkt->duration = end - pkt->dts;
7974
7975
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 if ((t = av_dict_get(c->metadata, "title", NULL, 0))) {
7976 static const char encd[12] = {
7977 0x00, 0x00, 0x00, 0x0C,
7978 'e', 'n', 'c', 'd',
7979 0x00, 0x00, 0x01, 0x00 };
7980 4 len = strlen(t->value);
7981 4 pkt->size = len + 2 + 12;
7982 4 pkt->data = av_malloc(pkt->size);
7983
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!pkt->data) {
7984 ✗ av_packet_unref(pkt);
7985 ✗ return AVERROR(ENOMEM);
7986 }
7987 4 AV_WB16(pkt->data, len);
7988 4 memcpy(pkt->data + 2, t->value, len);
7989 4 memcpy(pkt->data + len + 2, encd, sizeof(encd));
7990 4 ff_mov_write_packet(s, pkt);
7991 4 av_freep(&pkt->data);
7992 }
7993 }
7994
7995 1 av_packet_unref(mov->pkt);
7996
7997 1 return 0;
7998 }
7999
8000
8001 13 static int mov_check_timecode_track(AVFormatContext *s, AVTimecode *tc, AVStream *src_st, const char *tcstr)
8002 {
8003 int ret;
8004
8005 /* compute the frame number */
8006 13 ret = av_timecode_init_from_string(tc, src_st->avg_frame_rate, tcstr, s);
8007 13 return ret;
8008 }
8009
8010 6 static int mov_create_timecode_track(AVFormatContext *s, int index, int src_index, AVTimecode tc)
8011 {
8012 6 MOVMuxContext *mov = s->priv_data;
8013 6 MOVTrack *track = &mov->tracks[index];
8014 6 AVStream *src_st = mov->tracks[src_index].st;
8015 uint8_t data[4];
8016 6 AVPacket *pkt = mov->pkt;
8017 6 AVRational rate = src_st->avg_frame_rate;
8018 int ret;
8019
8020 /* tmcd track based on video stream */
8021 6 track->mode = mov->mode;
8022 6 track->tag = MKTAG('t','m','c','d');
8023 6 track->src_track = av_malloc(sizeof(*track->src_track));
8024
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!track->src_track)
8025 ✗ return AVERROR(ENOMEM);
8026 6 *track->src_track = src_index;
8027 6 track->nb_src_track = 1;
8028
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (tc.flags & AV_TIMECODE_FLAG_DROPFRAME)
8029 3 track->timescale = tc.fps * 1000;
8030
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 else if (tc.rate.den == 1001)
8031 ✗ track->timescale = tc.rate.num;
8032 else
8033 3 track->timescale = tc.fps;
8034
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (tc.flags & AV_TIMECODE_FLAG_DROPFRAME)
8035 3 track->timecode_flags |= MOV_TIMECODE_FLAG_DROPFRAME;
8036
8037 /* set st to src_st for metadata access*/
8038 6 track->st = src_st;
8039
8040 /* encode context: tmcd data stream */
8041 6 track->par = avcodec_parameters_alloc();
8042
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!track->par)
8043 ✗ return AVERROR(ENOMEM);
8044 6 track->par->codec_type = AVMEDIA_TYPE_DATA;
8045 6 track->par->codec_tag = track->tag;
8046 6 track->st->avg_frame_rate = rate;
8047
8048 /* the tmcd track just contains one packet with the frame number */
8049 6 pkt->data = data;
8050 6 pkt->stream_index = index;
8051 6 pkt->flags = AV_PKT_FLAG_KEY;
8052 6 pkt->pts = pkt->dts = av_rescale_q(tc.start, av_inv_q(rate), (AVRational){ 1, track->timescale });
8053 6 pkt->size = 4;
8054 6 AV_WB32(pkt->data, tc.start);
8055 6 ret = ff_mov_write_packet(s, pkt);
8056 6 av_packet_unref(pkt);
8057 6 return ret;
8058 }
8059
8060 /*
8061 * st->disposition controls the "enabled" flag in the tkhd tag.
8062 * QuickTime will not play a track if it is not enabled. So make sure
8063 * that one track of each type (audio, video, subtitle) is enabled.
8064 *
8065 * Subtitles are special. For audio and video, setting "enabled" also
8066 * makes the track "default" (i.e. it is rendered when played). For
8067 * subtitles, an "enabled" subtitle is not rendered by default, but
8068 * if no subtitle is enabled, the subtitle menu in QuickTime will be
8069 * empty!
8070 */
8071 262 static void enable_tracks(AVFormatContext *s)
8072 {
8073 262 MOVMuxContext *mov = s->priv_data;
8074 int i;
8075 int enabled[AVMEDIA_TYPE_NB];
8076 int first[AVMEDIA_TYPE_NB];
8077
8078
2/2
✓ Branch 0 taken 1310 times.
✓ Branch 1 taken 262 times.
1572 for (i = 0; i < AVMEDIA_TYPE_NB; i++) {
8079 1310 enabled[i] = 0;
8080 1310 first[i] = -1;
8081 }
8082
8083
2/2
✓ Branch 0 taken 425 times.
✓ Branch 1 taken 262 times.
687 for (i = 0; i < mov->nb_streams; i++) {
8084 425 AVStream *st = mov->tracks[i].st;
8085
8086
1/2
✓ Branch 0 taken 425 times.
✗ Branch 1 not taken.
425 if (st->codecpar->codec_type <= AVMEDIA_TYPE_UNKNOWN ||
8087
3/4
✓ Branch 0 taken 425 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 423 times.
850 st->codecpar->codec_type >= AVMEDIA_TYPE_NB ||
8088 425 is_cover_image(st))
8089 2 continue;
8090
8091
2/2
✓ Branch 0 taken 307 times.
✓ Branch 1 taken 116 times.
423 if (first[st->codecpar->codec_type] < 0)
8092 307 first[st->codecpar->codec_type] = i;
8093
2/2
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 379 times.
423 if (st->disposition & AV_DISPOSITION_DEFAULT) {
8094 44 mov->tracks[i].flags |= MOV_TRACK_ENABLED;
8095 44 enabled[st->codecpar->codec_type]++;
8096 }
8097 }
8098
8099
2/2
✓ Branch 0 taken 1310 times.
✓ Branch 1 taken 262 times.
1572 for (i = 0; i < AVMEDIA_TYPE_NB; i++) {
8100
2/2
✓ Branch 0 taken 786 times.
✓ Branch 1 taken 524 times.
1310 switch (i) {
8101 786 case AVMEDIA_TYPE_VIDEO:
8102 case AVMEDIA_TYPE_AUDIO:
8103 case AVMEDIA_TYPE_SUBTITLE:
8104
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 784 times.
786 if (enabled[i] > 1)
8105 2 mov->per_stream_grouping = 1;
8106
4/4
✓ Branch 0 taken 748 times.
✓ Branch 1 taken 38 times.
✓ Branch 2 taken 267 times.
✓ Branch 3 taken 481 times.
786 if (!enabled[i] && first[i] >= 0)
8107 267 mov->tracks[first[i]].flags |= MOV_TRACK_ENABLED;
8108 786 break;
8109 }
8110 }
8111 262 }
8112
8113 262 static void mov_free(AVFormatContext *s)
8114 {
8115 262 MOVMuxContext *mov = s->priv_data;
8116
8117
2/2
✓ Branch 0 taken 447 times.
✓ Branch 1 taken 262 times.
709 for (int i = 0; i < s->nb_streams; i++)
8118 447 s->streams[i]->priv_data = NULL;
8119
8120
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 262 times.
262 if (!mov->tracks)
8121 ✗ return;
8122
8123
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 261 times.
262 if (mov->chapter_track) {
8124 1 avcodec_parameters_free(&mov->tracks[mov->chapter_track].par);
8125 }
8126
8127
2/2
✓ Branch 0 taken 434 times.
✓ Branch 1 taken 262 times.
696 for (int i = 0; i < mov->nb_tracks; i++) {
8128 434 MOVTrack *const track = &mov->tracks[i];
8129
8130
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 432 times.
434 if (track->tag == MKTAG('r','t','p',' '))
8131 2 ff_mov_close_hinting(track);
8132
4/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 423 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 3 times.
432 else if (track->tag == MKTAG('t','m','c','d') && mov->nb_meta_tmcd)
8133 6 av_freep(&track->par);
8134 434 av_freep(&track->cluster);
8135 434 av_freep(&track->cluster_written);
8136 434 av_freep(&track->frag_info);
8137 434 av_packet_free(&track->cover_image);
8138
8139
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 424 times.
434 if (track->eac3_priv) {
8140 10 struct eac3_info *info = track->eac3_priv;
8141 10 av_packet_free(&info->pkt);
8142 10 av_freep(&track->eac3_priv);
8143 }
8144
2/2
✓ Branch 0 taken 436 times.
✓ Branch 1 taken 434 times.
870 for (int j = 0; j < track->stsd_count; j++)
8145 436 av_freep(&track->extradata[j]);
8146 434 av_freep(&track->extradata);
8147 434 av_freep(&track->extradata_size);
8148
8149
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 434 times.
445 for (int i = 0; i < track->nb_tref_tags; i++)
8150 11 av_freep(&track->tref_tags[i].id);
8151 434 av_freep(&track->tref_tags);
8152 434 av_freep(&track->src_track);
8153
8154 434 ff_mov_cenc_free(&track->cenc);
8155 434 ffio_free_dyn_buf(&track->mdat_buf);
8156
8157 #if CONFIG_IAMFENC
8158 434 ffio_free_dyn_buf(&track->iamf_buf);
8159
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 428 times.
434 if (track->iamf)
8160 6 ff_iamf_uninit_context(track->iamf);
8161 434 av_freep(&track->iamf);
8162 #endif
8163 434 ff_isom_close_apvc(&track->apv);
8164
8165 434 ff_packet_list_free(&track->squashed_packet_queue);
8166 }
8167
8168 262 av_freep(&mov->tracks);
8169 262 ffio_free_dyn_buf(&mov->mdat_buf);
8170 }
8171
8172 ✗ static uint32_t rgb_to_yuv(uint32_t rgb)
8173 {
8174 uint8_t r, g, b;
8175 int y, cb, cr;
8176
8177 ✗ r = (rgb >> 16) & 0xFF;
8178 ✗ g = (rgb >> 8) & 0xFF;
8179 ✗ b = (rgb ) & 0xFF;
8180
8181 ✗ y = av_clip_uint8(( 16000 + 257 * r + 504 * g + 98 * b)/1000);
8182 ✗ cb = av_clip_uint8((128000 - 148 * r - 291 * g + 439 * b)/1000);
8183 ✗ cr = av_clip_uint8((128000 + 439 * r - 368 * g - 71 * b)/1000);
8184
8185 ✗ return (y << 16) | (cr << 8) | cb;
8186 }
8187
8188 ✗ static int mov_create_dvd_sub_decoder_specific_info(MOVTrack *track,
8189 AVStream *st)
8190 {
8191 ✗ int i, width = 720, height = 480;
8192 ✗ int have_palette = 0, have_size = 0;
8193 uint32_t palette[16];
8194 ✗ char *cur = st->codecpar->extradata;
8195
8196 ✗ while (cur && *cur) {
8197 ✗ if (strncmp("palette:", cur, 8) == 0) {
8198 int i, count;
8199 ✗ count = sscanf(cur + 8,
8200 "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32", "
8201 "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32", "
8202 "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32", "
8203 "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32"",
8204 &palette[ 0], &palette[ 1], &palette[ 2], &palette[ 3],
8205 &palette[ 4], &palette[ 5], &palette[ 6], &palette[ 7],
8206 &palette[ 8], &palette[ 9], &palette[10], &palette[11],
8207 &palette[12], &palette[13], &palette[14], &palette[15]);
8208
8209 ✗ for (i = 0; i < count; i++) {
8210 ✗ palette[i] = rgb_to_yuv(palette[i]);
8211 }
8212 ✗ have_palette = 1;
8213 ✗ } else if (!strncmp("size:", cur, 5)) {
8214 ✗ sscanf(cur + 5, "%dx%d", &width, &height);
8215 ✗ have_size = 1;
8216 }
8217 ✗ if (have_palette && have_size)
8218 ✗ break;
8219 ✗ cur += strcspn(cur, "\n\r");
8220 ✗ cur += strspn(cur, "\n\r");
8221 }
8222 ✗ if (have_palette) {
8223 ✗ track->extradata[track->last_stsd_index] = av_malloc(16*4 + AV_INPUT_BUFFER_PADDING_SIZE);
8224 ✗ if (!track->extradata[track->last_stsd_index])
8225 ✗ return AVERROR(ENOMEM);
8226 ✗ for (i = 0; i < 16; i++) {
8227 ✗ AV_WB32(track->extradata[track->last_stsd_index] + i * 4, palette[i]);
8228 }
8229 ✗ memset(track->extradata[track->last_stsd_index] + 16*4, 0, AV_INPUT_BUFFER_PADDING_SIZE);
8230 ✗ track->extradata_size[track->last_stsd_index] = 16 * 4;
8231 }
8232 ✗ st->codecpar->width = width;
8233 ✗ st->codecpar->height = track->height = height;
8234
8235 ✗ return 0;
8236 }
8237
8238 #if CONFIG_IAMFENC
8239 262 static int mov_init_iamf_track(AVFormatContext *s)
8240 {
8241 262 MOVMuxContext *mov = s->priv_data;
8242 MOVTrack *track;
8243 IAMFContext *iamf;
8244 262 int first_iamf_idx = INT_MAX, last_iamf_idx = 0;
8245 262 int nb_audio_elements = 0, nb_mix_presentations = 0;
8246 int ret;
8247
8248
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 262 times.
276 for (int i = 0; i < s->nb_stream_groups; i++) {
8249 14 const AVStreamGroup *stg = s->stream_groups[i];
8250
8251
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
14 if (stg->type == AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
8252 7 nb_audio_elements++;
8253
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 8 times.
14 if (stg->type == AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION)
8254 6 nb_mix_presentations++;
8255 }
8256
8257
3/4
✓ Branch 0 taken 256 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 256 times.
✗ Branch 3 not taken.
262 if (!nb_audio_elements && !nb_mix_presentations)
8258 256 return 0;
8259
8260
3/6
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
6 if (nb_audio_elements < 1 || nb_audio_elements > 2 || nb_mix_presentations < 1) {
8261 ✗ av_log(s, AV_LOG_ERROR, "There must be >= 1 and <= 2 IAMF_AUDIO_ELEMENT and at least "
8262 "one IAMF_MIX_PRESENTATION stream groups to write a IMAF track\n");
8263 ✗ return AVERROR(EINVAL);
8264 }
8265
8266 6 iamf = av_mallocz(sizeof(*iamf));
8267
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!iamf)
8268 ✗ return AVERROR(ENOMEM);
8269
8270
8271
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 6 times.
19 for (int i = 0; i < s->nb_stream_groups; i++) {
8272 13 const AVStreamGroup *stg = s->stream_groups[i];
8273
2/3
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
13 switch(stg->type) {
8274 7 case AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT:
8275
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 7 times.
34 for (int j = 0; j < stg->nb_entries; j++) {
8276 27 first_iamf_idx = FFMIN(stg->entries[j]->stream->index, first_iamf_idx);
8277 27 last_iamf_idx = FFMAX(stg->entries[j]->stream->index, last_iamf_idx);
8278 }
8279
8280 7 ret = ff_iamf_add_audio_element(iamf, stg, s);
8281 7 break;
8282 6 case AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION:
8283 6 ret = ff_iamf_add_mix_presentation(iamf, stg, s);
8284 6 break;
8285 ✗ default:
8286 ✗ av_assert0(0);
8287 }
8288
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (ret < 0) {
8289 ✗ ff_iamf_uninit_context(iamf);
8290 ✗ av_free(iamf);
8291 ✗ return ret;
8292 }
8293 }
8294
8295 6 track = &mov->tracks[first_iamf_idx];
8296 6 track->iamf = iamf;
8297 6 track->first_iamf_idx = first_iamf_idx;
8298 6 track->last_iamf_idx = last_iamf_idx;
8299 6 track->tag = MKTAG('i','a','m','f');
8300
8301
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 6 times.
19 for (int i = 0; i < s->nb_stream_groups; i++) {
8302 13 AVStreamGroup *stg = s->stream_groups[i];
8303
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 7 times.
13 if (stg->type != AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
8304 6 continue;
8305
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 7 times.
34 for (int j = 0; j < stg->nb_entries; j++)
8306 27 stg->entries[j]->stream->priv_data = track;
8307 }
8308
8309 6 ret = avio_open_dyn_buf(&track->iamf_buf);
8310
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (ret < 0)
8311 ✗ return ret;
8312
8313 6 return 0;
8314 }
8315 #endif
8316
8317 262 static int mov_init(AVFormatContext *s)
8318 {
8319 262 MOVMuxContext *mov = s->priv_data;
8320 262 int has_iamf = 0;
8321 int i, ret;
8322
8323 262 mov->fc = s;
8324 262 mov->pkt = ffformatcontext(s)->pkt;
8325
8326 /* Default mode == MP4 */
8327 262 mov->mode = MODE_MP4;
8328
8329 #define IS_MODE(muxer, config) (CONFIG_ ## config ## _MUXER && !strcmp(#muxer, s->oformat->name))
8330
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 262 times.
262 if (IS_MODE(3gp, TGP)) mov->mode = MODE_3GP;
8331
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 262 times.
262 else if (IS_MODE(3g2, TG2)) mov->mode = MODE_3GP|MODE_3G2;
8332
2/2
✓ Branch 0 taken 158 times.
✓ Branch 1 taken 104 times.
262 else if (IS_MODE(mov, MOV)) mov->mode = MODE_MOV;
8333
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 103 times.
104 else if (IS_MODE(psp, PSP)) mov->mode = MODE_PSP;
8334
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 102 times.
103 else if (IS_MODE(ipod, IPOD)) mov->mode = MODE_IPOD;
8335
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 97 times.
102 else if (IS_MODE(ismv, ISMV)) mov->mode = MODE_ISM;
8336
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 97 times.
97 else if (IS_MODE(f4v, F4V)) mov->mode = MODE_F4V;
8337
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 96 times.
97 else if (IS_MODE(avif, AVIF)) mov->mode = MODE_AVIF;
8338 #undef IS_MODE
8339
8340
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 241 times.
262 if (mov->flags & FF_MOV_FLAG_DELAY_MOOV)
8341 21 mov->flags |= FF_MOV_FLAG_EMPTY_MOOV;
8342
8343
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 261 times.
262 if (mov->mode == MODE_AVIF)
8344 1 mov->flags |= FF_MOV_FLAG_DELAY_MOOV;
8345
8346 /* Set the FRAGMENT flag if any of the fragmentation methods are
8347 * enabled. */
8348
3/4
✓ Branch 0 taken 260 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 260 times.
✗ Branch 3 not taken.
262 if (mov->max_fragment_duration || mov->max_fragment_size ||
8349
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 220 times.
260 mov->flags & (FF_MOV_FLAG_EMPTY_MOOV |
8350 FF_MOV_FLAG_FRAG_KEYFRAME |
8351 FF_MOV_FLAG_FRAG_CUSTOM |
8352 FF_MOV_FLAG_FRAG_EVERY_FRAME))
8353 42 mov->flags |= FF_MOV_FLAG_FRAGMENT;
8354
8355
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 260 times.
262 if (mov->flags & FF_MOV_FLAG_HYBRID_FRAGMENTED &&
8356
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 mov->flags & FF_MOV_FLAG_FASTSTART) {
8357 ✗ av_log(s, AV_LOG_ERROR, "Setting both hybrid_fragmented and faststart is not supported.\n");
8358 ✗ return AVERROR(EINVAL);
8359 }
8360
8361 /* Set other implicit flags immediately */
8362
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 260 times.
262 if (mov->flags & FF_MOV_FLAG_HYBRID_FRAGMENTED)
8363 2 mov->flags |= FF_MOV_FLAG_FRAGMENT;
8364
8365
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 257 times.
262 if (mov->mode == MODE_ISM)
8366 5 mov->flags |= FF_MOV_FLAG_EMPTY_MOOV | FF_MOV_FLAG_SEPARATE_MOOF |
8367 FF_MOV_FLAG_FRAGMENT | FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS;
8368
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 247 times.
262 if (mov->flags & FF_MOV_FLAG_DASH)
8369 15 mov->flags |= FF_MOV_FLAG_FRAGMENT | FF_MOV_FLAG_EMPTY_MOOV |
8370 FF_MOV_FLAG_DEFAULT_BASE_MOOF;
8371
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 260 times.
262 if (mov->flags & FF_MOV_FLAG_CMAF)
8372 2 mov->flags |= FF_MOV_FLAG_FRAGMENT | FF_MOV_FLAG_EMPTY_MOOV |
8373 FF_MOV_FLAG_DEFAULT_BASE_MOOF | FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS;
8374
8375
4/4
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 219 times.
✓ Branch 2 taken 39 times.
✓ Branch 3 taken 4 times.
262 if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV && s->flags & AVFMT_FLAG_AUTO_BSF) {
8376 39 av_log(s, AV_LOG_VERBOSE, "Empty MOOV enabled; disabling automatic bitstream filtering\n");
8377 39 s->flags &= ~AVFMT_FLAG_AUTO_BSF;
8378 }
8379
8380
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 262 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
262 if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX && mov->flags & FF_MOV_FLAG_SKIP_SIDX) {
8381 ✗ av_log(s, AV_LOG_WARNING, "Global SIDX enabled; Ignoring skip_sidx option\n");
8382 ✗ mov->flags &= ~FF_MOV_FLAG_SKIP_SIDX;
8383 }
8384
8385
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 259 times.
262 if (mov->flags & FF_MOV_FLAG_FASTSTART) {
8386 3 mov->reserved_moov_size = -1;
8387 }
8388
8389
2/2
✓ Branch 0 taken 254 times.
✓ Branch 1 taken 8 times.
262 if (mov->use_editlist < 0) {
8390 254 mov->use_editlist = 1;
8391
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 213 times.
254 if (mov->flags & FF_MOV_FLAG_FRAGMENT &&
8392
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 19 times.
41 !(mov->flags & FF_MOV_FLAG_DELAY_MOOV)) {
8393 // If we can avoid needing an edit list by shifting the
8394 // tracks, prefer that over (trying to) write edit lists
8395 // in fragmented output.
8396
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 21 times.
22 if (s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO ||
8397
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO)
8398 21 mov->use_editlist = 0;
8399 }
8400 }
8401
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 219 times.
262 if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV &&
8402
4/4
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 21 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 21 times.
43 !(mov->flags & FF_MOV_FLAG_DELAY_MOOV) && mov->use_editlist)
8403 1 av_log(s, AV_LOG_WARNING, "No meaningful edit list will be written when using empty_moov without delay_moov\n");
8404
8405
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 260 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
262 if (mov->flags & FF_MOV_FLAG_CMAF && mov->use_editlist)
8406 ✗ mov->flags &= ~FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS;
8407
8408
4/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 234 times.
✓ Branch 2 taken 27 times.
✓ Branch 3 taken 1 times.
262 if (!mov->use_editlist && s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO &&
8409
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 8 times.
27 !(mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS))
8410 19 s->avoid_negative_ts = AVFMT_AVOID_NEG_TS_MAKE_ZERO;
8411
8412 /* Clear the omit_tfhd_offset flag if default_base_moof is set;
8413 * if the latter is set that's enough and omit_tfhd_offset doesn't
8414 * add anything extra on top of that. */
8415
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 262 times.
262 if (mov->flags & FF_MOV_FLAG_OMIT_TFHD_OFFSET &&
8416 ✗ mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF)
8417 ✗ mov->flags &= ~FF_MOV_FLAG_OMIT_TFHD_OFFSET;
8418
8419
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 261 times.
262 if (mov->frag_interleave &&
8420
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 mov->flags & (FF_MOV_FLAG_OMIT_TFHD_OFFSET | FF_MOV_FLAG_SEPARATE_MOOF)) {
8421 ✗ av_log(s, AV_LOG_ERROR,
8422 "Sample interleaving in fragments is mutually exclusive with "
8423 "omit_tfhd_offset and separate_moof\n");
8424 ✗ return AVERROR(EINVAL);
8425 }
8426
8427 /* Non-seekable output is ok if using fragmentation. If ism_lookahead
8428 * is enabled, we don't support non-seekable output at all. */
8429
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 233 times.
262 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL) &&
8430
2/4
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
✗ Branch 3 not taken.
29 (!(mov->flags & FF_MOV_FLAG_FRAGMENT) || mov->ism_lookahead ||
8431
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 mov->mode == MODE_AVIF)) {
8432 ✗ av_log(s, AV_LOG_ERROR, "muxer does not support non seekable output\n");
8433 ✗ return AVERROR(EINVAL);
8434 }
8435
8436 #if CONFIG_AVIF_MUXER
8437 /* AVIF output must have at most two video streams (one for YUV and one for
8438 * alpha). */
8439
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 261 times.
262 if (mov->mode == MODE_AVIF) {
8440
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (s->nb_streams > 2) {
8441 ✗ av_log(s, AV_LOG_ERROR, "AVIF output requires exactly one or two streams\n");
8442 ✗ return AVERROR(EINVAL);
8443 }
8444
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (s->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO ||
8445
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 (s->nb_streams > 1 && s->streams[1]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO)) {
8446 ✗ av_log(s, AV_LOG_ERROR, "AVIF output supports only video streams\n");
8447 ✗ return AVERROR(EINVAL);
8448 }
8449
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (!av_pix_fmt_desc_get(s->streams[0]->codecpar->format)) {
8450 ✗ av_log(s, AV_LOG_ERROR, "AVIF output requires a known pixel format\n");
8451 ✗ return AVERROR(EINVAL);
8452 }
8453
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (s->nb_streams > 1) {
8454 const AVPixFmtDescriptor *pixdesc =
8455 ✗ av_pix_fmt_desc_get(s->streams[1]->codecpar->format);
8456 ✗ if (!pixdesc || pixdesc->nb_components != 1) {
8457 ✗ av_log(s, AV_LOG_ERROR, "Second stream for AVIF (alpha) output must have exactly one plane\n");
8458 ✗ return AVERROR(EINVAL);
8459 }
8460 }
8461 1 s->streams[0]->disposition |= AV_DISPOSITION_DEFAULT;
8462 }
8463 #endif
8464
8465
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 262 times.
276 for (i = 0; i < s->nb_stream_groups; i++) {
8466 14 AVStreamGroup *stg = s->stream_groups[i];
8467
8468
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 14 times.
70 for (int j = 0; j < stg->nb_entries; j++) {
8469
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
56 if (stg->entries[j]->type != AV_STREAM_GROUP_ENTRY_STREAM) {
8470 ✗ av_log(s, AV_LOG_ERROR, "Unsupported Stream Group entry #%d "
8471 "in Stream Group id %"PRId64"\n",
8472 i, stg->id);
8473 ✗ return AVERROR(EINVAL);
8474 }
8475 }
8476
8477
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 13 times.
14 if (stg->type == AV_STREAM_GROUP_PARAMS_LCEVC) {
8478
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (stg->nb_entries != 2) {
8479 ✗ av_log(s, AV_LOG_ERROR, "Exactly two Streams are supported for Stream Groups of type LCEVC\n");
8480 ✗ return AVERROR(EINVAL);
8481 }
8482 1 AVStreamGroupLayeredVideo *lcevc = stg->params.layered_video;
8483
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (lcevc->el_index > 1)
8484 ✗ return AVERROR(EINVAL);
8485 1 AVStream *st = stg->entries[lcevc->el_index]->stream;
8486
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (st->codecpar->codec_id != AV_CODEC_ID_LCEVC) {
8487 ✗ av_log(s, AV_LOG_ERROR, "Stream #%u is not an LCEVC stream\n", lcevc->el_index);
8488 ✗ return AVERROR(EINVAL);
8489 }
8490 }
8491
8492 #if CONFIG_IAMFENC
8493
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
14 if (stg->type != AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
8494 7 continue;
8495
8496
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 7 times.
34 for (int j = 0; j < stg->nb_entries; j++) {
8497 27 AVStream *st = stg->entries[j]->stream;
8498
8499
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (st->priv_data) {
8500 ✗ av_log(s, AV_LOG_ERROR, "Stream %d is present in more than one Stream Group of type "
8501 "IAMF Audio Element\n", j);
8502 ✗ return AVERROR(EINVAL);
8503 }
8504 27 st->priv_data = st;
8505 }
8506 7 has_iamf = 1;
8507
8508
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1 times.
7 if (!mov->nb_tracks) // We support one track for the entire IAMF structure
8509 6 mov->nb_tracks++;
8510 #endif
8511 }
8512
8513
2/2
✓ Branch 0 taken 447 times.
✓ Branch 1 taken 262 times.
709 for (i = 0; i < s->nb_streams; i++) {
8514 447 AVStream *st = s->streams[i];
8515
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 420 times.
447 if (st->priv_data)
8516 27 continue;
8517 // Don't produce a track in the output file for timed ID3 streams.
8518
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 419 times.
420 if (st->codecpar->codec_id == AV_CODEC_ID_TIMED_ID3) {
8519 // Leave priv_data set to NULL for these AVStreams that don't
8520 // have a corresponding track.
8521 1 continue;
8522 }
8523 419 st->priv_data = st;
8524 419 mov->nb_tracks++;
8525 }
8526
8527 262 mov->nb_streams = mov->nb_tracks;
8528
8529
4/4
✓ Branch 0 taken 255 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 254 times.
262 if (mov->mode & (MODE_MP4|MODE_MOV|MODE_IPOD) && s->nb_chapters)
8530 1 mov->chapter_track = mov->nb_tracks++;
8531
8532
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 261 times.
262 if (mov->flags & FF_MOV_FLAG_RTP_HINT) {
8533
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 for (i = 0; i < s->nb_streams; i++)
8534
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (rtp_hinting_needed(s->streams[i]))
8535 2 mov->nb_tracks++;
8536 }
8537
8538
2/2
✓ Branch 0 taken 261 times.
✓ Branch 1 taken 1 times.
262 if (mov->write_btrt < 0) {
8539 261 mov->write_btrt = mov->mode == MODE_MP4;
8540 }
8541
8542
6/6
✓ Branch 0 taken 258 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 100 times.
✓ Branch 3 taken 158 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 96 times.
262 if ( mov->write_tmcd == -1 && (mov->mode == MODE_MOV || mov->mode == MODE_MP4)
8543
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
8 || mov->write_tmcd == 1) {
8544 257 AVDictionaryEntry *global_tcr = av_dict_get(s->metadata, "timecode",
8545 NULL, 0);
8546
8547 /* +1 tmcd track for each video stream with a timecode */
8548
2/2
✓ Branch 0 taken 439 times.
✓ Branch 1 taken 257 times.
696 for (i = 0; i < s->nb_streams; i++) {
8549 439 AVStream *st = s->streams[i];
8550 439 AVDictionaryEntry *t = global_tcr;
8551
4/4
✓ Branch 0 taken 205 times.
✓ Branch 1 taken 234 times.
✓ Branch 2 taken 199 times.
✓ Branch 3 taken 6 times.
439 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
8552
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 198 times.
199 (t || (t=av_dict_get(st->metadata, "timecode", NULL, 0)))) {
8553 AVTimecode tc;
8554 7 ret = mov_check_timecode_track(s, &tc, st, t->value);
8555
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (ret >= 0)
8556 7 mov->nb_meta_tmcd++;
8557 }
8558 }
8559
8560 /* check if there is already a tmcd track to remux */
8561
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 250 times.
257 if (mov->nb_meta_tmcd) {
8562
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 7 times.
20 for (i = 0; i < s->nb_streams; i++) {
8563 13 AVStream *st = s->streams[i];
8564
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 10 times.
13 if (st->codecpar->codec_tag == MKTAG('t','m','c','d')) {
8565 3 av_log(s, AV_LOG_WARNING, "You requested a copy of the original timecode track "
8566 "so timecode metadata are now ignored\n");
8567 3 mov->nb_meta_tmcd = 0;
8568 }
8569 }
8570 }
8571
8572 257 mov->nb_tracks += mov->nb_meta_tmcd;
8573 }
8574
8575 // Reserve an extra stream for chapters for the case where chapters
8576 // are written in the trailer
8577 262 mov->tracks = av_calloc(mov->nb_tracks + 1, sizeof(*mov->tracks));
8578
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 262 times.
262 if (!mov->tracks)
8579 ✗ return AVERROR(ENOMEM);
8580
8581
2/2
✓ Branch 0 taken 434 times.
✓ Branch 1 taken 262 times.
696 for (i = 0; i < mov->nb_tracks; i++) {
8582 434 MOVTrack *track = &mov->tracks[i];
8583
8584 434 track->stsd_count = 1;
8585 434 track->extradata = av_calloc(track->stsd_count, sizeof(*track->extradata));
8586 434 track->extradata_size = av_calloc(track->stsd_count, sizeof(*track->extradata_size));
8587
2/4
✓ Branch 0 taken 434 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 434 times.
434 if (!track->extradata || !track->extradata_size)
8588 ✗ return AVERROR(ENOMEM);
8589 }
8590
8591
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 257 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
262 if (mov->encryption_scheme_str != NULL && strcmp(mov->encryption_scheme_str, "none") != 0) {
8592
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (strcmp(mov->encryption_scheme_str, "cenc-aes-ctr") == 0) {
8593 5 mov->encryption_scheme = MOV_ENC_CENC_AES_CTR;
8594
8595
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (mov->encryption_key_len != AES_CTR_KEY_SIZE) {
8596 ✗ av_log(s, AV_LOG_ERROR, "Invalid encryption key len %d expected %d\n",
8597 mov->encryption_key_len, AES_CTR_KEY_SIZE);
8598 ✗ return AVERROR(EINVAL);
8599 }
8600
8601
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (mov->encryption_kid_len != CENC_KID_SIZE) {
8602 ✗ av_log(s, AV_LOG_ERROR, "Invalid encryption kid len %d expected %d\n",
8603 mov->encryption_kid_len, CENC_KID_SIZE);
8604 ✗ return AVERROR(EINVAL);
8605 }
8606 } else {
8607 ✗ av_log(s, AV_LOG_ERROR, "unsupported encryption scheme %s\n",
8608 mov->encryption_scheme_str);
8609 ✗ return AVERROR(EINVAL);
8610 }
8611 }
8612
8613 #if CONFIG_IAMFENC
8614 262 ret = mov_init_iamf_track(s);
8615
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 262 times.
262 if (ret < 0)
8616 ✗ return ret;
8617 #endif
8618
8619
2/2
✓ Branch 0 taken 447 times.
✓ Branch 1 taken 262 times.
709 for (int j = 0, i = 0; j < s->nb_streams; j++) {
8620 447 AVStream *st = s->streams[j];
8621
8622
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 419 times.
447 if (st != st->priv_data) {
8623
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 22 times.
28 if (has_iamf)
8624 6 i += has_iamf--;
8625 28 continue;
8626 }
8627 419 st->priv_data = &mov->tracks[i++];
8628 }
8629
8630 262 AVRational movie_timescale = (AVRational) { 0, 1 };
8631
2/2
✓ Branch 0 taken 447 times.
✓ Branch 1 taken 262 times.
709 for (i = 0; i < s->nb_streams; i++) {
8632 447 AVStream *st= s->streams[i];
8633 447 MOVTrack *track = st->priv_data;
8634
8635
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 446 times.
447 if (!track)
8636 1 continue;
8637
8638
2/2
✓ Branch 0 taken 425 times.
✓ Branch 1 taken 21 times.
446 if (!track->st) {
8639 425 track->st = st;
8640 425 track->par = st->codecpar;
8641 }
8642
8643 446 movie_timescale = av_gcd_q(movie_timescale, st->time_base, INT_MAX, (AVRational){1,0});
8644 }
8645
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 262 times.
262 if (!movie_timescale.den)
8646 ✗ movie_timescale = MOV_TIMESCALE_Q;
8647
8648
2/2
✓ Branch 0 taken 261 times.
✓ Branch 1 taken 1 times.
262 if (!mov->movie_timescale)
8649 261 mov->movie_timescale = FFMAX(movie_timescale.den, MOV_TIMESCALE);
8650
8651
2/2
✓ Branch 0 taken 447 times.
✓ Branch 1 taken 262 times.
709 for (i = 0; i < s->nb_streams; i++) {
8652 447 AVStream *st= s->streams[i];
8653 447 MOVTrack *track = st->priv_data;
8654 447 AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL,0);
8655
8656
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 446 times.
447 if (!track)
8657 1 continue;
8658
8659
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 411 times.
446 track->language = ff_mov_iso639_to_lang(lang?lang->value:"und", mov->mode!=MODE_MOV);
8660
2/2
✓ Branch 0 taken 166 times.
✓ Branch 1 taken 280 times.
446 if (track->language < 0)
8661 166 track->language = 32767; // Unspecified Macintosh language code
8662 446 track->mode = mov->mode;
8663
2/2
✓ Branch 0 taken 419 times.
✓ Branch 1 taken 27 times.
446 if (!track->tag)
8664 419 track->tag = mov_find_codec_tag(s, track);
8665
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 446 times.
446 if (!track->tag) {
8666 ✗ av_log(s, AV_LOG_ERROR, "Could not find tag for codec %s in stream #%d, "
8667 "codec not currently supported in container\n",
8668 ✗ avcodec_get_name(st->codecpar->codec_id), i);
8669 ✗ return AVERROR(EINVAL);
8670 }
8671 /* If hinting of this track is enabled by a later hint track,
8672 * this is updated. */
8673 446 track->hint_track = -1;
8674 446 track->start_dts = AV_NOPTS_VALUE;
8675 446 track->start_cts = AV_NOPTS_VALUE;
8676 446 track->end_pts = AV_NOPTS_VALUE;
8677 446 track->dts_shift = AV_NOPTS_VALUE;
8678
2/2
✓ Branch 0 taken 209 times.
✓ Branch 1 taken 237 times.
446 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
8679
2/4
✓ Branch 0 taken 209 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 209 times.
✗ Branch 3 not taken.
209 if (track->tag == MKTAG('m','x','3','p') || track->tag == MKTAG('m','x','3','n') ||
8680
2/4
✓ Branch 0 taken 209 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 209 times.
✗ Branch 3 not taken.
209 track->tag == MKTAG('m','x','4','p') || track->tag == MKTAG('m','x','4','n') ||
8681
2/4
✓ Branch 0 taken 209 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 209 times.
209 track->tag == MKTAG('m','x','5','p') || track->tag == MKTAG('m','x','5','n')) {
8682 ✗ if (st->codecpar->width != 720 || (st->codecpar->height != 608 && st->codecpar->height != 512)) {
8683 ✗ av_log(s, AV_LOG_ERROR, "D-10/IMX must use 720x608 or 720x512 video resolution\n");
8684 ✗ return AVERROR(EINVAL);
8685 }
8686 ✗ track->height = track->tag >> 24 == 'n' ? 486 : 576;
8687 }
8688
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 209 times.
209 if (mov->video_track_timescale) {
8689 ✗ track->timescale = mov->video_track_timescale;
8690 ✗ if (mov->mode == MODE_ISM && mov->video_track_timescale != 10000000)
8691 ✗ av_log(s, AV_LOG_WARNING, "Warning: some tools, like mp4split, assume a timescale of 10000000 for ISMV.\n");
8692 } else {
8693 209 track->timescale = st->time_base.den;
8694
2/2
✓ Branch 0 taken 1618 times.
✓ Branch 1 taken 209 times.
1827 while(track->timescale < 10000)
8695 1618 track->timescale *= 2;
8696 }
8697
2/4
✓ Branch 0 taken 209 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 209 times.
209 if (st->codecpar->width > 65535 || st->codecpar->height > 65535) {
8698 ✗ av_log(s, AV_LOG_ERROR, "Resolution %dx%d too large for mov/mp4\n", st->codecpar->width, st->codecpar->height);
8699 ✗ return AVERROR(EINVAL);
8700 }
8701
4/4
✓ Branch 0 taken 138 times.
✓ Branch 1 taken 71 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 133 times.
209 if (track->mode == MODE_MOV && track->timescale > 100000)
8702 5 av_log(s, AV_LOG_WARNING,
8703 "WARNING codec timebase is very high. If duration is too long,\n"
8704 "file may not be playable by quicktime. Specify a shorter timebase\n"
8705 "or choose different container.\n");
8706
2/2
✓ Branch 0 taken 138 times.
✓ Branch 1 taken 71 times.
209 if (track->mode == MODE_MOV &&
8707
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 121 times.
138 track->par->codec_id == AV_CODEC_ID_RAWVIDEO &&
8708
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 16 times.
17 track->tag == MKTAG('r','a','w',' ')) {
8709 1 enum AVPixelFormat pix_fmt = track->par->format;
8710
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 if (pix_fmt == AV_PIX_FMT_NONE && track->par->bits_per_coded_sample == 1)
8711 ✗ pix_fmt = AV_PIX_FMT_MONOWHITE;
8712 1 track->is_unaligned_qt_rgb =
8713 ✗ pix_fmt == AV_PIX_FMT_RGB24 ||
8714 ✗ pix_fmt == AV_PIX_FMT_BGR24 ||
8715 ✗ pix_fmt == AV_PIX_FMT_PAL8 ||
8716 ✗ pix_fmt == AV_PIX_FMT_GRAY8 ||
8717
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 pix_fmt == AV_PIX_FMT_MONOWHITE ||
8718 pix_fmt == AV_PIX_FMT_MONOBLACK;
8719 }
8720
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 209 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
209 if (track->par->codec_id == AV_CODEC_ID_VP9 && track->mode != MODE_MP4) {
8721 ✗ av_log(s, AV_LOG_ERROR, "%s only supported in MP4.\n", avcodec_get_name(track->par->codec_id));
8722 ✗ return AVERROR(EINVAL);
8723
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 206 times.
209 } else if (track->par->codec_id == AV_CODEC_ID_AV1 &&
8724
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
3 track->mode != MODE_MP4 && track->mode != MODE_AVIF) {
8725 ✗ av_log(s, AV_LOG_ERROR, "%s only supported in MP4 and AVIF.\n", avcodec_get_name(track->par->codec_id));
8726 ✗ return AVERROR(EINVAL);
8727
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 209 times.
209 } else if (track->par->codec_id == AV_CODEC_ID_VP8) {
8728 /* altref frames handling is not defined in the spec as of version v1.0,
8729 * so just forbid muxing VP8 streams altogether until a new version does */
8730 ✗ av_log(s, AV_LOG_ERROR, "VP8 muxing is currently not supported.\n");
8731 ✗ return AVERROR_PATCHWELCOME;
8732
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 208 times.
209 } else if (track->par->codec_id == AV_CODEC_ID_APV) {
8733 1 ret = ff_isom_init_apvc(&track->apv, s);
8734
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
8735 ✗ return ret;
8736 }
8737
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 207 times.
209 if (is_cover_image(st)) {
8738 2 track->cover_image = av_packet_alloc();
8739
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!track->cover_image)
8740 ✗ return AVERROR(ENOMEM);
8741 }
8742
2/2
✓ Branch 0 taken 228 times.
✓ Branch 1 taken 9 times.
237 } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
8743 228 track->timescale = st->codecpar->sample_rate;
8744
4/4
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 190 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 30 times.
228 if (!st->codecpar->frame_size && !av_get_bits_per_sample(st->codecpar->codec_id)) {
8745 8 av_log(s, AV_LOG_WARNING, "track %d: codec frame size is not set\n", i);
8746 8 track->audio_vbr = 1;
8747
1/2
✓ Branch 0 taken 220 times.
✗ Branch 1 not taken.
220 }else if (st->codecpar->codec_id == AV_CODEC_ID_ADPCM_MS ||
8748
1/2
✓ Branch 0 taken 220 times.
✗ Branch 1 not taken.
220 st->codecpar->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV ||
8749
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 220 times.
220 st->codecpar->codec_id == AV_CODEC_ID_ILBC){
8750 ✗ if (!st->codecpar->block_align) {
8751 ✗ av_log(s, AV_LOG_ERROR, "track %d: codec block align is not set for adpcm\n", i);
8752 ✗ return AVERROR(EINVAL);
8753 }
8754 ✗ track->sample_size = st->codecpar->block_align;
8755
2/2
✓ Branch 0 taken 190 times.
✓ Branch 1 taken 30 times.
220 }else if (st->codecpar->frame_size > 1){ /* assume compressed audio */
8756 190 track->audio_vbr = 1;
8757 }else{
8758 30 track->sample_size = (av_get_bits_per_sample(st->codecpar->codec_id) >> 3) *
8759 30 st->codecpar->ch_layout.nb_channels;
8760 }
8761
1/2
✓ Branch 0 taken 228 times.
✗ Branch 1 not taken.
228 if (st->codecpar->codec_id == AV_CODEC_ID_ILBC ||
8762
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 228 times.
228 st->codecpar->codec_id == AV_CODEC_ID_ADPCM_IMA_QT) {
8763 ✗ track->audio_vbr = 1;
8764 }
8765
2/2
✓ Branch 0 taken 191 times.
✓ Branch 1 taken 37 times.
228 if (track->mode != MODE_MOV &&
8766
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 190 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
191 track->par->codec_id == AV_CODEC_ID_MP3 && track->timescale < 16000) {
8767 ✗ if (s->strict_std_compliance >= FF_COMPLIANCE_NORMAL) {
8768 ✗ av_log(s, AV_LOG_ERROR, "track %d: muxing mp3 at %dhz is not standard, to mux anyway set strict to -1\n",
8769 ✗ i, track->par->sample_rate);
8770 ✗ return AVERROR(EINVAL);
8771 } else {
8772 ✗ av_log(s, AV_LOG_WARNING, "track %d: muxing mp3 at %dhz is not standard in MP4\n",
8773 ✗ i, track->par->sample_rate);
8774 }
8775 }
8776
2/2
✓ Branch 0 taken 201 times.
✓ Branch 1 taken 27 times.
228 if (track->par->codec_id == AV_CODEC_ID_FLAC ||
8777
1/2
✓ Branch 0 taken 201 times.
✗ Branch 1 not taken.
201 track->par->codec_id == AV_CODEC_ID_TRUEHD ||
8778
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 201 times.
201 track->par->codec_id == AV_CODEC_ID_OPUS) {
8779
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (track->mode != MODE_MP4) {
8780 ✗ av_log(s, AV_LOG_ERROR, "%s only supported in MP4.\n", avcodec_get_name(track->par->codec_id));
8781 ✗ return AVERROR(EINVAL);
8782 }
8783
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (track->par->codec_id == AV_CODEC_ID_TRUEHD &&
8784 ✗ s->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) {
8785 ✗ av_log(s, AV_LOG_ERROR,
8786 "%s in MP4 support is experimental, add "
8787 "'-strict %d' if you want to use it.\n",
8788 ✗ avcodec_get_name(track->par->codec_id), FF_COMPLIANCE_EXPERIMENTAL);
8789 ✗ return AVERROR_EXPERIMENTAL;
8790 }
8791 }
8792
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4 times.
9 } else if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
8793 5 track->timescale = st->time_base.den;
8794
8795
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
5 if (track->par->codec_id == AV_CODEC_ID_TTML) {
8796 /* 14496-30 requires us to use a single sample per fragment
8797 for TTML, for which we define a per-track flag.
8798
8799 We set the flag in case we are receiving TTML paragraphs
8800 from the input, in other words in case we are not doing
8801 stream copy. */
8802 4 track->squash_fragment_samples_to_one =
8803 4 ff_is_ttml_stream_paragraph_based(track->par);
8804
8805
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 if (track->mode != MODE_ISM &&
8806
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 track->par->codec_tag == MOV_ISMV_TTML_TAG &&
8807
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 s->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL) {
8808 ✗ av_log(s, AV_LOG_ERROR,
8809 "ISMV style TTML support with the 'dfxp' tag in "
8810 "non-ISMV formats is not officially supported. Add "
8811 "'-strict unofficial' if you want to use it.\n");
8812 ✗ return AVERROR_EXPERIMENTAL;
8813 }
8814 }
8815
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 } else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA) {
8816 4 track->timescale = st->time_base.den;
8817
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 if (track->tag == MKTAG('t','m','c','d') &&
8818
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 st->codecpar->extradata_size >= 8)
8819 3 track->timecode_flags = AV_RB32(st->codecpar->extradata + 4);
8820 } else {
8821 ✗ track->timescale = mov->movie_timescale;
8822 }
8823
1/2
✓ Branch 0 taken 446 times.
✗ Branch 1 not taken.
446 if (!track->height)
8824 446 track->height = st->codecpar->height;
8825 /* The Protected Interoperable File Format (PIFF) standard, used by ISMV recommends but
8826 doesn't mandate a track timescale of 10,000,000. The muxer allows a custom timescale
8827 for video tracks, so if user-set, it isn't overwritten */
8828
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 439 times.
446 if (mov->mode == MODE_ISM &&
8829
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 2 times.
7 (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO ||
8830
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
5 (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && !mov->video_track_timescale))) {
8831 7 track->timescale = 10000000;
8832 }
8833
8834 446 avpriv_set_pts_info(st, 64, 1, track->timescale);
8835
8836
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 441 times.
446 if (mov->encryption_scheme == MOV_ENC_CENC_AES_CTR) {
8837 5 ret = ff_mov_cenc_init(&track->cenc, mov->encryption_key,
8838
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 (track->par->codec_id == AV_CODEC_ID_H264 || track->par->codec_id == AV_CODEC_ID_HEVC ||
8839
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 track->par->codec_id == AV_CODEC_ID_VVC || track->par->codec_id == AV_CODEC_ID_AV1),
8840
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
5 track->par->codec_id, s->flags & AVFMT_FLAG_BITEXACT);
8841
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (ret)
8842 ✗ return ret;
8843 }
8844 }
8845
8846
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 262 times.
276 for (i = 0; i < s->nb_stream_groups; i++) {
8847 14 AVStreamGroup *stg = s->stream_groups[i];
8848
8849
2/3
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
14 switch (stg->type) {
8850 1 case AV_STREAM_GROUP_PARAMS_LCEVC: {
8851 1 AVStreamGroupLayeredVideo *lcevc = stg->params.layered_video;
8852 1 AVStream *st = stg->entries[lcevc->el_index]->stream;
8853 1 MOVTrack *track = st->priv_data;
8854
8855
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 for (int j = 0; j < mov->nb_tracks; j++) {
8856 1 MOVTrack *trk = &mov->tracks[j];
8857
8858
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 if (trk->st == stg->entries[!lcevc->el_index]->stream) {
8859 1 track->src_track = av_malloc(sizeof(*track->src_track));
8860
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!track->src_track)
8861 ✗ return AVERROR(ENOMEM);
8862 1 *track->src_track = j;
8863 1 track->nb_src_track = 1;
8864 1 break;
8865 }
8866 }
8867
8868 1 track->par->width = lcevc->width;
8869 1 track->par->height = track->height = lcevc->height;
8870 1 break;
8871 }
8872 ✗ case AV_STREAM_GROUP_PARAMS_TREF: {
8873 ✗ const AVStreamGroupTREF *tref = stg->params.tref;
8874 MOVTrack *track;
8875
8876 ✗ if (tref->metadata_index >= stg->nb_entries)
8877 ✗ return AVERROR(EINVAL);
8878
8879 ✗ track = stg->entries[tref->metadata_index]->stream->priv_data;
8880 ✗ for (int j = 0; j < stg->nb_entries; j++) {
8881 ✗ const AVStream *st2 = stg->entries[j]->stream;
8882 ✗ int index = -1;
8883
8884 ✗ if (j == tref->metadata_index)
8885 ✗ continue;
8886
8887 ✗ for (int k = 0; k < mov->nb_tracks; k++) {
8888 ✗ if (mov->tracks[k].st != st2)
8889 ✗ continue;
8890 ✗ index = k;
8891 ✗ break;
8892 }
8893 ✗ if (index < 0)
8894 ✗ return AVERROR(EINVAL);
8895
8896 ✗ int *tmp = av_realloc(track->src_track,
8897 ✗ (track->nb_src_track + 1) * sizeof(*track->src_track));
8898 ✗ if (!tmp)
8899 ✗ return AVERROR(ENOMEM);
8900 ✗ track->src_track = tmp;
8901 ✗ track->src_track[track->nb_src_track++] = index;
8902 }
8903 ✗ break;
8904 }
8905 13 default:
8906 13 break;
8907 }
8908 }
8909
8910 /* fill src_track for tmcd tracks not covered by stream groups or
8911 * created by this muxer, retaining the old behavior of src_track
8912 * being arbitrarily 0. */
8913
2/2
✓ Branch 0 taken 447 times.
✓ Branch 1 taken 262 times.
709 for (i = 0; i < s->nb_streams; i++) {
8914 447 AVStream *st = s->streams[i];
8915 447 MOVTrack *track = st->priv_data;
8916
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 444 times.
447 if (st->codecpar->codec_tag != MKTAG('t','m','c','d') ||
8917
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 track->nb_src_track)
8918 444 continue;
8919
8920 3 track->src_track = av_malloc(sizeof(*track->src_track));
8921
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!track->src_track)
8922 ✗ return AVERROR(ENOMEM);
8923 3 *track->src_track = 0;
8924 3 track->nb_src_track = 1;
8925 }
8926
8927 262 enable_tracks(s);
8928 262 return 0;
8929 }
8930
8931 262 static int mov_write_header(AVFormatContext *s)
8932 {
8933 262 AVIOContext *pb = s->pb;
8934 262 MOVMuxContext *mov = s->priv_data;
8935 262 int ret, hint_track = 0, tmcd_track = 0, nb_tracks = mov->nb_streams;
8936
8937
4/4
✓ Branch 0 taken 255 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 254 times.
262 if (mov->mode & (MODE_MP4|MODE_MOV|MODE_IPOD) && s->nb_chapters)
8938 1 nb_tracks++;
8939
8940
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 261 times.
262 if (mov->flags & FF_MOV_FLAG_RTP_HINT) {
8941 1 hint_track = nb_tracks;
8942
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 for (int i = 0; i < mov->nb_streams; i++) {
8943
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (rtp_hinting_needed(mov->tracks[i].st))
8944 2 nb_tracks++;
8945 }
8946 }
8947
8948
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 256 times.
262 if (mov->nb_meta_tmcd)
8949 6 tmcd_track = nb_tracks;
8950
8951
2/2
✓ Branch 0 taken 425 times.
✓ Branch 1 taken 262 times.
687 for (int i = 0; i < mov->nb_streams; i++) {
8952 425 MOVTrack *track = &mov->tracks[i];
8953 425 AVStream *st = track->st;
8954
8955 /* copy extradata if it exists */
8956
2/2
✓ Branch 0 taken 157 times.
✓ Branch 1 taken 268 times.
425 if (st->codecpar->extradata_size) {
8957
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 157 times.
157 if (st->codecpar->codec_id == AV_CODEC_ID_DVD_SUBTITLE)
8958 ✗ mov_create_dvd_sub_decoder_specific_info(track, st);
8959
15/30
✓ Branch 0 taken 157 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 157 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 157 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 157 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 157 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 157 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 157 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 157 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 157 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 157 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 157 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 157 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 157 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 157 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 157 times.
✗ Branch 29 not taken.
157 else if (!TAG_IS_AVCI(track->tag) && st->codecpar->codec_id != AV_CODEC_ID_DNXHD) {
8960 157 track->extradata_size[track->last_stsd_index] = st->codecpar->extradata_size;
8961 314 track->extradata[track->last_stsd_index] =
8962 157 av_malloc(track->extradata_size[track->last_stsd_index] + AV_INPUT_BUFFER_PADDING_SIZE);
8963
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 157 times.
157 if (!track->extradata[track->last_stsd_index]) {
8964 ✗ return AVERROR(ENOMEM);
8965 }
8966 157 memcpy(track->extradata[track->last_stsd_index],
8967 157 st->codecpar->extradata, track->extradata_size[track->last_stsd_index]);
8968 157 memset(track->extradata[track->last_stsd_index] + track->extradata_size[track->last_stsd_index],
8969 0, AV_INPUT_BUFFER_PADDING_SIZE);
8970 }
8971 }
8972
8973
4/4
✓ Branch 0 taken 207 times.
✓ Branch 1 taken 218 times.
✓ Branch 2 taken 93 times.
✓ Branch 3 taken 114 times.
632 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO ||
8974 207 av_channel_layout_compare(&track->par->ch_layout,
8975 207 &(AVChannelLayout)AV_CHANNEL_LAYOUT_MONO))
8976 311 continue;
8977
8978
2/2
✓ Branch 0 taken 10032 times.
✓ Branch 1 taken 114 times.
10146 for (int j = 0; j < mov->nb_streams; j++) {
8979 10032 AVStream *stj= mov->tracks[j].st;
8980 10032 MOVTrack *trackj= &mov->tracks[j];
8981
2/2
✓ Branch 0 taken 114 times.
✓ Branch 1 taken 9918 times.
10032 if (j == i)
8982 114 continue;
8983
8984
2/2
✓ Branch 0 taken 9911 times.
✓ Branch 1 taken 7 times.
9918 if (stj->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
8985
4/4
✓ Branch 0 taken 9907 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 9900 times.
✓ Branch 3 taken 7 times.
19818 (trackj->par->ch_layout.nb_channels != 1 ||
8986 9907 !av_channel_layout_compare(&trackj->par->ch_layout,
8987 9907 &(AVChannelLayout)AV_CHANNEL_LAYOUT_MONO))
8988 )
8989 9904 track->mono_as_fc = -1;
8990
8991
4/4
✓ Branch 0 taken 9911 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 9900 times.
19829 if (stj->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
8992 9911 av_channel_layout_compare(&trackj->par->ch_layout,
8993 9911 &(AVChannelLayout)AV_CHANNEL_LAYOUT_MONO) &&
8994
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
11 trackj->par->ch_layout.nb_channels == 1 && track->mono_as_fc >= 0
8995 )
8996 7 track->mono_as_fc++;
8997
8998
4/4
✓ Branch 0 taken 9911 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 9900 times.
✓ Branch 3 taken 11 times.
19829 if (stj->codecpar->codec_type != AVMEDIA_TYPE_AUDIO ||
8999 9911 av_channel_layout_compare(&trackj->par->ch_layout,
9000 9911 &(AVChannelLayout)AV_CHANNEL_LAYOUT_MONO) ||
9001
1/2
✓ Branch 0 taken 9900 times.
✗ Branch 1 not taken.
9900 trackj->language != track->language ||
9002
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9900 times.
9900 trackj->tag != track->tag
9003 )
9004 18 continue;
9005 9900 track->multichannel_as_mono++;
9006 }
9007 }
9008
9009
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 240 times.
262 if (!(mov->flags & FF_MOV_FLAG_DELAY_MOOV) ||
9010
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 (mov->flags & FF_MOV_FLAG_HYBRID_FRAGMENTED)) {
9011
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 240 times.
240 if ((ret = mov_write_identification(pb, s)) < 0)
9012 ✗ return ret;
9013 }
9014
9015
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 259 times.
262 if (mov->reserved_moov_size){
9016 3 mov->reserved_header_pos = avio_tell(pb);
9017
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (mov->reserved_moov_size > 0)
9018 ✗ avio_skip(pb, mov->reserved_moov_size);
9019 }
9020
9021
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 214 times.
262 if (mov->flags & FF_MOV_FLAG_FRAGMENT) {
9022 /* If no fragmentation options have been set, set a default. */
9023
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 41 times.
48 if (!(mov->flags & (FF_MOV_FLAG_FRAG_KEYFRAME |
9024 FF_MOV_FLAG_FRAG_CUSTOM |
9025 7 FF_MOV_FLAG_FRAG_EVERY_FRAME)) &&
9026
3/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
7 !mov->max_fragment_duration && !mov->max_fragment_size)
9027 6 mov->flags |= FF_MOV_FLAG_FRAG_KEYFRAME;
9028
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 46 times.
48 if (mov->flags & FF_MOV_FLAG_HYBRID_FRAGMENTED) {
9029 2 avio_wb32(pb, 8); // placeholder for extended size field (64 bit)
9030
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 ffio_wfourcc(pb, mov->mode == MODE_MOV ? "wide" : "free");
9031 2 mov->mdat_pos = avio_tell(pb);
9032 // The free/wide header that later will be converted into an
9033 // mdat, covering the initial moov and all the fragments.
9034 2 avio_wb32(pb, 0);
9035
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 ffio_wfourcc(pb, mov->mode == MODE_MOV ? "wide" : "free");
9036 // Write an ftyp atom, hidden in a free/wide. This is neither
9037 // exposed while the file is written, as fragmented, nor when the
9038 // file is finalized into non-fragmented form. However, this allows
9039 // accessing a pristine, sequential ftyp+moov init segment, even
9040 // after the file is finalized. It also allows dumping the whole
9041 // contents of the mdat box, to get the fragmented form of the
9042 // file.
9043
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if ((ret = mov_write_identification(pb, s)) < 0)
9044 ✗ return ret;
9045 2 update_size(pb, mov->mdat_pos);
9046 }
9047
2/2
✓ Branch 0 taken 213 times.
✓ Branch 1 taken 1 times.
214 } else if (mov->mode != MODE_AVIF) {
9048
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 210 times.
213 if (mov->flags & FF_MOV_FLAG_FASTSTART)
9049 3 mov->reserved_header_pos = avio_tell(pb);
9050 213 mov_write_mdat_tag(pb, mov);
9051 }
9052
9053 262 ff_parse_creation_time_metadata(s, &mov->time, 1);
9054
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 262 times.
262 if (mov->time)
9055 ✗ mov->time += 0x7C25B080; // 1970 based -> 1904 based
9056
9057
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 261 times.
262 if (mov->chapter_track)
9058
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if ((ret = mov_create_chapter_track(s, mov->chapter_track)) < 0)
9059 ✗ return ret;
9060
9061
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 261 times.
262 if (mov->flags & FF_MOV_FLAG_RTP_HINT) {
9062
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 for (int i = 0; i < mov->nb_streams; i++) {
9063
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (rtp_hinting_needed(mov->tracks[i].st)) {
9064
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if ((ret = ff_mov_init_hinting(s, hint_track, i)) < 0)
9065 ✗ return ret;
9066 2 hint_track++;
9067 }
9068 }
9069 }
9070
9071
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 256 times.
262 if (mov->nb_meta_tmcd) {
9072 6 const AVDictionaryEntry *t, *global_tcr = av_dict_get(s->metadata,
9073 "timecode", NULL, 0);
9074 /* Initialize the tmcd tracks */
9075
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 6 times.
14 for (int i = 0; i < mov->nb_streams; i++) {
9076 8 AVStream *st = mov->tracks[i].st;
9077 8 t = global_tcr;
9078
9079
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
9080 AVTimecode tc;
9081
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!t)
9082 ✗ t = av_dict_get(st->metadata, "timecode", NULL, 0);
9083
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!t)
9084 ✗ continue;
9085
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if (mov_check_timecode_track(s, &tc, st, t->value) < 0)
9086 ✗ continue;
9087
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if ((ret = mov_create_timecode_track(s, tmcd_track, i, tc)) < 0)
9088 ✗ return ret;
9089 6 tmcd_track++;
9090 }
9091 }
9092 }
9093
9094 262 avio_flush(pb);
9095
9096
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 262 times.
262 if (mov->flags & FF_MOV_FLAG_ISML)
9097 ✗ mov_write_isml_manifest(pb, mov, s);
9098
9099
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 219 times.
262 if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV &&
9100
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 21 times.
43 !(mov->flags & FF_MOV_FLAG_DELAY_MOOV)) {
9101
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
22 if ((ret = mov_write_moov_tag(pb, mov, s)) < 0)
9102 ✗ return ret;
9103 22 mov->moov_written = 1;
9104
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX)
9105 ✗ mov->reserved_header_pos = avio_tell(pb);
9106 }
9107
9108 262 return 0;
9109 }
9110
9111 33 static int get_moov_size(AVFormatContext *s)
9112 {
9113 int ret;
9114 AVIOContext *moov_buf;
9115 33 MOVMuxContext *mov = s->priv_data;
9116
9117
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
33 if ((ret = ffio_open_null_buf(&moov_buf)) < 0)
9118 ✗ return ret;
9119
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
33 if ((ret = mov_write_moov_tag(moov_buf, mov, s)) < 0)
9120 ✗ return ret;
9121 33 return ffio_close_null_buf(moov_buf);
9122 }
9123
9124 ✗ static int get_sidx_size(AVFormatContext *s)
9125 {
9126 int ret;
9127 AVIOContext *buf;
9128 ✗ MOVMuxContext *mov = s->priv_data;
9129
9130 ✗ if ((ret = ffio_open_null_buf(&buf)) < 0)
9131 ✗ return ret;
9132 ✗ mov_write_sidx_tags(buf, mov, -1, 0);
9133 ✗ return ffio_close_null_buf(buf);
9134 }
9135
9136 /*
9137 * This function gets the moov size if moved to the top of the file: the chunk
9138 * offset table can switch between stco (32-bit entries) to co64 (64-bit
9139 * entries) when the moov is moved to the beginning, so the size of the moov
9140 * would change. It also updates the chunk offset tables.
9141 */
9142 3 static int compute_moov_size(AVFormatContext *s)
9143 {
9144 int i, moov_size, moov_size2;
9145 3 MOVMuxContext *mov = s->priv_data;
9146
9147 3 moov_size = get_moov_size(s);
9148
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (moov_size < 0)
9149 ✗ return moov_size;
9150
9151
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 3 times.
11 for (i = 0; i < mov->nb_tracks; i++)
9152 8 mov->tracks[i].data_offset += moov_size;
9153
9154 3 moov_size2 = get_moov_size(s);
9155
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (moov_size2 < 0)
9156 ✗ return moov_size2;
9157
9158 /* if the size changed, we just switched from stco to co64 and need to
9159 * update the offsets */
9160
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (moov_size2 != moov_size)
9161 ✗ for (i = 0; i < mov->nb_tracks; i++)
9162 ✗ mov->tracks[i].data_offset += moov_size2 - moov_size;
9163
9164 3 return moov_size2;
9165 }
9166
9167 ✗ static int compute_sidx_size(AVFormatContext *s)
9168 {
9169 int i, sidx_size;
9170 ✗ MOVMuxContext *mov = s->priv_data;
9171
9172 ✗ sidx_size = get_sidx_size(s);
9173 ✗ if (sidx_size < 0)
9174 ✗ return sidx_size;
9175
9176 ✗ for (i = 0; i < mov->nb_tracks; i++)
9177 ✗ mov->tracks[i].data_offset += sidx_size;
9178
9179 ✗ return sidx_size;
9180 }
9181
9182 3 static int shift_data(AVFormatContext *s)
9183 {
9184 int moov_size;
9185 3 MOVMuxContext *mov = s->priv_data;
9186
9187
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (mov->flags & FF_MOV_FLAG_FRAGMENT)
9188 ✗ moov_size = compute_sidx_size(s);
9189 else
9190 3 moov_size = compute_moov_size(s);
9191
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (moov_size < 0)
9192 ✗ return moov_size;
9193
9194 3 return ff_format_shift_data(s, mov->reserved_header_pos, moov_size);
9195 }
9196
9197 215 static void mov_write_mdat_size(AVFormatContext *s)
9198 {
9199 215 MOVMuxContext *mov = s->priv_data;
9200 215 AVIOContext *pb = s->pb;
9201
9202 /* Write size of mdat tag */
9203
1/2
✓ Branch 0 taken 215 times.
✗ Branch 1 not taken.
215 if (mov->mdat_size + 8 <= UINT32_MAX) {
9204 215 avio_seek(pb, mov->mdat_pos, SEEK_SET);
9205 215 avio_wb32(pb, mov->mdat_size + 8);
9206
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 213 times.
215 if (mov->flags & FF_MOV_FLAG_HYBRID_FRAGMENTED)
9207 2 ffio_wfourcc(pb, "mdat"); // overwrite the original free/wide into a mdat
9208 } else {
9209 /* overwrite 'wide' placeholder atom */
9210 ✗ avio_seek(pb, mov->mdat_pos - 8, SEEK_SET);
9211 /* special value: real atom size will be 64 bit value after
9212 * tag field */
9213 ✗ avio_wb32(pb, 1);
9214 ✗ ffio_wfourcc(pb, "mdat");
9215 ✗ avio_wb64(pb, mov->mdat_size + 16);
9216 }
9217 215 }
9218
9219 261 static int mov_write_trailer(AVFormatContext *s)
9220 {
9221 261 MOVMuxContext *mov = s->priv_data;
9222 261 AVIOContext *pb = s->pb;
9223 261 int res = 0;
9224 int i;
9225 int64_t moov_pos;
9226
9227 /*
9228 * Before actually writing the trailer, make sure that there are no
9229 * dangling subtitles, that need a terminating sample.
9230 */
9231
2/2
✓ Branch 0 taken 433 times.
✓ Branch 1 taken 261 times.
694 for (i = 0; i < mov->nb_tracks; i++) {
9232 433 MOVTrack *trk = &mov->tracks[i];
9233
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 432 times.
433 if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT &&
9234
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 !trk->last_sample_is_subtitle_end) {
9235 1 mov_write_subtitle_end_packet(s, i, trk->track_duration);
9236 1 trk->last_sample_is_subtitle_end = 1;
9237 }
9238 }
9239
9240 //Also check for a buffered EAC3 packet
9241
2/2
✓ Branch 0 taken 433 times.
✓ Branch 1 taken 261 times.
694 for (i = 0; i < mov->nb_tracks; i++) {
9242 433 MOVTrack *trk = &mov->tracks[i];
9243
2/2
✓ Branch 0 taken 429 times.
✓ Branch 1 taken 4 times.
433 if (trk->par->codec_id != AV_CODEC_ID_EAC3)
9244 429 continue;
9245 4 struct eac3_info *info = trk->eac3_priv;
9246
3/6
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
4 if (!info || !info->pkt || !info->pkt->size)
9247 4 continue;
9248
9249 ✗ av_packet_move_ref(mov->pkt, info->pkt);
9250 ✗ info->eof = 1;
9251 ✗ res = mov_write_single_packet(s, mov->pkt);
9252 ✗ if (res < 0)
9253 ✗ return res;
9254
9255 ✗ av_packet_unref(mov->pkt);
9256 }
9257
9258 // Check if we have any tracks that require squashing.
9259 // In that case, we'll have to write the packet here.
9260
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 261 times.
261 if ((res = mov_write_squashed_packets(s)) < 0)
9261 ✗ return res;
9262
9263 // If there were no chapters when the header was written, but there
9264 // are chapters now, write them in the trailer. This only works
9265 // when we are not doing fragments.
9266
4/4
✓ Branch 0 taken 260 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 212 times.
✓ Branch 3 taken 48 times.
261 if (!mov->chapter_track && !(mov->flags & FF_MOV_FLAG_FRAGMENT)) {
9267
3/4
✓ Branch 0 taken 211 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 211 times.
212 if (mov->mode & (MODE_MP4|MODE_MOV|MODE_IPOD) && s->nb_chapters) {
9268 ✗ mov->chapter_track = mov->nb_tracks++;
9269 ✗ if ((res = mov_create_chapter_track(s, mov->chapter_track)) < 0)
9270 ✗ return res;
9271 }
9272 }
9273
9274
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 213 times.
261 if (!(mov->flags & FF_MOV_FLAG_FRAGMENT) ||
9275
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 46 times.
48 mov->flags & FF_MOV_FLAG_HYBRID_FRAGMENTED) {
9276
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 213 times.
215 if (mov->flags & FF_MOV_FLAG_HYBRID_FRAGMENTED) {
9277 2 mov_auto_flush_fragment(s, 1);
9278 2 mov->mdat_size = avio_tell(pb) - mov->mdat_pos - 8;
9279
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (i = 0; i < mov->nb_tracks; i++) {
9280 4 MOVTrack *track = &mov->tracks[i];
9281 4 track->data_offset = 0;
9282 4 av_free(track->cluster);
9283 4 track->cluster = track->cluster_written;
9284 4 track->entry = track->entry_written;
9285 4 track->cluster_written = NULL;
9286 4 track->entry_written = 0;
9287 4 track->chunkCount = 0; // Force build_chunks to rebuild the list of chunks
9288 }
9289 // Clear the empty_moov flag, as we do want the moov to include
9290 // all the samples at this point.
9291 2 mov->flags &= ~FF_MOV_FLAG_EMPTY_MOOV;
9292 }
9293
9294 215 moov_pos = avio_tell(pb);
9295
9296
2/2
✓ Branch 0 taken 213 times.
✓ Branch 1 taken 2 times.
215 if (!(mov->flags & FF_MOV_FLAG_HYBRID_FRAGMENTED))
9297 213 mov_write_mdat_size(s);
9298
9299
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 215 times.
215 avio_seek(pb, mov->reserved_moov_size > 0 ? mov->reserved_header_pos : moov_pos, SEEK_SET);
9300
9301
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 212 times.
215 if (mov->flags & FF_MOV_FLAG_FASTSTART) {
9302 3 av_log(s, AV_LOG_INFO, "Starting second pass: moving the moov atom to the beginning of the file\n");
9303 3 res = shift_data(s);
9304
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (res < 0)
9305 ✗ return res;
9306 3 avio_seek(pb, mov->reserved_header_pos, SEEK_SET);
9307
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if ((res = mov_write_moov_tag(pb, mov, s)) < 0)
9308 ✗ return res;
9309
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 212 times.
212 } else if (mov->reserved_moov_size > 0) {
9310 int64_t size;
9311 ✗ if ((res = mov_write_moov_tag(pb, mov, s)) < 0)
9312 ✗ return res;
9313 ✗ size = mov->reserved_moov_size - (avio_tell(pb) - mov->reserved_header_pos);
9314 ✗ if (size < 8){
9315 ✗ av_log(s, AV_LOG_ERROR, "reserved_moov_size is too small, needed %"PRId64" additional\n", 8-size);
9316 ✗ return AVERROR(EINVAL);
9317 }
9318 ✗ avio_wb32(pb, size);
9319 ✗ ffio_wfourcc(pb, "free");
9320 ✗ ffio_fill(pb, 0, size - 8);
9321 ✗ avio_seek(pb, moov_pos, SEEK_SET);
9322 } else {
9323
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 212 times.
212 if ((res = mov_write_moov_tag(pb, mov, s)) < 0)
9324 ✗ return res;
9325 }
9326
9327
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 213 times.
215 if (mov->flags & FF_MOV_FLAG_HYBRID_FRAGMENTED) {
9328 // With hybrid fragmentation, only write the mdat size (hiding
9329 // the original moov and all the fragments within the mdat)
9330 // after we've successfully written the complete moov, to avoid
9331 // risk for an unreadable file if writing the final moov fails.
9332 2 mov_write_mdat_size(s);
9333 }
9334
9335 215 res = 0;
9336 } else {
9337 46 mov_auto_flush_fragment(s, 1);
9338
2/2
✓ Branch 0 taken 178 times.
✓ Branch 1 taken 46 times.
224 for (i = 0; i < mov->nb_tracks; i++)
9339 178 mov->tracks[i].data_offset = 0;
9340
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX) {
9341 int64_t end;
9342 ✗ av_log(s, AV_LOG_INFO, "Starting second pass: inserting sidx atoms\n");
9343 ✗ res = shift_data(s);
9344 ✗ if (res < 0)
9345 ✗ return res;
9346 ✗ end = avio_tell(pb);
9347 ✗ avio_seek(pb, mov->reserved_header_pos, SEEK_SET);
9348 ✗ mov_write_sidx_tags(pb, mov, -1, 0);
9349 ✗ avio_seek(pb, end, SEEK_SET);
9350 }
9351
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 1 times.
46 if (!(mov->flags & FF_MOV_FLAG_SKIP_TRAILER)) {
9352 45 avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_TRAILER);
9353 45 res = mov_write_mfra_tag(pb, mov);
9354
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 if (res < 0)
9355 ✗ return res;
9356 }
9357 }
9358
9359 261 return res;
9360 }
9361
9362 274 static int mov_check_bitstream(AVFormatContext *s, AVStream *st,
9363 const AVPacket *pkt)
9364 {
9365 274 int ret = 1;
9366
9367
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 253 times.
274 if (st->codecpar->codec_id == AV_CODEC_ID_AAC) {
9368
2/4
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 21 times.
21 if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0)
9369 ✗ ret = ff_stream_add_bitstream_filter(st, "aac_adtstoasc", NULL);
9370
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 253 times.
253 } else if (st->codecpar->codec_id == AV_CODEC_ID_VP9) {
9371 ✗ ret = ff_stream_add_bitstream_filter(st, "vp9_superframe", NULL);
9372 }
9373
9374 274 return ret;
9375 }
9376
9377 #if CONFIG_AVIF_MUXER
9378 1 static int avif_write_trailer(AVFormatContext *s)
9379 {
9380 1 AVIOContext *pb = s->pb;
9381 1 MOVMuxContext *mov = s->priv_data;
9382 int64_t pos_backup, extent_offsets[2];
9383 uint8_t *buf;
9384 int buf_size, moov_size;
9385
9386
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (mov->moov_written) return 0;
9387
9388 1 mov->is_animated_avif = s->streams[0]->nb_frames > 1;
9389
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 if (mov->is_animated_avif && mov->nb_streams > 1) {
9390 // For animated avif with alpha channel, we need to write a tref tag
9391 // with type "auxl".
9392 ✗ MovTag *tag = mov_add_tref_tag(mov, &mov->tracks[1], MKTAG('a', 'u', 'x', 'l'));
9393 ✗ if (!tag)
9394 ✗ return AVERROR(ENOMEM);
9395
9396 ✗ int ret = mov_add_tref_id(mov, tag, 1);
9397 ✗ if (ret < 0)
9398 ✗ return ret;
9399 }
9400 1 mov_write_identification(pb, s);
9401 1 mov_write_meta_tag(pb, mov, s);
9402
9403 1 moov_size = get_moov_size(s);
9404
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 for (int i = 0; i < mov->nb_tracks; i++)
9405 1 mov->tracks[i].data_offset = avio_tell(pb) + moov_size + 8;
9406
9407
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (mov->is_animated_avif) {
9408 int ret;
9409 ✗ if ((ret = mov_write_moov_tag(pb, mov, s)) < 0)
9410 ✗ return ret;
9411 }
9412
9413 1 buf_size = avio_get_dyn_buf(mov->mdat_buf, &buf);
9414 1 avio_wb32(pb, buf_size + 8);
9415 1 ffio_wfourcc(pb, "mdat");
9416
9417 // The offset for the YUV planes is the starting position of mdat.
9418 1 extent_offsets[0] = avio_tell(pb);
9419 // The offset for alpha plane is YUV offset + YUV size.
9420 1 extent_offsets[1] = extent_offsets[0] + mov->avif_extent_length[0];
9421
9422 1 avio_write(pb, buf, buf_size);
9423
9424 // write extent offsets.
9425 1 pos_backup = avio_tell(pb);
9426
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 for (int i = 0; i < mov->nb_streams; i++) {
9427
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (extent_offsets[i] != (uint32_t)extent_offsets[i]) {
9428 ✗ av_log(s, AV_LOG_ERROR, "extent offset does not fit in 32 bits\n");
9429 ✗ return AVERROR_INVALIDDATA;
9430 }
9431 1 avio_seek(pb, mov->avif_extent_pos[i], SEEK_SET);
9432 1 avio_wb32(pb, extent_offsets[i]); /* rewrite offset */
9433 }
9434 1 avio_seek(pb, pos_backup, SEEK_SET);
9435
9436 1 return 0;
9437 }
9438 #endif
9439
9440 #if CONFIG_TGP_MUXER || CONFIG_TG2_MUXER
9441 static const AVCodecTag codec_3gp_tags[] = {
9442 { AV_CODEC_ID_H263, MKTAG('s','2','6','3') },
9443 { AV_CODEC_ID_H264, MKTAG('a','v','c','1') },
9444 { AV_CODEC_ID_MPEG4, MKTAG('m','p','4','v') },
9445 { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') },
9446 { AV_CODEC_ID_AMR_NB, MKTAG('s','a','m','r') },
9447 { AV_CODEC_ID_AMR_WB, MKTAG('s','a','w','b') },
9448 { AV_CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') },
9449 { AV_CODEC_ID_NONE, 0 },
9450 };
9451 static const AVCodecTag *const codec_3gp_tags_list[] = { codec_3gp_tags, NULL };
9452 #endif
9453
9454 static const AVCodecTag codec_mp4_tags[] = {
9455 { AV_CODEC_ID_MPEG4, MKTAG('m', 'p', '4', 'v') },
9456 { AV_CODEC_ID_H264, MKTAG('a', 'v', 'c', '1') },
9457 { AV_CODEC_ID_H264, MKTAG('a', 'v', 'c', '3') },
9458 { AV_CODEC_ID_HEVC, MKTAG('h', 'e', 'v', '1') },
9459 { AV_CODEC_ID_HEVC, MKTAG('h', 'v', 'c', '1') },
9460 { AV_CODEC_ID_HEVC, MKTAG('d', 'v', 'h', '1') },
9461 { AV_CODEC_ID_VVC, MKTAG('v', 'v', 'c', '1') },
9462 { AV_CODEC_ID_VVC, MKTAG('v', 'v', 'i', '1') },
9463 { AV_CODEC_ID_EVC, MKTAG('e', 'v', 'c', '1') },
9464 { AV_CODEC_ID_LCEVC, MKTAG('l', 'v', 'c', '1') },
9465 { AV_CODEC_ID_APV, MKTAG('a', 'p', 'v', '1') },
9466 { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'p', '4', 'v') },
9467 { AV_CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', '4', 'v') },
9468 { AV_CODEC_ID_MJPEG, MKTAG('m', 'p', '4', 'v') },
9469 { AV_CODEC_ID_PNG, MKTAG('m', 'p', '4', 'v') },
9470 { AV_CODEC_ID_JPEG2000, MKTAG('m', 'p', '4', 'v') },
9471 { AV_CODEC_ID_VC1, MKTAG('v', 'c', '-', '1') },
9472 { AV_CODEC_ID_DIRAC, MKTAG('d', 'r', 'a', 'c') },
9473 { AV_CODEC_ID_TSCC2, MKTAG('m', 'p', '4', 'v') },
9474 { AV_CODEC_ID_VP9, MKTAG('v', 'p', '0', '9') },
9475 { AV_CODEC_ID_AV1, MKTAG('a', 'v', '0', '1') },
9476 { AV_CODEC_ID_AV1, MKTAG('d', 'a', 'v', '1') },
9477 { AV_CODEC_ID_AAC, MKTAG('m', 'p', '4', 'a') },
9478 { AV_CODEC_ID_APPLE_APAC, MKTAG('a', 'p', 'a', 'c') },
9479 { AV_CODEC_ID_ALAC, MKTAG('a', 'l', 'a', 'c') },
9480 { AV_CODEC_ID_MP4ALS, MKTAG('m', 'p', '4', 'a') },
9481 { AV_CODEC_ID_MP3, MKTAG('m', 'p', '4', 'a') },
9482 { AV_CODEC_ID_MP2, MKTAG('m', 'p', '4', 'a') },
9483 { AV_CODEC_ID_AC3, MKTAG('a', 'c', '-', '3') },
9484 { AV_CODEC_ID_EAC3, MKTAG('e', 'c', '-', '3') },
9485 { AV_CODEC_ID_DTS, MKTAG('m', 'p', '4', 'a') },
9486 { AV_CODEC_ID_TRUEHD, MKTAG('m', 'l', 'p', 'a') },
9487 { AV_CODEC_ID_FLAC, MKTAG('f', 'L', 'a', 'C') },
9488 { AV_CODEC_ID_OPUS, MKTAG('O', 'p', 'u', 's') },
9489 { AV_CODEC_ID_VORBIS, MKTAG('m', 'p', '4', 'a') },
9490 { AV_CODEC_ID_QCELP, MKTAG('m', 'p', '4', 'a') },
9491 { AV_CODEC_ID_EVRC, MKTAG('m', 'p', '4', 'a') },
9492 { AV_CODEC_ID_DVD_SUBTITLE, MKTAG('m', 'p', '4', 's') },
9493 { AV_CODEC_ID_MOV_TEXT, MKTAG('t', 'x', '3', 'g') },
9494 { AV_CODEC_ID_BIN_DATA, MKTAG('g', 'p', 'm', 'd') },
9495 { AV_CODEC_ID_MPEGH_3D_AUDIO, MKTAG('m', 'h', 'm', '1') },
9496 { AV_CODEC_ID_TTML, MOV_MP4_TTML_TAG },
9497 { AV_CODEC_ID_TTML, MOV_ISMV_TTML_TAG },
9498 { AV_CODEC_ID_FFV1, MKTAG('F', 'F', 'V', '1') },
9499
9500 /* ISO/IEC 23003-5 integer formats */
9501 { AV_CODEC_ID_PCM_S16BE, MOV_MP4_IPCM_TAG },
9502 { AV_CODEC_ID_PCM_S16LE, MOV_MP4_IPCM_TAG },
9503 { AV_CODEC_ID_PCM_S24BE, MOV_MP4_IPCM_TAG },
9504 { AV_CODEC_ID_PCM_S24LE, MOV_MP4_IPCM_TAG },
9505 { AV_CODEC_ID_PCM_S32BE, MOV_MP4_IPCM_TAG },
9506 { AV_CODEC_ID_PCM_S32LE, MOV_MP4_IPCM_TAG },
9507 /* ISO/IEC 23003-5 floating-point formats */
9508 { AV_CODEC_ID_PCM_F32BE, MOV_MP4_FPCM_TAG },
9509 { AV_CODEC_ID_PCM_F32LE, MOV_MP4_FPCM_TAG },
9510 { AV_CODEC_ID_PCM_F64BE, MOV_MP4_FPCM_TAG },
9511 { AV_CODEC_ID_PCM_F64LE, MOV_MP4_FPCM_TAG },
9512
9513 { AV_CODEC_ID_AVS3, MKTAG('a', 'v', 's', '3') },
9514
9515 { AV_CODEC_ID_NONE, 0 },
9516 };
9517 #if CONFIG_MP4_MUXER || CONFIG_PSP_MUXER
9518 static const AVCodecTag *const mp4_codec_tags_list[] = { codec_mp4_tags, NULL };
9519 #endif
9520
9521 static const AVCodecTag codec_ism_tags[] = {
9522 { AV_CODEC_ID_WMAPRO , MKTAG('w', 'm', 'a', ' ') },
9523 { AV_CODEC_ID_TTML , MOV_ISMV_TTML_TAG },
9524 { AV_CODEC_ID_NONE , 0 },
9525 };
9526
9527 static const AVCodecTag codec_ipod_tags[] = {
9528 { AV_CODEC_ID_H264, MKTAG('a','v','c','1') },
9529 { AV_CODEC_ID_MPEG4, MKTAG('m','p','4','v') },
9530 { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') },
9531 { AV_CODEC_ID_ALAC, MKTAG('a','l','a','c') },
9532 { AV_CODEC_ID_AC3, MKTAG('a','c','-','3') },
9533 { AV_CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') },
9534 { AV_CODEC_ID_MOV_TEXT, MKTAG('t','e','x','t') },
9535 { AV_CODEC_ID_NONE, 0 },
9536 };
9537
9538 static const AVCodecTag codec_f4v_tags[] = {
9539 { AV_CODEC_ID_MP3, MKTAG('.','m','p','3') },
9540 { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') },
9541 { AV_CODEC_ID_H264, MKTAG('a','v','c','1') },
9542 { AV_CODEC_ID_VP6A, MKTAG('V','P','6','A') },
9543 { AV_CODEC_ID_VP6F, MKTAG('V','P','6','F') },
9544 { AV_CODEC_ID_NONE, 0 },
9545 };
9546
9547 #if CONFIG_AVIF_MUXER
9548
9549 static const AVOption avif_options[] = {
9550 { "movie_timescale", "set movie timescale", offsetof(MOVMuxContext, movie_timescale), AV_OPT_TYPE_INT, {.i64 = MOV_TIMESCALE}, 1, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
9551 { "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 },
9552 { NULL },
9553 };
9554 static const AVCodecTag codec_avif_tags[] = {
9555 { AV_CODEC_ID_AV1, MKTAG('a','v','0','1') },
9556 { AV_CODEC_ID_NONE, 0 },
9557 };
9558 static const AVCodecTag *const codec_avif_tags_list[] = { codec_avif_tags, NULL };
9559
9560 static const AVClass mov_avif_muxer_class = {
9561 .class_name = "avif muxer",
9562 .item_name = av_default_item_name,
9563 .option = avif_options,
9564 .version = LIBAVUTIL_VERSION_INT,
9565 };
9566 #endif
9567
9568 #if CONFIG_MOV_MUXER
9569 const FFOutputFormat ff_mov_muxer = {
9570 .p.name = "mov",
9571 .p.long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
9572 .p.extensions = "mov",
9573 .priv_data_size = sizeof(MOVMuxContext),
9574 .p.audio_codec = AV_CODEC_ID_AAC,
9575 .p.video_codec = CONFIG_LIBX264_ENCODER ?
9576 AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4,
9577 .init = mov_init,
9578 .write_header = mov_write_header,
9579 .write_packet = mov_write_packet,
9580 .write_trailer = mov_write_trailer,
9581 .deinit = mov_free,
9582 .p.flags = AVFMT_GLOBALHEADER | AVFMT_TS_NEGATIVE | AVFMT_VARIABLE_FPS,
9583 .p.codec_tag = (const AVCodecTag* const []){
9584 ff_codec_movvideo_tags, ff_codec_movaudio_tags, ff_codec_movsubtitle_tags, 0
9585 },
9586 .check_bitstream = mov_check_bitstream,
9587 .p.priv_class = &mov_isobmff_muxer_class,
9588 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
9589 };
9590 #endif
9591 #if CONFIG_TGP_MUXER
9592 const FFOutputFormat ff_tgp_muxer = {
9593 .p.name = "3gp",
9594 .p.long_name = NULL_IF_CONFIG_SMALL("3GP (3GPP file format)"),
9595 .p.extensions = "3gp",
9596 .priv_data_size = sizeof(MOVMuxContext),
9597 .p.audio_codec = AV_CODEC_ID_AMR_NB,
9598 .p.video_codec = AV_CODEC_ID_H263,
9599 .init = mov_init,
9600 .write_header = mov_write_header,
9601 .write_packet = mov_write_packet,
9602 .write_trailer = mov_write_trailer,
9603 .deinit = mov_free,
9604 .p.flags = AVFMT_GLOBALHEADER | AVFMT_TS_NEGATIVE,
9605 .p.codec_tag = codec_3gp_tags_list,
9606 .check_bitstream = mov_check_bitstream,
9607 .p.priv_class = &mov_isobmff_muxer_class,
9608 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
9609 };
9610 #endif
9611 #if CONFIG_MP4_MUXER
9612 const FFOutputFormat ff_mp4_muxer = {
9613 .p.name = "mp4",
9614 .p.long_name = NULL_IF_CONFIG_SMALL("MP4 (MPEG-4 Part 14)"),
9615 .p.mime_type = "video/mp4",
9616 .p.extensions = "mp4",
9617 .priv_data_size = sizeof(MOVMuxContext),
9618 .p.audio_codec = AV_CODEC_ID_AAC,
9619 .p.video_codec = CONFIG_LIBX264_ENCODER ?
9620 AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4,
9621 .init = mov_init,
9622 .write_header = mov_write_header,
9623 .write_packet = mov_write_packet,
9624 .write_trailer = mov_write_trailer,
9625 .deinit = mov_free,
9626 .p.flags = AVFMT_GLOBALHEADER | AVFMT_TS_NEGATIVE | AVFMT_VARIABLE_FPS,
9627 .p.codec_tag = mp4_codec_tags_list,
9628 .check_bitstream = mov_check_bitstream,
9629 .p.priv_class = &mov_isobmff_muxer_class,
9630 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
9631 };
9632 #endif
9633 #if CONFIG_PSP_MUXER
9634 const FFOutputFormat ff_psp_muxer = {
9635 .p.name = "psp",
9636 .p.long_name = NULL_IF_CONFIG_SMALL("PSP MP4 (MPEG-4 Part 14)"),
9637 .p.extensions = "mp4,psp",
9638 .priv_data_size = sizeof(MOVMuxContext),
9639 .p.audio_codec = AV_CODEC_ID_AAC,
9640 .p.video_codec = CONFIG_LIBX264_ENCODER ?
9641 AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4,
9642 .init = mov_init,
9643 .write_header = mov_write_header,
9644 .write_packet = mov_write_packet,
9645 .write_trailer = mov_write_trailer,
9646 .deinit = mov_free,
9647 .p.flags = AVFMT_GLOBALHEADER | AVFMT_TS_NEGATIVE,
9648 .p.codec_tag = mp4_codec_tags_list,
9649 .check_bitstream = mov_check_bitstream,
9650 .p.priv_class = &mov_isobmff_muxer_class,
9651 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
9652 };
9653 #endif
9654 #if CONFIG_TG2_MUXER
9655 const FFOutputFormat ff_tg2_muxer = {
9656 .p.name = "3g2",
9657 .p.long_name = NULL_IF_CONFIG_SMALL("3GP2 (3GPP2 file format)"),
9658 .p.extensions = "3g2",
9659 .priv_data_size = sizeof(MOVMuxContext),
9660 .p.audio_codec = AV_CODEC_ID_AMR_NB,
9661 .p.video_codec = AV_CODEC_ID_H263,
9662 .init = mov_init,
9663 .write_header = mov_write_header,
9664 .write_packet = mov_write_packet,
9665 .write_trailer = mov_write_trailer,
9666 .deinit = mov_free,
9667 .p.flags = AVFMT_GLOBALHEADER | AVFMT_TS_NEGATIVE,
9668 .p.codec_tag = codec_3gp_tags_list,
9669 .check_bitstream = mov_check_bitstream,
9670 .p.priv_class = &mov_isobmff_muxer_class,
9671 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
9672 };
9673 #endif
9674 #if CONFIG_IPOD_MUXER
9675 const FFOutputFormat ff_ipod_muxer = {
9676 .p.name = "ipod",
9677 .p.long_name = NULL_IF_CONFIG_SMALL("iPod H.264 MP4 (MPEG-4 Part 14)"),
9678 .p.mime_type = "video/mp4",
9679 .p.extensions = "m4v,m4a,m4b",
9680 .priv_data_size = sizeof(MOVMuxContext),
9681 .p.audio_codec = AV_CODEC_ID_AAC,
9682 .p.video_codec = AV_CODEC_ID_H264,
9683 .init = mov_init,
9684 .write_header = mov_write_header,
9685 .write_packet = mov_write_packet,
9686 .write_trailer = mov_write_trailer,
9687 .deinit = mov_free,
9688 .p.flags = AVFMT_GLOBALHEADER | AVFMT_TS_NEGATIVE,
9689 .p.codec_tag = (const AVCodecTag* const []){ codec_ipod_tags, 0 },
9690 .check_bitstream = mov_check_bitstream,
9691 .p.priv_class = &mov_isobmff_muxer_class,
9692 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
9693 };
9694 #endif
9695 #if CONFIG_ISMV_MUXER
9696 const FFOutputFormat ff_ismv_muxer = {
9697 .p.name = "ismv",
9698 .p.long_name = NULL_IF_CONFIG_SMALL("ISMV/ISMA (Smooth Streaming)"),
9699 .p.mime_type = "video/mp4",
9700 .p.extensions = "ismv,isma",
9701 .priv_data_size = sizeof(MOVMuxContext),
9702 .p.audio_codec = AV_CODEC_ID_AAC,
9703 .p.video_codec = AV_CODEC_ID_H264,
9704 .init = mov_init,
9705 .write_header = mov_write_header,
9706 .write_packet = mov_write_packet,
9707 .write_trailer = mov_write_trailer,
9708 .deinit = mov_free,
9709 .p.flags = AVFMT_GLOBALHEADER | AVFMT_TS_NEGATIVE,
9710 .p.codec_tag = (const AVCodecTag* const []){
9711 codec_mp4_tags, codec_ism_tags, 0 },
9712 .check_bitstream = mov_check_bitstream,
9713 .p.priv_class = &mov_isobmff_muxer_class,
9714 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
9715 };
9716 #endif
9717 #if CONFIG_F4V_MUXER
9718 const FFOutputFormat ff_f4v_muxer = {
9719 .p.name = "f4v",
9720 .p.long_name = NULL_IF_CONFIG_SMALL("F4V Adobe Flash Video"),
9721 .p.mime_type = "application/f4v",
9722 .p.extensions = "f4v",
9723 .priv_data_size = sizeof(MOVMuxContext),
9724 .p.audio_codec = AV_CODEC_ID_AAC,
9725 .p.video_codec = AV_CODEC_ID_H264,
9726 .init = mov_init,
9727 .write_header = mov_write_header,
9728 .write_packet = mov_write_packet,
9729 .write_trailer = mov_write_trailer,
9730 .deinit = mov_free,
9731 .p.flags = AVFMT_GLOBALHEADER,
9732 .p.codec_tag = (const AVCodecTag* const []){ codec_f4v_tags, 0 },
9733 .check_bitstream = mov_check_bitstream,
9734 .p.priv_class = &mov_isobmff_muxer_class,
9735 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
9736 };
9737 #endif
9738 #if CONFIG_AVIF_MUXER
9739 const FFOutputFormat ff_avif_muxer = {
9740 .p.name = "avif",
9741 .p.long_name = NULL_IF_CONFIG_SMALL("AVIF"),
9742 .p.mime_type = "image/avif",
9743 .p.extensions = "avif",
9744 .priv_data_size = sizeof(MOVMuxContext),
9745 .p.video_codec = AV_CODEC_ID_AV1,
9746 .init = mov_init,
9747 .write_header = mov_write_header,
9748 .write_packet = mov_write_packet,
9749 .write_trailer = avif_write_trailer,
9750 .deinit = mov_free,
9751 .p.flags = AVFMT_GLOBALHEADER,
9752 .p.codec_tag = codec_avif_tags_list,
9753 .p.priv_class = &mov_avif_muxer_class,
9754 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
9755 };
9756 #endif
9757