FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/movenc.c
Date: 2024-07-26 21:54:09
Exec Total Coverage
Lines: 3553 5317 66.8%
Functions: 171 223 76.7%
Branches: 2068 3633 56.9%

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 <stdint.h>
27 #include <inttypes.h>
28
29 #include "movenc.h"
30 #include "avformat.h"
31 #include "avio_internal.h"
32 #include "dovi_isom.h"
33 #include "riff.h"
34 #include "avio.h"
35 #include "iamf_writer.h"
36 #include "isom.h"
37 #include "av1.h"
38 #include "avc.h"
39 #include "evc.h"
40 #include "libavcodec/ac3_parser_internal.h"
41 #include "libavcodec/dnxhddata.h"
42 #include "libavcodec/flac.h"
43 #include "libavcodec/get_bits.h"
44
45 #include "libavcodec/internal.h"
46 #include "libavcodec/put_bits.h"
47 #include "libavcodec/vc1_common.h"
48 #include "libavcodec/raw.h"
49 #include "internal.h"
50 #include "libavutil/avstring.h"
51 #include "libavutil/channel_layout.h"
52 #include "libavutil/csp.h"
53 #include "libavutil/intfloat.h"
54 #include "libavutil/mathematics.h"
55 #include "libavutil/libm.h"
56 #include "libavutil/mem.h"
57 #include "libavutil/opt.h"
58 #include "libavutil/dict.h"
59 #include "libavutil/pixdesc.h"
60 #include "libavutil/stereo3d.h"
61 #include "libavutil/timecode.h"
62 #include "libavutil/dovi_meta.h"
63 #include "libavutil/uuid.h"
64 #include "hevc.h"
65 #include "rtpenc.h"
66 #include "nal.h"
67 #include "mov_chan.h"
68 #include "movenc_ttml.h"
69 #include "mux.h"
70 #include "rawutils.h"
71 #include "ttmlenc.h"
72 #include "version.h"
73 #include "vpcc.h"
74 #include "vvc.h"
75
76 static const AVOption options[] = {
77 { "brand", "Override major brand", offsetof(MOVMuxContext, major_brand), AV_OPT_TYPE_STRING, {.str = NULL}, .flags = AV_OPT_FLAG_ENCODING_PARAM },
78 { "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},
79 { "encryption_key", "The media encryption key (hex)", offsetof(MOVMuxContext, encryption_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_ENCODING_PARAM },
80 { "encryption_kid", "The media encryption key identifier (hex)", offsetof(MOVMuxContext, encryption_kid), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_ENCODING_PARAM },
81 { "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 },
82 { "frag_duration", "Maximum fragment duration", offsetof(MOVMuxContext, max_fragment_duration), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
83 { "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 },
84 { "frag_size", "Maximum fragment size", offsetof(MOVMuxContext, max_fragment_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
85 { "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},
86 { "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},
87 { "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},
88 { "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},
89 { "movflags", "MOV muxer flags", offsetof(MOVMuxContext, flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, .unit = "movflags" },
90 { "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" },
91 { "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" },
92 { "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" },
93 { "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" },
94 { "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" },
95 { "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" },
96 { "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" },
97 { "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" },
98 { "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" },
99 { "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" },
100 { "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" },
101 { "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" },
102 { "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" },
103 { "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 },
104 { "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" },
105 { "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" },
106 { "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" },
107 { "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" },
108 { "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" },
109 { "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" },
110 { "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" },
111 { "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" },
112 { "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" },
113 { "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" },
114 { "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" },
115 { "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},
116 { "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},
117 { "movie_timescale", "set movie timescale", offsetof(MOVMuxContext, movie_timescale), AV_OPT_TYPE_INT, {.i64 = MOV_TIMESCALE}, 1, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
118 FF_RTP_FLAG_OPTS(MOVMuxContext, rtp_flags),
119 { "skip_iods", "Skip writing iods atom.", offsetof(MOVMuxContext, iods_skip), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
120 { "use_editlist", "use edit list", offsetof(MOVMuxContext, use_editlist), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM},
121 { "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},
122 { "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},
123 { "write_btrt", "force or disable writing btrt", offsetof(MOVMuxContext, write_btrt), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM},
124 { "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"},
125 { "pts", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = MOV_PRFT_SRC_PTS}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM, .unit = "prft"},
126 { "wallclock", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = MOV_PRFT_SRC_WALLCLOCK}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM, .unit = "prft"},
127 { "write_tmcd", "force or disable writing tmcd", offsetof(MOVMuxContext, write_tmcd), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM},
128 { NULL },
129 };
130
131 static const AVClass mov_isobmff_muxer_class = {
132 .class_name = "mov/mp4/tgp/psp/tg2/ipod/ismv/f4v muxer",
133 .item_name = av_default_item_name,
134 .option = options,
135 .version = LIBAVUTIL_VERSION_INT,
136 };
137
138 static int get_moov_size(AVFormatContext *s);
139 static int mov_write_single_packet(AVFormatContext *s, AVPacket *pkt);
140
141 24 static int utf8len(const uint8_t *b)
142 {
143 24 int len = 0;
144 int val;
145
2/2
✓ Branch 0 taken 473 times.
✓ Branch 1 taken 24 times.
497 while (*b) {
146
3/8
✓ Branch 0 taken 473 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 473 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 473 times.
473 GET_UTF8(val, *b++, return -1;)
147 473 len++;
148 }
149 24 return len;
150 }
151
152 //FIXME support 64 bit variant with wide placeholders
153 6068 static int64_t update_size(AVIOContext *pb, int64_t pos)
154 {
155 6068 int64_t curpos = avio_tell(pb);
156 6068 avio_seek(pb, pos, SEEK_SET);
157 6068 avio_wb32(pb, curpos - pos); /* rewrite size */
158 6068 avio_seek(pb, curpos, SEEK_SET);
159
160 6068 return curpos - pos;
161 }
162
163 325 static int co64_required(const MOVTrack *track)
164 {
165
3/4
✓ Branch 0 taken 235 times.
✓ Branch 1 taken 90 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 235 times.
325 if (track->entry > 0 && track->cluster[track->entry - 1].pos + track->data_offset > UINT32_MAX)
166 return 1;
167 325 return 0;
168 }
169
170 18917 static int is_cover_image(const AVStream *st)
171 {
172 /* Eg. AV_DISPOSITION_ATTACHED_PIC | AV_DISPOSITION_TIMED_THUMBNAILS
173 * is encoded as sparse video track */
174
3/4
✓ Branch 0 taken 18917 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 18905 times.
18917 return st && st->disposition == AV_DISPOSITION_ATTACHED_PIC;
175 }
176
177 6 static int rtp_hinting_needed(const AVStream *st)
178 {
179 /* Add hint tracks for each real audio and video stream */
180
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if (is_cover_image(st))
181 return 0;
182
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
9 return st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ||
183
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO;
184 }
185
186 /* Chunk offset atom */
187 325 static int mov_write_stco_tag(AVIOContext *pb, MOVTrack *track)
188 {
189 int i;
190 325 int mode64 = co64_required(track); // use 32 bit size variant if possible
191 325 int64_t pos = avio_tell(pb);
192 325 avio_wb32(pb, 0); /* size */
193
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 325 times.
325 if (mode64)
194 ffio_wfourcc(pb, "co64");
195 else
196 325 ffio_wfourcc(pb, "stco");
197 325 avio_wb32(pb, 0); /* version & flags */
198 325 avio_wb32(pb, track->chunkCount); /* entry count */
199
2/2
✓ Branch 0 taken 13271 times.
✓ Branch 1 taken 325 times.
13596 for (i = 0; i < track->entry; i++) {
200
2/2
✓ Branch 0 taken 10290 times.
✓ Branch 1 taken 2981 times.
13271 if (!track->cluster[i].chunkNum)
201 10290 continue;
202
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2981 times.
2981 if (mode64 == 1)
203 avio_wb64(pb, track->cluster[i].pos + track->data_offset);
204 else
205 2981 avio_wb32(pb, track->cluster[i].pos + track->data_offset);
206 }
207 325 return update_size(pb, pos);
208 }
209
210 /* Sample size atom */
211 325 static int mov_write_stsz_tag(AVIOContext *pb, MOVTrack *track)
212 {
213 325 int equalChunks = 1;
214 325 int i, j, entries = 0, tst = -1, oldtst = -1;
215
216 325 int64_t pos = avio_tell(pb);
217 325 avio_wb32(pb, 0); /* size */
218 325 ffio_wfourcc(pb, "stsz");
219 325 avio_wb32(pb, 0); /* version & flags */
220
221
2/2
✓ Branch 0 taken 13271 times.
✓ Branch 1 taken 325 times.
13596 for (i = 0; i < track->entry; i++) {
222 13271 tst = track->cluster[i].size / track->cluster[i].entries;
223
4/4
✓ Branch 0 taken 13036 times.
✓ Branch 1 taken 235 times.
✓ Branch 2 taken 8624 times.
✓ Branch 3 taken 4412 times.
13271 if (oldtst != -1 && tst != oldtst)
224 8624 equalChunks = 0;
225 13271 oldtst = tst;
226 13271 entries += track->cluster[i].entries;
227 }
228
4/4
✓ Branch 0 taken 195 times.
✓ Branch 1 taken 130 times.
✓ Branch 2 taken 105 times.
✓ Branch 3 taken 90 times.
430 if (equalChunks && track->entry) {
229
1/2
✓ Branch 0 taken 105 times.
✗ Branch 1 not taken.
105 int sSize = track->entry ? track->cluster[0].size / track->cluster[0].entries : 0;
230 105 sSize = FFMAX(1, sSize); // adpcm mono case could make sSize == 0
231 105 avio_wb32(pb, sSize); // sample size
232 105 avio_wb32(pb, entries); // sample count
233 } else {
234 220 avio_wb32(pb, 0); // sample size
235 220 avio_wb32(pb, entries); // sample count
236
2/2
✓ Branch 0 taken 9782 times.
✓ Branch 1 taken 220 times.
10002 for (i = 0; i < track->entry; i++) {
237
2/2
✓ Branch 0 taken 9782 times.
✓ Branch 1 taken 9782 times.
19564 for (j = 0; j < track->cluster[i].entries; j++) {
238 9782 avio_wb32(pb, track->cluster[i].size /
239 9782 track->cluster[i].entries);
240 }
241 }
242 }
243 325 return update_size(pb, pos);
244 }
245
246 /* Sample to chunk atom */
247 325 static int mov_write_stsc_tag(AVIOContext *pb, MOVTrack *track)
248 {
249 325 int index = 0, oldval = -1, i;
250 int64_t entryPos, curpos;
251
252 325 int64_t pos = avio_tell(pb);
253 325 avio_wb32(pb, 0); /* size */
254 325 ffio_wfourcc(pb, "stsc");
255 325 avio_wb32(pb, 0); // version & flags
256 325 entryPos = avio_tell(pb);
257 325 avio_wb32(pb, track->chunkCount); // entry count
258
2/2
✓ Branch 0 taken 13271 times.
✓ Branch 1 taken 325 times.
13596 for (i = 0; i < track->entry; i++) {
259
4/4
✓ Branch 0 taken 11082 times.
✓ Branch 1 taken 2189 times.
✓ Branch 2 taken 792 times.
✓ Branch 3 taken 10290 times.
13271 if (oldval != track->cluster[i].samples_in_chunk && track->cluster[i].chunkNum) {
260 792 avio_wb32(pb, track->cluster[i].chunkNum); // first chunk
261 792 avio_wb32(pb, track->cluster[i].samples_in_chunk); // samples per chunk
262 792 avio_wb32(pb, 0x1); // sample description index
263 792 oldval = track->cluster[i].samples_in_chunk;
264 792 index++;
265 }
266 }
267 325 curpos = avio_tell(pb);
268 325 avio_seek(pb, entryPos, SEEK_SET);
269 325 avio_wb32(pb, index); // rewrite size
270 325 avio_seek(pb, curpos, SEEK_SET);
271
272 325 return update_size(pb, pos);
273 }
274
275 /* Sync sample atom */
276 55 static int mov_write_stss_tag(AVIOContext *pb, MOVTrack *track, uint32_t flag)
277 {
278 int64_t curpos, entryPos;
279 55 int i, index = 0;
280 55 int64_t pos = avio_tell(pb);
281 55 avio_wb32(pb, 0); // size
282
1/2
✓ Branch 0 taken 55 times.
✗ Branch 1 not taken.
55 ffio_wfourcc(pb, flag == MOV_SYNC_SAMPLE ? "stss" : "stps");
283 55 avio_wb32(pb, 0); // version & flags
284 55 entryPos = avio_tell(pb);
285 55 avio_wb32(pb, track->entry); // entry count
286
2/2
✓ Branch 0 taken 3109 times.
✓ Branch 1 taken 55 times.
3164 for (i = 0; i < track->entry; i++) {
287
2/2
✓ Branch 0 taken 200 times.
✓ Branch 1 taken 2909 times.
3109 if (track->cluster[i].flags & flag) {
288 200 avio_wb32(pb, i + 1);
289 200 index++;
290 }
291 }
292 55 curpos = avio_tell(pb);
293 55 avio_seek(pb, entryPos, SEEK_SET);
294 55 avio_wb32(pb, index); // rewrite size
295 55 avio_seek(pb, curpos, SEEK_SET);
296 55 return update_size(pb, pos);
297 }
298
299 /* Sample dependency atom */
300 3 static int mov_write_sdtp_tag(AVIOContext *pb, MOVTrack *track)
301 {
302 int i;
303 uint8_t leading, dependent, reference, redundancy;
304 3 int64_t pos = avio_tell(pb);
305 3 avio_wb32(pb, 0); // size
306 3 ffio_wfourcc(pb, "sdtp");
307 3 avio_wb32(pb, 0); // version & flags
308
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 3 times.
16 for (i = 0; i < track->entry; i++) {
309 13 dependent = MOV_SAMPLE_DEPENDENCY_YES;
310 13 leading = reference = redundancy = MOV_SAMPLE_DEPENDENCY_UNKNOWN;
311
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 6 times.
13 if (track->cluster[i].flags & MOV_DISPOSABLE_SAMPLE) {
312 7 reference = MOV_SAMPLE_DEPENDENCY_NO;
313 }
314
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 10 times.
13 if (track->cluster[i].flags & MOV_SYNC_SAMPLE) {
315 3 dependent = MOV_SAMPLE_DEPENDENCY_NO;
316 }
317 13 avio_w8(pb, (leading << 6) | (dependent << 4) |
318 13 (reference << 2) | redundancy);
319 }
320 3 return update_size(pb, pos);
321 }
322
323 #if CONFIG_IAMFENC
324 4 static int mov_write_iacb_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
325 {
326 AVIOContext *dyn_bc;
327 4 int64_t pos = avio_tell(pb);
328 4 uint8_t *dyn_buf = NULL;
329 int dyn_size;
330 4 int ret = avio_open_dyn_buf(&dyn_bc);
331
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0)
332 return ret;
333
334 4 avio_wb32(pb, 0);
335 4 ffio_wfourcc(pb, "iacb");
336 4 avio_w8(pb, 1); // configurationVersion
337
338 4 ret = ff_iamf_write_descriptors(track->iamf, dyn_bc, s);
339
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0)
340 return ret;
341
342 4 dyn_size = avio_close_dyn_buf(dyn_bc, &dyn_buf);
343 4 ffio_write_leb(pb, dyn_size);
344 4 avio_write(pb, dyn_buf, dyn_size);
345 4 av_free(dyn_buf);
346
347 4 return update_size(pb, pos);
348 }
349 #endif
350
351 static int mov_write_amr_tag(AVIOContext *pb, MOVTrack *track)
352 {
353 avio_wb32(pb, 0x11); /* size */
354 if (track->mode == MODE_MOV) ffio_wfourcc(pb, "samr");
355 else ffio_wfourcc(pb, "damr");
356 ffio_wfourcc(pb, "FFMP");
357 avio_w8(pb, 0); /* decoder version */
358
359 avio_wb16(pb, 0x81FF); /* Mode set (all modes for AMR_NB) */
360 avio_w8(pb, 0x00); /* Mode change period (no restriction) */
361 avio_w8(pb, 0x01); /* Frames per sample */
362 return 0x11;
363 }
364
365 struct eac3_info {
366 AVPacket *pkt;
367 uint8_t ec3_done;
368 uint8_t num_blocks;
369
370 /* Layout of the EC3SpecificBox */
371 /* maximum bitrate */
372 uint16_t data_rate;
373 int8_t ac3_bit_rate_code;
374 /* number of independent substreams */
375 uint8_t num_ind_sub;
376 struct {
377 /* sample rate code (see ff_ac3_sample_rate_tab) 2 bits */
378 uint8_t fscod;
379 /* bit stream identification 5 bits */
380 uint8_t bsid;
381 /* one bit reserved */
382 /* audio service mixing (not supported yet) 1 bit */
383 /* bit stream mode 3 bits */
384 uint8_t bsmod;
385 /* audio coding mode 3 bits */
386 uint8_t acmod;
387 /* sub woofer on 1 bit */
388 uint8_t lfeon;
389 /* 3 bits reserved */
390 /* number of dependent substreams associated with this substream 4 bits */
391 uint8_t num_dep_sub;
392 /* channel locations of the dependent substream(s), if any, 9 bits */
393 uint16_t chan_loc;
394 /* if there is no dependent substream, then one bit reserved instead */
395 } substream[1]; /* TODO: support 8 independent substreams */
396 };
397
398 5 static int mov_write_ac3_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
399 {
400 5 struct eac3_info *info = track->eac3_priv;
401 PutBitContext pbc;
402 uint8_t buf[3];
403
404
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (!info || !info->ec3_done) {
405 av_log(s, AV_LOG_ERROR,
406 "Cannot write moov atom before AC3 packets."
407 " Set the delay_moov flag to fix this.\n");
408 return AVERROR(EINVAL);
409 }
410
411
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (info->substream[0].bsid > 8) {
412 av_log(s, AV_LOG_ERROR,
413 "RealAudio AC-3/DolbyNet with bsid %d is not defined by the "
414 "ISOBMFF specification in ETSI TS 102 366!\n",
415 info->substream[0].bsid);
416 return AVERROR(EINVAL);
417 }
418
419
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (info->ac3_bit_rate_code < 0) {
420 av_log(s, AV_LOG_ERROR,
421 "No valid AC3 bit rate code for data rate of %d!\n",
422 info->data_rate);
423 return AVERROR(EINVAL);
424 }
425
426 5 avio_wb32(pb, 11);
427 5 ffio_wfourcc(pb, "dac3");
428
429 5 init_put_bits(&pbc, buf, sizeof(buf));
430 5 put_bits(&pbc, 2, info->substream[0].fscod);
431 5 put_bits(&pbc, 5, info->substream[0].bsid);
432 5 put_bits(&pbc, 3, info->substream[0].bsmod);
433 5 put_bits(&pbc, 3, info->substream[0].acmod);
434 5 put_bits(&pbc, 1, info->substream[0].lfeon);
435 5 put_bits(&pbc, 5, info->ac3_bit_rate_code); // bit_rate_code
436 5 put_bits(&pbc, 5, 0); // reserved
437
438 5 flush_put_bits(&pbc);
439 5 avio_write(pb, buf, sizeof(buf));
440
441 5 return 11;
442 }
443
444 1039 static int handle_eac3(MOVMuxContext *mov, AVPacket *pkt, MOVTrack *track)
445 {
446 1039 AC3HeaderInfo *hdr = NULL;
447 struct eac3_info *info;
448 int num_blocks, ret;
449
450
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1034 times.
1039 if (!track->eac3_priv) {
451
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 if (!(track->eac3_priv = av_mallocz(sizeof(*info))))
452 return AVERROR(ENOMEM);
453
454 5 ((struct eac3_info *)track->eac3_priv)->ac3_bit_rate_code = -1;
455 }
456 1039 info = track->eac3_priv;
457
458
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1034 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
1039 if (!info->pkt && !(info->pkt = av_packet_alloc()))
459 return AVERROR(ENOMEM);
460
461
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1038 times.
1039 if ((ret = avpriv_ac3_parse_header(&hdr, pkt->data, pkt->size)) < 0) {
462
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret == AVERROR(ENOMEM))
463 goto end;
464
465 /* drop the packets until we see a good one */
466
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (!track->entry) {
467 1 av_log(mov->fc, AV_LOG_WARNING, "Dropping invalid packet from start of the stream\n");
468 1 ret = 0;
469 } else
470 ret = AVERROR_INVALIDDATA;
471 1 goto end;
472 }
473
474 1038 info->data_rate = FFMAX(info->data_rate, hdr->bit_rate / 1000);
475 1038 info->ac3_bit_rate_code = FFMAX(info->ac3_bit_rate_code,
476 hdr->ac3_bit_rate_code);
477 1038 num_blocks = hdr->num_blocks;
478
479
2/2
✓ Branch 0 taken 1032 times.
✓ Branch 1 taken 6 times.
1038 if (!info->ec3_done) {
480 /* AC-3 substream must be the first one */
481
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
6 if (hdr->bitstream_id <= 10 && hdr->substreamid != 0) {
482 ret = AVERROR(EINVAL);
483 goto end;
484 }
485
486 /* this should always be the case, given that our AC-3 parser
487 * concatenates dependent frames to their independent parent */
488
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 if (hdr->frame_type == EAC3_FRAME_TYPE_INDEPENDENT ||
489
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 hdr->frame_type == EAC3_FRAME_TYPE_AC3_CONVERT) {
490 /* substream ids must be incremental */
491
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (hdr->substreamid > info->num_ind_sub + 1) {
492 ret = AVERROR(EINVAL);
493 goto end;
494 }
495
496
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (hdr->substreamid == info->num_ind_sub + 1) {
497 //info->num_ind_sub++;
498 avpriv_request_sample(mov->fc, "Multiple independent substreams");
499 ret = AVERROR_PATCHWELCOME;
500 goto end;
501
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 } else if (hdr->substreamid < info->num_ind_sub ||
502
3/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 5 times.
6 hdr->substreamid == 0 && info->substream[0].bsid) {
503 1 info->ec3_done = 1;
504 1 goto concatenate;
505 }
506 } else {
507 if (hdr->substreamid != 0) {
508 avpriv_request_sample(mov->fc, "Multiple non EAC3 independent substreams");
509 ret = AVERROR_PATCHWELCOME;
510 goto end;
511 }
512 }
513
514 /* fill the info needed for the "dec3" atom */
515 5 info->substream[hdr->substreamid].fscod = hdr->sr_code;
516 5 info->substream[hdr->substreamid].bsid = hdr->bitstream_id;
517 5 info->substream[hdr->substreamid].bsmod = hdr->bitstream_mode;
518 5 info->substream[hdr->substreamid].acmod = hdr->channel_mode;
519 5 info->substream[hdr->substreamid].lfeon = hdr->lfe_on;
520
521
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
5 if (track->par->codec_id == AV_CODEC_ID_AC3) {
522 // with AC-3 we only require the information of a single packet,
523 // so we can finish as soon as the basic values of the bit stream
524 // have been set to the track's informational structure.
525 4 info->ec3_done = 1;
526 4 goto concatenate;
527 }
528
529 /* Parse dependent substream(s), if any */
530
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (pkt->size != hdr->frame_size) {
531 int cumul_size = hdr->frame_size;
532 int parent = hdr->substreamid;
533
534 while (cumul_size != pkt->size) {
535 GetBitContext gbc;
536 int i;
537 ret = avpriv_ac3_parse_header(&hdr, pkt->data + cumul_size, pkt->size - cumul_size);
538 if (ret < 0)
539 goto end;
540 if (hdr->frame_type != EAC3_FRAME_TYPE_DEPENDENT) {
541 ret = AVERROR(EINVAL);
542 goto end;
543 }
544 info->substream[parent].num_dep_sub++;
545 ret /= 8;
546
547 /* header is parsed up to lfeon, but custom channel map may be needed */
548 init_get_bits8(&gbc, pkt->data + cumul_size + ret, pkt->size - cumul_size - ret);
549 /* skip bsid */
550 skip_bits(&gbc, 5);
551 /* skip volume control params */
552 for (i = 0; i < (hdr->channel_mode ? 1 : 2); i++) {
553 skip_bits(&gbc, 5); // skip dialog normalization
554 if (get_bits1(&gbc)) {
555 skip_bits(&gbc, 8); // skip compression gain word
556 }
557 }
558 /* get the dependent stream channel map, if exists */
559 if (get_bits1(&gbc))
560 info->substream[parent].chan_loc |= (get_bits(&gbc, 16) >> 5) & 0x1f;
561 else
562 info->substream[parent].chan_loc |= hdr->channel_mode;
563 cumul_size += hdr->frame_size;
564 }
565 }
566 }
567
568 1033 concatenate:
569
2/4
✓ Branch 0 taken 1038 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1038 times.
✗ Branch 3 not taken.
1038 if (!info->num_blocks && num_blocks == 6) {
570 1038 ret = pkt->size;
571 1038 goto end;
572 }
573 else if (info->num_blocks + num_blocks > 6) {
574 ret = AVERROR_INVALIDDATA;
575 goto end;
576 }
577
578 if (!info->num_blocks) {
579 ret = av_packet_ref(info->pkt, pkt);
580 if (!ret)
581 info->num_blocks = num_blocks;
582 goto end;
583 } else {
584 if ((ret = av_grow_packet(info->pkt, pkt->size)) < 0)
585 goto end;
586 memcpy(info->pkt->data + info->pkt->size - pkt->size, pkt->data, pkt->size);
587 info->num_blocks += num_blocks;
588 info->pkt->duration += pkt->duration;
589 if (info->num_blocks != 6)
590 goto end;
591 av_packet_unref(pkt);
592 av_packet_move_ref(pkt, info->pkt);
593 info->num_blocks = 0;
594 }
595 ret = pkt->size;
596
597 1039 end:
598 1039 av_free(hdr);
599
600 1039 return ret;
601 }
602
603 1 static int mov_write_eac3_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
604 {
605 PutBitContext pbc;
606 uint8_t *buf;
607 struct eac3_info *info;
608 int size, i;
609
610
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!track->eac3_priv) {
611 av_log(s, AV_LOG_ERROR,
612 "Cannot write moov atom before EAC3 packets parsed.\n");
613 return AVERROR(EINVAL);
614 }
615
616 1 info = track->eac3_priv;
617 1 size = 2 + ((34 * (info->num_ind_sub + 1) + 7) >> 3);
618 1 buf = av_malloc(size);
619
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!buf) {
620 return AVERROR(ENOMEM);
621 }
622
623 1 init_put_bits(&pbc, buf, size);
624 1 put_bits(&pbc, 13, info->data_rate);
625 1 put_bits(&pbc, 3, info->num_ind_sub);
626
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 for (i = 0; i <= info->num_ind_sub; i++) {
627 1 put_bits(&pbc, 2, info->substream[i].fscod);
628 1 put_bits(&pbc, 5, info->substream[i].bsid);
629 1 put_bits(&pbc, 1, 0); /* reserved */
630 1 put_bits(&pbc, 1, 0); /* asvc */
631 1 put_bits(&pbc, 3, info->substream[i].bsmod);
632 1 put_bits(&pbc, 3, info->substream[i].acmod);
633 1 put_bits(&pbc, 1, info->substream[i].lfeon);
634 1 put_bits(&pbc, 5, 0); /* reserved */
635 1 put_bits(&pbc, 4, info->substream[i].num_dep_sub);
636
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (!info->substream[i].num_dep_sub) {
637 1 put_bits(&pbc, 1, 0); /* reserved */
638 } else {
639 put_bits(&pbc, 9, info->substream[i].chan_loc);
640 }
641 }
642 1 flush_put_bits(&pbc);
643 1 size = put_bytes_output(&pbc);
644
645 1 avio_wb32(pb, size + 8);
646 1 ffio_wfourcc(pb, "dec3");
647 1 avio_write(pb, buf, size);
648
649 1 av_free(buf);
650
651 1 return size;
652 }
653
654 /**
655 * This function writes extradata "as is".
656 * Extradata must be formatted like a valid atom (with size and tag).
657 */
658 12 static int mov_write_extradata_tag(AVIOContext *pb, MOVTrack *track)
659 {
660 12 avio_write(pb, track->par->extradata, track->par->extradata_size);
661 12 return track->par->extradata_size;
662 }
663
664 static int mov_write_enda_tag(AVIOContext *pb)
665 {
666 avio_wb32(pb, 10);
667 ffio_wfourcc(pb, "enda");
668 avio_wb16(pb, 1); /* little endian */
669 return 10;
670 }
671
672 2 static int mov_write_enda_tag_be(AVIOContext *pb)
673 {
674 2 avio_wb32(pb, 10);
675 2 ffio_wfourcc(pb, "enda");
676 2 avio_wb16(pb, 0); /* big endian */
677 2 return 10;
678 }
679
680 308 static void put_descr(AVIOContext *pb, int tag, unsigned int size)
681 {
682 308 int i = 3;
683 308 avio_w8(pb, tag);
684
2/2
✓ Branch 0 taken 924 times.
✓ Branch 1 taken 308 times.
1232 for (; i > 0; i--)
685 924 avio_w8(pb, (size >> (7 * i)) | 0x80);
686 308 avio_w8(pb, size & 0x7F);
687 308 }
688
689 205 static unsigned compute_avg_bitrate(MOVTrack *track)
690 {
691 205 uint64_t size = 0;
692 int i;
693
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 168 times.
205 if (!track->track_duration)
694 37 return 0;
695
2/2
✓ Branch 0 taken 8864 times.
✓ Branch 1 taken 168 times.
9032 for (i = 0; i < track->entry; i++)
696 8864 size += track->cluster[i].size;
697 168 return size * 8 * track->timescale / track->track_duration;
698 }
699
700 struct mpeg4_bit_rate_values {
701 uint32_t buffer_size; ///< Size of the decoding buffer for the elementary stream in bytes.
702 uint32_t max_bit_rate; ///< Maximum rate in bits/second over any window of one second.
703 uint32_t avg_bit_rate; ///< Average rate in bits/second over the entire presentation.
704 };
705
706 205 static struct mpeg4_bit_rate_values calculate_mpeg4_bit_rates(MOVTrack *track)
707 {
708 410 const AVPacketSideData *sd = track->st ?
709 204 av_packet_side_data_get(track->st->codecpar->coded_side_data,
710 204 track->st->codecpar->nb_coded_side_data,
711
2/2
✓ Branch 0 taken 204 times.
✓ Branch 1 taken 1 times.
205 AV_PKT_DATA_CPB_PROPERTIES) : NULL;
712
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 175 times.
205 AVCPBProperties *props = sd ? (AVCPBProperties *)sd->data : NULL;
713 205 struct mpeg4_bit_rate_values bit_rates = { 0 };
714
715 205 bit_rates.avg_bit_rate = compute_avg_bitrate(track);
716
2/2
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 78 times.
205 if (!bit_rates.avg_bit_rate) {
717 // if the average bit rate cannot be calculated at this point, such as
718 // in the case of fragmented MP4, utilize the following values as
719 // fall-back in priority order:
720 //
721 // 1. average bit rate property
722 // 2. bit rate (usually average over the whole clip)
723 // 3. maximum bit rate property
724
725
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 124 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
127 if (props && props->avg_bitrate) {
726 3 bit_rates.avg_bit_rate = props->avg_bitrate;
727
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 122 times.
124 } else if (track->par->bit_rate) {
728 2 bit_rates.avg_bit_rate = track->par->bit_rate;
729
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 122 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
122 } else if (props && props->max_bitrate) {
730 bit_rates.avg_bit_rate = props->max_bitrate;
731 }
732 }
733
734 // (FIXME should be max rate in any 1 sec window)
735 205 bit_rates.max_bit_rate = FFMAX(track->par->bit_rate,
736 bit_rates.avg_bit_rate);
737
738 // utilize values from properties if we have them available
739
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 175 times.
205 if (props) {
740 30 bit_rates.max_bit_rate = FFMAX(bit_rates.max_bit_rate,
741 props->max_bitrate);
742 30 bit_rates.buffer_size = props->buffer_size / 8;
743 }
744
745 205 return bit_rates;
746 }
747
748 77 static int mov_write_esds_tag(AVIOContext *pb, MOVTrack *track) // Basic
749 {
750 77 struct mpeg4_bit_rate_values bit_rates = calculate_mpeg4_bit_rates(track);
751 77 int64_t pos = avio_tell(pb);
752
1/2
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
77 int decoder_specific_info_len = track->vos_len ? 5 + track->vos_len : 0;
753
754 77 avio_wb32(pb, 0); // size
755 77 ffio_wfourcc(pb, "esds");
756 77 avio_wb32(pb, 0); // Version
757
758 // ES descriptor
759 77 put_descr(pb, 0x03, 3 + 5+13 + decoder_specific_info_len + 5+1);
760 77 avio_wb16(pb, track->track_id);
761 77 avio_w8(pb, 0x00); // flags (= no flags)
762
763 // DecoderConfig descriptor
764 77 put_descr(pb, 0x04, 13 + decoder_specific_info_len);
765
766 // Object type indication
767
1/2
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
77 if ((track->par->codec_id == AV_CODEC_ID_MP2 ||
768
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 track->par->codec_id == AV_CODEC_ID_MP3) &&
769 track->par->sample_rate > 24000)
770 avio_w8(pb, 0x6B); // 11172-3
771 else
772 77 avio_w8(pb, ff_codec_get_tag(ff_mp4_obj_type, track->par->codec_id));
773
774 // the following fields is made of 6 bits to identify the streamtype (4 for video, 5 for audio)
775 // plus 1 bit to indicate upstream and 1 bit set to 1 (reserved)
776
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 if (track->par->codec_id == AV_CODEC_ID_DVD_SUBTITLE)
777 avio_w8(pb, (0x38 << 2) | 1); // flags (= NeroSubpicStream)
778
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 23 times.
77 else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO)
779 54 avio_w8(pb, 0x15); // flags (= Audiostream)
780 else
781 23 avio_w8(pb, 0x11); // flags (= Visualstream)
782
783 77 avio_wb24(pb, bit_rates.buffer_size); // Buffersize DB
784 77 avio_wb32(pb, bit_rates.max_bit_rate); // maxbitrate
785 77 avio_wb32(pb, bit_rates.avg_bit_rate);
786
787
1/2
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
77 if (track->vos_len) {
788 // DecoderSpecific info descriptor
789 77 put_descr(pb, 0x05, track->vos_len);
790 77 avio_write(pb, track->vos_data, track->vos_len);
791 }
792
793 // SL descriptor
794 77 put_descr(pb, 0x06, 1);
795 77 avio_w8(pb, 0x02);
796 77 return update_size(pb, pos);
797 }
798
799 77 static int mov_pcm_le_gt16(enum AVCodecID codec_id)
800 {
801
1/2
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
77 return codec_id == AV_CODEC_ID_PCM_S24LE ||
802
1/2
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
77 codec_id == AV_CODEC_ID_PCM_S32LE ||
803
2/4
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 77 times.
154 codec_id == AV_CODEC_ID_PCM_F32LE ||
804 codec_id == AV_CODEC_ID_PCM_F64LE;
805 }
806
807 77 static int mov_pcm_be_gt16(enum AVCodecID codec_id)
808 {
809
2/2
✓ Branch 0 taken 69 times.
✓ Branch 1 taken 4 times.
73 return codec_id == AV_CODEC_ID_PCM_S24BE ||
810
1/2
✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
69 codec_id == AV_CODEC_ID_PCM_S32BE ||
811
3/4
✓ Branch 0 taken 73 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 69 times.
150 codec_id == AV_CODEC_ID_PCM_F32BE ||
812 codec_id == AV_CODEC_ID_PCM_F64BE;
813 }
814
815 static int mov_write_ms_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
816 {
817 int ret;
818 int64_t pos = avio_tell(pb);
819 avio_wb32(pb, 0);
820 avio_wl32(pb, track->tag); // store it byteswapped
821 track->par->codec_tag = av_bswap16(track->tag >> 16);
822 if ((ret = ff_put_wav_header(s, pb, track->par, 0)) < 0)
823 return ret;
824 return update_size(pb, pos);
825 }
826
827 static int mov_write_wfex_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
828 {
829 int ret;
830 int64_t pos = avio_tell(pb);
831 avio_wb32(pb, 0);
832 ffio_wfourcc(pb, "wfex");
833 if ((ret = ff_put_wav_header(s, pb, track->st->codecpar, FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX)) < 0)
834 return ret;
835 return update_size(pb, pos);
836 }
837
838 static int mov_write_dfla_tag(AVIOContext *pb, MOVTrack *track)
839 {
840 int64_t pos = avio_tell(pb);
841 avio_wb32(pb, 0);
842 ffio_wfourcc(pb, "dfLa");
843 avio_w8(pb, 0); /* version */
844 avio_wb24(pb, 0); /* flags */
845
846 /* Expect the encoder to pass a METADATA_BLOCK_TYPE_STREAMINFO. */
847 if (track->par->extradata_size != FLAC_STREAMINFO_SIZE)
848 return AVERROR_INVALIDDATA;
849
850 /* TODO: Write other METADATA_BLOCK_TYPEs if the encoder makes them available. */
851 avio_w8(pb, 1 << 7 | FLAC_METADATA_TYPE_STREAMINFO); /* LastMetadataBlockFlag << 7 | BlockType */
852 avio_wb24(pb, track->par->extradata_size); /* Length */
853 avio_write(pb, track->par->extradata, track->par->extradata_size); /* BlockData[Length] */
854
855 return update_size(pb, pos);
856 }
857
858 static int mov_write_dops_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
859 {
860 int64_t pos = avio_tell(pb);
861 int channels, channel_map;
862 avio_wb32(pb, 0);
863 ffio_wfourcc(pb, "dOps");
864 avio_w8(pb, 0); /* Version */
865 if (track->par->extradata_size < 19) {
866 av_log(s, AV_LOG_ERROR, "invalid extradata size\n");
867 return AVERROR_INVALIDDATA;
868 }
869 /* extradata contains an Ogg OpusHead, other than byte-ordering and
870 OpusHead's preceeding magic/version, OpusSpecificBox is currently
871 identical. */
872 channels = AV_RB8(track->par->extradata + 9);
873 channel_map = AV_RB8(track->par->extradata + 18);
874
875 avio_w8(pb, channels); /* OuputChannelCount */
876 avio_wb16(pb, AV_RL16(track->par->extradata + 10)); /* PreSkip */
877 avio_wb32(pb, AV_RL32(track->par->extradata + 12)); /* InputSampleRate */
878 avio_wb16(pb, AV_RL16(track->par->extradata + 16)); /* OutputGain */
879 avio_w8(pb, channel_map); /* ChannelMappingFamily */
880 /* Write the rest of the header out without byte-swapping. */
881 if (channel_map) {
882 if (track->par->extradata_size < 21 + channels) {
883 av_log(s, AV_LOG_ERROR, "invalid extradata size\n");
884 return AVERROR_INVALIDDATA;
885 }
886 avio_write(pb, track->par->extradata + 19, 2 + channels); /* ChannelMappingTable */
887 }
888
889 return update_size(pb, pos);
890 }
891
892 static int mov_write_dmlp_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
893 {
894 int64_t pos = avio_tell(pb);
895 int length;
896 avio_wb32(pb, 0);
897 ffio_wfourcc(pb, "dmlp");
898
899 if (track->vos_len < 20) {
900 av_log(s, AV_LOG_ERROR,
901 "Cannot write moov atom before TrueHD packets."
902 " Set the delay_moov flag to fix this.\n");
903 return AVERROR(EINVAL);
904 }
905
906 length = (AV_RB16(track->vos_data) & 0xFFF) * 2;
907 if (length < 20 || length > track->vos_len)
908 return AVERROR_INVALIDDATA;
909
910 // Only TrueHD is supported
911 if (AV_RB32(track->vos_data + 4) != 0xF8726FBA)
912 return AVERROR_INVALIDDATA;
913
914 avio_wb32(pb, AV_RB32(track->vos_data + 8)); /* format_info */
915 avio_wb16(pb, AV_RB16(track->vos_data + 18) << 1); /* peak_data_rate */
916 avio_wb32(pb, 0); /* reserved */
917
918 return update_size(pb, pos);
919 }
920
921 64 static int mov_write_SA3D_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
922 {
923 64 const AVDictionaryEntry *str = av_dict_get(track->st->metadata, "SA3D", NULL, 0);
924 64 AVChannelLayout ch_layout = { 0 };
925 int64_t pos;
926 int ambisonic_order, ambi_channels, non_diegetic_channels;
927 int i, ret;
928
929
1/2
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
64 if (!str)
930 64 return 0;
931
932 ret = av_channel_layout_from_string(&ch_layout, str->value);
933 if (ret < 0) {
934 if (ret == AVERROR(EINVAL)) {
935 invalid:
936 av_log(s, AV_LOG_ERROR, "Invalid SA3D layout: \"%s\"\n", str->value);
937 ret = 0;
938 }
939 av_channel_layout_uninit(&ch_layout);
940 return ret;
941 }
942
943 if (track->st->codecpar->ch_layout.nb_channels != ch_layout.nb_channels)
944 goto invalid;
945
946 ambisonic_order = av_channel_layout_ambisonic_order(&ch_layout);
947 if (ambisonic_order < 0)
948 goto invalid;
949
950 ambi_channels = (ambisonic_order + 1LL) * (ambisonic_order + 1LL);
951 non_diegetic_channels = ch_layout.nb_channels - ambi_channels;
952 if (non_diegetic_channels &&
953 (non_diegetic_channels != 2 ||
954 av_channel_layout_subset(&ch_layout, AV_CH_LAYOUT_STEREO) != AV_CH_LAYOUT_STEREO))
955 goto invalid;
956
957 av_log(s, AV_LOG_VERBOSE, "Inserting SA3D box with layout: \"%s\"\n", str->value);
958
959 pos = avio_tell(pb);
960
961 avio_wb32(pb, 0); // Size
962 ffio_wfourcc(pb, "SA3D");
963 avio_w8(pb, 0); // version
964 avio_w8(pb, (!!non_diegetic_channels) << 7); // head_locked_stereo and ambisonic_type
965 avio_wb32(pb, ambisonic_order); // ambisonic_order
966 avio_w8(pb, 0); // ambisonic_channel_ordering
967 avio_w8(pb, 0); // ambisonic_normalization
968 avio_wb32(pb, ch_layout.nb_channels); // num_channels
969 for (i = 0; i < ambi_channels; i++)
970 avio_wb32(pb, av_channel_layout_channel_from_index(&ch_layout, i) - AV_CHAN_AMBISONIC_BASE);
971 for (; i < ch_layout.nb_channels; i++)
972 avio_wb32(pb, av_channel_layout_channel_from_index(&ch_layout, i) + ambi_channels);
973
974 av_channel_layout_uninit(&ch_layout);
975
976 return update_size(pb, pos);
977 }
978
979 40 static int mov_write_chan_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
980 {
981 uint32_t layout_tag, bitmap, *channel_desc;
982 40 int64_t pos = avio_tell(pb);
983 int num_desc, ret;
984
985
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 if (track->multichannel_as_mono)
986 return 0;
987
988 40 ret = ff_mov_get_channel_layout_tag(track->par, &layout_tag,
989 &bitmap, &channel_desc);
990
991
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 if (ret < 0) {
992 if (ret == AVERROR(ENOSYS)) {
993 av_log(s, AV_LOG_WARNING, "not writing 'chan' tag due to "
994 "lack of channel information\n");
995 ret = 0;
996 }
997
998 return ret;
999 }
1000
1001
4/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 3 times.
40 if (layout_tag == MOV_CH_LAYOUT_MONO && track->mono_as_fc > 0) {
1002
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 av_assert0(!channel_desc);
1003 1 channel_desc = av_malloc(sizeof(*channel_desc));
1004
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!channel_desc)
1005 return AVERROR(ENOMEM);
1006
1007 1 layout_tag = 0;
1008 1 bitmap = 0;
1009 1 *channel_desc = 3; // channel label "Center"
1010 }
1011
1012
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 37 times.
40 num_desc = layout_tag ? 0 : track->par->ch_layout.nb_channels;
1013
1014 40 avio_wb32(pb, 0); // Size
1015 40 ffio_wfourcc(pb, "chan"); // Type
1016 40 avio_w8(pb, 0); // Version
1017 40 avio_wb24(pb, 0); // Flags
1018 40 avio_wb32(pb, layout_tag); // mChannelLayoutTag
1019 40 avio_wb32(pb, bitmap); // mChannelBitmap
1020 40 avio_wb32(pb, num_desc); // mNumberChannelDescriptions
1021
1022
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 40 times.
43 for (int i = 0; i < num_desc; i++) {
1023 3 avio_wb32(pb, channel_desc[i]); // mChannelLabel
1024 3 avio_wb32(pb, 0); // mChannelFlags
1025 3 avio_wl32(pb, 0); // mCoordinates[0]
1026 3 avio_wl32(pb, 0); // mCoordinates[1]
1027 3 avio_wl32(pb, 0); // mCoordinates[2]
1028 }
1029
1030 40 av_free(channel_desc);
1031
1032 40 return update_size(pb, pos);
1033 }
1034
1035 15 static int mov_write_wave_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
1036 {
1037 15 int64_t pos = avio_tell(pb);
1038
1039 15 avio_wb32(pb, 0); /* size */
1040 15 ffio_wfourcc(pb, "wave");
1041
1042
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 if (track->par->codec_id != AV_CODEC_ID_QDM2) {
1043 15 avio_wb32(pb, 12); /* size */
1044 15 ffio_wfourcc(pb, "frma");
1045 15 avio_wl32(pb, track->tag);
1046 }
1047
1048
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 12 times.
15 if (track->par->codec_id == AV_CODEC_ID_AAC) {
1049 /* useless atom needed by mplayer, ipod, not needed by quicktime */
1050 3 avio_wb32(pb, 12); /* size */
1051 3 ffio_wfourcc(pb, "mp4a");
1052 3 avio_wb32(pb, 0);
1053 3 mov_write_esds_tag(pb, track);
1054
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
12 } else if (mov_pcm_le_gt16(track->par->codec_id)) {
1055 mov_write_enda_tag(pb);
1056
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 10 times.
12 } else if (mov_pcm_be_gt16(track->par->codec_id)) {
1057 2 mov_write_enda_tag_be(pb);
1058
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 } else if (track->par->codec_id == AV_CODEC_ID_AMR_NB) {
1059 mov_write_amr_tag(pb, track);
1060
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 9 times.
10 } else if (track->par->codec_id == AV_CODEC_ID_AC3) {
1061 1 mov_write_ac3_tag(s, pb, track);
1062
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 } else if (track->par->codec_id == AV_CODEC_ID_EAC3) {
1063 mov_write_eac3_tag(s, pb, track);
1064
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 } else if (track->par->codec_id == AV_CODEC_ID_ALAC ||
1065 track->par->codec_id == AV_CODEC_ID_QDM2) {
1066 9 mov_write_extradata_tag(pb, track);
1067 } else if (track->par->codec_id == AV_CODEC_ID_ADPCM_MS ||
1068 track->par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) {
1069 mov_write_ms_tag(s, pb, track);
1070 }
1071
1072 15 avio_wb32(pb, 8); /* size */
1073 15 avio_wb32(pb, 0); /* null tag */
1074
1075 15 return update_size(pb, pos);
1076 }
1077
1078 static int mov_write_dvc1_structs(MOVTrack *track, uint8_t *buf)
1079 {
1080 uint8_t *unescaped;
1081 const uint8_t *start, *next, *end = track->vos_data + track->vos_len;
1082 int unescaped_size, seq_found = 0;
1083 int level = 0, interlace = 0;
1084 int packet_seq = track->vc1_info.packet_seq;
1085 int packet_entry = track->vc1_info.packet_entry;
1086 int slices = track->vc1_info.slices;
1087 PutBitContext pbc;
1088
1089 if (track->start_dts == AV_NOPTS_VALUE) {
1090 /* No packets written yet, vc1_info isn't authoritative yet. */
1091 /* Assume inline sequence and entry headers. */
1092 packet_seq = packet_entry = 1;
1093 av_log(NULL, AV_LOG_WARNING,
1094 "moov atom written before any packets, unable to write correct "
1095 "dvc1 atom. Set the delay_moov flag to fix this.\n");
1096 }
1097
1098 unescaped = av_mallocz(track->vos_len + AV_INPUT_BUFFER_PADDING_SIZE);
1099 if (!unescaped)
1100 return AVERROR(ENOMEM);
1101 start = find_next_marker(track->vos_data, end);
1102 for (next = start; next < end; start = next) {
1103 GetBitContext gb;
1104 int size;
1105 next = find_next_marker(start + 4, end);
1106 size = next - start - 4;
1107 if (size <= 0)
1108 continue;
1109 unescaped_size = vc1_unescape_buffer(start + 4, size, unescaped);
1110 init_get_bits(&gb, unescaped, 8 * unescaped_size);
1111 if (AV_RB32(start) == VC1_CODE_SEQHDR) {
1112 int profile = get_bits(&gb, 2);
1113 if (profile != PROFILE_ADVANCED) {
1114 av_free(unescaped);
1115 return AVERROR(ENOSYS);
1116 }
1117 seq_found = 1;
1118 level = get_bits(&gb, 3);
1119 /* chromaformat, frmrtq_postproc, bitrtq_postproc, postprocflag,
1120 * width, height */
1121 skip_bits_long(&gb, 2 + 3 + 5 + 1 + 2*12);
1122 skip_bits(&gb, 1); /* broadcast */
1123 interlace = get_bits1(&gb);
1124 skip_bits(&gb, 4); /* tfcntrflag, finterpflag, reserved, psf */
1125 }
1126 }
1127 if (!seq_found) {
1128 av_free(unescaped);
1129 return AVERROR(ENOSYS);
1130 }
1131
1132 init_put_bits(&pbc, buf, 7);
1133 /* VC1DecSpecStruc */
1134 put_bits(&pbc, 4, 12); /* profile - advanced */
1135 put_bits(&pbc, 3, level);
1136 put_bits(&pbc, 1, 0); /* reserved */
1137 /* VC1AdvDecSpecStruc */
1138 put_bits(&pbc, 3, level);
1139 put_bits(&pbc, 1, 0); /* cbr */
1140 put_bits(&pbc, 6, 0); /* reserved */
1141 put_bits(&pbc, 1, !interlace); /* no interlace */
1142 put_bits(&pbc, 1, !packet_seq); /* no multiple seq */
1143 put_bits(&pbc, 1, !packet_entry); /* no multiple entry */
1144 put_bits(&pbc, 1, !slices); /* no slice code */
1145 put_bits(&pbc, 1, 0); /* no bframe */
1146 put_bits(&pbc, 1, 0); /* reserved */
1147
1148 /* framerate */
1149 if (track->st->avg_frame_rate.num > 0 && track->st->avg_frame_rate.den > 0)
1150 put_bits32(&pbc, track->st->avg_frame_rate.num / track->st->avg_frame_rate.den);
1151 else
1152 put_bits32(&pbc, 0xffffffff);
1153
1154 flush_put_bits(&pbc);
1155
1156 av_free(unescaped);
1157
1158 return 0;
1159 }
1160
1161 static int mov_write_dvc1_tag(AVIOContext *pb, MOVTrack *track)
1162 {
1163 uint8_t buf[7] = { 0 };
1164 int ret;
1165
1166 if ((ret = mov_write_dvc1_structs(track, buf)) < 0)
1167 return ret;
1168
1169 avio_wb32(pb, track->vos_len + 8 + sizeof(buf));
1170 ffio_wfourcc(pb, "dvc1");
1171 avio_write(pb, buf, sizeof(buf));
1172 avio_write(pb, track->vos_data, track->vos_len);
1173
1174 return 0;
1175 }
1176
1177 4 static int mov_write_glbl_tag(AVIOContext *pb, MOVTrack *track)
1178 {
1179 4 avio_wb32(pb, track->vos_len + 8);
1180 4 ffio_wfourcc(pb, "glbl");
1181 4 avio_write(pb, track->vos_data, track->vos_len);
1182 4 return 8 + track->vos_len;
1183 }
1184
1185 /**
1186 * Compute flags for 'lpcm' tag.
1187 * See CoreAudioTypes and AudioStreamBasicDescription at Apple.
1188 */
1189 8 static int mov_get_lpcm_flags(enum AVCodecID codec_id)
1190 {
1191
1/6
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 8 times.
8 switch (codec_id) {
1192 case AV_CODEC_ID_PCM_F32BE:
1193 case AV_CODEC_ID_PCM_F64BE:
1194 return 11;
1195 case AV_CODEC_ID_PCM_F32LE:
1196 case AV_CODEC_ID_PCM_F64LE:
1197 return 9;
1198 case AV_CODEC_ID_PCM_U8:
1199 return 10;
1200 case AV_CODEC_ID_PCM_S16BE:
1201 case AV_CODEC_ID_PCM_S24BE:
1202 case AV_CODEC_ID_PCM_S32BE:
1203 return 14;
1204 case AV_CODEC_ID_PCM_S8:
1205 case AV_CODEC_ID_PCM_S16LE:
1206 case AV_CODEC_ID_PCM_S24LE:
1207 case AV_CODEC_ID_PCM_S32LE:
1208 return 12;
1209 8 default:
1210 8 return 0;
1211 }
1212 }
1213
1214 24899 static int get_cluster_duration(MOVTrack *track, int cluster_idx)
1215 {
1216 int64_t next_dts;
1217
1218
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24899 times.
24899 if (cluster_idx >= track->entry)
1219 return 0;
1220
1221
2/2
✓ Branch 0 taken 635 times.
✓ Branch 1 taken 24264 times.
24899 if (cluster_idx + 1 == track->entry)
1222 635 next_dts = track->track_duration + track->start_dts;
1223 else
1224 24264 next_dts = track->cluster[cluster_idx + 1].dts;
1225
1226 24899 next_dts -= track->cluster[cluster_idx].dts;
1227
1228
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24899 times.
24899 av_assert0(next_dts >= 0);
1229
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24899 times.
24899 av_assert0(next_dts <= INT_MAX);
1230
1231 24899 return next_dts;
1232 }
1233
1234 4 static int get_samples_per_packet(MOVTrack *track)
1235 {
1236 int i, first_duration;
1237
1238 /* use 1 for raw PCM */
1239
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!track->audio_vbr)
1240 return 1;
1241
1242 /* check to see if duration is constant for all clusters */
1243
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!track->entry)
1244 return 0;
1245 4 first_duration = get_cluster_duration(track, 0);
1246
1/2
✓ Branch 0 taken 1872 times.
✗ Branch 1 not taken.
1872 for (i = 1; i < track->entry; i++) {
1247
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1868 times.
1872 if (get_cluster_duration(track, i) != first_duration)
1248 4 return 0;
1249 }
1250 return first_duration;
1251 }
1252
1253 128 static int mov_write_btrt_tag(AVIOContext *pb, MOVTrack *track)
1254 {
1255 128 int64_t pos = avio_tell(pb);
1256 128 struct mpeg4_bit_rate_values bit_rates = calculate_mpeg4_bit_rates(track);
1257
3/4
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 47 times.
✓ Branch 2 taken 81 times.
✗ Branch 3 not taken.
128 if (!bit_rates.max_bit_rate && !bit_rates.avg_bit_rate &&
1258
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 !bit_rates.buffer_size)
1259 // no useful data to be written, skip
1260 81 return 0;
1261
1262 47 avio_wb32(pb, 0); /* size */
1263 47 ffio_wfourcc(pb, "btrt");
1264
1265 47 avio_wb32(pb, bit_rates.buffer_size);
1266 47 avio_wb32(pb, bit_rates.max_bit_rate);
1267 47 avio_wb32(pb, bit_rates.avg_bit_rate);
1268
1269 47 return update_size(pb, pos);
1270 }
1271
1272 5 static int mov_write_chnl_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
1273 {
1274 5 int64_t pos = avio_tell(pb);
1275 5 int config = 0;
1276 int ret;
1277 5 uint8_t *speaker_pos = NULL;
1278 5 const AVChannelLayout *layout = &track->par->ch_layout;
1279
1280 5 ret = ff_mov_get_channel_config_from_layout(layout, &config);
1281
3/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 1 times.
5 if (ret || !config) {
1282 4 config = 0;
1283 4 speaker_pos = av_malloc(layout->nb_channels);
1284
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!speaker_pos)
1285 return AVERROR(ENOMEM);
1286 4 ret = ff_mov_get_channel_positions_from_layout(layout,
1287 4 speaker_pos, layout->nb_channels);
1288
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret) {
1289 char buf[128] = {0};
1290
1291 av_freep(&speaker_pos);
1292 av_channel_layout_describe(layout, buf, sizeof(buf));
1293 av_log(s, AV_LOG_ERROR, "unsupported channel layout %s\n", buf);
1294 return ret;
1295 }
1296 }
1297
1298 5 avio_wb32(pb, 0); /* size */
1299 5 ffio_wfourcc(pb, "chnl");
1300 5 avio_wb32(pb, 0); /* version & flags */
1301
1302 5 avio_w8(pb, 1); /* stream_structure */
1303 5 avio_w8(pb, config);
1304
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if (config) {
1305 1 avio_wb64(pb, 0);
1306 } else {
1307 4 avio_write(pb, speaker_pos, layout->nb_channels);
1308 4 av_freep(&speaker_pos);
1309 }
1310
1311 5 return update_size(pb, pos);
1312 }
1313
1314 7 static int mov_write_pcmc_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
1315 {
1316 7 int64_t pos = avio_tell(pb);
1317 int format_flags;
1318 int sample_size;
1319
1320 7 avio_wb32(pb, 0); /* size */
1321 7 ffio_wfourcc(pb, "pcmC");
1322 7 avio_wb32(pb, 0); /* version & flags */
1323
1324 /* 0x01: indicates little-endian format */
1325 20 format_flags = (track->par->codec_id == AV_CODEC_ID_PCM_F32LE ||
1326
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 track->par->codec_id == AV_CODEC_ID_PCM_F64LE ||
1327
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 track->par->codec_id == AV_CODEC_ID_PCM_S16LE ||
1328
2/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
13 track->par->codec_id == AV_CODEC_ID_PCM_S24LE ||
1329 track->par->codec_id == AV_CODEC_ID_PCM_S32LE);
1330 7 avio_w8(pb, format_flags);
1331 7 sample_size = track->par->bits_per_raw_sample;
1332
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
7 if (!sample_size)
1333 1 sample_size = av_get_exact_bits_per_sample(track->par->codec_id);
1334
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 av_assert0(sample_size);
1335 7 avio_w8(pb, sample_size);
1336
1337 7 return update_size(pb, pos);
1338 }
1339
1340 107 static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
1341 {
1342 107 int64_t pos = avio_tell(pb);
1343 107 int version = 0;
1344 107 uint32_t tag = track->tag;
1345 107 int ret = 0;
1346
1347
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 67 times.
107 if (track->mode == MODE_MOV) {
1348
3/4
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 36 times.
40 if (track->timescale > UINT16_MAX || !track->par->ch_layout.nb_channels) {
1349
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (mov_get_lpcm_flags(track->par->codec_id))
1350 tag = AV_RL32("lpcm");
1351 4 version = 2;
1352
5/6
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 10 times.
✓ Branch 3 taken 26 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 24 times.
✓ Branch 6 taken 2 times.
62 } else if (track->audio_vbr || mov_pcm_le_gt16(track->par->codec_id) ||
1353 26 mov_pcm_be_gt16(track->par->codec_id) ||
1354
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 track->par->codec_id == AV_CODEC_ID_ADPCM_MS ||
1355
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 track->par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV ||
1356
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 track->par->codec_id == AV_CODEC_ID_QDM2) {
1357 12 version = 1;
1358 }
1359 }
1360
1361 107 avio_wb32(pb, 0); /* size */
1362
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107 times.
107 if (mov->encryption_scheme != MOV_ENC_NONE) {
1363 ffio_wfourcc(pb, "enca");
1364 } else {
1365 107 avio_wl32(pb, tag); // store it byteswapped
1366 }
1367 107 avio_wb32(pb, 0); /* Reserved */
1368 107 avio_wb16(pb, 0); /* Reserved */
1369 107 avio_wb16(pb, 1); /* Data-reference index, XXX == 1 */
1370
1371 /* SoundDescription */
1372 107 avio_wb16(pb, version); /* Version */
1373 107 avio_wb16(pb, 0); /* Revision level */
1374 107 avio_wb32(pb, 0); /* Reserved */
1375
1376
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 103 times.
107 if (version == 2) {
1377 4 avio_wb16(pb, 3);
1378 4 avio_wb16(pb, 16);
1379 4 avio_wb16(pb, 0xfffe);
1380 4 avio_wb16(pb, 0);
1381 4 avio_wb32(pb, 0x00010000);
1382 4 avio_wb32(pb, 72);
1383 4 avio_wb64(pb, av_double2int(track->par->sample_rate));
1384 4 avio_wb32(pb, track->par->ch_layout.nb_channels);
1385 4 avio_wb32(pb, 0x7F000000);
1386 4 avio_wb32(pb, av_get_bits_per_sample(track->par->codec_id));
1387 4 avio_wb32(pb, mov_get_lpcm_flags(track->par->codec_id));
1388 4 avio_wb32(pb, track->sample_size);
1389 4 avio_wb32(pb, get_samples_per_packet(track));
1390 } else {
1391
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 67 times.
103 if (track->mode == MODE_MOV) {
1392 36 avio_wb16(pb, track->par->ch_layout.nb_channels);
1393
1/2
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
36 if (track->par->codec_id == AV_CODEC_ID_PCM_U8 ||
1394
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 35 times.
36 track->par->codec_id == AV_CODEC_ID_PCM_S8)
1395 1 avio_wb16(pb, 8); /* bits per sample */
1396
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
35 else if (track->par->codec_id == AV_CODEC_ID_ADPCM_G726)
1397 avio_wb16(pb, track->par->bits_per_coded_sample);
1398 else
1399 35 avio_wb16(pb, 16);
1400
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 26 times.
36 avio_wb16(pb, track->audio_vbr ? -2 : 0); /* compression ID */
1401 } else { /* reserved for mp4/3gp */
1402
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 4 times.
130 avio_wb16(pb, track->tag == MKTAG('i', 'a', 'm', 'f') ?
1403 63 0 : track->par->ch_layout.nb_channels);
1404
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 4 times.
67 if (track->par->codec_id == AV_CODEC_ID_FLAC ||
1405
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 track->par->codec_id == AV_CODEC_ID_ALAC) {
1406 4 avio_wb16(pb, track->par->bits_per_raw_sample);
1407 } else {
1408 63 avio_wb16(pb, 16);
1409 }
1410 67 avio_wb16(pb, 0);
1411 }
1412
1413 103 avio_wb16(pb, 0); /* packet size (= 0) */
1414
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 99 times.
103 if (track->tag == MKTAG('i','a','m','f'))
1415 4 avio_wb16(pb, 0); /* samplerate must be 0 for IAMF */
1416
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 99 times.
99 else if (track->par->codec_id == AV_CODEC_ID_OPUS)
1417 avio_wb16(pb, 48000);
1418
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 99 times.
99 else if (track->par->codec_id == AV_CODEC_ID_TRUEHD)
1419 avio_wb32(pb, track->par->sample_rate);
1420 else
1421
1/2
✓ Branch 0 taken 99 times.
✗ Branch 1 not taken.
198 avio_wb16(pb, track->par->sample_rate <= UINT16_MAX ?
1422 99 track->par->sample_rate : 0);
1423
1424
1/2
✓ Branch 0 taken 103 times.
✗ Branch 1 not taken.
103 if (track->par->codec_id != AV_CODEC_ID_TRUEHD)
1425 103 avio_wb16(pb, 0); /* Reserved */
1426 }
1427
1428
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 95 times.
107 if (version == 1) { /* SoundDescription V1 extended info */
1429
3/4
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 10 times.
24 if (mov_pcm_le_gt16(track->par->codec_id) ||
1430 12 mov_pcm_be_gt16(track->par->codec_id))
1431 2 avio_wb32(pb, 1); /* must be 1 for uncompressed formats */
1432 else
1433 10 avio_wb32(pb, track->par->frame_size); /* Samples per packet */
1434 12 avio_wb32(pb, track->sample_size / track->par->ch_layout.nb_channels); /* Bytes per packet */
1435 12 avio_wb32(pb, track->sample_size); /* Bytes per frame */
1436 12 avio_wb32(pb, 2); /* Bytes per sample */
1437 }
1438
1439
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 67 times.
107 if (track->mode == MODE_MOV &&
1440
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 3 times.
40 (track->par->codec_id == AV_CODEC_ID_AAC ||
1441
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 1 times.
37 track->par->codec_id == AV_CODEC_ID_AC3 ||
1442
1/2
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
36 track->par->codec_id == AV_CODEC_ID_EAC3 ||
1443
1/2
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
36 track->par->codec_id == AV_CODEC_ID_AMR_NB ||
1444
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 9 times.
36 track->par->codec_id == AV_CODEC_ID_ALAC ||
1445
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 track->par->codec_id == AV_CODEC_ID_ADPCM_MS ||
1446
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 track->par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV ||
1447
2/4
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 27 times.
54 track->par->codec_id == AV_CODEC_ID_QDM2 ||
1448
2/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 25 times.
54 (mov_pcm_le_gt16(track->par->codec_id) && version==1) ||
1449
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
29 (mov_pcm_be_gt16(track->par->codec_id) && version==1)))
1450 15 ret = mov_write_wave_tag(s, pb, track);
1451
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 41 times.
92 else if (track->tag == MKTAG('m','p','4','a'))
1452 51 ret = mov_write_esds_tag(pb, track);
1453 #if CONFIG_IAMFENC
1454
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 37 times.
41 else if (track->tag == MKTAG('i','a','m','f'))
1455 4 ret = mov_write_iacb_tag(mov->fc, pb, track);
1456 #endif
1457
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
37 else if (track->par->codec_id == AV_CODEC_ID_AMR_NB)
1458 ret = mov_write_amr_tag(pb, track);
1459
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 33 times.
37 else if (track->par->codec_id == AV_CODEC_ID_AC3)
1460 4 ret = mov_write_ac3_tag(s, pb, track);
1461
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 32 times.
33 else if (track->par->codec_id == AV_CODEC_ID_EAC3)
1462 1 ret = mov_write_eac3_tag(s, pb, track);
1463
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 else if (track->par->codec_id == AV_CODEC_ID_ALAC)
1464 ret = mov_write_extradata_tag(pb, track);
1465
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 else if (track->par->codec_id == AV_CODEC_ID_WMAPRO)
1466 ret = mov_write_wfex_tag(s, pb, track);
1467
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 else if (track->par->codec_id == AV_CODEC_ID_FLAC)
1468 ret = mov_write_dfla_tag(pb, track);
1469
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 else if (track->par->codec_id == AV_CODEC_ID_OPUS)
1470 ret = mov_write_dops_tag(s, pb, track);
1471
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 else if (track->par->codec_id == AV_CODEC_ID_TRUEHD)
1472 ret = mov_write_dmlp_tag(s, pb, track);
1473
4/4
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 25 times.
32 else if (tag == MOV_MP4_IPCM_TAG || tag == MOV_MP4_FPCM_TAG) {
1474
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 2 times.
7 if (track->par->ch_layout.nb_channels > 1)
1475 5 ret = mov_write_chnl_tag(s, pb, track);
1476
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (ret < 0)
1477 return ret;
1478 7 ret = mov_write_pcmc_tag(s, pb, track);
1479
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 } else if (track->vos_len > 0)
1480 ret = mov_write_glbl_tag(pb, track);
1481
1482
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107 times.
107 if (ret < 0)
1483 return ret;
1484
1485
3/4
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 43 times.
✓ Branch 2 taken 64 times.
✗ Branch 3 not taken.
107 if (track->mode == MODE_MP4 && track->par->codec_type == AVMEDIA_TYPE_AUDIO
1486
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 64 times.
64 && ((ret = mov_write_SA3D_tag(s, pb, track)) < 0)) {
1487 return ret;
1488 }
1489
1490
3/4
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 67 times.
✓ Branch 2 taken 40 times.
✗ Branch 3 not taken.
107 if (track->mode == MODE_MOV && track->par->codec_type == AVMEDIA_TYPE_AUDIO
1491
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
40 && ((ret = mov_write_chan_tag(s, pb, track)) < 0)) {
1492 return ret;
1493 }
1494
1495
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107 times.
107 if (mov->encryption_scheme != MOV_ENC_NONE
1496 && ((ret = ff_mov_cenc_write_sinf_tag(track, pb, mov->encryption_kid)) < 0)) {
1497 return ret;
1498 }
1499
1500
3/4
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 43 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 64 times.
171 if (mov->write_btrt &&
1501 64 ((ret = mov_write_btrt_tag(pb, track)) < 0))
1502 return ret;
1503
1504 107 ret = update_size(pb, pos);
1505 107 return ret;
1506 }
1507
1508 static int mov_write_d263_tag(AVIOContext *pb)
1509 {
1510 avio_wb32(pb, 0xf); /* size */
1511 ffio_wfourcc(pb, "d263");
1512 ffio_wfourcc(pb, "FFMP");
1513 avio_w8(pb, 0); /* decoder version */
1514 /* FIXME use AVCodecContext level/profile, when encoder will set values */
1515 avio_w8(pb, 0xa); /* level */
1516 avio_w8(pb, 0); /* profile */
1517 return 0xf;
1518 }
1519
1520 1 static int mov_write_av1c_tag(AVIOContext *pb, MOVTrack *track)
1521 {
1522 1 int64_t pos = avio_tell(pb);
1523
1524 1 avio_wb32(pb, 0);
1525 1 ffio_wfourcc(pb, "av1C");
1526 1 ff_isom_write_av1c(pb, track->vos_data, track->vos_len, track->mode != MODE_AVIF);
1527 1 return update_size(pb, pos);
1528 }
1529
1530 52 static int mov_write_avcc_tag(AVIOContext *pb, MOVTrack *track)
1531 {
1532 52 int64_t pos = avio_tell(pb);
1533
1534 52 avio_wb32(pb, 0);
1535 52 ffio_wfourcc(pb, "avcC");
1536 52 ff_isom_write_avcc(pb, track->vos_data, track->vos_len);
1537 52 return update_size(pb, pos);
1538 }
1539
1540 static int mov_write_vpcc_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
1541 {
1542 int64_t pos = avio_tell(pb);
1543
1544 avio_wb32(pb, 0);
1545 ffio_wfourcc(pb, "vpcC");
1546 ff_isom_write_vpcc(s, pb, track->vos_data, track->vos_len, track->par);
1547 return update_size(pb, pos);
1548 }
1549
1550 3 static int mov_write_hvcc_tag(AVIOContext *pb, MOVTrack *track)
1551 {
1552 3 int64_t pos = avio_tell(pb);
1553
1554 3 avio_wb32(pb, 0);
1555 3 ffio_wfourcc(pb, "hvcC");
1556
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (track->tag == MKTAG('h','v','c','1'))
1557 1 ff_isom_write_hvcc(pb, track->vos_data, track->vos_len, 1);
1558 else
1559 2 ff_isom_write_hvcc(pb, track->vos_data, track->vos_len, 0);
1560 3 return update_size(pb, pos);
1561 }
1562
1563 1 static int mov_write_lhvc_tag(AVIOContext *pb, MOVTrack *track)
1564 {
1565 1 int64_t pos = avio_tell(pb);
1566 int ret;
1567
1568 1 avio_wb32(pb, 0);
1569 1 ffio_wfourcc(pb, "lhvC");
1570
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (track->tag == MKTAG('h','v','c','1'))
1571 1 ret = ff_isom_write_lhvc(pb, track->vos_data, track->vos_len, 1);
1572 else
1573 ret = ff_isom_write_lhvc(pb, track->vos_data, track->vos_len, 0);
1574
1575
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0) {
1576 avio_seek(pb, pos, SEEK_SET);
1577 return ret;
1578 }
1579
1580 1 return update_size(pb, pos);
1581 }
1582
1583 1 static int mov_write_evcc_tag(AVIOContext *pb, MOVTrack *track)
1584 {
1585 1 int64_t pos = avio_tell(pb);
1586
1587 1 avio_wb32(pb, 0);
1588 1 ffio_wfourcc(pb, "evcC");
1589
1590
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (track->tag == MKTAG('e','v','c','1'))
1591 1 ff_isom_write_evcc(pb, track->vos_data, track->vos_len, 1);
1592 else
1593 ff_isom_write_evcc(pb, track->vos_data, track->vos_len, 0);
1594
1595 1 return update_size(pb, pos);
1596 }
1597
1598 1 static int mov_write_vvcc_tag(AVIOContext *pb, MOVTrack *track)
1599 {
1600 1 int64_t pos = avio_tell(pb);
1601
1602 1 avio_wb32(pb, 0);
1603 1 ffio_wfourcc(pb, "vvcC");
1604
1605 1 avio_w8 (pb, 0); /* version */
1606 1 avio_wb24(pb, 0); /* flags */
1607
1608
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (track->tag == MKTAG('v','v','c','1'))
1609 1 ff_isom_write_vvcc(pb, track->vos_data, track->vos_len, 1);
1610 else
1611 ff_isom_write_vvcc(pb, track->vos_data, track->vos_len, 0);
1612 1 return update_size(pb, pos);
1613 }
1614
1615 /* also used by all avid codecs (dv, imx, meridien) and their variants */
1616 23 static int mov_write_avid_tag(AVIOContext *pb, MOVTrack *track)
1617 {
1618 int interlaced;
1619 int cid;
1620 23 int display_width = track->par->width;
1621
1622
2/4
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23 times.
✗ Branch 3 not taken.
23 if (track->vos_data && track->vos_len > 0x29) {
1623
1/2
✓ Branch 1 taken 23 times.
✗ Branch 2 not taken.
46 if (ff_dnxhd_parse_header_prefix(track->vos_data) != 0) {
1624 /* looks like a DNxHD bit stream */
1625 23 interlaced = (track->vos_data[5] & 2);
1626 23 cid = AV_RB32(track->vos_data + 0x28);
1627 } else {
1628 av_log(NULL, AV_LOG_WARNING, "Could not locate DNxHD bit stream in vos_data\n");
1629 return 0;
1630 }
1631 } else {
1632 av_log(NULL, AV_LOG_WARNING, "Could not locate DNxHD bit stream, vos_data too small\n");
1633 return 0;
1634 }
1635
1636 23 avio_wb32(pb, 24); /* size */
1637 23 ffio_wfourcc(pb, "ACLR");
1638 23 ffio_wfourcc(pb, "ACLR");
1639 23 ffio_wfourcc(pb, "0001");
1640
1/2
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
23 if (track->par->color_range == AVCOL_RANGE_MPEG || /* Legal range (16-235) */
1641
1/2
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
23 track->par->color_range == AVCOL_RANGE_UNSPECIFIED) {
1642 23 avio_wb32(pb, 1); /* Corresponds to 709 in official encoder */
1643 } else { /* Full range (0-255) */
1644 avio_wb32(pb, 2); /* Corresponds to RGB in official encoder */
1645 }
1646 23 avio_wb32(pb, 0); /* unknown */
1647
1648
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 11 times.
23 if (track->tag == MKTAG('A','V','d','h')) {
1649 12 avio_wb32(pb, 32);
1650 12 ffio_wfourcc(pb, "ADHR");
1651 12 ffio_wfourcc(pb, "0001");
1652 12 avio_wb32(pb, cid);
1653 12 avio_wb32(pb, 0); /* unknown */
1654 12 avio_wb32(pb, 1); /* unknown */
1655 12 avio_wb32(pb, 0); /* unknown */
1656 12 avio_wb32(pb, 0); /* unknown */
1657 12 return 0;
1658 }
1659
1660 11 avio_wb32(pb, 24); /* size */
1661 11 ffio_wfourcc(pb, "APRG");
1662 11 ffio_wfourcc(pb, "APRG");
1663 11 ffio_wfourcc(pb, "0001");
1664 11 avio_wb32(pb, 1); /* unknown */
1665 11 avio_wb32(pb, 0); /* unknown */
1666
1667 11 avio_wb32(pb, 120); /* size */
1668 11 ffio_wfourcc(pb, "ARES");
1669 11 ffio_wfourcc(pb, "ARES");
1670 11 ffio_wfourcc(pb, "0001");
1671 11 avio_wb32(pb, cid); /* dnxhd cid, some id ? */
1672
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if ( track->par->sample_aspect_ratio.num > 0
1673 && track->par->sample_aspect_ratio.den > 0)
1674 display_width = display_width * track->par->sample_aspect_ratio.num / track->par->sample_aspect_ratio.den;
1675 11 avio_wb32(pb, display_width);
1676 /* values below are based on samples created with quicktime and avid codecs */
1677
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (interlaced) {
1678 11 avio_wb32(pb, track->par->height / 2);
1679 11 avio_wb32(pb, 2); /* unknown */
1680 11 avio_wb32(pb, 0); /* unknown */
1681 11 avio_wb32(pb, 4); /* unknown */
1682 } else {
1683 avio_wb32(pb, track->par->height);
1684 avio_wb32(pb, 1); /* unknown */
1685 avio_wb32(pb, 0); /* unknown */
1686 if (track->par->height == 1080)
1687 avio_wb32(pb, 5); /* unknown */
1688 else
1689 avio_wb32(pb, 6); /* unknown */
1690 }
1691 /* padding */
1692 11 ffio_fill(pb, 0, 10 * 8);
1693
1694 11 return 0;
1695 }
1696
1697 static int mov_write_dpxe_tag(AVIOContext *pb, MOVTrack *track)
1698 {
1699 avio_wb32(pb, 12);
1700 ffio_wfourcc(pb, "DpxE");
1701 if (track->par->extradata_size >= 12 &&
1702 !memcmp(&track->par->extradata[4], "DpxE", 4)) {
1703 avio_wb32(pb, track->par->extradata[11]);
1704 } else {
1705 avio_wb32(pb, 1);
1706 }
1707 return 0;
1708 }
1709
1710 1 static int mov_get_dv_codec_tag(AVFormatContext *s, MOVTrack *track)
1711 {
1712 int tag;
1713
1714
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (track->par->width == 720) { /* SD */
1715
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (track->par->height == 480) { /* NTSC */
1716
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');
1717 1 else tag = MKTAG('d','v','c',' ');
1718 }else if (track->par->format == AV_PIX_FMT_YUV422P) tag = MKTAG('d','v','5','p');
1719 else if (track->par->format == AV_PIX_FMT_YUV420P) tag = MKTAG('d','v','c','p');
1720 else tag = MKTAG('d','v','p','p');
1721 } else if (track->par->height == 720) { /* HD 720 line */
1722 if (track->st->time_base.den == 50) tag = MKTAG('d','v','h','q');
1723 else tag = MKTAG('d','v','h','p');
1724 } else if (track->par->height == 1080) { /* HD 1080 line */
1725 if (track->st->time_base.den == 25) tag = MKTAG('d','v','h','5');
1726 else tag = MKTAG('d','v','h','6');
1727 } else {
1728 av_log(s, AV_LOG_ERROR, "unsupported height for dv codec\n");
1729 return 0;
1730 }
1731
1732 1 return tag;
1733 }
1734
1735 2 static int defined_frame_rate(AVFormatContext *s, AVStream *st)
1736 {
1737 2 AVRational rational_framerate = st->avg_frame_rate;
1738 2 int rate = 0;
1739
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (rational_framerate.den != 0)
1740 2 rate = av_q2d(rational_framerate);
1741 2 return rate;
1742 }
1743
1744 1 static int mov_get_mpeg2_xdcam_codec_tag(AVFormatContext *s, MOVTrack *track)
1745 {
1746 1 int tag = track->par->codec_tag;
1747 1 int interlaced = track->par->field_order > AV_FIELD_PROGRESSIVE;
1748 1 AVStream *st = track->st;
1749 1 int rate = defined_frame_rate(s, st);
1750
1751
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!tag)
1752 tag = MKTAG('m', '2', 'v', '1'); //fallback tag
1753
1754
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (track->par->format == AV_PIX_FMT_YUV420P) {
1755
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) {
1756 if (!interlaced) {
1757 if (rate == 24) tag = MKTAG('x','d','v','4');
1758 else if (rate == 25) tag = MKTAG('x','d','v','5');
1759 else if (rate == 30) tag = MKTAG('x','d','v','1');
1760 else if (rate == 50) tag = MKTAG('x','d','v','a');
1761 else if (rate == 60) tag = MKTAG('x','d','v','9');
1762 }
1763
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) {
1764 if (!interlaced) {
1765 if (rate == 24) tag = MKTAG('x','d','v','6');
1766 else if (rate == 25) tag = MKTAG('x','d','v','7');
1767 else if (rate == 30) tag = MKTAG('x','d','v','8');
1768 } else {
1769 if (rate == 25) tag = MKTAG('x','d','v','3');
1770 else if (rate == 30) tag = MKTAG('x','d','v','2');
1771 }
1772
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) {
1773 if (!interlaced) {
1774 if (rate == 24) tag = MKTAG('x','d','v','d');
1775 else if (rate == 25) tag = MKTAG('x','d','v','e');
1776 else if (rate == 30) tag = MKTAG('x','d','v','f');
1777 } else {
1778 if (rate == 25) tag = MKTAG('x','d','v','c');
1779 else if (rate == 30) tag = MKTAG('x','d','v','b');
1780 }
1781 }
1782 } else if (track->par->format == AV_PIX_FMT_YUV422P) {
1783 if (track->par->width == 1280 && track->par->height == 720) {
1784 if (!interlaced) {
1785 if (rate == 24) tag = MKTAG('x','d','5','4');
1786 else if (rate == 25) tag = MKTAG('x','d','5','5');
1787 else if (rate == 30) tag = MKTAG('x','d','5','1');
1788 else if (rate == 50) tag = MKTAG('x','d','5','a');
1789 else if (rate == 60) tag = MKTAG('x','d','5','9');
1790 }
1791 } else if (track->par->width == 1920 && track->par->height == 1080) {
1792 if (!interlaced) {
1793 if (rate == 24) tag = MKTAG('x','d','5','d');
1794 else if (rate == 25) tag = MKTAG('x','d','5','e');
1795 else if (rate == 30) tag = MKTAG('x','d','5','f');
1796 } else {
1797 if (rate == 25) tag = MKTAG('x','d','5','c');
1798 else if (rate == 30) tag = MKTAG('x','d','5','b');
1799 }
1800 }
1801 }
1802
1803 1 return tag;
1804 }
1805
1806 1 static int mov_get_h264_codec_tag(AVFormatContext *s, MOVTrack *track)
1807 {
1808 1 int tag = track->par->codec_tag;
1809 1 int interlaced = track->par->field_order > AV_FIELD_PROGRESSIVE;
1810 1 AVStream *st = track->st;
1811 1 int rate = defined_frame_rate(s, st);
1812
1813
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!tag)
1814 tag = MKTAG('a', 'v', 'c', 'i'); //fallback tag
1815
1816
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (track->par->format == AV_PIX_FMT_YUV420P10) {
1817 if (track->par->width == 960 && track->par->height == 720) {
1818 if (!interlaced) {
1819 if (rate == 24) tag = MKTAG('a','i','5','p');
1820 else if (rate == 25) tag = MKTAG('a','i','5','q');
1821 else if (rate == 30) tag = MKTAG('a','i','5','p');
1822 else if (rate == 50) tag = MKTAG('a','i','5','q');
1823 else if (rate == 60) tag = MKTAG('a','i','5','p');
1824 }
1825 } else if (track->par->width == 1440 && track->par->height == 1080) {
1826 if (!interlaced) {
1827 if (rate == 24) tag = MKTAG('a','i','5','3');
1828 else if (rate == 25) tag = MKTAG('a','i','5','2');
1829 else if (rate == 30) tag = MKTAG('a','i','5','3');
1830 } else {
1831 if (rate == 50) tag = MKTAG('a','i','5','5');
1832 else if (rate == 60) tag = MKTAG('a','i','5','6');
1833 }
1834 }
1835
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 } else if (track->par->format == AV_PIX_FMT_YUV422P10) {
1836 if (track->par->width == 1280 && track->par->height == 720) {
1837 if (!interlaced) {
1838 if (rate == 24) tag = MKTAG('a','i','1','p');
1839 else if (rate == 25) tag = MKTAG('a','i','1','q');
1840 else if (rate == 30) tag = MKTAG('a','i','1','p');
1841 else if (rate == 50) tag = MKTAG('a','i','1','q');
1842 else if (rate == 60) tag = MKTAG('a','i','1','p');
1843 }
1844 } else if (track->par->width == 1920 && track->par->height == 1080) {
1845 if (!interlaced) {
1846 if (rate == 24) tag = MKTAG('a','i','1','3');
1847 else if (rate == 25) tag = MKTAG('a','i','1','2');
1848 else if (rate == 30) tag = MKTAG('a','i','1','3');
1849 } else {
1850 if (rate == 25) tag = MKTAG('a','i','1','5');
1851 else if (rate == 50) tag = MKTAG('a','i','1','5');
1852 else if (rate == 60) tag = MKTAG('a','i','1','6');
1853 }
1854 } else if ( track->par->width == 4096 && track->par->height == 2160
1855 || track->par->width == 3840 && track->par->height == 2160
1856 || track->par->width == 2048 && track->par->height == 1080) {
1857 tag = MKTAG('a','i','v','x');
1858 }
1859 }
1860
1861 1 return tag;
1862 }
1863
1864 static int mov_get_evc_codec_tag(AVFormatContext *s, MOVTrack *track)
1865 {
1866 int tag = track->par->codec_tag;
1867
1868 if (!tag)
1869 tag = MKTAG('e', 'v', 'c', '1');
1870
1871 return tag;
1872 }
1873
1874 static const struct {
1875 enum AVPixelFormat pix_fmt;
1876 uint32_t tag;
1877 unsigned bps;
1878 } mov_pix_fmt_tags[] = {
1879 { AV_PIX_FMT_YUYV422, MKTAG('y','u','v','2'), 0 },
1880 { AV_PIX_FMT_YUYV422, MKTAG('y','u','v','s'), 0 },
1881 { AV_PIX_FMT_UYVY422, MKTAG('2','v','u','y'), 0 },
1882 { AV_PIX_FMT_RGB555BE,MKTAG('r','a','w',' '), 16 },
1883 { AV_PIX_FMT_RGB555LE,MKTAG('L','5','5','5'), 16 },
1884 { AV_PIX_FMT_RGB565LE,MKTAG('L','5','6','5'), 16 },
1885 { AV_PIX_FMT_RGB565BE,MKTAG('B','5','6','5'), 16 },
1886 { AV_PIX_FMT_GRAY16BE,MKTAG('b','1','6','g'), 16 },
1887 { AV_PIX_FMT_RGB24, MKTAG('r','a','w',' '), 24 },
1888 { AV_PIX_FMT_BGR24, MKTAG('2','4','B','G'), 24 },
1889 { AV_PIX_FMT_ARGB, MKTAG('r','a','w',' '), 32 },
1890 { AV_PIX_FMT_BGRA, MKTAG('B','G','R','A'), 32 },
1891 { AV_PIX_FMT_RGBA, MKTAG('R','G','B','A'), 32 },
1892 { AV_PIX_FMT_ABGR, MKTAG('A','B','G','R'), 32 },
1893 { AV_PIX_FMT_RGB48BE, MKTAG('b','4','8','r'), 48 },
1894 };
1895
1896 23 static int mov_get_dnxhd_codec_tag(AVFormatContext *s, MOVTrack *track)
1897 {
1898 23 int tag = MKTAG('A','V','d','n');
1899
1/2
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
23 if (track->par->profile != AV_PROFILE_UNKNOWN &&
1900
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 11 times.
23 track->par->profile != AV_PROFILE_DNXHD)
1901 12 tag = MKTAG('A','V','d','h');
1902 23 return tag;
1903 }
1904
1905 13 static int mov_get_rawvideo_codec_tag(AVFormatContext *s, MOVTrack *track)
1906 {
1907 13 int tag = track->par->codec_tag;
1908 int i;
1909 enum AVPixelFormat pix_fmt;
1910
1911
2/2
✓ Branch 0 taken 189 times.
✓ Branch 1 taken 12 times.
201 for (i = 0; i < FF_ARRAY_ELEMS(mov_pix_fmt_tags); i++) {
1912
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 176 times.
189 if (track->par->format == mov_pix_fmt_tags[i].pix_fmt) {
1913 13 tag = mov_pix_fmt_tags[i].tag;
1914 13 track->par->bits_per_coded_sample = mov_pix_fmt_tags[i].bps;
1915
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12 times.
13 if (track->par->codec_tag == mov_pix_fmt_tags[i].tag)
1916 1 break;
1917 }
1918 }
1919
1920 13 pix_fmt = avpriv_pix_fmt_find(PIX_FMT_LIST_MOV,
1921 13 track->par->bits_per_coded_sample);
1922
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12 times.
13 if (tag == MKTAG('r','a','w',' ') &&
1923
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 track->par->format != pix_fmt &&
1924 track->par->format != AV_PIX_FMT_GRAY8 &&
1925 track->par->format != AV_PIX_FMT_NONE)
1926 av_log(s, AV_LOG_ERROR, "%s rawvideo cannot be written to mov, output file will be unreadable\n",
1927 av_get_pix_fmt_name(track->par->format));
1928 13 return tag;
1929 }
1930
1931 160 static unsigned int mov_get_codec_tag(AVFormatContext *s, MOVTrack *track)
1932 {
1933 160 unsigned int tag = track->par->codec_tag;
1934
1935 // "rtp " is used to distinguish internally created RTP-hint tracks
1936 // (with rtp_ctx) from other tracks.
1937
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 160 times.
160 if (tag == MKTAG('r','t','p',' '))
1938 tag = 0;
1939
3/4
✓ Branch 0 taken 160 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 124 times.
✓ Branch 3 taken 36 times.
160 if (!tag || (s->strict_std_compliance >= FF_COMPLIANCE_NORMAL &&
1940
2/2
✓ Branch 0 taken 123 times.
✓ Branch 1 taken 1 times.
124 (track->par->codec_id == AV_CODEC_ID_DVVIDEO ||
1941
2/2
✓ Branch 0 taken 110 times.
✓ Branch 1 taken 13 times.
123 track->par->codec_id == AV_CODEC_ID_RAWVIDEO ||
1942
1/2
✓ Branch 0 taken 110 times.
✗ Branch 1 not taken.
110 track->par->codec_id == AV_CODEC_ID_H263 ||
1943
2/2
✓ Branch 0 taken 109 times.
✓ Branch 1 taken 1 times.
110 track->par->codec_id == AV_CODEC_ID_H264 ||
1944
2/2
✓ Branch 0 taken 86 times.
✓ Branch 1 taken 23 times.
109 track->par->codec_id == AV_CODEC_ID_DNXHD ||
1945
4/4
✓ Branch 0 taken 85 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 67 times.
171 track->par->codec_id == AV_CODEC_ID_MPEG2VIDEO ||
1946 85 av_get_bits_per_sample(track->par->codec_id)))) { // pcm audio
1947
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 56 times.
57 if (track->par->codec_id == AV_CODEC_ID_DVVIDEO)
1948 1 tag = mov_get_dv_codec_tag(s, track);
1949
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 43 times.
56 else if (track->par->codec_id == AV_CODEC_ID_RAWVIDEO)
1950 13 tag = mov_get_rawvideo_codec_tag(s, track);
1951
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 42 times.
43 else if (track->par->codec_id == AV_CODEC_ID_MPEG2VIDEO)
1952 1 tag = mov_get_mpeg2_xdcam_codec_tag(s, track);
1953
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 41 times.
42 else if (track->par->codec_id == AV_CODEC_ID_H264)
1954 1 tag = mov_get_h264_codec_tag(s, track);
1955
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 else if (track->par->codec_id == AV_CODEC_ID_EVC)
1956 tag = mov_get_evc_codec_tag(s, track);
1957
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 18 times.
41 else if (track->par->codec_id == AV_CODEC_ID_DNXHD)
1958 23 tag = mov_get_dnxhd_codec_tag(s, track);
1959
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 else if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
1960 tag = ff_codec_get_tag(ff_codec_movvideo_tags, track->par->codec_id);
1961 if (!tag) { // if no mac fcc found, try with Microsoft tags
1962 tag = ff_codec_get_tag(ff_codec_bmp_tags, track->par->codec_id);
1963 if (tag)
1964 av_log(s, AV_LOG_WARNING, "Using MS style video codec tag, "
1965 "the file may be unplayable!\n");
1966 }
1967
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) {
1968 18 tag = ff_codec_get_tag(ff_codec_movaudio_tags, track->par->codec_id);
1969
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!tag) { // if no mac fcc found, try with Microsoft tags
1970 int ms_tag = ff_codec_get_tag(ff_codec_wav_tags, track->par->codec_id);
1971 if (ms_tag) {
1972 tag = MKTAG('m', 's', ((ms_tag >> 8) & 0xff), (ms_tag & 0xff));
1973 av_log(s, AV_LOG_WARNING, "Using MS style audio codec tag, "
1974 "the file may be unplayable!\n");
1975 }
1976 }
1977 } else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE)
1978 tag = ff_codec_get_tag(ff_codec_movsubtitle_tags, track->par->codec_id);
1979 }
1980
1981 160 return tag;
1982 }
1983
1984 static const AVCodecTag codec_cover_image_tags[] = {
1985 { AV_CODEC_ID_MJPEG, 0xD },
1986 { AV_CODEC_ID_PNG, 0xE },
1987 { AV_CODEC_ID_BMP, 0x1B },
1988 { AV_CODEC_ID_NONE, 0 },
1989 };
1990
1991 93 static unsigned int validate_codec_tag(const AVCodecTag *const *tags,
1992 unsigned int tag, int codec_id)
1993 {
1994 int i;
1995
1996 /**
1997 * Check that tag + id is in the table
1998 */
1999
2/4
✓ Branch 0 taken 93 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 93 times.
✗ Branch 3 not taken.
93 for (i = 0; tags && tags[i]; i++) {
2000 93 const AVCodecTag *codec_tags = tags[i];
2001
1/2
✓ Branch 0 taken 1289 times.
✗ Branch 1 not taken.
1289 while (codec_tags->id != AV_CODEC_ID_NONE) {
2002
2/2
✓ Branch 2 taken 105 times.
✓ Branch 3 taken 1184 times.
1289 if (ff_toupper4(codec_tags->tag) == ff_toupper4(tag) &&
2003
2/2
✓ Branch 0 taken 93 times.
✓ Branch 1 taken 12 times.
105 codec_tags->id == codec_id)
2004 93 return codec_tags->tag;
2005 1196 codec_tags++;
2006 }
2007 }
2008 return 0;
2009 }
2010
2011 255 static unsigned int mov_find_codec_tag(AVFormatContext *s, MOVTrack *track)
2012 {
2013
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 253 times.
255 if (is_cover_image(track->st))
2014 2 return ff_codec_get_tag(codec_cover_image_tags, track->par->codec_id);
2015
2016
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 252 times.
253 if (track->mode == MODE_IPOD)
2017
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") &&
2018
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 !av_match_ext(s->url, "m4v") &&
2019 1 !av_match_ext(s->url, "m4b"))
2020 1 av_log(s, AV_LOG_WARNING, "Warning, extension is not .m4a nor .m4v "
2021 "Quicktime/Ipod might not play the file\n");
2022
2023
2/2
✓ Branch 0 taken 160 times.
✓ Branch 1 taken 93 times.
253 if (track->mode == MODE_MOV) {
2024 160 return mov_get_codec_tag(s, track);
2025 } else
2026 93 return validate_codec_tag(s->oformat->codec_tag, track->par->codec_tag,
2027 93 track->par->codec_id);
2028 }
2029
2030 /** Write uuid atom.
2031 * Needed to make file play in iPods running newest firmware
2032 * goes after avcC atom in moov.trak.mdia.minf.stbl.stsd.avc1
2033 */
2034 static int mov_write_uuid_tag_ipod(AVIOContext *pb)
2035 {
2036 avio_wb32(pb, 28);
2037 ffio_wfourcc(pb, "uuid");
2038 avio_wb32(pb, 0x6b6840f2);
2039 avio_wb32(pb, 0x5f244fc5);
2040 avio_wb32(pb, 0xba39a51b);
2041 avio_wb32(pb, 0xcf0323f3);
2042 avio_wb32(pb, 0x0);
2043 return 28;
2044 }
2045
2046 static const uint16_t fiel_data[] = {
2047 0x0000, 0x0100, 0x0201, 0x0206, 0x0209, 0x020e
2048 };
2049
2050 91 static int mov_write_fiel_tag(AVIOContext *pb, MOVTrack *track, int field_order)
2051 {
2052 91 unsigned mov_field_order = 0;
2053
1/2
✓ Branch 0 taken 91 times.
✗ Branch 1 not taken.
91 if (field_order < FF_ARRAY_ELEMS(fiel_data))
2054 91 mov_field_order = fiel_data[field_order];
2055 else
2056 return 0;
2057 91 avio_wb32(pb, 10);
2058 91 ffio_wfourcc(pb, "fiel");
2059 91 avio_wb16(pb, mov_field_order);
2060 91 return 10;
2061 }
2062
2063 4 static int mov_write_subtitle_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
2064 {
2065 4 MOVMuxContext *mov = s->priv_data;
2066 4 int ret = AVERROR_BUG;
2067 4 int64_t pos = avio_tell(pb);
2068 4 avio_wb32(pb, 0); /* size */
2069 4 avio_wl32(pb, track->tag); // store it byteswapped
2070 4 avio_wb32(pb, 0); /* Reserved */
2071 4 avio_wb16(pb, 0); /* Reserved */
2072 4 avio_wb16(pb, 1); /* Data-reference index */
2073
2074
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (track->par->codec_id == AV_CODEC_ID_DVD_SUBTITLE)
2075 mov_write_esds_tag(pb, track);
2076
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 else if (track->par->codec_id == AV_CODEC_ID_TTML) {
2077
2/3
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 switch (track->par->codec_tag) {
2078 1 case MOV_ISMV_TTML_TAG:
2079 // ISMV dfxp requires no extradata.
2080 2 break;
2081 1 case MOV_MP4_TTML_TAG:
2082 // As specified in 14496-30, XMLSubtitleSampleEntry
2083 // Namespace
2084 1 avio_put_str(pb, "http://www.w3.org/ns/ttml");
2085 // Empty schema_location
2086 1 avio_w8(pb, 0);
2087 // Empty auxiliary_mime_types
2088 1 avio_w8(pb, 0);
2089 1 break;
2090 default:
2091 av_log(NULL, AV_LOG_ERROR,
2092 "Unknown codec tag '%s' utilized for TTML stream with "
2093 "index %d (track id %d)!\n",
2094 av_fourcc2str(track->par->codec_tag), track->st->index,
2095 track->track_id);
2096 return AVERROR(EINVAL);
2097 }
2098
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 } else if (track->par->extradata_size)
2099 2 avio_write(pb, track->par->extradata, track->par->extradata_size);
2100
2101
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
8 if (mov->write_btrt &&
2102 4 ((ret = mov_write_btrt_tag(pb, track)) < 0))
2103 return ret;
2104
2105 4 return update_size(pb, pos);
2106 }
2107
2108 static int mov_write_st3d_tag(AVFormatContext *s, AVIOContext *pb, AVStereo3D *stereo_3d)
2109 {
2110 int8_t stereo_mode;
2111
2112 if (stereo_3d->flags != 0) {
2113 av_log(s, AV_LOG_WARNING, "Unsupported stereo_3d flags %x. st3d not written.\n", stereo_3d->flags);
2114 return 0;
2115 }
2116
2117 switch (stereo_3d->type) {
2118 case AV_STEREO3D_2D:
2119 stereo_mode = 0;
2120 break;
2121 case AV_STEREO3D_TOPBOTTOM:
2122 stereo_mode = 1;
2123 break;
2124 case AV_STEREO3D_SIDEBYSIDE:
2125 stereo_mode = 2;
2126 break;
2127 default:
2128 av_log(s, AV_LOG_WARNING, "Unsupported stereo_3d type %s. st3d not written.\n", av_stereo3d_type_name(stereo_3d->type));
2129 return 0;
2130 }
2131 avio_wb32(pb, 13); /* size */
2132 ffio_wfourcc(pb, "st3d");
2133 avio_wb32(pb, 0); /* version = 0 & flags = 0 */
2134 avio_w8(pb, stereo_mode);
2135 return 13;
2136 }
2137
2138 static int mov_write_sv3d_tag(AVFormatContext *s, AVIOContext *pb, AVSphericalMapping *spherical_mapping)
2139 {
2140 int64_t sv3d_pos, svhd_pos, proj_pos;
2141 const char* metadata_source = s->flags & AVFMT_FLAG_BITEXACT ? "Lavf" : LIBAVFORMAT_IDENT;
2142
2143 if (spherical_mapping->projection != AV_SPHERICAL_EQUIRECTANGULAR &&
2144 spherical_mapping->projection != AV_SPHERICAL_EQUIRECTANGULAR_TILE &&
2145 spherical_mapping->projection != AV_SPHERICAL_CUBEMAP) {
2146 av_log(s, AV_LOG_WARNING, "Unsupported projection %d. sv3d not written.\n", spherical_mapping->projection);
2147 return 0;
2148 }
2149
2150 sv3d_pos = avio_tell(pb);
2151 avio_wb32(pb, 0); /* size */
2152 ffio_wfourcc(pb, "sv3d");
2153
2154 svhd_pos = avio_tell(pb);
2155 avio_wb32(pb, 0); /* size */
2156 ffio_wfourcc(pb, "svhd");
2157 avio_wb32(pb, 0); /* version = 0 & flags = 0 */
2158 avio_put_str(pb, metadata_source);
2159 update_size(pb, svhd_pos);
2160
2161 proj_pos = avio_tell(pb);
2162 avio_wb32(pb, 0); /* size */
2163 ffio_wfourcc(pb, "proj");
2164
2165 avio_wb32(pb, 24); /* size */
2166 ffio_wfourcc(pb, "prhd");
2167 avio_wb32(pb, 0); /* version = 0 & flags = 0 */
2168 avio_wb32(pb, spherical_mapping->yaw);
2169 avio_wb32(pb, spherical_mapping->pitch);
2170 avio_wb32(pb, spherical_mapping->roll);
2171
2172 switch (spherical_mapping->projection) {
2173 case AV_SPHERICAL_EQUIRECTANGULAR:
2174 case AV_SPHERICAL_EQUIRECTANGULAR_TILE:
2175 avio_wb32(pb, 28); /* size */
2176 ffio_wfourcc(pb, "equi");
2177 avio_wb32(pb, 0); /* version = 0 & flags = 0 */
2178 avio_wb32(pb, spherical_mapping->bound_top);
2179 avio_wb32(pb, spherical_mapping->bound_bottom);
2180 avio_wb32(pb, spherical_mapping->bound_left);
2181 avio_wb32(pb, spherical_mapping->bound_right);
2182 break;
2183 case AV_SPHERICAL_CUBEMAP:
2184 avio_wb32(pb, 20); /* size */
2185 ffio_wfourcc(pb, "cbmp");
2186 avio_wb32(pb, 0); /* version = 0 & flags = 0 */
2187 avio_wb32(pb, 0); /* layout */
2188 avio_wb32(pb, spherical_mapping->padding); /* padding */
2189 break;
2190 }
2191 update_size(pb, proj_pos);
2192
2193 return update_size(pb, sv3d_pos);
2194 }
2195
2196 5 static inline int64_t rescale_rational(AVRational q, int b)
2197 {
2198 5 return av_rescale(q.num, b, q.den);
2199 }
2200
2201 1 static void mov_write_hfov_tag(AVFormatContext *s, AVIOContext *pb,
2202 const AVStereo3D *stereo3d)
2203 {
2204
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!stereo3d->horizontal_field_of_view.num)
2205 return;
2206
2207 1 avio_wb32(pb, 12); /* size */
2208 1 ffio_wfourcc(pb, "hfov");
2209 1 avio_wb32(pb, rescale_rational(stereo3d->horizontal_field_of_view, 1000));
2210 }
2211
2212 1 static void mov_write_vexu_proj_tag(AVFormatContext *s, AVIOContext *pb,
2213 const AVSphericalMapping *spherical_mapping)
2214 {
2215 1 avio_wb32(pb, 24); /* size */
2216 1 ffio_wfourcc(pb, "proj");
2217 1 avio_wb32(pb, 16); /* size */
2218 1 ffio_wfourcc(pb, "prji");
2219 1 avio_wb32(pb, 0); /* version + flags */
2220
2221
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) {
2222 1 case AV_SPHERICAL_RECTILINEAR:
2223 1 ffio_wfourcc(pb, "rect");
2224 1 break;
2225 case AV_SPHERICAL_EQUIRECTANGULAR:
2226 ffio_wfourcc(pb, "equi");
2227 break;
2228 case AV_SPHERICAL_HALF_EQUIRECTANGULAR:
2229 ffio_wfourcc(pb, "hequ");
2230 break;
2231 case AV_SPHERICAL_FISHEYE:
2232 ffio_wfourcc(pb, "fish");
2233 break;
2234 default:
2235 av_assert0(0);
2236 }
2237 1 }
2238
2239 1 static int mov_write_eyes_tag(AVFormatContext *s, AVIOContext *pb,
2240 const AVStereo3D *stereo3d)
2241 {
2242 1 int64_t pos = avio_tell(pb);
2243 1 int view = 0;
2244
2245 1 avio_wb32(pb, 0); /* size */
2246 1 ffio_wfourcc(pb, "eyes");
2247
2248 // stri is mandatory
2249 1 avio_wb32(pb, 13); /* size */
2250 1 ffio_wfourcc(pb, "stri");
2251 1 avio_wb32(pb, 0); /* version + flags */
2252
1/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 switch (stereo3d->view) {
2253 case AV_STEREO3D_VIEW_LEFT:
2254 view |= 1 << 0;
2255 break;
2256 case AV_STEREO3D_VIEW_RIGHT:
2257 view |= 1 << 1;
2258 break;
2259 1 case AV_STEREO3D_VIEW_PACKED:
2260 1 view |= (1 << 0) | (1 << 1);
2261 1 break;
2262 }
2263 1 view |= !!(stereo3d->flags & AV_STEREO3D_FLAG_INVERT) << 3;
2264 1 avio_w8(pb, view);
2265
2266 // hero is optional
2267
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (stereo3d->primary_eye != AV_PRIMARY_EYE_NONE) {
2268 avio_wb32(pb, 13); /* size */
2269 ffio_wfourcc(pb, "hero");
2270 avio_wb32(pb, 0); /* version + flags */
2271 avio_w8(pb, stereo3d->primary_eye);
2272 }
2273
2274 // it's not clear if cams is mandatory or optional
2275
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (stereo3d->baseline) {
2276 1 avio_wb32(pb, 24); /* size */
2277 1 ffio_wfourcc(pb, "cams");
2278 1 avio_wb32(pb, 16); /* size */
2279 1 ffio_wfourcc(pb, "blin");
2280 1 avio_wb32(pb, 0); /* version + flags */
2281 1 avio_wb32(pb, stereo3d->baseline);
2282 }
2283
2284 // it's not clear if cmfy is mandatory or optional
2285
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (stereo3d->horizontal_disparity_adjustment.num) {
2286 1 avio_wb32(pb, 24); /* size */
2287 1 ffio_wfourcc(pb, "cmfy");
2288 1 avio_wb32(pb, 16); /* size */
2289 1 ffio_wfourcc(pb, "dadj");
2290 1 avio_wb32(pb, 0); /* version + flags */
2291 1 avio_wb32(pb, rescale_rational(stereo3d->horizontal_disparity_adjustment, 10000));
2292 }
2293
2294 1 return update_size(pb, pos);
2295 }
2296
2297 1 static int mov_write_vexu_tag(AVFormatContext *s, AVIOContext *pb,
2298 const AVStereo3D *stereo3d,
2299 const AVSphericalMapping *spherical_mapping)
2300 {
2301 int64_t pos;
2302
2303
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (spherical_mapping &&
2304
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 spherical_mapping->projection != AV_SPHERICAL_RECTILINEAR &&
2305 spherical_mapping->projection != AV_SPHERICAL_EQUIRECTANGULAR &&
2306 spherical_mapping->projection != AV_SPHERICAL_HALF_EQUIRECTANGULAR &&
2307 spherical_mapping->projection != AV_SPHERICAL_FISHEYE) {
2308 av_log(s, AV_LOG_WARNING, "Unsupported projection %d. proj not written.\n",
2309 spherical_mapping->projection);
2310 spherical_mapping = NULL;
2311 }
2312
2313
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 if (stereo3d && (stereo3d->type == AV_STEREO3D_2D ||
2314
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 (!(stereo3d->flags & AV_STEREO3D_FLAG_INVERT) &&
2315
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 stereo3d->view == AV_STEREO3D_VIEW_UNSPEC &&
2316 stereo3d->primary_eye == AV_PRIMARY_EYE_NONE &&
2317 !stereo3d->baseline &&
2318 !stereo3d->horizontal_disparity_adjustment.num))) {
2319 av_log(s, AV_LOG_WARNING, "Unsupported stereo 3d metadata. eyes not written.\n");
2320 stereo3d = NULL;
2321 }
2322
2323
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 if (!spherical_mapping && !stereo3d)
2324 return 0;
2325
2326 1 pos = avio_tell(pb);
2327 1 avio_wb32(pb, 0); /* size */
2328 1 ffio_wfourcc(pb, "vexu");
2329
2330
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (spherical_mapping)
2331 1 mov_write_vexu_proj_tag(s, pb, spherical_mapping);
2332
2333
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (stereo3d)
2334 1 mov_write_eyes_tag(s, pb, stereo3d);
2335
2336 1 return update_size(pb, pos);
2337 }
2338
2339 static int mov_write_dvcc_dvvc_tag(AVFormatContext *s, AVIOContext *pb, AVDOVIDecoderConfigurationRecord *dovi)
2340 {
2341 uint8_t buf[ISOM_DVCC_DVVC_SIZE];
2342
2343 avio_wb32(pb, 32); /* size = 8 + 24 */
2344 if (dovi->dv_profile > 10)
2345 ffio_wfourcc(pb, "dvwC");
2346 else if (dovi->dv_profile > 7)
2347 ffio_wfourcc(pb, "dvvC");
2348 else
2349 ffio_wfourcc(pb, "dvcC");
2350
2351 ff_isom_put_dvcc_dvvc(s, buf, dovi);
2352 avio_write(pb, buf, sizeof(buf));
2353
2354 return 32; /* 8 + 24 */
2355 }
2356
2357 1 static int mov_write_clap_tag(AVIOContext *pb, MOVTrack *track,
2358 uint32_t top, uint32_t bottom,
2359 uint32_t left, uint32_t right)
2360 {
2361 1 uint32_t cropped_width = track->par->width - left - right;
2362 1 uint32_t cropped_height = track->height - top - bottom;
2363 AVRational horizOff =
2364 1 av_sub_q((AVRational) { track->par->width - cropped_width, 2 },
2365 1 (AVRational) { left, 1 });
2366 AVRational vertOff =
2367 1 av_sub_q((AVRational) { track->height - cropped_height, 2 },
2368 1 (AVRational) { top, 1 });
2369
2370 1 avio_wb32(pb, 40);
2371 1 ffio_wfourcc(pb, "clap");
2372 1 avio_wb32(pb, cropped_width); /* apertureWidthN */
2373 1 avio_wb32(pb, 1); /* apertureWidthD */
2374 1 avio_wb32(pb, cropped_height); /* apertureHeightN */
2375 1 avio_wb32(pb, 1); /* apertureHeightD */
2376
2377 1 avio_wb32(pb, -horizOff.num);
2378 1 avio_wb32(pb, horizOff.den);
2379 1 avio_wb32(pb, -vertOff.num);
2380 1 avio_wb32(pb, vertOff.den);
2381
2382 1 return 40;
2383 }
2384
2385 6 static int mov_write_pasp_tag(AVIOContext *pb, MOVTrack *track)
2386 {
2387 AVRational sar;
2388 6 av_reduce(&sar.num, &sar.den, track->par->sample_aspect_ratio.num,
2389 6 track->par->sample_aspect_ratio.den, INT_MAX);
2390
2391 6 avio_wb32(pb, 16);
2392 6 ffio_wfourcc(pb, "pasp");
2393 6 avio_wb32(pb, sar.num);
2394 6 avio_wb32(pb, sar.den);
2395 6 return 16;
2396 }
2397
2398 static int mov_write_gama_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track, double gamma)
2399 {
2400 uint32_t gama = 0;
2401 if (gamma <= 0.0)
2402 gamma = av_csp_approximate_trc_gamma(track->par->color_trc);
2403 av_log(s, AV_LOG_DEBUG, "gamma value %g\n", gamma);
2404
2405 if (gamma > 1e-6) {
2406 gama = (uint32_t)lrint((double)(1<<16) * gamma);
2407 av_log(s, AV_LOG_DEBUG, "writing gama value %"PRId32"\n", gama);
2408
2409 av_assert0(track->mode == MODE_MOV);
2410 avio_wb32(pb, 12);
2411 ffio_wfourcc(pb, "gama");
2412 avio_wb32(pb, gama);
2413 return 12;
2414 } else {
2415 av_log(s, AV_LOG_WARNING, "gamma value unknown, unable to write gama atom\n");
2416 }
2417 return 0;
2418 }
2419
2420 9 static int mov_write_colr_tag(AVIOContext *pb, MOVTrack *track, int prefer_icc)
2421 {
2422 9 int64_t pos = avio_tell(pb);
2423
2424 // Ref (MOV): https://developer.apple.com/library/mac/technotes/tn2162/_index.html#//apple_ref/doc/uid/DTS40013070-CH1-TNTAG9
2425 // Ref (MP4): ISO/IEC 14496-12:2012
2426
2427
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 5 times.
9 if (prefer_icc) {
2428 4 const AVPacketSideData *sd = av_packet_side_data_get(track->st->codecpar->coded_side_data,
2429 4 track->st->codecpar->nb_coded_side_data,
2430 AV_PKT_DATA_ICC_PROFILE);
2431
2432
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (sd) {
2433 avio_wb32(pb, 12 + sd->size);
2434 ffio_wfourcc(pb, "colr");
2435 ffio_wfourcc(pb, "prof");
2436 avio_write(pb, sd->data, sd->size);
2437 return 12 + sd->size;
2438 }
2439 else {
2440 4 av_log(NULL, AV_LOG_INFO, "no ICC profile found, will write nclx/nclc colour info instead\n");
2441 }
2442 }
2443
2444 /* We should only ever be called for MOV, MP4 and AVIF. */
2445
3/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
9 av_assert0(track->mode == MODE_MOV || track->mode == MODE_MP4 ||
2446 track->mode == MODE_AVIF);
2447
2448 9 avio_wb32(pb, 0); /* size */
2449 9 ffio_wfourcc(pb, "colr");
2450
3/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
9 if (track->mode == MODE_MP4 || track->mode == MODE_AVIF)
2451 1 ffio_wfourcc(pb, "nclx");
2452 else
2453 8 ffio_wfourcc(pb, "nclc");
2454 // Do not try to guess the color info if it is AVCOL_PRI_UNSPECIFIED.
2455 // e.g., Dolby Vision for Apple devices should be set to AVCOL_PRI_UNSPECIFIED. See
2456 // https://developer.apple.com/av-foundation/High-Dynamic-Range-Metadata-for-Apple-Devices.pdf
2457 9 avio_wb16(pb, track->par->color_primaries);
2458 9 avio_wb16(pb, track->par->color_trc);
2459 9 avio_wb16(pb, track->par->color_space);
2460
3/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
9 if (track->mode == MODE_MP4 || track->mode == MODE_AVIF) {
2461 1 int full_range = track->par->color_range == AVCOL_RANGE_JPEG;
2462 1 avio_w8(pb, full_range << 7);
2463 }
2464
2465 9 return update_size(pb, pos);
2466 }
2467
2468 193 static int mov_write_clli_tag(AVIOContext *pb, MOVTrack *track)
2469 {
2470 const AVPacketSideData *side_data;
2471 const AVContentLightMetadata *content_light_metadata;
2472
2473 193 side_data = av_packet_side_data_get(track->st->codecpar->coded_side_data,
2474 193 track->st->codecpar->nb_coded_side_data,
2475 AV_PKT_DATA_CONTENT_LIGHT_LEVEL);
2476
1/2
✓ Branch 0 taken 193 times.
✗ Branch 1 not taken.
193 if (!side_data) {
2477 193 return 0;
2478 }
2479 content_light_metadata = (const AVContentLightMetadata*)side_data->data;
2480
2481 avio_wb32(pb, 12); // size
2482 ffio_wfourcc(pb, "clli");
2483 avio_wb16(pb, content_light_metadata->MaxCLL);
2484 avio_wb16(pb, content_light_metadata->MaxFALL);
2485 return 12;
2486 }
2487
2488 193 static int mov_write_mdcv_tag(AVIOContext *pb, MOVTrack *track)
2489 {
2490 193 const int chroma_den = 50000;
2491 193 const int luma_den = 10000;
2492 const AVPacketSideData *side_data;
2493 193 const AVMasteringDisplayMetadata *metadata = NULL;
2494
2495 193 side_data = av_packet_side_data_get(track->st->codecpar->coded_side_data,
2496 193 track->st->codecpar->nb_coded_side_data,
2497 AV_PKT_DATA_MASTERING_DISPLAY_METADATA);
2498
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 193 times.
193 if (side_data)
2499 metadata = (const AVMasteringDisplayMetadata*)side_data->data;
2500
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 193 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
193 if (!metadata || !metadata->has_primaries || !metadata->has_luminance) {
2501 193 return 0;
2502 }
2503
2504 avio_wb32(pb, 32); // size
2505 ffio_wfourcc(pb, "mdcv");
2506 avio_wb16(pb, rescale_rational(metadata->display_primaries[1][0], chroma_den));
2507 avio_wb16(pb, rescale_rational(metadata->display_primaries[1][1], chroma_den));
2508 avio_wb16(pb, rescale_rational(metadata->display_primaries[2][0], chroma_den));
2509 avio_wb16(pb, rescale_rational(metadata->display_primaries[2][1], chroma_den));
2510 avio_wb16(pb, rescale_rational(metadata->display_primaries[0][0], chroma_den));
2511 avio_wb16(pb, rescale_rational(metadata->display_primaries[0][1], chroma_den));
2512 avio_wb16(pb, rescale_rational(metadata->white_point[0], chroma_den));
2513 avio_wb16(pb, rescale_rational(metadata->white_point[1], chroma_den));
2514 avio_wb32(pb, rescale_rational(metadata->max_luminance, luma_den));
2515 avio_wb32(pb, rescale_rational(metadata->min_luminance, luma_den));
2516 return 32;
2517 }
2518
2519 193 static int mov_write_amve_tag(AVIOContext *pb, MOVTrack *track)
2520 {
2521 193 const int illuminance_den = 10000;
2522 193 const int ambient_den = 50000;
2523 const AVPacketSideData *side_data;
2524 const AVAmbientViewingEnvironment *ambient;
2525
2526
2527 193 side_data = av_packet_side_data_get(track->st->codecpar->coded_side_data,
2528 193 track->st->codecpar->nb_coded_side_data,
2529 AV_PKT_DATA_AMBIENT_VIEWING_ENVIRONMENT);
2530
2531
2/2
✓ Branch 0 taken 192 times.
✓ Branch 1 taken 1 times.
193 if (!side_data)
2532 192 return 0;
2533
2534 1 ambient = (const AVAmbientViewingEnvironment*)side_data->data;
2535
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)
2536 return 0;
2537
2538 1 avio_wb32(pb, 16); // size
2539 1 ffio_wfourcc(pb, "amve");
2540 1 avio_wb32(pb, rescale_rational(ambient->ambient_illuminance, illuminance_den));
2541 1 avio_wb16(pb, rescale_rational(ambient->ambient_light_x, ambient_den));
2542 1 avio_wb16(pb, rescale_rational(ambient->ambient_light_y, ambient_den));
2543 1 return 16;
2544 }
2545
2546 198 static void find_compressor(char * compressor_name, int len, MOVTrack *track)
2547 {
2548 AVDictionaryEntry *encoder;
2549
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 int xdcam_res = (track->par->width == 1280 && track->par->height == 720)
2550
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 197 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
197 || (track->par->width == 1440 && track->par->height == 1080)
2551
5/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 197 times.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 184 times.
✓ Branch 4 taken 13 times.
✗ Branch 5 not taken.
396 || (track->par->width == 1920 && track->par->height == 1080);
2552
2553
1/2
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
198 if ((track->mode == MODE_AVIF ||
2554
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 133 times.
198 track->mode == MODE_MOV ||
2555
4/4
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 139 times.
✓ Branch 3 taken 54 times.
258 track->mode == MODE_MP4) &&
2556 193 (encoder = av_dict_get(track->st->metadata, "encoder", NULL, 0))) {
2557 139 av_strlcpy(compressor_name, encoder->value, 32);
2558
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
59 } else if (track->par->codec_id == AV_CODEC_ID_MPEG2VIDEO && xdcam_res) {
2559 int interlaced = track->par->field_order > AV_FIELD_PROGRESSIVE;
2560 AVStream *st = track->st;
2561 int rate = defined_frame_rate(NULL, st);
2562 av_strlcatf(compressor_name, len, "XDCAM");
2563 if (track->par->format == AV_PIX_FMT_YUV422P) {
2564 av_strlcatf(compressor_name, len, " HD422");
2565 } else if(track->par->width == 1440) {
2566 av_strlcatf(compressor_name, len, " HD");
2567 } else
2568 av_strlcatf(compressor_name, len, " EX");
2569
2570 av_strlcatf(compressor_name, len, " %d%c", track->par->height, interlaced ? 'i' : 'p');
2571
2572 av_strlcatf(compressor_name, len, "%d", rate * (interlaced + 1));
2573 }
2574 198 }
2575
2576 static int mov_write_ccst_tag(AVIOContext *pb)
2577 {
2578 int64_t pos = avio_tell(pb);
2579 // Write sane defaults:
2580 // all_ref_pics_intra = 0 : all samples can use any type of reference.
2581 // intra_pred_used = 1 : intra prediction may or may not be used.
2582 // max_ref_per_pic = 15 : reserved value to indicate that any number of
2583 // reference images can be used.
2584 uint8_t ccstValue = (0 << 7) | /* all_ref_pics_intra */
2585 (1 << 6) | /* intra_pred_used */
2586 (15 << 2); /* max_ref_per_pic */
2587 avio_wb32(pb, 0); /* size */
2588 ffio_wfourcc(pb, "ccst");
2589 avio_wb32(pb, 0); /* Version & flags */
2590 avio_w8(pb, ccstValue);
2591 avio_wb24(pb, 0); /* reserved */
2592 return update_size(pb, pos);
2593 }
2594
2595 static int mov_write_aux_tag(AVIOContext *pb, const char *aux_type)
2596 {
2597 int64_t pos = avio_tell(pb);
2598 avio_wb32(pb, 0); /* size */
2599 ffio_wfourcc(pb, aux_type);
2600 avio_wb32(pb, 0); /* Version & flags */
2601 avio_write(pb, "urn:mpeg:mpegB:cicp:systems:auxiliary:alpha\0", 44);
2602 return update_size(pb, pos);
2603 }
2604
2605 198 static int mov_write_video_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
2606 {
2607 198 int ret = AVERROR_BUG;
2608 198 int64_t pos = avio_tell(pb);
2609 const AVPacketSideData *sd;
2610 198 char compressor_name[32] = { 0 };
2611 198 int avid = 0;
2612
2613
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 int uncompressed_ycbcr = ((track->par->codec_id == AV_CODEC_ID_RAWVIDEO && track->par->format == AV_PIX_FMT_UYVY422)
2614
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 185 times.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
198 || (track->par->codec_id == AV_CODEC_ID_RAWVIDEO && track->par->format == AV_PIX_FMT_YUYV422)
2615
1/2
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
198 || track->par->codec_id == AV_CODEC_ID_V308
2616
1/2
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
198 || track->par->codec_id == AV_CODEC_ID_V408
2617
1/2
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
198 || track->par->codec_id == AV_CODEC_ID_V410
2618
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 185 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 198 times.
396 || track->par->codec_id == AV_CODEC_ID_V210);
2619
2620 198 avio_wb32(pb, 0); /* size */
2621
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 198 times.
198 if (mov->encryption_scheme != MOV_ENC_NONE) {
2622 ffio_wfourcc(pb, "encv");
2623 } else {
2624 198 avio_wl32(pb, track->tag); // store it byteswapped
2625 }
2626 198 avio_wb32(pb, 0); /* Reserved */
2627 198 avio_wb16(pb, 0); /* Reserved */
2628 198 avio_wb16(pb, 1); /* Data-reference index */
2629
2630
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 198 times.
198 if (uncompressed_ycbcr) {
2631 avio_wb16(pb, 2); /* Codec stream version */
2632 } else {
2633 198 avio_wb16(pb, 0); /* Codec stream version */
2634 }
2635 198 avio_wb16(pb, 0); /* Codec stream revision (=0) */
2636
2/2
✓ Branch 0 taken 133 times.
✓ Branch 1 taken 65 times.
198 if (track->mode == MODE_MOV) {
2637 133 ffio_wfourcc(pb, "FFMP"); /* Vendor */
2638
3/4
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 120 times.
133 if (track->par->codec_id == AV_CODEC_ID_RAWVIDEO || uncompressed_ycbcr) {
2639 13 avio_wb32(pb, 0); /* Temporal Quality */
2640 13 avio_wb32(pb, 0x400); /* Spatial Quality = lossless*/
2641 } else {
2642 120 avio_wb32(pb, 0x200); /* Temporal Quality = normal */
2643 120 avio_wb32(pb, 0x200); /* Spatial Quality = normal */
2644 }
2645 } else {
2646 65 ffio_fill(pb, 0, 3 * 4); /* Reserved */
2647 }
2648 198 avio_wb16(pb, track->par->width); /* Video width */
2649 198 avio_wb16(pb, track->height); /* Video height */
2650 198 avio_wb32(pb, 0x00480000); /* Horizontal resolution 72dpi */
2651 198 avio_wb32(pb, 0x00480000); /* Vertical resolution 72dpi */
2652 198 avio_wb32(pb, 0); /* Data size (= 0) */
2653 198 avio_wb16(pb, 1); /* Frame count (= 1) */
2654
2655 198 find_compressor(compressor_name, 32, track);
2656 198 avio_w8(pb, strlen(compressor_name));
2657 198 avio_write(pb, compressor_name, 31);
2658
2659
2/2
✓ Branch 0 taken 133 times.
✓ Branch 1 taken 65 times.
198 if (track->mode == MODE_MOV &&
2660
2/4
✓ Branch 0 taken 133 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 133 times.
133 (track->par->codec_id == AV_CODEC_ID_V410 || track->par->codec_id == AV_CODEC_ID_V210))
2661 avio_wb16(pb, 0x18);
2662
4/4
✓ Branch 0 taken 133 times.
✓ Branch 1 taken 65 times.
✓ Branch 2 taken 31 times.
✓ Branch 3 taken 102 times.
198 else if (track->mode == MODE_MOV && track->par->bits_per_coded_sample)
2663 31 avio_wb16(pb, track->par->bits_per_coded_sample |
2664
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 28 times.
31 (track->par->format == AV_PIX_FMT_GRAY8 ? 0x20 : 0));
2665 else
2666 167 avio_wb16(pb, 0x18); /* Reserved */
2667
2668
4/4
✓ Branch 0 taken 133 times.
✓ Branch 1 taken 65 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 128 times.
203 if (track->mode == MODE_MOV && track->par->format == AV_PIX_FMT_PAL8) {
2669 int pal_size, i;
2670 5 avio_wb16(pb, 0); /* Color table ID */
2671 5 avio_wb32(pb, 0); /* Color table seed */
2672 5 avio_wb16(pb, 0x8000); /* Color table flags */
2673
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)
2674 return AVERROR(EINVAL);
2675 5 pal_size = 1 << track->par->bits_per_coded_sample;
2676 5 avio_wb16(pb, pal_size - 1); /* Color table size (zero-relative) */
2677
2/2
✓ Branch 0 taken 1040 times.
✓ Branch 1 taken 5 times.
1045 for (i = 0; i < pal_size; i++) {
2678 1040 uint32_t rgb = track->palette[i];
2679 1040 uint16_t r = (rgb >> 16) & 0xff;
2680 1040 uint16_t g = (rgb >> 8) & 0xff;
2681 1040 uint16_t b = rgb & 0xff;
2682 1040 avio_wb16(pb, 0);
2683 1040 avio_wb16(pb, (r << 8) | r);
2684 1040 avio_wb16(pb, (g << 8) | g);
2685 1040 avio_wb16(pb, (b << 8) | b);
2686 }
2687 } else
2688 193 avio_wb16(pb, 0xffff); /* Reserved */
2689
2690
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 175 times.
198 if (track->tag == MKTAG('m','p','4','v'))
2691 23 mov_write_esds_tag(pb, track);
2692
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 175 times.
175 else if (track->par->codec_id == AV_CODEC_ID_H263)
2693 mov_write_d263_tag(pb);
2694
2/2
✓ Branch 0 taken 172 times.
✓ Branch 1 taken 3 times.
175 else if (track->par->codec_id == AV_CODEC_ID_AVUI ||
2695
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 172 times.
172 track->par->codec_id == AV_CODEC_ID_SVQ3) {
2696 3 mov_write_extradata_tag(pb, track);
2697 3 avio_wb32(pb, 0);
2698
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 149 times.
172 } else if (track->par->codec_id == AV_CODEC_ID_DNXHD) {
2699 23 mov_write_avid_tag(pb, track);
2700 23 avid = 1;
2701
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 146 times.
149 } else if (track->par->codec_id == AV_CODEC_ID_HEVC) {
2702 3 mov_write_hvcc_tag(pb, track);
2703
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (track->st->disposition & AV_DISPOSITION_MULTILAYER) {
2704 1 ret = mov_write_lhvc_tag(pb, track);
2705
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
2706 av_log(mov->fc, AV_LOG_WARNING, "Not writing 'lhvC' atom for multilayer stream.\n");
2707 }
2708
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 145 times.
146 } else if (track->par->codec_id == AV_CODEC_ID_VVC)
2709 1 mov_write_vvcc_tag(pb, track);
2710
16/30
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 93 times.
✓ Branch 2 taken 52 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 52 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 52 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 52 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 52 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 52 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 52 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 52 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 52 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 52 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 52 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 52 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 52 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 52 times.
✗ Branch 29 not taken.
145 else if (track->par->codec_id == AV_CODEC_ID_H264 && !TAG_IS_AVCI(track->tag)) {
2711 52 mov_write_avcc_tag(pb, track);
2712
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 if (track->mode == MODE_IPOD)
2713 mov_write_uuid_tag_ipod(pb);
2714 }
2715
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 92 times.
93 else if (track->par->codec_id ==AV_CODEC_ID_EVC) {
2716 1 mov_write_evcc_tag(pb, track);
2717
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 92 times.
92 } else if (track->par->codec_id == AV_CODEC_ID_VP9) {
2718 mov_write_vpcc_tag(mov->fc, pb, track);
2719
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 91 times.
92 } else if (track->par->codec_id == AV_CODEC_ID_AV1) {
2720 1 mov_write_av1c_tag(pb, track);
2721
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 91 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
91 } else if (track->par->codec_id == AV_CODEC_ID_VC1 && track->vos_len > 0)
2722 mov_write_dvc1_tag(pb, track);
2723
1/2
✓ Branch 0 taken 91 times.
✗ Branch 1 not taken.
91 else if (track->par->codec_id == AV_CODEC_ID_VP6F ||
2724
1/2
✓ Branch 0 taken 91 times.
✗ Branch 1 not taken.
91 track->par->codec_id == AV_CODEC_ID_VP6A) {
2725 /* Don't write any potential extradata here - the cropping
2726 * is signalled via the normal width/height fields. */
2727
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 91 times.
91 } else if (track->par->codec_id == AV_CODEC_ID_R10K) {
2728 if (track->par->codec_tag == MKTAG('R','1','0','k'))
2729 mov_write_dpxe_tag(pb, track);
2730
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 87 times.
91 } else if (track->vos_len > 0)
2731 4 mov_write_glbl_tag(pb, track);
2732
2733
2/2
✓ Branch 0 taken 146 times.
✓ Branch 1 taken 52 times.
198 if (track->par->codec_id != AV_CODEC_ID_H264 &&
2734
2/2
✓ Branch 0 taken 123 times.
✓ Branch 1 taken 23 times.
146 track->par->codec_id != AV_CODEC_ID_MPEG4 &&
2735
2/2
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 23 times.
123 track->par->codec_id != AV_CODEC_ID_DNXHD) {
2736 100 int field_order = track->par->field_order;
2737
2738
2/2
✓ Branch 0 taken 91 times.
✓ Branch 1 taken 9 times.
100 if (field_order != AV_FIELD_UNKNOWN)
2739 91 mov_write_fiel_tag(pb, track, field_order);
2740 }
2741
2742
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 198 times.
198 if (mov->flags & FF_MOV_FLAG_WRITE_GAMA) {
2743 if (track->mode == MODE_MOV)
2744 mov_write_gama_tag(s, pb, track, mov->gamma);
2745 else
2746 av_log(mov->fc, AV_LOG_WARNING, "Not writing 'gama' atom. Format is not MOV.\n");
2747 }
2748
5/6
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 133 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 60 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 5 times.
391 if (track->mode == MODE_MOV || track->mode == MODE_MP4 || track->mode == MODE_AVIF) {
2749 391 int has_color_info = track->par->color_primaries != AVCOL_PRI_UNSPECIFIED &&
2750
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 188 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
198 track->par->color_trc != AVCOL_TRC_UNSPECIFIED &&
2751
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 track->par->color_space != AVCOL_SPC_UNSPECIFIED;
2752
5/6
✓ Branch 0 taken 188 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 184 times.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 184 times.
377 if (has_color_info || mov->flags & FF_MOV_FLAG_WRITE_COLR ||
2753 184 av_packet_side_data_get(track->st->codecpar->coded_side_data, track->st->codecpar->nb_coded_side_data,
2754 AV_PKT_DATA_ICC_PROFILE)) {
2755
3/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 5 times.
9 int prefer_icc = mov->flags & FF_MOV_FLAG_PREFER_ICC || !has_color_info;
2756 9 mov_write_colr_tag(pb, track, prefer_icc);
2757 }
2758
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 } else if (mov->flags & FF_MOV_FLAG_WRITE_COLR) {
2759 av_log(mov->fc, AV_LOG_WARNING, "Not writing 'colr' atom. Format is not MOV or MP4 or AVIF.\n");
2760 }
2761
2762
4/4
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 133 times.
✓ Branch 2 taken 60 times.
✓ Branch 3 taken 5 times.
198 if (track->mode == MODE_MOV || track->mode == MODE_MP4) {
2763 193 mov_write_clli_tag(pb, track);
2764 193 mov_write_mdcv_tag(pb, track);
2765 193 mov_write_amve_tag(pb, track);
2766 }
2767
2768
3/4
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 138 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 60 times.
198 if (track->mode == MODE_MP4 && mov->fc->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL) {
2769 const AVPacketSideData *stereo_3d = av_packet_side_data_get(track->st->codecpar->coded_side_data,
2770 track->st->codecpar->nb_coded_side_data,
2771 AV_PKT_DATA_STEREO3D);
2772 const AVPacketSideData *spherical_mapping = av_packet_side_data_get(track->st->codecpar->coded_side_data,
2773 track->st->codecpar->nb_coded_side_data,
2774 AV_PKT_DATA_SPHERICAL);
2775 if (stereo_3d)
2776 mov_write_st3d_tag(s, pb, (AVStereo3D*)stereo_3d->data);
2777 if (spherical_mapping)
2778 mov_write_sv3d_tag(mov->fc, pb, (AVSphericalMapping*)spherical_mapping->data);
2779 }
2780
2781
4/4
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 133 times.
✓ Branch 2 taken 60 times.
✓ Branch 3 taken 5 times.
198 if (track->mode == MODE_MOV || (track->mode == MODE_MP4 &&
2782
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
60 mov->fc->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL)) {
2783 133 const AVStereo3D *stereo3d = NULL;
2784 133 const AVSphericalMapping *spherical_mapping = NULL;
2785
2786 133 sd = av_packet_side_data_get(track->st->codecpar->coded_side_data,
2787 133 track->st->codecpar->nb_coded_side_data,
2788 AV_PKT_DATA_STEREO3D);
2789
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 132 times.
133 if (sd)
2790 1 stereo3d = (AVStereo3D *)sd->data;
2791
2792 133 sd = av_packet_side_data_get(track->st->codecpar->coded_side_data,
2793 133 track->st->codecpar->nb_coded_side_data,
2794 AV_PKT_DATA_SPHERICAL);
2795
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 132 times.
133 if (sd)
2796 1 spherical_mapping = (AVSphericalMapping *)sd->data;
2797
2798
3/4
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 132 times.
133 if (stereo3d || spherical_mapping)
2799 1 mov_write_vexu_tag(s, pb, stereo3d, spherical_mapping);
2800
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 132 times.
133 if (stereo3d)
2801 1 mov_write_hfov_tag(s, pb, stereo3d);
2802 }
2803
2804
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 138 times.
198 if (track->mode == MODE_MP4) {
2805 60 const AVPacketSideData *dovi = av_packet_side_data_get(track->st->codecpar->coded_side_data,
2806 60 track->st->codecpar->nb_coded_side_data,
2807 AV_PKT_DATA_DOVI_CONF);
2808
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
60 if (dovi && mov->fc->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL) {
2809 mov_write_dvcc_dvvc_tag(s, pb, (AVDOVIDecoderConfigurationRecord *)dovi->data);
2810
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
60 } else if (dovi) {
2811 av_log(mov->fc, AV_LOG_WARNING, "Not writing 'dvcC'/'dvvC' box. Requires -strict unofficial.\n");
2812 }
2813 }
2814
2815
3/4
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 192 times.
198 if (track->par->sample_aspect_ratio.den && track->par->sample_aspect_ratio.num) {
2816 6 mov_write_pasp_tag(pb, track);
2817 }
2818
2819 198 sd = av_packet_side_data_get(track->st->codecpar->coded_side_data,
2820 198 track->st->codecpar->nb_coded_side_data,
2821 AV_PKT_DATA_FRAME_CROPPING);
2822
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 197 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
199 if (sd && sd->size >= sizeof(uint32_t) * 4) {
2823 1 uint64_t top = AV_RL32(sd->data + 0);
2824 1 uint64_t bottom = AV_RL32(sd->data + 4);
2825 1 uint64_t left = AV_RL32(sd->data + 8);
2826 1 uint64_t right = AV_RL32(sd->data + 12);
2827
2828
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if ((left + right) >= track->par->width ||
2829
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 (top + bottom) >= track->height) {
2830 av_log(s, AV_LOG_ERROR, "Invalid cropping dimensions in stream side data\n");
2831 return AVERROR(EINVAL);
2832 }
2833
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)
2834 1 mov_write_clap_tag(pb, track, top, bottom, left, right);
2835
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 197 times.
197 } else if (uncompressed_ycbcr)
2836 mov_write_clap_tag(pb, track, 0, 0, 0, 0);
2837
2838
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 198 times.
198 if (mov->encryption_scheme != MOV_ENC_NONE) {
2839 ff_mov_cenc_write_sinf_tag(track, pb, mov->encryption_kid);
2840 }
2841
2842
3/4
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 138 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 60 times.
258 if (mov->write_btrt &&
2843 60 ((ret = mov_write_btrt_tag(pb, track)) < 0))
2844 return ret;
2845
2846 /* extra padding for avid stsd */
2847 /* https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/QTFFChap2/qtff2.html#//apple_ref/doc/uid/TP40000939-CH204-61112 */
2848
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 175 times.
198 if (avid)
2849 23 avio_wb32(pb, 0);
2850
2851
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 198 times.
198 if (track->mode == MODE_AVIF) {
2852 mov_write_ccst_tag(pb);
2853 if (mov->nb_streams > 0 && track == &mov->tracks[1])
2854 mov_write_aux_tag(pb, "auxi");
2855 }
2856
2857 198 return update_size(pb, pos);
2858 }
2859
2860 2 static int mov_write_rtp_tag(AVIOContext *pb, MOVTrack *track)
2861 {
2862 2 int64_t pos = avio_tell(pb);
2863 2 avio_wb32(pb, 0); /* size */
2864 2 ffio_wfourcc(pb, "rtp ");
2865 2 avio_wb32(pb, 0); /* Reserved */
2866 2 avio_wb16(pb, 0); /* Reserved */
2867 2 avio_wb16(pb, 1); /* Data-reference index */
2868
2869 2 avio_wb16(pb, 1); /* Hint track version */
2870 2 avio_wb16(pb, 1); /* Highest compatible version */
2871 2 avio_wb32(pb, track->max_packet_size); /* Max packet size */
2872
2873 2 avio_wb32(pb, 12); /* size */
2874 2 ffio_wfourcc(pb, "tims");
2875 2 avio_wb32(pb, track->timescale);
2876
2877 2 return update_size(pb, pos);
2878 }
2879
2880 2 static int mov_write_source_reference_tag(AVIOContext *pb, MOVTrack *track, const char *reel_name)
2881 {
2882 2 uint64_t str_size =strlen(reel_name);
2883 2 int64_t pos = avio_tell(pb);
2884
2885
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (str_size >= UINT16_MAX){
2886 av_log(NULL, AV_LOG_ERROR, "reel_name length %"PRIu64" is too large\n", str_size);
2887 avio_wb16(pb, 0);
2888 return AVERROR(EINVAL);
2889 }
2890
2891 2 avio_wb32(pb, 0); /* size */
2892 2 ffio_wfourcc(pb, "name"); /* Data format */
2893 2 avio_wb16(pb, str_size); /* string size */
2894 2 avio_wb16(pb, track->language); /* langcode */
2895 2 avio_write(pb, reel_name, str_size); /* reel name */
2896 2 return update_size(pb,pos);
2897 }
2898
2899 13 static int mov_write_tmcd_tag(AVIOContext *pb, MOVTrack *track)
2900 {
2901 13 int64_t pos = avio_tell(pb);
2902 #if 1
2903 int frame_duration;
2904 int nb_frames;
2905 13 AVDictionaryEntry *t = NULL;
2906
2907
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) {
2908 av_log(NULL, AV_LOG_ERROR, "avg_frame_rate not set for tmcd track.\n");
2909 return AVERROR(EINVAL);
2910 } else {
2911 13 frame_duration = av_rescale(track->timescale, track->st->avg_frame_rate.den, track->st->avg_frame_rate.num);
2912
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);
2913 }
2914
2915
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (nb_frames > 255) {
2916 av_log(NULL, AV_LOG_ERROR, "fps %d is too large\n", nb_frames);
2917 return AVERROR(EINVAL);
2918 }
2919
2920 13 avio_wb32(pb, 0); /* size */
2921 13 ffio_wfourcc(pb, "tmcd"); /* Data format */
2922 13 avio_wb32(pb, 0); /* Reserved */
2923 13 avio_wb32(pb, 1); /* Data reference index */
2924 13 avio_wb32(pb, 0); /* Flags */
2925 13 avio_wb32(pb, track->timecode_flags); /* Flags (timecode) */
2926 13 avio_wb32(pb, track->timescale); /* Timescale */
2927 13 avio_wb32(pb, frame_duration); /* Frame duration */
2928 13 avio_w8(pb, nb_frames); /* Number of frames */
2929 13 avio_w8(pb, 0); /* Reserved */
2930
2931 13 t = av_dict_get(track->st->metadata, "reel_name", NULL, 0);
2932
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)
2933 2 mov_write_source_reference_tag(pb, track, t->value);
2934 else
2935 11 avio_wb16(pb, 0); /* zero size */
2936 #else
2937
2938 avio_wb32(pb, 0); /* size */
2939 ffio_wfourcc(pb, "tmcd"); /* Data format */
2940 avio_wb32(pb, 0); /* Reserved */
2941 avio_wb32(pb, 1); /* Data reference index */
2942 if (track->par->extradata_size)
2943 avio_write(pb, track->par->extradata, track->par->extradata_size);
2944 #endif
2945 13 return update_size(pb, pos);
2946 }
2947
2948 1 static int mov_write_gpmd_tag(AVIOContext *pb, const MOVTrack *track)
2949 {
2950 1 int64_t pos = avio_tell(pb);
2951 1 avio_wb32(pb, 0); /* size */
2952 1 ffio_wfourcc(pb, "gpmd");
2953 1 avio_wb32(pb, 0); /* Reserved */
2954 1 avio_wb16(pb, 0); /* Reserved */
2955 1 avio_wb16(pb, 1); /* Data-reference index */
2956 1 avio_wb32(pb, 0); /* Reserved */
2957 1 return update_size(pb, pos);
2958 }
2959
2960 325 static int mov_write_stsd_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
2961 {
2962 325 int64_t pos = avio_tell(pb);
2963 325 int ret = 0;
2964 325 avio_wb32(pb, 0); /* size */
2965 325 ffio_wfourcc(pb, "stsd");
2966 325 avio_wb32(pb, 0); /* version & flags */
2967 325 avio_wb32(pb, 1); /* entry count */
2968
2/2
✓ Branch 0 taken 198 times.
✓ Branch 1 taken 127 times.
325 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO)
2969 198 ret = mov_write_video_tag(s, pb, mov, track);
2970
2/2
✓ Branch 0 taken 107 times.
✓ Branch 1 taken 20 times.
127 else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO)
2971 107 ret = mov_write_audio_tag(s, pb, mov, track);
2972
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 16 times.
20 else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE)
2973 4 ret = mov_write_subtitle_tag(s, pb, track);
2974
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 14 times.
16 else if (track->par->codec_tag == MKTAG('r','t','p',' '))
2975 2 ret = mov_write_rtp_tag(pb, track);
2976
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 1 times.
14 else if (track->par->codec_tag == MKTAG('t','m','c','d'))
2977 13 ret = mov_write_tmcd_tag(pb, track);
2978
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 else if (track->par->codec_tag == MKTAG('g','p','m','d'))
2979 1 ret = mov_write_gpmd_tag(pb, track);
2980
2981
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 325 times.
325 if (ret < 0)
2982 return ret;
2983
2984 325 return update_size(pb, pos);
2985 }
2986
2987 8 static int mov_write_ctts_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
2988 {
2989 8 MOVMuxContext *mov = s->priv_data;
2990 MOVCtts *ctts_entries;
2991 8 uint32_t entries = 0;
2992 uint32_t atom_size;
2993 int i;
2994
2995 8 ctts_entries = av_malloc_array((track->entry + 1), sizeof(*ctts_entries)); /* worst case */
2996
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!ctts_entries)
2997 return AVERROR(ENOMEM);
2998 8 ctts_entries[0].count = 1;
2999 8 ctts_entries[0].duration = track->cluster[0].cts;
3000
2/2
✓ Branch 0 taken 502 times.
✓ Branch 1 taken 8 times.
510 for (i = 1; i < track->entry; i++) {
3001
2/2
✓ Branch 0 taken 104 times.
✓ Branch 1 taken 398 times.
502 if (track->cluster[i].cts == ctts_entries[entries].duration) {
3002 104 ctts_entries[entries].count++; /* compress */
3003 } else {
3004 398 entries++;
3005 398 ctts_entries[entries].duration = track->cluster[i].cts;
3006 398 ctts_entries[entries].count = 1;
3007 }
3008 }
3009 8 entries++; /* last one */
3010 8 atom_size = 16 + (entries * 8);
3011 8 avio_wb32(pb, atom_size); /* size */
3012 8 ffio_wfourcc(pb, "ctts");
3013
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS)
3014 avio_w8(pb, 1); /* version */
3015 else
3016 8 avio_w8(pb, 0); /* version */
3017 8 avio_wb24(pb, 0); /* flags */
3018 8 avio_wb32(pb, entries); /* entry count */
3019
2/2
✓ Branch 0 taken 406 times.
✓ Branch 1 taken 8 times.
414 for (i = 0; i < entries; i++) {
3020 406 avio_wb32(pb, ctts_entries[i].count);
3021 406 avio_wb32(pb, ctts_entries[i].duration);
3022 }
3023 8 av_free(ctts_entries);
3024 8 return atom_size;
3025 }
3026
3027 /* Time to sample atom */
3028 325 static int mov_write_stts_tag(AVIOContext *pb, MOVTrack *track)
3029 {
3030 325 MOVStts *stts_entries = NULL;
3031 325 uint32_t entries = -1;
3032 uint32_t atom_size;
3033 int i;
3034
3035
4/4
✓ Branch 0 taken 107 times.
✓ Branch 1 taken 218 times.
✓ Branch 2 taken 33 times.
✓ Branch 3 taken 74 times.
325 if (track->par->codec_type == AVMEDIA_TYPE_AUDIO && !track->audio_vbr) {
3036 33 stts_entries = av_malloc(sizeof(*stts_entries)); /* one entry */
3037
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 if (!stts_entries)
3038 return AVERROR(ENOMEM);
3039 33 stts_entries[0].count = track->sample_count;
3040 33 stts_entries[0].duration = 1;
3041 33 entries = 1;
3042 } else {
3043
2/2
✓ Branch 0 taken 202 times.
✓ Branch 1 taken 90 times.
292 if (track->entry) {
3044 202 stts_entries = av_malloc_array(track->entry, sizeof(*stts_entries)); /* worst case */
3045
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 202 times.
202 if (!stts_entries)
3046 return AVERROR(ENOMEM);
3047 }
3048
2/2
✓ Branch 0 taken 11896 times.
✓ Branch 1 taken 292 times.
12188 for (i = 0; i < track->entry; i++) {
3049 11896 int duration = get_cluster_duration(track, i);
3050
4/4
✓ Branch 0 taken 11694 times.
✓ Branch 1 taken 202 times.
✓ Branch 2 taken 11290 times.
✓ Branch 3 taken 404 times.
11896 if (i && duration == stts_entries[entries].duration) {
3051 11290 stts_entries[entries].count++; /* compress */
3052 } else {
3053 606 entries++;
3054 606 stts_entries[entries].duration = duration;
3055 606 stts_entries[entries].count = 1;
3056 }
3057 }
3058 292 entries++; /* last one */
3059 }
3060 325 atom_size = 16 + (entries * 8);
3061 325 avio_wb32(pb, atom_size); /* size */
3062 325 ffio_wfourcc(pb, "stts");
3063 325 avio_wb32(pb, 0); /* version & flags */
3064 325 avio_wb32(pb, entries); /* entry count */
3065
2/2
✓ Branch 0 taken 639 times.
✓ Branch 1 taken 325 times.
964 for (i = 0; i < entries; i++) {
3066 639 avio_wb32(pb, stts_entries[i].count);
3067 639 avio_wb32(pb, stts_entries[i].duration);
3068 }
3069 325 av_free(stts_entries);
3070 325 return atom_size;
3071 }
3072
3073 325 static int mov_write_dref_tag(AVIOContext *pb)
3074 {
3075 325 avio_wb32(pb, 28); /* size */
3076 325 ffio_wfourcc(pb, "dref");
3077 325 avio_wb32(pb, 0); /* version & flags */
3078 325 avio_wb32(pb, 1); /* entry count */
3079
3080 325 avio_wb32(pb, 0xc); /* size */
3081 //FIXME add the alis and rsrc atom
3082 325 ffio_wfourcc(pb, "url ");
3083 325 avio_wb32(pb, 1); /* version & flags */
3084
3085 325 return 28;
3086 }
3087
3088 53 static int mov_preroll_write_stbl_atoms(AVIOContext *pb, MOVTrack *track)
3089 {
3090 struct sgpd_entry {
3091 int count;
3092 int16_t roll_distance;
3093 int group_description_index;
3094 };
3095
3096 53 struct sgpd_entry *sgpd_entries = NULL;
3097 53 int entries = -1;
3098 53 int group = 0;
3099 int i, j;
3100
3101 53 const int OPUS_SEEK_PREROLL_MS = 80;
3102 53 int roll_samples = av_rescale_q(OPUS_SEEK_PREROLL_MS,
3103 53 (AVRational){1, 1000},
3104 53 (AVRational){1, 48000});
3105
3106
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 12 times.
53 if (!track->entry)
3107 41 return 0;
3108
3109 12 sgpd_entries = av_malloc_array(track->entry, sizeof(*sgpd_entries));
3110
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!sgpd_entries)
3111 return AVERROR(ENOMEM);
3112
3113
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 av_assert0(track->par->codec_id == AV_CODEC_ID_OPUS || track->par->codec_id == AV_CODEC_ID_AAC);
3114
3115
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (track->par->codec_id == AV_CODEC_ID_OPUS) {
3116 for (i = 0; i < track->entry; i++) {
3117 int roll_samples_remaining = roll_samples;
3118 int distance = 0;
3119 for (j = i - 1; j >= 0; j--) {
3120 roll_samples_remaining -= get_cluster_duration(track, j);
3121 distance++;
3122 if (roll_samples_remaining <= 0)
3123 break;
3124 }
3125 /* We don't have enough preceeding samples to compute a valid
3126 roll_distance here, so this sample can't be independently
3127 decoded. */
3128 if (roll_samples_remaining > 0)
3129 distance = 0;
3130 /* Verify distance is a maximum of 32 (2.5ms) packets. */
3131 if (distance > 32)
3132 return AVERROR_INVALIDDATA;
3133 if (i && distance == sgpd_entries[entries].roll_distance) {
3134 sgpd_entries[entries].count++;
3135 } else {
3136 entries++;
3137 sgpd_entries[entries].count = 1;
3138 sgpd_entries[entries].roll_distance = distance;
3139 sgpd_entries[entries].group_description_index = distance ? ++group : 0;
3140 }
3141 }
3142 } else {
3143 12 entries++;
3144 12 sgpd_entries[entries].count = track->sample_count;
3145 12 sgpd_entries[entries].roll_distance = 1;
3146 12 sgpd_entries[entries].group_description_index = ++group;
3147 }
3148 12 entries++;
3149
3150
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!group) {
3151 av_free(sgpd_entries);
3152 return 0;
3153 }
3154
3155 /* Write sgpd tag */
3156 12 avio_wb32(pb, 24 + (group * 2)); /* size */
3157 12 ffio_wfourcc(pb, "sgpd");
3158 12 avio_wb32(pb, 1 << 24); /* fullbox */
3159 12 ffio_wfourcc(pb, "roll");
3160 12 avio_wb32(pb, 2); /* default_length */
3161 12 avio_wb32(pb, group); /* entry_count */
3162
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 for (i = 0; i < entries; i++) {
3163
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (sgpd_entries[i].group_description_index) {
3164 12 avio_wb16(pb, -sgpd_entries[i].roll_distance); /* roll_distance */
3165 }
3166 }
3167
3168 /* Write sbgp tag */
3169 12 avio_wb32(pb, 20 + (entries * 8)); /* size */
3170 12 ffio_wfourcc(pb, "sbgp");
3171 12 avio_wb32(pb, 0); /* fullbox */
3172 12 ffio_wfourcc(pb, "roll");
3173 12 avio_wb32(pb, entries); /* entry_count */
3174
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 for (i = 0; i < entries; i++) {
3175 12 avio_wb32(pb, sgpd_entries[i].count); /* sample_count */
3176 12 avio_wb32(pb, sgpd_entries[i].group_description_index); /* group_description_index */
3177 }
3178
3179 12 av_free(sgpd_entries);
3180 12 return 0;
3181 }
3182
3183 325 static int mov_write_stbl_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
3184 {
3185 325 int64_t pos = avio_tell(pb);
3186 325 int ret = 0;
3187
3188 325 avio_wb32(pb, 0); /* size */
3189 325 ffio_wfourcc(pb, "stbl");
3190
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 325 times.
325 if ((ret = mov_write_stsd_tag(s, pb, mov, track)) < 0)
3191 return ret;
3192 325 mov_write_stts_tag(pb, track);
3193
2/2
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 198 times.
325 if ((track->par->codec_type == AVMEDIA_TYPE_VIDEO ||
3194
1/2
✓ Branch 0 taken 127 times.
✗ Branch 1 not taken.
127 track->par->codec_id == AV_CODEC_ID_TRUEHD ||
3195
1/2
✓ Branch 0 taken 127 times.
✗ Branch 1 not taken.
127 track->par->codec_id == AV_CODEC_ID_MPEGH_3D_AUDIO ||
3196
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 125 times.
127 track->par->codec_tag == MKTAG('r','t','p',' ')) &&
3197
4/4
✓ Branch 0 taken 151 times.
✓ Branch 1 taken 49 times.
✓ Branch 2 taken 55 times.
✓ Branch 3 taken 96 times.
200 track->has_keyframes && track->has_keyframes < track->entry)
3198 55 mov_write_stss_tag(pb, track, MOV_SYNC_SAMPLE);
3199
4/4
✓ Branch 0 taken 198 times.
✓ Branch 1 taken 127 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 195 times.
325 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO && track->has_disposable)
3200 3 mov_write_sdtp_tag(pb, track);
3201
3/4
✓ Branch 0 taken 182 times.
✓ Branch 1 taken 143 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 182 times.
325 if (track->mode == MODE_MOV && track->flags & MOV_TRACK_STPS)
3202 mov_write_stss_tag(pb, track, MOV_PARTIAL_SYNC_SAMPLE);
3203
2/2
✓ Branch 0 taken 198 times.
✓ Branch 1 taken 127 times.
325 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO &&
3204
4/4
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 168 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 22 times.
198 track->flags & MOV_TRACK_CTTS && track->entry) {
3205
3206
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if ((ret = mov_write_ctts_tag(s, pb, track)) < 0)
3207 return ret;
3208 }
3209 325 mov_write_stsc_tag(pb, track);
3210 325 mov_write_stsz_tag(pb, track);
3211 325 mov_write_stco_tag(pb, track);
3212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 325 times.
325 if (track->cenc.aes_ctr) {
3213 ff_mov_cenc_write_stbl_atoms(&track->cenc, pb);
3214 }
3215
3/4
✓ Branch 0 taken 325 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 53 times.
✓ Branch 3 taken 272 times.
325 if (track->par->codec_id == AV_CODEC_ID_OPUS || track->par->codec_id == AV_CODEC_ID_AAC) {
3216 53 mov_preroll_write_stbl_atoms(pb, track);
3217 }
3218 325 return update_size(pb, pos);
3219 }
3220
3221 325 static int mov_write_dinf_tag(AVIOContext *pb)
3222 {
3223 325 int64_t pos = avio_tell(pb);
3224 325 avio_wb32(pb, 0); /* size */
3225 325 ffio_wfourcc(pb, "dinf");
3226 325 mov_write_dref_tag(pb);
3227 325 return update_size(pb, pos);
3228 }
3229
3230 6 static int mov_write_nmhd_tag(AVIOContext *pb)
3231 {
3232 6 avio_wb32(pb, 12);
3233 6 ffio_wfourcc(pb, "nmhd");
3234 6 avio_wb32(pb, 0);
3235 6 return 12;
3236 }
3237
3238 1 static int mov_write_sthd_tag(AVIOContext *pb)
3239 {
3240 1 avio_wb32(pb, 12);
3241 1 ffio_wfourcc(pb, "sthd");
3242 1 avio_wb32(pb, 0);
3243 1 return 12;
3244 }
3245
3246 9 static int mov_write_tcmi_tag(AVIOContext *pb, MOVTrack *track)
3247 {
3248 9 int64_t pos = avio_tell(pb);
3249 9 const char *font = "Lucida Grande";
3250 9 avio_wb32(pb, 0); /* size */
3251 9 ffio_wfourcc(pb, "tcmi"); /* timecode media information atom */
3252 9 avio_wb32(pb, 0); /* version & flags */
3253 9 avio_wb16(pb, 0); /* text font */
3254 9 avio_wb16(pb, 0); /* text face */
3255 9 avio_wb16(pb, 12); /* text size */
3256 9 avio_wb16(pb, 0); /* (unknown, not in the QT specs...) */
3257 9 avio_wb16(pb, 0x0000); /* text color (red) */
3258 9 avio_wb16(pb, 0x0000); /* text color (green) */
3259 9 avio_wb16(pb, 0x0000); /* text color (blue) */
3260 9 avio_wb16(pb, 0xffff); /* background color (red) */
3261 9 avio_wb16(pb, 0xffff); /* background color (green) */
3262 9 avio_wb16(pb, 0xffff); /* background color (blue) */
3263 9 avio_w8(pb, strlen(font)); /* font len (part of the pascal string) */
3264 9 avio_write(pb, font, strlen(font)); /* font name */
3265 9 return update_size(pb, pos);
3266 }
3267
3268 11 static int mov_write_gmhd_tag(AVIOContext *pb, MOVTrack *track)
3269 {
3270 11 int64_t pos = avio_tell(pb);
3271 11 avio_wb32(pb, 0); /* size */
3272 11 ffio_wfourcc(pb, "gmhd");
3273 11 avio_wb32(pb, 0x18); /* gmin size */
3274 11 ffio_wfourcc(pb, "gmin");/* generic media info */
3275 11 avio_wb32(pb, 0); /* version & flags */
3276 11 avio_wb16(pb, 0x40); /* graphics mode = */
3277 11 avio_wb16(pb, 0x8000); /* opColor (r?) */
3278 11 avio_wb16(pb, 0x8000); /* opColor (g?) */
3279 11 avio_wb16(pb, 0x8000); /* opColor (b?) */
3280 11 avio_wb16(pb, 0); /* balance */
3281 11 avio_wb16(pb, 0); /* reserved */
3282
3283 /*
3284 * This special text atom is required for
3285 * Apple Quicktime chapters. The contents
3286 * don't appear to be documented, so the
3287 * bytes are copied verbatim.
3288 */
3289
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (track->tag != MKTAG('c','6','0','8')) {
3290 11 avio_wb32(pb, 0x2C); /* size */
3291 11 ffio_wfourcc(pb, "text");
3292 11 avio_wb16(pb, 0x01);
3293 11 avio_wb32(pb, 0x00);
3294 11 avio_wb32(pb, 0x00);
3295 11 avio_wb32(pb, 0x00);
3296 11 avio_wb32(pb, 0x01);
3297 11 avio_wb32(pb, 0x00);
3298 11 avio_wb32(pb, 0x00);
3299 11 avio_wb32(pb, 0x00);
3300 11 avio_wb32(pb, 0x00004000);
3301 11 avio_wb16(pb, 0x0000);
3302 }
3303
3304
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2 times.
11 if (track->par->codec_tag == MKTAG('t','m','c','d')) {
3305 9 int64_t tmcd_pos = avio_tell(pb);
3306 9 avio_wb32(pb, 0); /* size */
3307 9 ffio_wfourcc(pb, "tmcd");
3308 9 mov_write_tcmi_tag(pb, track);
3309 9 update_size(pb, tmcd_pos);
3310
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 } else if (track->par->codec_tag == MKTAG('g','p','m','d')) {
3311 1 int64_t gpmd_pos = avio_tell(pb);
3312 1 avio_wb32(pb, 0); /* size */
3313 1 ffio_wfourcc(pb, "gpmd");
3314 1 avio_wb32(pb, 0); /* version */
3315 1 update_size(pb, gpmd_pos);
3316 }
3317 11 return update_size(pb, pos);
3318 }
3319
3320 107 static int mov_write_smhd_tag(AVIOContext *pb)
3321 {
3322 107 avio_wb32(pb, 16); /* size */
3323 107 ffio_wfourcc(pb, "smhd");
3324 107 avio_wb32(pb, 0); /* version & flags */
3325 107 avio_wb16(pb, 0); /* reserved (balance, normally = 0) */
3326 107 avio_wb16(pb, 0); /* reserved */
3327 107 return 16;
3328 }
3329
3330 198 static int mov_write_vmhd_tag(AVIOContext *pb)
3331 {
3332 198 avio_wb32(pb, 0x14); /* size (always 0x14) */
3333 198 ffio_wfourcc(pb, "vmhd");
3334 198 avio_wb32(pb, 0x01); /* version & flags */
3335 198 avio_wb64(pb, 0); /* reserved (graphics mode = copy) */
3336 198 return 0x14;
3337 }
3338
3339 213 static int is_clcp_track(MOVTrack *track)
3340 {
3341
1/2
✓ Branch 0 taken 213 times.
✗ Branch 1 not taken.
426 return track->tag == MKTAG('c','7','0','8') ||
3342
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 213 times.
213 track->tag == MKTAG('c','6','0','8');
3343 }
3344
3345 507 static int mov_write_hdlr_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
3346 {
3347 507 MOVMuxContext *mov = s->priv_data;
3348 507 const char *hdlr, *descr = NULL, *hdlr_type = NULL;
3349 507 int64_t pos = avio_tell(pb);
3350 size_t descr_len;
3351
3352 507 hdlr = "dhlr";
3353 507 hdlr_type = "url ";
3354 507 descr = "DataHandler";
3355
3356
2/2
✓ Branch 0 taken 325 times.
✓ Branch 1 taken 182 times.
507 if (track) {
3357
2/2
✓ Branch 0 taken 182 times.
✓ Branch 1 taken 143 times.
325 hdlr = (track->mode == MODE_MOV) ? "mhlr" : "\0\0\0\0";
3358
2/2
✓ Branch 0 taken 198 times.
✓ Branch 1 taken 127 times.
325 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
3359
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 198 times.
198 if (track->mode == MODE_AVIF) {
3360 hdlr_type = (track == &mov->tracks[0]) ? "pict" : "auxv";
3361 descr = "PictureHandler";
3362 } else {
3363 198 hdlr_type = "vide";
3364 198 descr = "VideoHandler";
3365 }
3366
2/2
✓ Branch 0 taken 107 times.
✓ Branch 1 taken 20 times.
127 } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) {
3367 107 hdlr_type = "soun";
3368 107 descr = "SoundHandler";
3369
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 16 times.
20 } else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE) {
3370
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (is_clcp_track(track)) {
3371 hdlr_type = "clcp";
3372 descr = "ClosedCaptionHandler";
3373 } else {
3374
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if (track->tag == MKTAG('t','x','3','g')) {
3375 1 hdlr_type = "sbtl";
3376
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 } else if (track->tag == MKTAG('m','p','4','s')) {
3377 hdlr_type = "subp";
3378
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 } else if (track->tag == MOV_MP4_TTML_TAG) {
3379 1 hdlr_type = "subt";
3380 } else {
3381 2 hdlr_type = "text";
3382 }
3383 4 descr = "SubtitleHandler";
3384 }
3385
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 14 times.
16 } else if (track->par->codec_tag == MKTAG('r','t','p',' ')) {
3386 2 hdlr_type = "hint";
3387 2 descr = "HintHandler";
3388
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 1 times.
14 } else if (track->par->codec_tag == MKTAG('t','m','c','d')) {
3389 13 hdlr_type = "tmcd";
3390 13 descr = "TimeCodeHandler";
3391
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 } else if (track->par->codec_tag == MKTAG('g','p','m','d')) {
3392 1 hdlr_type = "meta";
3393 1 descr = "GoPro MET"; // GoPro Metadata
3394 } else {
3395 av_log(s, AV_LOG_WARNING,
3396 "Unknown hdlr_type for %s, writing dummy values\n",
3397 av_fourcc2str(track->par->codec_tag));
3398 }
3399
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 3 times.
325 if (track->st) {
3400 // hdlr.name is used by some players to identify the content title
3401 // of the track. So if an alternate handler description is
3402 // specified, use it.
3403 AVDictionaryEntry *t;
3404 322 t = av_dict_get(track->st->metadata, "handler_name", NULL, 0);
3405
3/4
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 301 times.
✓ Branch 3 taken 21 times.
✗ Branch 4 not taken.
322 if (t && utf8len(t->value))
3406 21 descr = t->value;
3407 }
3408 }
3409
3410
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 507 times.
507 if (mov->empty_hdlr_name) /* expressly allowed by QTFF and not prohibited in ISO 14496-12 8.4.3.3 */
3411 descr = "";
3412
3413 507 avio_wb32(pb, 0); /* size */
3414 507 ffio_wfourcc(pb, "hdlr");
3415 507 avio_wb32(pb, 0); /* Version & flags */
3416 507 avio_write(pb, hdlr, 4); /* handler */
3417 507 ffio_wfourcc(pb, hdlr_type); /* handler type */
3418 507 avio_wb32(pb, 0); /* reserved */
3419 507 avio_wb32(pb, 0); /* reserved */
3420 507 avio_wb32(pb, 0); /* reserved */
3421 507 descr_len = strlen(descr);
3422
4/4
✓ Branch 0 taken 325 times.
✓ Branch 1 taken 182 times.
✓ Branch 2 taken 182 times.
✓ Branch 3 taken 143 times.
507 if (!track || track->mode == MODE_MOV)
3423 364 avio_w8(pb, descr_len); /* pascal string */
3424 507 avio_write(pb, descr, descr_len); /* handler description */
3425
4/4
✓ Branch 0 taken 325 times.
✓ Branch 1 taken 182 times.
✓ Branch 2 taken 143 times.
✓ Branch 3 taken 182 times.
507 if (track && track->mode != MODE_MOV)
3426 143 avio_w8(pb, 0); /* c string */
3427 507 return update_size(pb, pos);
3428 }
3429
3430 static int mov_write_pitm_tag(AVIOContext *pb, int item_id)
3431 {
3432 int64_t pos = avio_tell(pb);
3433 avio_wb32(pb, 0); /* size */
3434 ffio_wfourcc(pb, "pitm");
3435 avio_wb32(pb, 0); /* Version & flags */
3436 avio_wb16(pb, item_id); /* item_id */
3437 return update_size(pb, pos);
3438 }
3439
3440 static int mov_write_iloc_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
3441 {
3442 int64_t pos = avio_tell(pb);
3443 avio_wb32(pb, 0); /* size */
3444 ffio_wfourcc(pb, "iloc");
3445 avio_wb32(pb, 0); /* Version & flags */
3446 avio_w8(pb, (4 << 4) + 4); /* offset_size(4) and length_size(4) */
3447 avio_w8(pb, 0); /* base_offset_size(4) and reserved(4) */
3448 avio_wb16(pb, mov->nb_streams); /* item_count */
3449
3450 for (int i = 0; i < mov->nb_streams; i++) {
3451 avio_wb16(pb, i + 1); /* item_id */
3452 avio_wb16(pb, 0); /* data_reference_index */
3453 avio_wb16(pb, 1); /* extent_count */
3454 mov->avif_extent_pos[i] = avio_tell(pb);
3455 avio_wb32(pb, 0); /* extent_offset (written later) */
3456 // For animated AVIF, we simply write the first packet's size.
3457 avio_wb32(pb, mov->avif_extent_length[i]); /* extent_length */
3458 }
3459
3460 return update_size(pb, pos);
3461 }
3462
3463 static int mov_write_iinf_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
3464 {
3465 int64_t iinf_pos = avio_tell(pb);
3466 avio_wb32(pb, 0); /* size */
3467 ffio_wfourcc(pb, "iinf");
3468 avio_wb32(pb, 0); /* Version & flags */
3469 avio_wb16(pb, mov->nb_streams); /* entry_count */
3470
3471 for (int i = 0; i < mov->nb_streams; i++) {
3472 int64_t infe_pos = avio_tell(pb);
3473 avio_wb32(pb, 0); /* size */
3474 ffio_wfourcc(pb, "infe");
3475 avio_w8(pb, 0x2); /* Version */
3476 avio_wb24(pb, 0); /* flags */
3477 avio_wb16(pb, i + 1); /* item_id */
3478 avio_wb16(pb, 0); /* item_protection_index */
3479 avio_write(pb, "av01", 4); /* item_type */
3480 avio_write(pb, !i ? "Color\0" : "Alpha\0", 6); /* item_name */
3481 update_size(pb, infe_pos);
3482 }
3483
3484 return update_size(pb, iinf_pos);
3485 }
3486
3487
3488 static int mov_write_iref_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
3489 {
3490 int64_t auxl_pos;
3491 int64_t iref_pos = avio_tell(pb);
3492 avio_wb32(pb, 0); /* size */
3493 ffio_wfourcc(pb, "iref");
3494 avio_wb32(pb, 0); /* Version & flags */
3495
3496 auxl_pos = avio_tell(pb);
3497 avio_wb32(pb, 0); /* size */
3498 ffio_wfourcc(pb, "auxl");
3499 avio_wb16(pb, 2); /* from_item_ID */
3500 avio_wb16(pb, 1); /* reference_count */
3501 avio_wb16(pb, 1); /* to_item_ID */
3502 update_size(pb, auxl_pos);
3503
3504 return update_size(pb, iref_pos);
3505 }
3506
3507 static int mov_write_ispe_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s,
3508 int stream_index)
3509 {
3510 int64_t pos = avio_tell(pb);
3511 avio_wb32(pb, 0); /* size */
3512 ffio_wfourcc(pb, "ispe");
3513 avio_wb32(pb, 0); /* Version & flags */
3514 avio_wb32(pb, s->streams[stream_index]->codecpar->width); /* image_width */
3515 avio_wb32(pb, s->streams[stream_index]->codecpar->height); /* image_height */
3516 return update_size(pb, pos);
3517 }
3518
3519 static int mov_write_pixi_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s,
3520 int stream_index)
3521 {
3522 int64_t pos = avio_tell(pb);
3523 const AVPixFmtDescriptor *pixdesc =
3524 av_pix_fmt_desc_get(s->streams[stream_index]->codecpar->format);
3525 avio_wb32(pb, 0); /* size */
3526 ffio_wfourcc(pb, "pixi");
3527 avio_wb32(pb, 0); /* Version & flags */
3528 avio_w8(pb, pixdesc->nb_components); /* num_channels */
3529 for (int i = 0; i < pixdesc->nb_components; ++i) {
3530 avio_w8(pb, pixdesc->comp[i].depth); /* bits_per_channel */
3531 }
3532 return update_size(pb, pos);
3533 }
3534
3535 static int mov_write_ipco_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
3536 {
3537 int64_t pos = avio_tell(pb);
3538 avio_wb32(pb, 0); /* size */
3539 ffio_wfourcc(pb, "ipco");
3540 for (int i = 0; i < mov->nb_streams; i++) {
3541 mov_write_ispe_tag(pb, mov, s, i);
3542 mov_write_pixi_tag(pb, mov, s, i);
3543 mov_write_av1c_tag(pb, &mov->tracks[i]);
3544 if (!i)
3545 mov_write_colr_tag(pb, &mov->tracks[0], 0);
3546 else
3547 mov_write_aux_tag(pb, "auxC");
3548 }
3549 return update_size(pb, pos);
3550 }
3551
3552 static int mov_write_ipma_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
3553 {
3554 int64_t pos = avio_tell(pb);
3555 avio_wb32(pb, 0); /* size */
3556 ffio_wfourcc(pb, "ipma");
3557 avio_wb32(pb, 0); /* Version & flags */
3558 avio_wb32(pb, mov->nb_streams); /* entry_count */
3559
3560 for (int i = 0, index = 1; i < mov->nb_streams; i++) {
3561 avio_wb16(pb, i + 1); /* item_ID */
3562 avio_w8(pb, 4); /* association_count */
3563
3564 // ispe association.
3565 avio_w8(pb, index++); /* essential and property_index */
3566 // pixi association.
3567 avio_w8(pb, index++); /* essential and property_index */
3568 // av1C association.
3569 avio_w8(pb, 0x80 | index++); /* essential and property_index */
3570 // colr/auxC association.
3571 avio_w8(pb, index++); /* essential and property_index */
3572 }
3573 return update_size(pb, pos);
3574 }
3575
3576 static int mov_write_iprp_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
3577 {
3578 int64_t pos = avio_tell(pb);
3579 avio_wb32(pb, 0); /* size */
3580 ffio_wfourcc(pb, "iprp");
3581 mov_write_ipco_tag(pb, mov, s);
3582 mov_write_ipma_tag(pb, mov, s);
3583 return update_size(pb, pos);
3584 }
3585
3586 2 static int mov_write_hmhd_tag(AVIOContext *pb)
3587 {
3588 /* This atom must be present, but leaving the values at zero
3589 * seems harmless. */
3590 2 avio_wb32(pb, 28); /* size */
3591 2 ffio_wfourcc(pb, "hmhd");
3592 2 avio_wb32(pb, 0); /* version, flags */
3593 2 avio_wb16(pb, 0); /* maxPDUsize */
3594 2 avio_wb16(pb, 0); /* avgPDUsize */
3595 2 avio_wb32(pb, 0); /* maxbitrate */
3596 2 avio_wb32(pb, 0); /* avgbitrate */
3597 2 avio_wb32(pb, 0); /* reserved */
3598 2 return 28;
3599 }
3600
3601 325 static int mov_write_minf_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
3602 {
3603 325 int64_t pos = avio_tell(pb);
3604 int ret;
3605
3606 325 avio_wb32(pb, 0); /* size */
3607 325 ffio_wfourcc(pb, "minf");
3608
2/2
✓ Branch 0 taken 198 times.
✓ Branch 1 taken 127 times.
325 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO)
3609 198 mov_write_vmhd_tag(pb);
3610
2/2
✓ Branch 0 taken 107 times.
✓ Branch 1 taken 20 times.
127 else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO)
3611 107 mov_write_smhd_tag(pb);
3612
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 16 times.
20 else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE) {
3613
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
4 if (track->tag == MKTAG('t','e','x','t') || is_clcp_track(track)) {
3614 1 mov_write_gmhd_tag(pb, track);
3615
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 } else if (track->tag == MOV_MP4_TTML_TAG) {
3616 1 mov_write_sthd_tag(pb);
3617 } else {
3618 2 mov_write_nmhd_tag(pb);
3619 }
3620
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 14 times.
16 } else if (track->tag == MKTAG('r','t','p',' ')) {
3621 2 mov_write_hmhd_tag(pb);
3622
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 1 times.
14 } else if (track->tag == MKTAG('t','m','c','d')) {
3623
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 9 times.
13 if (track->mode != MODE_MOV)
3624 4 mov_write_nmhd_tag(pb);
3625 else
3626 9 mov_write_gmhd_tag(pb, track);
3627
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 } else if (track->tag == MKTAG('g','p','m','d')) {
3628 1 mov_write_gmhd_tag(pb, track);
3629 }
3630
2/2
✓ Branch 0 taken 182 times.
✓ Branch 1 taken 143 times.
325 if (track->mode == MODE_MOV) /* ISO 14496-12 8.4.3.1 specifies hdlr only within mdia or meta boxes */
3631 182 mov_write_hdlr_tag(s, pb, NULL);
3632 325 mov_write_dinf_tag(pb);
3633
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 325 times.
325 if ((ret = mov_write_stbl_tag(s, pb, mov, track)) < 0)
3634 return ret;
3635 325 return update_size(pb, pos);
3636 }
3637
3638 1262 static void get_pts_range(MOVMuxContext *mov, MOVTrack *track,
3639 int64_t *start, int64_t *end)
3640 {
3641
4/4
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 1212 times.
✓ Branch 2 taken 38 times.
✓ Branch 3 taken 12 times.
1262 if (track->tag == MKTAG('t','m','c','d') && mov->nb_meta_tmcd) {
3642 // tmcd tracks gets track_duration set in mov_write_moov_tag from
3643 // another track's duration, while the end_pts may be left at zero.
3644 // Calculate the pts duration for that track instead.
3645 38 get_pts_range(mov, &mov->tracks[track->src_track], start, end);
3646 38 *start = av_rescale(*start, track->timescale,
3647 38 mov->tracks[track->src_track].timescale);
3648 38 *end = av_rescale(*end, track->timescale,
3649 38 mov->tracks[track->src_track].timescale);
3650 38 return;
3651 }
3652
2/2
✓ Branch 0 taken 1166 times.
✓ Branch 1 taken 58 times.
1224 if (track->end_pts != AV_NOPTS_VALUE &&
3653
1/2
✓ Branch 0 taken 1166 times.
✗ Branch 1 not taken.
1166 track->start_dts != AV_NOPTS_VALUE &&
3654
1/2
✓ Branch 0 taken 1166 times.
✗ Branch 1 not taken.
1166 track->start_cts != AV_NOPTS_VALUE) {
3655 1166 *start = track->start_dts + track->start_cts;
3656 1166 *end = track->end_pts;
3657 1166 return;
3658 }
3659 58 *start = 0;
3660 58 *end = track->track_duration;
3661 }
3662
3663 600 static int64_t calc_samples_pts_duration(MOVMuxContext *mov, MOVTrack *track)
3664 {
3665 int64_t start, end;
3666 600 get_pts_range(mov, track, &start, &end);
3667 600 return end - start;
3668 }
3669
3670 // Calculate the actual duration of the track, after edits.
3671 // If it starts with a pts < 0, that is removed by the edit list.
3672 // If it starts with a pts > 0, the edit list adds a delay before that.
3673 // Thus, with edit lists enabled, the post-edit output of the file is
3674 // starting with pts=0.
3675 624 static int64_t calc_pts_duration(MOVMuxContext *mov, MOVTrack *track)
3676 {
3677 int64_t start, end;
3678 624 get_pts_range(mov, track, &start, &end);
3679
2/2
✓ Branch 0 taken 556 times.
✓ Branch 1 taken 68 times.
624 if (mov->use_editlist != 0)
3680 556 start = 0;
3681 624 return end - start;
3682 }
3683
3684 881 static int mov_mdhd_mvhd_tkhd_version(MOVMuxContext *mov, MOVTrack *track, int64_t duration)
3685 {
3686
4/4
✓ Branch 0 taken 650 times.
✓ Branch 1 taken 231 times.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 636 times.
881 if (track && track->mode == MODE_ISM)
3687 14 return 1;
3688
2/2
✓ Branch 0 taken 863 times.
✓ Branch 1 taken 4 times.
867 if (duration < INT32_MAX)
3689 863 return 0;
3690 4 return 1;
3691 }
3692
3693 325 static int mov_write_mdhd_tag(AVIOContext *pb, MOVMuxContext *mov,
3694 MOVTrack *track)
3695 {
3696 325 int64_t duration = calc_samples_pts_duration(mov, track);
3697 325 int version = mov_mdhd_mvhd_tkhd_version(mov, track, duration);
3698
3699
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 314 times.
325 (version == 1) ? avio_wb32(pb, 44) : avio_wb32(pb, 32); /* size */
3700 325 ffio_wfourcc(pb, "mdhd");
3701 325 avio_w8(pb, version);
3702 325 avio_wb24(pb, 0); /* flags */
3703
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 314 times.
325 if (version == 1) {
3704 11 avio_wb64(pb, track->time);
3705 11 avio_wb64(pb, track->time);
3706 } else {
3707 314 avio_wb32(pb, track->time); /* creation time */
3708 314 avio_wb32(pb, track->time); /* modification time */
3709 }
3710 325 avio_wb32(pb, track->timescale); /* time scale (sample rate for audio) */
3711
4/4
✓ Branch 0 taken 90 times.
✓ Branch 1 taken 235 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 83 times.
325 if (!track->entry && mov->mode == MODE_ISM)
3712
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 (version == 1) ? avio_wb64(pb, UINT64_C(0xffffffffffffffff)) : avio_wb32(pb, 0xffffffff);
3713
2/2
✓ Branch 0 taken 83 times.
✓ Branch 1 taken 235 times.
318 else if (!track->entry)
3714
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 79 times.
83 (version == 1) ? avio_wb64(pb, 0) : avio_wb32(pb, 0);
3715 else
3716
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 235 times.
235 (version == 1) ? avio_wb64(pb, duration) : avio_wb32(pb, duration); /* duration */
3717 325 avio_wb16(pb, track->language); /* language */
3718 325 avio_wb16(pb, 0); /* reserved (quality) */
3719
3720
3/4
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 314 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
325 if (version != 0 && track->mode == MODE_MOV) {
3721 av_log(NULL, AV_LOG_ERROR,
3722 "FATAL error, file duration too long for timebase, this file will not be\n"
3723 "playable with QuickTime. Choose a different timebase with "
3724 "-video_track_timescale or a different container format\n");
3725 }
3726
3727 325 return 32;
3728 }
3729
3730 325 static int mov_write_mdia_tag(AVFormatContext *s, AVIOContext *pb,
3731 MOVMuxContext *mov, MOVTrack *track)
3732 {
3733 325 int64_t pos = avio_tell(pb);
3734 int ret;
3735
3736 325 avio_wb32(pb, 0); /* size */
3737 325 ffio_wfourcc(pb, "mdia");
3738 325 mov_write_mdhd_tag(pb, mov, track);
3739 325 mov_write_hdlr_tag(s, pb, track);
3740
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 325 times.
325 if ((ret = mov_write_minf_tag(s, pb, mov, track)) < 0)
3741 return ret;
3742 325 return update_size(pb, pos);
3743 }
3744
3745 /* transformation matrix
3746 |a b u|
3747 |c d v|
3748 |tx ty w| */
3749 555 static void write_matrix(AVIOContext *pb, int16_t a, int16_t b, int16_t c,
3750 int16_t d, int16_t tx, int16_t ty)
3751 {
3752 555 avio_wb32(pb, a << 16); /* 16.16 format */
3753 555 avio_wb32(pb, b << 16); /* 16.16 format */
3754 555 avio_wb32(pb, 0); /* u in 2.30 format */
3755 555 avio_wb32(pb, c << 16); /* 16.16 format */
3756 555 avio_wb32(pb, d << 16); /* 16.16 format */
3757 555 avio_wb32(pb, 0); /* v in 2.30 format */
3758 555 avio_wb32(pb, tx << 16); /* 16.16 format */
3759 555 avio_wb32(pb, ty << 16); /* 16.16 format */
3760 555 avio_wb32(pb, 1 << 30); /* w in 2.30 format */
3761 555 }
3762
3763 325 static int mov_write_tkhd_tag(AVIOContext *pb, MOVMuxContext *mov,
3764 MOVTrack *track, AVStream *st)
3765 {
3766 650 int64_t duration = av_rescale_rnd(calc_pts_duration(mov, track),
3767 325 mov->movie_timescale, track->timescale,
3768 AV_ROUND_UP);
3769 int version;
3770 325 int flags = MOV_TKHD_FLAG_IN_MOVIE;
3771 325 int group = 0;
3772
3773 325 uint32_t *display_matrix = NULL;
3774 int i;
3775
3776
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 325 times.
325 if (mov->mode == MODE_AVIF)
3777 if (!mov->avif_loop_count)
3778 duration = INT64_MAX;
3779 else
3780 duration *= mov->avif_loop_count;
3781
3782
2/2
✓ Branch 0 taken 312 times.
✓ Branch 1 taken 13 times.
325 if (st) {
3783 const AVPacketSideData *sd;
3784
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 312 times.
312 if (mov->per_stream_grouping)
3785 group = st->index;
3786 else
3787 312 group = st->codecpar->codec_type;
3788
3789 312 sd = av_packet_side_data_get(st->codecpar->coded_side_data,
3790 312 st->codecpar->nb_coded_side_data,
3791 AV_PKT_DATA_DISPLAYMATRIX);
3792
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 311 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
312 if (sd && sd->size == 9 * sizeof(*display_matrix))
3793 1 display_matrix = (uint32_t *)sd->data;
3794 }
3795
3796
2/2
✓ Branch 0 taken 300 times.
✓ Branch 1 taken 25 times.
325 if (track->flags & MOV_TRACK_ENABLED)
3797 300 flags |= MOV_TKHD_FLAG_ENABLED;
3798
3799 325 version = mov_mdhd_mvhd_tkhd_version(mov, track, duration);
3800
3801
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 318 times.
325 (version == 1) ? avio_wb32(pb, 104) : avio_wb32(pb, 92); /* size */
3802 325 ffio_wfourcc(pb, "tkhd");
3803 325 avio_w8(pb, version);
3804 325 avio_wb24(pb, flags);
3805
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 318 times.
325 if (version == 1) {
3806 7 avio_wb64(pb, track->time);
3807 7 avio_wb64(pb, track->time);
3808 } else {
3809 318 avio_wb32(pb, track->time); /* creation time */
3810 318 avio_wb32(pb, track->time); /* modification time */
3811 }
3812 325 avio_wb32(pb, track->track_id); /* track-id */
3813 325 avio_wb32(pb, 0); /* reserved */
3814
4/4
✓ Branch 0 taken 90 times.
✓ Branch 1 taken 235 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 83 times.
325 if (!track->entry && mov->mode == MODE_ISM)
3815
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 (version == 1) ? avio_wb64(pb, UINT64_C(0xffffffffffffffff)) : avio_wb32(pb, 0xffffffff);
3816
2/2
✓ Branch 0 taken 83 times.
✓ Branch 1 taken 235 times.
318 else if (!track->entry)
3817
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 83 times.
83 (version == 1) ? avio_wb64(pb, 0) : avio_wb32(pb, 0);
3818 else
3819
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 235 times.
235 (version == 1) ? avio_wb64(pb, duration) : avio_wb32(pb, duration);
3820
3821 325 avio_wb32(pb, 0); /* reserved */
3822 325 avio_wb32(pb, 0); /* reserved */
3823 325 avio_wb16(pb, 0); /* layer */
3824 325 avio_wb16(pb, group); /* alternate group) */
3825 /* Volume, only for audio */
3826
2/2
✓ Branch 0 taken 107 times.
✓ Branch 1 taken 218 times.
325 if (track->par->codec_type == AVMEDIA_TYPE_AUDIO)
3827 107 avio_wb16(pb, 0x0100);
3828 else
3829 218 avio_wb16(pb, 0);
3830 325 avio_wb16(pb, 0); /* reserved */
3831
3832 /* Matrix structure */
3833
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 324 times.
325 if (display_matrix) {
3834
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1 times.
10 for (i = 0; i < 9; i++)
3835 9 avio_wb32(pb, display_matrix[i]);
3836 } else {
3837 324 write_matrix(pb, 1, 0, 0, 1, 0, 0);
3838 }
3839 /* Track width and height, for visual only */
3840
4/4
✓ Branch 0 taken 312 times.
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 114 times.
✓ Branch 3 taken 198 times.
325 if (st && (track->par->codec_type == AVMEDIA_TYPE_VIDEO ||
3841
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 111 times.
315 track->par->codec_type == AVMEDIA_TYPE_SUBTITLE)) {
3842 int64_t track_width_1616;
3843
3/4
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 133 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 68 times.
201 if (track->mode == MODE_MOV || track->mode == MODE_AVIF) {
3844 133 track_width_1616 = track->par->width * 0x10000ULL;
3845 } else {
3846 68 track_width_1616 = av_rescale(st->sample_aspect_ratio.num,
3847 68 track->par->width * 0x10000LL,
3848 68 st->sample_aspect_ratio.den);
3849
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 66 times.
68 if (!track_width_1616 ||
3850
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 track->height != track->par->height ||
3851 track_width_1616 > UINT32_MAX)
3852 66 track_width_1616 = track->par->width * 0x10000ULL;
3853 }
3854
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 201 times.
201 if (track_width_1616 > UINT32_MAX) {
3855 av_log(mov->fc, AV_LOG_WARNING, "track width is too large\n");
3856 track_width_1616 = 0;
3857 }
3858 201 avio_wb32(pb, track_width_1616);
3859
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 201 times.
201 if (track->height > 0xFFFF) {
3860 av_log(mov->fc, AV_LOG_WARNING, "track height is too large\n");
3861 avio_wb32(pb, 0);
3862 } else
3863 201 avio_wb32(pb, track->height * 0x10000U);
3864 } else {
3865 124 avio_wb32(pb, 0);
3866 124 avio_wb32(pb, 0);
3867 }
3868 325 return 0x5c;
3869 }
3870
3871 1 static int mov_write_tapt_tag(AVIOContext *pb, MOVTrack *track)
3872 {
3873 1 int32_t width = av_rescale(track->par->sample_aspect_ratio.num, track->par->width,
3874 1 track->par->sample_aspect_ratio.den);
3875
3876 1 int64_t pos = avio_tell(pb);
3877
3878 1 avio_wb32(pb, 0); /* size */
3879 1 ffio_wfourcc(pb, "tapt");
3880
3881 1 avio_wb32(pb, 20);
3882 1 ffio_wfourcc(pb, "clef");
3883 1 avio_wb32(pb, 0);
3884 1 avio_wb32(pb, width << 16);
3885 1 avio_wb32(pb, track->par->height << 16);
3886
3887 1 avio_wb32(pb, 20);
3888 1 ffio_wfourcc(pb, "prof");
3889 1 avio_wb32(pb, 0);
3890 1 avio_wb32(pb, width << 16);
3891 1 avio_wb32(pb, track->par->height << 16);
3892
3893 1 avio_wb32(pb, 20);
3894 1 ffio_wfourcc(pb, "enof");
3895 1 avio_wb32(pb, 0);
3896 1 avio_wb32(pb, track->par->width << 16);
3897 1 avio_wb32(pb, track->par->height << 16);
3898
3899 1 return update_size(pb, pos);
3900 }
3901
3902 // This box is written in the following cases:
3903 // * Seems important for the psp playback. Without it the movie seems to hang.
3904 // * Used for specifying the looping behavior of animated AVIF (as specified
3905 // in Section 9.6 of the HEIF specification ISO/IEC 23008-12).
3906 275 static int mov_write_edts_tag(AVIOContext *pb, MOVMuxContext *mov,
3907 MOVTrack *track)
3908 {
3909 550 int64_t duration = av_rescale_rnd(calc_samples_pts_duration(mov, track),
3910 275 mov->movie_timescale, track->timescale,
3911 AV_ROUND_UP);
3912 275 int version = duration < INT32_MAX ? 0 : 1;
3913 int entry_size, entry_count, size;
3914 275 int64_t delay, start_ct = track->start_cts;
3915 275 int64_t start_dts = track->start_dts;
3916 275 int flags = 0;
3917
3918
2/2
✓ Branch 0 taken 221 times.
✓ Branch 1 taken 54 times.
275 if (track->entry) {
3919
2/4
✓ Branch 0 taken 221 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 221 times.
221 if (start_dts != track->cluster[0].dts || start_ct != track->cluster[0].cts) {
3920
3921 av_log(mov->fc, AV_LOG_DEBUG,
3922 "EDTS using dts:%"PRId64" cts:%d instead of dts:%"PRId64" cts:%"PRId64" tid:%d\n",
3923 track->cluster[0].dts, track->cluster[0].cts,
3924 start_dts, start_ct, track->track_id);
3925 start_dts = track->cluster[0].dts;
3926 start_ct = track->cluster[0].cts;
3927 }
3928 }
3929
3930 275 delay = av_rescale_rnd(start_dts + start_ct, mov->movie_timescale,
3931 275 track->timescale, AV_ROUND_DOWN);
3932
3933
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 275 times.
275 if (mov->mode == MODE_AVIF) {
3934 delay = 0;
3935 // Section 9.6.3 of ISO/IEC 23008-12: flags specifies repetition of the
3936 // edit list as follows: (flags & 1) equal to 0 specifies that the edit
3937 // list is not repeated, while (flags & 1) equal to 1 specifies that the
3938 // edit list is repeated.
3939 flags = mov->avif_loop_count != 1;
3940 start_ct = 0;
3941 }
3942
3943 275 version |= delay < INT32_MAX ? 0 : 1;
3944
3945
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 275 times.
275 entry_size = (version == 1) ? 20 : 12;
3946
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 273 times.
275 entry_count = 1 + (delay > 0);
3947 275 size = 24 + entry_count * entry_size;
3948
3949 /* write the atom data */
3950 275 avio_wb32(pb, size);
3951 275 ffio_wfourcc(pb, "edts");
3952 275 avio_wb32(pb, size - 8);
3953 275 ffio_wfourcc(pb, "elst");
3954 275 avio_w8(pb, version);
3955 275 avio_wb24(pb, flags); /* flags */
3956
3957 275 avio_wb32(pb, entry_count);
3958
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 273 times.
275 if (delay > 0) { /* add an empty edit to delay presentation */
3959 /* In the positive delay case, the delay includes the cts
3960 * offset, and the second edit list entry below trims out
3961 * the same amount from the actual content. This makes sure
3962 * that the offset last sample is included in the edit
3963 * list duration as well. */
3964
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (version == 1) {
3965 avio_wb64(pb, delay);
3966 avio_wb64(pb, -1);
3967 } else {
3968 2 avio_wb32(pb, delay);
3969 2 avio_wb32(pb, -1);
3970 }
3971 2 avio_wb32(pb, 0x00010000);
3972
1/2
✓ Branch 0 taken 273 times.
✗ Branch 1 not taken.
273 } else if (mov->mode != MODE_AVIF) {
3973 /* Avoid accidentally ending up with start_ct = -1 which has got a
3974 * special meaning. Normally start_ct should end up positive or zero
3975 * here, but use FFMIN in case dts is a small positive integer
3976 * rounded to 0 when represented in movie timescale units. */
3977
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 273 times.
273 av_assert0(av_rescale_rnd(start_dts, mov->movie_timescale, track->timescale, AV_ROUND_DOWN) <= 0);
3978 273 start_ct = -FFMIN(start_dts, 0);
3979 /* Note, this delay is calculated from the pts of the first sample,
3980 * ensuring that we don't reduce the duration for cases with
3981 * dts<0 pts=0. */
3982 273 duration += delay;
3983 }
3984
3985 /* For fragmented files, we don't know the full length yet. Setting
3986 * duration to 0 allows us to only specify the offset, including
3987 * the rest of the content (from all future fragments) without specifying
3988 * an explicit duration. */
3989
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 217 times.
275 if (mov->flags & FF_MOV_FLAG_FRAGMENT)
3990 58 duration = 0;
3991
3992 /* duration */
3993
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 275 times.
275 if (version == 1) {
3994 avio_wb64(pb, duration);
3995 avio_wb64(pb, start_ct);
3996 } else {
3997 275 avio_wb32(pb, duration);
3998 275 avio_wb32(pb, start_ct);
3999 }
4000 275 avio_wb32(pb, 0x00010000);
4001 275 return size;
4002 }
4003
4004 14 static int mov_write_tref_tag(AVIOContext *pb, MOVTrack *track)
4005 {
4006 14 avio_wb32(pb, 20); // size
4007 14 ffio_wfourcc(pb, "tref");
4008 14 avio_wb32(pb, 12); // size (subatom)
4009 14 avio_wl32(pb, track->tref_tag);
4010 14 avio_wb32(pb, track->tref_id);
4011 14 return 20;
4012 }
4013
4014 // goes at the end of each track! ... Critical for PSP playback ("Incompatible data" without it)
4015 2 static int mov_write_uuid_tag_psp(AVIOContext *pb, MOVTrack *mov)
4016 {
4017 2 avio_wb32(pb, 0x34); /* size ... reports as 28 in mp4box! */
4018 2 ffio_wfourcc(pb, "uuid");
4019 2 ffio_wfourcc(pb, "USMT");
4020 2 avio_wb32(pb, 0x21d24fce);
4021 2 avio_wb32(pb, 0xbb88695c);
4022 2 avio_wb32(pb, 0xfac9c740);
4023 2 avio_wb32(pb, 0x1c); // another size here!
4024 2 ffio_wfourcc(pb, "MTDT");
4025 2 avio_wb32(pb, 0x00010012);
4026 2 avio_wb32(pb, 0x0a);
4027 2 avio_wb32(pb, 0x55c40000);
4028 2 avio_wb32(pb, 0x1);
4029 2 avio_wb32(pb, 0x0);
4030 2 return 0x34;
4031 }
4032
4033 2 static int mov_write_udta_sdp(AVIOContext *pb, MOVTrack *track)
4034 {
4035 2 AVFormatContext *ctx = track->rtp_ctx;
4036 2 char buf[1000] = "";
4037 int len;
4038
4039 2 ff_sdp_write_media(buf, sizeof(buf), ctx->streams[0], track->src_track,
4040 NULL, NULL, 0, 0, ctx);
4041 2 av_strlcatf(buf, sizeof(buf), "a=control:streamid=%d\r\n", track->track_id);
4042 2 len = strlen(buf);
4043
4044 2 avio_wb32(pb, len + 24);
4045 2 ffio_wfourcc(pb, "udta");
4046 2 avio_wb32(pb, len + 16);
4047 2 ffio_wfourcc(pb, "hnti");
4048 2 avio_wb32(pb, len + 8);
4049 2 ffio_wfourcc(pb, "sdp ");
4050 2 avio_write(pb, buf, len);
4051 2 return len + 24;
4052 }
4053
4054 304 static int mov_write_track_metadata(AVIOContext *pb, AVStream *st,
4055 const char *tag, const char *str)
4056 {
4057 304 int64_t pos = avio_tell(pb);
4058 304 AVDictionaryEntry *t = av_dict_get(st->metadata, str, NULL, 0);
4059
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 303 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
304 if (!t || !utf8len(t->value))
4060 303 return 0;
4061
4062 1 avio_wb32(pb, 0); /* size */
4063 1 ffio_wfourcc(pb, tag); /* type */
4064 1 avio_write(pb, t->value, strlen(t->value)); /* UTF8 string value */
4065 1 return update_size(pb, pos);
4066 }
4067
4068 2 static int mov_write_track_kind(AVIOContext *pb, const char *scheme_uri,
4069 const char *value)
4070 {
4071 2 int64_t pos = avio_tell(pb);
4072
4073 /* Box|FullBox basics */
4074 2 avio_wb32(pb, 0); /* size placeholder */
4075 2 ffio_wfourcc(pb, (const unsigned char *)"kind");
4076 2 avio_w8(pb, 0); /* version = 0 */
4077 2 avio_wb24(pb, 0); /* flags = 0 */
4078
4079 /* Required null-terminated scheme URI */
4080 2 avio_write(pb, (const unsigned char *)scheme_uri,
4081 2 strlen(scheme_uri));
4082 2 avio_w8(pb, 0);
4083
4084 /* Optional value string */
4085
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])
4086 2 avio_write(pb, (const unsigned char *)value,
4087 2 strlen(value));
4088
4089 2 avio_w8(pb, 0);
4090
4091 2 return update_size(pb, pos);
4092 }
4093
4094 128 static int mov_write_track_kinds(AVIOContext *pb, AVStream *st)
4095 {
4096 128 int ret = AVERROR_BUG;
4097
4098
2/2
✓ Branch 0 taken 128 times.
✓ Branch 1 taken 128 times.
256 for (int i = 0; ff_mov_track_kind_table[i].scheme_uri; i++) {
4099 128 const struct MP4TrackKindMapping map = ff_mov_track_kind_table[i];
4100
4101
2/2
✓ Branch 0 taken 640 times.
✓ Branch 1 taken 128 times.
768 for (int j = 0; map.value_maps[j].disposition; j++) {
4102 640 const struct MP4TrackKindValueMapping value_map = map.value_maps[j];
4103
2/2
✓ Branch 0 taken 638 times.
✓ Branch 1 taken 2 times.
640 if (!(st->disposition & value_map.disposition))
4104 638 continue;
4105
4106
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)
4107 return ret;
4108 }
4109 }
4110
4111 128 return 0;
4112 }
4113
4114 325 static int mov_write_track_udta_tag(AVIOContext *pb, MOVMuxContext *mov,
4115 AVStream *st)
4116 {
4117 AVIOContext *pb_buf;
4118 int ret, size;
4119 uint8_t *buf;
4120
4121
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 312 times.
325 if (!st)
4122 13 return 0;
4123
4124 312 ret = avio_open_dyn_buf(&pb_buf);
4125
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 312 times.
312 if (ret < 0)
4126 return ret;
4127
4128
2/2
✓ Branch 0 taken 304 times.
✓ Branch 1 taken 8 times.
312 if (mov->mode & (MODE_MP4|MODE_MOV))
4129 304 mov_write_track_metadata(pb_buf, st, "name", "title");
4130
4131
2/2
✓ Branch 0 taken 128 times.
✓ Branch 1 taken 184 times.
312 if (mov->mode & MODE_MP4) {
4132
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 128 times.
128 if ((ret = mov_write_track_kinds(pb_buf, st)) < 0)
4133 return ret;
4134 }
4135
4136
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 309 times.
312 if ((size = avio_get_dyn_buf(pb_buf, &buf)) > 0) {
4137 3 avio_wb32(pb, size + 8);
4138 3 ffio_wfourcc(pb, "udta");
4139 3 avio_write(pb, buf, size);
4140 }
4141 312 ffio_free_dyn_buf(&pb_buf);
4142
4143 312 return 0;
4144 }
4145
4146 325 static int mov_write_trak_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov,
4147 MOVTrack *track, AVStream *st)
4148 {
4149 325 int64_t pos = avio_tell(pb);
4150 325 int entry_backup = track->entry;
4151 325 int chunk_backup = track->chunkCount;
4152 int ret;
4153
4154 /* If we want to have an empty moov, but some samples already have been
4155 * buffered (delay_moov), pretend that no samples have been written yet. */
4156
2/2
✓ Branch 0 taken 90 times.
✓ Branch 1 taken 235 times.
325 if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV)
4157 90 track->chunkCount = track->entry = 0;
4158
4159 325 avio_wb32(pb, 0); /* size */
4160 325 ffio_wfourcc(pb, "trak");
4161 325 mov_write_tkhd_tag(pb, mov, track, st);
4162
4163 av_assert2(mov->use_editlist >= 0);
4164
4165
2/2
✓ Branch 0 taken 299 times.
✓ Branch 1 taken 26 times.
325 if (track->start_dts != AV_NOPTS_VALUE) {
4166
2/2
✓ Branch 0 taken 275 times.
✓ Branch 1 taken 24 times.
299 if (mov->use_editlist)
4167 275 mov_write_edts_tag(pb, mov, track); // PSP Movies and several other cases require edts box
4168
5/8
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 24 times.
24 else if ((track->entry && track->cluster[0].dts) || track->mode == MODE_PSP || is_clcp_track(track))
4169 av_log(mov->fc, AV_LOG_WARNING,
4170 "Not writing any edit list even though one would have been required\n");
4171 }
4172
4173
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 325 times.
325 if (mov->is_animated_avif)
4174 mov_write_edts_tag(pb, mov, track);
4175
4176
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 311 times.
325 if (track->tref_tag)
4177 14 mov_write_tref_tag(pb, track);
4178
4179
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 325 times.
325 if ((ret = mov_write_mdia_tag(s, pb, mov, track)) < 0)
4180 return ret;
4181
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 323 times.
325 if (track->mode == MODE_PSP)
4182 2 mov_write_uuid_tag_psp(pb, track); // PSP Movies require this uuid box
4183
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 323 times.
325 if (track->tag == MKTAG('r','t','p',' '))
4184 2 mov_write_udta_sdp(pb, track);
4185
2/2
✓ Branch 0 taken 182 times.
✓ Branch 1 taken 143 times.
325 if (track->mode == MODE_MOV) {
4186
2/2
✓ Branch 0 taken 133 times.
✓ Branch 1 taken 49 times.
182 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
4187 133 double sample_aspect_ratio = av_q2d(st->sample_aspect_ratio);
4188
4/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 129 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 3 times.
133 if (st->sample_aspect_ratio.num && 1.0 != sample_aspect_ratio) {
4189 1 mov_write_tapt_tag(pb, track);
4190 }
4191 }
4192
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 182 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
182 if (is_clcp_track(track) && st->sample_aspect_ratio.num) {
4193 mov_write_tapt_tag(pb, track);
4194 }
4195 }
4196 325 mov_write_track_udta_tag(pb, mov, st);
4197 325 track->entry = entry_backup;
4198 325 track->chunkCount = chunk_backup;
4199 325 return update_size(pb, pos);
4200 }
4201
4202 static int mov_write_iods_tag(AVIOContext *pb, MOVMuxContext *mov)
4203 {
4204 int i, has_audio = 0, has_video = 0;
4205 int64_t pos = avio_tell(pb);
4206 int audio_profile = mov->iods_audio_profile;
4207 int video_profile = mov->iods_video_profile;
4208 for (i = 0; i < mov->nb_tracks; i++) {
4209 if (mov->tracks[i].entry > 0 || mov->flags & FF_MOV_FLAG_EMPTY_MOOV) {
4210 has_audio |= mov->tracks[i].par->codec_type == AVMEDIA_TYPE_AUDIO;
4211 has_video |= mov->tracks[i].par->codec_type == AVMEDIA_TYPE_VIDEO;
4212 }
4213 }
4214 if (audio_profile < 0)
4215 audio_profile = 0xFF - has_audio;
4216 if (video_profile < 0)
4217 video_profile = 0xFF - has_video;
4218 avio_wb32(pb, 0x0); /* size */
4219 ffio_wfourcc(pb, "iods");
4220 avio_wb32(pb, 0); /* version & flags */
4221 put_descr(pb, 0x10, 7);
4222 avio_wb16(pb, 0x004f);
4223 avio_w8(pb, 0xff);
4224 avio_w8(pb, 0xff);
4225 avio_w8(pb, audio_profile);
4226 avio_w8(pb, video_profile);
4227 avio_w8(pb, 0xff);
4228 return update_size(pb, pos);
4229 }
4230
4231 108 static int mov_write_trex_tag(AVIOContext *pb, MOVTrack *track)
4232 {
4233 108 avio_wb32(pb, 0x20); /* size */
4234 108 ffio_wfourcc(pb, "trex");
4235 108 avio_wb32(pb, 0); /* version & flags */
4236 108 avio_wb32(pb, track->track_id); /* track ID */
4237 108 avio_wb32(pb, 1); /* default sample description index */
4238 108 avio_wb32(pb, 0); /* default sample duration */
4239 108 avio_wb32(pb, 0); /* default sample size */
4240 108 avio_wb32(pb, 0); /* default sample flags */
4241 108 return 0;
4242 }
4243
4244 56 static int mov_write_mvex_tag(AVIOContext *pb, MOVMuxContext *mov)
4245 {
4246 56 int64_t pos = avio_tell(pb);
4247 int i;
4248 56 avio_wb32(pb, 0x0); /* size */
4249 56 ffio_wfourcc(pb, "mvex");
4250
2/2
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 56 times.
164 for (i = 0; i < mov->nb_tracks; i++)
4251 108 mov_write_trex_tag(pb, &mov->tracks[i]);
4252 56 return update_size(pb, pos);
4253 }
4254
4255 231 static int mov_write_mvhd_tag(AVIOContext *pb, MOVMuxContext *mov)
4256 {
4257 231 int max_track_id = 1, i;
4258 231 int64_t max_track_len = 0;
4259 int version;
4260 int timescale;
4261
4262
2/2
✓ Branch 0 taken 327 times.
✓ Branch 1 taken 231 times.
558 for (i = 0; i < mov->nb_tracks; i++) {
4263
3/4
✓ Branch 0 taken 299 times.
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 299 times.
✗ Branch 3 not taken.
327 if (mov->tracks[i].entry > 0 && mov->tracks[i].timescale) {
4264 598 int64_t max_track_len_temp = av_rescale_rnd(
4265 299 calc_pts_duration(mov, &mov->tracks[i]),
4266 299 mov->movie_timescale,
4267 299 mov->tracks[i].timescale,
4268 AV_ROUND_UP);
4269
2/2
✓ Branch 0 taken 231 times.
✓ Branch 1 taken 68 times.
299 if (max_track_len < max_track_len_temp)
4270 231 max_track_len = max_track_len_temp;
4271
2/2
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 218 times.
299 if (max_track_id < mov->tracks[i].track_id)
4272 81 max_track_id = mov->tracks[i].track_id;
4273 }
4274 }
4275 /* If using delay_moov, make sure the output is the same as if no
4276 * samples had been written yet. */
4277
2/2
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 184 times.
231 if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV) {
4278 47 max_track_len = 0;
4279 47 max_track_id = 1;
4280 }
4281
4282 231 version = mov_mdhd_mvhd_tkhd_version(mov, NULL, max_track_len);
4283
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 231 times.
231 avio_wb32(pb, version == 1 ? 120 : 108); /* size */
4284
4285 231 ffio_wfourcc(pb, "mvhd");
4286 231 avio_w8(pb, version);
4287 231 avio_wb24(pb, 0); /* flags */
4288
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 231 times.
231 if (version == 1) {
4289 avio_wb64(pb, mov->time);
4290 avio_wb64(pb, mov->time);
4291 } else {
4292 231 avio_wb32(pb, mov->time); /* creation time */
4293 231 avio_wb32(pb, mov->time); /* modification time */
4294 }
4295
4296 231 timescale = mov->movie_timescale;
4297
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 231 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
231 if (mov->mode == MODE_AVIF && !timescale)
4298 timescale = mov->tracks[0].timescale;
4299
4300 231 avio_wb32(pb, timescale);
4301
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 231 times.
231 (version == 1) ? avio_wb64(pb, max_track_len) : avio_wb32(pb, max_track_len); /* duration of longest track */
4302
4303 231 avio_wb32(pb, 0x00010000); /* reserved (preferred rate) 1.0 = normal */
4304 231 avio_wb16(pb, 0x0100); /* reserved (preferred volume) 1.0 = normal */
4305 231 ffio_fill(pb, 0, 2 + 2 * 4); /* reserved */
4306
4307 /* Matrix structure */
4308 231 write_matrix(pb, 1, 0, 0, 1, 0, 0);
4309
4310 231 avio_wb32(pb, 0); /* reserved (preview time) */
4311 231 avio_wb32(pb, 0); /* reserved (preview duration) */
4312 231 avio_wb32(pb, 0); /* reserved (poster time) */
4313 231 avio_wb32(pb, 0); /* reserved (selection time) */
4314 231 avio_wb32(pb, 0); /* reserved (selection duration) */
4315 231 avio_wb32(pb, 0); /* reserved (current time) */
4316 231 avio_wb32(pb, max_track_id + 1); /* Next track id */
4317 231 return 0x6c;
4318 }
4319
4320 81 static int mov_write_itunes_hdlr_tag(AVIOContext *pb, MOVMuxContext *mov,
4321 AVFormatContext *s)
4322 {
4323 81 avio_wb32(pb, 33); /* size */
4324 81 ffio_wfourcc(pb, "hdlr");
4325 81 avio_wb32(pb, 0);
4326 81 avio_wb32(pb, 0);
4327 81 ffio_wfourcc(pb, "mdir");
4328 81 ffio_wfourcc(pb, "appl");
4329 81 avio_wb32(pb, 0);
4330 81 avio_wb32(pb, 0);
4331 81 avio_w8(pb, 0);
4332 81 return 33;
4333 }
4334
4335 /* helper function to write a data tag with the specified string as data */
4336 54 static int mov_write_string_data_tag(AVIOContext *pb, const char *data, int lang, int long_style)
4337 {
4338 54 size_t data_len = strlen(data);
4339
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 34 times.
54 if (long_style) {
4340 20 int size = 16 + data_len;
4341 20 avio_wb32(pb, size); /* size */
4342 20 ffio_wfourcc(pb, "data");
4343 20 avio_wb32(pb, 1);
4344 20 avio_wb32(pb, 0);
4345 20 avio_write(pb, data, data_len);
4346 20 return size;
4347 } else {
4348 34 avio_wb16(pb, data_len); /* string length */
4349
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 8 times.
34 if (!lang)
4350 26 lang = ff_mov_iso639_to_lang("und", 1);
4351 34 avio_wb16(pb, lang);
4352 34 avio_write(pb, data, data_len);
4353 34 return data_len + 4;
4354 }
4355 }
4356
4357 54 static int mov_write_string_tag(AVIOContext *pb, const char *name,
4358 const char *value, int lang, int long_style)
4359 {
4360 54 int size = 0;
4361
2/4
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 54 times.
✗ Branch 3 not taken.
54 if (value && value[0]) {
4362 54 int64_t pos = avio_tell(pb);
4363 54 avio_wb32(pb, 0); /* size */
4364 54 ffio_wfourcc(pb, name);
4365 54 mov_write_string_data_tag(pb, value, lang, long_style);
4366 54 size = update_size(pb, pos);
4367 }
4368 54 return size;
4369 }
4370
4371 3625 static AVDictionaryEntry *get_metadata_lang(AVFormatContext *s,
4372 const char *tag, int *lang)
4373 {
4374 int l, len, len2;
4375 3625 AVDictionaryEntry *t, *t2 = NULL;
4376 char tag2[16];
4377
4378 3625 *lang = 0;
4379
4380
2/2
✓ Branch 1 taken 3573 times.
✓ Branch 2 taken 52 times.
3625 if (!(t = av_dict_get(s->metadata, tag, NULL, 0)))
4381 3573 return NULL;
4382
4383 52 len = strlen(t->key);
4384 52 snprintf(tag2, sizeof(tag2), "%s-", tag);
4385
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 44 times.
52 while ((t2 = av_dict_get(s->metadata, tag2, t2, AV_DICT_IGNORE_SUFFIX))) {
4386 8 len2 = strlen(t2->key);
4387
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
8 if (len2 == len + 4 && !strcmp(t->value, t2->value)
4388
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 && (l = ff_mov_iso639_to_lang(&t2->key[len2 - 3], 1)) >= 0) {
4389 8 *lang = l;
4390 8 return t;
4391 }
4392 }
4393 44 return t;
4394 }
4395
4396 3544 static int mov_write_string_metadata(AVFormatContext *s, AVIOContext *pb,
4397 const char *name, const char *tag,
4398 int long_style)
4399 {
4400 int lang;
4401 3544 AVDictionaryEntry *t = get_metadata_lang(s, tag, &lang);
4402
2/2
✓ Branch 0 taken 3492 times.
✓ Branch 1 taken 52 times.
3544 if (!t)
4403 3492 return 0;
4404 52 return mov_write_string_tag(pb, name, t->value, lang, long_style);
4405 }
4406
4407 /* iTunes bpm number */
4408 81 static int mov_write_tmpo_tag(AVIOContext *pb, AVFormatContext *s)
4409 {
4410 81 AVDictionaryEntry *t = av_dict_get(s->metadata, "tmpo", NULL, 0);
4411
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 81 times.
81 int size = 0, tmpo = t ? atoi(t->value) : 0;
4412
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 81 times.
81 if (tmpo) {
4413 size = 26;
4414 avio_wb32(pb, size);
4415 ffio_wfourcc(pb, "tmpo");
4416 avio_wb32(pb, size-8); /* size */
4417 ffio_wfourcc(pb, "data");
4418 avio_wb32(pb, 0x15); //type specifier
4419 avio_wb32(pb, 0);
4420 avio_wb16(pb, tmpo); // data
4421 }
4422 81 return size;
4423 }
4424
4425 /* 3GPP TS 26.244 */
4426 81 static int mov_write_loci_tag(AVFormatContext *s, AVIOContext *pb)
4427 {
4428 int lang;
4429 81 int64_t pos = avio_tell(pb);
4430 double latitude, longitude, altitude;
4431 int32_t latitude_fix, longitude_fix, altitude_fix;
4432 81 AVDictionaryEntry *t = get_metadata_lang(s, "location", &lang);
4433 81 const char *ptr, *place = "";
4434 char *end;
4435 static const char *astronomical_body = "earth";
4436
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 if (!t)
4437 81 return 0;
4438
4439 ptr = t->value;
4440 latitude = strtod(ptr, &end);
4441 if (end == ptr) {
4442 av_log(s, AV_LOG_WARNING, "malformed location metadata\n");
4443 return 0;
4444 }
4445 ptr = end;
4446 longitude = strtod(ptr, &end);
4447 if (end == ptr) {
4448 av_log(s, AV_LOG_WARNING, "malformed location metadata\n");
4449 return 0;
4450 }
4451 ptr = end;
4452 altitude = strtod(ptr, &end);
4453 /* If no altitude was present, the default 0 should be fine */
4454 if (*end == '/')
4455 place = end + 1;
4456
4457 latitude_fix = (int32_t) ((1 << 16) * latitude);
4458 longitude_fix = (int32_t) ((1 << 16) * longitude);
4459 altitude_fix = (int32_t) ((1 << 16) * altitude);
4460
4461 avio_wb32(pb, 0); /* size */
4462 ffio_wfourcc(pb, "loci"); /* type */
4463 avio_wb32(pb, 0); /* version + flags */
4464 avio_wb16(pb, lang);
4465 avio_write(pb, place, strlen(place) + 1);
4466 avio_w8(pb, 0); /* role of place (0 == shooting location, 1 == real location, 2 == fictional location) */
4467 avio_wb32(pb, longitude_fix);
4468 avio_wb32(pb, latitude_fix);
4469 avio_wb32(pb, altitude_fix);
4470 avio_write(pb, astronomical_body, strlen(astronomical_body) + 1);
4471 avio_w8(pb, 0); /* additional notes, null terminated string */
4472
4473 return update_size(pb, pos);
4474 }
4475
4476 /* iTunes track or disc number */
4477 162 static int mov_write_trkn_tag(AVIOContext *pb, MOVMuxContext *mov,
4478 AVFormatContext *s, int disc)
4479 {
4480
2/2
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 81 times.
162 AVDictionaryEntry *t = av_dict_get(s->metadata,
4481 disc ? "disc" : "track",
4482 NULL, 0);
4483
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 160 times.
162 int size = 0, track = t ? atoi(t->value) : 0;
4484
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 160 times.
162 if (track) {
4485 2 int tracks = 0;
4486 2 char *slash = strchr(t->value, '/');
4487
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (slash)
4488 2 tracks = atoi(slash + 1);
4489 2 avio_wb32(pb, 32); /* size */
4490
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 ffio_wfourcc(pb, disc ? "disk" : "trkn");
4491 2 avio_wb32(pb, 24); /* size */
4492 2 ffio_wfourcc(pb, "data");
4493 2 avio_wb32(pb, 0); // 8 bytes empty
4494 2 avio_wb32(pb, 0);
4495 2 avio_wb16(pb, 0); // empty
4496 2 avio_wb16(pb, track); // track / disc number
4497 2 avio_wb16(pb, tracks); // total track / disc number
4498 2 avio_wb16(pb, 0); // empty
4499 2 size = 32;
4500 }
4501 162 return size;
4502 }
4503
4504 486 static int mov_write_int8_metadata(AVFormatContext *s, AVIOContext *pb,
4505 const char *name, const char *tag,
4506 int len)
4507 {
4508 486 AVDictionaryEntry *t = NULL;
4509 uint8_t num;
4510 486 int size = 24 + len;
4511
4512
3/4
✓ Branch 0 taken 162 times.
✓ Branch 1 taken 324 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 162 times.
486 if (len != 1 && len != 4)
4513 return -1;
4514
4515
2/2
✓ Branch 1 taken 484 times.
✓ Branch 2 taken 2 times.
486 if (!(t = av_dict_get(s->metadata, tag, NULL, 0)))
4516 484 return 0;
4517 2 num = atoi(t->value);
4518
4519 2 avio_wb32(pb, size);
4520 2 ffio_wfourcc(pb, name);
4521 2 avio_wb32(pb, size - 8);
4522 2 ffio_wfourcc(pb, "data");
4523 2 avio_wb32(pb, 0x15);
4524 2 avio_wb32(pb, 0);
4525
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (len==4) avio_wb32(pb, num);
4526 2 else avio_w8 (pb, num);
4527
4528 2 return size;
4529 }
4530
4531 81 static int mov_write_covr(AVIOContext *pb, AVFormatContext *s)
4532 {
4533 81 MOVMuxContext *mov = s->priv_data;
4534 81 int64_t pos = 0;
4535
4536
2/2
✓ Branch 0 taken 136 times.
✓ Branch 1 taken 81 times.
217 for (int i = 0; i < mov->nb_streams; i++) {
4537 136 MOVTrack *trk = &mov->tracks[i];
4538
4539
3/4
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 134 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
136 if (!is_cover_image(trk->st) || trk->cover_image->size <= 0)
4540 134 continue;
4541
4542
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (!pos) {
4543 1 pos = avio_tell(pb);
4544 1 avio_wb32(pb, 0);
4545 1 ffio_wfourcc(pb, "covr");
4546 }
4547 2 avio_wb32(pb, 16 + trk->cover_image->size);
4548 2 ffio_wfourcc(pb, "data");
4549 2 avio_wb32(pb, trk->tag);
4550 2 avio_wb32(pb , 0);
4551 2 avio_write(pb, trk->cover_image->data, trk->cover_image->size);
4552 }
4553
4554
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 80 times.
81 return pos ? update_size(pb, pos) : 0;
4555 }
4556
4557 /* iTunes meta data list */
4558 81 static int mov_write_ilst_tag(AVIOContext *pb, MOVMuxContext *mov,
4559 AVFormatContext *s)
4560 {
4561 81 int64_t pos = avio_tell(pb);
4562 81 avio_wb32(pb, 0); /* size */
4563 81 ffio_wfourcc(pb, "ilst");
4564 81 mov_write_string_metadata(s, pb, "\251nam", "title" , 1);
4565 81 mov_write_string_metadata(s, pb, "\251ART", "artist" , 1);
4566 81 mov_write_string_metadata(s, pb, "aART", "album_artist", 1);
4567 81 mov_write_string_metadata(s, pb, "\251wrt", "composer" , 1);
4568 81 mov_write_string_metadata(s, pb, "\251alb", "album" , 1);
4569 81 mov_write_string_metadata(s, pb, "\251day", "date" , 1);
4570
1/2
✓ Branch 1 taken 81 times.
✗ Branch 2 not taken.
81 if (!mov_write_string_metadata(s, pb, "\251too", "encoding_tool", 1)) {
4571
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 79 times.
81 if (!(s->flags & AVFMT_FLAG_BITEXACT))
4572 2 mov_write_string_tag(pb, "\251too", LIBAVFORMAT_IDENT, 0, 1);
4573 }
4574 81 mov_write_string_metadata(s, pb, "\251cmt", "comment" , 1);
4575 81 mov_write_string_metadata(s, pb, "\251gen", "genre" , 1);
4576 81 mov_write_string_metadata(s, pb, "cprt", "copyright", 1);
4577 81 mov_write_string_metadata(s, pb, "\251grp", "grouping" , 1);
4578 81 mov_write_string_metadata(s, pb, "\251lyr", "lyrics" , 1);
4579 81 mov_write_string_metadata(s, pb, "desc", "description",1);
4580 81 mov_write_string_metadata(s, pb, "ldes", "synopsis" , 1);
4581 81 mov_write_string_metadata(s, pb, "tvsh", "show" , 1);
4582 81 mov_write_string_metadata(s, pb, "tven", "episode_id",1);
4583 81 mov_write_string_metadata(s, pb, "tvnn", "network" , 1);
4584 81 mov_write_string_metadata(s, pb, "keyw", "keywords" , 1);
4585 81 mov_write_int8_metadata (s, pb, "tves", "episode_sort",4);
4586 81 mov_write_int8_metadata (s, pb, "tvsn", "season_number",4);
4587 81 mov_write_int8_metadata (s, pb, "stik", "media_type",1);
4588 81 mov_write_int8_metadata (s, pb, "hdvd", "hd_video", 1);
4589 81 mov_write_int8_metadata (s, pb, "pgap", "gapless_playback",1);
4590 81 mov_write_int8_metadata (s, pb, "cpil", "compilation", 1);
4591 81 mov_write_covr(pb, s);
4592 81 mov_write_trkn_tag(pb, mov, s, 0); // track number
4593 81 mov_write_trkn_tag(pb, mov, s, 1); // disc number
4594 81 mov_write_tmpo_tag(pb, s);
4595 81 return update_size(pb, pos);
4596 }
4597
4598 static int mov_write_mdta_hdlr_tag(AVIOContext *pb, MOVMuxContext *mov,
4599 AVFormatContext *s)
4600 {
4601 avio_wb32(pb, 33); /* size */
4602 ffio_wfourcc(pb, "hdlr");
4603 avio_wb32(pb, 0);
4604 avio_wb32(pb, 0);
4605 ffio_wfourcc(pb, "mdta");
4606 avio_wb32(pb, 0);
4607 avio_wb32(pb, 0);
4608 avio_wb32(pb, 0);
4609 avio_w8(pb, 0);
4610 return 33;
4611 }
4612
4613 static int mov_write_mdta_keys_tag(AVIOContext *pb, MOVMuxContext *mov,
4614 AVFormatContext *s)
4615 {
4616 const AVDictionaryEntry *t = NULL;
4617 int64_t pos = avio_tell(pb);
4618 int64_t curpos, entry_pos;
4619 int count = 0;
4620
4621 avio_wb32(pb, 0); /* size */
4622 ffio_wfourcc(pb, "keys");
4623 avio_wb32(pb, 0);
4624 entry_pos = avio_tell(pb);
4625 avio_wb32(pb, 0); /* entry count */
4626
4627 while (t = av_dict_iterate(s->metadata, t)) {
4628 size_t key_len = strlen(t->key);
4629 avio_wb32(pb, key_len + 8);
4630 ffio_wfourcc(pb, "mdta");
4631 avio_write(pb, t->key, key_len);
4632 count += 1;
4633 }
4634 curpos = avio_tell(pb);
4635 avio_seek(pb, entry_pos, SEEK_SET);
4636 avio_wb32(pb, count); // rewrite entry count
4637 avio_seek(pb, curpos, SEEK_SET);
4638
4639 return update_size(pb, pos);
4640 }
4641
4642 static int mov_write_mdta_ilst_tag(AVIOContext *pb, MOVMuxContext *mov,
4643 AVFormatContext *s)
4644 {
4645 const AVDictionaryEntry *t = NULL;
4646 int64_t pos = avio_tell(pb);
4647 int count = 1; /* keys are 1-index based */
4648
4649 avio_wb32(pb, 0); /* size */
4650 ffio_wfourcc(pb, "ilst");
4651
4652 while (t = av_dict_iterate(s->metadata, t)) {
4653 int64_t entry_pos = avio_tell(pb);
4654 avio_wb32(pb, 0); /* size */
4655 avio_wb32(pb, count); /* key */
4656 mov_write_string_data_tag(pb, t->value, 0, 1);
4657 update_size(pb, entry_pos);
4658 count += 1;
4659 }
4660 return update_size(pb, pos);
4661 }
4662
4663 /* meta data tags */
4664 81 static int mov_write_meta_tag(AVIOContext *pb, MOVMuxContext *mov,
4665 AVFormatContext *s)
4666 {
4667 81 int size = 0;
4668 81 int64_t pos = avio_tell(pb);
4669 81 avio_wb32(pb, 0); /* size */
4670 81 ffio_wfourcc(pb, "meta");
4671 81 avio_wb32(pb, 0);
4672
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 81 times.
81 if (mov->flags & FF_MOV_FLAG_USE_MDTA) {
4673 mov_write_mdta_hdlr_tag(pb, mov, s);
4674 mov_write_mdta_keys_tag(pb, mov, s);
4675 mov_write_mdta_ilst_tag(pb, mov, s);
4676
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 81 times.
81 } else if (mov->mode == MODE_AVIF) {
4677 mov_write_hdlr_tag(s, pb, &mov->tracks[0]);
4678 // We always write the primary item id as 1 since only one track is
4679 // supported for AVIF.
4680 mov_write_pitm_tag(pb, 1);
4681 mov_write_iloc_tag(pb, mov, s);
4682 mov_write_iinf_tag(pb, mov, s);
4683 if (mov->nb_streams > 1)
4684 mov_write_iref_tag(pb, mov, s);
4685 mov_write_iprp_tag(pb, mov, s);
4686 } else {
4687 /* iTunes metadata tag */
4688 81 mov_write_itunes_hdlr_tag(pb, mov, s);
4689 81 mov_write_ilst_tag(pb, mov, s);
4690 }
4691 81 size = update_size(pb, pos);
4692 81 return size;
4693 }
4694
4695 149 static int mov_write_raw_metadata_tag(AVFormatContext *s, AVIOContext *pb,
4696 const char *name, const char *key)
4697 {
4698 int len;
4699 AVDictionaryEntry *t;
4700
4701
1/2
✓ Branch 1 taken 149 times.
✗ Branch 2 not taken.
149 if (!(t = av_dict_get(s->metadata, key, NULL, 0)))
4702 149 return 0;
4703
4704 len = strlen(t->value);
4705 if (len > 0) {
4706 int size = len + 8;
4707 avio_wb32(pb, size);
4708 ffio_wfourcc(pb, name);
4709 avio_write(pb, t->value, len);
4710 return size;
4711 }
4712 return 0;
4713 }
4714
4715 static int ascii_to_wc(AVIOContext *pb, const uint8_t *b)
4716 {
4717 int val;
4718 while (*b) {
4719 GET_UTF8(val, *b++, return -1;)
4720 avio_wb16(pb, val);
4721 }
4722 avio_wb16(pb, 0x00);
4723 return 0;
4724 }
4725
4726 static uint16_t language_code(const char *str)
4727 {
4728 return (((str[0] - 0x60) & 0x1F) << 10) +
4729 (((str[1] - 0x60) & 0x1F) << 5) +
4730 (( str[2] - 0x60) & 0x1F);
4731 }
4732
4733 static int mov_write_3gp_udta_tag(AVIOContext *pb, AVFormatContext *s,
4734 const char *tag, const char *str)
4735 {
4736 int64_t pos = avio_tell(pb);
4737 AVDictionaryEntry *t = av_dict_get(s->metadata, str, NULL, 0);
4738 if (!t || !utf8len(t->value))
4739 return 0;
4740 avio_wb32(pb, 0); /* size */
4741 ffio_wfourcc(pb, tag); /* type */
4742 avio_wb32(pb, 0); /* version + flags */
4743 if (!strcmp(tag, "yrrc"))
4744 avio_wb16(pb, atoi(t->value));
4745 else {
4746 avio_wb16(pb, language_code("eng")); /* language */
4747 avio_write(pb, t->value, strlen(t->value) + 1); /* UTF8 string value */
4748 if (!strcmp(tag, "albm") &&
4749 (t = av_dict_get(s->metadata, "track", NULL, 0)))
4750 avio_w8(pb, atoi(t->value));
4751 }
4752 return update_size(pb, pos);
4753 }
4754
4755 1 static int mov_write_chpl_tag(AVIOContext *pb, AVFormatContext *s)
4756 {
4757 1 int64_t pos = avio_tell(pb);
4758 1 int i, nb_chapters = FFMIN(s->nb_chapters, 255);
4759
4760 1 avio_wb32(pb, 0); // size
4761 1 ffio_wfourcc(pb, "chpl");
4762 1 avio_wb32(pb, 0x01000000); // version + flags
4763 1 avio_wb32(pb, 0); // unknown
4764 1 avio_w8(pb, nb_chapters);
4765
4766
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
5 for (i = 0; i < nb_chapters; i++) {
4767 4 AVChapter *c = s->chapters[i];
4768 AVDictionaryEntry *t;
4769 4 avio_wb64(pb, av_rescale_q(c->start, c->time_base, (AVRational){1,10000000}));
4770
4771
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 if ((t = av_dict_get(c->metadata, "title", NULL, 0))) {
4772
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 int len = FFMIN(strlen(t->value), 255);
4773 4 avio_w8(pb, len);
4774 4 avio_write(pb, t->value, len);
4775 } else
4776 avio_w8(pb, 0);
4777 }
4778 1 return update_size(pb, pos);
4779 }
4780
4781 230 static int mov_write_udta_tag(AVIOContext *pb, MOVMuxContext *mov,
4782 AVFormatContext *s)
4783 {
4784 AVIOContext *pb_buf;
4785 int ret, size;
4786 uint8_t *buf;
4787
4788 230 ret = avio_open_dyn_buf(&pb_buf);
4789
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 230 times.
230 if (ret < 0)
4790 return ret;
4791
4792
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 230 times.
230 if (mov->mode & MODE_3GP) {
4793 mov_write_3gp_udta_tag(pb_buf, s, "perf", "artist");
4794 mov_write_3gp_udta_tag(pb_buf, s, "titl", "title");
4795 mov_write_3gp_udta_tag(pb_buf, s, "auth", "author");
4796 mov_write_3gp_udta_tag(pb_buf, s, "gnre", "genre");
4797 mov_write_3gp_udta_tag(pb_buf, s, "dscp", "comment");
4798 mov_write_3gp_udta_tag(pb_buf, s, "albm", "album");
4799 mov_write_3gp_udta_tag(pb_buf, s, "cprt", "copyright");
4800 mov_write_3gp_udta_tag(pb_buf, s, "yrrc", "date");
4801 mov_write_loci_tag(s, pb_buf);
4802
3/4
✓ Branch 0 taken 149 times.
✓ Branch 1 taken 81 times.
✓ Branch 2 taken 149 times.
✗ Branch 3 not taken.
230 } 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
4803 149 mov_write_string_metadata(s, pb_buf, "\251ART", "artist", 0);
4804 149 mov_write_string_metadata(s, pb_buf, "\251nam", "title", 0);
4805 149 mov_write_string_metadata(s, pb_buf, "\251aut", "author", 0);
4806 149 mov_write_string_metadata(s, pb_buf, "\251alb", "album", 0);
4807 149 mov_write_string_metadata(s, pb_buf, "\251day", "date", 0);
4808 149 mov_write_string_metadata(s, pb_buf, "\251swr", "encoder", 0);
4809 // currently ignored by mov.c
4810 149 mov_write_string_metadata(s, pb_buf, "\251des", "comment", 0);
4811 // add support for libquicktime, this atom is also actually read by mov.c
4812 149 mov_write_string_metadata(s, pb_buf, "\251cmt", "comment", 0);
4813 149 mov_write_string_metadata(s, pb_buf, "\251gen", "genre", 0);
4814 149 mov_write_string_metadata(s, pb_buf, "\251cpy", "copyright", 0);
4815 149 mov_write_string_metadata(s, pb_buf, "\251mak", "make", 0);
4816 149 mov_write_string_metadata(s, pb_buf, "\251mod", "model", 0);
4817 149 mov_write_string_metadata(s, pb_buf, "\251xyz", "location", 0);
4818 149 mov_write_string_metadata(s, pb_buf, "\251key", "keywords", 0);
4819 149 mov_write_raw_metadata_tag(s, pb_buf, "XMP_", "xmp");
4820 } else {
4821 /* iTunes meta data */
4822 81 mov_write_meta_tag(pb_buf, mov, s);
4823 81 mov_write_loci_tag(s, pb_buf);
4824 }
4825
4826
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 229 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
230 if (s->nb_chapters && !(mov->flags & FF_MOV_FLAG_DISABLE_CHPL))
4827 1 mov_write_chpl_tag(pb_buf, s);
4828
4829
2/2
✓ Branch 1 taken 109 times.
✓ Branch 2 taken 121 times.
230 if ((size = avio_get_dyn_buf(pb_buf, &buf)) > 0) {
4830 109 avio_wb32(pb, size + 8);
4831 109 ffio_wfourcc(pb, "udta");
4832 109 avio_write(pb, buf, size);
4833 }
4834 230 ffio_free_dyn_buf(&pb_buf);
4835
4836 230 return 0;
4837 }
4838
4839 static void mov_write_psp_udta_tag(AVIOContext *pb,
4840 const char *str, const char *lang, int type)
4841 {
4842 int len = utf8len(str) + 1;
4843 if (len <= 0)
4844 return;
4845 avio_wb16(pb, len * 2 + 10); /* size */
4846 avio_wb32(pb, type); /* type */
4847 avio_wb16(pb, language_code(lang)); /* language */
4848 avio_wb16(pb, 0x01); /* ? */
4849 ascii_to_wc(pb, str);
4850 }
4851
4852 1 static int mov_write_uuidusmt_tag(AVIOContext *pb, AVFormatContext *s)
4853 {
4854 1 AVDictionaryEntry *title = av_dict_get(s->metadata, "title", NULL, 0);
4855 int64_t pos, pos2;
4856
4857
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (title) {
4858 pos = avio_tell(pb);
4859 avio_wb32(pb, 0); /* size placeholder*/
4860 ffio_wfourcc(pb, "uuid");
4861 ffio_wfourcc(pb, "USMT");
4862 avio_wb32(pb, 0x21d24fce); /* 96 bit UUID */
4863 avio_wb32(pb, 0xbb88695c);
4864 avio_wb32(pb, 0xfac9c740);
4865
4866 pos2 = avio_tell(pb);
4867 avio_wb32(pb, 0); /* size placeholder*/
4868 ffio_wfourcc(pb, "MTDT");
4869 avio_wb16(pb, 4);
4870
4871 // ?
4872 avio_wb16(pb, 0x0C); /* size */
4873 avio_wb32(pb, 0x0B); /* type */
4874 avio_wb16(pb, language_code("und")); /* language */
4875 avio_wb16(pb, 0x0); /* ? */
4876 avio_wb16(pb, 0x021C); /* data */
4877
4878 if (!(s->flags & AVFMT_FLAG_BITEXACT))
4879 mov_write_psp_udta_tag(pb, LIBAVFORMAT_IDENT, "eng", 0x04);
4880 mov_write_psp_udta_tag(pb, title->value, "eng", 0x01);
4881 mov_write_psp_udta_tag(pb, "2006/04/01 11:11:11", "und", 0x03);
4882
4883 update_size(pb, pos2);
4884 return update_size(pb, pos);
4885 }
4886
4887 1 return 0;
4888 }
4889
4890 299 static void build_chunks(MOVTrack *trk)
4891 {
4892 int i;
4893 299 MOVIentry *chunk = &trk->cluster[0];
4894 299 uint64_t chunkSize = chunk->size;
4895 299 chunk->chunkNum = 1;
4896
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 244 times.
299 if (trk->chunkCount)
4897 55 return;
4898 244 trk->chunkCount = 1;
4899
2/2
✓ Branch 0 taken 14451 times.
✓ Branch 1 taken 244 times.
14695 for (i = 1; i<trk->entry; i++){
4900
2/2
✓ Branch 0 taken 12587 times.
✓ Branch 1 taken 1864 times.
14451 if (chunk->pos + chunkSize == trk->cluster[i].pos &&
4901
2/2
✓ Branch 0 taken 12014 times.
✓ Branch 1 taken 573 times.
12587 chunkSize + trk->cluster[i].size < (1<<20)){
4902 12014 chunkSize += trk->cluster[i].size;
4903 12014 chunk->samples_in_chunk += trk->cluster[i].entries;
4904 } else {
4905 2437 trk->cluster[i].chunkNum = chunk->chunkNum+1;
4906 2437 chunk=&trk->cluster[i];
4907 2437 chunkSize = chunk->size;
4908 2437 trk->chunkCount++;
4909 }
4910 }
4911 }
4912
4913 /**
4914 * Assign track ids. If option "use_stream_ids_as_track_ids" is set,
4915 * the stream ids are used as track ids.
4916 *
4917 * This assumes mov->tracks and s->streams are in the same order and
4918 * there are no gaps in either of them (so mov->tracks[n] refers to
4919 * s->streams[n]).
4920 *
4921 * As an exception, there can be more entries in
4922 * s->streams than in mov->tracks, in which case new track ids are
4923 * generated (starting after the largest found stream id).
4924 */
4925 231 static int mov_setup_track_ids(MOVMuxContext *mov, AVFormatContext *s)
4926 {
4927 int i;
4928
4929
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 203 times.
231 if (mov->track_ids_ok)
4930 28 return 0;
4931
4932
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 203 times.
203 if (mov->use_stream_ids_as_track_ids) {
4933 int next_generated_track_id = 0;
4934 for (i = 0; i < mov->nb_streams; i++) {
4935 AVStream *st = mov->tracks[i].st;
4936 if (st->id > next_generated_track_id)
4937 next_generated_track_id = st->id;
4938 }
4939
4940 for (i = 0; i < mov->nb_tracks; i++) {
4941 if (mov->tracks[i].entry <= 0 && !(mov->flags & FF_MOV_FLAG_FRAGMENT))
4942 continue;
4943
4944 mov->tracks[i].track_id = i >= mov->nb_streams ? ++next_generated_track_id : mov->tracks[i].st->id;
4945 }
4946 } else {
4947
2/2
✓ Branch 0 taken 268 times.
✓ Branch 1 taken 203 times.
471 for (i = 0; i < mov->nb_tracks; i++) {
4948
4/4
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 242 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 24 times.
268 if (mov->tracks[i].entry <= 0 && !(mov->flags & FF_MOV_FLAG_FRAGMENT))
4949 2 continue;
4950
4951 266 mov->tracks[i].track_id = i + 1;
4952 }
4953 }
4954
4955 203 mov->track_ids_ok = 1;
4956
4957 203 return 0;
4958 }
4959
4960 231 static int mov_write_moov_tag(AVIOContext *pb, MOVMuxContext *mov,
4961 AVFormatContext *s)
4962 {
4963 int i;
4964 231 int64_t pos = avio_tell(pb);
4965 231 avio_wb32(pb, 0); /* size placeholder*/
4966 231 ffio_wfourcc(pb, "moov");
4967
4968 231 mov_setup_track_ids(mov, s);
4969
4970
2/2
✓ Branch 0 taken 327 times.
✓ Branch 1 taken 231 times.
558 for (i = 0; i < mov->nb_tracks; i++) {
4971
4/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 299 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 26 times.
327 if (mov->tracks[i].entry <= 0 && !(mov->flags & FF_MOV_FLAG_FRAGMENT))
4972 2 continue;
4973
4974 325 mov->tracks[i].time = mov->time;
4975
4976
2/2
✓ Branch 0 taken 299 times.
✓ Branch 1 taken 26 times.
325 if (mov->tracks[i].entry)
4977 299 build_chunks(&mov->tracks[i]);
4978 }
4979
4980
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 230 times.
231 if (mov->chapter_track)
4981
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 for (i = 0; i < mov->nb_streams; i++) {
4982 1 mov->tracks[i].tref_tag = MKTAG('c','h','a','p');
4983 1 mov->tracks[i].tref_id = mov->tracks[mov->chapter_track].track_id;
4984 }
4985
2/2
✓ Branch 0 taken 327 times.
✓ Branch 1 taken 231 times.
558 for (i = 0; i < mov->nb_tracks; i++) {
4986 327 MOVTrack *track = &mov->tracks[i];
4987
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 325 times.
327 if (track->tag == MKTAG('r','t','p',' ')) {
4988 2 track->tref_tag = MKTAG('h','i','n','t');
4989 2 track->tref_id = mov->tracks[track->src_track].track_id;
4990
2/2
✓ Branch 0 taken 107 times.
✓ Branch 1 taken 218 times.
325 } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) {
4991 107 const AVPacketSideData *sd = av_packet_side_data_get(track->st->codecpar->coded_side_data,
4992 107 track->st->codecpar->nb_coded_side_data,
4993 AV_PKT_DATA_FALLBACK_TRACK );
4994
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 107 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
107 if (sd && sd->size == sizeof(int)) {
4995 int *fallback = (int *)sd->data;
4996 if (*fallback >= 0 && *fallback < mov->nb_tracks) {
4997 track->tref_tag = MKTAG('f','a','l','l');
4998 track->tref_id = mov->tracks[*fallback].track_id;
4999 }
5000 }
5001 }
5002 }
5003
2/2
✓ Branch 0 taken 327 times.
✓ Branch 1 taken 231 times.
558 for (i = 0; i < mov->nb_tracks; i++) {
5004
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 314 times.
327 if (mov->tracks[i].tag == MKTAG('t','m','c','d')) {
5005 13 int src_trk = mov->tracks[i].src_track;
5006 13 mov->tracks[src_trk].tref_tag = mov->tracks[i].tag;
5007 13 mov->tracks[src_trk].tref_id = mov->tracks[i].track_id;
5008 //src_trk may have a different timescale than the tmcd track
5009 13 mov->tracks[i].track_duration = av_rescale(mov->tracks[src_trk].track_duration,
5010 13 mov->tracks[i].timescale,
5011 13 mov->tracks[src_trk].timescale);
5012 }
5013 }
5014
5015 231 mov_write_mvhd_tag(pb, mov);
5016
4/6
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 149 times.
✓ Branch 2 taken 82 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 82 times.
231 if (mov->mode != MODE_MOV && mov->mode != MODE_AVIF && !mov->iods_skip)
5017 mov_write_iods_tag(pb, mov);
5018
2/2
✓ Branch 0 taken 327 times.
✓ Branch 1 taken 231 times.
558 for (i = 0; i < mov->nb_tracks; i++) {
5019
4/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 299 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 26 times.
327 if (mov->tracks[i].entry > 0 || mov->flags & FF_MOV_FLAG_FRAGMENT ||
5020
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 mov->mode == MODE_AVIF) {
5021
2/2
✓ Branch 0 taken 312 times.
✓ Branch 1 taken 13 times.
325 int ret = mov_write_trak_tag(s, pb, mov, &(mov->tracks[i]), i < mov->nb_streams ? mov->tracks[i].st : NULL);
5022
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 325 times.
325 if (ret < 0)
5023 return ret;
5024 }
5025 }
5026
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 175 times.
231 if (mov->flags & FF_MOV_FLAG_FRAGMENT)
5027 56 mov_write_mvex_tag(pb, mov); /* QuickTime requires trak to precede this */
5028
5029
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 230 times.
231 if (mov->mode == MODE_PSP)
5030 1 mov_write_uuidusmt_tag(pb, s);
5031
1/2
✓ Branch 0 taken 230 times.
✗ Branch 1 not taken.
230 else if (mov->mode != MODE_AVIF)
5032 230 mov_write_udta_tag(pb, mov, s);
5033
5034 231 return update_size(pb, pos);
5035 }
5036
5037 static void param_write_int(AVIOContext *pb, const char *name, int value)
5038 {
5039 avio_printf(pb, "<param name=\"%s\" value=\"%d\" valuetype=\"data\"/>\n", name, value);
5040 }
5041
5042 static void param_write_string(AVIOContext *pb, const char *name, const char *value)
5043 {
5044 avio_printf(pb, "<param name=\"%s\" value=\"%s\" valuetype=\"data\"/>\n", name, value);
5045 }
5046
5047 static void param_write_hex(AVIOContext *pb, const char *name, const uint8_t *value, int len)
5048 {
5049 char buf[150];
5050 len = FFMIN(sizeof(buf) / 2 - 1, len);
5051 ff_data_to_hex(buf, value, len, 0);
5052 avio_printf(pb, "<param name=\"%s\" value=\"%s\" valuetype=\"data\"/>\n", name, buf);
5053 }
5054
5055 static int mov_write_isml_manifest(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
5056 {
5057 int64_t pos = avio_tell(pb);
5058 int i;
5059
5060 static const AVUUID uuid = {
5061 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
5062 0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
5063 };
5064
5065 avio_wb32(pb, 0);
5066 ffio_wfourcc(pb, "uuid");
5067 avio_write(pb, uuid, AV_UUID_LEN);
5068 avio_wb32(pb, 0);
5069
5070 avio_printf(pb, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
5071 avio_printf(pb, "<smil xmlns=\"http://www.w3.org/2001/SMIL20/Language\">\n");
5072 avio_printf(pb, "<head>\n");
5073 if (!(mov->fc->flags & AVFMT_FLAG_BITEXACT))
5074 avio_printf(pb, "<meta name=\"creator\" content=\"%s\" />\n",
5075 LIBAVFORMAT_IDENT);
5076 avio_printf(pb, "</head>\n");
5077 avio_printf(pb, "<body>\n");
5078 avio_printf(pb, "<switch>\n");
5079
5080 mov_setup_track_ids(mov, s);
5081
5082 for (i = 0; i < mov->nb_tracks; i++) {
5083 MOVTrack *track = &mov->tracks[i];
5084 struct mpeg4_bit_rate_values bit_rates =
5085 calculate_mpeg4_bit_rates(track);
5086 const char *type;
5087 int track_id = track->track_id;
5088 char track_name_buf[32] = { 0 };
5089
5090 AVStream *st = track->st;
5091 AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL,0);
5092
5093 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO && !is_cover_image(st)) {
5094 type = "video";
5095 } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) {
5096 type = "audio";
5097 } else {
5098 continue;
5099 }
5100
5101 avio_printf(pb, "<%s systemBitrate=\"%"PRIu32"\">\n", type,
5102 bit_rates.avg_bit_rate);
5103 param_write_int(pb, "systemBitrate", bit_rates.avg_bit_rate);
5104 param_write_int(pb, "trackID", track_id);
5105 param_write_string(pb, "systemLanguage", lang ? lang->value : "und");
5106
5107 /* Build track name piece by piece: */
5108 /* 1. track type */
5109 av_strlcat(track_name_buf, type, sizeof(track_name_buf));
5110 /* 2. track language, if available */
5111 if (lang)
5112 av_strlcatf(track_name_buf, sizeof(track_name_buf),
5113 "_%s", lang->value);
5114 /* 3. special type suffix */
5115 /* "_cc" = closed captions, "_ad" = audio_description */
5116 if (st->disposition & AV_DISPOSITION_HEARING_IMPAIRED)
5117 av_strlcat(track_name_buf, "_cc", sizeof(track_name_buf));
5118 else if (st->disposition & AV_DISPOSITION_VISUAL_IMPAIRED)
5119 av_strlcat(track_name_buf, "_ad", sizeof(track_name_buf));
5120
5121 param_write_string(pb, "trackName", track_name_buf);
5122
5123 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
5124 if (track->par->codec_id == AV_CODEC_ID_H264) {
5125 uint8_t *ptr;
5126 int size = track->par->extradata_size;
5127 if (!ff_avc_write_annexb_extradata(track->par->extradata, &ptr,
5128 &size)) {
5129 param_write_hex(pb, "CodecPrivateData",
5130 ptr ? ptr : track->par->extradata,
5131 size);
5132 av_free(ptr);
5133 }
5134 param_write_string(pb, "FourCC", "H264");
5135 } else if (track->par->codec_id == AV_CODEC_ID_VC1) {
5136 param_write_string(pb, "FourCC", "WVC1");
5137 param_write_hex(pb, "CodecPrivateData", track->par->extradata,
5138 track->par->extradata_size);
5139 }
5140 param_write_int(pb, "MaxWidth", track->par->width);
5141 param_write_int(pb, "MaxHeight", track->par->height);
5142 param_write_int(pb, "DisplayWidth", track->par->width);
5143 param_write_int(pb, "DisplayHeight", track->par->height);
5144 } else {
5145 if (track->par->codec_id == AV_CODEC_ID_AAC) {
5146 switch (track->par->profile) {
5147 case AV_PROFILE_AAC_HE_V2:
5148 param_write_string(pb, "FourCC", "AACP");
5149 break;
5150 case AV_PROFILE_AAC_HE:
5151 param_write_string(pb, "FourCC", "AACH");
5152 break;
5153 default:
5154 param_write_string(pb, "FourCC", "AACL");
5155 }
5156 } else if (track->par->codec_id == AV_CODEC_ID_WMAPRO) {
5157 param_write_string(pb, "FourCC", "WMAP");
5158 }
5159 param_write_hex(pb, "CodecPrivateData", track->par->extradata,
5160 track->par->extradata_size);
5161 param_write_int(pb, "AudioTag", ff_codec_get_tag(ff_codec_wav_tags,
5162 track->par->codec_id));
5163 param_write_int(pb, "Channels", track->par->ch_layout.nb_channels);
5164 param_write_int(pb, "SamplingRate", track->tag == MKTAG('i','a','m','f') ?
5165 0 : track->par->sample_rate);
5166 param_write_int(pb, "BitsPerSample", 16);
5167 param_write_int(pb, "PacketSize", track->par->block_align ?
5168 track->par->block_align : 4);
5169 }
5170 avio_printf(pb, "</%s>\n", type);
5171 }
5172 avio_printf(pb, "</switch>\n");
5173 avio_printf(pb, "</body>\n");
5174 avio_printf(pb, "</smil>\n");
5175
5176 return update_size(pb, pos);
5177 }
5178
5179 142 static int mov_write_mfhd_tag(AVIOContext *pb, MOVMuxContext *mov)
5180 {
5181 142 avio_wb32(pb, 16);
5182 142 ffio_wfourcc(pb, "mfhd");
5183 142 avio_wb32(pb, 0);
5184 142 avio_wb32(pb, mov->fragments);
5185 142 return 0;
5186 }
5187
5188 10742 static uint32_t get_sample_flags(MOVTrack *track, MOVIentry *entry)
5189 {
5190
2/2
✓ Branch 0 taken 7200 times.
✓ Branch 1 taken 3542 times.
10742 return entry->flags & MOV_SYNC_SAMPLE ? MOV_FRAG_SAMPLE_FLAG_DEPENDS_NO :
5191 (MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES | MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC);
5192 }
5193
5194 234 static int mov_write_tfhd_tag(AVIOContext *pb, MOVMuxContext *mov,
5195 MOVTrack *track, int64_t moof_offset)
5196 {
5197 234 int64_t pos = avio_tell(pb);
5198 234 uint32_t flags = MOV_TFHD_DEFAULT_SIZE | MOV_TFHD_DEFAULT_DURATION |
5199 MOV_TFHD_BASE_DATA_OFFSET;
5200
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 234 times.
234 if (!track->entry) {
5201 flags |= MOV_TFHD_DURATION_IS_EMPTY;
5202 } else {
5203 234 flags |= MOV_TFHD_DEFAULT_FLAGS;
5204 }
5205
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 234 times.
234 if (mov->flags & FF_MOV_FLAG_OMIT_TFHD_OFFSET)
5206 flags &= ~MOV_TFHD_BASE_DATA_OFFSET;
5207
2/2
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 156 times.
234 if (mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF) {
5208 78 flags &= ~MOV_TFHD_BASE_DATA_OFFSET;
5209 78 flags |= MOV_TFHD_DEFAULT_BASE_IS_MOOF;
5210 }
5211 /* CMAF requires all values to be explicit in tfhd atoms */
5212
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 226 times.
234 if (mov->flags & FF_MOV_FLAG_CMAF)
5213 8 flags |= MOV_TFHD_STSD_ID;
5214
5215 /* Don't set a default sample size, the silverlight player refuses
5216 * to play files with that set. Don't set a default sample duration,
5217 * WMP freaks out if it is set. Don't set a base data offset, PIFF
5218 * file format says it MUST NOT be set. */
5219
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 204 times.
234 if (track->mode == MODE_ISM)
5220 30 flags &= ~(MOV_TFHD_DEFAULT_SIZE | MOV_TFHD_DEFAULT_DURATION |
5221 MOV_TFHD_BASE_DATA_OFFSET | MOV_TFHD_STSD_ID);
5222
5223 234 avio_wb32(pb, 0); /* size placeholder */
5224 234 ffio_wfourcc(pb, "tfhd");
5225 234 avio_w8(pb, 0); /* version */
5226 234 avio_wb24(pb, flags);
5227
5228 234 avio_wb32(pb, track->track_id); /* track-id */
5229
2/2
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 108 times.
234 if (flags & MOV_TFHD_BASE_DATA_OFFSET)
5230 126 avio_wb64(pb, moof_offset);
5231
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 226 times.
234 if (flags & MOV_TFHD_STSD_ID) {
5232 8 avio_wb32(pb, 1);
5233 }
5234
2/2
✓ Branch 0 taken 204 times.
✓ Branch 1 taken 30 times.
234 if (flags & MOV_TFHD_DEFAULT_DURATION) {
5235 204 track->default_duration = get_cluster_duration(track, 0);
5236 204 avio_wb32(pb, track->default_duration);
5237 }
5238
2/2
✓ Branch 0 taken 204 times.
✓ Branch 1 taken 30 times.
234 if (flags & MOV_TFHD_DEFAULT_SIZE) {
5239
1/2
✓ Branch 0 taken 204 times.
✗ Branch 1 not taken.
204 track->default_size = track->entry ? track->cluster[0].size : 1;
5240 204 avio_wb32(pb, track->default_size);
5241 } else
5242 30 track->default_size = -1;
5243
5244
1/2
✓ Branch 0 taken 234 times.
✗ Branch 1 not taken.
234 if (flags & MOV_TFHD_DEFAULT_FLAGS) {
5245 /* Set the default flags based on the second sample, if available.
5246 * If the first sample is different, that can be signaled via a separate field. */
5247
2/2
✓ Branch 0 taken 224 times.
✓ Branch 1 taken 10 times.
234 if (track->entry > 1)
5248 224 track->default_sample_flags = get_sample_flags(track, &track->cluster[1]);
5249 else
5250 10 track->default_sample_flags =
5251 10 track->par->codec_type == AVMEDIA_TYPE_VIDEO ?
5252
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 4 times.
10 (MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES | MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC) :
5253 MOV_FRAG_SAMPLE_FLAG_DEPENDS_NO;
5254 234 avio_wb32(pb, track->default_sample_flags);
5255 }
5256
5257 234 return update_size(pb, pos);
5258 }
5259
5260 234 static int mov_write_trun_tag(AVIOContext *pb, MOVMuxContext *mov,
5261 MOVTrack *track, int moof_size,
5262 int first, int end)
5263 {
5264 234 int64_t pos = avio_tell(pb);
5265 234 uint32_t flags = MOV_TRUN_DATA_OFFSET;
5266 int i;
5267
5268
2/2
✓ Branch 0 taken 10044 times.
✓ Branch 1 taken 234 times.
10278 for (i = first; i < end; i++) {
5269
2/2
✓ Branch 1 taken 618 times.
✓ Branch 2 taken 9426 times.
10044 if (get_cluster_duration(track, i) != track->default_duration)
5270 618 flags |= MOV_TRUN_SAMPLE_DURATION;
5271
2/2
✓ Branch 0 taken 500 times.
✓ Branch 1 taken 9544 times.
10044 if (track->cluster[i].size != track->default_size)
5272 500 flags |= MOV_TRUN_SAMPLE_SIZE;
5273
4/4
✓ Branch 0 taken 9810 times.
✓ Branch 1 taken 234 times.
✓ Branch 3 taken 10 times.
✓ Branch 4 taken 9800 times.
10044 if (i > first && get_sample_flags(track, &track->cluster[i]) != track->default_sample_flags)
5274 10 flags |= MOV_TRUN_SAMPLE_FLAGS;
5275 }
5276
3/4
✓ Branch 0 taken 226 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 226 times.
✗ Branch 3 not taken.
234 if (!(flags & MOV_TRUN_SAMPLE_FLAGS) && track->entry > first &&
5277
2/2
✓ Branch 1 taken 110 times.
✓ Branch 2 taken 116 times.
226 get_sample_flags(track, &track->cluster[first]) != track->default_sample_flags)
5278 110 flags |= MOV_TRUN_FIRST_SAMPLE_FLAGS;
5279
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 166 times.
234 if (track->flags & MOV_TRACK_CTTS)
5280 68 flags |= MOV_TRUN_SAMPLE_CTS;
5281
5282 234 avio_wb32(pb, 0); /* size placeholder */
5283 234 ffio_wfourcc(pb, "trun");
5284
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 180 times.
234 if (mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS)
5285 54 avio_w8(pb, 1); /* version */
5286 else
5287 180 avio_w8(pb, 0); /* version */
5288 234 avio_wb24(pb, flags);
5289
5290 234 avio_wb32(pb, end - first); /* sample count */
5291
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 234 times.
234 if (mov->flags & FF_MOV_FLAG_OMIT_TFHD_OFFSET &&
5292 !(mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF) &&
5293 !mov->first_trun)
5294 avio_wb32(pb, 0); /* Later tracks follow immediately after the previous one */
5295 else
5296 234 avio_wb32(pb, moof_size + 8 + track->data_offset +
5297 234 track->cluster[first].pos); /* data offset */
5298
2/2
✓ Branch 0 taken 110 times.
✓ Branch 1 taken 124 times.
234 if (flags & MOV_TRUN_FIRST_SAMPLE_FLAGS)
5299 110 avio_wb32(pb, get_sample_flags(track, &track->cluster[first]));
5300
5301
2/2
✓ Branch 0 taken 10044 times.
✓ Branch 1 taken 234 times.
10278 for (i = first; i < end; i++) {
5302
2/2
✓ Branch 0 taken 722 times.
✓ Branch 1 taken 9322 times.
10044 if (flags & MOV_TRUN_SAMPLE_DURATION)
5303 722 avio_wb32(pb, get_cluster_duration(track, i));
5304
2/2
✓ Branch 0 taken 1064 times.
✓ Branch 1 taken 8980 times.
10044 if (flags & MOV_TRUN_SAMPLE_SIZE)
5305 1064 avio_wb32(pb, track->cluster[i].size);
5306
2/2
✓ Branch 0 taken 372 times.
✓ Branch 1 taken 9672 times.
10044 if (flags & MOV_TRUN_SAMPLE_FLAGS)
5307 372 avio_wb32(pb, get_sample_flags(track, &track->cluster[i]));
5308
2/2
✓ Branch 0 taken 1980 times.
✓ Branch 1 taken 8064 times.
10044 if (flags & MOV_TRUN_SAMPLE_CTS)
5309 1980 avio_wb32(pb, track->cluster[i].cts);
5310 }
5311
5312 234 mov->first_trun = 0;
5313 234 return update_size(pb, pos);
5314 }
5315
5316 30 static int mov_write_tfxd_tag(AVIOContext *pb, MOVTrack *track)
5317 {
5318 30 int64_t pos = avio_tell(pb);
5319 static const uint8_t uuid[] = {
5320 0x6d, 0x1d, 0x9b, 0x05, 0x42, 0xd5, 0x44, 0xe6,
5321 0x80, 0xe2, 0x14, 0x1d, 0xaf, 0xf7, 0x57, 0xb2
5322 };
5323
5324 30 avio_wb32(pb, 0); /* size placeholder */
5325 30 ffio_wfourcc(pb, "uuid");
5326 30 avio_write(pb, uuid, AV_UUID_LEN);
5327 30 avio_w8(pb, 1);
5328 30 avio_wb24(pb, 0);
5329 30 avio_wb64(pb, track->cluster[0].dts + track->cluster[0].cts);
5330 30 avio_wb64(pb, track->end_pts -
5331 30 (track->cluster[0].dts + track->cluster[0].cts));
5332
5333 30 return update_size(pb, pos);
5334 }
5335
5336 static int mov_write_tfrf_tag(AVIOContext *pb, MOVMuxContext *mov,
5337 MOVTrack *track, int entry)
5338 {
5339 int n = track->nb_frag_info - 1 - entry, i;
5340 int size = 8 + 16 + 4 + 1 + 16*n;
5341 static const uint8_t uuid[] = {
5342 0xd4, 0x80, 0x7e, 0xf2, 0xca, 0x39, 0x46, 0x95,
5343 0x8e, 0x54, 0x26, 0xcb, 0x9e, 0x46, 0xa7, 0x9f
5344 };
5345
5346 if (entry < 0)
5347 return 0;
5348
5349 avio_seek(pb, track->frag_info[entry].tfrf_offset, SEEK_SET);
5350 avio_wb32(pb, size);
5351 ffio_wfourcc(pb, "uuid");
5352 avio_write(pb, uuid, AV_UUID_LEN);
5353 avio_w8(pb, 1);
5354 avio_wb24(pb, 0);
5355 avio_w8(pb, n);
5356 for (i = 0; i < n; i++) {
5357 int index = entry + 1 + i;
5358 avio_wb64(pb, track->frag_info[index].time);
5359 avio_wb64(pb, track->frag_info[index].duration);
5360 }
5361 if (n < mov->ism_lookahead) {
5362 int free_size = 16 * (mov->ism_lookahead - n);
5363 avio_wb32(pb, free_size);
5364 ffio_wfourcc(pb, "free");
5365 ffio_fill(pb, 0, free_size - 8);
5366 }
5367
5368 return 0;
5369 }
5370
5371 117 static int mov_write_tfrf_tags(AVIOContext *pb, MOVMuxContext *mov,
5372 MOVTrack *track)
5373 {
5374 117 int64_t pos = avio_tell(pb);
5375 int i;
5376
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 117 times.
117 for (i = 0; i < mov->ism_lookahead; i++) {
5377 /* Update the tfrf tag for the last ism_lookahead fragments,
5378 * nb_frag_info - 1 is the next fragment to be written. */
5379 mov_write_tfrf_tag(pb, mov, track, track->nb_frag_info - 2 - i);
5380 }
5381 117 avio_seek(pb, pos, SEEK_SET);
5382 117 return 0;
5383 }
5384
5385 71 static int mov_add_tfra_entries(AVIOContext *pb, MOVMuxContext *mov, int tracks,
5386 int size)
5387 {
5388 int i;
5389
2/2
✓ Branch 0 taken 133 times.
✓ Branch 1 taken 71 times.
204 for (i = 0; i < mov->nb_tracks; i++) {
5390 133 MOVTrack *track = &mov->tracks[i];
5391 MOVFragmentInfo *info;
5392
6/6
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 106 times.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 117 times.
133 if ((tracks >= 0 && i != tracks) || !track->entry)
5393 16 continue;
5394 117 track->nb_frag_info++;
5395
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 54 times.
117 if (track->nb_frag_info >= track->frag_info_capacity) {
5396 63 unsigned new_capacity = track->nb_frag_info + MOV_FRAG_INFO_ALLOC_INCREMENT;
5397
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 63 times.
63 if (av_reallocp_array(&track->frag_info,
5398 new_capacity,
5399 sizeof(*track->frag_info)))
5400 return AVERROR(ENOMEM);
5401 63 track->frag_info_capacity = new_capacity;
5402 }
5403 117 info = &track->frag_info[track->nb_frag_info - 1];
5404 117 info->offset = avio_tell(pb);
5405 117 info->size = size;
5406 // Try to recreate the original pts for the first packet
5407 // from the fields we have stored
5408 117 info->time = track->cluster[0].dts + track->cluster[0].cts;
5409 117 info->duration = track->end_pts -
5410 117 (track->cluster[0].dts + track->cluster[0].cts);
5411 // If the pts is less than zero, we will have trimmed
5412 // away parts of the media track using an edit list,
5413 // and the corresponding start presentation time is zero.
5414
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 109 times.
117 if (info->time < 0) {
5415 8 info->duration += info->time;
5416 8 info->time = 0;
5417 }
5418 117 info->tfrf_offset = 0;
5419 117 mov_write_tfrf_tags(pb, mov, track);
5420 }
5421 71 return 0;
5422 }
5423
5424 static void mov_prune_frag_info(MOVMuxContext *mov, int tracks, int max)
5425 {
5426 int i;
5427 for (i = 0; i < mov->nb_tracks; i++) {
5428 MOVTrack *track = &mov->tracks[i];
5429 if ((tracks >= 0 && i != tracks) || !track->entry)
5430 continue;
5431 if (track->nb_frag_info > max) {
5432 memmove(track->frag_info, track->frag_info + (track->nb_frag_info - max), max * sizeof(*track->frag_info));
5433 track->nb_frag_info = max;
5434 }
5435 }
5436 }
5437
5438 204 static int mov_write_tfdt_tag(AVIOContext *pb, MOVTrack *track)
5439 {
5440 204 int64_t pos = avio_tell(pb);
5441
5442 204 avio_wb32(pb, 0); /* size */
5443 204 ffio_wfourcc(pb, "tfdt");
5444 204 avio_w8(pb, 1); /* version */
5445 204 avio_wb24(pb, 0);
5446 204 avio_wb64(pb, track->cluster[0].dts - track->start_dts);
5447 204 return update_size(pb, pos);
5448 }
5449
5450 234 static int mov_write_traf_tag(AVIOContext *pb, MOVMuxContext *mov,
5451 MOVTrack *track, int64_t moof_offset,
5452 int moof_size)
5453 {
5454 234 int64_t pos = avio_tell(pb);
5455 234 int i, start = 0;
5456 234 avio_wb32(pb, 0); /* size placeholder */
5457 234 ffio_wfourcc(pb, "traf");
5458
5459 234 mov_write_tfhd_tag(pb, mov, track, moof_offset);
5460
2/2
✓ Branch 0 taken 204 times.
✓ Branch 1 taken 30 times.
234 if (mov->mode != MODE_ISM)
5461 204 mov_write_tfdt_tag(pb, track);
5462
2/2
✓ Branch 0 taken 9810 times.
✓ Branch 1 taken 234 times.
10044 for (i = 1; i < track->entry; i++) {
5463
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9810 times.
9810 if (track->cluster[i].pos != track->cluster[i - 1].pos + track->cluster[i - 1].size) {
5464 mov_write_trun_tag(pb, mov, track, moof_size, start, i);
5465 start = i;
5466 }
5467 }
5468 234 mov_write_trun_tag(pb, mov, track, moof_size, start, track->entry);
5469
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 204 times.
234 if (mov->mode == MODE_ISM) {
5470 30 mov_write_tfxd_tag(pb, track);
5471
5472
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (mov->ism_lookahead) {
5473 int size = 16 + 4 + 1 + 16 * mov->ism_lookahead;
5474
5475 if (track->nb_frag_info > 0) {
5476 MOVFragmentInfo *info = &track->frag_info[track->nb_frag_info - 1];
5477 if (!info->tfrf_offset)
5478 info->tfrf_offset = avio_tell(pb);
5479 }
5480 avio_wb32(pb, 8 + size);
5481 ffio_wfourcc(pb, "free");
5482 ffio_fill(pb, 0, size);
5483 }
5484 }
5485
5486 234 return update_size(pb, pos);
5487 }
5488
5489 142 static int mov_write_moof_tag_internal(AVIOContext *pb, MOVMuxContext *mov,
5490 int tracks, int moof_size)
5491 {
5492 142 int64_t pos = avio_tell(pb);
5493 int i;
5494
5495 142 avio_wb32(pb, 0); /* size placeholder */
5496 142 ffio_wfourcc(pb, "moof");
5497 142 mov->first_trun = 1;
5498
5499 142 mov_write_mfhd_tag(pb, mov);
5500
2/2
✓ Branch 0 taken 266 times.
✓ Branch 1 taken 142 times.
408 for (i = 0; i < mov->nb_tracks; i++) {
5501 266 MOVTrack *track = &mov->tracks[i];
5502
4/4
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 212 times.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 30 times.
266 if (tracks >= 0 && i != tracks)
5503 24 continue;
5504
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 234 times.
242 if (!track->entry)
5505 8 continue;
5506 234 mov_write_traf_tag(pb, mov, track, pos, moof_size);
5507 }
5508
5509 142 return update_size(pb, pos);
5510 }
5511
5512 70 static int mov_write_sidx_tag(AVIOContext *pb,
5513 MOVTrack *track, int ref_size, int total_sidx_size)
5514 {
5515 70 int64_t pos = avio_tell(pb), offset_pos, end_pos;
5516 int64_t presentation_time, duration, offset;
5517 unsigned starts_with_SAP;
5518 int i, entries;
5519
5520
1/2
✓ Branch 0 taken 70 times.
✗ Branch 1 not taken.
70 if (track->entry) {
5521 70 entries = 1;
5522 70 presentation_time = track->cluster[0].dts + track->cluster[0].cts -
5523 70 track->start_dts - track->start_cts;
5524 70 duration = track->end_pts -
5525 70 (track->cluster[0].dts + track->cluster[0].cts);
5526 70 starts_with_SAP = track->cluster[0].flags & MOV_SYNC_SAMPLE;
5527
5528 // pts<0 should be cut away using edts
5529
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 70 times.
70 if (presentation_time < 0) {
5530 duration += presentation_time;
5531 presentation_time = 0;
5532 }
5533 } else {
5534 entries = track->nb_frag_info;
5535 if (entries <= 0)
5536 return 0;
5537 presentation_time = track->frag_info[0].time;
5538 /* presentation_time <= 0 is handled by mov_add_tfra_entries() */
5539 if (presentation_time > 0)
5540 presentation_time -= track->start_dts + track->start_cts;
5541 }
5542
5543 70 avio_wb32(pb, 0); /* size */
5544 70 ffio_wfourcc(pb, "sidx");
5545 70 avio_w8(pb, 1); /* version */
5546 70 avio_wb24(pb, 0);
5547 70 avio_wb32(pb, track->track_id); /* reference_ID */
5548 70 avio_wb32(pb, track->timescale); /* timescale */
5549 70 avio_wb64(pb, presentation_time); /* earliest_presentation_time */
5550 70 offset_pos = avio_tell(pb);
5551 70 avio_wb64(pb, 0); /* first_offset (offset to referenced moof) */
5552 70 avio_wb16(pb, 0); /* reserved */
5553
5554 70 avio_wb16(pb, entries); /* reference_count */
5555
2/2
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 70 times.
140 for (i = 0; i < entries; i++) {
5556
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 70 times.
70 if (!track->entry) {
5557 if (i > 1 && track->frag_info[i].offset != track->frag_info[i - 1].offset + track->frag_info[i - 1].size) {
5558 av_log(NULL, AV_LOG_ERROR, "Non-consecutive fragments, writing incorrect sidx\n");
5559 }
5560 duration = track->frag_info[i].duration;
5561 ref_size = track->frag_info[i].size;
5562 starts_with_SAP = 1;
5563 }
5564 70 avio_wb32(pb, (0 << 31) | (ref_size & 0x7fffffff)); /* reference_type (0 = media) | referenced_size */
5565 70 avio_wb32(pb, duration); /* subsegment_duration */
5566 70 avio_wb32(pb, (starts_with_SAP << 31) | (0 << 28) | 0); /* starts_with_SAP | SAP_type | SAP_delta_time */
5567 }
5568
5569 70 end_pos = avio_tell(pb);
5570 70 offset = pos + total_sidx_size - end_pos;
5571 70 avio_seek(pb, offset_pos, SEEK_SET);
5572 70 avio_wb64(pb, offset);
5573 70 avio_seek(pb, end_pos, SEEK_SET);
5574 70 return update_size(pb, pos);
5575 }
5576
5577 20 static int mov_write_sidx_tags(AVIOContext *pb, MOVMuxContext *mov,
5578 int tracks, int ref_size)
5579 {
5580 int i, round, ret;
5581 AVIOContext *avio_buf;
5582 20 int total_size = 0;
5583
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 20 times.
60 for (round = 0; round < 2; round++) {
5584 // First run one round to calculate the total size of all
5585 // sidx atoms.
5586 // This would be much simpler if we'd only write one sidx
5587 // atom, for the first track in the moof.
5588
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 20 times.
40 if (round == 0) {
5589
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
20 if ((ret = ffio_open_null_buf(&avio_buf)) < 0)
5590 return ret;
5591 } else {
5592 20 avio_buf = pb;
5593 }
5594
2/2
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 40 times.
110 for (i = 0; i < mov->nb_tracks; i++) {
5595 70 MOVTrack *track = &mov->tracks[i];
5596
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 70 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
70 if (tracks >= 0 && i != tracks)
5597 continue;
5598 // When writing a sidx for the full file, entry is 0, but
5599 // we want to include all tracks. ref_size is 0 in this case,
5600 // since we read it from frag_info instead.
5601
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 70 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
70 if (!track->entry && ref_size > 0)
5602 continue;
5603 70 total_size -= mov_write_sidx_tag(avio_buf, track, ref_size,
5604 total_size);
5605 }
5606
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 20 times.
40 if (round == 0)
5607 20 total_size = ffio_close_null_buf(avio_buf);
5608 }
5609 20 return 0;
5610 }
5611
5612 static int mov_write_prft_tag(AVIOContext *pb, MOVMuxContext *mov, int tracks)
5613 {
5614 int64_t pos = avio_tell(pb), pts_us, ntp_ts;
5615 MOVTrack *first_track;
5616 int flags = 24;
5617
5618 /* PRFT should be associated with at most one track. So, choosing only the
5619 * first track. */
5620 if (tracks > 0)
5621 return 0;
5622 first_track = &(mov->tracks[0]);
5623
5624 if (!first_track->entry) {
5625 av_log(mov->fc, AV_LOG_WARNING, "Unable to write PRFT, no entries in the track\n");
5626 return 0;
5627 }
5628
5629 if (first_track->cluster[0].pts == AV_NOPTS_VALUE) {
5630 av_log(mov->fc, AV_LOG_WARNING, "Unable to write PRFT, first PTS is invalid\n");
5631 return 0;
5632 }
5633
5634 if (mov->write_prft == MOV_PRFT_SRC_WALLCLOCK) {
5635 if (first_track->cluster[0].prft.wallclock) {
5636 /* Round the NTP time to whole milliseconds. */
5637 ntp_ts = ff_get_formatted_ntp_time((first_track->cluster[0].prft.wallclock / 1000) * 1000 +
5638 NTP_OFFSET_US);
5639 flags = first_track->cluster[0].prft.flags;
5640 } else
5641 ntp_ts = ff_get_formatted_ntp_time(ff_ntp_time());
5642 } else if (mov->write_prft == MOV_PRFT_SRC_PTS) {
5643 pts_us = av_rescale_q(first_track->cluster[0].pts,
5644 first_track->st->time_base, AV_TIME_BASE_Q);
5645 ntp_ts = ff_get_formatted_ntp_time(pts_us + NTP_OFFSET_US);
5646 } else {
5647 av_log(mov->fc, AV_LOG_WARNING, "Unsupported PRFT box configuration: %d\n",
5648 mov->write_prft);
5649 return 0;
5650 }
5651
5652 avio_wb32(pb, 0); // Size place holder
5653 ffio_wfourcc(pb, "prft"); // Type
5654 avio_w8(pb, 1); // Version
5655 avio_wb24(pb, flags); // Flags
5656 avio_wb32(pb, first_track->track_id); // reference track ID
5657 avio_wb64(pb, ntp_ts); // NTP time stamp
5658 avio_wb64(pb, first_track->cluster[0].pts); //media time
5659 return update_size(pb, pos);
5660 }
5661
5662 71 static int mov_write_moof_tag(AVIOContext *pb, MOVMuxContext *mov, int tracks,
5663 int64_t mdat_size)
5664 {
5665 AVIOContext *avio_buf;
5666 int ret, moof_size;
5667
5668
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 71 times.
71 if ((ret = ffio_open_null_buf(&avio_buf)) < 0)
5669 return ret;
5670 71 mov_write_moof_tag_internal(avio_buf, mov, tracks, 0);
5671 71 moof_size = ffio_close_null_buf(avio_buf);
5672
5673
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 51 times.
71 if (mov->flags & FF_MOV_FLAG_DASH &&
5674
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 !(mov->flags & (FF_MOV_FLAG_GLOBAL_SIDX | FF_MOV_FLAG_SKIP_SIDX)))
5675 20 mov_write_sidx_tags(pb, mov, tracks, moof_size + 8 + mdat_size);
5676
5677
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
71 if (mov->write_prft > MOV_PRFT_NONE && mov->write_prft < MOV_PRFT_NB)
5678 mov_write_prft_tag(pb, mov, tracks);
5679
5680
1/2
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
71 if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX ||
5681
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
71 !(mov->flags & FF_MOV_FLAG_SKIP_TRAILER) ||
5682 mov->ism_lookahead) {
5683
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 71 times.
71 if ((ret = mov_add_tfra_entries(pb, mov, tracks, moof_size + 8 + mdat_size)) < 0)
5684 return ret;
5685
1/2
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
71 if (!(mov->flags & FF_MOV_FLAG_GLOBAL_SIDX) &&
5686
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
71 mov->flags & FF_MOV_FLAG_SKIP_TRAILER) {
5687 mov_prune_frag_info(mov, tracks, mov->ism_lookahead + 1);
5688 }
5689 }
5690
5691 71 return mov_write_moof_tag_internal(pb, mov, tracks, moof_size);
5692 }
5693
5694 61 static int mov_write_tfra_tag(AVIOContext *pb, MOVTrack *track)
5695 {
5696 61 int64_t pos = avio_tell(pb);
5697 int i;
5698
5699 61 avio_wb32(pb, 0); /* size placeholder */
5700 61 ffio_wfourcc(pb, "tfra");
5701 61 avio_w8(pb, 1); /* version */
5702 61 avio_wb24(pb, 0);
5703
5704 61 avio_wb32(pb, track->track_id);
5705 61 avio_wb32(pb, 0); /* length of traf/trun/sample num */
5706 61 avio_wb32(pb, track->nb_frag_info);
5707
2/2
✓ Branch 0 taken 114 times.
✓ Branch 1 taken 61 times.
175 for (i = 0; i < track->nb_frag_info; i++) {
5708 114 avio_wb64(pb, track->frag_info[i].time);
5709 114 avio_wb64(pb, track->frag_info[i].offset + track->data_offset);
5710 114 avio_w8(pb, 1); /* traf number */
5711 114 avio_w8(pb, 1); /* trun number */
5712 114 avio_w8(pb, 1); /* sample number */
5713 }
5714
5715 61 return update_size(pb, pos);
5716 }
5717
5718 33 static int mov_write_mfra_tag(AVIOContext *pb, MOVMuxContext *mov)
5719 {
5720 AVIOContext *mfra_pb;
5721 int i, ret, sz;
5722 uint8_t *buf;
5723
5724 33 ret = avio_open_dyn_buf(&mfra_pb);
5725
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 if (ret < 0)
5726 return ret;
5727
5728 33 avio_wb32(mfra_pb, 0); /* size placeholder */
5729 33 ffio_wfourcc(mfra_pb, "mfra");
5730 /* An empty mfra atom is enough to indicate to the publishing point that
5731 * the stream has ended. */
5732
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 if (mov->flags & FF_MOV_FLAG_ISML)
5733 goto done_mfra;
5734
5735
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 33 times.
96 for (i = 0; i < mov->nb_tracks; i++) {
5736 63 MOVTrack *track = &mov->tracks[i];
5737
2/2
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 2 times.
63 if (track->nb_frag_info)
5738 61 mov_write_tfra_tag(mfra_pb, track);
5739 }
5740
5741 33 avio_wb32(mfra_pb, 16);
5742 33 ffio_wfourcc(mfra_pb, "mfro");
5743 33 avio_wb32(mfra_pb, 0); /* version + flags */
5744 33 avio_wb32(mfra_pb, avio_tell(mfra_pb) + 4);
5745
5746 33 done_mfra:
5747
5748 33 sz = update_size(mfra_pb, 0);
5749 33 ret = avio_get_dyn_buf(mfra_pb, &buf);
5750 33 avio_write(pb, buf, ret);
5751 33 ffio_free_dyn_buf(&mfra_pb);
5752
5753 33 return sz;
5754 }
5755
5756 169 static int mov_write_mdat_tag(AVIOContext *pb, MOVMuxContext *mov)
5757 {
5758 169 avio_wb32(pb, 8); // placeholder for extended size field (64 bit)
5759
2/2
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 29 times.
169 ffio_wfourcc(pb, mov->mode == MODE_MOV ? "wide" : "free");
5760
5761 169 mov->mdat_pos = avio_tell(pb);
5762 169 avio_wb32(pb, 0); /* size placeholder*/
5763 169 ffio_wfourcc(pb, "mdat");
5764 169 return 0;
5765 }
5766
5767 406 static void mov_write_ftyp_tag_internal(AVIOContext *pb, AVFormatContext *s,
5768 int has_h264, int has_video, int write_minor)
5769 {
5770 406 MOVMuxContext *mov = s->priv_data;
5771 406 int minor = 0x200;
5772
5773
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 406 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
406 if (mov->major_brand && strlen(mov->major_brand) >= 4)
5774 ffio_wfourcc(pb, mov->major_brand);
5775
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 406 times.
406 else if (mov->mode == MODE_3GP) {
5776 ffio_wfourcc(pb, has_h264 ? "3gp6" : "3gp4");
5777 minor = has_h264 ? 0x100 : 0x200;
5778
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 406 times.
406 } else if (mov->mode == MODE_AVIF) {
5779 ffio_wfourcc(pb, mov->is_animated_avif ? "avis" : "avif");
5780 minor = 0;
5781
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 406 times.
406 } else if (mov->mode & MODE_3G2) {
5782 ffio_wfourcc(pb, has_h264 ? "3g2b" : "3g2a");
5783 minor = has_h264 ? 0x20000 : 0x10000;
5784
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 404 times.
406 } else if (mov->mode == MODE_PSP)
5785 2 ffio_wfourcc(pb, "MSNV");
5786
4/4
✓ Branch 0 taken 112 times.
✓ Branch 1 taken 292 times.
✓ Branch 2 taken 58 times.
✓ Branch 3 taken 54 times.
404 else if (mov->mode == MODE_MP4 && mov->flags & FF_MOV_FLAG_FRAGMENT &&
5787
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 52 times.
58 mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS)
5788 6 ffio_wfourcc(pb, "iso6"); // Required when using signed CTS offsets in trun boxes
5789
4/4
✓ Branch 0 taken 106 times.
✓ Branch 1 taken 292 times.
✓ Branch 2 taken 22 times.
✓ Branch 3 taken 84 times.
398 else if (mov->mode == MODE_MP4 && mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF)
5790 22 ffio_wfourcc(pb, "iso5"); // Required when using default-base-is-moof
5791
3/4
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 292 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 84 times.
376 else if (mov->mode == MODE_MP4 && mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS)
5792 ffio_wfourcc(pb, "iso4");
5793
2/2
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 292 times.
376 else if (mov->mode == MODE_MP4)
5794 84 ffio_wfourcc(pb, "isom");
5795
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 290 times.
292 else if (mov->mode == MODE_IPOD)
5796
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 ffio_wfourcc(pb, has_video ? "M4V ":"M4A ");
5797
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 282 times.
290 else if (mov->mode == MODE_ISM)
5798 8 ffio_wfourcc(pb, "isml");
5799
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 282 times.
282 else if (mov->mode == MODE_F4V)
5800 ffio_wfourcc(pb, "f4v ");
5801 else
5802 282 ffio_wfourcc(pb, "qt ");
5803
5804
2/2
✓ Branch 0 taken 203 times.
✓ Branch 1 taken 203 times.
406 if (write_minor)
5805 203 avio_wb32(pb, minor);
5806 406 }
5807
5808 203 static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s)
5809 {
5810 203 MOVMuxContext *mov = s->priv_data;
5811 203 int64_t pos = avio_tell(pb);
5812 203 int has_h264 = 0, has_av1 = 0, has_video = 0, has_dolby = 0, has_id3 = 0;
5813 203 int has_iamf = 0;
5814
5815 #if CONFIG_IAMFENC
5816
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 199 times.
203 for (int i = 0; i < s->nb_stream_groups; i++) {
5817 4 const AVStreamGroup *stg = s->stream_groups[i];
5818
5819
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (stg->type == AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT ||
5820 stg->type == AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION) {
5821 4 has_iamf = 1;
5822 4 break;
5823 }
5824 }
5825 #endif
5826
2/2
✓ Branch 0 taken 259 times.
✓ Branch 1 taken 203 times.
462 for (int i = 0; i < mov->nb_streams; i++) {
5827 259 AVStream *st = mov->tracks[i].st;
5828
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 257 times.
259 if (is_cover_image(st))
5829 2 continue;
5830
2/2
✓ Branch 0 taken 171 times.
✓ Branch 1 taken 86 times.
257 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
5831 171 has_video = 1;
5832
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 224 times.
257 if (st->codecpar->codec_id == AV_CODEC_ID_H264)
5833 33 has_h264 = 1;
5834
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 256 times.
257 if (st->codecpar->codec_id == AV_CODEC_ID_AV1)
5835 1 has_av1 = 1;
5836
2/2
✓ Branch 0 taken 253 times.
✓ Branch 1 taken 4 times.
257 if (st->codecpar->codec_id == AV_CODEC_ID_AC3 ||
5837
2/2
✓ Branch 0 taken 252 times.
✓ Branch 1 taken 1 times.
253 st->codecpar->codec_id == AV_CODEC_ID_EAC3 ||
5838
2/4
✓ Branch 0 taken 252 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 252 times.
504 st->codecpar->codec_id == AV_CODEC_ID_TRUEHD ||
5839 252 av_packet_side_data_get(st->codecpar->coded_side_data,
5840 252 st->codecpar->nb_coded_side_data,
5841 AV_PKT_DATA_DOVI_CONF))
5842 5 has_dolby = 1;
5843
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 257 times.
257 if (st->codecpar->codec_id == AV_CODEC_ID_TIMED_ID3)
5844 has_id3 = 1;
5845 }
5846
5847 203 avio_wb32(pb, 0); /* size */
5848 203 ffio_wfourcc(pb, "ftyp");
5849
5850 // Write major brand
5851 203 mov_write_ftyp_tag_internal(pb, s, has_h264, has_video, 1);
5852 // Write the major brand as the first compatible brand as well
5853 203 mov_write_ftyp_tag_internal(pb, s, has_h264, has_video, 0);
5854
5855 // Write compatible brands, ensuring that we don't write the major brand as a
5856 // compatible brand a second time.
5857
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 199 times.
203 if (mov->mode == MODE_ISM) {
5858 4 ffio_wfourcc(pb, "piff");
5859
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 199 times.
199 } else if (mov->mode == MODE_AVIF) {
5860 const AVPixFmtDescriptor *pix_fmt_desc =
5861 av_pix_fmt_desc_get(s->streams[0]->codecpar->format);
5862 const int depth = pix_fmt_desc->comp[0].depth;
5863 if (mov->is_animated_avif) {
5864 // For animated AVIF, major brand is "avis". Add "avif" as a
5865 // compatible brand.
5866 ffio_wfourcc(pb, "avif");
5867 ffio_wfourcc(pb, "msf1");
5868 ffio_wfourcc(pb, "iso8");
5869 }
5870 ffio_wfourcc(pb, "mif1");
5871 ffio_wfourcc(pb, "miaf");
5872 if (depth == 8 || depth == 10) {
5873 // MA1B and MA1A brands are based on AV1 profile. Short hand for
5874 // computing that is based on chroma subsampling type. 420 chroma
5875 // subsampling is MA1B. 444 chroma subsampling is MA1A.
5876 if (!pix_fmt_desc->log2_chroma_w && !pix_fmt_desc->log2_chroma_h) {
5877 // 444 chroma subsampling.
5878 ffio_wfourcc(pb, "MA1A");
5879 } else {
5880 // 420 chroma subsampling.
5881 ffio_wfourcc(pb, "MA1B");
5882 }
5883 }
5884
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 141 times.
199 } else if (mov->mode != MODE_MOV) {
5885 // We add tfdt atoms when fragmenting, signal this with the iso6 compatible
5886 // brand, if not already the major brand. This is compatible with users that
5887 // don't understand tfdt.
5888
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 2 times.
58 if (mov->mode == MODE_MP4) {
5889
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 55 times.
56 if (mov->flags & FF_MOV_FLAG_CMAF)
5890 1 ffio_wfourcc(pb, "cmfc");
5891
4/4
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 26 times.
✓ Branch 3 taken 3 times.
56 if (mov->flags & FF_MOV_FLAG_FRAGMENT && !(mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS))
5892 26 ffio_wfourcc(pb, "iso6");
5893
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 55 times.
56 if (has_av1)
5894 1 ffio_wfourcc(pb, "av01");
5895
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 53 times.
56 if (has_dolby)
5896 3 ffio_wfourcc(pb, "dby1");
5897
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 52 times.
56 if (has_iamf)
5898 4 ffio_wfourcc(pb, "iamf");
5899 } else {
5900
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (mov->flags & FF_MOV_FLAG_FRAGMENT)
5901 ffio_wfourcc(pb, "iso6");
5902
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF)
5903 ffio_wfourcc(pb, "iso5");
5904
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS)
5905 ffio_wfourcc(pb, "iso4");
5906 }
5907 // Brands prior to iso5 can't be signaled when using default-base-is-moof
5908
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 12 times.
58 if (!(mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF)) {
5909 // write isom for mp4 only if it it's not the major brand already.
5910
4/4
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 42 times.
46 if (mov->mode != MODE_MP4 || mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS)
5911 4 ffio_wfourcc(pb, "isom");
5912 46 ffio_wfourcc(pb, "iso2");
5913
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 26 times.
46 if (has_h264)
5914 20 ffio_wfourcc(pb, "avc1");
5915 }
5916 }
5917
5918
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 147 times.
203 if (mov->mode == MODE_MP4)
5919 56 ffio_wfourcc(pb, "mp41");
5920
5921
3/4
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 192 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
203 if (mov->flags & FF_MOV_FLAG_DASH && mov->flags & FF_MOV_FLAG_GLOBAL_SIDX)
5922 ffio_wfourcc(pb, "dash");
5923
5924
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 203 times.
203 if (has_id3)
5925 ffio_wfourcc(pb, "aid3");
5926
5927 203 return update_size(pb, pos);
5928 }
5929
5930 1 static int mov_write_uuidprof_tag(AVIOContext *pb, AVFormatContext *s)
5931 {
5932 1 AVStream *video_st = s->streams[0];
5933 1 AVCodecParameters *video_par = s->streams[0]->codecpar;
5934 1 AVCodecParameters *audio_par = s->streams[1]->codecpar;
5935 1 int audio_rate = audio_par->sample_rate;
5936 2 int64_t frame_rate = video_st->avg_frame_rate.den ?
5937
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 :
5938 0;
5939 1 int audio_kbitrate = audio_par->bit_rate / 1000;
5940 1 int video_kbitrate = FFMIN(video_par->bit_rate / 1000, 800 - audio_kbitrate);
5941
5942
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) {
5943 av_log(s, AV_LOG_ERROR, "Frame rate %f outside supported range\n", frame_rate / (double)0x10000);
5944 return AVERROR(EINVAL);
5945 }
5946
5947 1 avio_wb32(pb, 0x94); /* size */
5948 1 ffio_wfourcc(pb, "uuid");
5949 1 ffio_wfourcc(pb, "PROF");
5950
5951 1 avio_wb32(pb, 0x21d24fce); /* 96 bit UUID */
5952 1 avio_wb32(pb, 0xbb88695c);
5953 1 avio_wb32(pb, 0xfac9c740);
5954
5955 1 avio_wb32(pb, 0x0); /* ? */
5956 1 avio_wb32(pb, 0x3); /* 3 sections ? */
5957
5958 1 avio_wb32(pb, 0x14); /* size */
5959 1 ffio_wfourcc(pb, "FPRF");
5960 1 avio_wb32(pb, 0x0); /* ? */
5961 1 avio_wb32(pb, 0x0); /* ? */
5962 1 avio_wb32(pb, 0x0); /* ? */
5963
5964 1 avio_wb32(pb, 0x2c); /* size */
5965 1 ffio_wfourcc(pb, "APRF"); /* audio */
5966 1 avio_wb32(pb, 0x0);
5967 1 avio_wb32(pb, 0x2); /* TrackID */
5968 1 ffio_wfourcc(pb, "mp4a");
5969 1 avio_wb32(pb, 0x20f);
5970 1 avio_wb32(pb, 0x0);
5971 1 avio_wb32(pb, audio_kbitrate);
5972 1 avio_wb32(pb, audio_kbitrate);
5973 1 avio_wb32(pb, audio_rate);
5974 1 avio_wb32(pb, audio_par->ch_layout.nb_channels);
5975
5976 1 avio_wb32(pb, 0x34); /* size */
5977 1 ffio_wfourcc(pb, "VPRF"); /* video */
5978 1 avio_wb32(pb, 0x0);
5979 1 avio_wb32(pb, 0x1); /* TrackID */
5980
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (video_par->codec_id == AV_CODEC_ID_H264) {
5981 1 ffio_wfourcc(pb, "avc1");
5982 1 avio_wb16(pb, 0x014D);
5983 1 avio_wb16(pb, 0x0015);
5984 } else {
5985 ffio_wfourcc(pb, "mp4v");
5986 avio_wb16(pb, 0x0000);
5987 avio_wb16(pb, 0x0103);
5988 }
5989 1 avio_wb32(pb, 0x0);
5990 1 avio_wb32(pb, video_kbitrate);
5991 1 avio_wb32(pb, video_kbitrate);
5992 1 avio_wb32(pb, frame_rate);
5993 1 avio_wb32(pb, frame_rate);
5994 1 avio_wb16(pb, video_par->width);
5995 1 avio_wb16(pb, video_par->height);
5996 1 avio_wb32(pb, 0x010001); /* ? */
5997
5998 1 return 0;
5999 }
6000
6001 203 static int mov_write_identification(AVIOContext *pb, AVFormatContext *s)
6002 {
6003 203 MOVMuxContext *mov = s->priv_data;
6004 int i;
6005
6006 203 mov_write_ftyp_tag(pb,s);
6007
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 202 times.
203 if (mov->mode == MODE_PSP) {
6008 1 int video_streams_nb = 0, audio_streams_nb = 0, other_streams_nb = 0;
6009
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 for (i = 0; i < mov->nb_streams; i++) {
6010 2 AVStream *st = mov->tracks[i].st;
6011
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (is_cover_image(st))
6012 continue;
6013
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
6014 1 video_streams_nb++;
6015
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
6016 1 audio_streams_nb++;
6017 else
6018 other_streams_nb++;
6019 }
6020
6021
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) {
6022 av_log(s, AV_LOG_ERROR, "PSP mode need one video and one audio stream\n");
6023 return AVERROR(EINVAL);
6024 }
6025 1 return mov_write_uuidprof_tag(pb, s);
6026 }
6027 202 return 0;
6028 }
6029
6030 8 static int mov_parse_mpeg2_frame(AVPacket *pkt, uint32_t *flags)
6031 {
6032 8 uint32_t c = -1;
6033 8 int i, closed_gop = 0;
6034
6035
1/2
✓ Branch 0 taken 368 times.
✗ Branch 1 not taken.
368 for (i = 0; i < pkt->size - 4; i++) {
6036 368 c = (c << 8) + pkt->data[i];
6037
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 360 times.
368 if (c == 0x1b8) { // gop
6038 8 closed_gop = pkt->data[i + 4] >> 6 & 0x01;
6039
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 352 times.
360 } else if (c == 0x100) { // pic
6040 8 int temp_ref = (pkt->data[i + 1] << 2) | (pkt->data[i + 2] >> 6);
6041
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
6042 8 *flags = MOV_SYNC_SAMPLE;
6043 else
6044 *flags = MOV_PARTIAL_SYNC_SAMPLE;
6045 8 break;
6046 }
6047 }
6048 8 return 0;
6049 }
6050
6051 static void mov_parse_vc1_frame(AVPacket *pkt, MOVTrack *trk)
6052 {
6053 const uint8_t *start, *next, *end = pkt->data + pkt->size;
6054 int seq = 0, entry = 0;
6055 int key = pkt->flags & AV_PKT_FLAG_KEY;
6056 start = find_next_marker(pkt->data, end);
6057 for (next = start; next < end; start = next) {
6058 next = find_next_marker(start + 4, end);
6059 switch (AV_RB32(start)) {
6060 case VC1_CODE_SEQHDR:
6061 seq = 1;
6062 break;
6063 case VC1_CODE_ENTRYPOINT:
6064 entry = 1;
6065 break;
6066 case VC1_CODE_SLICE:
6067 trk->vc1_info.slices = 1;
6068 break;
6069 }
6070 }
6071 if (!trk->entry && trk->vc1_info.first_packet_seen)
6072 trk->vc1_info.first_frag_written = 1;
6073 if (!trk->entry && !trk->vc1_info.first_frag_written) {
6074 /* First packet in first fragment */
6075 trk->vc1_info.first_packet_seq = seq;
6076 trk->vc1_info.first_packet_entry = entry;
6077 trk->vc1_info.first_packet_seen = 1;
6078 } else if ((seq && !trk->vc1_info.packet_seq) ||
6079 (entry && !trk->vc1_info.packet_entry)) {
6080 int i;
6081 for (i = 0; i < trk->entry; i++)
6082 trk->cluster[i].flags &= ~MOV_SYNC_SAMPLE;
6083 trk->has_keyframes = 0;
6084 if (seq)
6085 trk->vc1_info.packet_seq = 1;
6086 if (entry)
6087 trk->vc1_info.packet_entry = 1;
6088 if (!trk->vc1_info.first_frag_written) {
6089 /* First fragment */
6090 if ((!seq || trk->vc1_info.first_packet_seq) &&
6091 (!entry || trk->vc1_info.first_packet_entry)) {
6092 /* First packet had the same headers as this one, readd the
6093 * sync sample flag. */
6094 trk->cluster[0].flags |= MOV_SYNC_SAMPLE;
6095 trk->has_keyframes = 1;
6096 }
6097 }
6098 }
6099 if (trk->vc1_info.packet_seq && trk->vc1_info.packet_entry)
6100 key = seq && entry;
6101 else if (trk->vc1_info.packet_seq)
6102 key = seq;
6103 else if (trk->vc1_info.packet_entry)
6104 key = entry;
6105 if (key) {
6106 trk->cluster[trk->entry].flags |= MOV_SYNC_SAMPLE;
6107 trk->has_keyframes++;
6108 }
6109 }
6110
6111 static void mov_parse_truehd_frame(AVPacket *pkt, MOVTrack *trk)
6112 {
6113 int length;
6114
6115 if (pkt->size < 8)
6116 return;
6117
6118 length = (AV_RB16(pkt->data) & 0xFFF) * 2;
6119 if (length < 8 || length > pkt->size)
6120 return;
6121
6122 if (AV_RB32(pkt->data + 4) == 0xF8726FBA) {
6123 trk->cluster[trk->entry].flags |= MOV_SYNC_SAMPLE;
6124 trk->has_keyframes++;
6125 }
6126
6127 return;
6128 }
6129
6130 static int mov_flush_fragment_interleaving(AVFormatContext *s, MOVTrack *track)
6131 {
6132 MOVMuxContext *mov = s->priv_data;
6133 int ret, buf_size;
6134 uint8_t *buf;
6135 int i, offset;
6136
6137 if (!track->mdat_buf)
6138 return 0;
6139 if (!mov->mdat_buf) {
6140 if ((ret = avio_open_dyn_buf(&mov->mdat_buf)) < 0)
6141 return ret;
6142 }
6143 buf_size = avio_get_dyn_buf(track->mdat_buf, &buf);
6144
6145 offset = avio_tell(mov->mdat_buf);
6146 avio_write(mov->mdat_buf, buf, buf_size);
6147 ffio_free_dyn_buf(&track->mdat_buf);
6148
6149 for (i = track->entries_flushed; i < track->entry; i++)
6150 track->cluster[i].pos += offset;
6151 track->entries_flushed = track->entry;
6152 return 0;
6153 }
6154
6155 2 static int mov_write_squashed_packet(AVFormatContext *s, MOVTrack *track)
6156 {
6157 2 MOVMuxContext *mov = s->priv_data;
6158 2 AVPacket *squashed_packet = mov->pkt;
6159 2 int ret = AVERROR_BUG;
6160
6161
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 switch (track->st->codecpar->codec_id) {
6162 2 case AV_CODEC_ID_TTML: {
6163 2 int had_packets = !!track->squashed_packet_queue.head;
6164
6165
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if ((ret = ff_mov_generate_squashed_ttml_packet(s, track, squashed_packet)) < 0) {
6166 goto finish_squash;
6167 }
6168
6169 // We have generated a padding packet (no actual input packets in
6170 // queue) and its duration is zero. Skipping writing it.
6171
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2 if (!had_packets && squashed_packet->duration == 0) {
6172 goto finish_squash;
6173 }
6174
6175 2 track->end_reliable = 1;
6176 2 break;
6177 }
6178 default:
6179 ret = AVERROR(EINVAL);
6180 goto finish_squash;
6181 }
6182
6183 2 squashed_packet->stream_index = track->st->index;
6184
6185 2 ret = mov_write_single_packet(s, squashed_packet);
6186
6187 2 finish_squash:
6188 2 av_packet_unref(squashed_packet);
6189
6190 2 return ret;
6191 }
6192
6193 309 static int mov_write_squashed_packets(AVFormatContext *s)
6194 {
6195 309 MOVMuxContext *mov = s->priv_data;
6196
6197
2/2
✓ Branch 0 taken 451 times.
✓ Branch 1 taken 309 times.
760 for (int i = 0; i < mov->nb_streams; i++) {
6198 451 MOVTrack *track = &mov->tracks[i];
6199 451 int ret = AVERROR_BUG;
6200
6201
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 449 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
451 if (track->squash_fragment_samples_to_one && !track->entry) {
6202
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if ((ret = mov_write_squashed_packet(s, track)) < 0) {
6203 av_log(s, AV_LOG_ERROR,
6204 "Failed to write squashed packet for %s stream with "
6205 "index %d and track id %d. Error: %s\n",
6206 avcodec_get_name(track->st->codecpar->codec_id),
6207 track->st->index, track->track_id,
6208 av_err2str(ret));
6209 return ret;
6210 }
6211 }
6212 }
6213
6214 309 return 0;
6215 }
6216
6217 129 static int mov_finish_fragment(MOVMuxContext *mov, MOVTrack *track,
6218 int64_t ref_pos)
6219 {
6220 int i;
6221
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 125 times.
129 if (!track->entry)
6222 4 return 0;
6223
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 120 times.
125 if (mov->flags & FF_MOV_FLAG_HYBRID_FRAGMENTED) {
6224
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 5 times.
41 for (i = 0; i < track->entry; i++)
6225 36 track->cluster[i].pos += ref_pos + track->data_offset;
6226
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
5 if (track->cluster_written == 0 && !(mov->flags & FF_MOV_FLAG_EMPTY_MOOV)) {
6227 // First flush. If this was a case of not using empty moov, reset chunking.
6228
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 2 times.
20 for (i = 0; i < track->entry; i++) {
6229 18 track->cluster[i].chunkNum = 0;
6230 18 track->cluster[i].samples_in_chunk = track->cluster[i].entries;
6231 }
6232 }
6233
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (av_reallocp_array(&track->cluster_written,
6234 5 track->entry_written + track->entry,
6235 sizeof(*track->cluster)))
6236 return AVERROR(ENOMEM);
6237 5 memcpy(&track->cluster_written[track->entry_written],
6238 5 track->cluster, track->entry * sizeof(*track->cluster));
6239 5 track->entry_written += track->entry;
6240 }
6241 125 track->entry = 0;
6242 125 track->entries_flushed = 0;
6243 125 track->end_reliable = 0;
6244 125 return 0;
6245 }
6246
6247 106 static int mov_flush_fragment(AVFormatContext *s, int force)
6248 {
6249 106 MOVMuxContext *mov = s->priv_data;
6250 106 int i, first_track = -1;
6251 106 int64_t mdat_size = 0, mdat_start = 0;
6252 int ret;
6253 106 int has_video = 0, starts_with_key = 0, first_video_track = 1;
6254
6255
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 106 times.
106 if (!(mov->flags & FF_MOV_FLAG_FRAGMENT))
6256 return 0;
6257
6258 // Check if we have any tracks that require squashing.
6259 // In that case, we'll have to write the packet here.
6260
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 106 times.
106 if ((ret = mov_write_squashed_packets(s)) < 0)
6261 return ret;
6262
6263 // Try to fill in the duration of the last packet in each stream
6264 // from queued packets in the interleave queues. If the flushing
6265 // of fragments was triggered automatically by an AVPacket, we
6266 // already have reliable info for the end of that track, but other
6267 // tracks may need to be filled in.
6268
2/2
✓ Branch 0 taken 192 times.
✓ Branch 1 taken 106 times.
298 for (i = 0; i < mov->nb_streams; i++) {
6269 192 MOVTrack *track = &mov->tracks[i];
6270
2/2
✓ Branch 0 taken 154 times.
✓ Branch 1 taken 38 times.
192 if (!track->end_reliable) {
6271 154 const AVPacket *pkt = ff_interleaved_peek(s, i);
6272
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 148 times.
154 if (pkt) {
6273 int64_t offset, dts, pts;
6274 6 ff_get_muxer_ts_offset(s, i, &offset);
6275 6 pts = pkt->pts + offset;
6276 6 dts = pkt->dts + offset;
6277
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (track->dts_shift != AV_NOPTS_VALUE)
6278 dts += track->dts_shift;
6279 6 track->track_duration = dts - track->start_dts;
6280
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (pts != AV_NOPTS_VALUE)
6281 6 track->end_pts = pts;
6282 else
6283 track->end_pts = dts;
6284 }
6285 }
6286 }
6287
6288
2/2
✓ Branch 0 taken 198 times.
✓ Branch 1 taken 106 times.
304 for (i = 0; i < mov->nb_tracks; i++) {
6289 198 MOVTrack *track = &mov->tracks[i];
6290
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 153 times.
198 if (track->entry <= 1)
6291 45 continue;
6292 // Sample durations are calculated as the diff of dts values,
6293 // but for the last sample in a fragment, we don't know the dts
6294 // of the first sample in the next fragment, so we have to rely
6295 // on what was set as duration in the AVPacket. Not all callers
6296 // set this though, so we might want to replace it with an
6297 // estimate if it currently is zero.
6298
2/2
✓ Branch 1 taken 151 times.
✓ Branch 2 taken 2 times.
153 if (get_cluster_duration(track, track->entry - 1) != 0)
6299 151 continue;
6300 // Use the duration (i.e. dts diff) of the second last sample for
6301 // the last one. This is a wild guess (and fatal if it turns out
6302 // to be too long), but probably the best we can do - having a zero
6303 // duration is bad as well.
6304 2 track->track_duration += get_cluster_duration(track, track->entry - 2);
6305 2 track->end_pts += get_cluster_duration(track, track->entry - 2);
6306
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!mov->missing_duration_warned) {
6307 2 av_log(s, AV_LOG_WARNING,
6308 "Estimating the duration of the last packet in a "
6309 "fragment, consider setting the duration field in "
6310 "AVPacket instead.\n");
6311 2 mov->missing_duration_warned = 1;
6312 }
6313 }
6314
6315
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 83 times.
106 if (!mov->moov_written) {
6316 23 int64_t pos = avio_tell(s->pb);
6317 uint8_t *buf;
6318 int buf_size, moov_size;
6319
6320
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 19 times.
64 for (i = 0; i < mov->nb_tracks; i++)
6321
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 41 times.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
45 if (!mov->tracks[i].entry && !is_cover_image(mov->tracks[i].st))
6322 4 break;
6323 /* Don't write the initial moov unless all tracks have data */
6324
4/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 19 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
23 if (i < mov->nb_tracks && !force)
6325 2 return 0;
6326
6327 21 moov_size = get_moov_size(s);
6328
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 21 times.
62 for (i = 0; i < mov->nb_tracks; i++)
6329 41 mov->tracks[i].data_offset = pos + moov_size + 8;
6330
6331 21 avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_HEADER);
6332
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 4 times.
21 if (mov->flags & FF_MOV_FLAG_DELAY_MOOV)
6333 17 mov_write_identification(s->pb, s);
6334
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
21 if ((ret = mov_write_moov_tag(s->pb, mov, s)) < 0)
6335 return ret;
6336
6337
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 4 times.
21 if (mov->flags & FF_MOV_FLAG_DELAY_MOOV) {
6338
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX)
6339 mov->reserved_header_pos = avio_tell(s->pb);
6340 17 avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT);
6341 17 mov->moov_written = 1;
6342 17 return 0;
6343 }
6344
6345 4 buf_size = avio_get_dyn_buf(mov->mdat_buf, &buf);
6346 4 avio_wb32(s->pb, buf_size + 8);
6347 4 ffio_wfourcc(s->pb, "mdat");
6348 4 avio_write(s->pb, buf, buf_size);
6349 4 ffio_free_dyn_buf(&mov->mdat_buf);
6350
6351
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX)
6352 mov->reserved_header_pos = avio_tell(s->pb);
6353
6354 4 mov->moov_written = 1;
6355 4 mov->mdat_size = 0;
6356
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 for (i = 0; i < mov->nb_tracks; i++)
6357 8 mov_finish_fragment(mov, &mov->tracks[i], 0);
6358 4 avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT);
6359 4 return 0;
6360 }
6361
6362
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 83 times.
83 if (mov->frag_interleave) {
6363 for (i = 0; i < mov->nb_tracks; i++) {
6364 MOVTrack *track = &mov->tracks[i];
6365 int ret;
6366 if ((ret = mov_flush_fragment_interleaving(s, track)) < 0)
6367 return ret;
6368 }
6369
6370 if (!mov->mdat_buf)
6371 return 0;
6372 mdat_size = avio_tell(mov->mdat_buf);
6373 }
6374
6375
2/2
✓ Branch 0 taken 153 times.
✓ Branch 1 taken 83 times.
236 for (i = 0; i < mov->nb_tracks; i++) {
6376 153 MOVTrack *track = &mov->tracks[i];
6377
3/4
✓ Branch 0 taken 134 times.
✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 134 times.
153 if (mov->flags & FF_MOV_FLAG_SEPARATE_MOOF || mov->frag_interleave)
6378 19 track->data_offset = 0;
6379 else
6380 134 track->data_offset = mdat_size;
6381
2/2
✓ Branch 0 taken 73 times.
✓ Branch 1 taken 80 times.
153 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
6382 73 has_video = 1;
6383
1/2
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
73 if (first_video_track) {
6384
2/2
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 12 times.
73 if (track->entry)
6385 61 starts_with_key = track->cluster[0].flags & MOV_SYNC_SAMPLE;
6386 73 first_video_track = 0;
6387 }
6388 }
6389
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 117 times.
153 if (!track->entry)
6390 36 continue;
6391
1/2
✓ Branch 0 taken 117 times.
✗ Branch 1 not taken.
117 if (track->mdat_buf)
6392 117 mdat_size += avio_tell(track->mdat_buf);
6393
2/2
✓ Branch 0 taken 67 times.
✓ Branch 1 taken 50 times.
117 if (first_track < 0)
6394 67 first_track = i;
6395 }
6396
6397
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 67 times.
83 if (!mdat_size)
6398 16 return 0;
6399
6400
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 3 times.
67 avio_write_marker(s->pb,
6401 67 av_rescale(mov->tracks[first_track].cluster[0].dts, AV_TIME_BASE, mov->tracks[first_track].timescale),
6402
2/2
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 6 times.
67 (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);
6403
6404
2/2
✓ Branch 0 taken 125 times.
✓ Branch 1 taken 67 times.
192 for (i = 0; i < mov->nb_tracks; i++) {
6405 125 MOVTrack *track = &mov->tracks[i];
6406 125 int buf_size, write_moof = 1, moof_tracks = -1;
6407 uint8_t *buf;
6408
6409
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 106 times.
125 if (mov->flags & FF_MOV_FLAG_SEPARATE_MOOF) {
6410
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 15 times.
19 if (!track->entry)
6411 8 continue;
6412 15 mdat_size = avio_tell(track->mdat_buf);
6413 15 moof_tracks = i;
6414 } else {
6415 106 write_moof = i == first_track;
6416 }
6417
6418
2/2
✓ Branch 0 taken 71 times.
✓ Branch 1 taken 50 times.
121 if (write_moof) {
6419 71 avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT);
6420
6421 71 mov_write_moof_tag(s->pb, mov, moof_tracks, mdat_size);
6422 71 mov->fragments++;
6423
6424 71 avio_wb32(s->pb, mdat_size + 8);
6425 71 ffio_wfourcc(s->pb, "mdat");
6426 71 mdat_start = avio_tell(s->pb);
6427 }
6428
6429 121 mov_finish_fragment(mov, &mov->tracks[i], mdat_start);
6430
1/2
✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
121 if (!mov->frag_interleave) {
6431
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 117 times.
121 if (!track->mdat_buf)
6432 4 continue;
6433 117 buf_size = avio_close_dyn_buf(track->mdat_buf, &buf);
6434 117 track->mdat_buf = NULL;
6435 } else {
6436 if (!mov->mdat_buf)
6437 continue;
6438 buf_size = avio_close_dyn_buf(mov->mdat_buf, &buf);
6439 mov->mdat_buf = NULL;
6440 }
6441
6442 117 avio_write(s->pb, buf, buf_size);
6443 117 av_free(buf);
6444 }
6445
6446 67 mov->mdat_size = 0;
6447
6448 67 avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT);
6449 67 return 0;
6450 }
6451
6452 61 static int mov_auto_flush_fragment(AVFormatContext *s, int force)
6453 {
6454 61 MOVMuxContext *mov = s->priv_data;
6455 61 int had_moov = mov->moov_written;
6456 61 int ret = mov_flush_fragment(s, force);
6457
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 if (ret < 0)
6458 return ret;
6459 // If using delay_moov, the first flush only wrote the moov,
6460 // not the actual moof+mdat pair, thus flush once again.
6461
4/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 48 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 4 times.
61 if (!had_moov && mov->flags & FF_MOV_FLAG_DELAY_MOOV)
6462 9 ret = mov_flush_fragment(s, force);
6463 61 return ret;
6464 }
6465
6466 35542 static int check_pkt(AVFormatContext *s, MOVTrack *trk, AVPacket *pkt)
6467 {
6468 int64_t ref;
6469 uint64_t duration;
6470
6471
2/2
✓ Branch 0 taken 34920 times.
✓ Branch 1 taken 622 times.
35542 if (trk->entry) {
6472 34920 ref = trk->cluster[trk->entry - 1].dts;
6473
2/2
✓ Branch 0 taken 114 times.
✓ Branch 1 taken 508 times.
622 } else if ( trk->start_dts != AV_NOPTS_VALUE
6474
2/2
✓ Branch 0 taken 106 times.
✓ Branch 1 taken 8 times.
114 && !trk->frag_discont) {
6475 106 ref = trk->start_dts + trk->track_duration;
6476 } else
6477 516 ref = pkt->dts; // Skip tests for the first packet
6478
6479
2/2
✓ Branch 0 taken 1655 times.
✓ Branch 1 taken 33887 times.
35542 if (trk->dts_shift != AV_NOPTS_VALUE) {
6480 /* With negative CTS offsets we have set an offset to the DTS,
6481 * reverse this for the check. */
6482 1655 ref -= trk->dts_shift;
6483 }
6484
6485 35542 duration = pkt->dts - ref;
6486
2/4
✓ Branch 0 taken 35542 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 35542 times.
35542 if (pkt->dts < ref || duration >= INT_MAX) {
6487 av_log(s, AV_LOG_WARNING, "Packet duration: %"PRId64" / dts: %"PRId64" is out of range\n",
6488 duration, pkt->dts);
6489
6490 pkt->dts = ref + 1;
6491 pkt->pts = AV_NOPTS_VALUE;
6492 }
6493
6494
2/4
✓ Branch 0 taken 35542 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 35542 times.
35542 if (pkt->duration < 0 || pkt->duration > INT_MAX) {
6495 av_log(s, AV_LOG_ERROR, "Application provided duration: %"PRId64" is invalid\n", pkt->duration);
6496 return AVERROR(EINVAL);
6497 }
6498 35542 return 0;
6499 }
6500
6501 17790 int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
6502 {
6503 17790 MOVMuxContext *mov = s->priv_data;
6504 17790 AVIOContext *pb = s->pb;
6505 MOVTrack *trk;
6506 AVCodecParameters *par;
6507 AVProducerReferenceTime *prft;
6508 17790 unsigned int samples_in_chunk = 0;
6509 17790 int size = pkt->size, ret = 0, offset = 0;
6510 size_t prft_size;
6511 17790 uint8_t *reformatted_data = NULL;
6512
6513
2/2
✓ Branch 0 taken 17744 times.
✓ Branch 1 taken 46 times.
17790 if (pkt->stream_index < s->nb_streams)
6514 17744 trk = s->streams[pkt->stream_index]->priv_data;
6515 else // Timecode or chapter
6516 46 trk = &mov->tracks[pkt->stream_index];
6517 17790 par = trk->par;
6518
6519 17790 ret = check_pkt(s, trk, pkt);
6520
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17790 times.
17790 if (ret < 0)
6521 return ret;
6522
6523
2/2
✓ Branch 0 taken 17188 times.
✓ Branch 1 taken 602 times.
17790 if (pkt->pts != AV_NOPTS_VALUE &&
6524
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17188 times.
17188 (uint64_t)pkt->dts - pkt->pts != (int32_t)((uint64_t)pkt->dts - pkt->pts)) {
6525 av_log(s, AV_LOG_WARNING, "pts/dts pair unsupported\n");
6526 return AVERROR_PATCHWELCOME;
6527 }
6528
6529
3/4
✓ Branch 0 taken 12530 times.
✓ Branch 1 taken 5260 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12530 times.
17790 if (mov->flags & FF_MOV_FLAG_FRAGMENT || mov->mode == MODE_AVIF) {
6530 int ret;
6531
4/4
✓ Branch 0 taken 2130 times.
✓ Branch 1 taken 3130 times.
✓ Branch 2 taken 1892 times.
✓ Branch 3 taken 238 times.
5260 if (mov->moov_written || mov->flags & FF_MOV_FLAG_EMPTY_MOOV) {
6532
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5022 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
5022 if (mov->frag_interleave && mov->fragments > 0) {
6533 if (trk->entry - trk->entries_flushed >= mov->frag_interleave) {
6534 if ((ret = mov_flush_fragment_interleaving(s, trk)) < 0)
6535 return ret;
6536 }
6537 }
6538
6539
2/2
✓ Branch 0 taken 117 times.
✓ Branch 1 taken 4905 times.
5022 if (!trk->mdat_buf) {
6540
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 117 times.
117 if ((ret = avio_open_dyn_buf(&trk->mdat_buf)) < 0)
6541 return ret;
6542 }
6543 5022 pb = trk->mdat_buf;
6544 } else {
6545
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 234 times.
238 if (!mov->mdat_buf) {
6546
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((ret = avio_open_dyn_buf(&mov->mdat_buf)) < 0)
6547 return ret;
6548 }
6549 238 pb = mov->mdat_buf;
6550 }
6551 }
6552
6553
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17790 times.
17790 if (par->codec_id == AV_CODEC_ID_AMR_NB) {
6554 /* We must find out how many AMR blocks there are in one packet */
6555 static const uint16_t packed_size[16] =
6556 {13, 14, 16, 18, 20, 21, 27, 32, 6, 0, 0, 0, 0, 0, 0, 1};
6557 int len = 0;
6558
6559 while (len < size && samples_in_chunk < 100) {
6560 len += packed_size[(pkt->data[len] >> 3) & 0x0F];
6561 samples_in_chunk++;
6562 }
6563 if (samples_in_chunk > 1) {
6564 av_log(s, AV_LOG_ERROR, "fatal error, input is not a single packet, implement a AVParser for it\n");
6565 return -1;
6566 }
6567
1/2
✓ Branch 0 taken 17790 times.
✗ Branch 1 not taken.
17790 } else if (par->codec_id == AV_CODEC_ID_ADPCM_MS ||
6568
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17790 times.
17790 par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) {
6569 samples_in_chunk = trk->par->frame_size;
6570
2/2
✓ Branch 0 taken 1297 times.
✓ Branch 1 taken 16493 times.
17790 } else if (trk->sample_size)
6571 1297 samples_in_chunk = size / trk->sample_size;
6572 else
6573 16493 samples_in_chunk = 1;
6574
6575
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17790 times.
17790 if (samples_in_chunk < 1) {
6576 av_log(s, AV_LOG_ERROR, "fatal error, input packet contains no samples\n");
6577 return AVERROR_PATCHWELCOME;
6578 }
6579
6580 /* copy extradata if it exists */
6581
4/4
✓ Branch 0 taken 5175 times.
✓ Branch 1 taken 12615 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 5173 times.
17790 if (trk->vos_len == 0 && par->extradata_size > 0 &&
6582
14/28
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 2 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 2 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 2 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 2 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 2 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 2 times.
✗ Branch 27 not taken.
2 !TAG_IS_AVCI(trk->tag) &&
6583
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 (par->codec_id != AV_CODEC_ID_DNXHD)) {
6584 2 trk->vos_len = par->extradata_size;
6585 2 trk->vos_data = av_malloc(trk->vos_len + AV_INPUT_BUFFER_PADDING_SIZE);
6586
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!trk->vos_data) {
6587 ret = AVERROR(ENOMEM);
6588 goto err;
6589 }
6590 2 memcpy(trk->vos_data, par->extradata, trk->vos_len);
6591 2 memset(trk->vos_data + trk->vos_len, 0, AV_INPUT_BUFFER_PADDING_SIZE);
6592 }
6593
6594
2/2
✓ Branch 0 taken 17675 times.
✓ Branch 1 taken 115 times.
17790 if ((par->codec_id == AV_CODEC_ID_DNXHD ||
6595
2/2
✓ Branch 0 taken 15137 times.
✓ Branch 1 taken 2538 times.
17675 par->codec_id == AV_CODEC_ID_H264 ||
6596
2/2
✓ Branch 0 taken 14982 times.
✓ Branch 1 taken 155 times.
15137 par->codec_id == AV_CODEC_ID_HEVC ||
6597
2/2
✓ Branch 0 taken 14972 times.
✓ Branch 1 taken 10 times.
14982 par->codec_id == AV_CODEC_ID_VVC ||
6598
1/2
✓ Branch 0 taken 14972 times.
✗ Branch 1 not taken.
14972 par->codec_id == AV_CODEC_ID_VP9 ||
6599
2/2
✓ Branch 0 taken 14672 times.
✓ Branch 1 taken 300 times.
14972 par->codec_id == AV_CODEC_ID_EVC ||
6600
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 14672 times.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 3094 times.
17790 par->codec_id == AV_CODEC_ID_TRUEHD) && !trk->vos_len &&
6601
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)) {
6602 /* copy frame to create needed atoms */
6603 24 trk->vos_len = size;
6604 24 trk->vos_data = av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
6605
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (!trk->vos_data) {
6606 ret = AVERROR(ENOMEM);
6607 goto err;
6608 }
6609 24 memcpy(trk->vos_data, pkt->data, size);
6610 24 memset(trk->vos_data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
6611 }
6612
6613
3/4
✓ Branch 0 taken 5540 times.
✓ Branch 1 taken 12250 times.
✓ Branch 2 taken 5540 times.
✗ Branch 3 not taken.
17790 if (par->codec_id == AV_CODEC_ID_AAC && pkt->size > 2 &&
6614
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5540 times.
5540 (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) {
6615 if (!trk->st->nb_frames) {
6616 av_log(s, AV_LOG_ERROR, "Malformed AAC bitstream detected: "
6617 "use the audio bitstream filter 'aac_adtstoasc' to fix it "
6618 "('-bsf:a aac_adtstoasc' option with ffmpeg)\n");
6619 return -1;
6620 }
6621 av_log(s, AV_LOG_WARNING, "aac bitstream error\n");
6622 }
6623
19/34
✓ Branch 0 taken 2538 times.
✓ Branch 1 taken 15252 times.
✓ Branch 2 taken 2538 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 448 times.
✓ Branch 5 taken 2090 times.
✓ Branch 6 taken 448 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 448 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 448 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 448 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 448 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 448 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 448 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 448 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 448 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 448 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 448 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 448 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 448 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 448 times.
✗ Branch 33 not taken.
17790 if (par->codec_id == AV_CODEC_ID_H264 && trk->vos_len > 0 && *(uint8_t *)trk->vos_data != 1 && !TAG_IS_AVCI(trk->tag)) {
6624 /* from x264 or from bytestream H.264 */
6625 /* NAL reformatting needed */
6626
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 448 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
448 if (trk->hint_track >= 0 && trk->hint_track < mov->nb_tracks) {
6627 ret = ff_nal_parse_units_buf(pkt->data, &reformatted_data,
6628 &size);
6629 if (ret < 0)
6630 return ret;
6631 avio_write(pb, reformatted_data, size);
6632 } else {
6633
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 448 times.
448 if (trk->cenc.aes_ctr) {
6634 size = ff_mov_cenc_avc_parse_nal_units(&trk->cenc, pb, pkt->data, size);
6635 if (size < 0) {
6636 ret = size;
6637 goto err;
6638 }
6639 } else {
6640 448 size = ff_nal_parse_units(pb, pkt->data, pkt->size);
6641 }
6642 }
6643
3/4
✓ Branch 0 taken 155 times.
✓ Branch 1 taken 17187 times.
✓ Branch 2 taken 155 times.
✗ Branch 3 not taken.
17342 } else if (par->codec_id == AV_CODEC_ID_HEVC && trk->vos_len > 6 &&
6644
3/4
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
155 (AV_RB24(trk->vos_data) == 1 || AV_RB32(trk->vos_data) == 1)) {
6645 /* extradata is Annex B, assume the bitstream is too and convert it */
6646
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
144 if (trk->hint_track >= 0 && trk->hint_track < mov->nb_tracks) {
6647 ret = ff_hevc_annexb2mp4_buf(pkt->data, &reformatted_data,
6648 &size, 0, NULL);
6649 if (ret < 0)
6650 return ret;
6651 avio_write(pb, reformatted_data, size);
6652 } else {
6653
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 if (trk->cenc.aes_ctr) {
6654 size = ff_mov_cenc_avc_parse_nal_units(&trk->cenc, pb, pkt->data, size);
6655 if (size < 0) {
6656 ret = size;
6657 goto err;
6658 }
6659 } else {
6660 144 size = ff_hevc_annexb2mp4(pb, pkt->data, pkt->size, 0, NULL);
6661 }
6662 }
6663
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 17188 times.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
17198 } else if (par->codec_id == AV_CODEC_ID_VVC && trk->vos_len > 6 &&
6664
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
10 (AV_RB24(trk->vos_data) == 1 || AV_RB32(trk->vos_data) == 1)) {
6665 /* extradata is Annex B, assume the bitstream is too and convert it */
6666
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) {
6667 ret = ff_vvc_annexb2mp4_buf(pkt->data, &reformatted_data,
6668 &size, 0, NULL);
6669 if (ret < 0)
6670 return ret;
6671 avio_write(pb, reformatted_data, size);
6672 } else {
6673 10 size = ff_vvc_annexb2mp4(pb, pkt->data, pkt->size, 0, NULL);
6674 }
6675
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 17184 times.
17188 } else if (par->codec_id == AV_CODEC_ID_AV1) {
6676
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
4 if (trk->hint_track >= 0 && trk->hint_track < mov->nb_tracks) {
6677 ret = ff_av1_filter_obus_buf(pkt->data, &reformatted_data,
6678 &size, &offset);
6679 if (ret < 0)
6680 return ret;
6681 avio_write(pb, reformatted_data, size);
6682 } else {
6683 4 size = ff_av1_filter_obus(pb, pkt->data, pkt->size);
6684
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
4 if (trk->mode == MODE_AVIF && !mov->avif_extent_length[pkt->stream_index]) {
6685 mov->avif_extent_length[pkt->stream_index] = size;
6686 }
6687 }
6688
6689
2/2
✓ Branch 0 taken 16797 times.
✓ Branch 1 taken 387 times.
17184 } else if (par->codec_id == AV_CODEC_ID_AC3 ||
6690
2/2
✓ Branch 0 taken 652 times.
✓ Branch 1 taken 16145 times.
16797 par->codec_id == AV_CODEC_ID_EAC3) {
6691 1039 size = handle_eac3(mov, pkt, trk);
6692
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1039 times.
1039 if (size < 0)
6693 return size;
6694
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1038 times.
1039 else if (!size)
6695 1 goto end;
6696 1038 avio_write(pb, pkt->data, size);
6697
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16145 times.
16145 } else if (par->codec_id == AV_CODEC_ID_EIA_608) {
6698 size = 8;
6699
6700 for (int i = 0; i < pkt->size; i += 3) {
6701 if (pkt->data[i] == 0xFC) {
6702 size += 2;
6703 }
6704 }
6705 avio_wb32(pb, size);
6706 ffio_wfourcc(pb, "cdat");
6707 for (int i = 0; i < pkt->size; i += 3) {
6708 if (pkt->data[i] == 0xFC) {
6709 avio_w8(pb, pkt->data[i + 1]);
6710 avio_w8(pb, pkt->data[i + 2]);
6711 }
6712 }
6713 } else {
6714
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16145 times.
16145 if (trk->cenc.aes_ctr) {
6715 if (par->codec_id == AV_CODEC_ID_H264 && par->extradata_size > 4) {
6716 int nal_size_length = (par->extradata[4] & 0x3) + 1;
6717 ret = ff_mov_cenc_avc_write_nal_units(s, &trk->cenc, nal_size_length, pb, pkt->data, size);
6718 } else if(par->codec_id == AV_CODEC_ID_HEVC && par->extradata_size > 21) {
6719 int nal_size_length = (par->extradata[21] & 0x3) + 1;
6720 ret = ff_mov_cenc_avc_write_nal_units(s, &trk->cenc, nal_size_length, pb, pkt->data, size);
6721 } else if(par->codec_id == AV_CODEC_ID_VVC) {
6722 ret = AVERROR_PATCHWELCOME;
6723 } else {
6724 ret = ff_mov_cenc_write_packet(&trk->cenc, pb, pkt->data, size);
6725 }
6726
6727 if (ret) {
6728 goto err;
6729 }
6730 } else {
6731 16145 avio_write(pb, pkt->data, size);
6732 }
6733 }
6734
6735
2/2
✓ Branch 0 taken 265 times.
✓ Branch 1 taken 17524 times.
17789 if (trk->entry >= trk->cluster_capacity) {
6736 265 unsigned new_capacity = trk->entry + MOV_INDEX_CLUSTER_SIZE;
6737 265 void *cluster = av_realloc_array(trk->cluster, new_capacity, sizeof(*trk->cluster));
6738
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 265 times.
265 if (!cluster) {
6739 ret = AVERROR(ENOMEM);
6740 goto err;
6741 }
6742 265 trk->cluster = cluster;
6743 265 trk->cluster_capacity = new_capacity;
6744 }
6745
6746 17789 trk->cluster[trk->entry].pos = avio_tell(pb) - size;
6747 17789 trk->cluster[trk->entry].samples_in_chunk = samples_in_chunk;
6748 17789 trk->cluster[trk->entry].chunkNum = 0;
6749 17789 trk->cluster[trk->entry].size = size;
6750 17789 trk->cluster[trk->entry].entries = samples_in_chunk;
6751 17789 trk->cluster[trk->entry].dts = pkt->dts;
6752 17789 trk->cluster[trk->entry].pts = pkt->pts;
6753
2/2
✓ Branch 0 taken 17787 times.
✓ Branch 1 taken 2 times.
17789 if (!trk->squash_fragment_samples_to_one &&
6754
4/4
✓ Branch 0 taken 324 times.
✓ Branch 1 taken 17463 times.
✓ Branch 2 taken 75 times.
✓ Branch 3 taken 249 times.
17787 !trk->entry && trk->start_dts != AV_NOPTS_VALUE) {
6755
2/2
✓ Branch 0 taken 71 times.
✓ Branch 1 taken 4 times.
75 if (!trk->frag_discont) {
6756 /* First packet of a new fragment. We already wrote the duration
6757 * of the last packet of the previous fragment based on track_duration,
6758 * which might not exactly match our dts. Therefore adjust the dts
6759 * of this packet to be what the previous packets duration implies. */
6760 71 trk->cluster[trk->entry].dts = trk->start_dts + trk->track_duration;
6761 /* We also may have written the pts and the corresponding duration
6762 * in sidx/tfrf/tfxd tags; make sure the sidx pts and duration match up with
6763 * the next fragment. This means the cts of the first sample must
6764 * be the same in all fragments, unless end_pts was updated by
6765 * the packet causing the fragment to be written. */
6766
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 57 times.
71 if ((mov->flags & FF_MOV_FLAG_DASH &&
6767
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 !(mov->flags & (FF_MOV_FLAG_GLOBAL_SIDX | FF_MOV_FLAG_SKIP_SIDX))) ||
6768
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 47 times.
57 mov->mode == MODE_ISM)
6769 24 pkt->pts = pkt->dts + trk->end_pts - trk->cluster[trk->entry].dts;
6770 } else {
6771 /* New fragment, but discontinuous from previous fragments.
6772 * Pretend the duration sum of the earlier fragments is
6773 * pkt->dts - trk->start_dts. */
6774 4 trk->end_pts = AV_NOPTS_VALUE;
6775 4 trk->frag_discont = 0;
6776 }
6777 }
6778
6779
6/6
✓ Branch 0 taken 326 times.
✓ Branch 1 taken 17463 times.
✓ Branch 2 taken 251 times.
✓ Branch 3 taken 75 times.
✓ Branch 4 taken 30 times.
✓ Branch 5 taken 221 times.
17789 if (!trk->entry && trk->start_dts == AV_NOPTS_VALUE && !mov->use_editlist &&
6780
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 11 times.
30 s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO) {
6781 /* Not using edit lists and shifting the first track to start from zero.
6782 * If the other streams start from a later timestamp, we won't be able
6783 * to signal the difference in starting time without an edit list.
6784 * Thus move the timestamp for this first sample to 0, increasing
6785 * its duration instead. */
6786 19 trk->cluster[trk->entry].dts = trk->start_dts = 0;
6787 }
6788
2/2
✓ Branch 0 taken 232 times.
✓ Branch 1 taken 17557 times.
17789 if (trk->start_dts == AV_NOPTS_VALUE) {
6789 232 trk->start_dts = pkt->dts;
6790
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 226 times.
232 if (trk->frag_discont) {
6791
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 if (mov->use_editlist) {
6792 /* Pretend the whole stream started at pts=0, with earlier fragments
6793 * already written. If the stream started at pts=0, the duration sum
6794 * of earlier fragments would have been pkt->pts. */
6795 4 trk->start_dts = pkt->dts - pkt->pts;
6796 } else {
6797 /* Pretend the whole stream started at dts=0, with earlier fragments
6798 * already written, with a duration summing up to pkt->dts. */
6799 2 trk->start_dts = 0;
6800 }
6801 6 trk->frag_discont = 0;
6802
4/4
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 194 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 30 times.
226 } else if (pkt->dts && mov->moov_written)
6803 2 av_log(s, AV_LOG_WARNING,
6804 "Track %d starts with a nonzero dts %"PRId64", while the moov "
6805 "already has been written. Set the delay_moov flag to handle "
6806 "this case.\n",
6807 pkt->stream_index, pkt->dts);
6808 }
6809 17789 trk->track_duration = pkt->dts - trk->start_dts + pkt->duration;
6810 17789 trk->last_sample_is_subtitle_end = 0;
6811
6812
2/2
✓ Branch 0 taken 602 times.
✓ Branch 1 taken 17187 times.
17789 if (pkt->pts == AV_NOPTS_VALUE) {
6813 602 av_log(s, AV_LOG_WARNING, "pts has no value\n");
6814 602 pkt->pts = pkt->dts;
6815 }
6816
2/2
✓ Branch 0 taken 1001 times.
✓ Branch 1 taken 16788 times.
17789 if (pkt->dts != pkt->pts)
6817 1001 trk->flags |= MOV_TRACK_CTTS;
6818 17789 trk->cluster[trk->entry].cts = pkt->pts - pkt->dts;
6819 17789 trk->cluster[trk->entry].flags = 0;
6820
2/2
✓ Branch 0 taken 251 times.
✓ Branch 1 taken 17538 times.
17789 if (trk->start_cts == AV_NOPTS_VALUE)
6821 251 trk->start_cts = pkt->pts - pkt->dts;
6822
2/2
✓ Branch 0 taken 255 times.
✓ Branch 1 taken 17534 times.
17789 if (trk->end_pts == AV_NOPTS_VALUE)
6823 255 trk->end_pts = trk->cluster[trk->entry].dts +
6824 255 trk->cluster[trk->entry].cts + pkt->duration;
6825 else
6826 17534 trk->end_pts = FFMAX(trk->end_pts, trk->cluster[trk->entry].dts +
6827 trk->cluster[trk->entry].cts +
6828 pkt->duration);
6829
6830
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17789 times.
17789 if (par->codec_id == AV_CODEC_ID_VC1) {
6831 mov_parse_vc1_frame(pkt, trk);
6832
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17789 times.
17789 } else if (par->codec_id == AV_CODEC_ID_TRUEHD) {
6833 mov_parse_truehd_frame(pkt, trk);
6834
2/2
✓ Branch 0 taken 13242 times.
✓ Branch 1 taken 4547 times.
17789 } else if (pkt->flags & AV_PKT_FLAG_KEY) {
6835
4/4
✓ Branch 0 taken 6155 times.
✓ Branch 1 taken 7087 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 6146 times.
13242 if (mov->mode == MODE_MOV && par->codec_id == AV_CODEC_ID_MPEG2VIDEO &&
6836
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
9 trk->entry > 0) { // force sync sample for the first key frame
6837 8 mov_parse_mpeg2_frame(pkt, &trk->cluster[trk->entry].flags);
6838
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (trk->cluster[trk->entry].flags & MOV_PARTIAL_SYNC_SAMPLE)
6839 trk->flags |= MOV_TRACK_STPS;
6840 } else {
6841 13234 trk->cluster[trk->entry].flags = MOV_SYNC_SAMPLE;
6842 }
6843
1/2
✓ Branch 0 taken 13242 times.
✗ Branch 1 not taken.
13242 if (trk->cluster[trk->entry].flags & MOV_SYNC_SAMPLE)
6844 13242 trk->has_keyframes++;
6845 }
6846
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 17782 times.
17789 if (pkt->flags & AV_PKT_FLAG_DISPOSABLE) {
6847 7 trk->cluster[trk->entry].flags |= MOV_DISPOSABLE_SAMPLE;
6848 7 trk->has_disposable++;
6849 }
6850
6851 17789 prft = (AVProducerReferenceTime *)av_packet_get_side_data(pkt, AV_PKT_DATA_PRFT, &prft_size);
6852
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 17789 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
17789 if (prft && prft_size == sizeof(AVProducerReferenceTime))
6853 memcpy(&trk->cluster[trk->entry].prft, prft, prft_size);
6854 else
6855 17789 memset(&trk->cluster[trk->entry].prft, 0, sizeof(AVProducerReferenceTime));
6856
6857 17789 trk->entry++;
6858 17789 trk->sample_count += samples_in_chunk;
6859 17789 mov->mdat_size += size;
6860
6861
3/4
✓ Branch 0 taken 17707 times.
✓ Branch 1 taken 82 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 82 times.
17789 if (trk->hint_track >= 0 && trk->hint_track < mov->nb_tracks)
6862 82 ff_mov_add_hinted_packet(s, pkt, trk->hint_track, trk->entry,
6863
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 82 times.
82 reformatted_data ? reformatted_data + offset
6864 : NULL, size);
6865
6866 17790 end:
6867 17790 err:
6868
6869
1/2
✓ Branch 0 taken 17790 times.
✗ Branch 1 not taken.
17790 if (pkt->data != reformatted_data)
6870 17790 av_free(reformatted_data);
6871 17790 return ret;
6872 }
6873
6874 17752 static int mov_write_single_packet(AVFormatContext *s, AVPacket *pkt)
6875 {
6876 17752 MOVMuxContext *mov = s->priv_data;
6877 17752 MOVTrack *trk = s->streams[pkt->stream_index]->priv_data;
6878 17752 AVCodecParameters *par = trk->par;
6879 17752 int64_t frag_duration = 0;
6880 17752 int size = pkt->size;
6881
6882 17752 int ret = check_pkt(s, trk, pkt);
6883
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17752 times.
17752 if (ret < 0)
6884 return ret;
6885
6886
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 17747 times.
17752 if (mov->flags & FF_MOV_FLAG_FRAG_DISCONT) {
6887
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 5 times.
15 for (int i = 0; i < mov->nb_streams; i++)
6888 10 mov->tracks[i].frag_discont = 1;
6889 5 mov->flags &= ~FF_MOV_FLAG_FRAG_DISCONT;
6890 }
6891
6892
2/2
✓ Branch 0 taken 810 times.
✓ Branch 1 taken 16942 times.
17752 if (mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS) {
6893
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 799 times.
810 if (trk->dts_shift == AV_NOPTS_VALUE)
6894 11 trk->dts_shift = pkt->pts - pkt->dts;
6895 810 pkt->dts += trk->dts_shift;
6896 }
6897
6898
1/2
✓ Branch 0 taken 17752 times.
✗ Branch 1 not taken.
17752 if (trk->par->codec_id == AV_CODEC_ID_MP4ALS ||
6899
2/2
✓ Branch 0 taken 12210 times.
✓ Branch 1 taken 5542 times.
17752 trk->par->codec_id == AV_CODEC_ID_AAC ||
6900
2/2
✓ Branch 0 taken 12206 times.
✓ Branch 1 taken 4 times.
12210 trk->par->codec_id == AV_CODEC_ID_AV1 ||
6901
2/2
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 12162 times.
12206 trk->par->codec_id == AV_CODEC_ID_FLAC) {
6902 size_t side_size;
6903 5590 uint8_t *side = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size);
6904
6/8
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5585 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
5590 if (side && side_size > 0 && (side_size != par->extradata_size || memcmp(side, par->extradata, side_size))) {
6905 5 void *newextra = av_mallocz(side_size + AV_INPUT_BUFFER_PADDING_SIZE);
6906
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!newextra)
6907 return AVERROR(ENOMEM);
6908 5 av_free(par->extradata);
6909 5 par->extradata = newextra;
6910 5 memcpy(par->extradata, side, side_size);
6911 5 par->extradata_size = side_size;
6912
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
5 if (!pkt->size) // Flush packet
6913 4 mov->need_rewrite_extradata = 1;
6914 }
6915 }
6916
6917
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 17744 times.
17752 if (!pkt->size) {
6918
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
8 if (trk->start_dts == AV_NOPTS_VALUE && trk->frag_discont) {
6919 4 trk->start_dts = pkt->dts;
6920
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (pkt->pts != AV_NOPTS_VALUE)
6921 4 trk->start_cts = pkt->pts - pkt->dts;
6922 else
6923 trk->start_cts = 0;
6924 }
6925
6926 8 return 0; /* Discard 0 sized packets */
6927 }
6928
6929
3/4
✓ Branch 0 taken 17453 times.
✓ Branch 1 taken 291 times.
✓ Branch 2 taken 17453 times.
✗ Branch 3 not taken.
17744 if (trk->entry && pkt->stream_index < mov->nb_streams)
6930 17453 frag_duration = av_rescale_q(pkt->dts - trk->cluster[0].dts,
6931 17453 s->streams[pkt->stream_index]->time_base,
6932 17453 AV_TIME_BASE_Q);
6933
2/2
✓ Branch 0 taken 173 times.
✓ Branch 1 taken 17571 times.
17744 if ((mov->max_fragment_duration &&
6934
2/2
✓ Branch 0 taken 170 times.
✓ Branch 1 taken 3 times.
173 frag_duration >= mov->max_fragment_duration) ||
6935
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 17741 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
17741 (mov->max_fragment_size && mov->mdat_size + size >= mov->max_fragment_size) ||
6936
2/2
✓ Branch 0 taken 3673 times.
✓ Branch 1 taken 14068 times.
17741 (mov->flags & FF_MOV_FLAG_FRAG_KEYFRAME &&
6937
2/2
✓ Branch 0 taken 1125 times.
✓ Branch 1 taken 2548 times.
3673 par->codec_type == AVMEDIA_TYPE_VIDEO &&
6938
4/4
✓ Branch 0 taken 1101 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 1076 times.
✓ Branch 3 taken 25 times.
1125 trk->entry && pkt->flags & AV_PKT_FLAG_KEY) ||
6939
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17716 times.
17716 (mov->flags & FF_MOV_FLAG_FRAG_EVERY_FRAME)) {
6940
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 if (frag_duration >= mov->min_fragment_duration) {
6941
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 if (trk->entry) {
6942 // Set the duration of this track to line up with the next
6943 // sample in this track. This avoids relying on AVPacket
6944 // duration, but only helps for this particular track, not
6945 // for the other ones that are flushed at the same time.
6946 //
6947 // If we have trk->entry == 0, no fragment will be written
6948 // for this track, and we can't adjust the track end here.
6949 28 trk->track_duration = pkt->dts - trk->start_dts;
6950
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 if (pkt->pts != AV_NOPTS_VALUE)
6951 28 trk->end_pts = pkt->pts;
6952 else
6953 trk->end_pts = pkt->dts;
6954 28 trk->end_reliable = 1;
6955 }
6956 28 mov_auto_flush_fragment(s, 0);
6957 }
6958 }
6959
6960 17744 return ff_mov_write_packet(s, pkt);
6961 }
6962
6963 3 static int mov_write_subtitle_end_packet(AVFormatContext *s,
6964 int stream_index,
6965 int64_t dts) {
6966 3 MOVMuxContext *mov = s->priv_data;
6967 3 AVPacket *end = mov->pkt;
6968 3 uint8_t data[2] = {0};
6969 int ret;
6970
6971 3 end->size = sizeof(data);
6972 3 end->data = data;
6973 3 end->pts = dts;
6974 3 end->dts = dts;
6975 3 end->duration = 0;
6976 3 end->stream_index = stream_index;
6977
6978 3 ret = mov_write_single_packet(s, end);
6979 3 av_packet_unref(end);
6980
6981 3 return ret;
6982 }
6983
6984 #if CONFIG_IAMFENC
6985 198 static int mov_build_iamf_packet(AVFormatContext *s, MOVTrack *trk, AVPacket *pkt)
6986 {
6987 uint8_t *data;
6988 int ret;
6989
6990
2/2
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 154 times.
198 if (pkt->stream_index == trk->first_iamf_idx) {
6991 44 ret = ff_iamf_write_parameter_blocks(trk->iamf, trk->iamf_buf, pkt, s);
6992
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (ret < 0)
6993 return ret;
6994 }
6995
6996 198 ret = ff_iamf_write_audio_frame(trk->iamf, trk->iamf_buf,
6997 198 s->streams[pkt->stream_index]->id, pkt);
6998
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 198 times.
198 if (ret < 0)
6999 return ret;
7000
7001
2/2
✓ Branch 0 taken 154 times.
✓ Branch 1 taken 44 times.
198 if (pkt->stream_index != trk->last_iamf_idx)
7002 154 return AVERROR(EAGAIN);
7003
7004 44 ret = avio_close_dyn_buf(trk->iamf_buf, &data);
7005 44 trk->iamf_buf = NULL;
7006
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 40 times.
44 if (!ret) {
7007
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (pkt->size) {
7008 // Either all or none of the packets for a single
7009 // IA Sample may be empty.
7010 av_log(s, AV_LOG_ERROR, "Unexpected packet from "
7011 "stream #%d\n", pkt->stream_index);
7012 ret = AVERROR_INVALIDDATA;
7013 }
7014 4 av_free(data);
7015 4 return ret;
7016 }
7017
7018 40 av_buffer_unref(&pkt->buf);
7019 40 pkt->buf = av_buffer_create(data, ret, NULL, NULL, 0);
7020
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 if (!pkt->buf) {
7021 av_free(data);
7022 return AVERROR(ENOMEM);
7023 }
7024 40 pkt->data = data;
7025 40 pkt->size = ret;
7026 40 pkt->stream_index = trk->first_iamf_idx;
7027
7028 40 return avio_open_dyn_buf(&trk->iamf_buf);
7029 }
7030 #endif
7031
7032 2 static int mov_write_emsg_tag(AVIOContext *pb, AVStream *st, AVPacket *pkt)
7033 {
7034 2 int64_t pos = avio_tell(pb);
7035 2 const char *scheme_id_uri = "https://aomedia.org/emsg/ID3";
7036 2 const char *value = "";
7037
7038
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 av_assert0(st->time_base.num == 1);
7039
7040 2 avio_write_marker(pb,
7041 2 av_rescale_q(pkt->pts, st->time_base, AV_TIME_BASE_Q),
7042 AVIO_DATA_MARKER_BOUNDARY_POINT);
7043
7044 2 avio_wb32(pb, 0); /* size */
7045 2 ffio_wfourcc(pb, "emsg");
7046 2 avio_w8(pb, 1); /* version */
7047 2 avio_wb24(pb, 0);
7048 2 avio_wb32(pb, st->time_base.den); /* timescale */
7049 2 avio_wb64(pb, pkt->pts); /* presentation_time */
7050 2 avio_wb32(pb, 0xFFFFFFFFU); /* event_duration */
7051 2 avio_wb32(pb, 0); /* id */
7052 /* null terminated UTF8 strings */
7053 2 avio_write(pb, scheme_id_uri, strlen(scheme_id_uri) + 1);
7054 2 avio_write(pb, value, strlen(value) + 1);
7055 2 avio_write(pb, pkt->data, pkt->size);
7056
7057 2 return update_size(pb, pos);
7058 }
7059
7060 18014 static int mov_write_packet(AVFormatContext *s, AVPacket *pkt)
7061 {
7062 18014 MOVMuxContext *mov = s->priv_data;
7063 MOVTrack *trk;
7064
7065
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 17979 times.
18014 if (!pkt) {
7066 35 mov_flush_fragment(s, 1);
7067 35 return 1;
7068 }
7069
7070
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 17977 times.
17979 if (s->streams[pkt->stream_index]->codecpar->codec_id == AV_CODEC_ID_TIMED_ID3) {
7071 2 mov_write_emsg_tag(s->pb, s->streams[pkt->stream_index], pkt);
7072 2 return 0;
7073 }
7074
7075 17977 trk = s->streams[pkt->stream_index]->priv_data;
7076
7077 #if CONFIG_IAMFENC
7078
2/2
✓ Branch 0 taken 198 times.
✓ Branch 1 taken 17779 times.
17977 if (trk->iamf) {
7079 198 int ret = mov_build_iamf_packet(s, trk, pkt);
7080
2/2
✓ Branch 0 taken 154 times.
✓ Branch 1 taken 44 times.
198 if (ret < 0) {
7081
1/2
✓ Branch 0 taken 154 times.
✗ Branch 1 not taken.
154 if (ret == AVERROR(EAGAIN))
7082 154 return 0;
7083 av_log(s, AV_LOG_ERROR, "Error assembling an IAMF packet "
7084 "for stream #%d\n", trk->st->index);
7085 return ret;
7086 }
7087 }
7088 #endif
7089
7090
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 17821 times.
17823 if (is_cover_image(trk->st)) {
7091 int ret;
7092
7093
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (trk->st->nb_frames >= 1) {
7094 if (trk->st->nb_frames == 1)
7095 av_log(s, AV_LOG_WARNING, "Got more than one picture in stream %d,"
7096 " ignoring.\n", pkt->stream_index);
7097 return 0;
7098 }
7099
7100
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if ((ret = av_packet_ref(trk->cover_image, pkt)) < 0)
7101 return ret;
7102
7103 2 return 0;
7104 } else {
7105 int i;
7106
7107
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 17813 times.
17821 if (!pkt->size)
7108 8 return mov_write_single_packet(s, pkt); /* Passthrough. */
7109
7110 /*
7111 * Subtitles require special handling.
7112 *
7113 * 1) For full complaince, every track must have a sample at
7114 * dts == 0, which is rarely true for subtitles. So, as soon
7115 * as we see any packet with dts > 0, write an empty subtitle
7116 * at dts == 0 for any subtitle track with no samples in it.
7117 *
7118 * 2) For each subtitle track, check if the current packet's
7119 * dts is past the duration of the last subtitle sample. If
7120 * so, we now need to write an end sample for that subtitle.
7121 *
7122 * This must be done conditionally to allow for subtitles that
7123 * immediately replace each other, in which case an end sample
7124 * is not needed, and is, in fact, actively harmful.
7125 *
7126 * 3) See mov_write_trailer for how the final end sample is
7127 * handled.
7128 */
7129
2/2
✓ Branch 0 taken 32481 times.
✓ Branch 1 taken 17813 times.
50294 for (i = 0; i < mov->nb_tracks; i++) {
7130 32481 MOVTrack *trk = &mov->tracks[i];
7131 int ret;
7132
7133
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 32478 times.
32481 if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT &&
7134
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 trk->track_duration < pkt->dts &&
7135
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)) {
7136 2 ret = mov_write_subtitle_end_packet(s, i, trk->track_duration);
7137
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0) return ret;
7138 2 trk->last_sample_is_subtitle_end = 1;
7139 }
7140 }
7141
7142
2/2
✓ Branch 0 taken 74 times.
✓ Branch 1 taken 17739 times.
17813 if (trk->squash_fragment_samples_to_one) {
7143 /*
7144 * If the track has to have its samples squashed into one sample,
7145 * we just take it into the track's queue.
7146 * This will then be utilized as the samples get written in either
7147 * mov_flush_fragment or when the mux is finalized in
7148 * mov_write_trailer.
7149 */
7150 74 int ret = AVERROR_BUG;
7151
7152
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 74 times.
74 if (pkt->pts == AV_NOPTS_VALUE) {
7153 av_log(s, AV_LOG_ERROR,
7154 "Packets without a valid presentation timestamp are "
7155 "not supported with packet squashing!\n");
7156 return AVERROR(EINVAL);
7157 }
7158
7159 /* The following will reset pkt and is only allowed to be used
7160 * because we return immediately. afterwards. */
7161
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 74 times.
74 if ((ret = avpriv_packet_list_put(&trk->squashed_packet_queue,
7162 pkt, NULL, 0)) < 0) {
7163 return ret;
7164 }
7165
7166 74 return 0;
7167 }
7168
7169
7170
4/4
✓ Branch 0 taken 7575 times.
✓ Branch 1 taken 10164 times.
✓ Branch 2 taken 3452 times.
✓ Branch 3 taken 4123 times.
17739 if (trk->mode == MODE_MOV && trk->par->codec_type == AVMEDIA_TYPE_VIDEO) {
7171 3452 AVPacket *opkt = pkt;
7172 int reshuffle_ret, ret;
7173
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 3427 times.
3452 if (trk->is_unaligned_qt_rgb) {
7174
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;
7175 25 int expected_stride = ((trk->par->width * bpc + 15) >> 4)*2;
7176 25 reshuffle_ret = ff_reshuffle_raw_rgb(s, &pkt, trk->par, expected_stride);
7177
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (reshuffle_ret < 0)
7178 return reshuffle_ret;
7179 } else
7180 3427 reshuffle_ret = 0;
7181
4/4
✓ Branch 0 taken 238 times.
✓ Branch 1 taken 3214 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 233 times.
3452 if (trk->par->format == AV_PIX_FMT_PAL8 && !trk->pal_done) {
7182 5 ret = ff_get_packet_palette(s, opkt, reshuffle_ret, trk->palette);
7183
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (ret < 0)
7184 goto fail;
7185
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (ret)
7186 5 trk->pal_done++;
7187
2/2
✓ Branch 0 taken 625 times.
✓ Branch 1 taken 2822 times.
3447 } else if (trk->par->codec_id == AV_CODEC_ID_RAWVIDEO &&
7188
1/2
✓ Branch 0 taken 625 times.
✗ Branch 1 not taken.
625 (trk->par->format == AV_PIX_FMT_GRAY8 ||
7189
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 625 times.
625 trk->par->format == AV_PIX_FMT_MONOBLACK)) {
7190 ret = av_packet_make_writable(pkt);
7191 if (ret < 0)
7192 goto fail;
7193 for (i = 0; i < pkt->size; i++)
7194 pkt->data[i] = ~pkt->data[i];
7195 }
7196
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3452 times.
3452 if (reshuffle_ret) {
7197 ret = mov_write_single_packet(s, pkt);
7198 fail:
7199 if (reshuffle_ret)
7200 av_packet_free(&pkt);
7201 return ret;
7202 }
7203 }
7204
7205 17739 return mov_write_single_packet(s, pkt);
7206 }
7207 }
7208
7209 // QuickTime chapters involve an additional text track with the chapter names
7210 // as samples, and a tref pointing from the other tracks to the chapter one.
7211 1 static int mov_create_chapter_track(AVFormatContext *s, int tracknum)
7212 {
7213 static const uint8_t stub_header[] = {
7214 // TextSampleEntry
7215 0x00, 0x00, 0x00, 0x01, // displayFlags
7216 0x00, 0x00, // horizontal + vertical justification
7217 0x00, 0x00, 0x00, 0x00, // bgColourRed/Green/Blue/Alpha
7218 // BoxRecord
7219 0x00, 0x00, 0x00, 0x00, // defTextBoxTop/Left
7220 0x00, 0x00, 0x00, 0x00, // defTextBoxBottom/Right
7221 // StyleRecord
7222 0x00, 0x00, 0x00, 0x00, // startChar + endChar
7223 0x00, 0x01, // fontID
7224 0x00, 0x00, // fontStyleFlags + fontSize
7225 0x00, 0x00, 0x00, 0x00, // fgColourRed/Green/Blue/Alpha
7226 // FontTableBox
7227 0x00, 0x00, 0x00, 0x0D, // box size
7228 'f', 't', 'a', 'b', // box atom name
7229 0x00, 0x01, // entry count
7230 // FontRecord
7231 0x00, 0x01, // font ID
7232 0x00, // font name length
7233 };
7234 1 MOVMuxContext *mov = s->priv_data;
7235 1 MOVTrack *track = &mov->tracks[tracknum];
7236 1 AVPacket *pkt = mov->pkt;
7237 int i, len;
7238 int ret;
7239
7240 1 track->mode = mov->mode;
7241 1 track->tag = MKTAG('t','e','x','t');
7242 1 track->timescale = mov->movie_timescale;
7243 1 track->par = avcodec_parameters_alloc();
7244
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!track->par)
7245 return AVERROR(ENOMEM);
7246 1 track->par->codec_type = AVMEDIA_TYPE_SUBTITLE;
7247 1 ret = ff_alloc_extradata(track->par, sizeof(stub_header));
7248
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
7249 return ret;
7250 1 memcpy(track->par->extradata, stub_header, sizeof(stub_header));
7251
7252 1 pkt->stream_index = tracknum;
7253 1 pkt->flags = AV_PKT_FLAG_KEY;
7254
7255
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
5 for (i = 0; i < s->nb_chapters; i++) {
7256 4 AVChapter *c = s->chapters[i];
7257 AVDictionaryEntry *t;
7258
7259 4 int64_t end = av_rescale_q(c->end, c->time_base, (AVRational){1,mov->movie_timescale});
7260 4 pkt->pts = pkt->dts = av_rescale_q(c->start, c->time_base, (AVRational){1,mov->movie_timescale});
7261 4 pkt->duration = end - pkt->dts;
7262
7263
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 if ((t = av_dict_get(c->metadata, "title", NULL, 0))) {
7264 static const char encd[12] = {
7265 0x00, 0x00, 0x00, 0x0C,
7266 'e', 'n', 'c', 'd',
7267 0x00, 0x00, 0x01, 0x00 };
7268 4 len = strlen(t->value);
7269 4 pkt->size = len + 2 + 12;
7270 4 pkt->data = av_malloc(pkt->size);
7271
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!pkt->data) {
7272 av_packet_unref(pkt);
7273 return AVERROR(ENOMEM);
7274 }
7275 4 AV_WB16(pkt->data, len);
7276 4 memcpy(pkt->data + 2, t->value, len);
7277 4 memcpy(pkt->data + len + 2, encd, sizeof(encd));
7278 4 ff_mov_write_packet(s, pkt);
7279 4 av_freep(&pkt->data);
7280 }
7281 }
7282
7283 1 av_packet_unref(mov->pkt);
7284
7285 1 return 0;
7286 }
7287
7288
7289 13 static int mov_check_timecode_track(AVFormatContext *s, AVTimecode *tc, AVStream *src_st, const char *tcstr)
7290 {
7291 int ret;
7292
7293 /* compute the frame number */
7294 13 ret = av_timecode_init_from_string(tc, src_st->avg_frame_rate, tcstr, s);
7295 13 return ret;
7296 }
7297
7298 6 static int mov_create_timecode_track(AVFormatContext *s, int index, int src_index, AVTimecode tc)
7299 {
7300 6 MOVMuxContext *mov = s->priv_data;
7301 6 MOVTrack *track = &mov->tracks[index];
7302 6 AVStream *src_st = mov->tracks[src_index].st;
7303 uint8_t data[4];
7304 6 AVPacket *pkt = mov->pkt;
7305 6 AVRational rate = src_st->avg_frame_rate;
7306 int ret;
7307
7308 /* tmcd track based on video stream */
7309 6 track->mode = mov->mode;
7310 6 track->tag = MKTAG('t','m','c','d');
7311 6 track->src_track = src_index;
7312 6 track->timescale = mov->tracks[src_index].timescale;
7313
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (tc.flags & AV_TIMECODE_FLAG_DROPFRAME)
7314 3 track->timecode_flags |= MOV_TIMECODE_FLAG_DROPFRAME;
7315
7316 /* set st to src_st for metadata access*/
7317 6 track->st = src_st;
7318
7319 /* encode context: tmcd data stream */
7320 6 track->par = avcodec_parameters_alloc();
7321
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!track->par)
7322 return AVERROR(ENOMEM);
7323 6 track->par->codec_type = AVMEDIA_TYPE_DATA;
7324 6 track->par->codec_tag = track->tag;
7325 6 track->st->avg_frame_rate = rate;
7326
7327 /* the tmcd track just contains one packet with the frame number */
7328 6 pkt->data = data;
7329 6 pkt->stream_index = index;
7330 6 pkt->flags = AV_PKT_FLAG_KEY;
7331 6 pkt->pts = pkt->dts = av_rescale_q(tc.start, av_inv_q(rate), (AVRational){1,mov->movie_timescale});
7332 6 pkt->size = 4;
7333 6 AV_WB32(pkt->data, tc.start);
7334 6 ret = ff_mov_write_packet(s, pkt);
7335 6 av_packet_unref(pkt);
7336 6 return ret;
7337 }
7338
7339 /*
7340 * st->disposition controls the "enabled" flag in the tkhd tag.
7341 * QuickTime will not play a track if it is not enabled. So make sure
7342 * that one track of each type (audio, video, subtitle) is enabled.
7343 *
7344 * Subtitles are special. For audio and video, setting "enabled" also
7345 * makes the track "default" (i.e. it is rendered when played). For
7346 * subtitles, an "enabled" subtitle is not rendered by default, but
7347 * if no subtitle is enabled, the subtitle menu in QuickTime will be
7348 * empty!
7349 */
7350 203 static void enable_tracks(AVFormatContext *s)
7351 {
7352 203 MOVMuxContext *mov = s->priv_data;
7353 int i;
7354 int enabled[AVMEDIA_TYPE_NB];
7355 int first[AVMEDIA_TYPE_NB];
7356
7357
2/2
✓ Branch 0 taken 1015 times.
✓ Branch 1 taken 203 times.
1218 for (i = 0; i < AVMEDIA_TYPE_NB; i++) {
7358 1015 enabled[i] = 0;
7359 1015 first[i] = -1;
7360 }
7361
7362
2/2
✓ Branch 0 taken 259 times.
✓ Branch 1 taken 203 times.
462 for (i = 0; i < mov->nb_streams; i++) {
7363 259 AVStream *st = mov->tracks[i].st;
7364
7365
1/2
✓ Branch 0 taken 259 times.
✗ Branch 1 not taken.
259 if (st->codecpar->codec_type <= AVMEDIA_TYPE_UNKNOWN ||
7366
3/4
✓ Branch 0 taken 259 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 257 times.
518 st->codecpar->codec_type >= AVMEDIA_TYPE_NB ||
7367 259 is_cover_image(st))
7368 2 continue;
7369
7370
2/2
✓ Branch 0 taken 243 times.
✓ Branch 1 taken 14 times.
257 if (first[st->codecpar->codec_type] < 0)
7371 243 first[st->codecpar->codec_type] = i;
7372
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 229 times.
257 if (st->disposition & AV_DISPOSITION_DEFAULT) {
7373 28 mov->tracks[i].flags |= MOV_TRACK_ENABLED;
7374 28 enabled[st->codecpar->codec_type]++;
7375 }
7376 }
7377
7378
2/2
✓ Branch 0 taken 1015 times.
✓ Branch 1 taken 203 times.
1218 for (i = 0; i < AVMEDIA_TYPE_NB; i++) {
7379
2/2
✓ Branch 0 taken 609 times.
✓ Branch 1 taken 406 times.
1015 switch (i) {
7380 609 case AVMEDIA_TYPE_VIDEO:
7381 case AVMEDIA_TYPE_AUDIO:
7382 case AVMEDIA_TYPE_SUBTITLE:
7383
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 609 times.
609 if (enabled[i] > 1)
7384 mov->per_stream_grouping = 1;
7385
4/4
✓ Branch 0 taken 585 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 217 times.
✓ Branch 3 taken 368 times.
609 if (!enabled[i] && first[i] >= 0)
7386 217 mov->tracks[first[i]].flags |= MOV_TRACK_ENABLED;
7387 609 break;
7388 }
7389 }
7390 203 }
7391
7392 203 static void mov_free(AVFormatContext *s)
7393 {
7394 203 MOVMuxContext *mov = s->priv_data;
7395
7396
2/2
✓ Branch 0 taken 274 times.
✓ Branch 1 taken 203 times.
477 for (int i = 0; i < s->nb_streams; i++)
7397 274 s->streams[i]->priv_data = NULL;
7398
7399
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 203 times.
203 if (!mov->tracks)
7400 return;
7401
7402
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 202 times.
203 if (mov->chapter_track) {
7403 1 avcodec_parameters_free(&mov->tracks[mov->chapter_track].par);
7404 }
7405
7406
2/2
✓ Branch 0 taken 268 times.
✓ Branch 1 taken 203 times.
471 for (int i = 0; i < mov->nb_tracks; i++) {
7407 268 MOVTrack *const track = &mov->tracks[i];
7408
7409
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 266 times.
268 if (track->tag == MKTAG('r','t','p',' '))
7410 2 ff_mov_close_hinting(track);
7411
4/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 257 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 3 times.
266 else if (track->tag == MKTAG('t','m','c','d') && mov->nb_meta_tmcd)
7412 6 av_freep(&track->par);
7413 268 av_freep(&track->cluster);
7414 268 av_freep(&track->cluster_written);
7415 268 av_freep(&track->frag_info);
7416 268 av_packet_free(&track->cover_image);
7417
7418
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 263 times.
268 if (track->eac3_priv) {
7419 5 struct eac3_info *info = track->eac3_priv;
7420 5 av_packet_free(&info->pkt);
7421 5 av_freep(&track->eac3_priv);
7422 }
7423
2/2
✓ Branch 0 taken 139 times.
✓ Branch 1 taken 129 times.
268 if (track->vos_len)
7424 139 av_freep(&track->vos_data);
7425
7426 268 ff_mov_cenc_free(&track->cenc);
7427 268 ffio_free_dyn_buf(&track->mdat_buf);
7428
7429 #if CONFIG_IAMFENC
7430 268 ffio_free_dyn_buf(&track->iamf_buf);
7431
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 264 times.
268 if (track->iamf)
7432 4 ff_iamf_uninit_context(track->iamf);
7433 268 av_freep(&track->iamf);
7434 #endif
7435
7436 268 avpriv_packet_list_free(&track->squashed_packet_queue);
7437 }
7438
7439 203 av_freep(&mov->tracks);
7440 203 ffio_free_dyn_buf(&mov->mdat_buf);
7441 }
7442
7443 static uint32_t rgb_to_yuv(uint32_t rgb)
7444 {
7445 uint8_t r, g, b;
7446 int y, cb, cr;
7447
7448 r = (rgb >> 16) & 0xFF;
7449 g = (rgb >> 8) & 0xFF;
7450 b = (rgb ) & 0xFF;
7451
7452 y = av_clip_uint8(( 16000 + 257 * r + 504 * g + 98 * b)/1000);
7453 cb = av_clip_uint8((128000 - 148 * r - 291 * g + 439 * b)/1000);
7454 cr = av_clip_uint8((128000 + 439 * r - 368 * g - 71 * b)/1000);
7455
7456 return (y << 16) | (cr << 8) | cb;
7457 }
7458
7459 static int mov_create_dvd_sub_decoder_specific_info(MOVTrack *track,
7460 AVStream *st)
7461 {
7462 int i, width = 720, height = 480;
7463 int have_palette = 0, have_size = 0;
7464 uint32_t palette[16];
7465 char *cur = st->codecpar->extradata;
7466
7467 while (cur && *cur) {
7468 if (strncmp("palette:", cur, 8) == 0) {
7469 int i, count;
7470 count = sscanf(cur + 8,
7471 "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32", "
7472 "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32", "
7473 "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32", "
7474 "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32"",
7475 &palette[ 0], &palette[ 1], &palette[ 2], &palette[ 3],
7476 &palette[ 4], &palette[ 5], &palette[ 6], &palette[ 7],
7477 &palette[ 8], &palette[ 9], &palette[10], &palette[11],
7478 &palette[12], &palette[13], &palette[14], &palette[15]);
7479
7480 for (i = 0; i < count; i++) {
7481 palette[i] = rgb_to_yuv(palette[i]);
7482 }
7483 have_palette = 1;
7484 } else if (!strncmp("size:", cur, 5)) {
7485 sscanf(cur + 5, "%dx%d", &width, &height);
7486 have_size = 1;
7487 }
7488 if (have_palette && have_size)
7489 break;
7490 cur += strcspn(cur, "\n\r");
7491 cur += strspn(cur, "\n\r");
7492 }
7493 if (have_palette) {
7494 track->vos_data = av_malloc(16*4 + AV_INPUT_BUFFER_PADDING_SIZE);
7495 if (!track->vos_data)
7496 return AVERROR(ENOMEM);
7497 for (i = 0; i < 16; i++) {
7498 AV_WB32(track->vos_data + i * 4, palette[i]);
7499 }
7500 memset(track->vos_data + 16*4, 0, AV_INPUT_BUFFER_PADDING_SIZE);
7501 track->vos_len = 16 * 4;
7502 }
7503 st->codecpar->width = width;
7504 st->codecpar->height = track->height = height;
7505
7506 return 0;
7507 }
7508
7509 #if CONFIG_IAMFENC
7510 203 static int mov_init_iamf_track(AVFormatContext *s)
7511 {
7512 203 MOVMuxContext *mov = s->priv_data;
7513 203 MOVTrack *track = &mov->tracks[0]; // IAMF if present is always the first track
7514 203 int nb_audio_elements = 0, nb_mix_presentations = 0;
7515 int ret;
7516
7517
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 203 times.
211 for (int i = 0; i < s->nb_stream_groups; i++) {
7518 8 const AVStreamGroup *stg = s->stream_groups[i];
7519
7520
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 if (stg->type == AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
7521 4 nb_audio_elements++;
7522
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 if (stg->type == AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION)
7523 4 nb_mix_presentations++;
7524 }
7525
7526
3/4
✓ Branch 0 taken 199 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 199 times.
✗ Branch 3 not taken.
203 if (!nb_audio_elements && !nb_mix_presentations)
7527 199 return 0;
7528
7529
3/6
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
4 if (nb_audio_elements < 1 || nb_audio_elements > 2 || nb_mix_presentations < 1) {
7530 av_log(s, AV_LOG_ERROR, "There must be >= 1 and <= 2 IAMF_AUDIO_ELEMENT and at least "
7531 "one IAMF_MIX_PRESENTATION stream groups to write a IMAF track\n");
7532 return AVERROR(EINVAL);
7533 }
7534
7535 4 track->iamf = av_mallocz(sizeof(*track->iamf));
7536
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!track->iamf)
7537 return AVERROR(ENOMEM);
7538
7539
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 for (int i = 0; i < s->nb_stream_groups; i++) {
7540 8 const AVStreamGroup *stg = s->stream_groups[i];
7541
2/3
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
8 switch(stg->type) {
7542 4 case AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT:
7543
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 4 times.
22 for (int j = 0; j < stg->nb_streams; j++) {
7544 18 track->first_iamf_idx = FFMIN(stg->streams[j]->index, track->first_iamf_idx);
7545 18 track->last_iamf_idx = FFMAX(stg->streams[j]->index, track->last_iamf_idx);
7546 18 stg->streams[j]->priv_data = track;
7547 }
7548
7549 4 ret = ff_iamf_add_audio_element(track->iamf, stg, s);
7550 4 break;
7551 4 case AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION:
7552 4 ret = ff_iamf_add_mix_presentation(track->iamf, stg, s);
7553 4 break;
7554 default:
7555 av_assert0(0);
7556 }
7557
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (ret < 0)
7558 return ret;
7559 }
7560
7561 4 track->tag = MKTAG('i','a','m','f');
7562
7563 4 ret = avio_open_dyn_buf(&track->iamf_buf);
7564
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0)
7565 return ret;
7566
7567 4 return 0;
7568 }
7569 #endif
7570
7571 203 static int mov_init(AVFormatContext *s)
7572 {
7573 203 MOVMuxContext *mov = s->priv_data;
7574 int i, ret;
7575
7576 203 mov->fc = s;
7577 203 mov->pkt = ffformatcontext(s)->pkt;
7578
7579 /* Default mode == MP4 */
7580 203 mov->mode = MODE_MP4;
7581
7582 #define IS_MODE(muxer, config) (CONFIG_ ## config ## _MUXER && !strcmp(#muxer, s->oformat->name))
7583
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 203 times.
203 if (IS_MODE(3gp, TGP)) mov->mode = MODE_3GP;
7584
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 203 times.
203 else if (IS_MODE(3g2, TG2)) mov->mode = MODE_3GP|MODE_3G2;
7585
2/2
✓ Branch 0 taken 141 times.
✓ Branch 1 taken 62 times.
203 else if (IS_MODE(mov, MOV)) mov->mode = MODE_MOV;
7586
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 61 times.
62 else if (IS_MODE(psp, PSP)) mov->mode = MODE_PSP;
7587
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 60 times.
61 else if (IS_MODE(ipod, IPOD)) mov->mode = MODE_IPOD;
7588
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 56 times.
60 else if (IS_MODE(ismv, ISMV)) mov->mode = MODE_ISM;
7589
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
56 else if (IS_MODE(f4v, F4V)) mov->mode = MODE_F4V;
7590
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
56 else if (IS_MODE(avif, AVIF)) mov->mode = MODE_AVIF;
7591 #undef IS_MODE
7592
7593
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 186 times.
203 if (mov->flags & FF_MOV_FLAG_DELAY_MOOV)
7594 17 mov->flags |= FF_MOV_FLAG_EMPTY_MOOV;
7595
7596
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 203 times.
203 if (mov->mode == MODE_AVIF)
7597 mov->flags |= FF_MOV_FLAG_DELAY_MOOV;
7598
7599 /* Set the FRAGMENT flag if any of the fragmentation methods are
7600 * enabled. */
7601
3/4
✓ Branch 0 taken 202 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 202 times.
✗ Branch 3 not taken.
203 if (mov->max_fragment_duration || mov->max_fragment_size ||
7602
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 173 times.
202 mov->flags & (FF_MOV_FLAG_EMPTY_MOOV |
7603 FF_MOV_FLAG_FRAG_KEYFRAME |
7604 FF_MOV_FLAG_FRAG_CUSTOM |
7605 FF_MOV_FLAG_FRAG_EVERY_FRAME))
7606 30 mov->flags |= FF_MOV_FLAG_FRAGMENT;
7607
7608 /* Set other implicit flags immediately */
7609
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 202 times.
203 if (mov->flags & FF_MOV_FLAG_HYBRID_FRAGMENTED)
7610 1 mov->flags |= FF_MOV_FLAG_FRAGMENT;
7611
7612
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 199 times.
203 if (mov->mode == MODE_ISM)
7613 4 mov->flags |= FF_MOV_FLAG_EMPTY_MOOV | FF_MOV_FLAG_SEPARATE_MOOF |
7614 FF_MOV_FLAG_FRAGMENT | FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS;
7615
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 192 times.
203 if (mov->flags & FF_MOV_FLAG_DASH)
7616 11 mov->flags |= FF_MOV_FLAG_FRAGMENT | FF_MOV_FLAG_EMPTY_MOOV |
7617 FF_MOV_FLAG_DEFAULT_BASE_MOOF;
7618
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 202 times.
203 if (mov->flags & FF_MOV_FLAG_CMAF)
7619 1 mov->flags |= FF_MOV_FLAG_FRAGMENT | FF_MOV_FLAG_EMPTY_MOOV |
7620 FF_MOV_FLAG_DEFAULT_BASE_MOOF | FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS;
7621
7622
4/4
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 173 times.
✓ Branch 2 taken 29 times.
✓ Branch 3 taken 1 times.
203 if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV && s->flags & AVFMT_FLAG_AUTO_BSF) {
7623 29 av_log(s, AV_LOG_VERBOSE, "Empty MOOV enabled; disabling automatic bitstream filtering\n");
7624 29 s->flags &= ~AVFMT_FLAG_AUTO_BSF;
7625 }
7626
7627
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 203 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
203 if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX && mov->flags & FF_MOV_FLAG_SKIP_SIDX) {
7628 av_log(s, AV_LOG_WARNING, "Global SIDX enabled; Ignoring skip_sidx option\n");
7629 mov->flags &= ~FF_MOV_FLAG_SKIP_SIDX;
7630 }
7631
7632
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 200 times.
203 if (mov->flags & FF_MOV_FLAG_FASTSTART) {
7633 3 mov->reserved_moov_size = -1;
7634 }
7635
7636
2/2
✓ Branch 0 taken 196 times.
✓ Branch 1 taken 7 times.
203 if (mov->use_editlist < 0) {
7637 196 mov->use_editlist = 1;
7638
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 169 times.
196 if (mov->flags & FF_MOV_FLAG_FRAGMENT &&
7639
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 15 times.
27 !(mov->flags & FF_MOV_FLAG_DELAY_MOOV)) {
7640 // If we can avoid needing an edit list by shifting the
7641 // tracks, prefer that over (trying to) write edit lists
7642 // in fragmented output.
7643
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 11 times.
12 if (s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO ||
7644
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO)
7645 11 mov->use_editlist = 0;
7646 }
7647
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 195 times.
196 if (mov->flags & FF_MOV_FLAG_CMAF) {
7648 // CMAF Track requires negative cts offsets without edit lists
7649 1 mov->use_editlist = 0;
7650 }
7651 }
7652
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 173 times.
203 if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV &&
7653
4/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 12 times.
30 !(mov->flags & FF_MOV_FLAG_DELAY_MOOV) && mov->use_editlist)
7654 1 av_log(s, AV_LOG_WARNING, "No meaningful edit list will be written when using empty_moov without delay_moov\n");
7655
7656
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 202 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
203 if (mov->flags & FF_MOV_FLAG_CMAF && mov->use_editlist) {
7657 av_log(s, AV_LOG_WARNING, "Edit list enabled; Assuming writing CMAF Track File\n");
7658 mov->flags &= ~FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS;
7659 }
7660
4/4
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 186 times.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 1 times.
203 if (!mov->use_editlist && s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO &&
7661
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 6 times.
16 !(mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS))
7662 10 s->avoid_negative_ts = AVFMT_AVOID_NEG_TS_MAKE_ZERO;
7663
7664 /* Clear the omit_tfhd_offset flag if default_base_moof is set;
7665 * if the latter is set that's enough and omit_tfhd_offset doesn't
7666 * add anything extra on top of that. */
7667
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 203 times.
203 if (mov->flags & FF_MOV_FLAG_OMIT_TFHD_OFFSET &&
7668 mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF)
7669 mov->flags &= ~FF_MOV_FLAG_OMIT_TFHD_OFFSET;
7670
7671
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 203 times.
203 if (mov->frag_interleave &&
7672 mov->flags & (FF_MOV_FLAG_OMIT_TFHD_OFFSET | FF_MOV_FLAG_SEPARATE_MOOF)) {
7673 av_log(s, AV_LOG_ERROR,
7674 "Sample interleaving in fragments is mutually exclusive with "
7675 "omit_tfhd_offset and separate_moof\n");
7676 return AVERROR(EINVAL);
7677 }
7678
7679 /* Non-seekable output is ok if using fragmentation. If ism_lookahead
7680 * is enabled, we don't support non-seekable output at all. */
7681
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 175 times.
203 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL) &&
7682
2/4
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
28 (!(mov->flags & FF_MOV_FLAG_FRAGMENT) || mov->ism_lookahead ||
7683
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 mov->mode == MODE_AVIF)) {
7684 av_log(s, AV_LOG_ERROR, "muxer does not support non seekable output\n");
7685 return AVERROR(EINVAL);
7686 }
7687
7688 /* AVIF output must have at most two video streams (one for YUV and one for
7689 * alpha). */
7690
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 203 times.
203 if (mov->mode == MODE_AVIF) {
7691 if (s->nb_streams > 2) {
7692 av_log(s, AV_LOG_ERROR, "AVIF output requires exactly one or two streams\n");
7693 return AVERROR(EINVAL);
7694 }
7695 if (s->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO &&
7696 (s->nb_streams > 1 && s->streams[1]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO)) {
7697 av_log(s, AV_LOG_ERROR, "AVIF output supports only video streams\n");
7698 return AVERROR(EINVAL);
7699 }
7700 if (s->nb_streams > 1) {
7701 const AVPixFmtDescriptor *pixdesc =
7702 av_pix_fmt_desc_get(s->streams[1]->codecpar->format);
7703 if (pixdesc->nb_components != 1) {
7704 av_log(s, AV_LOG_ERROR, "Second stream for AVIF (alpha) output must have exactly one plane\n");
7705 return AVERROR(EINVAL);
7706 }
7707 }
7708 s->streams[0]->disposition |= AV_DISPOSITION_DEFAULT;
7709 }
7710
7711 #if CONFIG_IAMFENC
7712
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 203 times.
211 for (i = 0; i < s->nb_stream_groups; i++) {
7713 8 AVStreamGroup *stg = s->stream_groups[i];
7714
7715
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 if (stg->type != AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
7716 4 continue;
7717
7718
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 4 times.
22 for (int j = 0; j < stg->nb_streams; j++) {
7719 18 AVStream *st = stg->streams[j];
7720
7721
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (st->priv_data) {
7722 av_log(s, AV_LOG_ERROR, "Stream %d is present in more than one Stream Group of type "
7723 "IAMF Audio Element\n", j);
7724 return AVERROR(EINVAL);
7725 }
7726 18 st->priv_data = st;
7727 }
7728
7729
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (!mov->nb_tracks) // We support one track for the entire IAMF structure
7730 4 mov->nb_tracks++;
7731 }
7732 #endif
7733
7734
2/2
✓ Branch 0 taken 274 times.
✓ Branch 1 taken 203 times.
477 for (i = 0; i < s->nb_streams; i++) {
7735 274 AVStream *st = s->streams[i];
7736
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 256 times.
274 if (st->priv_data)
7737 18 continue;
7738 // Don't produce a track in the output file for timed ID3 streams.
7739
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 255 times.
256 if (st->codecpar->codec_id == AV_CODEC_ID_TIMED_ID3) {
7740 // Leave priv_data set to NULL for these AVStreams that don't
7741 // have a corresponding track.
7742 1 continue;
7743 }
7744 255 st->priv_data = st;
7745 255 mov->nb_tracks++;
7746 }
7747
7748 203 mov->nb_streams = mov->nb_tracks;
7749
7750
4/4
✓ Branch 0 taken 198 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 197 times.
203 if (mov->mode & (MODE_MP4|MODE_MOV|MODE_IPOD) && s->nb_chapters)
7751 1 mov->chapter_track = mov->nb_tracks++;
7752
7753
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 202 times.
203 if (mov->flags & FF_MOV_FLAG_RTP_HINT) {
7754
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 for (i = 0; i < s->nb_streams; i++)
7755
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (rtp_hinting_needed(s->streams[i]))
7756 2 mov->nb_tracks++;
7757 }
7758
7759
1/2
✓ Branch 0 taken 203 times.
✗ Branch 1 not taken.
203 if (mov->write_btrt < 0) {
7760 203 mov->write_btrt = mov->mode == MODE_MP4;
7761 }
7762
7763
6/6
✓ Branch 0 taken 200 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 59 times.
✓ Branch 3 taken 141 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 56 times.
203 if ( mov->write_tmcd == -1 && (mov->mode == MODE_MOV || mov->mode == MODE_MP4)
7764
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 || mov->write_tmcd == 1) {
7765 200 AVDictionaryEntry *global_tcr = av_dict_get(s->metadata, "timecode",
7766 NULL, 0);
7767
7768 /* +1 tmcd track for each video stream with a timecode */
7769
2/2
✓ Branch 0 taken 269 times.
✓ Branch 1 taken 200 times.
469 for (i = 0; i < s->nb_streams; i++) {
7770 269 AVStream *st = s->streams[i];
7771 269 AVDictionaryEntry *t = global_tcr;
7772
4/4
✓ Branch 0 taken 171 times.
✓ Branch 1 taken 98 times.
✓ Branch 2 taken 164 times.
✓ Branch 3 taken 7 times.
269 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
7773
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 164 times.
164 (t || (t=av_dict_get(st->metadata, "timecode", NULL, 0)))) {
7774 AVTimecode tc;
7775 7 ret = mov_check_timecode_track(s, &tc, st, t->value);
7776
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (ret >= 0)
7777 7 mov->nb_meta_tmcd++;
7778 }
7779 }
7780
7781 /* check if there is already a tmcd track to remux */
7782
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 193 times.
200 if (mov->nb_meta_tmcd) {
7783
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 7 times.
20 for (i = 0; i < s->nb_streams; i++) {
7784 13 AVStream *st = s->streams[i];
7785
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 10 times.
13 if (st->codecpar->codec_tag == MKTAG('t','m','c','d')) {
7786 3 av_log(s, AV_LOG_WARNING, "You requested a copy of the original timecode track "
7787 "so timecode metadata are now ignored\n");
7788 3 mov->nb_meta_tmcd = 0;
7789 }
7790 }
7791 }
7792
7793 200 mov->nb_tracks += mov->nb_meta_tmcd;
7794 }
7795
7796 // Reserve an extra stream for chapters for the case where chapters
7797 // are written in the trailer
7798 203 mov->tracks = av_calloc(mov->nb_tracks + 1, sizeof(*mov->tracks));
7799
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 203 times.
203 if (!mov->tracks)
7800 return AVERROR(ENOMEM);
7801
7802
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 203 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
203 if (mov->encryption_scheme_str != NULL && strcmp(mov->encryption_scheme_str, "none") != 0) {
7803 if (strcmp(mov->encryption_scheme_str, "cenc-aes-ctr") == 0) {
7804 mov->encryption_scheme = MOV_ENC_CENC_AES_CTR;
7805
7806 if (mov->encryption_key_len != AES_CTR_KEY_SIZE) {
7807 av_log(s, AV_LOG_ERROR, "Invalid encryption key len %d expected %d\n",
7808 mov->encryption_key_len, AES_CTR_KEY_SIZE);
7809 return AVERROR(EINVAL);
7810 }
7811
7812 if (mov->encryption_kid_len != CENC_KID_SIZE) {
7813 av_log(s, AV_LOG_ERROR, "Invalid encryption kid len %d expected %d\n",
7814 mov->encryption_kid_len, CENC_KID_SIZE);
7815 return AVERROR(EINVAL);
7816 }
7817 } else {
7818 av_log(s, AV_LOG_ERROR, "unsupported encryption scheme %s\n",
7819 mov->encryption_scheme_str);
7820 return AVERROR(EINVAL);
7821 }
7822 }
7823
7824 #if CONFIG_IAMFENC
7825 203 ret = mov_init_iamf_track(s);
7826
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 203 times.
203 if (ret < 0)
7827 return ret;
7828 #endif
7829
7830
2/2
✓ Branch 0 taken 274 times.
✓ Branch 1 taken 203 times.
477 for (int j = 0, i = 0; j < s->nb_streams; j++) {
7831 274 AVStream *st = s->streams[j];
7832
7833
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 255 times.
274 if (st != st->priv_data)
7834 19 continue;
7835 255 st->priv_data = &mov->tracks[i++];
7836 }
7837
7838
2/2
✓ Branch 0 taken 274 times.
✓ Branch 1 taken 203 times.
477 for (i = 0; i < s->nb_streams; i++) {
7839 274 AVStream *st= s->streams[i];
7840 274 MOVTrack *track = st->priv_data;
7841 274 AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL,0);
7842
7843
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 273 times.
274 if (!track)
7844 1 continue;
7845
7846
2/2
✓ Branch 0 taken 259 times.
✓ Branch 1 taken 14 times.
273 if (!track->st) {
7847 259 track->st = st;
7848 259 track->par = st->codecpar;
7849 }
7850
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 249 times.
273 track->language = ff_mov_iso639_to_lang(lang?lang->value:"und", mov->mode!=MODE_MOV);
7851
2/2
✓ Branch 0 taken 150 times.
✓ Branch 1 taken 123 times.
273 if (track->language < 0)
7852 150 track->language = 32767; // Unspecified Macintosh language code
7853 273 track->mode = mov->mode;
7854
2/2
✓ Branch 0 taken 255 times.
✓ Branch 1 taken 18 times.
273 if (!track->tag)
7855 255 track->tag = mov_find_codec_tag(s, track);
7856
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 273 times.
273 if (!track->tag) {
7857 av_log(s, AV_LOG_ERROR, "Could not find tag for codec %s in stream #%d, "
7858 "codec not currently supported in container\n",
7859 avcodec_get_name(st->codecpar->codec_id), i);
7860 return AVERROR(EINVAL);
7861 }
7862 /* If hinting of this track is enabled by a later hint track,
7863 * this is updated. */
7864 273 track->hint_track = -1;
7865 273 track->start_dts = AV_NOPTS_VALUE;
7866 273 track->start_cts = AV_NOPTS_VALUE;
7867 273 track->end_pts = AV_NOPTS_VALUE;
7868 273 track->dts_shift = AV_NOPTS_VALUE;
7869
2/2
✓ Branch 0 taken 173 times.
✓ Branch 1 taken 100 times.
273 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
7870
2/4
✓ Branch 0 taken 173 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173 times.
✗ Branch 3 not taken.
173 if (track->tag == MKTAG('m','x','3','p') || track->tag == MKTAG('m','x','3','n') ||
7871
2/4
✓ Branch 0 taken 173 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173 times.
✗ Branch 3 not taken.
173 track->tag == MKTAG('m','x','4','p') || track->tag == MKTAG('m','x','4','n') ||
7872
2/4
✓ Branch 0 taken 173 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 173 times.
173 track->tag == MKTAG('m','x','5','p') || track->tag == MKTAG('m','x','5','n')) {
7873 if (st->codecpar->width != 720 || (st->codecpar->height != 608 && st->codecpar->height != 512)) {
7874 av_log(s, AV_LOG_ERROR, "D-10/IMX must use 720x608 or 720x512 video resolution\n");
7875 return AVERROR(EINVAL);
7876 }
7877 track->height = track->tag >> 24 == 'n' ? 486 : 576;
7878 }
7879
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 173 times.
173 if (mov->video_track_timescale) {
7880 track->timescale = mov->video_track_timescale;
7881 if (mov->mode == MODE_ISM && mov->video_track_timescale != 10000000)
7882 av_log(s, AV_LOG_WARNING, "Warning: some tools, like mp4split, assume a timescale of 10000000 for ISMV.\n");
7883 } else {
7884 173 track->timescale = st->time_base.den;
7885
2/2
✓ Branch 0 taken 1413 times.
✓ Branch 1 taken 173 times.
1586 while(track->timescale < 10000)
7886 1413 track->timescale *= 2;
7887 }
7888
2/4
✓ Branch 0 taken 173 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 173 times.
173 if (st->codecpar->width > 65535 || st->codecpar->height > 65535) {
7889 av_log(s, AV_LOG_ERROR, "Resolution %dx%d too large for mov/mp4\n", st->codecpar->width, st->codecpar->height);
7890 return AVERROR(EINVAL);
7891 }
7892
4/4
✓ Branch 0 taken 125 times.
✓ Branch 1 taken 48 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 124 times.
173 if (track->mode == MODE_MOV && track->timescale > 100000)
7893 1 av_log(s, AV_LOG_WARNING,
7894 "WARNING codec timebase is very high. If duration is too long,\n"
7895 "file may not be playable by quicktime. Specify a shorter timebase\n"
7896 "or choose different container.\n");
7897
2/2
✓ Branch 0 taken 125 times.
✓ Branch 1 taken 48 times.
173 if (track->mode == MODE_MOV &&
7898
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 112 times.
125 track->par->codec_id == AV_CODEC_ID_RAWVIDEO &&
7899
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12 times.
13 track->tag == MKTAG('r','a','w',' ')) {
7900 1 enum AVPixelFormat pix_fmt = track->par->format;
7901
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)
7902 pix_fmt = AV_PIX_FMT_MONOWHITE;
7903 1 track->is_unaligned_qt_rgb =
7904 pix_fmt == AV_PIX_FMT_RGB24 ||
7905 pix_fmt == AV_PIX_FMT_BGR24 ||
7906 pix_fmt == AV_PIX_FMT_PAL8 ||
7907 pix_fmt == AV_PIX_FMT_GRAY8 ||
7908
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 ||
7909 pix_fmt == AV_PIX_FMT_MONOBLACK;
7910 }
7911
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 173 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
173 if (track->par->codec_id == AV_CODEC_ID_VP9 && track->mode != MODE_MP4) {
7912 av_log(s, AV_LOG_ERROR, "%s only supported in MP4.\n", avcodec_get_name(track->par->codec_id));
7913 return AVERROR(EINVAL);
7914
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 172 times.
173 } else if (track->par->codec_id == AV_CODEC_ID_AV1 &&
7915
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 track->mode != MODE_MP4 && track->mode != MODE_AVIF) {
7916 av_log(s, AV_LOG_ERROR, "%s only supported in MP4 and AVIF.\n", avcodec_get_name(track->par->codec_id));
7917 return AVERROR(EINVAL);
7918
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 173 times.
173 } else if (track->par->codec_id == AV_CODEC_ID_VP8) {
7919 /* altref frames handling is not defined in the spec as of version v1.0,
7920 * so just forbid muxing VP8 streams altogether until a new version does */
7921 av_log(s, AV_LOG_ERROR, "VP8 muxing is currently not supported.\n");
7922 return AVERROR_PATCHWELCOME;
7923 }
7924
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 171 times.
173 if (is_cover_image(st)) {
7925 2 track->cover_image = av_packet_alloc();
7926
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!track->cover_image)
7927 return AVERROR(ENOMEM);
7928 }
7929
2/2
✓ Branch 0 taken 93 times.
✓ Branch 1 taken 7 times.
100 } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
7930 93 track->timescale = st->codecpar->sample_rate;
7931
4/4
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 62 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 25 times.
93 if (!st->codecpar->frame_size && !av_get_bits_per_sample(st->codecpar->codec_id)) {
7932 6 av_log(s, AV_LOG_WARNING, "track %d: codec frame size is not set\n", i);
7933 6 track->audio_vbr = 1;
7934
1/2
✓ Branch 0 taken 87 times.
✗ Branch 1 not taken.
87 }else if (st->codecpar->codec_id == AV_CODEC_ID_ADPCM_MS ||
7935
1/2
✓ Branch 0 taken 87 times.
✗ Branch 1 not taken.
87 st->codecpar->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV ||
7936
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 87 times.
87 st->codecpar->codec_id == AV_CODEC_ID_ILBC){
7937 if (!st->codecpar->block_align) {
7938 av_log(s, AV_LOG_ERROR, "track %d: codec block align is not set for adpcm\n", i);
7939 return AVERROR(EINVAL);
7940 }
7941 track->sample_size = st->codecpar->block_align;
7942
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 25 times.
87 }else if (st->codecpar->frame_size > 1){ /* assume compressed audio */
7943 62 track->audio_vbr = 1;
7944 }else{
7945 25 track->sample_size = (av_get_bits_per_sample(st->codecpar->codec_id) >> 3) *
7946 25 st->codecpar->ch_layout.nb_channels;
7947 }
7948
1/2
✓ Branch 0 taken 93 times.
✗ Branch 1 not taken.
93 if (st->codecpar->codec_id == AV_CODEC_ID_ILBC ||
7949
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 93 times.
93 st->codecpar->codec_id == AV_CODEC_ID_ADPCM_IMA_QT) {
7950 track->audio_vbr = 1;
7951 }
7952
2/2
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 32 times.
93 if (track->mode != MODE_MOV &&
7953
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
61 track->par->codec_id == AV_CODEC_ID_MP3 && track->timescale < 16000) {
7954 if (s->strict_std_compliance >= FF_COMPLIANCE_NORMAL) {
7955 av_log(s, AV_LOG_ERROR, "track %d: muxing mp3 at %dhz is not standard, to mux anyway set strict to -1\n",
7956 i, track->par->sample_rate);
7957 return AVERROR(EINVAL);
7958 } else {
7959 av_log(s, AV_LOG_WARNING, "track %d: muxing mp3 at %dhz is not standard in MP4\n",
7960 i, track->par->sample_rate);
7961 }
7962 }
7963
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 18 times.
93 if (track->par->codec_id == AV_CODEC_ID_FLAC ||
7964
1/2
✓ Branch 0 taken 75 times.
✗ Branch 1 not taken.
75 track->par->codec_id == AV_CODEC_ID_TRUEHD ||
7965
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
75 track->par->codec_id == AV_CODEC_ID_OPUS) {
7966
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (track->mode != MODE_MP4) {
7967 av_log(s, AV_LOG_ERROR, "%s only supported in MP4.\n", avcodec_get_name(track->par->codec_id));
7968 return AVERROR(EINVAL);
7969 }
7970
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (track->par->codec_id == AV_CODEC_ID_TRUEHD &&
7971 s->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) {
7972 av_log(s, AV_LOG_ERROR,
7973 "%s in MP4 support is experimental, add "
7974 "'-strict %d' if you want to use it.\n",
7975 avcodec_get_name(track->par->codec_id), FF_COMPLIANCE_EXPERIMENTAL);
7976 return AVERROR_EXPERIMENTAL;
7977 }
7978 }
7979
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 4 times.
7 } else if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
7980 3 track->timescale = st->time_base.den;
7981
7982
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 if (track->par->codec_id == AV_CODEC_ID_TTML) {
7983 /* 14496-30 requires us to use a single sample per fragment
7984 for TTML, for which we define a per-track flag.
7985
7986 We set the flag in case we are receiving TTML paragraphs
7987 from the input, in other words in case we are not doing
7988 stream copy. */
7989 2 track->squash_fragment_samples_to_one =
7990 2 ff_is_ttml_stream_paragraph_based(track->par);
7991
7992
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (mov->flags & FF_MOV_FLAG_FRAGMENT &&
7993 track->squash_fragment_samples_to_one) {
7994 av_log(s, AV_LOG_ERROR,
7995 "Fragmentation is not currently supported for "
7996 "TTML in MP4/ISMV (track synchronization between "
7997 "subtitles and other media is not yet implemented)!\n");
7998 return AVERROR_PATCHWELCOME;
7999 }
8000
8001
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (track->mode != MODE_ISM &&
8002
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 track->par->codec_tag == MOV_ISMV_TTML_TAG &&
8003
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 s->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL) {
8004 av_log(s, AV_LOG_ERROR,
8005 "ISMV style TTML support with the 'dfxp' tag in "
8006 "non-ISMV formats is not officially supported. Add "
8007 "'-strict unofficial' if you want to use it.\n");
8008 return AVERROR_EXPERIMENTAL;
8009 }
8010 }
8011
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 } else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA) {
8012 4 track->timescale = st->time_base.den;
8013 } else {
8014 track->timescale = mov->movie_timescale;
8015 }
8016
1/2
✓ Branch 0 taken 273 times.
✗ Branch 1 not taken.
273 if (!track->height)
8017 273 track->height = st->codecpar->height;
8018 /* The Protected Interoperable File Format (PIFF) standard, used by ISMV recommends but
8019 doesn't mandate a track timescale of 10,000,000. The muxer allows a custom timescale
8020 for video tracks, so if user-set, it isn't overwritten */
8021
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 268 times.
273 if (mov->mode == MODE_ISM &&
8022
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
5 (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO ||
8023
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && !mov->video_track_timescale))) {
8024 5 track->timescale = 10000000;
8025 }
8026
8027 273 avpriv_set_pts_info(st, 64, 1, track->timescale);
8028
8029
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 273 times.
273 if (mov->encryption_scheme == MOV_ENC_CENC_AES_CTR) {
8030 ret = ff_mov_cenc_init(&track->cenc, mov->encryption_key,
8031 (track->par->codec_id == AV_CODEC_ID_H264 || track->par->codec_id == AV_CODEC_ID_HEVC ||
8032 track->par->codec_id == AV_CODEC_ID_VVC),
8033 s->flags & AVFMT_FLAG_BITEXACT);
8034 if (ret)
8035 return ret;
8036 }
8037 }
8038
8039 203 enable_tracks(s);
8040 203 return 0;
8041 }
8042
8043 203 static int mov_write_header(AVFormatContext *s)
8044 {
8045 203 AVIOContext *pb = s->pb;
8046 203 MOVMuxContext *mov = s->priv_data;
8047 203 int ret, hint_track = 0, tmcd_track = 0, nb_tracks = mov->nb_streams;
8048
8049
4/4
✓ Branch 0 taken 198 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 197 times.
203 if (mov->mode & (MODE_MP4|MODE_MOV|MODE_IPOD) && s->nb_chapters)
8050 1 nb_tracks++;
8051
8052
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 202 times.
203 if (mov->flags & FF_MOV_FLAG_RTP_HINT) {
8053 1 hint_track = nb_tracks;
8054
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 for (int i = 0; i < mov->nb_streams; i++) {
8055
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (rtp_hinting_needed(mov->tracks[i].st))
8056 2 nb_tracks++;
8057 }
8058 }
8059
8060
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 197 times.
203 if (mov->nb_meta_tmcd)
8061 6 tmcd_track = nb_tracks;
8062
8063
2/2
✓ Branch 0 taken 259 times.
✓ Branch 1 taken 203 times.
462 for (int i = 0; i < mov->nb_streams; i++) {
8064 259 MOVTrack *track = &mov->tracks[i];
8065 259 AVStream *st = track->st;
8066
8067 /* copy extradata if it exists */
8068
2/2
✓ Branch 0 taken 113 times.
✓ Branch 1 taken 146 times.
259 if (st->codecpar->extradata_size) {
8069
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 113 times.
113 if (st->codecpar->codec_id == AV_CODEC_ID_DVD_SUBTITLE)
8070 mov_create_dvd_sub_decoder_specific_info(track, st);
8071
15/30
✓ Branch 0 taken 113 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 113 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 113 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 113 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 113 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 113 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 113 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 113 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 113 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 113 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 113 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 113 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 113 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 113 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 113 times.
✗ Branch 29 not taken.
113 else if (!TAG_IS_AVCI(track->tag) && st->codecpar->codec_id != AV_CODEC_ID_DNXHD) {
8072 113 track->vos_len = st->codecpar->extradata_size;
8073 113 track->vos_data = av_malloc(track->vos_len + AV_INPUT_BUFFER_PADDING_SIZE);
8074
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 113 times.
113 if (!track->vos_data) {
8075 return AVERROR(ENOMEM);
8076 }
8077 113 memcpy(track->vos_data, st->codecpar->extradata, track->vos_len);
8078 113 memset(track->vos_data + track->vos_len, 0, AV_INPUT_BUFFER_PADDING_SIZE);
8079 }
8080 }
8081
8082
4/4
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 180 times.
✓ Branch 2 taken 65 times.
✓ Branch 3 taken 14 times.
338 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO ||
8083 79 av_channel_layout_compare(&track->par->ch_layout,
8084 79 &(AVChannelLayout)AV_CHANNEL_LAYOUT_MONO))
8085 245 continue;
8086
8087
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 14 times.
47 for (int j = 0; j < mov->nb_streams; j++) {
8088 33 AVStream *stj= mov->tracks[j].st;
8089 33 MOVTrack *trackj= &mov->tracks[j];
8090
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 19 times.
33 if (j == i)
8091 14 continue;
8092
8093
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 8 times.
19 if (stj->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
8094
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
18 (trackj->par->ch_layout.nb_channels != 1 ||
8095 7 !av_channel_layout_compare(&trackj->par->ch_layout,
8096 7 &(AVChannelLayout)AV_CHANNEL_LAYOUT_MONO))
8097 )
8098 4 track->mono_as_fc = -1;
8099
8100
3/4
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
30 if (stj->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
8101 11 av_channel_layout_compare(&trackj->par->ch_layout,
8102 11 &(AVChannelLayout)AV_CHANNEL_LAYOUT_MONO) &&
8103
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
8104 )
8105 7 track->mono_as_fc++;
8106
8107
3/4
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
30 if (stj->codecpar->codec_type != AVMEDIA_TYPE_AUDIO ||
8108 11 av_channel_layout_compare(&trackj->par->ch_layout,
8109 11 &(AVChannelLayout)AV_CHANNEL_LAYOUT_MONO) ||
8110 trackj->language != track->language ||
8111 trackj->tag != track->tag
8112 )
8113 19 continue;
8114 track->multichannel_as_mono++;
8115 }
8116 }
8117
8118
2/2
✓ Branch 0 taken 186 times.
✓ Branch 1 taken 17 times.
203 if (!(mov->flags & FF_MOV_FLAG_DELAY_MOOV)) {
8119
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 186 times.
186 if ((ret = mov_write_identification(pb, s)) < 0)
8120 return ret;
8121 }
8122
8123
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 200 times.
203 if (mov->reserved_moov_size){
8124 3 mov->reserved_header_pos = avio_tell(pb);
8125
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (mov->reserved_moov_size > 0)
8126 avio_skip(pb, mov->reserved_moov_size);
8127 }
8128
8129
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 169 times.
203 if (mov->flags & FF_MOV_FLAG_FRAGMENT) {
8130 /* If no fragmentation options have been set, set a default. */
8131
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 30 times.
34 if (!(mov->flags & (FF_MOV_FLAG_FRAG_KEYFRAME |
8132 FF_MOV_FLAG_FRAG_CUSTOM |
8133 4 FF_MOV_FLAG_FRAG_EVERY_FRAME)) &&
8134
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 !mov->max_fragment_duration && !mov->max_fragment_size)
8135 4 mov->flags |= FF_MOV_FLAG_FRAG_KEYFRAME;
8136
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 33 times.
34 if (mov->flags & FF_MOV_FLAG_HYBRID_FRAGMENTED) {
8137 1 avio_wb32(pb, 8); // placeholder for extended size field (64 bit)
8138
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 ffio_wfourcc(pb, mov->mode == MODE_MOV ? "wide" : "free");
8139 1 mov->mdat_pos = avio_tell(pb);
8140 }
8141
1/2
✓ Branch 0 taken 169 times.
✗ Branch 1 not taken.
169 } else if (mov->mode != MODE_AVIF) {
8142
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 166 times.
169 if (mov->flags & FF_MOV_FLAG_FASTSTART)
8143 3 mov->reserved_header_pos = avio_tell(pb);
8144 169 mov_write_mdat_tag(pb, mov);
8145 }
8146
8147 203 ff_parse_creation_time_metadata(s, &mov->time, 1);
8148
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 203 times.
203 if (mov->time)
8149 mov->time += 0x7C25B080; // 1970 based -> 1904 based
8150
8151
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 202 times.
203 if (mov->chapter_track)
8152
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if ((ret = mov_create_chapter_track(s, mov->chapter_track)) < 0)
8153 return ret;
8154
8155
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 202 times.
203 if (mov->flags & FF_MOV_FLAG_RTP_HINT) {
8156
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 for (int i = 0; i < mov->nb_streams; i++) {
8157
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (rtp_hinting_needed(mov->tracks[i].st)) {
8158
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if ((ret = ff_mov_init_hinting(s, hint_track, i)) < 0)
8159 return ret;
8160 2 hint_track++;
8161 }
8162 }
8163 }
8164
8165
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 197 times.
203 if (mov->nb_meta_tmcd) {
8166 6 const AVDictionaryEntry *t, *global_tcr = av_dict_get(s->metadata,
8167 "timecode", NULL, 0);
8168 /* Initialize the tmcd tracks */
8169
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 6 times.
14 for (int i = 0; i < mov->nb_streams; i++) {
8170 8 AVStream *st = mov->tracks[i].st;
8171 8 t = global_tcr;
8172
8173
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
8174 AVTimecode tc;
8175
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!t)
8176 t = av_dict_get(st->metadata, "timecode", NULL, 0);
8177
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!t)
8178 continue;
8179
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if (mov_check_timecode_track(s, &tc, st, t->value) < 0)
8180 continue;
8181
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if ((ret = mov_create_timecode_track(s, tmcd_track, i, tc)) < 0)
8182 return ret;
8183 6 tmcd_track++;
8184 }
8185 }
8186 }
8187
8188 203 avio_flush(pb);
8189
8190
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 203 times.
203 if (mov->flags & FF_MOV_FLAG_ISML)
8191 mov_write_isml_manifest(pb, mov, s);
8192
8193
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 173 times.
203 if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV &&
8194
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 17 times.
30 !(mov->flags & FF_MOV_FLAG_DELAY_MOOV)) {
8195
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
13 if ((ret = mov_write_moov_tag(pb, mov, s)) < 0)
8196 return ret;
8197 13 mov->moov_written = 1;
8198
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX)
8199 mov->reserved_header_pos = avio_tell(pb);
8200 }
8201
8202 203 return 0;
8203 }
8204
8205 27 static int get_moov_size(AVFormatContext *s)
8206 {
8207 int ret;
8208 AVIOContext *moov_buf;
8209 27 MOVMuxContext *mov = s->priv_data;
8210
8211
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
27 if ((ret = ffio_open_null_buf(&moov_buf)) < 0)
8212 return ret;
8213
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
27 if ((ret = mov_write_moov_tag(moov_buf, mov, s)) < 0)
8214 return ret;
8215 27 return ffio_close_null_buf(moov_buf);
8216 }
8217
8218 static int get_sidx_size(AVFormatContext *s)
8219 {
8220 int ret;
8221 AVIOContext *buf;
8222 MOVMuxContext *mov = s->priv_data;
8223
8224 if ((ret = ffio_open_null_buf(&buf)) < 0)
8225 return ret;
8226 mov_write_sidx_tags(buf, mov, -1, 0);
8227 return ffio_close_null_buf(buf);
8228 }
8229
8230 /*
8231 * This function gets the moov size if moved to the top of the file: the chunk
8232 * offset table can switch between stco (32-bit entries) to co64 (64-bit
8233 * entries) when the moov is moved to the beginning, so the size of the moov
8234 * would change. It also updates the chunk offset tables.
8235 */
8236 3 static int compute_moov_size(AVFormatContext *s)
8237 {
8238 int i, moov_size, moov_size2;
8239 3 MOVMuxContext *mov = s->priv_data;
8240
8241 3 moov_size = get_moov_size(s);
8242
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (moov_size < 0)
8243 return moov_size;
8244
8245
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 3 times.
11 for (i = 0; i < mov->nb_tracks; i++)
8246 8 mov->tracks[i].data_offset += moov_size;
8247
8248 3 moov_size2 = get_moov_size(s);
8249
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (moov_size2 < 0)
8250 return moov_size2;
8251
8252 /* if the size changed, we just switched from stco to co64 and need to
8253 * update the offsets */
8254
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (moov_size2 != moov_size)
8255 for (i = 0; i < mov->nb_tracks; i++)
8256 mov->tracks[i].data_offset += moov_size2 - moov_size;
8257
8258 3 return moov_size2;
8259 }
8260
8261 static int compute_sidx_size(AVFormatContext *s)
8262 {
8263 int i, sidx_size;
8264 MOVMuxContext *mov = s->priv_data;
8265
8266 sidx_size = get_sidx_size(s);
8267 if (sidx_size < 0)
8268 return sidx_size;
8269
8270 for (i = 0; i < mov->nb_tracks; i++)
8271 mov->tracks[i].data_offset += sidx_size;
8272
8273 return sidx_size;
8274 }
8275
8276 3 static int shift_data(AVFormatContext *s)
8277 {
8278 int moov_size;
8279 3 MOVMuxContext *mov = s->priv_data;
8280
8281
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (mov->flags & FF_MOV_FLAG_FRAGMENT)
8282 moov_size = compute_sidx_size(s);
8283 else
8284 3 moov_size = compute_moov_size(s);
8285
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (moov_size < 0)
8286 return moov_size;
8287
8288 3 return ff_format_shift_data(s, mov->reserved_header_pos, moov_size);
8289 }
8290
8291 203 static int mov_write_trailer(AVFormatContext *s)
8292 {
8293 203 MOVMuxContext *mov = s->priv_data;
8294 203 AVIOContext *pb = s->pb;
8295 203 int res = 0;
8296 int i;
8297 int64_t moov_pos;
8298
8299
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 199 times.
203 if (mov->need_rewrite_extradata) {
8300
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 for (i = 0; i < mov->nb_streams; i++) {
8301 4 MOVTrack *track = &mov->tracks[i];
8302 4 AVCodecParameters *par = track->par;
8303
8304 4 track->vos_len = par->extradata_size;
8305 4 av_freep(&track->vos_data);
8306 4 track->vos_data = av_malloc(track->vos_len + AV_INPUT_BUFFER_PADDING_SIZE);
8307
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!track->vos_data)
8308 return AVERROR(ENOMEM);
8309 4 memcpy(track->vos_data, par->extradata, track->vos_len);
8310 4 memset(track->vos_data + track->vos_len, 0, AV_INPUT_BUFFER_PADDING_SIZE);
8311 }
8312 4 mov->need_rewrite_extradata = 0;
8313 }
8314
8315 /*
8316 * Before actually writing the trailer, make sure that there are no
8317 * dangling subtitles, that need a terminating sample.
8318 */
8319
2/2
✓ Branch 0 taken 268 times.
✓ Branch 1 taken 203 times.
471 for (i = 0; i < mov->nb_tracks; i++) {
8320 268 MOVTrack *trk = &mov->tracks[i];
8321
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 267 times.
268 if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT &&
8322
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 !trk->last_sample_is_subtitle_end) {
8323 1 mov_write_subtitle_end_packet(s, i, trk->track_duration);
8324 1 trk->last_sample_is_subtitle_end = 1;
8325 }
8326 }
8327
8328 // Check if we have any tracks that require squashing.
8329 // In that case, we'll have to write the packet here.
8330
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 203 times.
203 if ((res = mov_write_squashed_packets(s)) < 0)
8331 return res;
8332
8333 // If there were no chapters when the header was written, but there
8334 // are chapters now, write them in the trailer. This only works
8335 // when we are not doing fragments.
8336
4/4
✓ Branch 0 taken 202 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 168 times.
✓ Branch 3 taken 34 times.
203 if (!mov->chapter_track && !(mov->flags & FF_MOV_FLAG_FRAGMENT)) {
8337
3/4
✓ Branch 0 taken 167 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 167 times.
168 if (mov->mode & (MODE_MP4|MODE_MOV|MODE_IPOD) && s->nb_chapters) {
8338 mov->chapter_track = mov->nb_tracks++;
8339 if ((res = mov_create_chapter_track(s, mov->chapter_track)) < 0)
8340 return res;
8341 }
8342 }
8343
8344
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 169 times.
203 if (!(mov->flags & FF_MOV_FLAG_FRAGMENT) ||
8345
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 33 times.
34 mov->flags & FF_MOV_FLAG_HYBRID_FRAGMENTED) {
8346
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 169 times.
170 if (mov->flags & FF_MOV_FLAG_HYBRID_FRAGMENTED) {
8347 1 mov_flush_fragment(s, 1);
8348 1 mov->mdat_size = avio_tell(pb) - mov->mdat_pos - 8;
8349
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 for (i = 0; i < mov->nb_tracks; i++) {
8350 2 MOVTrack *track = &mov->tracks[i];
8351 2 track->data_offset = 0;
8352 2 av_free(track->cluster);
8353 2 track->cluster = track->cluster_written;
8354 2 track->entry = track->entry_written;
8355 2 track->cluster_written = NULL;
8356 2 track->entry_written = 0;
8357 2 track->chunkCount = 0; // Force build_chunks to rebuild the list of chunks
8358 }
8359 // Clear the empty_moov flag, as we do want the moov to include
8360 // all the samples at this point.
8361 1 mov->flags &= ~FF_MOV_FLAG_EMPTY_MOOV;
8362 }
8363
8364 170 moov_pos = avio_tell(pb);
8365
8366 /* Write size of mdat tag */
8367
1/2
✓ Branch 0 taken 170 times.
✗ Branch 1 not taken.
170 if (mov->mdat_size + 8 <= UINT32_MAX) {
8368 170 avio_seek(pb, mov->mdat_pos, SEEK_SET);
8369 170 avio_wb32(pb, mov->mdat_size + 8);
8370
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 169 times.
170 if (mov->flags & FF_MOV_FLAG_HYBRID_FRAGMENTED)
8371 1 ffio_wfourcc(pb, "mdat"); // overwrite the original moov into a mdat
8372 } else {
8373 /* overwrite 'wide' placeholder atom */
8374 avio_seek(pb, mov->mdat_pos - 8, SEEK_SET);
8375 /* special value: real atom size will be 64 bit value after
8376 * tag field */
8377 avio_wb32(pb, 1);
8378 ffio_wfourcc(pb, "mdat");
8379 avio_wb64(pb, mov->mdat_size + 16);
8380 }
8381
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 170 times.
170 avio_seek(pb, mov->reserved_moov_size > 0 ? mov->reserved_header_pos : moov_pos, SEEK_SET);
8382
8383
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 167 times.
170 if (mov->flags & FF_MOV_FLAG_FASTSTART) {
8384 3 av_log(s, AV_LOG_INFO, "Starting second pass: moving the moov atom to the beginning of the file\n");
8385 3 res = shift_data(s);
8386
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (res < 0)
8387 return res;
8388 3 avio_seek(pb, mov->reserved_header_pos, SEEK_SET);
8389
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if ((res = mov_write_moov_tag(pb, mov, s)) < 0)
8390 return res;
8391
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 167 times.
167 } else if (mov->reserved_moov_size > 0) {
8392 int64_t size;
8393 if ((res = mov_write_moov_tag(pb, mov, s)) < 0)
8394 return res;
8395 size = mov->reserved_moov_size - (avio_tell(pb) - mov->reserved_header_pos);
8396 if (size < 8){
8397 av_log(s, AV_LOG_ERROR, "reserved_moov_size is too small, needed %"PRId64" additional\n", 8-size);
8398 return AVERROR(EINVAL);
8399 }
8400 avio_wb32(pb, size);
8401 ffio_wfourcc(pb, "free");
8402 ffio_fill(pb, 0, size - 8);
8403 avio_seek(pb, moov_pos, SEEK_SET);
8404 } else {
8405
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 167 times.
167 if ((res = mov_write_moov_tag(pb, mov, s)) < 0)
8406 return res;
8407 }
8408 170 res = 0;
8409 } else {
8410 33 mov_auto_flush_fragment(s, 1);
8411
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 33 times.
96 for (i = 0; i < mov->nb_tracks; i++)
8412 63 mov->tracks[i].data_offset = 0;
8413
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX) {
8414 int64_t end;
8415 av_log(s, AV_LOG_INFO, "Starting second pass: inserting sidx atoms\n");
8416 res = shift_data(s);
8417 if (res < 0)
8418 return res;
8419 end = avio_tell(pb);
8420 avio_seek(pb, mov->reserved_header_pos, SEEK_SET);
8421 mov_write_sidx_tags(pb, mov, -1, 0);
8422 avio_seek(pb, end, SEEK_SET);
8423 }
8424
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 if (!(mov->flags & FF_MOV_FLAG_SKIP_TRAILER)) {
8425 33 avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_TRAILER);
8426 33 res = mov_write_mfra_tag(pb, mov);
8427
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 if (res < 0)
8428 return res;
8429 }
8430 }
8431
8432 203 return res;
8433 }
8434
8435 218 static int mov_check_bitstream(AVFormatContext *s, AVStream *st,
8436 const AVPacket *pkt)
8437 {
8438 218 int ret = 1;
8439
8440
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 209 times.
218 if (st->codecpar->codec_id == AV_CODEC_ID_AAC) {
8441
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
9 if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0)
8442 ret = ff_stream_add_bitstream_filter(st, "aac_adtstoasc", NULL);
8443
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 209 times.
209 } else if (st->codecpar->codec_id == AV_CODEC_ID_VP9) {
8444 ret = ff_stream_add_bitstream_filter(st, "vp9_superframe", NULL);
8445 }
8446
8447 218 return ret;
8448 }
8449
8450 #if CONFIG_AVIF_MUXER
8451 static int avif_write_trailer(AVFormatContext *s)
8452 {
8453 AVIOContext *pb = s->pb;
8454 MOVMuxContext *mov = s->priv_data;
8455 int64_t pos_backup, extent_offsets[2];
8456 uint8_t *buf;
8457 int buf_size, moov_size;
8458
8459 if (mov->moov_written) return 0;
8460
8461 mov->is_animated_avif = s->streams[0]->nb_frames > 1;
8462 if (mov->is_animated_avif && mov->nb_streams > 1) {
8463 // For animated avif with alpha channel, we need to write a tref tag
8464 // with type "auxl".
8465 mov->tracks[1].tref_tag = MKTAG('a', 'u', 'x', 'l');
8466 mov->tracks[1].tref_id = 1;
8467 }
8468 mov_write_identification(pb, s);
8469 mov_write_meta_tag(pb, mov, s);
8470
8471 moov_size = get_moov_size(s);
8472 for (int i = 0; i < mov->nb_tracks; i++)
8473 mov->tracks[i].data_offset = avio_tell(pb) + moov_size + 8;
8474
8475 if (mov->is_animated_avif) {
8476 int ret;
8477 if ((ret = mov_write_moov_tag(pb, mov, s)) < 0)
8478 return ret;
8479 }
8480
8481 buf_size = avio_get_dyn_buf(mov->mdat_buf, &buf);
8482 avio_wb32(pb, buf_size + 8);
8483 ffio_wfourcc(pb, "mdat");
8484
8485 // The offset for the YUV planes is the starting position of mdat.
8486 extent_offsets[0] = avio_tell(pb);
8487 // The offset for alpha plane is YUV offset + YUV size.
8488 extent_offsets[1] = extent_offsets[0] + mov->avif_extent_length[0];
8489
8490 avio_write(pb, buf, buf_size);
8491
8492 // write extent offsets.
8493 pos_backup = avio_tell(pb);
8494 for (int i = 0; i < mov->nb_streams; i++) {
8495 if (extent_offsets[i] != (uint32_t)extent_offsets[i]) {
8496 av_log(s, AV_LOG_ERROR, "extent offset does not fit in 32 bits\n");
8497 return AVERROR_INVALIDDATA;
8498 }
8499 avio_seek(pb, mov->avif_extent_pos[i], SEEK_SET);
8500 avio_wb32(pb, extent_offsets[i]); /* rewrite offset */
8501 }
8502 avio_seek(pb, pos_backup, SEEK_SET);
8503
8504 return 0;
8505 }
8506 #endif
8507
8508 #if CONFIG_TGP_MUXER || CONFIG_TG2_MUXER
8509 static const AVCodecTag codec_3gp_tags[] = {
8510 { AV_CODEC_ID_H263, MKTAG('s','2','6','3') },
8511 { AV_CODEC_ID_H264, MKTAG('a','v','c','1') },
8512 { AV_CODEC_ID_MPEG4, MKTAG('m','p','4','v') },
8513 { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') },
8514 { AV_CODEC_ID_AMR_NB, MKTAG('s','a','m','r') },
8515 { AV_CODEC_ID_AMR_WB, MKTAG('s','a','w','b') },
8516 { AV_CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') },
8517 { AV_CODEC_ID_NONE, 0 },
8518 };
8519 static const AVCodecTag *const codec_3gp_tags_list[] = { codec_3gp_tags, NULL };
8520 #endif
8521
8522 static const AVCodecTag codec_mp4_tags[] = {
8523 { AV_CODEC_ID_MPEG4, MKTAG('m', 'p', '4', 'v') },
8524 { AV_CODEC_ID_H264, MKTAG('a', 'v', 'c', '1') },
8525 { AV_CODEC_ID_H264, MKTAG('a', 'v', 'c', '3') },
8526 { AV_CODEC_ID_HEVC, MKTAG('h', 'e', 'v', '1') },
8527 { AV_CODEC_ID_HEVC, MKTAG('h', 'v', 'c', '1') },
8528 { AV_CODEC_ID_HEVC, MKTAG('d', 'v', 'h', '1') },
8529 { AV_CODEC_ID_VVC, MKTAG('v', 'v', 'c', '1') },
8530 { AV_CODEC_ID_VVC, MKTAG('v', 'v', 'i', '1') },
8531 { AV_CODEC_ID_EVC, MKTAG('e', 'v', 'c', '1') },
8532 { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'p', '4', 'v') },
8533 { AV_CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', '4', 'v') },
8534 { AV_CODEC_ID_MJPEG, MKTAG('m', 'p', '4', 'v') },
8535 { AV_CODEC_ID_PNG, MKTAG('m', 'p', '4', 'v') },
8536 { AV_CODEC_ID_JPEG2000, MKTAG('m', 'p', '4', 'v') },
8537 { AV_CODEC_ID_VC1, MKTAG('v', 'c', '-', '1') },
8538 { AV_CODEC_ID_DIRAC, MKTAG('d', 'r', 'a', 'c') },
8539 { AV_CODEC_ID_TSCC2, MKTAG('m', 'p', '4', 'v') },
8540 { AV_CODEC_ID_VP9, MKTAG('v', 'p', '0', '9') },
8541 { AV_CODEC_ID_AV1, MKTAG('a', 'v', '0', '1') },
8542 { AV_CODEC_ID_AAC, MKTAG('m', 'p', '4', 'a') },
8543 { AV_CODEC_ID_ALAC, MKTAG('a', 'l', 'a', 'c') },
8544 { AV_CODEC_ID_MP4ALS, MKTAG('m', 'p', '4', 'a') },
8545 { AV_CODEC_ID_MP3, MKTAG('m', 'p', '4', 'a') },
8546 { AV_CODEC_ID_MP2, MKTAG('m', 'p', '4', 'a') },
8547 { AV_CODEC_ID_AC3, MKTAG('a', 'c', '-', '3') },
8548 { AV_CODEC_ID_EAC3, MKTAG('e', 'c', '-', '3') },
8549 { AV_CODEC_ID_DTS, MKTAG('m', 'p', '4', 'a') },
8550 { AV_CODEC_ID_TRUEHD, MKTAG('m', 'l', 'p', 'a') },
8551 { AV_CODEC_ID_FLAC, MKTAG('f', 'L', 'a', 'C') },
8552 { AV_CODEC_ID_OPUS, MKTAG('O', 'p', 'u', 's') },
8553 { AV_CODEC_ID_VORBIS, MKTAG('m', 'p', '4', 'a') },
8554 { AV_CODEC_ID_QCELP, MKTAG('m', 'p', '4', 'a') },
8555 { AV_CODEC_ID_EVRC, MKTAG('m', 'p', '4', 'a') },
8556 { AV_CODEC_ID_DVD_SUBTITLE, MKTAG('m', 'p', '4', 's') },
8557 { AV_CODEC_ID_MOV_TEXT, MKTAG('t', 'x', '3', 'g') },
8558 { AV_CODEC_ID_BIN_DATA, MKTAG('g', 'p', 'm', 'd') },
8559 { AV_CODEC_ID_MPEGH_3D_AUDIO, MKTAG('m', 'h', 'm', '1') },
8560 { AV_CODEC_ID_TTML, MOV_MP4_TTML_TAG },
8561 { AV_CODEC_ID_TTML, MOV_ISMV_TTML_TAG },
8562
8563 /* ISO/IEC 23003-5 integer formats */
8564 { AV_CODEC_ID_PCM_S16BE, MOV_MP4_IPCM_TAG },
8565 { AV_CODEC_ID_PCM_S16LE, MOV_MP4_IPCM_TAG },
8566 { AV_CODEC_ID_PCM_S24BE, MOV_MP4_IPCM_TAG },
8567 { AV_CODEC_ID_PCM_S24LE, MOV_MP4_IPCM_TAG },
8568 { AV_CODEC_ID_PCM_S32BE, MOV_MP4_IPCM_TAG },
8569 { AV_CODEC_ID_PCM_S32LE, MOV_MP4_IPCM_TAG },
8570 /* ISO/IEC 23003-5 floating-point formats */
8571 { AV_CODEC_ID_PCM_F32BE, MOV_MP4_FPCM_TAG },
8572 { AV_CODEC_ID_PCM_F32LE, MOV_MP4_FPCM_TAG },
8573 { AV_CODEC_ID_PCM_F64BE, MOV_MP4_FPCM_TAG },
8574 { AV_CODEC_ID_PCM_F64LE, MOV_MP4_FPCM_TAG },
8575
8576 { AV_CODEC_ID_NONE, 0 },
8577 };
8578 #if CONFIG_MP4_MUXER || CONFIG_PSP_MUXER
8579 static const AVCodecTag *const mp4_codec_tags_list[] = { codec_mp4_tags, NULL };
8580 #endif
8581
8582 static const AVCodecTag codec_ism_tags[] = {
8583 { AV_CODEC_ID_WMAPRO , MKTAG('w', 'm', 'a', ' ') },
8584 { AV_CODEC_ID_TTML , MOV_ISMV_TTML_TAG },
8585 { AV_CODEC_ID_NONE , 0 },
8586 };
8587
8588 static const AVCodecTag codec_ipod_tags[] = {
8589 { AV_CODEC_ID_H264, MKTAG('a','v','c','1') },
8590 { AV_CODEC_ID_MPEG4, MKTAG('m','p','4','v') },
8591 { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') },
8592 { AV_CODEC_ID_ALAC, MKTAG('a','l','a','c') },
8593 { AV_CODEC_ID_AC3, MKTAG('a','c','-','3') },
8594 { AV_CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') },
8595 { AV_CODEC_ID_MOV_TEXT, MKTAG('t','e','x','t') },
8596 { AV_CODEC_ID_NONE, 0 },
8597 };
8598
8599 static const AVCodecTag codec_f4v_tags[] = {
8600 { AV_CODEC_ID_MP3, MKTAG('.','m','p','3') },
8601 { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') },
8602 { AV_CODEC_ID_H264, MKTAG('a','v','c','1') },
8603 { AV_CODEC_ID_VP6A, MKTAG('V','P','6','A') },
8604 { AV_CODEC_ID_VP6F, MKTAG('V','P','6','F') },
8605 { AV_CODEC_ID_NONE, 0 },
8606 };
8607
8608 #if CONFIG_AVIF_MUXER
8609
8610 static const AVOption avif_options[] = {
8611 { "movie_timescale", "set movie timescale", offsetof(MOVMuxContext, movie_timescale), AV_OPT_TYPE_INT, {.i64 = MOV_TIMESCALE}, 1, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
8612 { "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 },
8613 { NULL },
8614 };
8615 static const AVCodecTag codec_avif_tags[] = {
8616 { AV_CODEC_ID_AV1, MKTAG('a','v','0','1') },
8617 { AV_CODEC_ID_NONE, 0 },
8618 };
8619 static const AVCodecTag *const codec_avif_tags_list[] = { codec_avif_tags, NULL };
8620
8621 static const AVClass mov_avif_muxer_class = {
8622 .class_name = "avif muxer",
8623 .item_name = av_default_item_name,
8624 .option = avif_options,
8625 .version = LIBAVUTIL_VERSION_INT,
8626 };
8627 #endif
8628
8629 #if CONFIG_MOV_MUXER
8630 const FFOutputFormat ff_mov_muxer = {
8631 .p.name = "mov",
8632 .p.long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
8633 .p.extensions = "mov",
8634 .priv_data_size = sizeof(MOVMuxContext),
8635 .p.audio_codec = AV_CODEC_ID_AAC,
8636 .p.video_codec = CONFIG_LIBX264_ENCODER ?
8637 AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4,
8638 .init = mov_init,
8639 .write_header = mov_write_header,
8640 .write_packet = mov_write_packet,
8641 .write_trailer = mov_write_trailer,
8642 .deinit = mov_free,
8643 .p.flags = AVFMT_GLOBALHEADER | AVFMT_TS_NEGATIVE | AVFMT_VARIABLE_FPS
8644 #if FF_API_ALLOW_FLUSH
8645 | AVFMT_ALLOW_FLUSH
8646 #endif
8647 ,
8648 .p.codec_tag = (const AVCodecTag* const []){
8649 ff_codec_movvideo_tags, ff_codec_movaudio_tags, ff_codec_movsubtitle_tags, 0
8650 },
8651 .check_bitstream = mov_check_bitstream,
8652 .p.priv_class = &mov_isobmff_muxer_class,
8653 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
8654 };
8655 #endif
8656 #if CONFIG_TGP_MUXER
8657 const FFOutputFormat ff_tgp_muxer = {
8658 .p.name = "3gp",
8659 .p.long_name = NULL_IF_CONFIG_SMALL("3GP (3GPP file format)"),
8660 .p.extensions = "3gp",
8661 .priv_data_size = sizeof(MOVMuxContext),
8662 .p.audio_codec = AV_CODEC_ID_AMR_NB,
8663 .p.video_codec = AV_CODEC_ID_H263,
8664 .init = mov_init,
8665 .write_header = mov_write_header,
8666 .write_packet = mov_write_packet,
8667 .write_trailer = mov_write_trailer,
8668 .deinit = mov_free,
8669 #if FF_API_ALLOW_FLUSH
8670 .p.flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
8671 #else
8672 .p.flags = AVFMT_GLOBALHEADER | AVFMT_TS_NEGATIVE,
8673 #endif
8674 .p.codec_tag = codec_3gp_tags_list,
8675 .check_bitstream = mov_check_bitstream,
8676 .p.priv_class = &mov_isobmff_muxer_class,
8677 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
8678 };
8679 #endif
8680 #if CONFIG_MP4_MUXER
8681 const FFOutputFormat ff_mp4_muxer = {
8682 .p.name = "mp4",
8683 .p.long_name = NULL_IF_CONFIG_SMALL("MP4 (MPEG-4 Part 14)"),
8684 .p.mime_type = "video/mp4",
8685 .p.extensions = "mp4",
8686 .priv_data_size = sizeof(MOVMuxContext),
8687 .p.audio_codec = AV_CODEC_ID_AAC,
8688 .p.video_codec = CONFIG_LIBX264_ENCODER ?
8689 AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4,
8690 .init = mov_init,
8691 .write_header = mov_write_header,
8692 .write_packet = mov_write_packet,
8693 .write_trailer = mov_write_trailer,
8694 .deinit = mov_free,
8695 .p.flags = AVFMT_GLOBALHEADER | AVFMT_TS_NEGATIVE | AVFMT_VARIABLE_FPS
8696 #if FF_API_ALLOW_FLUSH
8697 | AVFMT_ALLOW_FLUSH
8698 #endif
8699 ,
8700 .p.codec_tag = mp4_codec_tags_list,
8701 .check_bitstream = mov_check_bitstream,
8702 .p.priv_class = &mov_isobmff_muxer_class,
8703 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
8704 };
8705 #endif
8706 #if CONFIG_PSP_MUXER
8707 const FFOutputFormat ff_psp_muxer = {
8708 .p.name = "psp",
8709 .p.long_name = NULL_IF_CONFIG_SMALL("PSP MP4 (MPEG-4 Part 14)"),
8710 .p.extensions = "mp4,psp",
8711 .priv_data_size = sizeof(MOVMuxContext),
8712 .p.audio_codec = AV_CODEC_ID_AAC,
8713 .p.video_codec = CONFIG_LIBX264_ENCODER ?
8714 AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4,
8715 .init = mov_init,
8716 .write_header = mov_write_header,
8717 .write_packet = mov_write_packet,
8718 .write_trailer = mov_write_trailer,
8719 .deinit = mov_free,
8720 #if FF_API_ALLOW_FLUSH
8721 .p.flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
8722 #else
8723 .p.flags = AVFMT_GLOBALHEADER | AVFMT_TS_NEGATIVE,
8724 #endif
8725 .p.codec_tag = mp4_codec_tags_list,
8726 .check_bitstream = mov_check_bitstream,
8727 .p.priv_class = &mov_isobmff_muxer_class,
8728 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
8729 };
8730 #endif
8731 #if CONFIG_TG2_MUXER
8732 const FFOutputFormat ff_tg2_muxer = {
8733 .p.name = "3g2",
8734 .p.long_name = NULL_IF_CONFIG_SMALL("3GP2 (3GPP2 file format)"),
8735 .p.extensions = "3g2",
8736 .priv_data_size = sizeof(MOVMuxContext),
8737 .p.audio_codec = AV_CODEC_ID_AMR_NB,
8738 .p.video_codec = AV_CODEC_ID_H263,
8739 .init = mov_init,
8740 .write_header = mov_write_header,
8741 .write_packet = mov_write_packet,
8742 .write_trailer = mov_write_trailer,
8743 .deinit = mov_free,
8744 #if FF_API_ALLOW_FLUSH
8745 .p.flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
8746 #else
8747 .p.flags = AVFMT_GLOBALHEADER | AVFMT_TS_NEGATIVE,
8748 #endif
8749 .p.codec_tag = codec_3gp_tags_list,
8750 .check_bitstream = mov_check_bitstream,
8751 .p.priv_class = &mov_isobmff_muxer_class,
8752 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
8753 };
8754 #endif
8755 #if CONFIG_IPOD_MUXER
8756 const FFOutputFormat ff_ipod_muxer = {
8757 .p.name = "ipod",
8758 .p.long_name = NULL_IF_CONFIG_SMALL("iPod H.264 MP4 (MPEG-4 Part 14)"),
8759 .p.mime_type = "video/mp4",
8760 .p.extensions = "m4v,m4a,m4b",
8761 .priv_data_size = sizeof(MOVMuxContext),
8762 .p.audio_codec = AV_CODEC_ID_AAC,
8763 .p.video_codec = AV_CODEC_ID_H264,
8764 .init = mov_init,
8765 .write_header = mov_write_header,
8766 .write_packet = mov_write_packet,
8767 .write_trailer = mov_write_trailer,
8768 .deinit = mov_free,
8769 #if FF_API_ALLOW_FLUSH
8770 .p.flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
8771 #else
8772 .p.flags = AVFMT_GLOBALHEADER | AVFMT_TS_NEGATIVE,
8773 #endif
8774 .p.codec_tag = (const AVCodecTag* const []){ codec_ipod_tags, 0 },
8775 .check_bitstream = mov_check_bitstream,
8776 .p.priv_class = &mov_isobmff_muxer_class,
8777 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
8778 };
8779 #endif
8780 #if CONFIG_ISMV_MUXER
8781 const FFOutputFormat ff_ismv_muxer = {
8782 .p.name = "ismv",
8783 .p.long_name = NULL_IF_CONFIG_SMALL("ISMV/ISMA (Smooth Streaming)"),
8784 .p.mime_type = "video/mp4",
8785 .p.extensions = "ismv,isma",
8786 .priv_data_size = sizeof(MOVMuxContext),
8787 .p.audio_codec = AV_CODEC_ID_AAC,
8788 .p.video_codec = AV_CODEC_ID_H264,
8789 .init = mov_init,
8790 .write_header = mov_write_header,
8791 .write_packet = mov_write_packet,
8792 .write_trailer = mov_write_trailer,
8793 .deinit = mov_free,
8794 #if FF_API_ALLOW_FLUSH
8795 .p.flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
8796 #else
8797 .p.flags = AVFMT_GLOBALHEADER | AVFMT_TS_NEGATIVE,
8798 #endif
8799 .p.codec_tag = (const AVCodecTag* const []){
8800 codec_mp4_tags, codec_ism_tags, 0 },
8801 .check_bitstream = mov_check_bitstream,
8802 .p.priv_class = &mov_isobmff_muxer_class,
8803 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
8804 };
8805 #endif
8806 #if CONFIG_F4V_MUXER
8807 const FFOutputFormat ff_f4v_muxer = {
8808 .p.name = "f4v",
8809 .p.long_name = NULL_IF_CONFIG_SMALL("F4V Adobe Flash Video"),
8810 .p.mime_type = "application/f4v",
8811 .p.extensions = "f4v",
8812 .priv_data_size = sizeof(MOVMuxContext),
8813 .p.audio_codec = AV_CODEC_ID_AAC,
8814 .p.video_codec = AV_CODEC_ID_H264,
8815 .init = mov_init,
8816 .write_header = mov_write_header,
8817 .write_packet = mov_write_packet,
8818 .write_trailer = mov_write_trailer,
8819 .deinit = mov_free,
8820 #if FF_API_ALLOW_FLUSH
8821 .p.flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH,
8822 #else
8823 .p.flags = AVFMT_GLOBALHEADER,
8824 #endif
8825 .p.codec_tag = (const AVCodecTag* const []){ codec_f4v_tags, 0 },
8826 .check_bitstream = mov_check_bitstream,
8827 .p.priv_class = &mov_isobmff_muxer_class,
8828 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
8829 };
8830 #endif
8831 #if CONFIG_AVIF_MUXER
8832 const FFOutputFormat ff_avif_muxer = {
8833 .p.name = "avif",
8834 .p.long_name = NULL_IF_CONFIG_SMALL("AVIF"),
8835 .p.mime_type = "image/avif",
8836 .p.extensions = "avif",
8837 .priv_data_size = sizeof(MOVMuxContext),
8838 .p.video_codec = AV_CODEC_ID_AV1,
8839 .init = mov_init,
8840 .write_header = mov_write_header,
8841 .write_packet = mov_write_packet,
8842 .write_trailer = avif_write_trailer,
8843 .deinit = mov_free,
8844 #if FF_API_ALLOW_FLUSH
8845 .p.flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH,
8846 #else
8847 .p.flags = AVFMT_GLOBALHEADER,
8848 #endif
8849 .p.codec_tag = codec_avif_tags_list,
8850 .p.priv_class = &mov_avif_muxer_class,
8851 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
8852 };
8853 #endif
8854