FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/fftools/ffmpeg_mux_init.c
Date: 2026-10-19 01:23:10
Exec Total Coverage
Lines: 1495 2189 68.3%
Functions: 48 55 87.3%
Branches: 1033 1698 60.8%

Line Branch Exec Source
1 /*
2 * Muxer/output file setup.
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include <string.h>
22
23 #include "cmdutils.h"
24 #include "ffmpeg.h"
25 #include "ffmpeg_mux.h"
26 #include "ffmpeg_sched.h"
27 #include "fopen_utf8.h"
28
29 #include "libavformat/avformat.h"
30 #include "libavformat/avio.h"
31
32 #include "libavcodec/avcodec.h"
33
34 #include "libavfilter/avfilter.h"
35
36 #include "libavutil/avassert.h"
37 #include "libavutil/avstring.h"
38 #include "libavutil/avutil.h"
39 #include "libavutil/bprint.h"
40 #include "libavutil/dict.h"
41 #include "libavutil/display.h"
42 #include "libavutil/getenv_utf8.h"
43 #include "libavutil/iamf.h"
44 #include "libavutil/intreadwrite.h"
45 #include "libavutil/log.h"
46 #include "libavutil/mem.h"
47 #include "libavutil/opt.h"
48 #include "libavutil/parseutils.h"
49 #include "libavutil/pixdesc.h"
50 #include "libavutil/stereo3d.h"
51
52 #define DEFAULT_PASS_LOGFILENAME_PREFIX "ffmpeg2pass"
53
54 6902 static int check_opt_bitexact(void *ctx, const AVDictionary *opts,
55 const char *opt_name, int flag)
56 {
57 6902 const AVDictionaryEntry *e = av_dict_get(opts, opt_name, NULL, 0);
58
59
2/2
✓ Branch 0 taken 5815 times.
✓ Branch 1 taken 1087 times.
6902 if (e) {
60 5815 const AVOption *o = av_opt_find(ctx, opt_name, NULL, 0, 0);
61 5815 int val = 0;
62
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5815 times.
5815 if (!o)
63 ✗ return 0;
64 5815 av_opt_eval_flags(ctx, o, e->value, &val);
65 5815 return !!(val & flag);
66 }
67 1087 return 0;
68 }
69
70 9595 static int choose_encoder(const OptionsContext *o, AVFormatContext *s,
71 MuxStream *ms, const AVCodec **enc)
72 {
73 9595 OutputStream *ost = &ms->ost;
74 9595 enum AVMediaType type = ost->type;
75 9595 const char *codec_name = NULL;
76
77 9595 *enc = NULL;
78
79 9595 opt_match_per_stream_str(ost, &o->codec_names, s, ost->st, &codec_name);
80
81
4/4
✓ Branch 0 taken 2136 times.
✓ Branch 1 taken 7459 times.
✓ Branch 2 taken 97 times.
✓ Branch 3 taken 2039 times.
9595 if (type != AVMEDIA_TYPE_VIDEO &&
82
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 84 times.
97 type != AVMEDIA_TYPE_AUDIO &&
83 type != AVMEDIA_TYPE_SUBTITLE) {
84
3/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
13 if (codec_name && strcmp(codec_name, "copy")) {
85 ✗ const char *type_str = av_get_media_type_string(type);
86 ✗ av_log(ost, AV_LOG_FATAL,
87 "Encoder '%s' specified, but only '-codec copy' supported "
88 "for %s streams\n", codec_name, type_str);
89 ✗ return AVERROR(ENOSYS);
90 }
91 13 return 0;
92 }
93
94
2/2
✓ Branch 0 taken 4308 times.
✓ Branch 1 taken 5274 times.
9582 if (!codec_name) {
95 4308 ms->par_in->codec_id = av_guess_codec(s->oformat, NULL, s->url, NULL, ost->type);
96 4308 *enc = avcodec_find_encoder(ms->par_in->codec_id);
97
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4308 times.
4308 if (!*enc) {
98 ✗ av_log(ost, AV_LOG_FATAL, "Automatic encoder selection failed "
99 "Default encoder for format %s (codec %s) is "
100 "probably disabled. Please choose an encoder manually.\n",
101 ✗ s->oformat->name, avcodec_get_name(ms->par_in->codec_id));
102 ✗ return AVERROR_ENCODER_NOT_FOUND;
103 }
104
2/2
✓ Branch 0 taken 4304 times.
✓ Branch 1 taken 970 times.
5274 } else if (strcmp(codec_name, "copy")) {
105 4304 int ret = find_codec(ost, codec_name, ost->type, 1, enc);
106
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4304 times.
4304 if (ret < 0)
107 ✗ return ret;
108 4304 ms->par_in->codec_id = (*enc)->id;
109 }
110
111 9582 return 0;
112 }
113
114 ✗ static char *get_line(AVIOContext *s, AVBPrint *bprint)
115 {
116 char c;
117
118 ✗ while ((c = avio_r8(s)) && c != '\n')
119 ✗ av_bprint_chars(bprint, c, 1);
120
121 ✗ if (!av_bprint_is_complete(bprint))
122 ✗ return NULL;
123
124 ✗ return bprint->str;
125 }
126
127 ✗ static int get_preset_file_2(const char *preset_name, const char *codec_name, AVIOContext **s)
128 {
129 ✗ int i, ret = -1;
130 char filename[1000];
131 ✗ char *env_avconv_datadir = getenv_utf8("AVCONV_DATADIR");
132 ✗ char *env_home = getenv_utf8("HOME");
133 ✗ const char *base[3] = { env_avconv_datadir,
134 env_home,
135 AVCONV_DATADIR,
136 };
137
138 ✗ for (i = 0; i < FF_ARRAY_ELEMS(base) && ret < 0; i++) {
139 ✗ if (!base[i])
140 ✗ continue;
141 ✗ if (codec_name) {
142 ✗ snprintf(filename, sizeof(filename), "%s%s/%s-%s.avpreset", base[i],
143 i != 1 ? "" : "/.avconv", codec_name, preset_name);
144 ✗ ret = avio_open2(s, filename, AVIO_FLAG_READ, &int_cb, NULL);
145 }
146 ✗ if (ret < 0) {
147 ✗ snprintf(filename, sizeof(filename), "%s%s/%s.avpreset", base[i],
148 i != 1 ? "" : "/.avconv", preset_name);
149 ✗ ret = avio_open2(s, filename, AVIO_FLAG_READ, &int_cb, NULL);
150 }
151 }
152 ✗ freeenv_utf8(env_home);
153 ✗ freeenv_utf8(env_avconv_datadir);
154 ✗ return ret;
155 }
156
157 typedef struct EncStatsFile {
158 char *path;
159 AVIOContext *io;
160 } EncStatsFile;
161
162 static EncStatsFile *enc_stats_files;
163 static int nb_enc_stats_files;
164
165 ✗ static int enc_stats_get_file(AVIOContext **io, const char *path)
166 {
167 EncStatsFile *esf;
168 int ret;
169
170 ✗ for (int i = 0; i < nb_enc_stats_files; i++)
171 ✗ if (!strcmp(path, enc_stats_files[i].path)) {
172 ✗ *io = enc_stats_files[i].io;
173 ✗ return 0;
174 }
175
176 ✗ ret = GROW_ARRAY(enc_stats_files, nb_enc_stats_files);
177 ✗ if (ret < 0)
178 ✗ return ret;
179
180 ✗ esf = &enc_stats_files[nb_enc_stats_files - 1];
181
182 ✗ ret = avio_open2(&esf->io, path, AVIO_FLAG_WRITE, &int_cb, NULL);
183 ✗ if (ret < 0) {
184 ✗ av_log(NULL, AV_LOG_ERROR, "Error opening stats file '%s': %s\n",
185 ✗ path, av_err2str(ret));
186 ✗ return ret;
187 }
188
189 ✗ esf->path = av_strdup(path);
190 ✗ if (!esf->path)
191 ✗ return AVERROR(ENOMEM);
192
193 ✗ *io = esf->io;
194
195 ✗ return 0;
196 }
197
198 8935 void of_enc_stats_close(void)
199 {
200
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8935 times.
8935 for (int i = 0; i < nb_enc_stats_files; i++) {
201 ✗ av_freep(&enc_stats_files[i].path);
202 ✗ avio_closep(&enc_stats_files[i].io);
203 }
204 8935 av_freep(&enc_stats_files);
205 8935 nb_enc_stats_files = 0;
206 8935 }
207
208 ✗ static int unescape(char **pdst, size_t *dst_len,
209 const char **pstr, char delim)
210 {
211 ✗ const char *str = *pstr;
212 char *dst;
213 size_t len, idx;
214
215 ✗ *pdst = NULL;
216
217 ✗ len = strlen(str);
218 ✗ if (!len)
219 ✗ return 0;
220
221 ✗ dst = av_malloc(len + 1);
222 ✗ if (!dst)
223 ✗ return AVERROR(ENOMEM);
224
225 ✗ for (idx = 0; *str; idx++, str++) {
226 ✗ if (str[0] == '\\' && str[1])
227 ✗ str++;
228 ✗ else if (*str == delim)
229 ✗ break;
230
231 ✗ dst[idx] = *str;
232 }
233 ✗ if (!idx) {
234 ✗ av_freep(&dst);
235 ✗ return 0;
236 }
237
238 ✗ dst[idx] = 0;
239
240 ✗ *pdst = dst;
241 ✗ *dst_len = idx;
242 ✗ *pstr = str;
243
244 ✗ return 0;
245 }
246
247 ✗ static int enc_stats_init(OutputStream *ost, EncStats *es, int pre,
248 const char *path, const char *fmt_spec)
249 {
250 static const struct {
251 enum EncStatsType type;
252 const char *str;
253 unsigned pre_only:1;
254 unsigned post_only:1;
255 unsigned need_input_data:1;
256 } fmt_specs[] = {
257 { ENC_STATS_FILE_IDX, "fidx" },
258 { ENC_STATS_STREAM_IDX, "sidx" },
259 { ENC_STATS_FRAME_NUM, "n" },
260 { ENC_STATS_FRAME_NUM_IN, "ni", 0, 0, 1 },
261 { ENC_STATS_TIMEBASE, "tb" },
262 { ENC_STATS_TIMEBASE_IN, "tbi", 0, 0, 1 },
263 { ENC_STATS_PTS, "pts" },
264 { ENC_STATS_PTS_TIME, "t" },
265 { ENC_STATS_PTS_IN, "ptsi", 0, 0, 1 },
266 { ENC_STATS_PTS_TIME_IN, "ti", 0, 0, 1 },
267 { ENC_STATS_DTS, "dts", 0, 1 },
268 { ENC_STATS_DTS_TIME, "dt", 0, 1 },
269 { ENC_STATS_SAMPLE_NUM, "sn", 1 },
270 { ENC_STATS_NB_SAMPLES, "samp", 1 },
271 { ENC_STATS_PKT_SIZE, "size", 0, 1 },
272 { ENC_STATS_BITRATE, "br", 0, 1 },
273 { ENC_STATS_AVG_BITRATE, "abr", 0, 1 },
274 { ENC_STATS_KEYFRAME, "key", 0, 1 },
275 };
276 ✗ const char *next = fmt_spec;
277
278 int ret;
279
280 ✗ while (*next) {
281 EncStatsComponent *c;
282 char *val;
283 size_t val_len;
284
285 // get the sequence up until next opening brace
286 ✗ ret = unescape(&val, &val_len, &next, '{');
287 ✗ if (ret < 0)
288 ✗ return ret;
289
290 ✗ if (val) {
291 ✗ ret = GROW_ARRAY(es->components, es->nb_components);
292 ✗ if (ret < 0) {
293 ✗ av_freep(&val);
294 ✗ return ret;
295 }
296
297 ✗ c = &es->components[es->nb_components - 1];
298 ✗ c->type = ENC_STATS_LITERAL;
299 ✗ c->str = val;
300 ✗ c->str_len = val_len;
301 }
302
303 ✗ if (!*next)
304 ✗ break;
305 ✗ next++;
306
307 // get the part inside braces
308 ✗ ret = unescape(&val, &val_len, &next, '}');
309 ✗ if (ret < 0)
310 ✗ return ret;
311
312 ✗ if (!val) {
313 ✗ av_log(NULL, AV_LOG_ERROR,
314 "Empty formatting directive in: %s\n", fmt_spec);
315 ✗ return AVERROR(EINVAL);
316 }
317
318 ✗ if (!*next) {
319 ✗ av_log(NULL, AV_LOG_ERROR,
320 "Missing closing brace in: %s\n", fmt_spec);
321 ✗ ret = AVERROR(EINVAL);
322 ✗ goto fail;
323 }
324 ✗ next++;
325
326 ✗ ret = GROW_ARRAY(es->components, es->nb_components);
327 ✗ if (ret < 0)
328 ✗ goto fail;
329
330 ✗ c = &es->components[es->nb_components - 1];
331
332 ✗ for (size_t i = 0; i < FF_ARRAY_ELEMS(fmt_specs); i++) {
333 ✗ if (!strcmp(val, fmt_specs[i].str)) {
334 ✗ if ((pre && fmt_specs[i].post_only) || (!pre && fmt_specs[i].pre_only)) {
335 ✗ av_log(NULL, AV_LOG_ERROR,
336 "Format directive '%s' may only be used %s-encoding\n",
337 val, pre ? "post" : "pre");
338 ✗ ret = AVERROR(EINVAL);
339 ✗ goto fail;
340 }
341
342 ✗ c->type = fmt_specs[i].type;
343
344 ✗ if (fmt_specs[i].need_input_data && !ost->ist) {
345 ✗ av_log(ost, AV_LOG_WARNING,
346 "Format directive '%s' is unavailable, because "
347 "this output stream has no associated input stream\n",
348 val);
349 }
350
351 ✗ break;
352 }
353 }
354
355 ✗ if (!c->type) {
356 ✗ av_log(NULL, AV_LOG_ERROR, "Invalid format directive: %s\n", val);
357 ✗ ret = AVERROR(EINVAL);
358 ✗ goto fail;
359 }
360
361 ✗ fail:
362 ✗ av_freep(&val);
363 ✗ if (ret < 0)
364 ✗ return ret;
365 }
366
367 ✗ ret = pthread_mutex_init(&es->lock, NULL);
368 ✗ if (ret)
369 ✗ return AVERROR(ret);
370 ✗ es->lock_initialized = 1;
371
372 ✗ ret = enc_stats_get_file(&es->io, path);
373 ✗ if (ret < 0)
374 ✗ return ret;
375
376 ✗ return 0;
377 }
378
379 2788 static const char *output_stream_item_name(void *obj)
380 {
381 2788 const MuxStream *ms = obj;
382
383 2788 return ms->log_name;
384 }
385
386 static const AVClass output_stream_class = {
387 .class_name = "OutputStream",
388 .version = LIBAVUTIL_VERSION_INT,
389 .item_name = output_stream_item_name,
390 .category = AV_CLASS_CATEGORY_MUXER,
391 };
392
393 9595 static MuxStream *mux_stream_alloc(Muxer *mux, enum AVMediaType type)
394 {
395 9595 const char *type_str = av_get_media_type_string(type);
396 MuxStream *ms;
397
398 9595 ms = allocate_array_elem(&mux->of.streams, sizeof(*ms), &mux->of.nb_streams);
399
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9595 times.
9595 if (!ms)
400 ✗ return NULL;
401
402 9595 ms->ost.file = &mux->of;
403 9595 ms->ost.index = mux->of.nb_streams - 1;
404 9595 ms->ost.type = type;
405
406 9595 ms->ost.class = &output_stream_class;
407
408 9595 ms->sch_idx = -1;
409 9595 ms->sch_idx_enc = -1;
410
411
1/2
✓ Branch 0 taken 9595 times.
✗ Branch 1 not taken.
9595 snprintf(ms->log_name, sizeof(ms->log_name), "%cost#%d:%d",
412 9595 type_str ? *type_str : '?', mux->of.index, ms->ost.index);
413
414 9595 return ms;
415 }
416
417 8568 static int ost_get_filters(const OptionsContext *o, AVFormatContext *oc,
418 OutputStream *ost, char **dst)
419 {
420 8568 const char *filters = NULL;
421 8568 opt_match_per_stream_str(ost, &o->filters, oc, ost->st, &filters);
422
423
2/2
✓ Branch 0 taken 1546 times.
✓ Branch 1 taken 7022 times.
8568 if (!ost->ist) {
424
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1546 times.
1546 if (filters) {
425 ✗ av_log(ost, AV_LOG_ERROR,
426 "Filtergraph '%s' was specified for a stream fed from a complex "
427 "filtergraph. Simple and complex filtering cannot be used "
428 "together for the same stream.\n", filters);
429 ✗ return AVERROR(EINVAL);
430 }
431 1546 return 0;
432 }
433
434
2/2
✓ Branch 0 taken 3977 times.
✓ Branch 1 taken 3045 times.
7022 if (filters)
435 3977 *dst = av_strdup(filters);
436 else
437
2/2
✓ Branch 0 taken 2358 times.
✓ Branch 1 taken 687 times.
3045 *dst = av_strdup(ost->type == AVMEDIA_TYPE_VIDEO ? "null" : "anull");
438
1/2
✓ Branch 0 taken 7022 times.
✗ Branch 1 not taken.
7022 return *dst ? 0 : AVERROR(ENOMEM);
439 }
440
441 ✗ static int parse_matrix_coeffs(void *logctx, uint16_t *dest, const char *str)
442 {
443 ✗ const char *p = str;
444 ✗ for (int i = 0;; i++) {
445 ✗ dest[i] = atoi(p);
446 ✗ if (i == 63)
447 ✗ break;
448 ✗ p = strchr(p, ',');
449 ✗ if (!p) {
450 ✗ av_log(logctx, AV_LOG_FATAL,
451 "Syntax error in matrix \"%s\" at coeff %d\n", str, i);
452 ✗ return AVERROR(EINVAL);
453 }
454 ✗ p++;
455 }
456
457 ✗ return 0;
458 }
459
460 662 static int pixfmt_in_list(const enum AVPixelFormat *formats, enum AVPixelFormat format)
461 {
462
1/2
✓ Branch 0 taken 3730 times.
✗ Branch 1 not taken.
3730 for (; *formats != AV_PIX_FMT_NONE; formats++)
463
2/2
✓ Branch 0 taken 662 times.
✓ Branch 1 taken 3068 times.
3730 if (*formats == format)
464 662 return 1;
465 ✗ return 0;
466 }
467
468 static enum AVPixelFormat
469 ✗ choose_pixel_fmt(const AVCodecContext *avctx, enum AVPixelFormat target)
470 {
471 const enum AVPixelFormat *p;
472 ✗ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(target);
473 //FIXME: This should check for AV_PIX_FMT_FLAG_ALPHA after PAL8 pixel format without alpha is implemented
474 ✗ int has_alpha = desc ? desc->nb_components % 2 == 0 : 0;
475 ✗ enum AVPixelFormat best= AV_PIX_FMT_NONE;
476 int ret;
477
478 ✗ ret = avcodec_get_supported_config(avctx, NULL, AV_CODEC_CONFIG_PIX_FORMAT,
479 0, (const void **) &p, NULL);
480 ✗ if (ret < 0)
481 ✗ return AV_PIX_FMT_NONE;
482
483 ✗ for (; *p != AV_PIX_FMT_NONE; p++) {
484 ✗ best = av_find_best_pix_fmt_of_2(best, *p, target, has_alpha, NULL);
485 ✗ if (*p == target)
486 ✗ break;
487 }
488 ✗ if (*p == AV_PIX_FMT_NONE) {
489 ✗ if (target != AV_PIX_FMT_NONE)
490 ✗ av_log(NULL, AV_LOG_WARNING,
491 "Incompatible pixel format '%s' for codec '%s', auto-selecting format '%s'\n",
492 av_get_pix_fmt_name(target),
493 ✗ avctx->codec->name,
494 av_get_pix_fmt_name(best));
495 ✗ return best;
496 }
497 ✗ return target;
498 }
499
500 5387 static enum AVPixelFormat pix_fmt_parse(OutputStream *ost, const char *name)
501 {
502 const enum AVPixelFormat *fmts;
503 enum AVPixelFormat fmt;
504 int ret;
505
506 5387 fmt = av_get_pix_fmt(name);
507
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5387 times.
5387 if (fmt == AV_PIX_FMT_NONE) {
508 ✗ av_log(ost, AV_LOG_FATAL, "Unknown pixel format requested: %s.\n", name);
509 ✗ return AV_PIX_FMT_NONE;
510 }
511
512 5387 ret = avcodec_get_supported_config(ost->enc->enc_ctx, NULL, AV_CODEC_CONFIG_PIX_FORMAT,
513 0, (const void **) &fmts, NULL);
514
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5387 times.
5387 if (ret < 0)
515 ✗ return AV_PIX_FMT_NONE;
516
517 /* when the user specified-format is an alias for an endianness-specific
518 * one (e.g. rgb48 -> rgb48be/le), it gets translated into the native
519 * endianness by av_get_pix_fmt();
520 * the following code handles the case when the native endianness is not
521 * supported by the encoder, but the other one is */
522
3/4
✓ Branch 0 taken 331 times.
✓ Branch 1 taken 5056 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 331 times.
5387 if (fmts && !pixfmt_in_list(fmts, fmt)) {
523 ✗ const char *name_canonical = av_get_pix_fmt_name(fmt);
524 ✗ int len = strlen(name_canonical);
525
526 ✗ if (strcmp(name, name_canonical) &&
527 ✗ (!strcmp(name_canonical + len - 2, "le") ||
528 ✗ !strcmp(name_canonical + len - 2, "be"))) {
529 char name_other[64];
530 enum AVPixelFormat fmt_other;
531
532 ✗ snprintf(name_other, sizeof(name_other), "%s%ce",
533 ✗ name, name_canonical[len - 2] == 'l' ? 'b' : 'l');
534 ✗ fmt_other = av_get_pix_fmt(name_other);
535 ✗ if (fmt_other != AV_PIX_FMT_NONE && pixfmt_in_list(fmts, fmt_other)) {
536 ✗ av_log(ost, AV_LOG_VERBOSE, "Mapping pixel format %s->%s\n",
537 name, name_other);
538 ✗ fmt = fmt_other;
539 }
540 }
541 }
542
543
3/4
✓ Branch 0 taken 331 times.
✓ Branch 1 taken 5056 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 331 times.
5387 if (fmts && !pixfmt_in_list(fmts, fmt))
544 ✗ fmt = choose_pixel_fmt(ost->enc->enc_ctx, fmt);
545
546 5387 return fmt;
547 }
548
549 5 static int parse_stereo3d_type(void *logctx, const char *arg, int *type)
550 {
551 static const struct {
552 const char *name;
553 int type;
554 } aliases[] = {
555 { "2d", AV_STEREO3D_2D },
556 { "mono", AV_STEREO3D_2D },
557 { "sbs", AV_STEREO3D_SIDEBYSIDE },
558 { "sbsl", AV_STEREO3D_SIDEBYSIDE },
559 { "tb", AV_STEREO3D_TOPBOTTOM },
560 { "tbl", AV_STEREO3D_TOPBOTTOM },
561 };
562 static const enum AVStereo3DType v1_types[] = {
563 AV_STEREO3D_2D,
564 AV_STEREO3D_SIDEBYSIDE,
565 AV_STEREO3D_TOPBOTTOM,
566 };
567
568
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 for (int i = 0; i < FF_ARRAY_ELEMS(aliases); i++) {
569
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 16 times.
21 if (!av_strcasecmp(arg, aliases[i].name)) {
570 5 *type = aliases[i].type;
571 5 return 0;
572 }
573 }
574
575 ✗ for (int i = 0; i < FF_ARRAY_ELEMS(v1_types); i++) {
576 ✗ const char *name = av_stereo3d_type_name(v1_types[i]);
577 ✗ if (!av_strcasecmp(arg, name)) {
578 ✗ *type = v1_types[i];
579 ✗ return 0;
580 }
581 }
582
583 ✗ av_log(logctx, AV_LOG_ERROR,
584 "Invalid stereoscopic 3D layout '%s'. "
585 "Valid values are: 2d, mono, sbs, sbsl, side by side, "
586 "tb, tbl, top and bottom.\n", arg);
587 ✗ return AVERROR(EINVAL);
588 }
589
590 8934 static int check_stereo3d_leftovers(Muxer *mux, const OptionsContext *o)
591 {
592 8934 AVFormatContext *oc = mux->fc;
593
594
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 8934 times.
8939 for (int i = 0; i < o->stereo3ds.nb_opt; i++) {
595 5 const SpecifierOpt *so = &o->stereo3ds.opt[i];
596 5 int matched_video = 0, matched_other = 0;
597
598 /* Empty specifier applies to video only; ignore other stream types. */
599
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!so->specifier[0])
600 ✗ continue;
601
602
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 5 times.
11 for (unsigned j = 0; j < oc->nb_streams; j++) {
603 6 AVStream *st = oc->streams[j];
604
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 5 times.
6 if (!stream_specifier_match(&so->stream_spec, oc, st, mux))
605 1 continue;
606
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
607 5 matched_video++;
608 else
609 ✗ matched_other++;
610 }
611
612
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (matched_other) {
613 ✗ av_log(mux, AV_LOG_ERROR,
614 "-stereo3d is only valid for video streams (specifier '%s').\n",
615 ✗ so->specifier);
616 ✗ return AVERROR(EINVAL);
617 }
618
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!matched_video) {
619 ✗ av_log(mux, AV_LOG_ERROR,
620 "Stream specifier '%s' for -stereo3d matches no video streams.\n",
621 ✗ so->specifier);
622 ✗ return AVERROR(EINVAL);
623 }
624 }
625
626 8934 return 0;
627 }
628
629 7459 static int new_stream_video(Muxer *mux, const OptionsContext *o,
630 OutputStream *ost, int *keep_pix_fmt,
631 enum VideoSyncMethod *vsync_method)
632 {
633 7459 MuxStream *ms = ms_from_ost(ost);
634 7459 AVFormatContext *oc = mux->fc;
635 AVStream *st;
636 7459 const char *frame_rate = NULL, *max_frame_rate = NULL, *frame_aspect_ratio = NULL;
637 7459 const char *stereo3d = NULL;
638 7459 int ret = 0;
639
640 7459 st = ost->st;
641
642 7459 opt_match_per_stream_str(ost, &o->frame_rates, oc, st, &frame_rate);
643
3/4
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 7437 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 22 times.
7459 if (frame_rate && av_parse_video_rate(&ms->frame_rate, frame_rate) < 0) {
644 ✗ av_log(ost, AV_LOG_FATAL, "Invalid framerate value: %s\n", frame_rate);
645 ✗ return AVERROR(EINVAL);
646 }
647
648 7459 opt_match_per_stream_str(ost, &o->max_frame_rates, oc, st, &max_frame_rate);
649
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 7459 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
7459 if (max_frame_rate && av_parse_video_rate(&ms->max_frame_rate, max_frame_rate) < 0) {
650 ✗ av_log(ost, AV_LOG_FATAL, "Invalid maximum framerate value: %s\n", max_frame_rate);
651 ✗ return AVERROR(EINVAL);
652 }
653
654
3/4
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 7437 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 22 times.
7459 if (frame_rate && max_frame_rate) {
655 ✗ av_log(ost, AV_LOG_ERROR, "Only one of -fpsmax and -r can be set for a stream.\n");
656 ✗ return AVERROR(EINVAL);
657 }
658
659 7459 opt_match_per_stream_str(ost, &o->frame_aspect_ratios, oc, st, &frame_aspect_ratio);
660
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7459 times.
7459 if (frame_aspect_ratio) {
661 AVRational q;
662 ✗ if (av_parse_ratio(&q, frame_aspect_ratio, 255, 0, NULL) < 0 ||
663 ✗ q.num <= 0 || q.den <= 0) {
664 ✗ av_log(ost, AV_LOG_FATAL, "Invalid aspect ratio: %s\n", frame_aspect_ratio);
665 ✗ return AVERROR(EINVAL);
666 }
667 ✗ ost->frame_aspect_ratio = q;
668 }
669
670 7459 opt_match_per_stream_str(ost, &o->stereo3ds, oc, st, &stereo3d);
671
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 7454 times.
7459 if (stereo3d) {
672 5 ret = parse_stereo3d_type(ost, stereo3d, &ms->stereo3d_type);
673
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (ret < 0)
674 ✗ return ret;
675 5 ms->stereo3d_set = 1;
676 }
677
678
2/2
✓ Branch 0 taken 6986 times.
✓ Branch 1 taken 473 times.
7459 if (ost->enc) {
679 6986 AVCodecContext *video_enc = ost->enc->enc_ctx;
680 6986 const char *p = NULL, *fps_mode = NULL;
681 6986 const char *frame_size = NULL;
682 6986 const char *frame_pix_fmt = NULL;
683 6986 const char *intra_matrix = NULL, *inter_matrix = NULL;
684 6986 const char *chroma_intra_matrix = NULL;
685 6986 int do_pass = 0;
686 int i;
687
688 6986 opt_match_per_stream_str(ost, &o->frame_sizes, oc, st, &frame_size);
689
2/2
✓ Branch 0 taken 1350 times.
✓ Branch 1 taken 5636 times.
6986 if (frame_size) {
690 1350 ret = av_parse_video_size(&video_enc->width, &video_enc->height, frame_size);
691
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1350 times.
1350 if (ret < 0) {
692 ✗ av_log(ost, AV_LOG_FATAL, "Invalid frame size: %s.\n", frame_size);
693 ✗ return AVERROR(EINVAL);
694 }
695 }
696
697 6986 opt_match_per_stream_str(ost, &o->frame_pix_fmts, oc, st, &frame_pix_fmt);
698
3/4
✓ Branch 0 taken 5387 times.
✓ Branch 1 taken 1599 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5387 times.
6986 if (frame_pix_fmt && *frame_pix_fmt == '+') {
699 ✗ *keep_pix_fmt = 1;
700 ✗ if (!*++frame_pix_fmt)
701 ✗ frame_pix_fmt = NULL;
702 }
703
2/2
✓ Branch 0 taken 5387 times.
✓ Branch 1 taken 1599 times.
6986 if (frame_pix_fmt) {
704 5387 video_enc->pix_fmt = pix_fmt_parse(ost, frame_pix_fmt);
705
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5387 times.
5387 if (video_enc->pix_fmt == AV_PIX_FMT_NONE)
706 ✗ return AVERROR(EINVAL);
707 }
708
709 6986 opt_match_per_stream_str(ost, &o->intra_matrices, oc, st, &intra_matrix);
710
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6986 times.
6986 if (intra_matrix) {
711 ✗ if (!(video_enc->intra_matrix = av_mallocz(sizeof(*video_enc->intra_matrix) * 64)))
712 ✗ return AVERROR(ENOMEM);
713
714 ✗ ret = parse_matrix_coeffs(ost, video_enc->intra_matrix, intra_matrix);
715 ✗ if (ret < 0)
716 ✗ return ret;
717 }
718 6986 opt_match_per_stream_str(ost, &o->chroma_intra_matrices, oc, st, &chroma_intra_matrix);
719
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6986 times.
6986 if (chroma_intra_matrix) {
720 ✗ if (!(video_enc->chroma_intra_matrix = av_mallocz(sizeof(*video_enc->chroma_intra_matrix) * 64)))
721 ✗ return AVERROR(ENOMEM);
722 ✗ ret = parse_matrix_coeffs(ost, video_enc->chroma_intra_matrix, chroma_intra_matrix);
723 ✗ if (ret < 0)
724 ✗ return ret;
725 }
726 6986 opt_match_per_stream_str(ost, &o->inter_matrices, oc, st, &inter_matrix);
727
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6986 times.
6986 if (inter_matrix) {
728 ✗ if (!(video_enc->inter_matrix = av_mallocz(sizeof(*video_enc->inter_matrix) * 64)))
729 ✗ return AVERROR(ENOMEM);
730 ✗ ret = parse_matrix_coeffs(ost, video_enc->inter_matrix, inter_matrix);
731 ✗ if (ret < 0)
732 ✗ return ret;
733 }
734
735 6986 opt_match_per_stream_str(ost, &o->rc_overrides, oc, st, &p);
736
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6986 times.
6986 for (i = 0; p; i++) {
737 int start, end, q;
738 ✗ int e = sscanf(p, "%d,%d,%d", &start, &end, &q);
739 ✗ if (e != 3) {
740 ✗ av_log(ost, AV_LOG_FATAL, "error parsing rc_override\n");
741 ✗ return AVERROR(EINVAL);
742 }
743 ✗ video_enc->rc_override =
744 ✗ av_realloc_array(video_enc->rc_override,
745 ✗ i + 1, sizeof(RcOverride));
746 ✗ if (!video_enc->rc_override) {
747 ✗ av_log(ost, AV_LOG_FATAL, "Could not (re)allocate memory for rc_override.\n");
748 ✗ return AVERROR(ENOMEM);
749 }
750 ✗ video_enc->rc_override[i].start_frame = start;
751 ✗ video_enc->rc_override[i].end_frame = end;
752 ✗ if (q > 0) {
753 ✗ video_enc->rc_override[i].qscale = q;
754 ✗ video_enc->rc_override[i].quality_factor = 1.0;
755 }
756 else {
757 ✗ video_enc->rc_override[i].qscale = 0;
758 ✗ video_enc->rc_override[i].quality_factor = -q/100.0;
759 }
760 ✗ p = strchr(p, '/');
761 ✗ if (p) p++;
762 }
763 6986 video_enc->rc_override_count = i;
764
765 /* two pass mode */
766 6986 opt_match_per_stream_int(ost, &o->pass, oc, st, &do_pass);
767
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 6970 times.
6986 if (do_pass) {
768
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
16 if (do_pass & 1)
769 8 video_enc->flags |= AV_CODEC_FLAG_PASS1;
770
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
16 if (do_pass & 2)
771 8 video_enc->flags |= AV_CODEC_FLAG_PASS2;
772 }
773
774 6986 opt_match_per_stream_str(ost, &o->passlogfiles, oc, st, &ost->logfile_prefix);
775
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 6970 times.
6986 if (ost->logfile_prefix &&
776
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
16 !(ost->logfile_prefix = av_strdup(ost->logfile_prefix)))
777 ✗ return AVERROR(ENOMEM);
778
779
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 6970 times.
6986 if (do_pass) {
780 16 int ost_idx = -1;
781 char logfilename[1024];
782 FILE *f;
783
784 /* compute this stream's global index */
785
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 16 times.
32 for (int idx = 0; idx <= ost->file->index; idx++)
786 16 ost_idx += output_files[idx]->nb_streams;
787
788 16 snprintf(logfilename, sizeof(logfilename), "%s-%d.log",
789
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 ost->logfile_prefix ? ost->logfile_prefix :
790 DEFAULT_PASS_LOGFILENAME_PREFIX,
791 ost_idx);
792
2/4
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
16 if (!strcmp(video_enc->codec->name, "libx264") || !strcmp(video_enc->codec->name, "libvvenc")) {
793 ✗ if (av_opt_is_set_to_default_by_name(video_enc, "stats",
794 AV_OPT_SEARCH_CHILDREN) > 0)
795 ✗ av_opt_set(video_enc, "stats", logfilename,
796 AV_OPT_SEARCH_CHILDREN);
797
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 } else if (!strcmp(video_enc->codec->name, "libx265")) {
798 ✗ if (av_opt_is_set_to_default_by_name(video_enc, "x265-stats",
799 AV_OPT_SEARCH_CHILDREN) > 0)
800 ✗ av_opt_set(video_enc, "x265-stats", logfilename,
801 AV_OPT_SEARCH_CHILDREN);
802 } else {
803
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
16 if (video_enc->flags & AV_CODEC_FLAG_PASS2) {
804 8 char *logbuffer = read_file_to_string(logfilename);
805
806
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!logbuffer) {
807 ✗ av_log(ost, AV_LOG_FATAL, "Error reading log file '%s' for pass-2 encoding\n",
808 logfilename);
809 ✗ return AVERROR(EIO);
810 }
811 8 video_enc->stats_in = logbuffer;
812 }
813
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
16 if (video_enc->flags & AV_CODEC_FLAG_PASS1) {
814 8 f = fopen_utf8(logfilename, "wb");
815
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!f) {
816 ✗ av_log(ost, AV_LOG_FATAL,
817 "Cannot write log file '%s' for pass-1 encoding: %s\n",
818 ✗ logfilename, strerror(errno));
819 ✗ return AVERROR(errno);
820 }
821 8 ost->logfile = f;
822 }
823 }
824 }
825
826 6986 opt_match_per_stream_int(ost, &o->force_fps, oc, st, &ms->force_fps);
827
828 6986 *vsync_method = VSYNC_AUTO;
829 6986 opt_match_per_stream_str(ost, &o->fps_mode, oc, st, &fps_mode);
830
2/2
✓ Branch 0 taken 544 times.
✓ Branch 1 taken 6442 times.
6986 if (fps_mode) {
831 544 ret = parse_and_set_vsync(fps_mode, vsync_method, ost->file->index, ost->index);
832
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 544 times.
544 if (ret < 0)
833 ✗ return ret;
834 }
835
836
3/4
✓ Branch 0 taken 6965 times.
✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6965 times.
6986 if ((ms->frame_rate.num || ms->max_frame_rate.num) &&
837
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 20 times.
21 !(*vsync_method == VSYNC_AUTO ||
838
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 *vsync_method == VSYNC_CFR || *vsync_method == VSYNC_VSCFR)) {
839 ✗ av_log(ost, AV_LOG_FATAL, "One of -r/-fpsmax was specified "
840 "together a non-CFR -vsync/-fps_mode. This is contradictory.\n");
841 ✗ return AVERROR(EINVAL);
842 }
843
844
2/2
✓ Branch 0 taken 6442 times.
✓ Branch 1 taken 544 times.
6986 if (*vsync_method == VSYNC_AUTO) {
845
3/4
✓ Branch 0 taken 6422 times.
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6422 times.
6442 if (ms->frame_rate.num || ms->max_frame_rate.num) {
846 20 *vsync_method = VSYNC_CFR;
847
2/2
✓ Branch 0 taken 305 times.
✓ Branch 1 taken 6117 times.
6422 } else if (!strcmp(oc->oformat->name, "avi")) {
848 305 *vsync_method = VSYNC_VFR;
849 } else {
850 6117 *vsync_method = (oc->oformat->flags & AVFMT_VARIABLE_FPS) ?
851 4618 ((oc->oformat->flags & AVFMT_NOTIMESTAMPS) ?
852
4/4
✓ Branch 0 taken 4618 times.
✓ Branch 1 taken 1499 times.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 4597 times.
6117 VSYNC_PASSTHROUGH : VSYNC_VFR) : VSYNC_CFR;
853 }
854
855
4/4
✓ Branch 0 taken 5172 times.
✓ Branch 1 taken 1270 times.
✓ Branch 2 taken 411 times.
✓ Branch 3 taken 4761 times.
6442 if (ost->ist && *vsync_method == VSYNC_CFR) {
856 411 const InputFile *ifile = ost->ist->file;
857
858
3/4
✓ Branch 0 taken 366 times.
✓ Branch 1 taken 45 times.
✓ Branch 2 taken 366 times.
✗ Branch 3 not taken.
411 if (ifile->nb_streams == 1 && ifile->input_ts_offset == 0)
859 366 *vsync_method = VSYNC_VSCFR;
860 }
861
862
3/4
✓ Branch 0 taken 1153 times.
✓ Branch 1 taken 5289 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1153 times.
6442 if (*vsync_method == VSYNC_CFR && copy_ts) {
863 ✗ *vsync_method = VSYNC_VSCFR;
864 }
865 }
866 }
867
868 7459 return 0;
869 }
870
871 2039 static int new_stream_audio(Muxer *mux, const OptionsContext *o,
872 OutputStream *ost)
873 {
874 2039 MuxStream *ms = ms_from_ost(ost);
875 2039 AVFormatContext *oc = mux->fc;
876 2039 AVStream *st = ost->st;
877
878
2/2
✓ Branch 0 taken 1582 times.
✓ Branch 1 taken 457 times.
2039 if (ost->enc) {
879 1582 AVCodecContext *audio_enc = ost->enc->enc_ctx;
880 1582 int channels = 0;
881 1582 const char *layout = NULL;
882 1582 const char *sample_fmt = NULL;
883
884 1582 opt_match_per_stream_int(ost, &o->audio_channels, oc, st, &channels);
885
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 1572 times.
1582 if (channels) {
886 10 audio_enc->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
887 10 audio_enc->ch_layout.nb_channels = channels;
888 }
889
890 1582 opt_match_per_stream_str(ost, &o->audio_ch_layouts, oc, st, &layout);
891
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1581 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1582 if (layout && av_channel_layout_from_string(&audio_enc->ch_layout, layout) < 0) {
892 ✗ av_log(ost, AV_LOG_FATAL, "Unknown channel layout: %s\n", layout);
893 ✗ return AVERROR(EINVAL);
894 }
895
896 1582 opt_match_per_stream_str(ost, &o->sample_fmts, oc, st, &sample_fmt);
897
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1581 times.
1582 if (sample_fmt &&
898
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 (audio_enc->sample_fmt = av_get_sample_fmt(sample_fmt)) == AV_SAMPLE_FMT_NONE) {
899 ✗ av_log(ost, AV_LOG_FATAL, "Invalid sample format '%s'\n", sample_fmt);
900 ✗ return AVERROR(EINVAL);
901 }
902
903 1582 opt_match_per_stream_int(ost, &o->audio_sample_rate, oc, st, &audio_enc->sample_rate);
904 1582 opt_match_per_stream_str(ost, &o->apad, oc, st, &ms->apad);
905 }
906
907 2039 return 0;
908 }
909
910 84 static int new_stream_subtitle(Muxer *mux, const OptionsContext *o,
911 OutputStream *ost)
912 {
913 AVStream *st;
914
915 84 st = ost->st;
916
917
2/2
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 40 times.
84 if (ost->enc) {
918 44 AVCodecContext *subtitle_enc = ost->enc->enc_ctx;
919
920 AVCodecDescriptor const *input_descriptor =
921 44 avcodec_descriptor_get(ost->ist->par->codec_id);
922 AVCodecDescriptor const *output_descriptor =
923 44 avcodec_descriptor_get(subtitle_enc->codec_id);
924 44 int input_props = 0, output_props = 0;
925
926 44 const char *frame_size = NULL;
927
928 44 opt_match_per_stream_str(ost, &o->frame_sizes, mux->fc, st, &frame_size);
929
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (frame_size) {
930 ✗ int ret = av_parse_video_size(&subtitle_enc->width, &subtitle_enc->height, frame_size);
931 ✗ if (ret < 0) {
932 ✗ av_log(ost, AV_LOG_FATAL, "Invalid frame size: %s.\n", frame_size);
933 ✗ return ret;
934 }
935 }
936
1/2
✓ Branch 0 taken 44 times.
✗ Branch 1 not taken.
44 if (input_descriptor)
937 44 input_props = input_descriptor->props & (AV_CODEC_PROP_TEXT_SUB | AV_CODEC_PROP_BITMAP_SUB);
938
1/2
✓ Branch 0 taken 44 times.
✗ Branch 1 not taken.
44 if (output_descriptor)
939 44 output_props = output_descriptor->props & (AV_CODEC_PROP_TEXT_SUB | AV_CODEC_PROP_BITMAP_SUB);
940
3/6
✓ Branch 0 taken 44 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 44 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 44 times.
44 if (input_props && output_props && input_props != output_props) {
941 ✗ av_log(ost, AV_LOG_ERROR,
942 "Subtitle encoding currently only possible from text to text "
943 "or bitmap to bitmap\n");
944 ✗ return AVERROR(EINVAL);
945 }
946 }
947
948 84 return 0;
949 }
950
951 static int
952 8568 ost_bind_filter(const Muxer *mux, MuxStream *ms, OutputFilter *ofilter,
953 const OptionsContext *o,
954 AVRational enc_tb, enum VideoSyncMethod vsync_method,
955 int keep_pix_fmt, int autoscale, int threads_manual,
956 const ViewSpecifier *vs,
957 SchedulerNode *src)
958 {
959 8568 OutputStream *ost = &ms->ost;
960 8568 AVCodecContext *enc_ctx = ost->enc->enc_ctx;
961 char name[16];
962 8568 char *filters = NULL;
963 int ret;
964
965 34272 OutputFilterOptions opts = {
966 8568 .enc = enc_ctx->codec,
967 .name = name,
968 8568 .format = (ost->type == AVMEDIA_TYPE_VIDEO) ?
969 8568 enc_ctx->pix_fmt : enc_ctx->sample_fmt,
970 8568 .width = enc_ctx->width,
971 8568 .height = enc_ctx->height,
972 8568 .color_space = enc_ctx->colorspace,
973 8568 .color_range = enc_ctx->color_range,
974 8568 .alpha_mode = enc_ctx->alpha_mode,
975 8568 .chroma_location = enc_ctx->chroma_sample_location,
976 .vsync_method = vsync_method,
977 .frame_rate = ms->frame_rate,
978 .max_frame_rate = ms->max_frame_rate,
979 8568 .sample_rate = enc_ctx->sample_rate,
980 .ch_layout = enc_ctx->ch_layout,
981 8568 .sws_opts = o->g->sws_dict,
982 8568 .swr_opts = o->g->swr_opts,
983 .output_tb = enc_tb,
984 8568 .trim_start_us = mux->of.start_time,
985 8568 .trim_duration_us = mux->of.recording_time,
986 8568 .ts_offset = mux->of.start_time == AV_NOPTS_VALUE ?
987
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8567 times.
8568 0 : mux->of.start_time,
988 .vs = vs,
989 .nb_threads = -1,
990 8568 .reinit_opts = ost->enc->reinit_opts,
991
992 17136 .flags = OFILTER_FLAG_DISABLE_CONVERT * !!keep_pix_fmt |
993
3/4
✓ Branch 0 taken 8568 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6986 times.
✓ Branch 3 taken 1582 times.
17136 OFILTER_FLAG_AUTOSCALE * !!autoscale |
994
2/2
✓ Branch 1 taken 65 times.
✓ Branch 2 taken 8503 times.
8568 OFILTER_FLAG_AUDIO_24BIT * !!(av_get_exact_bits_per_sample(enc_ctx->codec_id) == 24),
995 };
996
997 8568 snprintf(name, sizeof(name), "#%d:%d", mux->of.index, ost->index);
998
999
2/2
✓ Branch 0 taken 6986 times.
✓ Branch 1 taken 1582 times.
8568 if (ost->type == AVMEDIA_TYPE_VIDEO) {
1000
1/2
✓ Branch 0 taken 6986 times.
✗ Branch 1 not taken.
6986 if (!keep_pix_fmt) {
1001 6986 ret = avcodec_get_supported_config(enc_ctx, NULL,
1002 AV_CODEC_CONFIG_PIX_FORMAT, 0,
1003 (const void **) &opts.pix_fmts, NULL);
1004
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6986 times.
6986 if (ret < 0)
1005 ✗ return ret;
1006 }
1007
2/2
✓ Branch 0 taken 6985 times.
✓ Branch 1 taken 1 times.
6986 if (!ms->force_fps) {
1008 6985 ret = avcodec_get_supported_config(enc_ctx, NULL,
1009 AV_CODEC_CONFIG_FRAME_RATE, 0,
1010 (const void **) &opts.frame_rates, NULL);
1011
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6985 times.
6985 if (ret < 0)
1012 ✗ return ret;
1013 }
1014 6986 ret = avcodec_get_supported_config(enc_ctx, NULL,
1015 AV_CODEC_CONFIG_COLOR_SPACE, 0,
1016 (const void **) &opts.color_spaces, NULL);
1017
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6986 times.
6986 if (ret < 0)
1018 ✗ return ret;
1019 6986 ret = avcodec_get_supported_config(enc_ctx, NULL,
1020 AV_CODEC_CONFIG_COLOR_RANGE, 0,
1021 (const void **) &opts.color_ranges, NULL);
1022
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6986 times.
6986 if (ret < 0)
1023 ✗ return ret;
1024 6986 ret = avcodec_get_supported_config(enc_ctx, NULL,
1025 AV_CODEC_CONFIG_ALPHA_MODE, 0,
1026 (const void **) &opts.alpha_modes, NULL);
1027
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6986 times.
6986 if (ret < 0)
1028 ✗ return ret;
1029 6986 ret = avcodec_get_supported_config(enc_ctx, NULL,
1030 AV_CODEC_CONFIG_CHROMA_LOCATION, 0,
1031 (const void **) &opts.chroma_locations, NULL);
1032
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6986 times.
6986 if (ret < 0)
1033 ✗ return ret;
1034 } else {
1035 1582 ret = avcodec_get_supported_config(enc_ctx, NULL,
1036 AV_CODEC_CONFIG_SAMPLE_FORMAT, 0,
1037 (const void **) &opts.sample_fmts, NULL);
1038
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1582 times.
1582 if (ret < 0)
1039 ✗ return ret;
1040 1582 ret = avcodec_get_supported_config(enc_ctx, NULL,
1041 AV_CODEC_CONFIG_SAMPLE_RATE, 0,
1042 (const void **) &opts.sample_rates, NULL);
1043
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1582 times.
1582 if (ret < 0)
1044 ✗ return ret;
1045 1582 ret = avcodec_get_supported_config(enc_ctx, NULL,
1046 AV_CODEC_CONFIG_CHANNEL_LAYOUT, 0,
1047 (const void **) &opts.ch_layouts, NULL);
1048
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1582 times.
1582 if (ret < 0)
1049 ✗ return ret;
1050 }
1051
1052
2/2
✓ Branch 0 taken 5526 times.
✓ Branch 1 taken 3042 times.
8568 if (threads_manual) {
1053 5526 ret = av_opt_get_int(enc_ctx, "threads", 0, &opts.nb_threads);
1054
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5526 times.
5526 if (ret < 0)
1055 ✗ return ret;
1056 }
1057
1058 8568 ret = ost_get_filters(o, mux->fc, ost, &filters);
1059
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8568 times.
8568 if (ret < 0)
1060 ✗ return ret;
1061
1062
2/2
✓ Branch 0 taken 1546 times.
✓ Branch 1 taken 7022 times.
8568 if (ofilter) {
1063
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1546 times.
1546 av_assert0(!filters);
1064 1546 ost->filter = ofilter;
1065 1546 ret = ofilter_bind_enc(ofilter, ms->sch_idx_enc, &opts);
1066 } else {
1067 7022 ret = fg_create_simple(&ost->fg_simple, ost->ist, &filters,
1068 7022 mux->sch, ms->sch_idx_enc, &opts);
1069
2/2
✓ Branch 0 taken 7021 times.
✓ Branch 1 taken 1 times.
7022 if (ret >= 0)
1070 7021 ost->filter = ost->fg_simple->outputs[0];
1071
1072 }
1073
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8567 times.
8568 if (ret < 0)
1074 1 return ret;
1075
1076 8567 *src = SCH_ENC(ms->sch_idx_enc);
1077
1078 8567 return 0;
1079 }
1080
1081 982 static int streamcopy_init(const OptionsContext *o, const Muxer *mux,
1082 OutputStream *ost, AVDictionary **encoder_opts)
1083 {
1084 982 MuxStream *ms = ms_from_ost(ost);
1085
1086 982 const InputStream *ist = ost->ist;
1087 982 const InputFile *ifile = ist->file;
1088
1089 982 AVCodecParameters *par = ms->par_in;
1090 982 uint32_t codec_tag = par->codec_tag;
1091
1092 982 AVCodecContext *codec_ctx = NULL;
1093
1094 982 AVRational fr = ms->frame_rate;
1095
1096 982 int ret = 0;
1097
1098 982 const char *filters = NULL;
1099 982 opt_match_per_stream_str(ost, &o->filters, mux->fc, ost->st, &filters);
1100
1101
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 982 times.
982 if (filters) {
1102 ✗ av_log(ost, AV_LOG_ERROR,
1103 "Filtergraph '%s' was specified, but codec copy was selected. "
1104 "Filtering and streamcopy cannot be used together.\n", filters);
1105 ✗ return AVERROR(EINVAL);
1106 }
1107
1108 982 codec_ctx = avcodec_alloc_context3(NULL);
1109
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 982 times.
982 if (!codec_ctx)
1110 ✗ return AVERROR(ENOMEM);
1111
1112 982 ret = avcodec_parameters_to_context(codec_ctx, ist->par);
1113
1/2
✓ Branch 0 taken 982 times.
✗ Branch 1 not taken.
982 if (ret >= 0)
1114 982 ret = av_opt_set_dict(codec_ctx, encoder_opts);
1115
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 982 times.
982 if (ret < 0) {
1116 ✗ av_log(ost, AV_LOG_FATAL,
1117 "Error setting up codec context options.\n");
1118 ✗ goto fail;
1119 }
1120
1121 982 ret = avcodec_parameters_from_context(par, codec_ctx);
1122
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 982 times.
982 if (ret < 0) {
1123 ✗ av_log(ost, AV_LOG_FATAL,
1124 "Error getting reference codec parameters.\n");
1125 ✗ goto fail;
1126 }
1127
1128
2/2
✓ Branch 0 taken 975 times.
✓ Branch 1 taken 7 times.
982 if (!codec_tag) {
1129 975 const struct AVCodecTag * const *ct = mux->fc->oformat->codec_tag;
1130 unsigned int codec_tag_tmp;
1131
6/6
✓ Branch 0 taken 183 times.
✓ Branch 1 taken 792 times.
✓ Branch 3 taken 140 times.
✓ Branch 4 taken 43 times.
✓ Branch 5 taken 16 times.
✓ Branch 6 taken 124 times.
1115 if (!ct || av_codec_get_id (ct, par->codec_tag) == par->codec_id ||
1132 140 !av_codec_get_tag2(ct, par->codec_id, &codec_tag_tmp))
1133 851 codec_tag = par->codec_tag;
1134 }
1135
1136 982 par->codec_tag = codec_tag;
1137
1138
2/2
✓ Branch 0 taken 981 times.
✓ Branch 1 taken 1 times.
982 if (!fr.num)
1139 981 fr = ist->framerate;
1140
1141
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 980 times.
982 if (fr.num)
1142 2 ost->st->avg_frame_rate = fr;
1143 else
1144 980 ost->st->avg_frame_rate = ist->st->avg_frame_rate;
1145
1146 // copy timebase while removing common factors
1147
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 982 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
982 if (ost->st->time_base.num <= 0 || ost->st->time_base.den <= 0) {
1148
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 980 times.
982 if (fr.num)
1149 2 ost->st->time_base = av_inv_q(fr);
1150 else
1151 980 ost->st->time_base = av_add_q(ist->st->time_base, (AVRational){0, 1});
1152 }
1153
1154
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 982 times.
982 if (!ms->copy_prior_start) {
1155 ✗ ms->ts_copy_start = (mux->of.start_time == AV_NOPTS_VALUE) ?
1156 ✗ 0 : mux->of.start_time;
1157 ✗ if (copy_ts && ifile->start_time != AV_NOPTS_VALUE) {
1158 ✗ ms->ts_copy_start = FFMAX(ms->ts_copy_start,
1159 ifile->start_time + ifile->ts_offset);
1160 }
1161 }
1162
1163
2/2
✓ Branch 0 taken 129 times.
✓ Branch 1 taken 982 times.
1111 for (int i = 0; i < ist->st->codecpar->nb_coded_side_data; i++) {
1164 129 const AVPacketSideData *sd_src = &ist->st->codecpar->coded_side_data[i];
1165 AVPacketSideData *sd_dst;
1166
1167 129 sd_dst = av_packet_side_data_new(&ost->st->codecpar->coded_side_data,
1168 129 &ost->st->codecpar->nb_coded_side_data,
1169 129 sd_src->type, sd_src->size, 0);
1170
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 129 times.
129 if (!sd_dst) {
1171 ✗ ret = AVERROR(ENOMEM);
1172 ✗ goto fail;
1173 }
1174 129 memcpy(sd_dst->data, sd_src->data, sd_src->size);
1175 }
1176
1177
3/3
✓ Branch 0 taken 457 times.
✓ Branch 1 taken 473 times.
✓ Branch 2 taken 52 times.
982 switch (par->codec_type) {
1178 457 case AVMEDIA_TYPE_AUDIO:
1179
4/6
✓ Branch 0 taken 452 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 452 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 452 times.
457 if ((par->block_align == 1 || par->block_align == 1152 || par->block_align == 576) &&
1180
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 par->codec_id == AV_CODEC_ID_MP3)
1181 ✗ par->block_align = 0;
1182
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 442 times.
457 if (par->codec_id == AV_CODEC_ID_AC3)
1183 15 par->block_align = 0;
1184 457 break;
1185 473 case AVMEDIA_TYPE_VIDEO: {
1186 AVRational sar;
1187
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 473 times.
473 if (ost->frame_aspect_ratio.num) { // overridden by the -aspect cli option
1188 sar =
1189 ✗ av_mul_q(ost->frame_aspect_ratio,
1190 ✗ (AVRational){ par->height, par->width });
1191 ✗ av_log(ost, AV_LOG_WARNING, "Overriding aspect ratio "
1192 "with stream copy may produce invalid files\n");
1193 }
1194
2/2
✓ Branch 0 taken 137 times.
✓ Branch 1 taken 336 times.
473 else if (ist->st->sample_aspect_ratio.num)
1195 137 sar = ist->st->sample_aspect_ratio;
1196 else
1197 336 sar = par->sample_aspect_ratio;
1198 473 ost->st->sample_aspect_ratio = par->sample_aspect_ratio = sar;
1199 473 ost->st->r_frame_rate = ist->st->r_frame_rate;
1200 473 break;
1201 }
1202 }
1203
1204 982 fail:
1205 982 avcodec_free_context(&codec_ctx);
1206 982 return ret;
1207 }
1208
1209 8612 static int set_encoder_id(OutputStream *ost, const AVCodec *codec)
1210 {
1211 8612 const char *cname = codec->name;
1212 uint8_t *encoder_string;
1213 int encoder_string_len;
1214
1215 8612 encoder_string_len = sizeof(LIBAVCODEC_IDENT) + strlen(cname) + 2;
1216 8612 encoder_string = av_mallocz(encoder_string_len);
1217
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8612 times.
8612 if (!encoder_string)
1218 ✗ return AVERROR(ENOMEM);
1219
1220
4/4
✓ Branch 0 taken 938 times.
✓ Branch 1 taken 7674 times.
✓ Branch 2 taken 924 times.
✓ Branch 3 taken 14 times.
8612 if (!ost->file->bitexact && !ost->bitexact)
1221 924 av_strlcpy(encoder_string, LIBAVCODEC_IDENT " ", encoder_string_len);
1222 else
1223 7688 av_strlcpy(encoder_string, "Lavc ", encoder_string_len);
1224 8612 av_strlcat(encoder_string, cname, encoder_string_len);
1225 8612 av_dict_set(&ost->st->metadata, "encoder", encoder_string,
1226 AV_DICT_DONT_STRDUP_VAL | AV_DICT_DONT_OVERWRITE);
1227
1228 8612 return 0;
1229 }
1230
1231 9595 static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
1232 InputStream *ist, OutputFilter *ofilter, const ViewSpecifier *vs,
1233 OutputStream **post)
1234 {
1235 9595 AVFormatContext *oc = mux->fc;
1236 MuxStream *ms;
1237 OutputStream *ost;
1238 const AVCodec *enc;
1239 AVStream *st;
1240 9595 SchedulerNode src = { .type = SCH_NODE_TYPE_NONE };
1241 9595 AVDictionary *encoder_opts = NULL;
1242 9595 int ret = 0, keep_pix_fmt = 0, autoscale = 1;
1243 9595 int threads_manual = 0;
1244 9595 AVRational enc_tb = { 0, 0 };
1245 9595 enum VideoSyncMethod vsync_method = VSYNC_AUTO;
1246 9595 const char *bsfs = NULL, *time_base = NULL, *codec_tag = NULL, *manual_disp = NULL;
1247 char *next;
1248 9595 double qscale = -1;
1249
1250 9595 st = avformat_new_stream(oc, NULL);
1251
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9595 times.
9595 if (!st)
1252 ✗ return AVERROR(ENOMEM);
1253
1254 9595 ms = mux_stream_alloc(mux, type);
1255
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9595 times.
9595 if (!ms)
1256 ✗ return AVERROR(ENOMEM);
1257
1258 // only streams with sources (i.e. not attachments)
1259 // are handled by the scheduler
1260
4/4
✓ Branch 0 taken 1547 times.
✓ Branch 1 taken 8048 times.
✓ Branch 2 taken 1546 times.
✓ Branch 3 taken 1 times.
9595 if (ist || ofilter) {
1261 9594 ret = GROW_ARRAY(mux->sch_stream_idx, mux->nb_sch_stream_idx);
1262
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9594 times.
9594 if (ret < 0)
1263 ✗ return ret;
1264
1265 9594 ret = sch_add_mux_stream(mux->sch, mux->sch_idx);
1266
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9594 times.
9594 if (ret < 0)
1267 ✗ return ret;
1268
1269
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9594 times.
9594 av_assert0(ret == mux->nb_sch_stream_idx - 1);
1270 9594 mux->sch_stream_idx[ret] = ms->ost.index;
1271 9594 ms->sch_idx = ret;
1272 }
1273
1274 9595 ost = &ms->ost;
1275
1276
2/2
✓ Branch 0 taken 83 times.
✓ Branch 1 taken 9512 times.
9595 if (o->streamid) {
1277 AVDictionaryEntry *e;
1278 char idx[16], *p;
1279 83 snprintf(idx, sizeof(idx), "%d", ost->index);
1280
1281 83 e = av_dict_get(o->streamid, idx, NULL, 0);
1282
1/2
✓ Branch 0 taken 83 times.
✗ Branch 1 not taken.
83 if (e) {
1283 83 st->id = strtol(e->value, &p, 0);
1284
2/4
✓ Branch 0 taken 83 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 83 times.
83 if (!e->value[0] || *p) {
1285 ✗ av_log(ost, AV_LOG_FATAL, "Invalid stream id: %s\n", e->value);
1286 ✗ return AVERROR(EINVAL);
1287 }
1288 }
1289 }
1290
1291 9595 ms->par_in = avcodec_parameters_alloc();
1292
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9595 times.
9595 if (!ms->par_in)
1293 ✗ return AVERROR(ENOMEM);
1294
1295 9595 ms->last_mux_dts = AV_NOPTS_VALUE;
1296
1297 9595 ost->st = st;
1298 9595 ost->ist = ist;
1299 9595 ost->kf.ref_pts = AV_NOPTS_VALUE;
1300 9595 ms->par_in->codec_type = type;
1301 9595 st->codecpar->codec_type = type;
1302
1303
2/2
✓ Branch 0 taken 7459 times.
✓ Branch 1 taken 2136 times.
9595 if (ost->type == AVMEDIA_TYPE_VIDEO) {
1304
2/2
✓ Branch 0 taken 6184 times.
✓ Branch 1 taken 1275 times.
7459 if (ost->ist)
1305 6184 ost->st->disposition = ost->ist->st->disposition;
1306
1307 7459 opt_match_per_stream_str(ost, &o->disposition, oc, st, &manual_disp);
1308
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 7451 times.
7459 if (manual_disp) {
1309 8 ret = av_opt_set(ost->st, "disposition", manual_disp, 0);
1310
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (ret < 0)
1311 ✗ return ret;
1312 }
1313
1314 7459 ost->st->disposition &= AV_DISPOSITION_ATTACHED_PIC;
1315 }
1316
1317 9595 ret = choose_encoder(o, oc, ms, &enc);
1318
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9595 times.
9595 if (ret < 0) {
1319 ✗ av_log(ost, AV_LOG_FATAL, "Error selecting an encoder\n");
1320 ✗ return ret;
1321 }
1322
1323
2/2
✓ Branch 0 taken 8612 times.
✓ Branch 1 taken 983 times.
9595 if (enc) {
1324 8612 ret = sch_add_enc(mux->sch, encoder_thread, ost,
1325
2/2
✓ Branch 0 taken 8568 times.
✓ Branch 1 taken 44 times.
8612 ost->type == AVMEDIA_TYPE_SUBTITLE ? NULL : enc_open);
1326
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8612 times.
8612 if (ret < 0)
1327 ✗ return ret;
1328 8612 ms->sch_idx_enc = ret;
1329
1330 8612 ret = enc_alloc(&ost->enc, enc, mux->sch, ms->sch_idx_enc, ost);
1331
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8612 times.
8612 if (ret < 0)
1332 ✗ return ret;
1333
1334 8612 av_strlcat(ms->log_name, "/", sizeof(ms->log_name));
1335 8612 av_strlcat(ms->log_name, enc->name, sizeof(ms->log_name));
1336 } else {
1337
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 983 times.
983 if (ofilter) {
1338 ✗ av_log(ost, AV_LOG_ERROR,
1339 "Streamcopy requested for output stream fed "
1340 "from a complex filtergraph. Filtering and streamcopy "
1341 "cannot be used together.\n");
1342 ✗ return AVERROR(EINVAL);
1343 }
1344
1345 983 av_strlcat(ms->log_name, "/copy", sizeof(ms->log_name));
1346 }
1347
1348 9595 av_log(ost, AV_LOG_VERBOSE, "Created %s stream from ",
1349 av_get_media_type_string(type));
1350
2/2
✓ Branch 0 taken 8048 times.
✓ Branch 1 taken 1547 times.
9595 if (ist)
1351 8048 av_log(ost, AV_LOG_VERBOSE, "input stream %d:%d",
1352 8048 ist->file->index, ist->index);
1353
2/2
✓ Branch 0 taken 1546 times.
✓ Branch 1 taken 1 times.
1547 else if (ofilter)
1354 1546 av_log(ost, AV_LOG_VERBOSE, "complex filtergraph %d:[%s]",
1355 1546 ofilter->graph->index, ofilter->name);
1356
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 else if (type == AVMEDIA_TYPE_ATTACHMENT)
1357 1 av_log(ost, AV_LOG_VERBOSE, "attached file");
1358 ✗ else av_assert0(0);
1359 9595 av_log(ost, AV_LOG_VERBOSE, "\n");
1360
1361 9595 ms->pkt = av_packet_alloc();
1362
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9595 times.
9595 if (!ms->pkt)
1363 ✗ return AVERROR(ENOMEM);
1364
1365
2/2
✓ Branch 0 taken 8612 times.
✓ Branch 1 taken 983 times.
9595 if (ost->enc) {
1366 8612 AVIOContext *s = NULL;
1367 8612 char *buf = NULL, *arg = NULL;
1368 8612 const char *enc_stats_pre = NULL, *enc_stats_post = NULL, *mux_stats = NULL;
1369 8612 const char *enc_time_base = NULL, *enc_reinit_opts = NULL, *preset = NULL;
1370
1371 8612 ret = filter_codec_opts(o->g->codec_opts, enc->id,
1372 oc, st, enc, &encoder_opts,
1373 &mux->enc_opts_used);
1374
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8612 times.
8612 if (ret < 0)
1375 ✗ goto fail;
1376
1377 8612 opt_match_per_stream_str(ost, &o->presets, oc, st, &preset);
1378 8612 opt_match_per_stream_int(ost, &o->autoscale, oc, st, &autoscale);
1379
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8612 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
8612 if (preset && (!(ret = get_preset_file_2(preset, enc->name, &s)))) {
1380 AVBPrint bprint;
1381 ✗ av_bprint_init(&bprint, 0, AV_BPRINT_SIZE_UNLIMITED);
1382 do {
1383 ✗ av_bprint_clear(&bprint);
1384 ✗ buf = get_line(s, &bprint);
1385 ✗ if (!buf) {
1386 ✗ ret = AVERROR(ENOMEM);
1387 ✗ break;
1388 }
1389
1390 ✗ if (!buf[0] || buf[0] == '#')
1391 ✗ continue;
1392 ✗ if (!(arg = strchr(buf, '='))) {
1393 ✗ av_log(ost, AV_LOG_FATAL, "Invalid line found in the preset file.\n");
1394 ✗ ret = AVERROR(EINVAL);
1395 ✗ break;
1396 }
1397 ✗ *arg++ = 0;
1398 ✗ av_dict_set(&encoder_opts, buf, arg, AV_DICT_DONT_OVERWRITE);
1399 ✗ } while (!s->eof_reached);
1400 ✗ av_bprint_finalize(&bprint, NULL);
1401 ✗ avio_closep(&s);
1402 }
1403
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8612 times.
8612 if (ret) {
1404 ✗ av_log(ost, AV_LOG_FATAL,
1405 "Preset %s specified, but could not be opened.\n", preset);
1406 ✗ goto fail;
1407 }
1408
1409 8612 opt_match_per_stream_str(ost, &o->enc_reinit_opts, oc, st, &enc_reinit_opts);
1410
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8612 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8612 if (enc_reinit_opts &&
1411 ✗ (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) {
1412 ✗ ost->enc->reinit_opts = av_strdup(enc_reinit_opts);
1413 ✗ if (!ost->enc->reinit_opts) {
1414 ✗ ret = AVERROR(ENOMEM);
1415 ✗ goto fail;
1416 }
1417 }
1418
1419 8612 opt_match_per_stream_str(ost, &o->enc_stats_pre, oc, st, &enc_stats_pre);
1420
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8612 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8612 if (enc_stats_pre &&
1421 ✗ (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) {
1422 ✗ const char *format = "{fidx} {sidx} {n} {t}";
1423
1424 ✗ opt_match_per_stream_str(ost, &o->enc_stats_pre_fmt, oc, st, &format);
1425
1426 ✗ ret = enc_stats_init(ost, &ost->enc_stats_pre, 1, enc_stats_pre, format);
1427 ✗ if (ret < 0)
1428 ✗ goto fail;
1429 }
1430
1431 8612 opt_match_per_stream_str(ost, &o->enc_stats_post, oc, st, &enc_stats_post);
1432
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8612 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8612 if (enc_stats_post &&
1433 ✗ (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) {
1434 ✗ const char *format = "{fidx} {sidx} {n} {t}";
1435
1436 ✗ opt_match_per_stream_str(ost, &o->enc_stats_post_fmt, oc, st, &format);
1437
1438 ✗ ret = enc_stats_init(ost, &ost->enc_stats_post, 0, enc_stats_post, format);
1439 ✗ if (ret < 0)
1440 ✗ goto fail;
1441 }
1442
1443 8612 opt_match_per_stream_str(ost, &o->mux_stats, oc, st, &mux_stats);
1444
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8612 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8612 if (mux_stats &&
1445 ✗ (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) {
1446 ✗ const char *format = "{fidx} {sidx} {n} {t}";
1447
1448 ✗ opt_match_per_stream_str(ost, &o->mux_stats_fmt, oc, st, &format);
1449
1450 ✗ ret = enc_stats_init(ost, &ms->stats, 0, mux_stats, format);
1451 ✗ if (ret < 0)
1452 ✗ goto fail;
1453 }
1454
1455 8612 opt_match_per_stream_str(ost, &o->enc_time_bases, oc, st, &enc_time_base);
1456
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8611 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
8612 if (enc_time_base && type == AVMEDIA_TYPE_SUBTITLE)
1457 ✗ av_log(ost, AV_LOG_WARNING,
1458 "-enc_time_base not supported for subtitles, ignoring\n");
1459
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8611 times.
8612 else if (enc_time_base) {
1460 AVRational q;
1461
1462
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (!strcmp(enc_time_base, "demux")) {
1463 1 q = (AVRational){ ENC_TIME_BASE_DEMUX, 0 };
1464 ✗ } else if (!strcmp(enc_time_base, "filter")) {
1465 ✗ q = (AVRational){ ENC_TIME_BASE_FILTER, 0 };
1466 } else {
1467 ✗ ret = av_parse_ratio(&q, enc_time_base, INT_MAX, 0, NULL);
1468 ✗ if (ret < 0 || q.den <= 0 || q.num < 0) {
1469 ✗ av_log(ost, AV_LOG_FATAL, "Invalid time base: %s\n", enc_time_base);
1470 ✗ ret = ret < 0 ? ret : AVERROR(EINVAL);
1471 ✗ goto fail;
1472 }
1473 }
1474
1475 1 enc_tb = q;
1476 }
1477
1478 8612 threads_manual = !!av_dict_get(encoder_opts, "threads", NULL, 0);
1479
1480 8612 ret = av_dict_copy(&ost->enc->encoder_opts, encoder_opts, 0);
1481
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8612 times.
8612 if (ret < 0)
1482 ✗ goto fail;
1483 8612 ret = av_opt_set_dict2(ost->enc->enc_ctx, &encoder_opts, AV_OPT_SEARCH_CHILDREN);
1484
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8612 times.
8612 if (ret < 0) {
1485 ✗ av_log(ost, AV_LOG_ERROR, "Error applying encoder options: %s\n",
1486 ✗ av_err2str(ret));
1487 ✗ goto fail;
1488 }
1489
1490 8612 ret = check_avoptions(encoder_opts);
1491
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8612 times.
8612 if (ret < 0)
1492 ✗ goto fail;
1493
1494 // default to automatic thread count
1495
2/2
✓ Branch 0 taken 3086 times.
✓ Branch 1 taken 5526 times.
8612 if (!threads_manual)
1496 3086 ost->enc->enc_ctx->thread_count = 0;
1497 } else {
1498 983 ret = filter_codec_opts(o->g->codec_opts, AV_CODEC_ID_NONE, oc, st,
1499 NULL, &encoder_opts,
1500 &mux->enc_opts_used);
1501
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 983 times.
983 if (ret < 0)
1502 ✗ goto fail;
1503 }
1504
1505
1506
2/2
✓ Branch 0 taken 2272 times.
✓ Branch 1 taken 7323 times.
9595 if (o->bitexact) {
1507 2272 ost->bitexact = 1;
1508
2/2
✓ Branch 0 taken 6521 times.
✓ Branch 1 taken 802 times.
7323 } else if (ost->enc) {
1509 6521 ost->bitexact = !!(ost->enc->enc_ctx->flags & AV_CODEC_FLAG_BITEXACT);
1510 }
1511
1512
2/2
✓ Branch 0 taken 8612 times.
✓ Branch 1 taken 983 times.
9595 if (enc) {
1513 8612 ret = set_encoder_id(ost, enc);
1514
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8612 times.
8612 if (ret < 0)
1515 ✗ return ret;
1516 }
1517
1518 9595 opt_match_per_stream_str(ost, &o->time_bases, oc, st, &time_base);
1519
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 9591 times.
9595 if (time_base) {
1520 AVRational q;
1521
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 if (av_parse_ratio(&q, time_base, INT_MAX, 0, NULL) < 0 ||
1522
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 q.num <= 0 || q.den <= 0) {
1523 ✗ av_log(ost, AV_LOG_FATAL, "Invalid time base: %s\n", time_base);
1524 ✗ ret = AVERROR(EINVAL);
1525 ✗ goto fail;
1526 }
1527 4 st->time_base = q;
1528 }
1529
1530 9595 ms->max_frames = INT64_MAX;
1531 9595 opt_match_per_stream_int64(ost, &o->max_frames, oc, st, &ms->max_frames);
1532
2/2
✓ Branch 0 taken 5530 times.
✓ Branch 1 taken 9589 times.
15119 for (int i = 0; i < o->max_frames.nb_opt; i++) {
1533 5530 char *p = o->max_frames.opt[i].specifier;
1534
4/4
✓ Branch 0 taken 169 times.
✓ Branch 1 taken 5361 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 163 times.
5530 if (!*p && type != AVMEDIA_TYPE_VIDEO) {
1535 6 av_log(ost, AV_LOG_WARNING, "Applying unspecific -frames to non video streams, maybe you meant -vframes ?\n");
1536 6 break;
1537 }
1538 }
1539
1540 9595 ms->copy_prior_start = -1;
1541 9595 opt_match_per_stream_int(ost, &o->copy_prior_start, oc, st, &ms->copy_prior_start);
1542 9595 opt_match_per_stream_str(ost, &o->bitstream_filters, oc, st, &bsfs);
1543
3/4
✓ Branch 0 taken 197 times.
✓ Branch 1 taken 9398 times.
✓ Branch 2 taken 197 times.
✗ Branch 3 not taken.
9595 if (bsfs && *bsfs) {
1544 197 ret = av_bsf_list_parse_str(bsfs, &ms->bsf_ctx);
1545
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 197 times.
197 if (ret < 0) {
1546 ✗ av_log(ost, AV_LOG_ERROR, "Error parsing bitstream filter sequence '%s': %s\n", bsfs, av_err2str(ret));
1547 ✗ goto fail;
1548 }
1549 }
1550
1551 9595 opt_match_per_stream_str(ost, &o->codec_tags, oc, st, &codec_tag);
1552
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9586 times.
9595 if (codec_tag) {
1553 9 uint32_t tag = strtol(codec_tag, &next, 0);
1554
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if (*next) {
1555 9 uint8_t buf[4] = { 0 };
1556
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 memcpy(buf, codec_tag, FFMIN(sizeof(buf), strlen(codec_tag)));
1557 9 tag = AV_RL32(buf);
1558 }
1559 9 ost->st->codecpar->codec_tag = tag;
1560 9 ms->par_in->codec_tag = tag;
1561
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7 times.
9 if (ost->enc)
1562 2 ost->enc->codec_tag = tag;
1563 }
1564
1565 9595 opt_match_per_stream_dbl(ost, &o->qscale, oc, st, &qscale);
1566
2/2
✓ Branch 0 taken 8612 times.
✓ Branch 1 taken 983 times.
9595 if (ost->enc) {
1567
2/2
✓ Branch 0 taken 283 times.
✓ Branch 1 taken 8329 times.
8612 if (qscale >= 0) {
1568 283 ost->enc->flags |= AV_CODEC_FLAG_QSCALE;
1569 283 ost->enc->global_quality = FF_QP2LAMBDA * qscale;
1570 } else
1571 8329 ost->enc->global_quality = ost->enc->enc_ctx->global_quality;
1572 }
1573
1574
2/2
✓ Branch 0 taken 9594 times.
✓ Branch 1 taken 1 times.
9595 if (ms->sch_idx >= 0) {
1575 9594 int max_muxing_queue_size = 128;
1576 9594 int muxing_queue_data_threshold = 50 * 1024 * 1024;
1577
1578 9594 opt_match_per_stream_int(ost, &o->max_muxing_queue_size, oc, st,
1579 &max_muxing_queue_size);
1580 9594 opt_match_per_stream_int(ost, &o->muxing_queue_data_threshold,
1581 oc, st, &muxing_queue_data_threshold);
1582
1583 9594 sch_mux_stream_buffering(mux->sch, mux->sch_idx, ms->sch_idx,
1584 max_muxing_queue_size, muxing_queue_data_threshold);
1585 }
1586
1587 9595 opt_match_per_stream_int(ost, &o->bits_per_raw_sample, oc, st,
1588 &ost->bits_per_raw_sample);
1589
1590 9595 opt_match_per_stream_int(ost, &o->fix_sub_duration_heartbeat,
1591 9595 oc, st, &ost->fix_sub_duration_heartbeat);
1592
1593
4/4
✓ Branch 0 taken 3427 times.
✓ Branch 1 taken 6168 times.
✓ Branch 2 taken 3255 times.
✓ Branch 3 taken 172 times.
9595 if (oc->oformat->flags & AVFMT_GLOBALHEADER && ost->enc)
1594 3255 ost->enc->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
1595
4/4
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 9539 times.
✓ Branch 2 taken 32 times.
✓ Branch 3 taken 24 times.
9595 if (oc->oformat->flags & AVFMT_FIXED_FRAMESIZE && ost->enc)
1596 32 ost->enc->flags2 |= AV_CODEC_FLAG2_FIXED_FRAME_SIZE;
1597
1598 9595 opt_match_per_stream_int(ost, &o->copy_initial_nonkeyframes,
1599 oc, st, &ms->copy_initial_nonkeyframes);
1600
4/4
✓ Branch 0 taken 7459 times.
✓ Branch 1 taken 2039 times.
✓ Branch 2 taken 84 times.
✓ Branch 3 taken 13 times.
9595 switch (type) {
1601 7459 case AVMEDIA_TYPE_VIDEO: ret = new_stream_video (mux, o, ost, &keep_pix_fmt, &vsync_method); break;
1602 2039 case AVMEDIA_TYPE_AUDIO: ret = new_stream_audio (mux, o, ost); break;
1603 84 case AVMEDIA_TYPE_SUBTITLE: ret = new_stream_subtitle (mux, o, ost); break;
1604 }
1605
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9595 times.
9595 if (ret < 0)
1606 ✗ goto fail;
1607
1608
4/4
✓ Branch 0 taken 8612 times.
✓ Branch 1 taken 983 times.
✓ Branch 2 taken 1626 times.
✓ Branch 3 taken 6986 times.
9595 if (ost->enc &&
1609
2/2
✓ Branch 0 taken 1582 times.
✓ Branch 1 taken 44 times.
1626 (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) {
1610 8568 ret = ost_bind_filter(mux, ms, ofilter, o, enc_tb, vsync_method,
1611 keep_pix_fmt, autoscale, threads_manual, vs, &src);
1612
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8567 times.
8568 if (ret < 0)
1613 1 goto fail;
1614
2/2
✓ Branch 0 taken 1026 times.
✓ Branch 1 taken 1 times.
1027 } else if (ost->ist) {
1615 1026 ret = ist_use(ost->ist, !!ost->enc, NULL, &src);
1616
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1026 times.
1026 if (ret < 0) {
1617 ✗ av_log(ost, AV_LOG_ERROR,
1618 "Error binding an input stream\n");
1619 ✗ goto fail;
1620 }
1621 1026 ms->sch_idx_src = src.idx;
1622
1623 // src refers to a decoder for transcoding, demux stream otherwise
1624
2/2
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 982 times.
1026 if (ost->enc) {
1625 44 ret = sch_connect(mux->sch,
1626 44 src, SCH_ENC(ms->sch_idx_enc));
1627
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (ret < 0)
1628 ✗ goto fail;
1629 44 src = SCH_ENC(ms->sch_idx_enc);
1630 }
1631 }
1632
1633
2/2
✓ Branch 0 taken 9593 times.
✓ Branch 1 taken 1 times.
9594 if (src.type != SCH_NODE_TYPE_NONE) {
1634 9593 ret = sch_connect(mux->sch,
1635 9593 src, SCH_MSTREAM(mux->sch_idx, ms->sch_idx));
1636
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9593 times.
9593 if (ret < 0)
1637 ✗ goto fail;
1638 } else {
1639 // only attachment streams don't have a source
1640
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 av_assert0(type == AVMEDIA_TYPE_ATTACHMENT && ms->sch_idx < 0);
1641 }
1642
1643
4/4
✓ Branch 0 taken 8047 times.
✓ Branch 1 taken 1547 times.
✓ Branch 2 taken 982 times.
✓ Branch 3 taken 7065 times.
9594 if (ost->ist && !ost->enc) {
1644 982 ret = streamcopy_init(o, mux, ost, &encoder_opts);
1645
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 982 times.
982 if (ret < 0)
1646 ✗ goto fail;
1647 }
1648
1649 // copy estimated duration as a hint to the muxer
1650
4/4
✓ Branch 0 taken 8047 times.
✓ Branch 1 taken 1547 times.
✓ Branch 2 taken 6308 times.
✓ Branch 3 taken 1739 times.
9594 if (ost->ist && ost->ist->st->duration > 0) {
1651 6308 ms->stream_duration = ist->st->duration;
1652 6308 ms->stream_duration_tb = ist->st->time_base;
1653 }
1654
1655
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 9593 times.
9594 if (post)
1656 1 *post = ost;
1657
1658 9594 ret = 0;
1659
1660 9595 fail:
1661 9595 av_dict_free(&encoder_opts);
1662
1663 9595 return ret;
1664 }
1665
1666 7214 static int map_auto_video(Muxer *mux, const OptionsContext *o)
1667 {
1668 7214 AVFormatContext *oc = mux->fc;
1669 7214 InputStreamGroup *best_istg = NULL;
1670 7214 InputStream *best_ist = NULL;
1671 7214 int64_t best_score = 0;
1672 int qcr;
1673
1674 /* video: highest resolution */
1675
2/2
✓ Branch 1 taken 790 times.
✓ Branch 2 taken 6424 times.
7214 if (av_guess_codec(oc->oformat, NULL, oc->url, NULL, AVMEDIA_TYPE_VIDEO) == AV_CODEC_ID_NONE)
1676 790 return 0;
1677
1678 6424 qcr = avformat_query_codec(oc->oformat, oc->oformat->video_codec, 0);
1679
2/2
✓ Branch 0 taken 6465 times.
✓ Branch 1 taken 6424 times.
12889 for (int j = 0; j < nb_input_files; j++) {
1680 6465 InputFile *ifile = input_files[j];
1681 6465 InputStreamGroup *file_best_istg = NULL;
1682 6465 InputStream *file_best_ist = NULL;
1683 6465 int64_t file_best_score = 0;
1684
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 6465 times.
6487 for (int i = 0; i < ifile->nb_stream_groups; i++) {
1685 22 InputStreamGroup *istg = ifile->stream_groups[i];
1686 22 int64_t score = 0;
1687
1688
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 1 times.
22 if (!istg->fg)
1689 21 continue;
1690
1691
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 for (int j = 0; j < istg->stg->nb_entries; j++) {
1692
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (istg->stg->entries[j]->type != AV_STREAM_GROUP_ENTRY_STREAM)
1693 ✗ continue;
1694
1695 1 AVStream *st = istg->stg->entries[j]->stream;
1696
1697
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (st->event_flags & AVSTREAM_EVENT_FLAG_NEW_PACKETS) {
1698 1 score = 100000000;
1699 1 break;
1700 }
1701 }
1702
1703
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 switch (istg->stg->type) {
1704 1 case AV_STREAM_GROUP_PARAMS_TILE_GRID: {
1705 1 const AVStreamGroupTileGrid *tg = istg->stg->params.tile_grid;
1706 2 score += tg->width * (int64_t)tg->height
1707
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 + 5000000*!!(istg->stg->disposition & AV_DISPOSITION_DEFAULT);
1708 1 break;
1709 }
1710 ✗ default:
1711 ✗ continue;
1712 }
1713
1714
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (score > file_best_score) {
1715 1 file_best_score = score;
1716 1 file_best_istg = istg;
1717 }
1718 }
1719
2/2
✓ Branch 0 taken 6750 times.
✓ Branch 1 taken 6465 times.
13215 for (int i = 0; i < ifile->nb_streams; i++) {
1720 6750 InputStream *ist = ifile->streams[i];
1721 6750 const AVCodecDescriptor *desc = avcodec_descriptor_get(ist->st->codecpar->codec_id);
1722 int64_t score;
1723
1724
2/2
✓ Branch 0 taken 6749 times.
✓ Branch 1 taken 1 times.
6750 if (ist->user_set_discard == AVDISCARD_ALL ||
1725
3/4
✓ Branch 0 taken 5953 times.
✓ Branch 1 taken 796 times.
✓ Branch 2 taken 5953 times.
✗ Branch 3 not taken.
6749 ist->st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO ||
1726
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5953 times.
5953 (desc && (desc->props & AV_CODEC_PROP_ENHANCEMENT)))
1727 797 continue;
1728
1729 11906 score = ist->st->codecpar->width * (int64_t)ist->st->codecpar->height
1730
2/2
✓ Branch 0 taken 5951 times.
✓ Branch 1 taken 2 times.
5953 + 100000000 * !!(ist->st->event_flags & AVSTREAM_EVENT_FLAG_NEW_PACKETS)
1731
2/2
✓ Branch 0 taken 552 times.
✓ Branch 1 taken 5401 times.
5953 + 5000000*!!(ist->st->disposition & AV_DISPOSITION_DEFAULT);
1732
3/4
✓ Branch 0 taken 5953 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 5944 times.
5953 if((qcr!=MKTAG('A', 'P', 'I', 'C')) && (ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC))
1733 9 score = 1;
1734
1735
2/2
✓ Branch 0 taken 5948 times.
✓ Branch 1 taken 5 times.
5953 if (score > file_best_score) {
1736
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5948 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
5948 if((qcr==MKTAG('A', 'P', 'I', 'C')) && !(ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC))
1737 ✗ continue;
1738 5948 file_best_score = score;
1739 5948 file_best_ist = ist;
1740 5948 file_best_istg = NULL;
1741 }
1742 }
1743
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6464 times.
6465 if (file_best_istg) {
1744
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 file_best_score -= 5000000*!!(file_best_istg->stg->disposition & AV_DISPOSITION_DEFAULT);
1745
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (file_best_score > best_score) {
1746 1 best_score = file_best_score;
1747 1 best_istg = file_best_istg;
1748 1 best_ist = NULL;
1749 }
1750 }
1751
2/2
✓ Branch 0 taken 5948 times.
✓ Branch 1 taken 517 times.
6465 if (file_best_ist) {
1752
1/2
✓ Branch 0 taken 5948 times.
✗ Branch 1 not taken.
5948 if((qcr == MKTAG('A', 'P', 'I', 'C')) ||
1753
2/2
✓ Branch 0 taken 5940 times.
✓ Branch 1 taken 8 times.
5948 !(file_best_ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC))
1754
2/2
✓ Branch 0 taken 552 times.
✓ Branch 1 taken 5388 times.
5940 file_best_score -= 5000000*!!(file_best_ist->st->disposition & AV_DISPOSITION_DEFAULT);
1755
1/2
✓ Branch 0 taken 5948 times.
✗ Branch 1 not taken.
5948 if (file_best_score > best_score) {
1756 5948 best_score = file_best_score;
1757 5948 best_ist = file_best_ist;
1758 5948 best_istg = NULL;
1759 }
1760 }
1761 }
1762
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6423 times.
6424 if (best_istg) {
1763 1 FilterGraph *fg = best_istg->fg;
1764 1 OutputFilter *ofilter = fg->outputs[0];
1765
1766
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 av_assert0(fg->nb_outputs == 1);
1767 1 av_log(mux, AV_LOG_VERBOSE, "Creating output stream from stream group derived complex filtergraph %d.\n", fg->index);
1768
1769 1 return ost_add(mux, o, AVMEDIA_TYPE_VIDEO, NULL, ofilter, NULL, NULL);
1770 }
1771
2/2
✓ Branch 0 taken 5948 times.
✓ Branch 1 taken 475 times.
6423 if (best_ist)
1772 5948 return ost_add(mux, o, AVMEDIA_TYPE_VIDEO, best_ist, NULL, NULL, NULL);
1773
1774 475 return 0;
1775 }
1776
1777 8482 static int map_auto_audio(Muxer *mux, const OptionsContext *o)
1778 {
1779 8482 AVFormatContext *oc = mux->fc;
1780 8482 InputStream *best_ist = NULL;
1781 8482 int best_score = 0;
1782
1783 /* audio: most channels */
1784
2/2
✓ Branch 1 taken 2002 times.
✓ Branch 2 taken 6480 times.
8482 if (av_guess_codec(oc->oformat, NULL, oc->url, NULL, AVMEDIA_TYPE_AUDIO) == AV_CODEC_ID_NONE)
1785 2002 return 0;
1786
1787
2/2
✓ Branch 0 taken 6413 times.
✓ Branch 1 taken 6480 times.
12893 for (int j = 0; j < nb_input_files; j++) {
1788 6413 InputFile *ifile = input_files[j];
1789 6413 InputStream *file_best_ist = NULL;
1790 6413 int file_best_score = 0;
1791
2/2
✓ Branch 0 taken 6621 times.
✓ Branch 1 taken 6413 times.
13034 for (int i = 0; i < ifile->nb_streams; i++) {
1792 6621 InputStream *ist = ifile->streams[i];
1793 int score;
1794
1795
2/2
✓ Branch 0 taken 6620 times.
✓ Branch 1 taken 1 times.
6621 if (ist->user_set_discard == AVDISCARD_ALL ||
1796
2/2
✓ Branch 0 taken 5098 times.
✓ Branch 1 taken 1522 times.
6620 ist->st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
1797 5099 continue;
1798
1799 3044 score = ist->st->codecpar->ch_layout.nb_channels
1800
2/2
✓ Branch 0 taken 1464 times.
✓ Branch 1 taken 58 times.
1522 + 100000000 * !!(ist->st->event_flags & AVSTREAM_EVENT_FLAG_NEW_PACKETS)
1801
2/2
✓ Branch 0 taken 222 times.
✓ Branch 1 taken 1300 times.
1522 + 5000000*!!(ist->st->disposition & AV_DISPOSITION_DEFAULT);
1802
2/2
✓ Branch 0 taken 1512 times.
✓ Branch 1 taken 10 times.
1522 if (score > file_best_score) {
1803 1512 file_best_score = score;
1804 1512 file_best_ist = ist;
1805 }
1806 }
1807
2/2
✓ Branch 0 taken 1512 times.
✓ Branch 1 taken 4901 times.
6413 if (file_best_ist) {
1808
2/2
✓ Branch 0 taken 222 times.
✓ Branch 1 taken 1290 times.
1512 file_best_score -= 5000000*!!(file_best_ist->st->disposition & AV_DISPOSITION_DEFAULT);
1809
1/2
✓ Branch 0 taken 1512 times.
✗ Branch 1 not taken.
1512 if (file_best_score > best_score) {
1810 1512 best_score = file_best_score;
1811 1512 best_ist = file_best_ist;
1812 }
1813 }
1814 }
1815
2/2
✓ Branch 0 taken 1512 times.
✓ Branch 1 taken 4968 times.
6480 if (best_ist)
1816 1512 return ost_add(mux, o, AVMEDIA_TYPE_AUDIO, best_ist, NULL, NULL, NULL);
1817
1818 4968 return 0;
1819 }
1820
1821 8653 static int map_auto_subtitle(Muxer *mux, const OptionsContext *o)
1822 {
1823 8653 AVFormatContext *oc = mux->fc;
1824 8653 const char *subtitle_codec_name = NULL;
1825
1826 /* subtitles: pick first */
1827 8653 subtitle_codec_name = opt_match_per_type_str(&o->codec_names, 's');
1828
4/4
✓ Branch 1 taken 8579 times.
✓ Branch 2 taken 74 times.
✓ Branch 3 taken 8571 times.
✓ Branch 4 taken 8 times.
8653 if (!avcodec_find_encoder(oc->oformat->subtitle_codec) && !subtitle_codec_name)
1829 8571 return 0;
1830
1831
2/2
✓ Branch 2 taken 95 times.
✓ Branch 3 taken 29 times.
124 for (InputStream *ist = ist_iter(NULL); ist; ist = ist_iter(ist))
1832
2/2
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 42 times.
95 if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
1833 AVCodecDescriptor const *input_descriptor =
1834 53 avcodec_descriptor_get(ist->st->codecpar->codec_id);
1835 53 AVCodecDescriptor const *output_descriptor = NULL;
1836 AVCodec const *output_codec =
1837 53 avcodec_find_encoder(oc->oformat->subtitle_codec);
1838 53 int input_props = 0, output_props = 0;
1839
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
53 if (ist->user_set_discard == AVDISCARD_ALL)
1840 ✗ continue;
1841
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 8 times.
53 if (output_codec)
1842 45 output_descriptor = avcodec_descriptor_get(output_codec->id);
1843
1/2
✓ Branch 0 taken 53 times.
✗ Branch 1 not taken.
53 if (input_descriptor)
1844 53 input_props = input_descriptor->props & (AV_CODEC_PROP_TEXT_SUB | AV_CODEC_PROP_BITMAP_SUB);
1845
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 8 times.
53 if (output_descriptor)
1846 45 output_props = output_descriptor->props & (AV_CODEC_PROP_TEXT_SUB | AV_CODEC_PROP_BITMAP_SUB);
1847
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 17 times.
53 if (subtitle_codec_name ||
1848
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
36 input_props & output_props ||
1849 // Map dvb teletext which has neither property to any output subtitle encoder
1850 ✗ input_descriptor && output_descriptor &&
1851 ✗ (!input_descriptor->props ||
1852 ✗ !output_descriptor->props)) {
1853 53 return ost_add(mux, o, AVMEDIA_TYPE_SUBTITLE, ist, NULL, NULL, NULL);
1854 }
1855 }
1856
1857 29 return 0;
1858 }
1859
1860 8654 static int map_auto_data(Muxer *mux, const OptionsContext *o)
1861 {
1862 8654 AVFormatContext *oc = mux->fc;
1863 /* Data only if codec id match */
1864 8654 enum AVCodecID codec_id = av_guess_codec(oc->oformat, NULL, oc->url, NULL, AVMEDIA_TYPE_DATA);
1865
1866
1/2
✓ Branch 0 taken 8654 times.
✗ Branch 1 not taken.
8654 if (codec_id == AV_CODEC_ID_NONE)
1867 8654 return 0;
1868
1869 ✗ for (InputStream *ist = ist_iter(NULL); ist; ist = ist_iter(ist)) {
1870 ✗ if (ist->user_set_discard == AVDISCARD_ALL)
1871 ✗ continue;
1872 ✗ if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_DATA &&
1873 ✗ ist->st->codecpar->codec_id == codec_id) {
1874 ✗ int ret = ost_add(mux, o, AVMEDIA_TYPE_DATA, ist, NULL, NULL, NULL);
1875 ✗ if (ret < 0)
1876 ✗ return ret;
1877 }
1878 }
1879
1880 ✗ return 0;
1881 }
1882
1883 623 static int map_manual(Muxer *mux, const OptionsContext *o, const StreamMap *map)
1884 {
1885 InputStream *ist;
1886 int ret;
1887
1888
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 623 times.
623 if (map->disabled)
1889 ✗ return 0;
1890
1891
2/2
✓ Branch 0 taken 88 times.
✓ Branch 1 taken 535 times.
623 if (map->linklabel) {
1892 FilterGraph *fg;
1893 88 OutputFilter *ofilter = NULL;
1894 int j, k;
1895
1896
1/2
✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
88 for (j = 0; j < nb_filtergraphs; j++) {
1897 88 fg = filtergraphs[j];
1898
1/2
✓ Branch 0 taken 286 times.
✗ Branch 1 not taken.
286 for (k = 0; k < fg->nb_outputs; k++) {
1899 286 const char *linklabel = fg->outputs[k]->linklabel;
1900
4/4
✓ Branch 0 taken 122 times.
✓ Branch 1 taken 164 times.
✓ Branch 2 taken 88 times.
✓ Branch 3 taken 34 times.
286 if (linklabel && !strcmp(linklabel, map->linklabel)) {
1901 88 ofilter = fg->outputs[k];
1902 88 goto loop_end;
1903 }
1904 }
1905 }
1906 ✗ loop_end:
1907
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 88 times.
88 if (!ofilter) {
1908 ✗ av_log(mux, AV_LOG_FATAL, "Output with label '%s' does not exist "
1909 ✗ "in any defined filter graph, or was already used elsewhere.\n", map->linklabel);
1910 ✗ return AVERROR(EINVAL);
1911 }
1912
1913 88 av_log(mux, AV_LOG_VERBOSE, "Creating output stream from an explicitly "
1914 88 "mapped complex filtergraph %d, output [%s]\n", fg->index, map->linklabel);
1915
1916 88 ret = ost_add(mux, o, ofilter->type, NULL, ofilter, NULL, NULL);
1917
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 88 times.
88 if (ret < 0)
1918 ✗ return ret;
1919 } else {
1920 1070 const ViewSpecifier *vs = map->vs.type == VIEW_SPECIFIER_TYPE_NONE ?
1921
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 521 times.
535 NULL : &map->vs;
1922
1923 535 ist = input_files[map->file_index]->streams[map->stream_index];
1924
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 535 times.
535 if (ist->user_set_discard == AVDISCARD_ALL) {
1925 ✗ av_log(mux, AV_LOG_FATAL, "Stream #%d:%d is disabled and cannot be mapped.\n",
1926 ✗ map->file_index, map->stream_index);
1927 ✗ return AVERROR(EINVAL);
1928 }
1929
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 535 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
535 if(o->subtitle_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE)
1930 ✗ return 0;
1931
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 535 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
535 if(o-> audio_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
1932 ✗ return 0;
1933
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 534 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
535 if(o-> video_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
1934 ✗ return 0;
1935
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 535 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
535 if(o-> data_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_DATA)
1936 ✗ return 0;
1937
1938
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 535 times.
535 if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_UNKNOWN &&
1939 ✗ !copy_unknown_streams) {
1940 ✗ av_log(mux, ignore_unknown_streams ? AV_LOG_WARNING : AV_LOG_FATAL,
1941 "Cannot map stream #%d:%d - unsupported type.\n",
1942 ✗ map->file_index, map->stream_index);
1943 ✗ if (!ignore_unknown_streams) {
1944 ✗ av_log(mux, AV_LOG_FATAL,
1945 "If you want unsupported types ignored instead "
1946 "of failing, please use the -ignore_unknown option\n"
1947 "If you want them copied, please use -copy_unknown\n");
1948 ✗ return AVERROR(EINVAL);
1949 }
1950 ✗ return 0;
1951 }
1952
1953
3/4
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 521 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 14 times.
535 if (vs && ist->st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO) {
1954 ✗ av_log(mux, AV_LOG_ERROR,
1955 "View specifier given for mapping a %s input stream\n",
1956 ✗ av_get_media_type_string(ist->st->codecpar->codec_type));
1957 ✗ return AVERROR(EINVAL);
1958 }
1959
1960 535 ret = ost_add(mux, o, ist->st->codecpar->codec_type, ist, NULL, vs, NULL);
1961
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 535 times.
535 if (ret < 0)
1962 ✗ return ret;
1963 }
1964
1965 623 return 0;
1966 }
1967
1968 8934 static int of_add_attachments(Muxer *mux, const OptionsContext *o)
1969 {
1970 MuxStream *ms;
1971 OutputStream *ost;
1972 int err;
1973
1974
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8934 times.
8935 for (int i = 0; i < o->nb_attachments; i++) {
1975 AVIOContext *pb;
1976 uint8_t *attachment;
1977 char *attachment_filename;
1978 const char *p;
1979 int64_t len;
1980
1981
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if ((err = avio_open2(&pb, o->attachments[i], AVIO_FLAG_READ, &int_cb, NULL)) < 0) {
1982 ✗ av_log(mux, AV_LOG_FATAL, "Could not open attachment file %s.\n",
1983 ✗ o->attachments[i]);
1984 ✗ return err;
1985 }
1986
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if ((len = avio_size(pb)) <= 0) {
1987 ✗ av_log(mux, AV_LOG_FATAL, "Could not get size of the attachment %s.\n",
1988 ✗ o->attachments[i]);
1989 ✗ err = len ? len : AVERROR_INVALIDDATA;
1990 ✗ goto read_fail;
1991 }
1992
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (len > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) {
1993 ✗ av_log(mux, AV_LOG_FATAL, "Attachment %s too large.\n",
1994 ✗ o->attachments[i]);
1995 ✗ err = AVERROR(ERANGE);
1996 ✗ goto read_fail;
1997 }
1998
1999 1 attachment = av_malloc(len + AV_INPUT_BUFFER_PADDING_SIZE);
2000
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!attachment) {
2001 ✗ err = AVERROR(ENOMEM);
2002 ✗ goto read_fail;
2003 }
2004
2005 1 err = avio_read(pb, attachment, len);
2006
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (err < 0)
2007 ✗ av_log(mux, AV_LOG_FATAL, "Error reading attachment file %s: %s\n",
2008 ✗ o->attachments[i], av_err2str(err));
2009
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 else if (err != len) {
2010 ✗ av_log(mux, AV_LOG_FATAL, "Could not read all %"PRId64" bytes for "
2011 ✗ "attachment file %s\n", len, o->attachments[i]);
2012 ✗ err = AVERROR(EIO);
2013 }
2014
2015 1 read_fail:
2016 1 avio_closep(&pb);
2017
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (err < 0)
2018 ✗ return err;
2019
2020 1 memset(attachment + len, 0, AV_INPUT_BUFFER_PADDING_SIZE);
2021
2022 1 av_log(mux, AV_LOG_VERBOSE, "Creating attachment stream from file %s\n",
2023 1 o->attachments[i]);
2024
2025 1 attachment_filename = av_strdup(o->attachments[i]);
2026
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!attachment_filename) {
2027 ✗ av_free(attachment);
2028 ✗ return AVERROR(ENOMEM);
2029 }
2030
2031 1 err = ost_add(mux, o, AVMEDIA_TYPE_ATTACHMENT, NULL, NULL, NULL, &ost);
2032
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (err < 0) {
2033 ✗ av_free(attachment_filename);
2034 ✗ av_freep(&attachment);
2035 ✗ return err;
2036 }
2037
2038 1 ms = ms_from_ost(ost);
2039
2040 1 ost->attachment_filename = attachment_filename;
2041 1 ms->par_in->extradata = attachment;
2042 1 ms->par_in->extradata_size = len;
2043
2044 1 p = strrchr(o->attachments[i], '/');
2045
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 av_dict_set(&ost->st->metadata, "filename", (p && *p) ? p + 1 : o->attachments[i], AV_DICT_DONT_OVERWRITE);
2046 }
2047
2048 8934 return 0;
2049 }
2050
2051 8935 static int create_streams(Muxer *mux, const OptionsContext *o)
2052 {
2053 static int (* const map_func[])(Muxer *mux, const OptionsContext *o) = {
2054 [AVMEDIA_TYPE_VIDEO] = map_auto_video,
2055 [AVMEDIA_TYPE_AUDIO] = map_auto_audio,
2056 [AVMEDIA_TYPE_SUBTITLE] = map_auto_subtitle,
2057 [AVMEDIA_TYPE_DATA] = map_auto_data,
2058 };
2059
2060 8935 AVFormatContext *oc = mux->fc;
2061
2062 8935 int auto_disable =
2063 8935 o->video_disable * (1 << AVMEDIA_TYPE_VIDEO) |
2064 8935 o->audio_disable * (1 << AVMEDIA_TYPE_AUDIO) |
2065 8935 o->subtitle_disable * (1 << AVMEDIA_TYPE_SUBTITLE) |
2066 8935 o->data_disable * (1 << AVMEDIA_TYPE_DATA);
2067
2068 int ret;
2069
2070 /* create streams for all unlabeled output pads */
2071
2/2
✓ Branch 0 taken 1319 times.
✓ Branch 1 taken 8935 times.
10254 for (int i = 0; i < nb_filtergraphs; i++) {
2072 1319 FilterGraph *fg = filtergraphs[i];
2073
2/2
✓ Branch 0 taken 1558 times.
✓ Branch 1 taken 1319 times.
2877 for (int j = 0; j < fg->nb_outputs; j++) {
2074 1558 OutputFilter *ofilter = fg->outputs[j];
2075
2076
4/4
✓ Branch 0 taken 1460 times.
✓ Branch 1 taken 98 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 1457 times.
1558 if (ofilter->linklabel || ofilter->bound)
2077 101 continue;
2078
2079 1457 auto_disable |= 1 << ofilter->type;
2080
2081 1457 av_log(mux, AV_LOG_VERBOSE, "Creating output stream from unlabeled "
2082 "output of complex filtergraph %d.", fg->index);
2083
1/2
✓ Branch 0 taken 1457 times.
✗ Branch 1 not taken.
1457 if (!o->nb_stream_maps)
2084 1457 av_log(mux, AV_LOG_VERBOSE, " This overrides automatic %s mapping.",
2085 av_get_media_type_string(ofilter->type));
2086 1457 av_log(mux, AV_LOG_VERBOSE, "\n");
2087
2088 1457 ret = ost_add(mux, o, ofilter->type, NULL, ofilter, NULL, NULL);
2089
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1457 times.
1457 if (ret < 0)
2090 ✗ return ret;
2091 }
2092 }
2093
2094
2/2
✓ Branch 0 taken 8655 times.
✓ Branch 1 taken 280 times.
8935 if (!o->nb_stream_maps) {
2095 8655 av_log(mux, AV_LOG_VERBOSE, "No explicit maps, mapping streams automatically...\n");
2096
2097 /* pick the "best" stream of each type */
2098
2/2
✓ Branch 0 taken 34618 times.
✓ Branch 1 taken 8654 times.
43272 for (int i = 0; i < FF_ARRAY_ELEMS(map_func); i++) {
2099
3/4
✓ Branch 0 taken 34618 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1615 times.
✓ Branch 3 taken 33003 times.
34618 if (!map_func[i] || auto_disable & (1 << i))
2100 1615 continue;
2101 33003 ret = map_func[i](mux, o);
2102
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 33002 times.
33003 if (ret < 0)
2103 1 return ret;
2104 }
2105 } else {
2106 280 av_log(mux, AV_LOG_VERBOSE, "Adding streams from explicit maps...\n");
2107
2108
2/2
✓ Branch 0 taken 623 times.
✓ Branch 1 taken 280 times.
903 for (int i = 0; i < o->nb_stream_maps; i++) {
2109 623 ret = map_manual(mux, o, &o->stream_maps[i]);
2110
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 623 times.
623 if (ret < 0)
2111 ✗ return ret;
2112 }
2113 }
2114
2115 8934 ret = of_add_attachments(mux, o);
2116
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8934 times.
8934 if (ret < 0)
2117 ✗ return ret;
2118
2119 // setup fix_sub_duration_heartbeat mappings
2120
2/2
✓ Branch 0 taken 9594 times.
✓ Branch 1 taken 8934 times.
18528 for (unsigned i = 0; i < oc->nb_streams; i++) {
2121 9594 MuxStream *src = ms_from_ost(mux->of.streams[i]);
2122
2123
2/2
✓ Branch 0 taken 9593 times.
✓ Branch 1 taken 1 times.
9594 if (!src->ost.fix_sub_duration_heartbeat)
2124 9593 continue;
2125
2126
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 for (unsigned j = 0; j < oc->nb_streams; j++) {
2127 2 MuxStream *dst = ms_from_ost(mux->of.streams[j]);
2128
2129
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 if (src == dst || dst->ost.type != AVMEDIA_TYPE_SUBTITLE ||
2130
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 !dst->ost.enc || !dst->ost.ist || !dst->ost.ist->fix_sub_duration)
2131 1 continue;
2132
2133 1 ret = sch_mux_sub_heartbeat_add(mux->sch, mux->sch_idx, src->sch_idx,
2134 1 dst->sch_idx_src);
2135
2136 }
2137 }
2138
2139 // handle -apad
2140
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 8930 times.
8934 if (o->shortest) {
2141 4 int have_video = 0;
2142
2143
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 for (unsigned i = 0; i < mux->of.nb_streams; i++)
2144
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (mux->of.streams[i]->type == AVMEDIA_TYPE_VIDEO) {
2145 4 have_video = 1;
2146 4 break;
2147 }
2148
2149
3/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 4 times.
12 for (unsigned i = 0; have_video && i < mux->of.nb_streams; i++) {
2150 8 MuxStream *ms = ms_from_ost(mux->of.streams[i]);
2151 8 OutputFilter *ofilter = ms->ost.filter;
2152
2153
3/6
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
8 if (ms->ost.type != AVMEDIA_TYPE_AUDIO || !ms->apad || !ofilter)
2154 8 continue;
2155
2156 ✗ ofilter->apad = av_strdup(ms->apad);
2157 ✗ if (!ofilter->apad)
2158 ✗ return AVERROR(ENOMEM);
2159 }
2160 }
2161
2/2
✓ Branch 0 taken 9594 times.
✓ Branch 1 taken 8934 times.
18528 for (unsigned i = 0; i < mux->of.nb_streams; i++) {
2162 9594 MuxStream *ms = ms_from_ost(mux->of.streams[i]);
2163 9594 ms->apad = NULL;
2164 }
2165
2166
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8934 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8934 if (!oc->nb_streams && !(oc->oformat->flags & AVFMT_NOSTREAMS)) {
2167 ✗ av_dump_format(oc, nb_output_files - 1, oc->url, 1);
2168 ✗ av_log(mux, AV_LOG_ERROR, "Output file does not contain any stream\n");
2169 ✗ return AVERROR(EINVAL);
2170 }
2171
2172 8934 return check_stereo3d_leftovers(mux, o);
2173 }
2174
2175 8931 static int setup_sync_queues(Muxer *mux, AVFormatContext *oc,
2176 int64_t buf_size_us, int shortest)
2177 {
2178 8931 OutputFile *of = &mux->of;
2179 8931 int nb_av_enc = 0, nb_audio_fs = 0, nb_interleaved = 0;
2180 8931 int limit_frames = 0, limit_frames_av_enc = 0;
2181
2182 #define IS_AV_ENC(ost, type) \
2183 (ost->enc && (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO))
2184 #define IS_INTERLEAVED(type) (type != AVMEDIA_TYPE_ATTACHMENT)
2185
2186
2/2
✓ Branch 0 taken 9591 times.
✓ Branch 1 taken 8931 times.
18522 for (int i = 0; i < oc->nb_streams; i++) {
2187 9591 OutputStream *ost = of->streams[i];
2188 9591 MuxStream *ms = ms_from_ost(ost);
2189 9591 enum AVMediaType type = ost->type;
2190
2191 9591 ms->sq_idx_mux = -1;
2192
2193 9591 nb_interleaved += IS_INTERLEAVED(type);
2194
6/6
✓ Branch 0 taken 8610 times.
✓ Branch 1 taken 981 times.
✓ Branch 2 taken 1624 times.
✓ Branch 3 taken 6986 times.
✓ Branch 4 taken 1580 times.
✓ Branch 5 taken 44 times.
9591 nb_av_enc += IS_AV_ENC(ost, type);
2195
4/4
✓ Branch 0 taken 8610 times.
✓ Branch 1 taken 981 times.
✓ Branch 2 taken 1580 times.
✓ Branch 3 taken 7030 times.
11171 nb_audio_fs += (ost->enc && type == AVMEDIA_TYPE_AUDIO &&
2196
2/2
✓ Branch 0 taken 1250 times.
✓ Branch 1 taken 330 times.
1580 (!(ost->enc->enc_ctx->codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE) ||
2197
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1250 times.
1250 (ost->enc->flags2 & AV_CODEC_FLAG2_FIXED_FRAME_SIZE)));
2198
2199 9591 limit_frames |= ms->max_frames < INT64_MAX;
2200
7/8
✓ Branch 0 taken 3192 times.
✓ Branch 1 taken 6399 times.
✓ Branch 2 taken 3111 times.
✓ Branch 3 taken 81 times.
✓ Branch 4 taken 40 times.
✓ Branch 5 taken 3071 times.
✓ Branch 6 taken 40 times.
✗ Branch 7 not taken.
9591 limit_frames_av_enc |= (ms->max_frames < INT64_MAX) && IS_AV_ENC(ost, type);
2201 }
2202
2203
7/8
✓ Branch 0 taken 269 times.
✓ Branch 1 taken 8662 times.
✓ Branch 2 taken 265 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 8927 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5621 times.
✓ Branch 7 taken 168 times.
14720 if (!((nb_interleaved > 1 && shortest) ||
2204
2/2
✓ Branch 0 taken 5789 times.
✓ Branch 1 taken 3138 times.
8927 (nb_interleaved > 0 && limit_frames) ||
2205 nb_audio_fs))
2206 5621 return 0;
2207
2208 /* we use a sync queue before encoding when:
2209 * - 'shortest' is in effect and we have two or more encoded audio/video
2210 * streams
2211 * - at least one encoded audio/video stream is frame-limited, since
2212 * that has similar semantics to 'shortest'
2213 * - at least one audio encoder requires constant frame sizes
2214 *
2215 * Note that encoding sync queues are handled in the scheduler, because
2216 * different encoders run in different threads and need external
2217 * synchronization, while muxer sync queues can be handled inside the muxer
2218 */
2219
8/8
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3306 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 199 times.
✓ Branch 5 taken 3110 times.
✓ Branch 6 taken 170 times.
✓ Branch 7 taken 29 times.
3310 if ((shortest && nb_av_enc > 1) || limit_frames_av_enc || nb_audio_fs) {
2220 int sq_idx, ret;
2221
2222 3281 sq_idx = sch_add_sq_enc(mux->sch, buf_size_us, mux);
2223
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3281 times.
3281 if (sq_idx < 0)
2224 ✗ return sq_idx;
2225
2226
2/2
✓ Branch 0 taken 3453 times.
✓ Branch 1 taken 3281 times.
6734 for (int i = 0; i < oc->nb_streams; i++) {
2227 3453 OutputStream *ost = of->streams[i];
2228 3453 MuxStream *ms = ms_from_ost(ost);
2229 3453 enum AVMediaType type = ost->type;
2230
2231
5/6
✓ Branch 0 taken 3446 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 358 times.
✓ Branch 3 taken 3088 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 358 times.
3453 if (!IS_AV_ENC(ost, type))
2232 7 continue;
2233
2234 3446 ret = sch_sq_add_enc(mux->sch, sq_idx, ms->sch_idx_enc,
2235
2/2
✓ Branch 0 taken 3111 times.
✓ Branch 1 taken 331 times.
3442 shortest || ms->max_frames < INT64_MAX,
2236
2/2
✓ Branch 0 taken 3442 times.
✓ Branch 1 taken 4 times.
3446 ms->max_frames);
2237
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3446 times.
3446 if (ret < 0)
2238 ✗ return ret;
2239 }
2240 }
2241
2242 /* if there are any additional interleaved streams, then ALL the streams
2243 * are also synchronized before sending them to the muxer */
2244
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 3277 times.
3310 if (nb_interleaved > nb_av_enc) {
2245 33 mux->sq_mux = sq_alloc(SYNC_QUEUE_PACKETS, buf_size_us, mux);
2246
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 if (!mux->sq_mux)
2247 ✗ return AVERROR(ENOMEM);
2248
2249 33 mux->sq_pkt = av_packet_alloc();
2250
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 if (!mux->sq_pkt)
2251 ✗ return AVERROR(ENOMEM);
2252
2253
2/2
✓ Branch 0 taken 97 times.
✓ Branch 1 taken 33 times.
130 for (int i = 0; i < oc->nb_streams; i++) {
2254 97 OutputStream *ost = of->streams[i];
2255 97 MuxStream *ms = ms_from_ost(ost);
2256 97 enum AVMediaType type = ost->type;
2257
2258
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 97 times.
97 if (!IS_INTERLEAVED(type))
2259 ✗ continue;
2260
2261
2/2
✓ Branch 0 taken 91 times.
✓ Branch 1 taken 6 times.
188 ms->sq_idx_mux = sq_add_stream(mux->sq_mux,
2262
2/2
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 10 times.
91 shortest || ms->max_frames < INT64_MAX);
2263
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 97 times.
97 if (ms->sq_idx_mux < 0)
2264 ✗ return ms->sq_idx_mux;
2265
2266
2/2
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 16 times.
97 if (ms->max_frames != INT64_MAX)
2267 81 sq_limit_frames(mux->sq_mux, ms->sq_idx_mux, ms->max_frames);
2268 }
2269 }
2270
2271 #undef IS_AV_ENC
2272 #undef IS_INTERLEAVED
2273
2274 3310 return 0;
2275 }
2276
2277 15 static int of_parse_iamf_audio_element_layers(Muxer *mux, AVStreamGroup *stg, char *ptr)
2278 {
2279 15 AVIAMFAudioElement *audio_element = stg->params.iamf_audio_element;
2280 15 AVDictionary *dict = NULL;
2281 const char *token;
2282 15 int ret = 0;
2283
2284 15 audio_element->demixing_info =
2285 15 av_iamf_param_definition_alloc(AV_IAMF_PARAMETER_DEFINITION_DEMIXING, 1, NULL);
2286 15 audio_element->recon_gain_info =
2287 15 av_iamf_param_definition_alloc(AV_IAMF_PARAMETER_DEFINITION_RECON_GAIN, 1, NULL);
2288
2289
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 if (!audio_element->demixing_info ||
2290
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 !audio_element->recon_gain_info)
2291 ✗ return AVERROR(ENOMEM);
2292
2293 /* process manually set layers and parameters */
2294 15 token = av_strtok(NULL, ",", &ptr);
2295
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 15 times.
66 while (token) {
2296 const AVDictionaryEntry *e;
2297 51 int demixing = 0, recon_gain = 0;
2298 51 int layer = 0;
2299
2300
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 3 times.
51 if (ptr)
2301 48 ptr += strspn(ptr, " \n\t\r");
2302
2/2
✓ Branch 1 taken 31 times.
✓ Branch 2 taken 20 times.
51 if (av_strstart(token, "layer=", &token))
2303 31 layer = 1;
2304
2/2
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 10 times.
20 else if (av_strstart(token, "demixing=", &token))
2305 10 demixing = 1;
2306
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 else if (av_strstart(token, "recon_gain=", &token))
2307 10 recon_gain = 1;
2308
2309 51 av_dict_free(&dict);
2310 51 ret = av_dict_parse_string(&dict, token, "=", ":", 0);
2311
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
51 if (ret < 0) {
2312 ✗ av_log(mux, AV_LOG_ERROR, "Error parsing audio element specification %s\n", token);
2313 ✗ goto fail;
2314 }
2315
2316
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 20 times.
51 if (layer) {
2317 31 AVIAMFLayer *audio_layer = av_iamf_audio_element_add_layer(audio_element);
2318
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (!audio_layer) {
2319 ✗ av_log(mux, AV_LOG_ERROR, "Error adding layer to stream group %d\n", stg->index);
2320 ✗ ret = AVERROR(ENOMEM);
2321 ✗ goto fail;
2322 }
2323 31 av_opt_set_dict(audio_layer, &dict);
2324
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
20 } else if (demixing || recon_gain) {
2325 20 AVIAMFParamDefinition *param = demixing ? audio_element->demixing_info
2326
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 : audio_element->recon_gain_info;
2327 20 void *subblock = av_iamf_param_definition_get_subblock(param, 0);
2328
2329 20 av_opt_set_dict(param, &dict);
2330 20 av_opt_set_dict(subblock, &dict);
2331 }
2332
2333 // make sure that no entries are left in the dict
2334 51 e = NULL;
2335
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 51 times.
51 if (e = av_dict_iterate(dict, e)) {
2336 ✗ av_log(mux, AV_LOG_FATAL, "Unknown layer key %s.\n", e->key);
2337 ✗ ret = AVERROR(EINVAL);
2338 ✗ goto fail;
2339 }
2340 51 token = av_strtok(NULL, ",", &ptr);
2341 }
2342
2343 15 fail:
2344 15 av_dict_free(&dict);
2345
2/4
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
15 if (!ret && !audio_element->nb_layers) {
2346 ✗ av_log(mux, AV_LOG_ERROR, "No layer in audio element specification\n");
2347 ✗ ret = AVERROR(EINVAL);
2348 }
2349
2350 15 return ret;
2351 }
2352
2353 14 static int of_parse_iamf_submixes(Muxer *mux, AVStreamGroup *stg, char *ptr)
2354 {
2355 14 AVFormatContext *oc = mux->fc;
2356 14 AVIAMFMixPresentation *mix = stg->params.iamf_mix_presentation;
2357 14 AVDictionary *dict = NULL;
2358 const char *token;
2359 14 char *submix_str = NULL;
2360 14 int ret = 0;
2361
2362 /* process manually set submixes */
2363 14 token = av_strtok(NULL, ",", &ptr);
2364
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 14 times.
30 while (token) {
2365 16 AVIAMFSubmix *submix = NULL;
2366 const char *subtoken;
2367 16 char *subptr = NULL;
2368
2369
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 3 times.
16 if (ptr)
2370 13 ptr += strspn(ptr, " \n\t\r");
2371
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
16 if (!av_strstart(token, "submix=", &token)) {
2372 ✗ av_log(mux, AV_LOG_ERROR, "No submix in mix presentation specification \"%s\"\n", token);
2373 ✗ goto fail;
2374 }
2375
2376 16 submix_str = av_strdup(token);
2377
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!submix_str)
2378 ✗ goto fail;
2379
2380 16 submix = av_iamf_mix_presentation_add_submix(mix);
2381
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!submix) {
2382 ✗ av_log(mux, AV_LOG_ERROR, "Error adding submix to stream group %d\n", stg->index);
2383 ✗ ret = AVERROR(ENOMEM);
2384 ✗ goto fail;
2385 }
2386 16 submix->output_mix_config =
2387 16 av_iamf_param_definition_alloc(AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN, 0, NULL);
2388
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!submix->output_mix_config) {
2389 ✗ ret = AVERROR(ENOMEM);
2390 ✗ goto fail;
2391 }
2392
2393 16 subptr = NULL;
2394 16 subtoken = av_strtok(submix_str, "|", &subptr);
2395
2/2
✓ Branch 0 taken 67 times.
✓ Branch 1 taken 16 times.
83 while (subtoken) {
2396 const AVDictionaryEntry *e;
2397 67 int element = 0, layout = 0;
2398
2399
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 16 times.
67 if (subptr)
2400 51 subptr += strspn(subptr, " \n\t\r");
2401
2/2
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 50 times.
67 if (av_strstart(subtoken, "element=", &subtoken))
2402 17 element = 1;
2403
2/2
✓ Branch 1 taken 34 times.
✓ Branch 2 taken 16 times.
50 else if (av_strstart(subtoken, "layout=", &subtoken))
2404 34 layout = 1;
2405
2406 67 av_dict_free(&dict);
2407 67 ret = av_dict_parse_string(&dict, subtoken, "=", ":", 0);
2408
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 67 times.
67 if (ret < 0) {
2409 ✗ av_log(mux, AV_LOG_ERROR, "Error parsing submix specification \"%s\"\n", subtoken);
2410 ✗ goto fail;
2411 }
2412
2413
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 50 times.
67 if (element) {
2414 AVIAMFSubmixElement *submix_element;
2415 17 char *endptr = NULL;
2416 17 int64_t idx = -1;
2417
2418
1/2
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
17 if (e = av_dict_get(dict, "stg", NULL, 0))
2419 17 idx = strtoll(e->value, &endptr, 0);
2420
4/8
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 17 times.
✗ Branch 7 not taken.
17 if (!endptr || *endptr || idx < 0 || idx >= oc->nb_stream_groups - 1 ||
2421
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 oc->stream_groups[idx]->type != AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT) {
2422 ✗ av_log(mux, AV_LOG_ERROR, "Invalid or missing stream group index in "
2423 "submix element specification \"%s\"\n", subtoken);
2424 ✗ ret = AVERROR(EINVAL);
2425 ✗ goto fail;
2426 }
2427 17 submix_element = av_iamf_submix_add_element(submix);
2428
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if (!submix_element) {
2429 ✗ av_log(mux, AV_LOG_ERROR, "Error adding element to submix\n");
2430 ✗ ret = AVERROR(ENOMEM);
2431 ✗ goto fail;
2432 }
2433
2434 17 submix_element->audio_element_id = oc->stream_groups[idx]->id;
2435
2436 17 submix_element->element_mix_config =
2437 17 av_iamf_param_definition_alloc(AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN, 0, NULL);
2438
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if (!submix_element->element_mix_config)
2439 ✗ ret = AVERROR(ENOMEM);
2440 17 av_dict_set(&dict, "stg", NULL, 0);
2441 17 av_opt_set_dict2(submix_element, &dict, AV_OPT_SEARCH_CHILDREN);
2442
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 16 times.
50 } else if (layout) {
2443 34 AVIAMFSubmixLayout *submix_layout = av_iamf_submix_add_layout(submix);
2444
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 if (!submix_layout) {
2445 ✗ av_log(mux, AV_LOG_ERROR, "Error adding layout to submix\n");
2446 ✗ ret = AVERROR(ENOMEM);
2447 ✗ goto fail;
2448 }
2449 34 av_opt_set_dict(submix_layout, &dict);
2450 } else
2451 16 av_opt_set_dict2(submix, &dict, AV_OPT_SEARCH_CHILDREN);
2452
2453
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 67 times.
67 if (ret < 0) {
2454 ✗ goto fail;
2455 }
2456
2457 // make sure that no entries are left in the dict
2458 67 e = NULL;
2459
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 67 times.
67 while (e = av_dict_iterate(dict, e)) {
2460 ✗ av_log(mux, AV_LOG_FATAL, "Unknown submix key %s.\n", e->key);
2461 ✗ ret = AVERROR(EINVAL);
2462 ✗ goto fail;
2463 }
2464 67 subtoken = av_strtok(NULL, "|", &subptr);
2465 }
2466 16 av_freep(&submix_str);
2467
2468
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!submix->nb_elements) {
2469 ✗ av_log(mux, AV_LOG_ERROR, "No audio elements in submix specification \"%s\"\n", token);
2470 ✗ ret = AVERROR(EINVAL);
2471 }
2472 16 token = av_strtok(NULL, ",", &ptr);
2473 }
2474
2475 14 fail:
2476 14 av_dict_free(&dict);
2477 14 av_free(submix_str);
2478
2479 14 return ret;
2480 }
2481
2482 27 static int of_serialize_options(Muxer *mux, void *obj, AVBPrint *bp)
2483 {
2484 char *ptr;
2485 int ret;
2486
2487 27 ret = av_opt_serialize(obj, AV_OPT_FLAG_DEPRECATED,
2488 AV_OPT_SERIALIZE_SKIP_DEFAULTS |
2489 AV_OPT_SERIALIZE_SEARCH_CHILDREN |
2490 AV_OPT_SERIALIZE_OPT_FLAGS_EXCLUDE,
2491 &ptr, '=', ':');
2492
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (ret < 0) {
2493 ✗ av_log(mux, AV_LOG_ERROR, "Failed to serialize group\n");
2494 ✗ return ret;
2495 }
2496
2497 27 av_bprintf(bp, "%s", ptr);
2498 27 ret = strlen(ptr);
2499 27 av_free(ptr);
2500
2501 27 return ret;
2502 }
2503
2504 #define SERIALIZE(parent, child) do { \
2505 ret = of_serialize_options(mux, parent->child, bp); \
2506 if (ret < 0) \
2507 return ret; \
2508 } while (0)
2509
2510 #define SERIALIZE_LOOP_SUBBLOCK(obj) do { \
2511 for (int k = 0; k < obj->nb_subblocks; k++) { \
2512 ret = of_serialize_options(mux, \
2513 av_iamf_param_definition_get_subblock(obj, k), bp); \
2514 if (ret < 0) \
2515 return ret; \
2516 } \
2517 } while (0)
2518
2519 #define SERIALIZE_LOOP(parent, child, suffix, separator) do { \
2520 for (int j = 0; j < parent->nb_## child ## suffix; j++) { \
2521 av_bprintf(bp, separator#child "="); \
2522 SERIALIZE(parent, child ## suffix[j]); \
2523 } \
2524 } while (0)
2525
2526 3 static int64_t get_stream_group_index_from_id(Muxer *mux, int64_t id)
2527 {
2528 3 AVFormatContext *oc = mux->fc;
2529
2530
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 for (unsigned i = 0; i < oc->nb_stream_groups; i++)
2531
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (oc->stream_groups[i]->id == id)
2532 3 return oc->stream_groups[i]->index;
2533
2534 ✗ return AVERROR(EINVAL);
2535 }
2536
2537 8 static int of_map_group(Muxer *mux, AVDictionary **dict, AVBPrint *bp, const char *map)
2538 {
2539 AVStreamGroup *stg;
2540 int ret, file_idx, stream_idx;
2541 char *ptr;
2542
2543 8 file_idx = strtol(map, &ptr, 0);
2544
3/6
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 8 times.
8 if (file_idx >= nb_input_files || file_idx < 0 || map == ptr) {
2545 ✗ av_log(mux, AV_LOG_ERROR, "Invalid input file index: %d.\n", file_idx);
2546 ✗ return AVERROR(EINVAL);
2547 }
2548
2549
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 stream_idx = strtol(*ptr == '=' ? ptr + 1 : ptr, &ptr, 0);
2550
3/6
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 8 times.
8 if (*ptr || stream_idx >= input_files[file_idx]->ctx->nb_stream_groups || stream_idx < 0) {
2551 ✗ av_log(mux, AV_LOG_ERROR, "Invalid input stream group index: %d.\n", stream_idx);
2552 ✗ return AVERROR(EINVAL);
2553 }
2554
2555 8 stg = input_files[file_idx]->ctx->stream_groups[stream_idx];
2556 8 ret = of_serialize_options(mux, stg, bp);
2557
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (ret < 0)
2558 ✗ return ret;
2559
2560 8 ret = av_dict_parse_string(dict, bp->str, "=", ":", 0);
2561
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (ret < 0)
2562 ✗ av_log(mux, AV_LOG_ERROR, "Error parsing mapped group specification %s\n", ptr);
2563 8 av_dict_set_int(dict, "type", stg->type, 0);
2564
2565 8 av_bprint_clear(bp);
2566
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
8 switch(stg->type) {
2567 3 case AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT: {
2568 3 AVIAMFAudioElement *audio_element = stg->params.iamf_audio_element;
2569
2570
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (audio_element->demixing_info) {
2571 1 AVIAMFParamDefinition *demixing_info = audio_element->demixing_info;
2572 1 av_bprintf(bp, ",demixing=");
2573
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 SERIALIZE(audio_element, demixing_info);
2574
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 if (ret && demixing_info->nb_subblocks)
2575 1 av_bprintf(bp, ":");
2576
3/4
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
2 SERIALIZE_LOOP_SUBBLOCK(demixing_info);
2577 }
2578
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (audio_element->recon_gain_info) {
2579 1 AVIAMFParamDefinition *recon_gain_info = audio_element->recon_gain_info;
2580 1 av_bprintf(bp, ",recon_gain=");
2581
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 SERIALIZE(audio_element, recon_gain_info);
2582
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 if (ret && recon_gain_info->nb_subblocks)
2583 1 av_bprintf(bp, ":");
2584
3/4
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
2 SERIALIZE_LOOP_SUBBLOCK(recon_gain_info);
2585 }
2586
3/4
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 3 times.
7 SERIALIZE_LOOP(audio_element, layer, s, ",");
2587 3 break;
2588 }
2589 3 case AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION: {
2590 3 AVIAMFMixPresentation *mix = stg->params.iamf_mix_presentation;
2591
2592
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 for (int i = 0; i < mix->nb_submixes; i++) {
2593 3 AVIAMFSubmix *submix = mix->submixes[i];
2594 3 AVIAMFParamDefinition *output_mix_config = submix->output_mix_config;
2595
2596 3 av_bprintf(bp, ",submix=");
2597
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 SERIALIZE(mix, submixes[i]);
2598
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 if (ret && output_mix_config->nb_subblocks)
2599 ✗ av_bprintf(bp, ":");
2600
1/4
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
3 SERIALIZE_LOOP_SUBBLOCK(output_mix_config);
2601
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 for (int j = 0; j < submix->nb_elements; j++) {
2602 3 AVIAMFSubmixElement *element = submix->elements[j];
2603 3 AVIAMFParamDefinition *element_mix_config = element->element_mix_config;
2604 3 int64_t id = get_stream_group_index_from_id(mux, element->audio_element_id);
2605
2606
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (id < 0) {
2607 ✗ av_log(mux, AV_LOG_ERROR, "Invalid or missing stream group index in"
2608 "submix element");
2609 ✗ return id;
2610 }
2611
2612 3 av_bprintf(bp, "|element=");
2613
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 SERIALIZE(submix, elements[j]);
2614
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 if (ret && element_mix_config->nb_subblocks)
2615 ✗ av_bprintf(bp, ":");
2616
1/4
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
3 SERIALIZE_LOOP_SUBBLOCK(element_mix_config);
2617
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (ret)
2618 3 av_bprintf(bp, ":");
2619 3 av_bprintf(bp, "stg=%"PRId64, id);
2620 }
2621
3/4
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 3 times.
8 SERIALIZE_LOOP(submix, layout, s, "|");
2622 }
2623 3 break;
2624 }
2625 2 case AV_STREAM_GROUP_PARAMS_LCEVC:
2626 case AV_STREAM_GROUP_PARAMS_TREF:
2627 case AV_STREAM_GROUP_PARAMS_DOLBY_VISION:
2628 case AV_STREAM_GROUP_PARAMS_GAIN_MAP:
2629 2 break;
2630 ✗ default:
2631 ✗ av_log(mux, AV_LOG_ERROR, "Unsupported mapped group type %d.\n", stg->type);
2632 ✗ ret = AVERROR(EINVAL);
2633 ✗ break;
2634 }
2635 8 return 0;
2636 }
2637
2638 32 static int of_parse_group_token(Muxer *mux, const char *token, char *ptr)
2639 {
2640 32 AVFormatContext *oc = mux->fc;
2641 AVStreamGroup *stg;
2642 32 AVDictionary *dict = NULL, *tmp = NULL;
2643 32 char *mapped_string = NULL;
2644 const AVDictionaryEntry *e;
2645 32 const AVOption opts[] = {
2646 { "type", "Set group type", offsetof(AVStreamGroup, type), AV_OPT_TYPE_INT,
2647 { .i64 = 0 }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, .unit = "type" },
2648 { "iamf_audio_element", NULL, 0, AV_OPT_TYPE_CONST,
2649 { .i64 = AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT }, .unit = "type" },
2650 { "iamf_mix_presentation", NULL, 0, AV_OPT_TYPE_CONST,
2651 { .i64 = AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION }, .unit = "type" },
2652 { "lcevc", NULL, 0, AV_OPT_TYPE_CONST,
2653 { .i64 = AV_STREAM_GROUP_PARAMS_LCEVC }, .unit = "type" },
2654 { "tref", NULL, 0, AV_OPT_TYPE_CONST,
2655 { .i64 = AV_STREAM_GROUP_PARAMS_TREF }, .unit = "type" },
2656 { "gain_map", NULL, 0, AV_OPT_TYPE_CONST,
2657 { .i64 = AV_STREAM_GROUP_PARAMS_GAIN_MAP }, .unit = "type" },
2658 { NULL },
2659 };
2660 32 const AVClass class = {
2661 .class_name = "StreamGroupType",
2662 .item_name = av_default_item_name,
2663 .option = opts,
2664 .version = LIBAVUTIL_VERSION_INT,
2665 };
2666 32 const AVClass *pclass = &class;
2667 int type, ret;
2668
2669 32 ret = av_dict_parse_string(&dict, token, "=", ":", AV_DICT_MULTIKEY);
2670
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (ret < 0) {
2671 ✗ av_log(mux, AV_LOG_ERROR, "Error parsing group specification %s\n", token);
2672 ✗ return ret;
2673 }
2674
2675 32 av_dict_copy(&tmp, dict, 0);
2676 32 e = av_dict_get(dict, "map", NULL, 0);
2677
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 24 times.
32 if (e) {
2678 AVBPrint bp;
2679
2680
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (ptr) {
2681 ✗ av_log(mux, AV_LOG_ERROR, "Unexpected extra parameters when mapping a"
2682 " stream group\n");
2683 ✗ ret = AVERROR(EINVAL);
2684 ✗ goto end;
2685 }
2686
2687 8 av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC);
2688 8 ret = of_map_group(mux, &tmp, &bp, e->value);
2689
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (ret < 0) {
2690 ✗ av_bprint_finalize(&bp, NULL);
2691 ✗ goto end;
2692 }
2693
2694 8 av_bprint_finalize(&bp, &mapped_string);
2695 8 ptr = mapped_string;
2696 }
2697
2698 // "type" is not a user settable AVOption in AVStreamGroup, so handle it here
2699 32 e = av_dict_get(tmp, "type", NULL, 0);
2700
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (!e) {
2701 ✗ av_log(mux, AV_LOG_ERROR, "No type specified for Stream Group in \"%s\"\n", token);
2702 ✗ ret = AVERROR(EINVAL);
2703 ✗ goto end;
2704 }
2705
2706 32 ret = av_opt_eval_int(&pclass, opts, e->value, &type);
2707
2/4
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 32 times.
32 if (!ret && type == AV_STREAM_GROUP_PARAMS_NONE)
2708 ✗ ret = AVERROR(EINVAL);
2709
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (ret < 0) {
2710 ✗ av_log(mux, AV_LOG_ERROR, "Invalid group type \"%s\"\n", e->value);
2711 ✗ goto end;
2712 }
2713
2714 32 stg = avformat_stream_group_create(oc, type, &tmp);
2715
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (!stg) {
2716 ✗ ret = AVERROR(ENOMEM);
2717 ✗ goto end;
2718 }
2719
2720 32 e = NULL;
2721
2/2
✓ Branch 1 taken 87 times.
✓ Branch 2 taken 32 times.
119 while (e = av_dict_get(dict, "st", e, 0)) {
2722 char *endptr;
2723 87 int64_t idx = strtoll(e->value, &endptr, 0);
2724
3/6
✓ Branch 0 taken 87 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 87 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 87 times.
87 if (*endptr || idx < 0 || idx >= oc->nb_streams) {
2725 ✗ av_log(mux, AV_LOG_ERROR, "Invalid stream index %"PRId64"\n", idx);
2726 ✗ ret = AVERROR(EINVAL);
2727 ✗ goto end;
2728 }
2729 87 ret = avformat_stream_group_add_stream(stg, oc->streams[idx]);
2730
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 87 times.
87 if (ret < 0)
2731 ✗ goto end;
2732 87 OutputStream *ost = mux->of.streams[idx];
2733
4/4
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 57 times.
87 if (ost->enc && (type == AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT ||
2734
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 type == AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION))
2735 57 ost->enc->flags2 |= AV_CODEC_FLAG2_FIXED_FRAME_SIZE;
2736 }
2737
2/2
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 32 times.
46 while (e = av_dict_get(dict, "stg", e, 0)) {
2738 char *endptr;
2739 14 int64_t idx = strtoll(e->value, &endptr, 0);
2740
3/6
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 14 times.
14 if (*endptr || idx < 0 || idx >= oc->nb_stream_groups - 1) {
2741 ✗ av_log(mux, AV_LOG_ERROR, "Invalid stream group index %"PRId64"\n", idx);
2742 ✗ ret = AVERROR(EINVAL);
2743 ✗ goto end;
2744 }
2745
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 14 times.
94 for (unsigned i = 0; i < oc->stream_groups[idx]->nb_entries; i++) {
2746 80 ret = avformat_stream_group_add_stream(stg, oc->stream_groups[idx]->entries[i]->stream);
2747
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (ret < 0)
2748 ✗ goto end;
2749 }
2750 }
2751
2752
3/3
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 3 times.
32 switch(type) {
2753 15 case AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT:
2754 15 ret = of_parse_iamf_audio_element_layers(mux, stg, ptr);
2755 15 break;
2756 14 case AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION:
2757 14 ret = of_parse_iamf_submixes(mux, stg, ptr);
2758 14 break;
2759 3 default:
2760 3 break;
2761 }
2762
2763
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (ret < 0)
2764 ✗ goto end;
2765
2766 // make sure that nothing but "st" and "stg" entries are left in the dict
2767 32 e = NULL;
2768 32 av_dict_set(&tmp, "map", NULL, 0);
2769 32 av_dict_set(&tmp, "type", NULL, 0);
2770
2/2
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 32 times.
64 while (e = av_dict_iterate(tmp, e)) {
2771
3/4
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
32 if (!strcmp(e->key, "st") || !strcmp(e->key, "stg"))
2772 32 continue;
2773
2774 ✗ av_log(mux, AV_LOG_FATAL, "Unknown group key %s.\n", e->key);
2775 ✗ ret = AVERROR(EINVAL);
2776 ✗ goto end;
2777 }
2778
2779 32 ret = 0;
2780 32 end:
2781 32 av_free(mapped_string);
2782 32 av_dict_free(&dict);
2783 32 av_dict_free(&tmp);
2784
2785 32 return ret;
2786 }
2787
2788 8931 static int of_add_groups(Muxer *mux, const OptionsContext *o)
2789 {
2790 /* process manually set groups */
2791
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 8931 times.
8963 for (int i = 0; i < o->stream_groups.nb_opt; i++) {
2792 const char *token;
2793 32 char *str, *ptr = NULL;
2794 32 int ret = 0;
2795
2796 32 str = av_strdup(o->stream_groups.opt[i].u.str);
2797
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (!str)
2798 ✗ return ret;
2799
2800 32 token = av_strtok(str, ",", &ptr);
2801
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 if (token) {
2802
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 9 times.
32 if (ptr)
2803 23 ptr += strspn(ptr, " \n\t\r");
2804 32 ret = of_parse_group_token(mux, token, ptr);
2805 }
2806
2807 32 av_free(str);
2808
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (ret < 0)
2809 ✗ return ret;
2810 }
2811
2812 8931 return 0;
2813 }
2814
2815 8931 static int of_add_programs(Muxer *mux, const OptionsContext *o)
2816 {
2817 8931 AVFormatContext *oc = mux->fc;
2818 /* process manually set programs */
2819
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8931 times.
8931 for (int i = 0; i < o->program.nb_opt; i++) {
2820 ✗ AVDictionary *dict = NULL;
2821 const AVDictionaryEntry *e;
2822 AVProgram *program;
2823 ✗ int ret, progid = i + 1;
2824
2825 ✗ ret = av_dict_parse_string(&dict, o->program.opt[i].u.str, "=", ":",
2826 AV_DICT_MULTIKEY);
2827 ✗ if (ret < 0) {
2828 ✗ av_log(mux, AV_LOG_ERROR, "Error parsing program specification %s\n",
2829 ✗ o->program.opt[i].u.str);
2830 ✗ return ret;
2831 }
2832
2833 ✗ e = av_dict_get(dict, "program_num", NULL, 0);
2834 ✗ if (e) {
2835 ✗ progid = strtol(e->value, NULL, 0);
2836 ✗ av_dict_set(&dict, e->key, NULL, 0);
2837 }
2838
2839 ✗ program = av_new_program(oc, progid);
2840 ✗ if (!program) {
2841 ✗ ret = AVERROR(ENOMEM);
2842 ✗ goto fail;
2843 }
2844
2845 ✗ e = av_dict_get(dict, "title", NULL, 0);
2846 ✗ if (e) {
2847 ✗ av_dict_set(&program->metadata, e->key, e->value, 0);
2848 ✗ av_dict_set(&dict, e->key, NULL, 0);
2849 }
2850
2851 ✗ e = NULL;
2852 ✗ while (e = av_dict_get(dict, "st", e, 0)) {
2853 ✗ int st_num = strtol(e->value, NULL, 0);
2854 ✗ av_program_add_stream_index(oc, progid, st_num);
2855 }
2856
2857 // make sure that nothing but "st" entries are left in the dict
2858 ✗ e = NULL;
2859 ✗ while (e = av_dict_iterate(dict, e)) {
2860 ✗ if (!strcmp(e->key, "st"))
2861 ✗ continue;
2862
2863 ✗ av_log(mux, AV_LOG_FATAL, "Unknown program key %s.\n", e->key);
2864 ✗ ret = AVERROR(EINVAL);
2865 ✗ goto fail;
2866 }
2867
2868 ✗ fail:
2869 ✗ av_dict_free(&dict);
2870 ✗ if (ret < 0)
2871 ✗ return ret;
2872 }
2873
2874 8931 return 0;
2875 }
2876
2877 /**
2878 * Parse a metadata specifier passed as 'arg' parameter.
2879 * @param arg metadata string to parse
2880 * @param type metadata type is written here -- g(lobal)/s(tream)/c(hapter)/p(rogram)
2881 * @param index for type c/p, chapter/program index is written here
2882 * @param stream_spec for type s, the stream specifier is written here
2883 */
2884 455 static int parse_meta_type(void *logctx, const char *arg,
2885 char *type, int *index, const char **stream_spec)
2886 {
2887
2/2
✓ Branch 0 taken 189 times.
✓ Branch 1 taken 266 times.
455 if (*arg) {
2888 189 *type = *arg;
2889
4/4
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 149 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 1 times.
189 switch (*arg) {
2890 27 case 'g':
2891 27 break;
2892 149 case 's':
2893
2/4
✓ Branch 0 taken 149 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 149 times.
149 if (*(++arg) && *arg != ':') {
2894 ✗ av_log(logctx, AV_LOG_FATAL, "Invalid metadata specifier %s.\n", arg);
2895 ✗ return AVERROR(EINVAL);
2896 }
2897
1/2
✓ Branch 0 taken 149 times.
✗ Branch 1 not taken.
149 *stream_spec = *arg == ':' ? arg + 1 : "";
2898 149 break;
2899 12 case 'c':
2900 case 'p':
2901
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1 times.
12 if (*(++arg) == ':')
2902 11 *index = strtol(++arg, NULL, 0);
2903 12 break;
2904 1 default:
2905 1 av_log(logctx, AV_LOG_FATAL, "Invalid metadata type %c.\n", *arg);
2906 1 return AVERROR(EINVAL);
2907 }
2908 } else
2909 266 *type = 'g';
2910
2911 454 return 0;
2912 }
2913
2914 8931 static int of_add_metadata(OutputFile *of, AVFormatContext *oc,
2915 const OptionsContext *o)
2916 {
2917
2/2
✓ Branch 0 taken 261 times.
✓ Branch 1 taken 8931 times.
9192 for (int i = 0; i < o->metadata.nb_opt; i++) {
2918 AVDictionary **m;
2919 char type, *val;
2920 const char *stream_spec;
2921 261 int index = 0, ret = 0;
2922
2923 261 val = strchr(o->metadata.opt[i].u.str, '=');
2924
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 261 times.
261 if (!val) {
2925 ✗ av_log(of, AV_LOG_FATAL, "No '=' character in metadata string %s.\n",
2926 ✗ o->metadata.opt[i].u.str);
2927 ✗ return AVERROR(EINVAL);
2928 }
2929 261 *val++ = 0;
2930
2931 261 ret = parse_meta_type(of, o->metadata.opt[i].specifier, &type, &index, &stream_spec);
2932
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 261 times.
261 if (ret < 0)
2933 ✗ return ret;
2934
2935
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 216 times.
261 if (type == 's') {
2936
2/2
✓ Branch 0 taken 223 times.
✓ Branch 1 taken 45 times.
268 for (int j = 0; j < oc->nb_streams; j++) {
2937
2/2
✓ Branch 1 taken 44 times.
✓ Branch 2 taken 179 times.
223 if ((ret = check_stream_specifier(oc, oc->streams[j], stream_spec)) > 0) {
2938
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 1 times.
44 av_dict_set(&oc->streams[j]->metadata, o->metadata.opt[i].u.str, *val ? val : NULL, 0);
2939
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 179 times.
179 } else if (ret < 0)
2940 ✗ return ret;
2941 }
2942 } else {
2943
2/4
✓ Branch 0 taken 211 times.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
216 switch (type) {
2944 211 case 'g':
2945 211 m = &oc->metadata;
2946 211 break;
2947 5 case 'c':
2948
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (index < 0 || index >= oc->nb_chapters) {
2949 ✗ av_log(of, AV_LOG_FATAL, "Invalid chapter index %d in metadata specifier.\n", index);
2950 ✗ return AVERROR(EINVAL);
2951 }
2952 5 m = &oc->chapters[index]->metadata;
2953 5 break;
2954 ✗ case 'p':
2955 ✗ if (index < 0 || index >= oc->nb_programs) {
2956 ✗ av_log(of, AV_LOG_FATAL, "Invalid program index %d in metadata specifier.\n", index);
2957 ✗ return AVERROR(EINVAL);
2958 }
2959 ✗ m = &oc->programs[index]->metadata;
2960 ✗ break;
2961 ✗ default:
2962 ✗ av_log(of, AV_LOG_FATAL, "Invalid metadata specifier %s.\n", o->metadata.opt[i].specifier);
2963 ✗ return AVERROR(EINVAL);
2964 }
2965
2/2
✓ Branch 0 taken 215 times.
✓ Branch 1 taken 1 times.
216 av_dict_set(m, o->metadata.opt[i].u.str, *val ? val : NULL, 0);
2966 }
2967 }
2968
2969 8931 return 0;
2970 }
2971
2972 39 static int copy_chapters(InputFile *ifile, OutputFile *ofile, AVFormatContext *os,
2973 int copy_metadata)
2974 {
2975 39 AVFormatContext *is = ifile->ctx;
2976 AVChapter **tmp;
2977
2978 39 tmp = av_realloc_f(os->chapters, is->nb_chapters + os->nb_chapters, sizeof(*os->chapters));
2979
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (!tmp)
2980 ✗ return AVERROR(ENOMEM);
2981 39 os->chapters = tmp;
2982
2983
2/2
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 36 times.
113 for (int i = 0; i < is->nb_chapters; i++) {
2984 77 AVChapter *in_ch = is->chapters[i], *out_ch;
2985
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 int64_t start_time = (ofile->start_time == AV_NOPTS_VALUE) ? 0 : ofile->start_time;
2986 77 int64_t ts_off = av_rescale_q(start_time - ifile->ts_offset,
2987 77 AV_TIME_BASE_Q, in_ch->time_base);
2988
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 52 times.
77 int64_t rt = (ofile->recording_time == INT64_MAX) ? INT64_MAX :
2989 25 av_rescale_q(ofile->recording_time, AV_TIME_BASE_Q, in_ch->time_base);
2990
2991
2992
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 if (in_ch->end < ts_off)
2993 ✗ continue;
2994
4/4
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 52 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 22 times.
77 if (rt != INT64_MAX && in_ch->start > rt + ts_off)
2995 3 break;
2996
2997 74 out_ch = av_mallocz(sizeof(AVChapter));
2998
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 74 times.
74 if (!out_ch)
2999 ✗ return AVERROR(ENOMEM);
3000
3001 74 out_ch->id = in_ch->id;
3002 74 out_ch->time_base = in_ch->time_base;
3003 74 out_ch->start = FFMAX(0, in_ch->start - ts_off);
3004 74 out_ch->end = FFMIN(rt, in_ch->end - ts_off);
3005
3006
1/2
✓ Branch 0 taken 74 times.
✗ Branch 1 not taken.
74 if (copy_metadata)
3007 74 av_dict_copy(&out_ch->metadata, in_ch->metadata, 0);
3008
3009 74 os->chapters[os->nb_chapters++] = out_ch;
3010 }
3011 39 return 0;
3012 }
3013
3014 28 static int copy_metadata(Muxer *mux, AVFormatContext *ic,
3015 const char *outspec, const char *inspec,
3016 int *metadata_global_manual, int *metadata_streams_manual,
3017 int *metadata_chapters_manual)
3018 {
3019 28 AVFormatContext *oc = mux->fc;
3020 28 AVDictionary **meta_in = NULL;
3021 28 AVDictionary **meta_out = NULL;
3022 28 int i, ret = 0;
3023 char type_in, type_out;
3024 28 const char *istream_spec = NULL, *ostream_spec = NULL;
3025 28 int idx_in = 0, idx_out = 0;
3026
3027 28 ret = parse_meta_type(mux, inspec, &type_in, &idx_in, &istream_spec);
3028
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 if (ret >= 0)
3029 28 ret = parse_meta_type(mux, outspec, &type_out, &idx_out, &ostream_spec);
3030
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (ret < 0)
3031 ✗ return ret;
3032
3033
4/8
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
28 if (type_in == 'g' || type_out == 'g' || (!*outspec && !ic))
3034 25 *metadata_global_manual = 1;
3035
8/8
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 21 times.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 18 times.
✓ Branch 7 taken 3 times.
28 if (type_in == 's' || type_out == 's' || (!*outspec && !ic))
3036 22 *metadata_streams_manual = 1;
3037
6/8
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 21 times.
✓ Branch 5 taken 7 times.
✓ Branch 6 taken 18 times.
✓ Branch 7 taken 3 times.
28 if (type_in == 'c' || type_out == 'c' || (!*outspec && !ic))
3038 18 *metadata_chapters_manual = 1;
3039
3040 /* ic is NULL when just disabling automatic mappings */
3041
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 8 times.
28 if (!ic)
3042 20 return 0;
3043
3044 #define METADATA_CHECK_INDEX(index, nb_elems, desc)\
3045 if ((index) < 0 || (index) >= (nb_elems)) {\
3046 av_log(mux, AV_LOG_FATAL, "Invalid %s index %d while processing metadata maps.\n",\
3047 (desc), (index));\
3048 return AVERROR(EINVAL);\
3049 }
3050
3051 #define SET_DICT(type, meta, context, index)\
3052 switch (type) {\
3053 case 'g':\
3054 meta = &context->metadata;\
3055 break;\
3056 case 'c':\
3057 METADATA_CHECK_INDEX(index, context->nb_chapters, "chapter")\
3058 meta = &context->chapters[index]->metadata;\
3059 break;\
3060 case 'p':\
3061 METADATA_CHECK_INDEX(index, context->nb_programs, "program")\
3062 meta = &context->programs[index]->metadata;\
3063 break;\
3064 case 's':\
3065 break; /* handled separately below */ \
3066 default: av_assert0(0);\
3067 }\
3068
3069
2/13
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
8 SET_DICT(type_in, meta_in, ic, idx_in);
3070
2/13
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
8 SET_DICT(type_out, meta_out, oc, idx_out);
3071
3072 /* for input streams choose first matching stream */
3073
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
8 if (type_in == 's') {
3074
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 for (i = 0; i < ic->nb_streams; i++) {
3075
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 1 times.
4 if ((ret = check_stream_specifier(ic, ic->streams[i], istream_spec)) > 0) {
3076 3 meta_in = &ic->streams[i]->metadata;
3077 3 break;
3078
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 } else if (ret < 0)
3079 ✗ return ret;
3080 }
3081
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!meta_in) {
3082 ✗ av_log(mux, AV_LOG_FATAL, "Stream specifier %s does not match any streams.\n", istream_spec);
3083 ✗ return AVERROR(EINVAL);
3084 }
3085 }
3086
3087
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 if (type_out == 's') {
3088
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 4 times.
13 for (i = 0; i < oc->nb_streams; i++) {
3089
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 5 times.
9 if ((ret = check_stream_specifier(oc, oc->streams[i], ostream_spec)) > 0) {
3090 4 meta_out = &oc->streams[i]->metadata;
3091 4 av_dict_copy(meta_out, *meta_in, AV_DICT_DONT_OVERWRITE);
3092
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 } else if (ret < 0)
3093 ✗ return ret;
3094 }
3095 } else
3096 4 av_dict_copy(meta_out, *meta_in, AV_DICT_DONT_OVERWRITE);
3097
3098 8 return 0;
3099 }
3100
3101 #define REENC_MASK(type) (1u << (type))
3102 #define REENC_AUDIO_ONLY REENC_MASK(AVMEDIA_TYPE_AUDIO)
3103 #define REENC_VIDEO_ONLY REENC_MASK(AVMEDIA_TYPE_VIDEO)
3104 #define REENC_ANY (REENC_AUDIO_ONLY | REENC_VIDEO_ONLY)
3105
3106 static const struct {
3107 const char *key;
3108 int flags;
3109 unsigned reenc_mask; /* 0 = always delete; non-zero = bit-mask of
3110 * REENC_* values whose re-encoding triggers
3111 * deletion of this key */
3112 } reenc_delete_keys[] = {
3113 // Note: "encoder" is intentionally absent — set_encoder_id() stamps it
3114 // after copy_meta() runs, so it always reflects the current encoder.
3115
3116 // iTunes gapless playback: encoder-specific sample counts and padding;
3117 // gapless_playback is the M4A/MOV equivalent of iTunPGAP
3118 { "iTunPGAP", 0, REENC_AUDIO_ONLY },
3119 { "comment-iTunPGAP-eng", 0, REENC_AUDIO_ONLY },
3120 { "iTunSMPB", 0, REENC_AUDIO_ONLY },
3121 { "comment-iTunSMPB-eng", 0, REENC_AUDIO_ONLY },
3122 { "gapless_playback", 0, REENC_AUDIO_ONLY },
3123 // iTunes Sound Check: peak amplitude computed from the original waveform
3124 { "iTunNORM", 0, REENC_AUDIO_ONLY },
3125 { "comment-iTunNORM-eng", 0, REENC_AUDIO_ONLY },
3126 // encoding provenance: describe the original encoder, not the new one
3127 { "encoded_by", 0, REENC_ANY },
3128 { "encoding_tool", 0, REENC_ANY },
3129 // MOV/MP4 stream: vendor 4CC identifies the original encoder
3130 { "vendor_id", 0, REENC_ANY },
3131 // Matroska stream stats written by mkvmerge; all are invalidated by re-encoding
3132 { "BPS", AV_DICT_IGNORE_SUFFIX, REENC_ANY },
3133 { "DURATION", AV_DICT_IGNORE_SUFFIX, REENC_ANY },
3134 { "NUMBER_OF_BYTES", AV_DICT_IGNORE_SUFFIX, REENC_ANY },
3135 { "NUMBER_OF_FRAMES", AV_DICT_IGNORE_SUFFIX, REENC_ANY },
3136 { "_STATISTICS_TAGS", AV_DICT_IGNORE_SUFFIX, REENC_ANY },
3137 { "_STATISTICS_WRITING_APP", AV_DICT_IGNORE_SUFFIX, REENC_ANY },
3138 { "_STATISTICS_WRITING_DATE_UTC", AV_DICT_IGNORE_SUFFIX, REENC_ANY },
3139
3140 // MOV/MP4: source container brand written by the demuxer; muxer ignores
3141 // these keys and writes its own ftyp, so they always describe the source file
3142 { "major_brand", 0, 0 },
3143 { "minor_version", 0, 0 },
3144 { "compatible_brands", 0, 0 },
3145 { NULL }
3146 };
3147
3148 127 static int meta_spec_matches(void *log_ctx, AVFormatContext *oc, AVStream *st,
3149 const char *spec)
3150 {
3151 char type;
3152 127 int index = 0;
3153 127 const char *stream_spec = NULL;
3154
3155
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 127 times.
127 if (parse_meta_type(log_ctx, spec, &type, &index, &stream_spec) < 0)
3156 ✗ return 0;
3157
3158
2/2
✓ Branch 0 taken 101 times.
✓ Branch 1 taken 26 times.
127 if (*spec) {
3159
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 97 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
101 if (type == 'g' && st)
3160 ✗ return 0;
3161
2/2
✓ Branch 0 taken 90 times.
✓ Branch 1 taken 11 times.
101 if (type == 's') {
3162 int ret;
3163
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 42 times.
90 if (!st)
3164 48 return 0;
3165 42 ret = check_stream_specifier(oc, st, stream_spec);
3166
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 return ret < 0 ? ret : ret > 0;
3167 }
3168
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
11 if (type == 'c' || type == 'p')
3169 7 return 0;
3170 }
3171 30 return 1;
3172 }
3173
3174 1848 static int reenc_delete_metadata_key(const OptionsContext *o, void *log_ctx,
3175 AVFormatContext *oc, AVStream *st,
3176 const char *family, const char *key, int flags)
3177 {
3178
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 1843 times.
1897 for (int i = 0; i < o->keep_metadata.nb_opt; i++) {
3179 54 int ret = meta_spec_matches(log_ctx, oc, st, o->keep_metadata.opt[i].specifier);
3180
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 if (ret < 0)
3181 ✗ return ret;
3182
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 36 times.
54 if (!ret)
3183 18 continue;
3184 36 const char *keep = o->keep_metadata.opt[i].u.str;
3185
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 8 times.
36 if (flags & AV_DICT_IGNORE_SUFFIX) {
3186 /* accept the unsuffixed family name (e.g. NUMBER_OF_BYTES keeps
3187 * NUMBER_OF_BYTES-eng) or the exact matched key; an arbitrary
3188 * prefix like NUMBER does not match NUMBER_OF_BYTES-eng */
3189
4/4
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 25 times.
28 if (!strcmp(keep, family) || !strcmp(keep, key))
3190 3 return 0;
3191 } else {
3192
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
8 if (!strcmp(key, keep))
3193 2 return 0;
3194 }
3195 }
3196
2/2
✓ Branch 0 taken 74 times.
✓ Branch 1 taken 1842 times.
1916 for (int i = 0; i < o->metadata.nb_opt; i++) {
3197 int ret;
3198 /* plain -metadata (empty specifier) applies to global metadata only,
3199 * matching of_add_metadata(); don't let it suppress stream-level pruning */
3200
4/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 58 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 15 times.
74 if (!*o->metadata.opt[i].specifier && st)
3201 1 continue;
3202 73 ret = meta_spec_matches(log_ctx, oc, st, o->metadata.opt[i].specifier);
3203
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
73 if (ret < 0)
3204 ✗ return ret;
3205
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 15 times.
73 if (!ret)
3206 58 continue;
3207 15 size_t klen = strcspn(o->metadata.opt[i].u.str, "=");
3208
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
15 if (!strncmp(key, o->metadata.opt[i].u.str, klen) && key[klen] == '\0')
3209 1 return 0;
3210 }
3211 1842 return 1;
3212 }
3213
3214 18522 static int reenc_delete_stale_metadata(const OptionsContext *o, void *log_ctx,
3215 AVFormatContext *oc, AVStream *st,
3216 AVDictionary **dict, const char *kind,
3217 unsigned reenc_mask)
3218 {
3219
2/2
✓ Branch 0 taken 370440 times.
✓ Branch 1 taken 18522 times.
388962 for (int i = 0; reenc_delete_keys[i].key; i++) {
3220 370440 const char *key = reenc_delete_keys[i].key;
3221 370440 int flags = reenc_delete_keys[i].flags;
3222 const AVDictionaryEntry *e;
3223 int ret;
3224
3225
4/4
✓ Branch 0 taken 314874 times.
✓ Branch 1 taken 55566 times.
✓ Branch 2 taken 126555 times.
✓ Branch 3 taken 188319 times.
370440 if (reenc_delete_keys[i].reenc_mask && !(reenc_delete_keys[i].reenc_mask & reenc_mask))
3226 126555 continue;
3227
3228 243885 e = NULL;
3229
2/2
✓ Branch 1 taken 1848 times.
✓ Branch 2 taken 243885 times.
245733 while ((e = av_dict_get(*dict, key, e, flags | AV_DICT_MATCH_CASE))) {
3230 1848 ret = reenc_delete_metadata_key(o, log_ctx, oc, st, key, e->key, flags);
3231
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1848 times.
1848 if (ret < 0)
3232 ✗ return ret;
3233
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1842 times.
1848 if (!ret)
3234 6 continue;
3235
2/2
✓ Branch 0 taken 397 times.
✓ Branch 1 taken 1445 times.
1842 if (reenc_mask & reenc_delete_keys[i].reenc_mask)
3236 397 av_log(log_ctx, AV_LOG_WARNING,
3237 "Discarding %s metadata '%s' because %s stream is being "
3238 "re-encoded. Use '-keep_metadata %s' to keep it.\n",
3239 397 kind, e->key,
3240
2/2
✓ Branch 0 taken 331 times.
✓ Branch 1 taken 66 times.
397 !strcmp(kind, "stream") ? "the" : "a", e->key);
3241 1842 av_dict_set(dict, e->key, NULL, 0);
3242 1842 e = NULL;
3243 }
3244 }
3245 18522 return 0;
3246 }
3247
3248 8933 static int copy_meta(Muxer *mux, const OptionsContext *o)
3249 {
3250 8933 OutputFile *of = &mux->of;
3251 8933 AVFormatContext *oc = mux->fc;
3252 8933 int chapters_input_file = o->chapters_input_file;
3253 8933 int metadata_global_manual = 0;
3254 8933 int metadata_streams_manual = 0;
3255 8933 int metadata_chapters_manual = 0;
3256 int ret;
3257
3258 /* copy metadata */
3259
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 8933 times.
8961 for (int i = 0; i < o->metadata_map.nb_opt; i++) {
3260 char *p;
3261 28 int in_file_index = strtol(o->metadata_map.opt[i].u.str, &p, 0);
3262
3263
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (in_file_index >= nb_input_files) {
3264 ✗ av_log(mux, AV_LOG_FATAL, "Invalid input file index %d while "
3265 "processing metadata maps\n", in_file_index);
3266 ✗ return AVERROR(EINVAL);
3267 }
3268 51 ret = copy_metadata(mux,
3269 8 in_file_index >= 0 ? input_files[in_file_index]->ctx : NULL,
3270
4/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 23 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 20 times.
51 o->metadata_map.opt[i].specifier, *p ? p + 1 : p,
3271 &metadata_global_manual, &metadata_streams_manual,
3272 &metadata_chapters_manual);
3273
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (ret < 0)
3274 ✗ return ret;
3275 }
3276
3277 /* copy chapters */
3278
1/2
✓ Branch 0 taken 8933 times.
✗ Branch 1 not taken.
8933 if (chapters_input_file >= nb_input_files) {
3279
1/2
✓ Branch 0 taken 8933 times.
✗ Branch 1 not taken.
8933 if (chapters_input_file == INT_MAX) {
3280 /* copy chapters from the first input file that has them*/
3281 8933 chapters_input_file = -1;
3282
2/2
✓ Branch 0 taken 7800 times.
✓ Branch 1 taken 8894 times.
16694 for (int i = 0; i < nb_input_files; i++)
3283
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 7761 times.
7800 if (input_files[i]->ctx->nb_chapters) {
3284 39 chapters_input_file = i;
3285 39 break;
3286 }
3287 } else {
3288 ✗ av_log(mux, AV_LOG_FATAL, "Invalid input file index %d in chapter mapping.\n",
3289 chapters_input_file);
3290 ✗ return AVERROR(EINVAL);
3291 }
3292 }
3293
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 8894 times.
8933 if (chapters_input_file >= 0)
3294 39 copy_chapters(input_files[chapters_input_file], of, oc,
3295 !metadata_chapters_manual);
3296
3297 /* copy global metadata by default */
3298
4/4
✓ Branch 0 taken 8909 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 7674 times.
✓ Branch 3 taken 1235 times.
8933 if (!metadata_global_manual && nb_input_files){
3299 7674 av_dict_copy(&oc->metadata, input_files[0]->ctx->metadata,
3300 AV_DICT_DONT_OVERWRITE);
3301
2/2
✓ Branch 0 taken 236 times.
✓ Branch 1 taken 7438 times.
7674 if (of->recording_time != INT64_MAX)
3302 236 av_dict_set(&oc->metadata, "duration", NULL, 0);
3303 7674 av_dict_set(&oc->metadata, "creation_time", NULL, 0);
3304 7674 av_dict_set(&oc->metadata, "company_name", NULL, 0);
3305 7674 av_dict_set(&oc->metadata, "product_name", NULL, 0);
3306 7674 av_dict_set(&oc->metadata, "product_version", NULL, 0);
3307
3308 }
3309
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 8931 times.
8942 for (int i = 0; i < o->keep_metadata.nb_opt; i++) {
3310 char type;
3311 11 int index = 0;
3312 11 const char *stream_spec = NULL;
3313 11 const char *spec = o->keep_metadata.opt[i].specifier;
3314 11 ret = parse_meta_type(mux, spec, &type, &index, &stream_spec);
3315
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10 times.
11 if (ret < 0)
3316 2 return ret;
3317
2/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
10 if (type == 'c' || type == 'p') {
3318 ✗ av_log(mux, AV_LOG_WARNING,
3319 "-keep_metadata:%s: chapter and program metadata filtering "
3320 "is not supported and will be ignored.\n", spec);
3321
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 3 times.
10 } else if (type == 's') {
3322
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 6 times.
13 for (int j = 0; j < oc->nb_streams; j++) {
3323 7 ret = check_stream_specifier(oc, oc->streams[j], stream_spec);
3324
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
7 if (ret < 0)
3325 1 return ret;
3326 }
3327 }
3328 }
3329
3330 /* reenc_mask keys only apply when an audio/video stream is re-encoded;
3331 * subtitle/attachment re-encodes do not affect format-level tags.
3332 * Runs unconditionally so -map_metadata does not bypass the pruning. */
3333 {
3334 8931 unsigned reenc_mask = 0;
3335
2/2
✓ Branch 0 taken 9591 times.
✓ Branch 1 taken 8931 times.
18522 for (int i = 0; i < of->nb_streams; i++) {
3336 9591 OutputStream *ost = of->streams[i];
3337
2/2
✓ Branch 0 taken 8610 times.
✓ Branch 1 taken 981 times.
9591 if (ost->enc)
3338 8610 reenc_mask |= REENC_MASK(ost->st->codecpar->codec_type);
3339 }
3340 8931 ret = reenc_delete_stale_metadata(o, mux, oc, NULL, &oc->metadata, "format", reenc_mask);
3341
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8931 times.
8931 if (ret < 0)
3342 ✗ return ret;
3343 }
3344
2/2
✓ Branch 0 taken 8910 times.
✓ Branch 1 taken 21 times.
8931 if (!metadata_streams_manual)
3345
2/2
✓ Branch 0 taken 9567 times.
✓ Branch 1 taken 8910 times.
18477 for (int i = 0; i < of->nb_streams; i++) {
3346 9567 OutputStream *ost = of->streams[i];
3347
3348
2/2
✓ Branch 0 taken 1546 times.
✓ Branch 1 taken 8021 times.
9567 if (!ost->ist) /* this is true e.g. for attached files */
3349 1546 continue;
3350 8021 av_dict_copy(&ost->st->metadata, ost->ist->st->metadata, AV_DICT_DONT_OVERWRITE);
3351 }
3352 /* runs unconditionally so -map_metadata does not bypass the pruning;
3353 * applies to all output streams, including filter outputs without ost->ist */
3354
2/2
✓ Branch 0 taken 9591 times.
✓ Branch 1 taken 8931 times.
18522 for (int i = 0; i < of->nb_streams; i++) {
3355 9591 OutputStream *ost = of->streams[i];
3356
3357 9591 ret = reenc_delete_stale_metadata(o, ost, oc, ost->st, &ost->st->metadata, "stream",
3358
2/2
✓ Branch 0 taken 8610 times.
✓ Branch 1 taken 981 times.
9591 ost->enc ? REENC_MASK(ost->st->codecpar->codec_type) : 0);
3359
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9591 times.
9591 if (ret < 0)
3360 ✗ return ret;
3361 }
3362
3363 8931 return 0;
3364 }
3365
3366 8931 static int set_dispositions(Muxer *mux, const OptionsContext *o)
3367 {
3368 8931 OutputFile *of = &mux->of;
3369 8931 AVFormatContext *ctx = mux->fc;
3370
3371 // indexed by type+1, because AVMEDIA_TYPE_UNKNOWN=-1
3372 8931 int nb_streams[AVMEDIA_TYPE_NB + 1] = { 0 };
3373 8931 int have_default[AVMEDIA_TYPE_NB + 1] = { 0 };
3374 8931 int have_manual = 0;
3375 8931 int ret = 0;
3376
3377 const char **dispositions;
3378
3379 8931 dispositions = av_calloc(ctx->nb_streams, sizeof(*dispositions));
3380
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8931 times.
8931 if (!dispositions)
3381 ✗ return AVERROR(ENOMEM);
3382
3383 // reset any apic flag set for option stream-spec matching in ost_add
3384
2/2
✓ Branch 0 taken 9591 times.
✓ Branch 1 taken 8931 times.
18522 for (int i = 0; i < ctx->nb_streams; i++) {
3385 9591 of->streams[i]->st->disposition = 0;
3386 }
3387
3388 // first, copy the input dispositions
3389
2/2
✓ Branch 0 taken 9591 times.
✓ Branch 1 taken 8931 times.
18522 for (int i = 0; i < ctx->nb_streams; i++) {
3390 9591 OutputStream *ost = of->streams[i];
3391
3392 9591 nb_streams[ost->type + 1]++;
3393
3394 9591 opt_match_per_stream_str(ost, &o->disposition, ctx, ost->st, &dispositions[i]);
3395
3396 9591 have_manual |= !!dispositions[i];
3397
3398
2/2
✓ Branch 0 taken 8044 times.
✓ Branch 1 taken 1547 times.
9591 if (ost->ist) {
3399 8044 ost->st->disposition = ost->ist->st->disposition;
3400
3401
2/2
✓ Branch 0 taken 930 times.
✓ Branch 1 taken 7114 times.
8044 if (ost->st->disposition & AV_DISPOSITION_DEFAULT)
3402 930 have_default[ost->type + 1] = 1;
3403 }
3404 }
3405
3406
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 8922 times.
8931 if (have_manual) {
3407 // process manually set dispositions - they override the above copy
3408
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 9 times.
34 for (int i = 0; i < ctx->nb_streams; i++) {
3409 25 OutputStream *ost = of->streams[i];
3410 25 const char *disp = dispositions[i];
3411
3412
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 17 times.
25 if (!disp)
3413 8 continue;
3414
3415 17 ret = av_opt_set(ost->st, "disposition", disp, 0);
3416
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if (ret < 0)
3417 ✗ goto finish;
3418 }
3419 } else {
3420 // For each media type with more than one stream, find a suitable stream to
3421 // mark as default, unless one is already marked default.
3422 // "Suitable" means the first of that type, skipping attached pictures.
3423
2/2
✓ Branch 0 taken 9566 times.
✓ Branch 1 taken 8922 times.
18488 for (int i = 0; i < ctx->nb_streams; i++) {
3424 9566 OutputStream *ost = of->streams[i];
3425 9566 enum AVMediaType type = ost->type;
3426
3427
4/4
✓ Branch 0 taken 566 times.
✓ Branch 1 taken 9000 times.
✓ Branch 2 taken 89 times.
✓ Branch 3 taken 477 times.
9566 if (nb_streams[type + 1] < 2 || have_default[type + 1] ||
3428
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 57 times.
89 ost->st->disposition & AV_DISPOSITION_ATTACHED_PIC)
3429 9509 continue;
3430
3431 57 ost->st->disposition |= AV_DISPOSITION_DEFAULT;
3432 57 have_default[type + 1] = 1;
3433 }
3434 }
3435
3436 8922 finish:
3437 8931 av_freep(&dispositions);
3438
3439 8931 return ret;
3440 }
3441
3442 static const char *const forced_keyframes_const_names[] = {
3443 "n",
3444 "n_forced",
3445 "prev_forced_n",
3446 "prev_forced_t",
3447 "t",
3448 NULL
3449 };
3450
3451 1 static int compare_int64(const void *a, const void *b)
3452 {
3453 1 return FFDIFFSIGN(*(const int64_t *)a, *(const int64_t *)b);
3454 }
3455
3456 1 static int parse_forced_key_frames(void *log, KeyframeForceCtx *kf,
3457 const Muxer *mux, const char *spec)
3458 {
3459 1 int n = 1, i, ret, size, index = 0;
3460 int64_t t, *pts;
3461
3462
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 1 times.
14 for (const char *p = spec; *p; p++)
3463
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12 times.
13 if (*p == ',')
3464 1 n++;
3465 1 size = n;
3466
3467 1 char *spec_dup = av_strdup(spec);
3468 1 pts = av_malloc_array(size, sizeof(*pts));
3469
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (!spec_dup || !pts) {
3470 ✗ ret = AVERROR(ENOMEM);
3471 ✗ goto fail;
3472 }
3473
3474 1 char *p = spec_dup;
3475
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 for (i = 0; i < n; i++) {
3476 2 char *next = strchr(p, ',');
3477
3478
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (next)
3479 1 *next++ = 0;
3480
3481
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (strstr(p, "chapters") == p) {
3482 ✗ AVChapter * const *ch = mux->fc->chapters;
3483 ✗ unsigned int nb_ch = mux->fc->nb_chapters;
3484 int j;
3485
3486 ✗ if (nb_ch > INT_MAX - size) {
3487 ✗ ret = AVERROR(ERANGE);
3488 ✗ goto fail;
3489 }
3490 ✗ size += nb_ch - 1;
3491 ✗ pts = av_realloc_f(pts, size, sizeof(*pts));
3492 ✗ if (!pts) {
3493 ✗ ret = AVERROR(ENOMEM);
3494 ✗ goto fail;
3495 }
3496
3497 ✗ if (p[8]) {
3498 ✗ ret = av_parse_time(&t, p + 8, 1);
3499 ✗ if (ret < 0) {
3500 ✗ av_log(log, AV_LOG_ERROR,
3501 "Invalid chapter time offset: %s\n", p + 8);
3502 ✗ goto fail;
3503 }
3504 } else
3505 ✗ t = 0;
3506
3507 ✗ for (j = 0; j < nb_ch; j++) {
3508 ✗ const AVChapter *c = ch[j];
3509 av_assert1(index < size);
3510 ✗ pts[index++] = av_rescale_q(c->start, c->time_base,
3511 ✗ AV_TIME_BASE_Q) + t;
3512 }
3513
3514 } else {
3515 av_assert1(index < size);
3516 2 ret = av_parse_time(&t, p, 1);
3517
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0) {
3518 ✗ av_log(log, AV_LOG_ERROR, "Invalid keyframe time: %s\n", p);
3519 ✗ goto fail;
3520 }
3521
3522 2 pts[index++] = t;
3523 }
3524
3525 2 p = next;
3526 }
3527
3528
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 av_assert0(index == size);
3529 1 qsort(pts, size, sizeof(*pts), compare_int64);
3530 1 kf->nb_pts = size;
3531 1 kf->pts = pts;
3532
3533 1 av_freep(&spec_dup);
3534
3535 1 return 0;
3536 ✗ fail:
3537 ✗ av_freep(&spec_dup);
3538 ✗ av_freep(&pts);
3539 ✗ return ret;
3540 }
3541
3542 8931 static int process_forced_keyframes(Muxer *mux, const OptionsContext *o)
3543 {
3544
2/2
✓ Branch 0 taken 9591 times.
✓ Branch 1 taken 8931 times.
18522 for (int i = 0; i < mux->of.nb_streams; i++) {
3545 9591 OutputStream *ost = mux->of.streams[i];
3546 9591 const char *forced_keyframes = NULL;
3547
3548 9591 opt_match_per_stream_str(ost, &o->forced_key_frames,
3549 mux->fc, ost->st, &forced_keyframes);
3550
3551
2/2
✓ Branch 0 taken 7459 times.
✓ Branch 1 taken 2132 times.
9591 if (!(ost->type == AVMEDIA_TYPE_VIDEO &&
3552
4/4
✓ Branch 0 taken 6986 times.
✓ Branch 1 taken 473 times.
✓ Branch 2 taken 6981 times.
✓ Branch 3 taken 5 times.
7459 ost->enc && forced_keyframes))
3553 9586 continue;
3554
3555
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!strncmp(forced_keyframes, "expr:", 5)) {
3556 ✗ int ret = av_expr_parse(&ost->kf.pexpr, forced_keyframes + 5,
3557 forced_keyframes_const_names, NULL, NULL, NULL, NULL, 0, NULL);
3558 ✗ if (ret < 0) {
3559 ✗ av_log(ost, AV_LOG_ERROR,
3560 "Invalid force_key_frames expression '%s'\n", forced_keyframes + 5);
3561 ✗ return ret;
3562 }
3563 ✗ ost->kf.expr_const_values[FKF_N] = 0;
3564 ✗ ost->kf.expr_const_values[FKF_N_FORCED] = 0;
3565 ✗ ost->kf.expr_const_values[FKF_PREV_FORCED_N] = NAN;
3566 ✗ ost->kf.expr_const_values[FKF_PREV_FORCED_T] = NAN;
3567
3568 // Don't parse the 'forced_keyframes' in case of 'keep-source-keyframes',
3569 // parse it only for static kf timings
3570
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
5 } else if (!strcmp(forced_keyframes, "source")) {
3571 3 ost->kf.type = KF_FORCE_SOURCE;
3572
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 } else if (!strcmp(forced_keyframes, "scd_metadata")) {
3573 1 ost->kf.type = KF_FORCE_SCD_METADATA;
3574 } else {
3575 1 int ret = parse_forced_key_frames(ost, &ost->kf, mux, forced_keyframes);
3576
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
3577 ✗ return ret;
3578 }
3579 }
3580
3581 8931 return 0;
3582 }
3583
3584 9469 static const char *output_file_item_name(void *obj)
3585 {
3586 9469 const Muxer *mux = obj;
3587
3588 9469 return mux->log_name;
3589 }
3590
3591 static const AVClass output_file_class = {
3592 .class_name = "OutputFile",
3593 .version = LIBAVUTIL_VERSION_INT,
3594 .item_name = output_file_item_name,
3595 .category = AV_CLASS_CATEGORY_MUXER,
3596 };
3597
3598 8936 static Muxer *mux_alloc(void)
3599 {
3600 8936 Muxer *mux = allocate_array_elem(&output_files, sizeof(*mux), &nb_output_files);
3601
3602
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8936 times.
8936 if (!mux)
3603 ✗ return NULL;
3604
3605 8936 mux->of.class = &output_file_class;
3606 8936 mux->of.index = nb_output_files - 1;
3607
3608 8936 snprintf(mux->log_name, sizeof(mux->log_name), "out#%d", mux->of.index);
3609
3610 8936 return mux;
3611 }
3612
3613 8936 int of_open(const OptionsContext *o, const char *filename, Scheduler *sch)
3614 {
3615 Muxer *mux;
3616 AVFormatContext *oc;
3617 int err;
3618 OutputFile *of;
3619
3620 8936 int64_t recording_time = o->recording_time;
3621 8936 int64_t stop_time = o->stop_time;
3622
3623 8936 mux = mux_alloc();
3624
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8936 times.
8936 if (!mux)
3625 ✗ return AVERROR(ENOMEM);
3626
3627 8936 of = &mux->of;
3628
3629
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8936 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8936 if (stop_time != INT64_MAX && recording_time != INT64_MAX) {
3630 ✗ stop_time = INT64_MAX;
3631 ✗ av_log(mux, AV_LOG_WARNING, "-t and -to cannot be used together; using -t.\n");
3632 }
3633
3634
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8936 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8936 if (stop_time != INT64_MAX && recording_time == INT64_MAX) {
3635 ✗ int64_t start_time = o->start_time == AV_NOPTS_VALUE ? 0 : o->start_time;
3636 ✗ if (stop_time <= start_time) {
3637 ✗ av_log(mux, AV_LOG_ERROR, "-to value smaller than -ss; aborting.\n");
3638 ✗ return AVERROR(EINVAL);
3639 } else {
3640 ✗ recording_time = stop_time - start_time;
3641 }
3642 }
3643
3644
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8935 times.
8936 if (recording_time < 0) {
3645 1 av_log(mux, AV_LOG_ERROR, "-t value must be non-negative; aborting.\n");
3646 1 return AVERROR(EINVAL);
3647 }
3648
3649 8935 of->recording_time = recording_time;
3650 8935 of->start_time = o->start_time;
3651
3652 8935 mux->limit_filesize = o->limit_filesize;
3653 8935 av_dict_copy(&mux->opts, o->g->format_opts, 0);
3654
3655
2/2
✓ Branch 0 taken 2977 times.
✓ Branch 1 taken 5958 times.
8935 if (!strcmp(filename, "-"))
3656 2977 filename = "pipe:";
3657
3658 8935 err = avformat_alloc_output_context2(&oc, NULL, o->format, filename);
3659
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8935 times.
8935 if (!oc) {
3660 ✗ av_log(mux, AV_LOG_FATAL, "Error initializing the muxer for %s: %s\n",
3661 ✗ filename, av_err2str(err));
3662 ✗ return err;
3663 }
3664 8935 mux->fc = oc;
3665
3666 8935 av_strlcat(mux->log_name, "/", sizeof(mux->log_name));
3667 8935 av_strlcat(mux->log_name, oc->oformat->name, sizeof(mux->log_name));
3668
3669
3670
2/2
✓ Branch 0 taken 1349 times.
✓ Branch 1 taken 7586 times.
8935 if (recording_time != INT64_MAX)
3671 1349 oc->duration = recording_time;
3672
3673 8935 oc->interrupt_callback = int_cb;
3674
3675
2/2
✓ Branch 0 taken 2033 times.
✓ Branch 1 taken 6902 times.
8935 if (o->bitexact) {
3676 2033 oc->flags |= AVFMT_FLAG_BITEXACT;
3677 2033 of->bitexact = 1;
3678 } else {
3679 6902 of->bitexact = check_opt_bitexact(oc, mux->opts, "fflags",
3680 AVFMT_FLAG_BITEXACT);
3681 }
3682
3683 8935 err = sch_add_mux(sch, muxer_thread, mux_check_init, mux,
3684 8935 !strcmp(oc->oformat->name, "rtp"), o->thread_queue_size);
3685
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8935 times.
8935 if (err < 0)
3686 ✗ return err;
3687 8935 mux->sch = sch;
3688 8935 mux->sch_idx = err;
3689
3690 /* create all output streams for this file */
3691 8935 err = create_streams(mux, o);
3692
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8934 times.
8935 if (err < 0)
3693 1 return err;
3694
3695 /* check if all codec options have been used */
3696 8934 err = check_avoptions_used(o->g->codec_opts, mux->enc_opts_used, mux, 0);
3697 8934 av_dict_free(&mux->enc_opts_used);
3698
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8934 times.
8934 if (err < 0)
3699 ✗ return err;
3700
3701 /* check filename in case of an image number is expected */
3702
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8934 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
8934 if (oc->oformat->flags & AVFMT_NEEDNUMBER && !av_filename_number_test(oc->url)) {
3703 ✗ av_log(mux, AV_LOG_FATAL,
3704 "Output filename '%s' does not contain a numeric pattern like "
3705 "'%%d', which is required by output format '%s'.\n",
3706 ✗ oc->url, oc->oformat->name);
3707 ✗ return AVERROR(EINVAL);
3708 }
3709
3710
2/2
✓ Branch 0 taken 8775 times.
✓ Branch 1 taken 159 times.
8934 if (!(oc->oformat->flags & AVFMT_NOFILE)) {
3711 /* test if it already exists to avoid losing precious files */
3712 8775 err = assert_file_overwrite(filename);
3713
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8774 times.
8775 if (err < 0)
3714 1 return err;
3715
3716 /* open the file */
3717
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8774 times.
8774 if ((err = avio_open2(&oc->pb, filename, AVIO_FLAG_WRITE,
3718 8774 &oc->interrupt_callback,
3719 &mux->opts)) < 0) {
3720 ✗ av_log(mux, AV_LOG_FATAL, "Error opening output %s: %s\n",
3721 ✗ filename, av_err2str(err));
3722 ✗ return err;
3723 }
3724
4/4
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 96 times.
✓ Branch 3 taken 11 times.
✓ Branch 4 taken 52 times.
159 } else if (strcmp(oc->oformat->name, "image2")==0 && !av_filename_number_test(filename)) {
3725 11 err = assert_file_overwrite(filename);
3726
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (err < 0)
3727 ✗ return err;
3728 }
3729
3730
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8933 times.
8933 if (o->mux_preload) {
3731 ✗ av_dict_set_int(&mux->opts, "preload", o->mux_preload*AV_TIME_BASE, 0);
3732 }
3733 8933 oc->max_delay = (int)(o->mux_max_delay * AV_TIME_BASE);
3734
3735 /* copy metadata and chapters from input files */
3736 8933 err = copy_meta(mux, o);
3737
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8931 times.
8933 if (err < 0)
3738 2 return err;
3739
3740 8931 err = of_add_groups(mux, o);
3741
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8931 times.
8931 if (err < 0)
3742 ✗ return err;
3743
3744 8931 err = of_add_programs(mux, o);
3745
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8931 times.
8931 if (err < 0)
3746 ✗ return err;
3747
3748 8931 err = of_add_metadata(of, oc, o);
3749
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8931 times.
8931 if (err < 0)
3750 ✗ return err;
3751
3752 8931 err = set_dispositions(mux, o);
3753
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8931 times.
8931 if (err < 0) {
3754 ✗ av_log(mux, AV_LOG_FATAL, "Error setting output stream dispositions\n");
3755 ✗ return err;
3756 }
3757
3758 // parse forced keyframe specifications;
3759 // must be done after chapters are created
3760 8931 err = process_forced_keyframes(mux, o);
3761
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8931 times.
8931 if (err < 0) {
3762 ✗ av_log(mux, AV_LOG_FATAL, "Error processing forced keyframes\n");
3763 ✗ return err;
3764 }
3765
3766 8931 err = setup_sync_queues(mux, oc, o->shortest_buf_duration * AV_TIME_BASE,
3767 8931 o->shortest);
3768
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8931 times.
8931 if (err < 0) {
3769 ✗ av_log(mux, AV_LOG_FATAL, "Error setting up output sync queues\n");
3770 ✗ return err;
3771 }
3772
3773 8931 of->url = filename;
3774
3775 /* initialize streamcopy streams. */
3776
2/2
✓ Branch 0 taken 9591 times.
✓ Branch 1 taken 8931 times.
18522 for (int i = 0; i < of->nb_streams; i++) {
3777 9591 OutputStream *ost = of->streams[i];
3778
3779
2/2
✓ Branch 0 taken 981 times.
✓ Branch 1 taken 8610 times.
9591 if (!ost->enc) {
3780 981 err = of_stream_init(of, ost, NULL);
3781
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 981 times.
981 if (err < 0)
3782 ✗ return err;
3783 }
3784 }
3785
3786 8931 return 0;
3787 }
3788