FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/fftools/ffmpeg_mux_init.c
Date: 2026-09-14 12:48:48
Exec Total Coverage
Lines: 1484 2181 68.0%
Functions: 48 55 87.3%
Branches: 1027 1694 60.6%

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 6840 static int check_opt_bitexact(void *ctx, const AVDictionary *opts,
55 const char *opt_name, int flag)
56 {
57 6840 const AVDictionaryEntry *e = av_dict_get(opts, opt_name, NULL, 0);
58
59
2/2
✓ Branch 0 taken 5779 times.
✓ Branch 1 taken 1061 times.
6840 if (e) {
60 5779 const AVOption *o = av_opt_find(ctx, opt_name, NULL, 0, 0);
61 5779 int val = 0;
62
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5779 times.
5779 if (!o)
63 return 0;
64 5779 av_opt_eval_flags(ctx, o, e->value, &val);
65 5779 return !!(val & flag);
66 }
67 1061 return 0;
68 }
69
70 9331 static int choose_encoder(const OptionsContext *o, AVFormatContext *s,
71 MuxStream *ms, const AVCodec **enc)
72 {
73 9331 OutputStream *ost = &ms->ost;
74 9331 enum AVMediaType type = ost->type;
75 9331 const char *codec_name = NULL;
76
77 9331 *enc = NULL;
78
79 9331 opt_match_per_stream_str(ost, &o->codec_names, s, ost->st, &codec_name);
80
81
4/4
✓ Branch 0 taken 1946 times.
✓ Branch 1 taken 7385 times.
✓ Branch 2 taken 94 times.
✓ Branch 3 taken 1852 times.
9331 if (type != AVMEDIA_TYPE_VIDEO &&
82
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 81 times.
94 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 4255 times.
✓ Branch 1 taken 5063 times.
9318 if (!codec_name) {
95 4255 ms->par_in->codec_id = av_guess_codec(s->oformat, NULL, s->url, NULL, ost->type);
96 4255 *enc = avcodec_find_encoder(ms->par_in->codec_id);
97
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4255 times.
4255 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 4168 times.
✓ Branch 1 taken 895 times.
5063 } else if (strcmp(codec_name, "copy")) {
105 4168 int ret = find_codec(ost, codec_name, ost->type, 1, enc);
106
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4168 times.
4168 if (ret < 0)
107 return ret;
108 4168 ms->par_in->codec_id = (*enc)->id;
109 }
110
111 9318 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 8823 void of_enc_stats_close(void)
199 {
200
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8823 times.
8823 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 8823 av_freep(&enc_stats_files);
205 8823 nb_enc_stats_files = 0;
206 8823 }
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 2782 static const char *output_stream_item_name(void *obj)
380 {
381 2782 const MuxStream *ms = obj;
382
383 2782 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 9331 static MuxStream *mux_stream_alloc(Muxer *mux, enum AVMediaType type)
394 {
395 9331 const char *type_str = av_get_media_type_string(type);
396 MuxStream *ms;
397
398 9331 ms = allocate_array_elem(&mux->of.streams, sizeof(*ms), &mux->of.nb_streams);
399
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9331 times.
9331 if (!ms)
400 return NULL;
401
402 9331 ms->ost.file = &mux->of;
403 9331 ms->ost.index = mux->of.nb_streams - 1;
404 9331 ms->ost.type = type;
405
406 9331 ms->ost.class = &output_stream_class;
407
408 9331 ms->sch_idx = -1;
409 9331 ms->sch_idx_enc = -1;
410
411
1/2
✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
9331 snprintf(ms->log_name, sizeof(ms->log_name), "%cost#%d:%d",
412 9331 type_str ? *type_str : '?', mux->of.index, ms->ost.index);
413
414 9331 return ms;
415 }
416
417 8381 static int ost_get_filters(const OptionsContext *o, AVFormatContext *oc,
418 OutputStream *ost, char **dst)
419 {
420 8381 const char *filters = NULL;
421 8381 opt_match_per_stream_str(ost, &o->filters, oc, ost->st, &filters);
422
423
2/2
✓ Branch 0 taken 1406 times.
✓ Branch 1 taken 6975 times.
8381 if (!ost->ist) {
424
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1406 times.
1406 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 1406 return 0;
432 }
433
434
2/2
✓ Branch 0 taken 3958 times.
✓ Branch 1 taken 3017 times.
6975 if (filters)
435 3958 *dst = av_strdup(filters);
436 else
437
2/2
✓ Branch 0 taken 2342 times.
✓ Branch 1 taken 675 times.
3017 *dst = av_strdup(ost->type == AVMEDIA_TYPE_VIDEO ? "null" : "anull");
438
1/2
✓ Branch 0 taken 6975 times.
✗ Branch 1 not taken.
6975 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 650 static int pixfmt_in_list(const enum AVPixelFormat *formats, enum AVPixelFormat format)
461 {
462
1/2
✓ Branch 0 taken 3710 times.
✗ Branch 1 not taken.
3710 for (; *formats != AV_PIX_FMT_NONE; formats++)
463
2/2
✓ Branch 0 taken 650 times.
✓ Branch 1 taken 3060 times.
3710 if (*formats == format)
464 650 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 5368 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 5368 fmt = av_get_pix_fmt(name);
507
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5368 times.
5368 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 5368 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 5368 times.
5368 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 325 times.
✓ Branch 1 taken 5043 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 325 times.
5368 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 325 times.
✓ Branch 1 taken 5043 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 325 times.
5368 if (fmts && !pixfmt_in_list(fmts, fmt))
544 fmt = choose_pixel_fmt(ost->enc->enc_ctx, fmt);
545
546 5368 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 8821 static int check_stereo3d_leftovers(Muxer *mux, const OptionsContext *o)
591 {
592 8821 AVFormatContext *oc = mux->fc;
593
594
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 8821 times.
8826 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 8821 return 0;
627 }
628
629 7385 static int new_stream_video(Muxer *mux, const OptionsContext *o,
630 OutputStream *ost, int *keep_pix_fmt,
631 enum VideoSyncMethod *vsync_method)
632 {
633 7385 MuxStream *ms = ms_from_ost(ost);
634 7385 AVFormatContext *oc = mux->fc;
635 AVStream *st;
636 7385 const char *frame_rate = NULL, *max_frame_rate = NULL, *frame_aspect_ratio = NULL;
637 7385 const char *stereo3d = NULL;
638 7385 int ret = 0;
639
640 7385 st = ost->st;
641
642 7385 opt_match_per_stream_str(ost, &o->frame_rates, oc, st, &frame_rate);
643
3/4
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 7363 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 22 times.
7385 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 7385 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 7385 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
7385 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 7363 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 22 times.
7385 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 7385 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 7385 times.
7385 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 7385 opt_match_per_stream_str(ost, &o->stereo3ds, oc, st, &stereo3d);
671
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 7380 times.
7385 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 6930 times.
✓ Branch 1 taken 455 times.
7385 if (ost->enc) {
679 6930 AVCodecContext *video_enc = ost->enc->enc_ctx;
680 6930 const char *p = NULL, *fps_mode = NULL;
681 6930 const char *frame_size = NULL;
682 6930 const char *frame_pix_fmt = NULL;
683 6930 const char *intra_matrix = NULL, *inter_matrix = NULL;
684 6930 const char *chroma_intra_matrix = NULL;
685 6930 int do_pass = 0;
686 int i;
687
688 6930 opt_match_per_stream_str(ost, &o->frame_sizes, oc, st, &frame_size);
689
2/2
✓ Branch 0 taken 1350 times.
✓ Branch 1 taken 5580 times.
6930 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 6930 opt_match_per_stream_str(ost, &o->frame_pix_fmts, oc, st, &frame_pix_fmt);
698
3/4
✓ Branch 0 taken 5368 times.
✓ Branch 1 taken 1562 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5368 times.
6930 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 5368 times.
✓ Branch 1 taken 1562 times.
6930 if (frame_pix_fmt) {
704 5368 video_enc->pix_fmt = pix_fmt_parse(ost, frame_pix_fmt);
705
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5368 times.
5368 if (video_enc->pix_fmt == AV_PIX_FMT_NONE)
706 return AVERROR(EINVAL);
707 }
708
709 6930 opt_match_per_stream_str(ost, &o->intra_matrices, oc, st, &intra_matrix);
710
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6930 times.
6930 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 6930 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 6930 times.
6930 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 6930 opt_match_per_stream_str(ost, &o->inter_matrices, oc, st, &inter_matrix);
727
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6930 times.
6930 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 6930 opt_match_per_stream_str(ost, &o->rc_overrides, oc, st, &p);
736
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6930 times.
6930 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 6930 video_enc->rc_override_count = i;
764
765 /* two pass mode */
766 6930 opt_match_per_stream_int(ost, &o->pass, oc, st, &do_pass);
767
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 6914 times.
6930 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 6930 opt_match_per_stream_str(ost, &o->passlogfiles, oc, st, &ost->logfile_prefix);
775
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 6914 times.
6930 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 6914 times.
6930 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 6930 opt_match_per_stream_int(ost, &o->force_fps, oc, st, &ms->force_fps);
827
828 6930 *vsync_method = VSYNC_AUTO;
829 6930 opt_match_per_stream_str(ost, &o->fps_mode, oc, st, &fps_mode);
830
2/2
✓ Branch 0 taken 535 times.
✓ Branch 1 taken 6395 times.
6930 if (fps_mode) {
831 535 ret = parse_and_set_vsync(fps_mode, vsync_method, ost->file->index, ost->index);
832
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 535 times.
535 if (ret < 0)
833 return ret;
834 }
835
836
3/4
✓ Branch 0 taken 6909 times.
✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6909 times.
6930 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 6395 times.
✓ Branch 1 taken 535 times.
6930 if (*vsync_method == VSYNC_AUTO) {
845
3/4
✓ Branch 0 taken 6375 times.
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6375 times.
6395 if (ms->frame_rate.num || ms->max_frame_rate.num) {
846 20 *vsync_method = VSYNC_CFR;
847
2/2
✓ Branch 0 taken 300 times.
✓ Branch 1 taken 6075 times.
6375 } else if (!strcmp(oc->oformat->name, "avi")) {
848 300 *vsync_method = VSYNC_VFR;
849 } else {
850 6075 *vsync_method = (oc->oformat->flags & AVFMT_VARIABLE_FPS) ?
851 4579 ((oc->oformat->flags & AVFMT_NOTIMESTAMPS) ?
852
4/4
✓ Branch 0 taken 4579 times.
✓ Branch 1 taken 1496 times.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 4559 times.
6075 VSYNC_PASSTHROUGH : VSYNC_VFR) : VSYNC_CFR;
853 }
854
855
4/4
✓ Branch 0 taken 5162 times.
✓ Branch 1 taken 1233 times.
✓ Branch 2 taken 411 times.
✓ Branch 3 taken 4751 times.
6395 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 1150 times.
✓ Branch 1 taken 5245 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1150 times.
6395 if (*vsync_method == VSYNC_CFR && copy_ts) {
863 *vsync_method = VSYNC_VSCFR;
864 }
865 }
866 }
867
868 7385 return 0;
869 }
870
871 1852 static int new_stream_audio(Muxer *mux, const OptionsContext *o,
872 OutputStream *ost)
873 {
874 1852 MuxStream *ms = ms_from_ost(ost);
875 1852 AVFormatContext *oc = mux->fc;
876 1852 AVStream *st = ost->st;
877
878
2/2
✓ Branch 0 taken 1451 times.
✓ Branch 1 taken 401 times.
1852 if (ost->enc) {
879 1451 AVCodecContext *audio_enc = ost->enc->enc_ctx;
880 1451 int channels = 0;
881 1451 const char *layout = NULL;
882 1451 const char *sample_fmt = NULL;
883
884 1451 opt_match_per_stream_int(ost, &o->audio_channels, oc, st, &channels);
885
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 1441 times.
1451 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 1451 opt_match_per_stream_str(ost, &o->audio_ch_layouts, oc, st, &layout);
891
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1450 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1451 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 1451 opt_match_per_stream_str(ost, &o->sample_fmts, oc, st, &sample_fmt);
897
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1450 times.
1451 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 1451 opt_match_per_stream_int(ost, &o->audio_sample_rate, oc, st, &audio_enc->sample_rate);
904 1451 opt_match_per_stream_str(ost, &o->apad, oc, st, &ms->apad);
905 }
906
907 1852 return 0;
908 }
909
910 81 static int new_stream_subtitle(Muxer *mux, const OptionsContext *o,
911 OutputStream *ost)
912 {
913 AVStream *st;
914
915 81 st = ost->st;
916
917
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 39 times.
81 if (ost->enc) {
918 42 AVCodecContext *subtitle_enc = ost->enc->enc_ctx;
919
920 AVCodecDescriptor const *input_descriptor =
921 42 avcodec_descriptor_get(ost->ist->par->codec_id);
922 AVCodecDescriptor const *output_descriptor =
923 42 avcodec_descriptor_get(subtitle_enc->codec_id);
924 42 int input_props = 0, output_props = 0;
925
926 42 const char *frame_size = NULL;
927
928 42 opt_match_per_stream_str(ost, &o->frame_sizes, mux->fc, st, &frame_size);
929
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 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 42 times.
✗ Branch 1 not taken.
42 if (input_descriptor)
937 42 input_props = input_descriptor->props & (AV_CODEC_PROP_TEXT_SUB | AV_CODEC_PROP_BITMAP_SUB);
938
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 if (output_descriptor)
939 42 output_props = output_descriptor->props & (AV_CODEC_PROP_TEXT_SUB | AV_CODEC_PROP_BITMAP_SUB);
940
3/6
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 42 times.
42 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 81 return 0;
949 }
950
951 static int
952 8381 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 8381 OutputStream *ost = &ms->ost;
960 8381 AVCodecContext *enc_ctx = ost->enc->enc_ctx;
961 char name[16];
962 8381 char *filters = NULL;
963 int ret;
964
965 33524 OutputFilterOptions opts = {
966 8381 .enc = enc_ctx->codec,
967 .name = name,
968 8381 .format = (ost->type == AVMEDIA_TYPE_VIDEO) ?
969 8381 enc_ctx->pix_fmt : enc_ctx->sample_fmt,
970 8381 .width = enc_ctx->width,
971 8381 .height = enc_ctx->height,
972 8381 .color_space = enc_ctx->colorspace,
973 8381 .color_range = enc_ctx->color_range,
974 8381 .alpha_mode = enc_ctx->alpha_mode,
975 .vsync_method = vsync_method,
976 .frame_rate = ms->frame_rate,
977 .max_frame_rate = ms->max_frame_rate,
978 8381 .sample_rate = enc_ctx->sample_rate,
979 .ch_layout = enc_ctx->ch_layout,
980 8381 .sws_opts = o->g->sws_dict,
981 8381 .swr_opts = o->g->swr_opts,
982 .output_tb = enc_tb,
983 8381 .trim_start_us = mux->of.start_time,
984 8381 .trim_duration_us = mux->of.recording_time,
985 8381 .ts_offset = mux->of.start_time == AV_NOPTS_VALUE ?
986
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8380 times.
8381 0 : mux->of.start_time,
987 .vs = vs,
988 .nb_threads = -1,
989 8381 .reinit_opts = ost->enc->reinit_opts,
990
991 16762 .flags = OFILTER_FLAG_DISABLE_CONVERT * !!keep_pix_fmt |
992
3/4
✓ Branch 0 taken 8381 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6930 times.
✓ Branch 3 taken 1451 times.
16762 OFILTER_FLAG_AUTOSCALE * !!autoscale |
993
2/2
✓ Branch 1 taken 65 times.
✓ Branch 2 taken 8316 times.
8381 OFILTER_FLAG_AUDIO_24BIT * !!(av_get_exact_bits_per_sample(enc_ctx->codec_id) == 24),
994 };
995
996 8381 snprintf(name, sizeof(name), "#%d:%d", mux->of.index, ost->index);
997
998
2/2
✓ Branch 0 taken 6930 times.
✓ Branch 1 taken 1451 times.
8381 if (ost->type == AVMEDIA_TYPE_VIDEO) {
999
1/2
✓ Branch 0 taken 6930 times.
✗ Branch 1 not taken.
6930 if (!keep_pix_fmt) {
1000 6930 ret = avcodec_get_supported_config(enc_ctx, NULL,
1001 AV_CODEC_CONFIG_PIX_FORMAT, 0,
1002 (const void **) &opts.pix_fmts, NULL);
1003
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6930 times.
6930 if (ret < 0)
1004 return ret;
1005 }
1006
2/2
✓ Branch 0 taken 6929 times.
✓ Branch 1 taken 1 times.
6930 if (!ms->force_fps) {
1007 6929 ret = avcodec_get_supported_config(enc_ctx, NULL,
1008 AV_CODEC_CONFIG_FRAME_RATE, 0,
1009 (const void **) &opts.frame_rates, NULL);
1010
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6929 times.
6929 if (ret < 0)
1011 return ret;
1012 }
1013 6930 ret = avcodec_get_supported_config(enc_ctx, NULL,
1014 AV_CODEC_CONFIG_COLOR_SPACE, 0,
1015 (const void **) &opts.color_spaces, NULL);
1016
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6930 times.
6930 if (ret < 0)
1017 return ret;
1018 6930 ret = avcodec_get_supported_config(enc_ctx, NULL,
1019 AV_CODEC_CONFIG_COLOR_RANGE, 0,
1020 (const void **) &opts.color_ranges, NULL);
1021
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6930 times.
6930 if (ret < 0)
1022 return ret;
1023 6930 ret = avcodec_get_supported_config(enc_ctx, NULL,
1024 AV_CODEC_CONFIG_ALPHA_MODE, 0,
1025 (const void **) &opts.alpha_modes, NULL);
1026
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6930 times.
6930 if (ret < 0)
1027 return ret;
1028 } else {
1029 1451 ret = avcodec_get_supported_config(enc_ctx, NULL,
1030 AV_CODEC_CONFIG_SAMPLE_FORMAT, 0,
1031 (const void **) &opts.sample_fmts, NULL);
1032
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1451 times.
1451 if (ret < 0)
1033 return ret;
1034 1451 ret = avcodec_get_supported_config(enc_ctx, NULL,
1035 AV_CODEC_CONFIG_SAMPLE_RATE, 0,
1036 (const void **) &opts.sample_rates, NULL);
1037
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1451 times.
1451 if (ret < 0)
1038 return ret;
1039 1451 ret = avcodec_get_supported_config(enc_ctx, NULL,
1040 AV_CODEC_CONFIG_CHANNEL_LAYOUT, 0,
1041 (const void **) &opts.ch_layouts, NULL);
1042
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1451 times.
1451 if (ret < 0)
1043 return ret;
1044 }
1045
1046
2/2
✓ Branch 0 taken 5514 times.
✓ Branch 1 taken 2867 times.
8381 if (threads_manual) {
1047 5514 ret = av_opt_get_int(enc_ctx, "threads", 0, &opts.nb_threads);
1048
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5514 times.
5514 if (ret < 0)
1049 return ret;
1050 }
1051
1052 8381 ret = ost_get_filters(o, mux->fc, ost, &filters);
1053
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8381 times.
8381 if (ret < 0)
1054 return ret;
1055
1056
2/2
✓ Branch 0 taken 1406 times.
✓ Branch 1 taken 6975 times.
8381 if (ofilter) {
1057
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1406 times.
1406 av_assert0(!filters);
1058 1406 ost->filter = ofilter;
1059 1406 ret = ofilter_bind_enc(ofilter, ms->sch_idx_enc, &opts);
1060 } else {
1061 6975 ret = fg_create_simple(&ost->fg_simple, ost->ist, &filters,
1062 6975 mux->sch, ms->sch_idx_enc, &opts);
1063
2/2
✓ Branch 0 taken 6974 times.
✓ Branch 1 taken 1 times.
6975 if (ret >= 0)
1064 6974 ost->filter = ost->fg_simple->outputs[0];
1065
1066 }
1067
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8380 times.
8381 if (ret < 0)
1068 1 return ret;
1069
1070 8380 *src = SCH_ENC(ms->sch_idx_enc);
1071
1072 8380 return 0;
1073 }
1074
1075 907 static int streamcopy_init(const OptionsContext *o, const Muxer *mux,
1076 OutputStream *ost, AVDictionary **encoder_opts)
1077 {
1078 907 MuxStream *ms = ms_from_ost(ost);
1079
1080 907 const InputStream *ist = ost->ist;
1081 907 const InputFile *ifile = ist->file;
1082
1083 907 AVCodecParameters *par = ms->par_in;
1084 907 uint32_t codec_tag = par->codec_tag;
1085
1086 907 AVCodecContext *codec_ctx = NULL;
1087
1088 907 AVRational fr = ms->frame_rate;
1089
1090 907 int ret = 0;
1091
1092 907 const char *filters = NULL;
1093 907 opt_match_per_stream_str(ost, &o->filters, mux->fc, ost->st, &filters);
1094
1095
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 907 times.
907 if (filters) {
1096 av_log(ost, AV_LOG_ERROR,
1097 "Filtergraph '%s' was specified, but codec copy was selected. "
1098 "Filtering and streamcopy cannot be used together.\n", filters);
1099 return AVERROR(EINVAL);
1100 }
1101
1102 907 codec_ctx = avcodec_alloc_context3(NULL);
1103
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 907 times.
907 if (!codec_ctx)
1104 return AVERROR(ENOMEM);
1105
1106 907 ret = avcodec_parameters_to_context(codec_ctx, ist->par);
1107
1/2
✓ Branch 0 taken 907 times.
✗ Branch 1 not taken.
907 if (ret >= 0)
1108 907 ret = av_opt_set_dict(codec_ctx, encoder_opts);
1109
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 907 times.
907 if (ret < 0) {
1110 av_log(ost, AV_LOG_FATAL,
1111 "Error setting up codec context options.\n");
1112 goto fail;
1113 }
1114
1115 907 ret = avcodec_parameters_from_context(par, codec_ctx);
1116
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 907 times.
907 if (ret < 0) {
1117 av_log(ost, AV_LOG_FATAL,
1118 "Error getting reference codec parameters.\n");
1119 goto fail;
1120 }
1121
1122
2/2
✓ Branch 0 taken 900 times.
✓ Branch 1 taken 7 times.
907 if (!codec_tag) {
1123 900 const struct AVCodecTag * const *ct = mux->fc->oformat->codec_tag;
1124 unsigned int codec_tag_tmp;
1125
6/6
✓ Branch 0 taken 164 times.
✓ Branch 1 taken 736 times.
✓ Branch 3 taken 122 times.
✓ Branch 4 taken 42 times.
✓ Branch 5 taken 16 times.
✓ Branch 6 taken 106 times.
1022 if (!ct || av_codec_get_id (ct, par->codec_tag) == par->codec_id ||
1126 122 !av_codec_get_tag2(ct, par->codec_id, &codec_tag_tmp))
1127 794 codec_tag = par->codec_tag;
1128 }
1129
1130 907 par->codec_tag = codec_tag;
1131
1132
2/2
✓ Branch 0 taken 906 times.
✓ Branch 1 taken 1 times.
907 if (!fr.num)
1133 906 fr = ist->framerate;
1134
1135
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 905 times.
907 if (fr.num)
1136 2 ost->st->avg_frame_rate = fr;
1137 else
1138 905 ost->st->avg_frame_rate = ist->st->avg_frame_rate;
1139
1140 // copy timebase while removing common factors
1141
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 907 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
907 if (ost->st->time_base.num <= 0 || ost->st->time_base.den <= 0) {
1142
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 905 times.
907 if (fr.num)
1143 2 ost->st->time_base = av_inv_q(fr);
1144 else
1145 905 ost->st->time_base = av_add_q(ist->st->time_base, (AVRational){0, 1});
1146 }
1147
1148
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 907 times.
907 if (!ms->copy_prior_start) {
1149 ms->ts_copy_start = (mux->of.start_time == AV_NOPTS_VALUE) ?
1150 0 : mux->of.start_time;
1151 if (copy_ts && ifile->start_time != AV_NOPTS_VALUE) {
1152 ms->ts_copy_start = FFMAX(ms->ts_copy_start,
1153 ifile->start_time + ifile->ts_offset);
1154 }
1155 }
1156
1157
2/2
✓ Branch 0 taken 124 times.
✓ Branch 1 taken 907 times.
1031 for (int i = 0; i < ist->st->codecpar->nb_coded_side_data; i++) {
1158 124 const AVPacketSideData *sd_src = &ist->st->codecpar->coded_side_data[i];
1159 AVPacketSideData *sd_dst;
1160
1161 124 sd_dst = av_packet_side_data_new(&ost->st->codecpar->coded_side_data,
1162 124 &ost->st->codecpar->nb_coded_side_data,
1163 124 sd_src->type, sd_src->size, 0);
1164
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 124 times.
124 if (!sd_dst) {
1165 ret = AVERROR(ENOMEM);
1166 goto fail;
1167 }
1168 124 memcpy(sd_dst->data, sd_src->data, sd_src->size);
1169 }
1170
1171
3/3
✓ Branch 0 taken 401 times.
✓ Branch 1 taken 455 times.
✓ Branch 2 taken 51 times.
907 switch (par->codec_type) {
1172 401 case AVMEDIA_TYPE_AUDIO:
1173
4/6
✓ Branch 0 taken 396 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 396 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 396 times.
401 if ((par->block_align == 1 || par->block_align == 1152 || par->block_align == 576) &&
1174
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 par->codec_id == AV_CODEC_ID_MP3)
1175 par->block_align = 0;
1176
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 386 times.
401 if (par->codec_id == AV_CODEC_ID_AC3)
1177 15 par->block_align = 0;
1178 401 break;
1179 455 case AVMEDIA_TYPE_VIDEO: {
1180 AVRational sar;
1181
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 455 times.
455 if (ost->frame_aspect_ratio.num) { // overridden by the -aspect cli option
1182 sar =
1183 av_mul_q(ost->frame_aspect_ratio,
1184 (AVRational){ par->height, par->width });
1185 av_log(ost, AV_LOG_WARNING, "Overriding aspect ratio "
1186 "with stream copy may produce invalid files\n");
1187 }
1188
2/2
✓ Branch 0 taken 134 times.
✓ Branch 1 taken 321 times.
455 else if (ist->st->sample_aspect_ratio.num)
1189 134 sar = ist->st->sample_aspect_ratio;
1190 else
1191 321 sar = par->sample_aspect_ratio;
1192 455 ost->st->sample_aspect_ratio = par->sample_aspect_ratio = sar;
1193 455 ost->st->r_frame_rate = ist->st->r_frame_rate;
1194 455 break;
1195 }
1196 }
1197
1198 907 fail:
1199 907 avcodec_free_context(&codec_ctx);
1200 907 return ret;
1201 }
1202
1203 8423 static int set_encoder_id(OutputStream *ost, const AVCodec *codec)
1204 {
1205 8423 const char *cname = codec->name;
1206 uint8_t *encoder_string;
1207 int encoder_string_len;
1208
1209 8423 encoder_string_len = sizeof(LIBAVCODEC_IDENT) + strlen(cname) + 2;
1210 8423 encoder_string = av_mallocz(encoder_string_len);
1211
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8423 times.
8423 if (!encoder_string)
1212 return AVERROR(ENOMEM);
1213
1214
4/4
✓ Branch 0 taken 915 times.
✓ Branch 1 taken 7508 times.
✓ Branch 2 taken 904 times.
✓ Branch 3 taken 11 times.
8423 if (!ost->file->bitexact && !ost->bitexact)
1215 904 av_strlcpy(encoder_string, LIBAVCODEC_IDENT " ", encoder_string_len);
1216 else
1217 7519 av_strlcpy(encoder_string, "Lavc ", encoder_string_len);
1218 8423 av_strlcat(encoder_string, cname, encoder_string_len);
1219 8423 av_dict_set(&ost->st->metadata, "encoder", encoder_string,
1220 AV_DICT_DONT_STRDUP_VAL | AV_DICT_DONT_OVERWRITE);
1221
1222 8423 return 0;
1223 }
1224
1225 9331 static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
1226 InputStream *ist, OutputFilter *ofilter, const ViewSpecifier *vs,
1227 OutputStream **post)
1228 {
1229 9331 AVFormatContext *oc = mux->fc;
1230 MuxStream *ms;
1231 OutputStream *ost;
1232 const AVCodec *enc;
1233 AVStream *st;
1234 9331 SchedulerNode src = { .type = SCH_NODE_TYPE_NONE };
1235 9331 AVDictionary *encoder_opts = NULL;
1236 9331 int ret = 0, keep_pix_fmt = 0, autoscale = 1;
1237 9331 int threads_manual = 0;
1238 9331 AVRational enc_tb = { 0, 0 };
1239 9331 enum VideoSyncMethod vsync_method = VSYNC_AUTO;
1240 9331 const char *bsfs = NULL, *time_base = NULL, *codec_tag = NULL, *manual_disp = NULL;
1241 char *next;
1242 9331 double qscale = -1;
1243
1244 9331 st = avformat_new_stream(oc, NULL);
1245
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9331 times.
9331 if (!st)
1246 return AVERROR(ENOMEM);
1247
1248 9331 ms = mux_stream_alloc(mux, type);
1249
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9331 times.
9331 if (!ms)
1250 return AVERROR(ENOMEM);
1251
1252 // only streams with sources (i.e. not attachments)
1253 // are handled by the scheduler
1254
4/4
✓ Branch 0 taken 1407 times.
✓ Branch 1 taken 7924 times.
✓ Branch 2 taken 1406 times.
✓ Branch 3 taken 1 times.
9331 if (ist || ofilter) {
1255 9330 ret = GROW_ARRAY(mux->sch_stream_idx, mux->nb_sch_stream_idx);
1256
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9330 times.
9330 if (ret < 0)
1257 return ret;
1258
1259 9330 ret = sch_add_mux_stream(mux->sch, mux->sch_idx);
1260
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9330 times.
9330 if (ret < 0)
1261 return ret;
1262
1263
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9330 times.
9330 av_assert0(ret == mux->nb_sch_stream_idx - 1);
1264 9330 mux->sch_stream_idx[ret] = ms->ost.index;
1265 9330 ms->sch_idx = ret;
1266 }
1267
1268 9331 ost = &ms->ost;
1269
1270
2/2
✓ Branch 0 taken 67 times.
✓ Branch 1 taken 9264 times.
9331 if (o->streamid) {
1271 AVDictionaryEntry *e;
1272 char idx[16], *p;
1273 67 snprintf(idx, sizeof(idx), "%d", ost->index);
1274
1275 67 e = av_dict_get(o->streamid, idx, NULL, 0);
1276
1/2
✓ Branch 0 taken 67 times.
✗ Branch 1 not taken.
67 if (e) {
1277 67 st->id = strtol(e->value, &p, 0);
1278
2/4
✓ Branch 0 taken 67 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 67 times.
67 if (!e->value[0] || *p) {
1279 av_log(ost, AV_LOG_FATAL, "Invalid stream id: %s\n", e->value);
1280 return AVERROR(EINVAL);
1281 }
1282 }
1283 }
1284
1285 9331 ms->par_in = avcodec_parameters_alloc();
1286
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9331 times.
9331 if (!ms->par_in)
1287 return AVERROR(ENOMEM);
1288
1289 9331 ms->last_mux_dts = AV_NOPTS_VALUE;
1290
1291 9331 ost->st = st;
1292 9331 ost->ist = ist;
1293 9331 ost->kf.ref_pts = AV_NOPTS_VALUE;
1294 9331 ms->par_in->codec_type = type;
1295 9331 st->codecpar->codec_type = type;
1296
1297
2/2
✓ Branch 0 taken 7385 times.
✓ Branch 1 taken 1946 times.
9331 if (ost->type == AVMEDIA_TYPE_VIDEO) {
1298
2/2
✓ Branch 0 taken 6148 times.
✓ Branch 1 taken 1237 times.
7385 if (ost->ist)
1299 6148 ost->st->disposition = ost->ist->st->disposition;
1300
1301 7385 opt_match_per_stream_str(ost, &o->disposition, oc, st, &manual_disp);
1302
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 7377 times.
7385 if (manual_disp) {
1303 8 ret = av_opt_set(ost->st, "disposition", manual_disp, 0);
1304
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (ret < 0)
1305 return ret;
1306 }
1307
1308 7385 ost->st->disposition &= AV_DISPOSITION_ATTACHED_PIC;
1309 }
1310
1311 9331 ret = choose_encoder(o, oc, ms, &enc);
1312
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9331 times.
9331 if (ret < 0) {
1313 av_log(ost, AV_LOG_FATAL, "Error selecting an encoder\n");
1314 return ret;
1315 }
1316
1317
2/2
✓ Branch 0 taken 8423 times.
✓ Branch 1 taken 908 times.
9331 if (enc) {
1318 8423 ret = sch_add_enc(mux->sch, encoder_thread, ost,
1319
2/2
✓ Branch 0 taken 8381 times.
✓ Branch 1 taken 42 times.
8423 ost->type == AVMEDIA_TYPE_SUBTITLE ? NULL : enc_open);
1320
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8423 times.
8423 if (ret < 0)
1321 return ret;
1322 8423 ms->sch_idx_enc = ret;
1323
1324 8423 ret = enc_alloc(&ost->enc, enc, mux->sch, ms->sch_idx_enc, ost);
1325
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8423 times.
8423 if (ret < 0)
1326 return ret;
1327
1328 8423 av_strlcat(ms->log_name, "/", sizeof(ms->log_name));
1329 8423 av_strlcat(ms->log_name, enc->name, sizeof(ms->log_name));
1330 } else {
1331
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 908 times.
908 if (ofilter) {
1332 av_log(ost, AV_LOG_ERROR,
1333 "Streamcopy requested for output stream fed "
1334 "from a complex filtergraph. Filtering and streamcopy "
1335 "cannot be used together.\n");
1336 return AVERROR(EINVAL);
1337 }
1338
1339 908 av_strlcat(ms->log_name, "/copy", sizeof(ms->log_name));
1340 }
1341
1342 9331 av_log(ost, AV_LOG_VERBOSE, "Created %s stream from ",
1343 av_get_media_type_string(type));
1344
2/2
✓ Branch 0 taken 7924 times.
✓ Branch 1 taken 1407 times.
9331 if (ist)
1345 7924 av_log(ost, AV_LOG_VERBOSE, "input stream %d:%d",
1346 7924 ist->file->index, ist->index);
1347
2/2
✓ Branch 0 taken 1406 times.
✓ Branch 1 taken 1 times.
1407 else if (ofilter)
1348 1406 av_log(ost, AV_LOG_VERBOSE, "complex filtergraph %d:[%s]",
1349 1406 ofilter->graph->index, ofilter->name);
1350
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 else if (type == AVMEDIA_TYPE_ATTACHMENT)
1351 1 av_log(ost, AV_LOG_VERBOSE, "attached file");
1352 else av_assert0(0);
1353 9331 av_log(ost, AV_LOG_VERBOSE, "\n");
1354
1355 9331 ms->pkt = av_packet_alloc();
1356
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9331 times.
9331 if (!ms->pkt)
1357 return AVERROR(ENOMEM);
1358
1359
2/2
✓ Branch 0 taken 8423 times.
✓ Branch 1 taken 908 times.
9331 if (ost->enc) {
1360 8423 AVIOContext *s = NULL;
1361 8423 char *buf = NULL, *arg = NULL;
1362 8423 const char *enc_stats_pre = NULL, *enc_stats_post = NULL, *mux_stats = NULL;
1363 8423 const char *enc_time_base = NULL, *enc_reinit_opts = NULL, *preset = NULL;
1364
1365 8423 ret = filter_codec_opts(o->g->codec_opts, enc->id,
1366 oc, st, enc, &encoder_opts,
1367 &mux->enc_opts_used);
1368
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8423 times.
8423 if (ret < 0)
1369 goto fail;
1370
1371 8423 opt_match_per_stream_str(ost, &o->presets, oc, st, &preset);
1372 8423 opt_match_per_stream_int(ost, &o->autoscale, oc, st, &autoscale);
1373
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8423 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
8423 if (preset && (!(ret = get_preset_file_2(preset, enc->name, &s)))) {
1374 AVBPrint bprint;
1375 av_bprint_init(&bprint, 0, AV_BPRINT_SIZE_UNLIMITED);
1376 do {
1377 av_bprint_clear(&bprint);
1378 buf = get_line(s, &bprint);
1379 if (!buf) {
1380 ret = AVERROR(ENOMEM);
1381 break;
1382 }
1383
1384 if (!buf[0] || buf[0] == '#')
1385 continue;
1386 if (!(arg = strchr(buf, '='))) {
1387 av_log(ost, AV_LOG_FATAL, "Invalid line found in the preset file.\n");
1388 ret = AVERROR(EINVAL);
1389 break;
1390 }
1391 *arg++ = 0;
1392 av_dict_set(&encoder_opts, buf, arg, AV_DICT_DONT_OVERWRITE);
1393 } while (!s->eof_reached);
1394 av_bprint_finalize(&bprint, NULL);
1395 avio_closep(&s);
1396 }
1397
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8423 times.
8423 if (ret) {
1398 av_log(ost, AV_LOG_FATAL,
1399 "Preset %s specified, but could not be opened.\n", preset);
1400 goto fail;
1401 }
1402
1403 8423 opt_match_per_stream_str(ost, &o->enc_reinit_opts, oc, st, &enc_reinit_opts);
1404
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8423 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8423 if (enc_reinit_opts &&
1405 (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) {
1406 ost->enc->reinit_opts = av_strdup(enc_reinit_opts);
1407 if (!ost->enc->reinit_opts) {
1408 ret = AVERROR(ENOMEM);
1409 goto fail;
1410 }
1411 }
1412
1413 8423 opt_match_per_stream_str(ost, &o->enc_stats_pre, oc, st, &enc_stats_pre);
1414
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8423 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8423 if (enc_stats_pre &&
1415 (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) {
1416 const char *format = "{fidx} {sidx} {n} {t}";
1417
1418 opt_match_per_stream_str(ost, &o->enc_stats_pre_fmt, oc, st, &format);
1419
1420 ret = enc_stats_init(ost, &ost->enc_stats_pre, 1, enc_stats_pre, format);
1421 if (ret < 0)
1422 goto fail;
1423 }
1424
1425 8423 opt_match_per_stream_str(ost, &o->enc_stats_post, oc, st, &enc_stats_post);
1426
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8423 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8423 if (enc_stats_post &&
1427 (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) {
1428 const char *format = "{fidx} {sidx} {n} {t}";
1429
1430 opt_match_per_stream_str(ost, &o->enc_stats_post_fmt, oc, st, &format);
1431
1432 ret = enc_stats_init(ost, &ost->enc_stats_post, 0, enc_stats_post, format);
1433 if (ret < 0)
1434 goto fail;
1435 }
1436
1437 8423 opt_match_per_stream_str(ost, &o->mux_stats, oc, st, &mux_stats);
1438
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8423 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8423 if (mux_stats &&
1439 (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) {
1440 const char *format = "{fidx} {sidx} {n} {t}";
1441
1442 opt_match_per_stream_str(ost, &o->mux_stats_fmt, oc, st, &format);
1443
1444 ret = enc_stats_init(ost, &ms->stats, 0, mux_stats, format);
1445 if (ret < 0)
1446 goto fail;
1447 }
1448
1449 8423 opt_match_per_stream_str(ost, &o->enc_time_bases, oc, st, &enc_time_base);
1450
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8422 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
8423 if (enc_time_base && type == AVMEDIA_TYPE_SUBTITLE)
1451 av_log(ost, AV_LOG_WARNING,
1452 "-enc_time_base not supported for subtitles, ignoring\n");
1453
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8422 times.
8423 else if (enc_time_base) {
1454 AVRational q;
1455
1456
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (!strcmp(enc_time_base, "demux")) {
1457 1 q = (AVRational){ ENC_TIME_BASE_DEMUX, 0 };
1458 } else if (!strcmp(enc_time_base, "filter")) {
1459 q = (AVRational){ ENC_TIME_BASE_FILTER, 0 };
1460 } else {
1461 ret = av_parse_ratio(&q, enc_time_base, INT_MAX, 0, NULL);
1462 if (ret < 0 || q.den <= 0 || q.num < 0) {
1463 av_log(ost, AV_LOG_FATAL, "Invalid time base: %s\n", enc_time_base);
1464 ret = ret < 0 ? ret : AVERROR(EINVAL);
1465 goto fail;
1466 }
1467 }
1468
1469 1 enc_tb = q;
1470 }
1471
1472 8423 threads_manual = !!av_dict_get(encoder_opts, "threads", NULL, 0);
1473
1474 8423 ret = av_dict_copy(&ost->enc->encoder_opts, encoder_opts, 0);
1475
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8423 times.
8423 if (ret < 0)
1476 goto fail;
1477 8423 ret = av_opt_set_dict2(ost->enc->enc_ctx, &encoder_opts, AV_OPT_SEARCH_CHILDREN);
1478
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8423 times.
8423 if (ret < 0) {
1479 av_log(ost, AV_LOG_ERROR, "Error applying encoder options: %s\n",
1480 av_err2str(ret));
1481 goto fail;
1482 }
1483
1484 8423 ret = check_avoptions(encoder_opts);
1485
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8423 times.
8423 if (ret < 0)
1486 goto fail;
1487
1488 // default to automatic thread count
1489
2/2
✓ Branch 0 taken 2909 times.
✓ Branch 1 taken 5514 times.
8423 if (!threads_manual)
1490 2909 ost->enc->enc_ctx->thread_count = 0;
1491 } else {
1492 908 ret = filter_codec_opts(o->g->codec_opts, AV_CODEC_ID_NONE, oc, st,
1493 NULL, &encoder_opts,
1494 &mux->enc_opts_used);
1495
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 908 times.
908 if (ret < 0)
1496 goto fail;
1497 }
1498
1499
1500
2/2
✓ Branch 0 taken 2121 times.
✓ Branch 1 taken 7210 times.
9331 if (o->bitexact) {
1501 2121 ost->bitexact = 1;
1502
2/2
✓ Branch 0 taken 6481 times.
✓ Branch 1 taken 729 times.
7210 } else if (ost->enc) {
1503 6481 ost->bitexact = !!(ost->enc->enc_ctx->flags & AV_CODEC_FLAG_BITEXACT);
1504 }
1505
1506
2/2
✓ Branch 0 taken 8423 times.
✓ Branch 1 taken 908 times.
9331 if (enc) {
1507 8423 ret = set_encoder_id(ost, enc);
1508
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8423 times.
8423 if (ret < 0)
1509 return ret;
1510 }
1511
1512 9331 opt_match_per_stream_str(ost, &o->time_bases, oc, st, &time_base);
1513
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 9327 times.
9331 if (time_base) {
1514 AVRational q;
1515
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 if (av_parse_ratio(&q, time_base, INT_MAX, 0, NULL) < 0 ||
1516
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) {
1517 av_log(ost, AV_LOG_FATAL, "Invalid time base: %s\n", time_base);
1518 ret = AVERROR(EINVAL);
1519 goto fail;
1520 }
1521 4 st->time_base = q;
1522 }
1523
1524 9331 ms->max_frames = INT64_MAX;
1525 9331 opt_match_per_stream_int64(ost, &o->max_frames, oc, st, &ms->max_frames);
1526
2/2
✓ Branch 0 taken 5474 times.
✓ Branch 1 taken 9325 times.
14799 for (int i = 0; i < o->max_frames.nb_opt; i++) {
1527 5474 char *p = o->max_frames.opt[i].specifier;
1528
4/4
✓ Branch 0 taken 169 times.
✓ Branch 1 taken 5305 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 163 times.
5474 if (!*p && type != AVMEDIA_TYPE_VIDEO) {
1529 6 av_log(ost, AV_LOG_WARNING, "Applying unspecific -frames to non video streams, maybe you meant -vframes ?\n");
1530 6 break;
1531 }
1532 }
1533
1534 9331 ms->copy_prior_start = -1;
1535 9331 opt_match_per_stream_int(ost, &o->copy_prior_start, oc, st, &ms->copy_prior_start);
1536 9331 opt_match_per_stream_str(ost, &o->bitstream_filters, oc, st, &bsfs);
1537
3/4
✓ Branch 0 taken 193 times.
✓ Branch 1 taken 9138 times.
✓ Branch 2 taken 193 times.
✗ Branch 3 not taken.
9331 if (bsfs && *bsfs) {
1538 193 ret = av_bsf_list_parse_str(bsfs, &ms->bsf_ctx);
1539
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 193 times.
193 if (ret < 0) {
1540 av_log(ost, AV_LOG_ERROR, "Error parsing bitstream filter sequence '%s': %s\n", bsfs, av_err2str(ret));
1541 goto fail;
1542 }
1543 }
1544
1545 9331 opt_match_per_stream_str(ost, &o->codec_tags, oc, st, &codec_tag);
1546
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9322 times.
9331 if (codec_tag) {
1547 9 uint32_t tag = strtol(codec_tag, &next, 0);
1548
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if (*next) {
1549 9 uint8_t buf[4] = { 0 };
1550
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 memcpy(buf, codec_tag, FFMIN(sizeof(buf), strlen(codec_tag)));
1551 9 tag = AV_RL32(buf);
1552 }
1553 9 ost->st->codecpar->codec_tag = tag;
1554 9 ms->par_in->codec_tag = tag;
1555
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7 times.
9 if (ost->enc)
1556 2 ost->enc->codec_tag = tag;
1557 }
1558
1559 9331 opt_match_per_stream_dbl(ost, &o->qscale, oc, st, &qscale);
1560
4/4
✓ Branch 0 taken 8423 times.
✓ Branch 1 taken 908 times.
✓ Branch 2 taken 276 times.
✓ Branch 3 taken 8147 times.
9331 if (ost->enc && qscale >= 0) {
1561 276 ost->enc->flags |= AV_CODEC_FLAG_QSCALE;
1562 276 ost->enc->global_quality = FF_QP2LAMBDA * qscale;
1563 }
1564
1565
2/2
✓ Branch 0 taken 9330 times.
✓ Branch 1 taken 1 times.
9331 if (ms->sch_idx >= 0) {
1566 9330 int max_muxing_queue_size = 128;
1567 9330 int muxing_queue_data_threshold = 50 * 1024 * 1024;
1568
1569 9330 opt_match_per_stream_int(ost, &o->max_muxing_queue_size, oc, st,
1570 &max_muxing_queue_size);
1571 9330 opt_match_per_stream_int(ost, &o->muxing_queue_data_threshold,
1572 oc, st, &muxing_queue_data_threshold);
1573
1574 9330 sch_mux_stream_buffering(mux->sch, mux->sch_idx, ms->sch_idx,
1575 max_muxing_queue_size, muxing_queue_data_threshold);
1576 }
1577
1578 9331 opt_match_per_stream_int(ost, &o->bits_per_raw_sample, oc, st,
1579 &ost->bits_per_raw_sample);
1580
1581 9331 opt_match_per_stream_int(ost, &o->fix_sub_duration_heartbeat,
1582 9331 oc, st, &ost->fix_sub_duration_heartbeat);
1583
1584
4/4
✓ Branch 0 taken 3301 times.
✓ Branch 1 taken 6030 times.
✓ Branch 2 taken 3149 times.
✓ Branch 3 taken 152 times.
9331 if (oc->oformat->flags & AVFMT_GLOBALHEADER && ost->enc)
1585 3149 ost->enc->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
1586
4/4
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 9291 times.
✓ Branch 2 taken 32 times.
✓ Branch 3 taken 8 times.
9331 if (oc->oformat->flags & AVFMT_FIXED_FRAMESIZE && ost->enc)
1587 32 ost->enc->flags2 |= AV_CODEC_FLAG2_FIXED_FRAME_SIZE;
1588
1589 9331 opt_match_per_stream_int(ost, &o->copy_initial_nonkeyframes,
1590 oc, st, &ms->copy_initial_nonkeyframes);
1591
4/4
✓ Branch 0 taken 7385 times.
✓ Branch 1 taken 1852 times.
✓ Branch 2 taken 81 times.
✓ Branch 3 taken 13 times.
9331 switch (type) {
1592 7385 case AVMEDIA_TYPE_VIDEO: ret = new_stream_video (mux, o, ost, &keep_pix_fmt, &vsync_method); break;
1593 1852 case AVMEDIA_TYPE_AUDIO: ret = new_stream_audio (mux, o, ost); break;
1594 81 case AVMEDIA_TYPE_SUBTITLE: ret = new_stream_subtitle (mux, o, ost); break;
1595 }
1596
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9331 times.
9331 if (ret < 0)
1597 goto fail;
1598
1599
4/4
✓ Branch 0 taken 8423 times.
✓ Branch 1 taken 908 times.
✓ Branch 2 taken 1493 times.
✓ Branch 3 taken 6930 times.
9331 if (ost->enc &&
1600
2/2
✓ Branch 0 taken 1451 times.
✓ Branch 1 taken 42 times.
1493 (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) {
1601 8381 ret = ost_bind_filter(mux, ms, ofilter, o, enc_tb, vsync_method,
1602 keep_pix_fmt, autoscale, threads_manual, vs, &src);
1603
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8380 times.
8381 if (ret < 0)
1604 1 goto fail;
1605
2/2
✓ Branch 0 taken 949 times.
✓ Branch 1 taken 1 times.
950 } else if (ost->ist) {
1606 949 ret = ist_use(ost->ist, !!ost->enc, NULL, &src);
1607
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 949 times.
949 if (ret < 0) {
1608 av_log(ost, AV_LOG_ERROR,
1609 "Error binding an input stream\n");
1610 goto fail;
1611 }
1612 949 ms->sch_idx_src = src.idx;
1613
1614 // src refers to a decoder for transcoding, demux stream otherwise
1615
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 907 times.
949 if (ost->enc) {
1616 42 ret = sch_connect(mux->sch,
1617 42 src, SCH_ENC(ms->sch_idx_enc));
1618
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (ret < 0)
1619 goto fail;
1620 42 src = SCH_ENC(ms->sch_idx_enc);
1621 }
1622 }
1623
1624
2/2
✓ Branch 0 taken 9329 times.
✓ Branch 1 taken 1 times.
9330 if (src.type != SCH_NODE_TYPE_NONE) {
1625 9329 ret = sch_connect(mux->sch,
1626 9329 src, SCH_MSTREAM(mux->sch_idx, ms->sch_idx));
1627
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9329 times.
9329 if (ret < 0)
1628 goto fail;
1629 } else {
1630 // only attachment streams don't have a source
1631
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);
1632 }
1633
1634
4/4
✓ Branch 0 taken 7923 times.
✓ Branch 1 taken 1407 times.
✓ Branch 2 taken 907 times.
✓ Branch 3 taken 7016 times.
9330 if (ost->ist && !ost->enc) {
1635 907 ret = streamcopy_init(o, mux, ost, &encoder_opts);
1636
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 907 times.
907 if (ret < 0)
1637 goto fail;
1638 }
1639
1640 // copy estimated duration as a hint to the muxer
1641
4/4
✓ Branch 0 taken 7923 times.
✓ Branch 1 taken 1407 times.
✓ Branch 2 taken 6209 times.
✓ Branch 3 taken 1714 times.
9330 if (ost->ist && ost->ist->st->duration > 0) {
1642 6209 ms->stream_duration = ist->st->duration;
1643 6209 ms->stream_duration_tb = ist->st->time_base;
1644 }
1645
1646
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 9329 times.
9330 if (post)
1647 1 *post = ost;
1648
1649 9330 ret = 0;
1650
1651 9331 fail:
1652 9331 av_dict_free(&encoder_opts);
1653
1654 9331 return ret;
1655 }
1656
1657 7155 static int map_auto_video(Muxer *mux, const OptionsContext *o)
1658 {
1659 7155 AVFormatContext *oc = mux->fc;
1660 7155 InputStreamGroup *best_istg = NULL;
1661 7155 InputStream *best_ist = NULL;
1662 7155 int64_t best_score = 0;
1663 int qcr;
1664
1665 /* video: highest resolution */
1666
2/2
✓ Branch 1 taken 780 times.
✓ Branch 2 taken 6375 times.
7155 if (av_guess_codec(oc->oformat, NULL, oc->url, NULL, AVMEDIA_TYPE_VIDEO) == AV_CODEC_ID_NONE)
1667 780 return 0;
1668
1669 6375 qcr = avformat_query_codec(oc->oformat, oc->oformat->video_codec, 0);
1670
2/2
✓ Branch 0 taken 6416 times.
✓ Branch 1 taken 6375 times.
12791 for (int j = 0; j < nb_input_files; j++) {
1671 6416 InputFile *ifile = input_files[j];
1672 6416 InputStreamGroup *file_best_istg = NULL;
1673 6416 InputStream *file_best_ist = NULL;
1674 6416 int64_t file_best_score = 0;
1675
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 6416 times.
6438 for (int i = 0; i < ifile->nb_stream_groups; i++) {
1676 22 InputStreamGroup *istg = ifile->stream_groups[i];
1677 22 int64_t score = 0;
1678
1679
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 1 times.
22 if (!istg->fg)
1680 21 continue;
1681
1682
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 for (int j = 0; j < istg->stg->nb_streams; j++) {
1683 1 AVStream *st = istg->stg->streams[j];
1684
1685
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (st->event_flags & AVSTREAM_EVENT_FLAG_NEW_PACKETS) {
1686 1 score = 100000000;
1687 1 break;
1688 }
1689 }
1690
1691
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 switch (istg->stg->type) {
1692 1 case AV_STREAM_GROUP_PARAMS_TILE_GRID: {
1693 1 const AVStreamGroupTileGrid *tg = istg->stg->params.tile_grid;
1694 2 score += tg->width * (int64_t)tg->height
1695
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 + 5000000*!!(istg->stg->disposition & AV_DISPOSITION_DEFAULT);
1696 1 break;
1697 }
1698 default:
1699 continue;
1700 }
1701
1702
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (score > file_best_score) {
1703 1 file_best_score = score;
1704 1 file_best_istg = istg;
1705 }
1706 }
1707
2/2
✓ Branch 0 taken 6701 times.
✓ Branch 1 taken 6416 times.
13117 for (int i = 0; i < ifile->nb_streams; i++) {
1708 6701 InputStream *ist = ifile->streams[i];
1709 6701 const AVCodecDescriptor *desc = avcodec_descriptor_get(ist->st->codecpar->codec_id);
1710 int64_t score;
1711
1712
2/2
✓ Branch 0 taken 6700 times.
✓ Branch 1 taken 1 times.
6701 if (ist->user_set_discard == AVDISCARD_ALL ||
1713
3/4
✓ Branch 0 taken 5932 times.
✓ Branch 1 taken 768 times.
✓ Branch 2 taken 5932 times.
✗ Branch 3 not taken.
6700 ist->st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO ||
1714
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5932 times.
5932 (desc && (desc->props & AV_CODEC_PROP_ENHANCEMENT)))
1715 769 continue;
1716
1717 11864 score = ist->st->codecpar->width * (int64_t)ist->st->codecpar->height
1718
2/2
✓ Branch 0 taken 5930 times.
✓ Branch 1 taken 2 times.
5932 + 100000000 * !!(ist->st->event_flags & AVSTREAM_EVENT_FLAG_NEW_PACKETS)
1719
2/2
✓ Branch 0 taken 552 times.
✓ Branch 1 taken 5380 times.
5932 + 5000000*!!(ist->st->disposition & AV_DISPOSITION_DEFAULT);
1720
3/4
✓ Branch 0 taken 5932 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 5923 times.
5932 if((qcr!=MKTAG('A', 'P', 'I', 'C')) && (ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC))
1721 9 score = 1;
1722
1723
2/2
✓ Branch 0 taken 5927 times.
✓ Branch 1 taken 5 times.
5932 if (score > file_best_score) {
1724
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5927 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
5927 if((qcr==MKTAG('A', 'P', 'I', 'C')) && !(ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC))
1725 continue;
1726 5927 file_best_score = score;
1727 5927 file_best_ist = ist;
1728 5927 file_best_istg = NULL;
1729 }
1730 }
1731
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6415 times.
6416 if (file_best_istg) {
1732
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 file_best_score -= 5000000*!!(file_best_istg->stg->disposition & AV_DISPOSITION_DEFAULT);
1733
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (file_best_score > best_score) {
1734 1 best_score = file_best_score;
1735 1 best_istg = file_best_istg;
1736 1 best_ist = NULL;
1737 }
1738 }
1739
2/2
✓ Branch 0 taken 5927 times.
✓ Branch 1 taken 489 times.
6416 if (file_best_ist) {
1740
1/2
✓ Branch 0 taken 5927 times.
✗ Branch 1 not taken.
5927 if((qcr == MKTAG('A', 'P', 'I', 'C')) ||
1741
2/2
✓ Branch 0 taken 5919 times.
✓ Branch 1 taken 8 times.
5927 !(file_best_ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC))
1742
2/2
✓ Branch 0 taken 552 times.
✓ Branch 1 taken 5367 times.
5919 file_best_score -= 5000000*!!(file_best_ist->st->disposition & AV_DISPOSITION_DEFAULT);
1743
1/2
✓ Branch 0 taken 5927 times.
✗ Branch 1 not taken.
5927 if (file_best_score > best_score) {
1744 5927 best_score = file_best_score;
1745 5927 best_ist = file_best_ist;
1746 5927 best_istg = NULL;
1747 }
1748 }
1749 }
1750
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6374 times.
6375 if (best_istg) {
1751 1 FilterGraph *fg = best_istg->fg;
1752 1 OutputFilter *ofilter = fg->outputs[0];
1753
1754
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 av_assert0(fg->nb_outputs == 1);
1755 1 av_log(mux, AV_LOG_VERBOSE, "Creating output stream from stream group derived complex filtergraph %d.\n", fg->index);
1756
1757 1 return ost_add(mux, o, AVMEDIA_TYPE_VIDEO, NULL, ofilter, NULL, NULL);
1758 }
1759
2/2
✓ Branch 0 taken 5927 times.
✓ Branch 1 taken 447 times.
6374 if (best_ist)
1760 5927 return ost_add(mux, o, AVMEDIA_TYPE_VIDEO, best_ist, NULL, NULL, NULL);
1761
1762 447 return 0;
1763 }
1764
1765 8391 static int map_auto_audio(Muxer *mux, const OptionsContext *o)
1766 {
1767 8391 AVFormatContext *oc = mux->fc;
1768 8391 InputStream *best_ist = NULL;
1769 8391 int best_score = 0;
1770
1771 /* audio: most channels */
1772
2/2
✓ Branch 1 taken 1994 times.
✓ Branch 2 taken 6397 times.
8391 if (av_guess_codec(oc->oformat, NULL, oc->url, NULL, AVMEDIA_TYPE_AUDIO) == AV_CODEC_ID_NONE)
1773 1994 return 0;
1774
1775
2/2
✓ Branch 0 taken 6364 times.
✓ Branch 1 taken 6397 times.
12761 for (int j = 0; j < nb_input_files; j++) {
1776 6364 InputFile *ifile = input_files[j];
1777 6364 InputStream *file_best_ist = NULL;
1778 6364 int file_best_score = 0;
1779
2/2
✓ Branch 0 taken 6572 times.
✓ Branch 1 taken 6364 times.
12936 for (int i = 0; i < ifile->nb_streams; i++) {
1780 6572 InputStream *ist = ifile->streams[i];
1781 int score;
1782
1783
2/2
✓ Branch 0 taken 6571 times.
✓ Branch 1 taken 1 times.
6572 if (ist->user_set_discard == AVDISCARD_ALL ||
1784
2/2
✓ Branch 0 taken 5083 times.
✓ Branch 1 taken 1488 times.
6571 ist->st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
1785 5084 continue;
1786
1787 2976 score = ist->st->codecpar->ch_layout.nb_channels
1788
2/2
✓ Branch 0 taken 1430 times.
✓ Branch 1 taken 58 times.
1488 + 100000000 * !!(ist->st->event_flags & AVSTREAM_EVENT_FLAG_NEW_PACKETS)
1789
2/2
✓ Branch 0 taken 216 times.
✓ Branch 1 taken 1272 times.
1488 + 5000000*!!(ist->st->disposition & AV_DISPOSITION_DEFAULT);
1790
2/2
✓ Branch 0 taken 1478 times.
✓ Branch 1 taken 10 times.
1488 if (score > file_best_score) {
1791 1478 file_best_score = score;
1792 1478 file_best_ist = ist;
1793 }
1794 }
1795
2/2
✓ Branch 0 taken 1478 times.
✓ Branch 1 taken 4886 times.
6364 if (file_best_ist) {
1796
2/2
✓ Branch 0 taken 216 times.
✓ Branch 1 taken 1262 times.
1478 file_best_score -= 5000000*!!(file_best_ist->st->disposition & AV_DISPOSITION_DEFAULT);
1797
1/2
✓ Branch 0 taken 1478 times.
✗ Branch 1 not taken.
1478 if (file_best_score > best_score) {
1798 1478 best_score = file_best_score;
1799 1478 best_ist = file_best_ist;
1800 }
1801 }
1802 }
1803
2/2
✓ Branch 0 taken 1478 times.
✓ Branch 1 taken 4919 times.
6397 if (best_ist)
1804 1478 return ost_add(mux, o, AVMEDIA_TYPE_AUDIO, best_ist, NULL, NULL, NULL);
1805
1806 4919 return 0;
1807 }
1808
1809 8559 static int map_auto_subtitle(Muxer *mux, const OptionsContext *o)
1810 {
1811 8559 AVFormatContext *oc = mux->fc;
1812 8559 const char *subtitle_codec_name = NULL;
1813
1814 /* subtitles: pick first */
1815 8559 subtitle_codec_name = opt_match_per_type_str(&o->codec_names, 's');
1816
4/4
✓ Branch 1 taken 8491 times.
✓ Branch 2 taken 68 times.
✓ Branch 3 taken 8483 times.
✓ Branch 4 taken 8 times.
8559 if (!avcodec_find_encoder(oc->oformat->subtitle_codec) && !subtitle_codec_name)
1817 8483 return 0;
1818
1819
2/2
✓ Branch 2 taken 90 times.
✓ Branch 3 taken 25 times.
115 for (InputStream *ist = ist_iter(NULL); ist; ist = ist_iter(ist))
1820
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 39 times.
90 if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
1821 AVCodecDescriptor const *input_descriptor =
1822 51 avcodec_descriptor_get(ist->st->codecpar->codec_id);
1823 51 AVCodecDescriptor const *output_descriptor = NULL;
1824 AVCodec const *output_codec =
1825 51 avcodec_find_encoder(oc->oformat->subtitle_codec);
1826 51 int input_props = 0, output_props = 0;
1827
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
51 if (ist->user_set_discard == AVDISCARD_ALL)
1828 continue;
1829
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 8 times.
51 if (output_codec)
1830 43 output_descriptor = avcodec_descriptor_get(output_codec->id);
1831
1/2
✓ Branch 0 taken 51 times.
✗ Branch 1 not taken.
51 if (input_descriptor)
1832 51 input_props = input_descriptor->props & (AV_CODEC_PROP_TEXT_SUB | AV_CODEC_PROP_BITMAP_SUB);
1833
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 8 times.
51 if (output_descriptor)
1834 43 output_props = output_descriptor->props & (AV_CODEC_PROP_TEXT_SUB | AV_CODEC_PROP_BITMAP_SUB);
1835
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 17 times.
51 if (subtitle_codec_name ||
1836
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
34 input_props & output_props ||
1837 // Map dvb teletext which has neither property to any output subtitle encoder
1838 input_descriptor && output_descriptor &&
1839 (!input_descriptor->props ||
1840 !output_descriptor->props)) {
1841 51 return ost_add(mux, o, AVMEDIA_TYPE_SUBTITLE, ist, NULL, NULL, NULL);
1842 }
1843 }
1844
1845 25 return 0;
1846 }
1847
1848 8560 static int map_auto_data(Muxer *mux, const OptionsContext *o)
1849 {
1850 8560 AVFormatContext *oc = mux->fc;
1851 /* Data only if codec id match */
1852 8560 enum AVCodecID codec_id = av_guess_codec(oc->oformat, NULL, oc->url, NULL, AVMEDIA_TYPE_DATA);
1853
1854
1/2
✓ Branch 0 taken 8560 times.
✗ Branch 1 not taken.
8560 if (codec_id == AV_CODEC_ID_NONE)
1855 8560 return 0;
1856
1857 for (InputStream *ist = ist_iter(NULL); ist; ist = ist_iter(ist)) {
1858 if (ist->user_set_discard == AVDISCARD_ALL)
1859 continue;
1860 if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_DATA &&
1861 ist->st->codecpar->codec_id == codec_id) {
1862 int ret = ost_add(mux, o, AVMEDIA_TYPE_DATA, ist, NULL, NULL, NULL);
1863 if (ret < 0)
1864 return ret;
1865 }
1866 }
1867
1868 return 0;
1869 }
1870
1871 552 static int map_manual(Muxer *mux, const OptionsContext *o, const StreamMap *map)
1872 {
1873 InputStream *ist;
1874 int ret;
1875
1876
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 552 times.
552 if (map->disabled)
1877 return 0;
1878
1879
2/2
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 468 times.
552 if (map->linklabel) {
1880 FilterGraph *fg;
1881 84 OutputFilter *ofilter = NULL;
1882 int j, k;
1883
1884
1/2
✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
84 for (j = 0; j < nb_filtergraphs; j++) {
1885 84 fg = filtergraphs[j];
1886
1/2
✓ Branch 0 taken 281 times.
✗ Branch 1 not taken.
281 for (k = 0; k < fg->nb_outputs; k++) {
1887 281 const char *linklabel = fg->outputs[k]->linklabel;
1888
4/4
✓ Branch 0 taken 118 times.
✓ Branch 1 taken 163 times.
✓ Branch 2 taken 84 times.
✓ Branch 3 taken 34 times.
281 if (linklabel && !strcmp(linklabel, map->linklabel)) {
1889 84 ofilter = fg->outputs[k];
1890 84 goto loop_end;
1891 }
1892 }
1893 }
1894 loop_end:
1895
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
84 if (!ofilter) {
1896 av_log(mux, AV_LOG_FATAL, "Output with label '%s' does not exist "
1897 "in any defined filter graph, or was already used elsewhere.\n", map->linklabel);
1898 return AVERROR(EINVAL);
1899 }
1900
1901 84 av_log(mux, AV_LOG_VERBOSE, "Creating output stream from an explicitly "
1902 84 "mapped complex filtergraph %d, output [%s]\n", fg->index, map->linklabel);
1903
1904 84 ret = ost_add(mux, o, ofilter->type, NULL, ofilter, NULL, NULL);
1905
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
84 if (ret < 0)
1906 return ret;
1907 } else {
1908 936 const ViewSpecifier *vs = map->vs.type == VIEW_SPECIFIER_TYPE_NONE ?
1909
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 454 times.
468 NULL : &map->vs;
1910
1911 468 ist = input_files[map->file_index]->streams[map->stream_index];
1912
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 468 times.
468 if (ist->user_set_discard == AVDISCARD_ALL) {
1913 av_log(mux, AV_LOG_FATAL, "Stream #%d:%d is disabled and cannot be mapped.\n",
1914 map->file_index, map->stream_index);
1915 return AVERROR(EINVAL);
1916 }
1917
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 468 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
468 if(o->subtitle_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE)
1918 return 0;
1919
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 468 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
468 if(o-> audio_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
1920 return 0;
1921
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 467 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
468 if(o-> video_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
1922 return 0;
1923
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 468 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
468 if(o-> data_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_DATA)
1924 return 0;
1925
1926
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 468 times.
468 if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_UNKNOWN &&
1927 !copy_unknown_streams) {
1928 av_log(mux, ignore_unknown_streams ? AV_LOG_WARNING : AV_LOG_FATAL,
1929 "Cannot map stream #%d:%d - unsupported type.\n",
1930 map->file_index, map->stream_index);
1931 if (!ignore_unknown_streams) {
1932 av_log(mux, AV_LOG_FATAL,
1933 "If you want unsupported types ignored instead "
1934 "of failing, please use the -ignore_unknown option\n"
1935 "If you want them copied, please use -copy_unknown\n");
1936 return AVERROR(EINVAL);
1937 }
1938 return 0;
1939 }
1940
1941
3/4
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 454 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 14 times.
468 if (vs && ist->st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO) {
1942 av_log(mux, AV_LOG_ERROR,
1943 "View specifier given for mapping a %s input stream\n",
1944 av_get_media_type_string(ist->st->codecpar->codec_type));
1945 return AVERROR(EINVAL);
1946 }
1947
1948 468 ret = ost_add(mux, o, ist->st->codecpar->codec_type, ist, NULL, vs, NULL);
1949
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 468 times.
468 if (ret < 0)
1950 return ret;
1951 }
1952
1953 552 return 0;
1954 }
1955
1956 8821 static int of_add_attachments(Muxer *mux, const OptionsContext *o)
1957 {
1958 MuxStream *ms;
1959 OutputStream *ost;
1960 int err;
1961
1962
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8821 times.
8822 for (int i = 0; i < o->nb_attachments; i++) {
1963 AVIOContext *pb;
1964 uint8_t *attachment;
1965 char *attachment_filename;
1966 const char *p;
1967 int64_t len;
1968
1969
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) {
1970 av_log(mux, AV_LOG_FATAL, "Could not open attachment file %s.\n",
1971 o->attachments[i]);
1972 return err;
1973 }
1974
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if ((len = avio_size(pb)) <= 0) {
1975 av_log(mux, AV_LOG_FATAL, "Could not get size of the attachment %s.\n",
1976 o->attachments[i]);
1977 err = len ? len : AVERROR_INVALIDDATA;
1978 goto read_fail;
1979 }
1980
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (len > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) {
1981 av_log(mux, AV_LOG_FATAL, "Attachment %s too large.\n",
1982 o->attachments[i]);
1983 err = AVERROR(ERANGE);
1984 goto read_fail;
1985 }
1986
1987 1 attachment = av_malloc(len + AV_INPUT_BUFFER_PADDING_SIZE);
1988
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!attachment) {
1989 err = AVERROR(ENOMEM);
1990 goto read_fail;
1991 }
1992
1993 1 err = avio_read(pb, attachment, len);
1994
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (err < 0)
1995 av_log(mux, AV_LOG_FATAL, "Error reading attachment file %s: %s\n",
1996 o->attachments[i], av_err2str(err));
1997
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 else if (err != len) {
1998 av_log(mux, AV_LOG_FATAL, "Could not read all %"PRId64" bytes for "
1999 "attachment file %s\n", len, o->attachments[i]);
2000 err = AVERROR(EIO);
2001 }
2002
2003 1 read_fail:
2004 1 avio_closep(&pb);
2005
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (err < 0)
2006 return err;
2007
2008 1 memset(attachment + len, 0, AV_INPUT_BUFFER_PADDING_SIZE);
2009
2010 1 av_log(mux, AV_LOG_VERBOSE, "Creating attachment stream from file %s\n",
2011 1 o->attachments[i]);
2012
2013 1 attachment_filename = av_strdup(o->attachments[i]);
2014
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!attachment_filename) {
2015 av_free(attachment);
2016 return AVERROR(ENOMEM);
2017 }
2018
2019 1 err = ost_add(mux, o, AVMEDIA_TYPE_ATTACHMENT, NULL, NULL, NULL, &ost);
2020
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (err < 0) {
2021 av_free(attachment_filename);
2022 av_freep(&attachment);
2023 return err;
2024 }
2025
2026 1 ms = ms_from_ost(ost);
2027
2028 1 ost->attachment_filename = attachment_filename;
2029 1 ms->par_in->extradata = attachment;
2030 1 ms->par_in->extradata_size = len;
2031
2032 1 p = strrchr(o->attachments[i], '/');
2033
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);
2034 }
2035
2036 8821 return 0;
2037 }
2038
2039 8822 static int create_streams(Muxer *mux, const OptionsContext *o)
2040 {
2041 static int (* const map_func[])(Muxer *mux, const OptionsContext *o) = {
2042 [AVMEDIA_TYPE_VIDEO] = map_auto_video,
2043 [AVMEDIA_TYPE_AUDIO] = map_auto_audio,
2044 [AVMEDIA_TYPE_SUBTITLE] = map_auto_subtitle,
2045 [AVMEDIA_TYPE_DATA] = map_auto_data,
2046 };
2047
2048 8822 AVFormatContext *oc = mux->fc;
2049
2050 8822 int auto_disable =
2051 8822 o->video_disable * (1 << AVMEDIA_TYPE_VIDEO) |
2052 8822 o->audio_disable * (1 << AVMEDIA_TYPE_AUDIO) |
2053 8822 o->subtitle_disable * (1 << AVMEDIA_TYPE_SUBTITLE) |
2054 8822 o->data_disable * (1 << AVMEDIA_TYPE_DATA);
2055
2056 int ret;
2057
2058 /* create streams for all unlabeled output pads */
2059
2/2
✓ Branch 0 taken 1278 times.
✓ Branch 1 taken 8822 times.
10100 for (int i = 0; i < nb_filtergraphs; i++) {
2060 1278 FilterGraph *fg = filtergraphs[i];
2061
2/2
✓ Branch 0 taken 1417 times.
✓ Branch 1 taken 1278 times.
2695 for (int j = 0; j < fg->nb_outputs; j++) {
2062 1417 OutputFilter *ofilter = fg->outputs[j];
2063
2064
4/4
✓ Branch 0 taken 1324 times.
✓ Branch 1 taken 93 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 1321 times.
1417 if (ofilter->linklabel || ofilter->bound)
2065 96 continue;
2066
2067 1321 auto_disable |= 1 << ofilter->type;
2068
2069 1321 av_log(mux, AV_LOG_VERBOSE, "Creating output stream from unlabeled "
2070 "output of complex filtergraph %d.", fg->index);
2071
1/2
✓ Branch 0 taken 1321 times.
✗ Branch 1 not taken.
1321 if (!o->nb_stream_maps)
2072 1321 av_log(mux, AV_LOG_VERBOSE, " This overrides automatic %s mapping.",
2073 av_get_media_type_string(ofilter->type));
2074 1321 av_log(mux, AV_LOG_VERBOSE, "\n");
2075
2076 1321 ret = ost_add(mux, o, ofilter->type, NULL, ofilter, NULL, NULL);
2077
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1321 times.
1321 if (ret < 0)
2078 return ret;
2079 }
2080 }
2081
2082
2/2
✓ Branch 0 taken 8561 times.
✓ Branch 1 taken 261 times.
8822 if (!o->nb_stream_maps) {
2083 8561 av_log(mux, AV_LOG_VERBOSE, "No explicit maps, mapping streams automatically...\n");
2084
2085 /* pick the "best" stream of each type */
2086
2/2
✓ Branch 0 taken 34242 times.
✓ Branch 1 taken 8560 times.
42802 for (int i = 0; i < FF_ARRAY_ELEMS(map_func); i++) {
2087
3/4
✓ Branch 0 taken 34242 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1577 times.
✓ Branch 3 taken 32665 times.
34242 if (!map_func[i] || auto_disable & (1 << i))
2088 1577 continue;
2089 32665 ret = map_func[i](mux, o);
2090
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 32664 times.
32665 if (ret < 0)
2091 1 return ret;
2092 }
2093 } else {
2094 261 av_log(mux, AV_LOG_VERBOSE, "Adding streams from explicit maps...\n");
2095
2096
2/2
✓ Branch 0 taken 552 times.
✓ Branch 1 taken 261 times.
813 for (int i = 0; i < o->nb_stream_maps; i++) {
2097 552 ret = map_manual(mux, o, &o->stream_maps[i]);
2098
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 552 times.
552 if (ret < 0)
2099 return ret;
2100 }
2101 }
2102
2103 8821 ret = of_add_attachments(mux, o);
2104
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8821 times.
8821 if (ret < 0)
2105 return ret;
2106
2107 // setup fix_sub_duration_heartbeat mappings
2108
2/2
✓ Branch 0 taken 9330 times.
✓ Branch 1 taken 8821 times.
18151 for (unsigned i = 0; i < oc->nb_streams; i++) {
2109 9330 MuxStream *src = ms_from_ost(mux->of.streams[i]);
2110
2111
2/2
✓ Branch 0 taken 9329 times.
✓ Branch 1 taken 1 times.
9330 if (!src->ost.fix_sub_duration_heartbeat)
2112 9329 continue;
2113
2114
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 for (unsigned j = 0; j < oc->nb_streams; j++) {
2115 2 MuxStream *dst = ms_from_ost(mux->of.streams[j]);
2116
2117
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 ||
2118
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)
2119 1 continue;
2120
2121 1 ret = sch_mux_sub_heartbeat_add(mux->sch, mux->sch_idx, src->sch_idx,
2122 1 dst->sch_idx_src);
2123
2124 }
2125 }
2126
2127 // handle -apad
2128
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 8817 times.
8821 if (o->shortest) {
2129 4 int have_video = 0;
2130
2131
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 for (unsigned i = 0; i < mux->of.nb_streams; i++)
2132
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (mux->of.streams[i]->type == AVMEDIA_TYPE_VIDEO) {
2133 4 have_video = 1;
2134 4 break;
2135 }
2136
2137
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++) {
2138 8 MuxStream *ms = ms_from_ost(mux->of.streams[i]);
2139 8 OutputFilter *ofilter = ms->ost.filter;
2140
2141
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)
2142 8 continue;
2143
2144 ofilter->apad = av_strdup(ms->apad);
2145 if (!ofilter->apad)
2146 return AVERROR(ENOMEM);
2147 }
2148 }
2149
2/2
✓ Branch 0 taken 9330 times.
✓ Branch 1 taken 8821 times.
18151 for (unsigned i = 0; i < mux->of.nb_streams; i++) {
2150 9330 MuxStream *ms = ms_from_ost(mux->of.streams[i]);
2151 9330 ms->apad = NULL;
2152 }
2153
2154
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8821 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8821 if (!oc->nb_streams && !(oc->oformat->flags & AVFMT_NOSTREAMS)) {
2155 av_dump_format(oc, nb_output_files - 1, oc->url, 1);
2156 av_log(mux, AV_LOG_ERROR, "Output file does not contain any stream\n");
2157 return AVERROR(EINVAL);
2158 }
2159
2160 8821 return check_stereo3d_leftovers(mux, o);
2161 }
2162
2163 8818 static int setup_sync_queues(Muxer *mux, AVFormatContext *oc,
2164 int64_t buf_size_us, int shortest)
2165 {
2166 8818 OutputFile *of = &mux->of;
2167 8818 int nb_av_enc = 0, nb_audio_fs = 0, nb_interleaved = 0;
2168 8818 int limit_frames = 0, limit_frames_av_enc = 0;
2169
2170 #define IS_AV_ENC(ost, type) \
2171 (ost->enc && (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO))
2172 #define IS_INTERLEAVED(type) (type != AVMEDIA_TYPE_ATTACHMENT)
2173
2174
2/2
✓ Branch 0 taken 9327 times.
✓ Branch 1 taken 8818 times.
18145 for (int i = 0; i < oc->nb_streams; i++) {
2175 9327 OutputStream *ost = of->streams[i];
2176 9327 MuxStream *ms = ms_from_ost(ost);
2177 9327 enum AVMediaType type = ost->type;
2178
2179 9327 ms->sq_idx_mux = -1;
2180
2181 9327 nb_interleaved += IS_INTERLEAVED(type);
2182
6/6
✓ Branch 0 taken 8421 times.
✓ Branch 1 taken 906 times.
✓ Branch 2 taken 1491 times.
✓ Branch 3 taken 6930 times.
✓ Branch 4 taken 1449 times.
✓ Branch 5 taken 42 times.
9327 nb_av_enc += IS_AV_ENC(ost, type);
2183
4/4
✓ Branch 0 taken 8421 times.
✓ Branch 1 taken 906 times.
✓ Branch 2 taken 1449 times.
✓ Branch 3 taken 6972 times.
10776 nb_audio_fs += (ost->enc && type == AVMEDIA_TYPE_AUDIO &&
2184
2/2
✓ Branch 0 taken 1228 times.
✓ Branch 1 taken 221 times.
1449 (!(ost->enc->enc_ctx->codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE) ||
2185
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1228 times.
1228 (ost->enc->flags2 & AV_CODEC_FLAG2_FIXED_FRAME_SIZE)));
2186
2187 9327 limit_frames |= ms->max_frames < INT64_MAX;
2188
7/8
✓ Branch 0 taken 3136 times.
✓ Branch 1 taken 6191 times.
✓ Branch 2 taken 3091 times.
✓ Branch 3 taken 45 times.
✓ Branch 4 taken 38 times.
✓ Branch 5 taken 3053 times.
✓ Branch 6 taken 38 times.
✗ Branch 7 not taken.
9327 limit_frames_av_enc |= (ms->max_frames < INT64_MAX) && IS_AV_ENC(ost, type);
2189 }
2190
2191
7/8
✓ Branch 0 taken 261 times.
✓ Branch 1 taken 8557 times.
✓ Branch 2 taken 257 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 8814 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5542 times.
✓ Branch 7 taken 160 times.
14520 if (!((nb_interleaved > 1 && shortest) ||
2192
2/2
✓ Branch 0 taken 5702 times.
✓ Branch 1 taken 3112 times.
8814 (nb_interleaved > 0 && limit_frames) ||
2193 nb_audio_fs))
2194 5542 return 0;
2195
2196 /* we use a sync queue before encoding when:
2197 * - 'shortest' is in effect and we have two or more encoded audio/video
2198 * streams
2199 * - at least one encoded audio/video stream is frame-limited, since
2200 * that has similar semantics to 'shortest'
2201 * - at least one audio encoder requires constant frame sizes
2202 *
2203 * Note that encoding sync queues are handled in the scheduler, because
2204 * different encoders run in different threads and need external
2205 * synchronization, while muxer sync queues can be handled inside the muxer
2206 */
2207
8/8
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3272 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 185 times.
✓ Branch 5 taken 3090 times.
✓ Branch 6 taken 162 times.
✓ Branch 7 taken 23 times.
3276 if ((shortest && nb_av_enc > 1) || limit_frames_av_enc || nb_audio_fs) {
2208 int sq_idx, ret;
2209
2210 3253 sq_idx = sch_add_sq_enc(mux->sch, buf_size_us, mux);
2211
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3253 times.
3253 if (sq_idx < 0)
2212 return sq_idx;
2213
2214
2/2
✓ Branch 0 taken 3326 times.
✓ Branch 1 taken 3253 times.
6579 for (int i = 0; i < oc->nb_streams; i++) {
2215 3326 OutputStream *ost = of->streams[i];
2216 3326 MuxStream *ms = ms_from_ost(ost);
2217 3326 enum AVMediaType type = ost->type;
2218
2219
5/6
✓ Branch 0 taken 3319 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 249 times.
✓ Branch 3 taken 3070 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 249 times.
3326 if (!IS_AV_ENC(ost, type))
2220 7 continue;
2221
2222 3319 ret = sch_sq_add_enc(mux->sch, sq_idx, ms->sch_idx_enc,
2223
2/2
✓ Branch 0 taken 3091 times.
✓ Branch 1 taken 224 times.
3315 shortest || ms->max_frames < INT64_MAX,
2224
2/2
✓ Branch 0 taken 3315 times.
✓ Branch 1 taken 4 times.
3319 ms->max_frames);
2225
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3319 times.
3319 if (ret < 0)
2226 return ret;
2227 }
2228 }
2229
2230 /* if there are any additional interleaved streams, then ALL the streams
2231 * are also synchronized before sending them to the muxer */
2232
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 3249 times.
3276 if (nb_interleaved > nb_av_enc) {
2233 27 mux->sq_mux = sq_alloc(SYNC_QUEUE_PACKETS, buf_size_us, mux);
2234
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (!mux->sq_mux)
2235 return AVERROR(ENOMEM);
2236
2237 27 mux->sq_pkt = av_packet_alloc();
2238
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (!mux->sq_pkt)
2239 return AVERROR(ENOMEM);
2240
2241
2/2
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 27 times.
88 for (int i = 0; i < oc->nb_streams; i++) {
2242 61 OutputStream *ost = of->streams[i];
2243 61 MuxStream *ms = ms_from_ost(ost);
2244 61 enum AVMediaType type = ost->type;
2245
2246
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 if (!IS_INTERLEAVED(type))
2247 continue;
2248
2249
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 6 times.
116 ms->sq_idx_mux = sq_add_stream(mux->sq_mux,
2250
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 10 times.
55 shortest || ms->max_frames < INT64_MAX);
2251
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 if (ms->sq_idx_mux < 0)
2252 return ms->sq_idx_mux;
2253
2254
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 16 times.
61 if (ms->max_frames != INT64_MAX)
2255 45 sq_limit_frames(mux->sq_mux, ms->sq_idx_mux, ms->max_frames);
2256 }
2257 }
2258
2259 #undef IS_AV_ENC
2260 #undef IS_INTERLEAVED
2261
2262 3276 return 0;
2263 }
2264
2265 14 static int of_parse_iamf_audio_element_layers(Muxer *mux, AVStreamGroup *stg, char *ptr)
2266 {
2267 14 AVIAMFAudioElement *audio_element = stg->params.iamf_audio_element;
2268 14 AVDictionary *dict = NULL;
2269 const char *token;
2270 14 int ret = 0;
2271
2272 14 audio_element->demixing_info =
2273 14 av_iamf_param_definition_alloc(AV_IAMF_PARAMETER_DEFINITION_DEMIXING, 1, NULL);
2274 14 audio_element->recon_gain_info =
2275 14 av_iamf_param_definition_alloc(AV_IAMF_PARAMETER_DEFINITION_RECON_GAIN, 1, NULL);
2276
2277
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 if (!audio_element->demixing_info ||
2278
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 !audio_element->recon_gain_info)
2279 return AVERROR(ENOMEM);
2280
2281 /* process manually set layers and parameters */
2282 14 token = av_strtok(NULL, ",", &ptr);
2283
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 14 times.
64 while (token) {
2284 const AVDictionaryEntry *e;
2285 50 int demixing = 0, recon_gain = 0;
2286 50 int layer = 0;
2287
2288
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 2 times.
50 if (ptr)
2289 48 ptr += strspn(ptr, " \n\t\r");
2290
2/2
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 20 times.
50 if (av_strstart(token, "layer=", &token))
2291 30 layer = 1;
2292
2/2
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 10 times.
20 else if (av_strstart(token, "demixing=", &token))
2293 10 demixing = 1;
2294
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 else if (av_strstart(token, "recon_gain=", &token))
2295 10 recon_gain = 1;
2296
2297 50 av_dict_free(&dict);
2298 50 ret = av_dict_parse_string(&dict, token, "=", ":", 0);
2299
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (ret < 0) {
2300 av_log(mux, AV_LOG_ERROR, "Error parsing audio element specification %s\n", token);
2301 goto fail;
2302 }
2303
2304
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 20 times.
50 if (layer) {
2305 30 AVIAMFLayer *audio_layer = av_iamf_audio_element_add_layer(audio_element);
2306
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (!audio_layer) {
2307 av_log(mux, AV_LOG_ERROR, "Error adding layer to stream group %d\n", stg->index);
2308 ret = AVERROR(ENOMEM);
2309 goto fail;
2310 }
2311 30 av_opt_set_dict(audio_layer, &dict);
2312
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) {
2313 20 AVIAMFParamDefinition *param = demixing ? audio_element->demixing_info
2314
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 : audio_element->recon_gain_info;
2315 20 void *subblock = av_iamf_param_definition_get_subblock(param, 0);
2316
2317 20 av_opt_set_dict(param, &dict);
2318 20 av_opt_set_dict(subblock, &dict);
2319 }
2320
2321 // make sure that no entries are left in the dict
2322 50 e = NULL;
2323
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 50 times.
50 if (e = av_dict_iterate(dict, e)) {
2324 av_log(mux, AV_LOG_FATAL, "Unknown layer key %s.\n", e->key);
2325 ret = AVERROR(EINVAL);
2326 goto fail;
2327 }
2328 50 token = av_strtok(NULL, ",", &ptr);
2329 }
2330
2331 14 fail:
2332 14 av_dict_free(&dict);
2333
2/4
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 14 times.
14 if (!ret && !audio_element->nb_layers) {
2334 av_log(mux, AV_LOG_ERROR, "No layer in audio element specification\n");
2335 ret = AVERROR(EINVAL);
2336 }
2337
2338 14 return ret;
2339 }
2340
2341 13 static int of_parse_iamf_submixes(Muxer *mux, AVStreamGroup *stg, char *ptr)
2342 {
2343 13 AVFormatContext *oc = mux->fc;
2344 13 AVIAMFMixPresentation *mix = stg->params.iamf_mix_presentation;
2345 13 AVDictionary *dict = NULL;
2346 const char *token;
2347 13 char *submix_str = NULL;
2348 13 int ret = 0;
2349
2350 /* process manually set submixes */
2351 13 token = av_strtok(NULL, ",", &ptr);
2352
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 13 times.
28 while (token) {
2353 15 AVIAMFSubmix *submix = NULL;
2354 const char *subtoken;
2355 15 char *subptr = NULL;
2356
2357
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 2 times.
15 if (ptr)
2358 13 ptr += strspn(ptr, " \n\t\r");
2359
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
15 if (!av_strstart(token, "submix=", &token)) {
2360 av_log(mux, AV_LOG_ERROR, "No submix in mix presentation specification \"%s\"\n", token);
2361 goto fail;
2362 }
2363
2364 15 submix_str = av_strdup(token);
2365
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (!submix_str)
2366 goto fail;
2367
2368 15 submix = av_iamf_mix_presentation_add_submix(mix);
2369
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (!submix) {
2370 av_log(mux, AV_LOG_ERROR, "Error adding submix to stream group %d\n", stg->index);
2371 ret = AVERROR(ENOMEM);
2372 goto fail;
2373 }
2374 15 submix->output_mix_config =
2375 15 av_iamf_param_definition_alloc(AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN, 0, NULL);
2376
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (!submix->output_mix_config) {
2377 ret = AVERROR(ENOMEM);
2378 goto fail;
2379 }
2380
2381 15 subptr = NULL;
2382 15 subtoken = av_strtok(submix_str, "|", &subptr);
2383
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 15 times.
78 while (subtoken) {
2384 const AVDictionaryEntry *e;
2385 63 int element = 0, layout = 0;
2386
2387
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 15 times.
63 if (subptr)
2388 48 subptr += strspn(subptr, " \n\t\r");
2389
2/2
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 47 times.
63 if (av_strstart(subtoken, "element=", &subtoken))
2390 16 element = 1;
2391
2/2
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 15 times.
47 else if (av_strstart(subtoken, "layout=", &subtoken))
2392 32 layout = 1;
2393
2394 63 av_dict_free(&dict);
2395 63 ret = av_dict_parse_string(&dict, subtoken, "=", ":", 0);
2396
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 if (ret < 0) {
2397 av_log(mux, AV_LOG_ERROR, "Error parsing submix specification \"%s\"\n", subtoken);
2398 goto fail;
2399 }
2400
2401
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 47 times.
63 if (element) {
2402 AVIAMFSubmixElement *submix_element;
2403 16 char *endptr = NULL;
2404 16 int64_t idx = -1;
2405
2406
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 if (e = av_dict_get(dict, "stg", NULL, 0))
2407 16 idx = strtoll(e->value, &endptr, 0);
2408
4/8
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 16 times.
✗ Branch 7 not taken.
16 if (!endptr || *endptr || idx < 0 || idx >= oc->nb_stream_groups - 1 ||
2409
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 oc->stream_groups[idx]->type != AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT) {
2410 av_log(mux, AV_LOG_ERROR, "Invalid or missing stream group index in "
2411 "submix element specification \"%s\"\n", subtoken);
2412 ret = AVERROR(EINVAL);
2413 goto fail;
2414 }
2415 16 submix_element = av_iamf_submix_add_element(submix);
2416
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!submix_element) {
2417 av_log(mux, AV_LOG_ERROR, "Error adding element to submix\n");
2418 ret = AVERROR(ENOMEM);
2419 goto fail;
2420 }
2421
2422 16 submix_element->audio_element_id = oc->stream_groups[idx]->id;
2423
2424 16 submix_element->element_mix_config =
2425 16 av_iamf_param_definition_alloc(AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN, 0, NULL);
2426
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!submix_element->element_mix_config)
2427 ret = AVERROR(ENOMEM);
2428 16 av_dict_set(&dict, "stg", NULL, 0);
2429 16 av_opt_set_dict2(submix_element, &dict, AV_OPT_SEARCH_CHILDREN);
2430
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 15 times.
47 } else if (layout) {
2431 32 AVIAMFSubmixLayout *submix_layout = av_iamf_submix_add_layout(submix);
2432
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (!submix_layout) {
2433 av_log(mux, AV_LOG_ERROR, "Error adding layout to submix\n");
2434 ret = AVERROR(ENOMEM);
2435 goto fail;
2436 }
2437 32 av_opt_set_dict(submix_layout, &dict);
2438 } else
2439 15 av_opt_set_dict2(submix, &dict, AV_OPT_SEARCH_CHILDREN);
2440
2441
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 if (ret < 0) {
2442 goto fail;
2443 }
2444
2445 // make sure that no entries are left in the dict
2446 63 e = NULL;
2447
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 63 times.
63 while (e = av_dict_iterate(dict, e)) {
2448 av_log(mux, AV_LOG_FATAL, "Unknown submix key %s.\n", e->key);
2449 ret = AVERROR(EINVAL);
2450 goto fail;
2451 }
2452 63 subtoken = av_strtok(NULL, "|", &subptr);
2453 }
2454 15 av_freep(&submix_str);
2455
2456
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (!submix->nb_elements) {
2457 av_log(mux, AV_LOG_ERROR, "No audio elements in submix specification \"%s\"\n", token);
2458 ret = AVERROR(EINVAL);
2459 }
2460 15 token = av_strtok(NULL, ",", &ptr);
2461 }
2462
2463 13 fail:
2464 13 av_dict_free(&dict);
2465 13 av_free(submix_str);
2466
2467 13 return ret;
2468 }
2469
2470 18 static int of_serialize_options(Muxer *mux, void *obj, AVBPrint *bp)
2471 {
2472 char *ptr;
2473 int ret;
2474
2475 18 ret = av_opt_serialize(obj, 0, AV_OPT_SERIALIZE_SKIP_DEFAULTS | AV_OPT_SERIALIZE_SEARCH_CHILDREN,
2476 &ptr, '=', ':');
2477
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (ret < 0) {
2478 av_log(mux, AV_LOG_ERROR, "Failed to serialize group\n");
2479 return ret;
2480 }
2481
2482 18 av_bprintf(bp, "%s", ptr);
2483 18 ret = strlen(ptr);
2484 18 av_free(ptr);
2485
2486 18 return ret;
2487 }
2488
2489 #define SERIALIZE(parent, child) do { \
2490 ret = of_serialize_options(mux, parent->child, bp); \
2491 if (ret < 0) \
2492 return ret; \
2493 } while (0)
2494
2495 #define SERIALIZE_LOOP_SUBBLOCK(obj) do { \
2496 for (int k = 0; k < obj->nb_subblocks; k++) { \
2497 ret = of_serialize_options(mux, \
2498 av_iamf_param_definition_get_subblock(obj, k), bp); \
2499 if (ret < 0) \
2500 return ret; \
2501 } \
2502 } while (0)
2503
2504 #define SERIALIZE_LOOP(parent, child, suffix, separator) do { \
2505 for (int j = 0; j < parent->nb_## child ## suffix; j++) { \
2506 av_bprintf(bp, separator#child "="); \
2507 SERIALIZE(parent, child ## suffix[j]); \
2508 } \
2509 } while (0)
2510
2511 2 static int64_t get_stream_group_index_from_id(Muxer *mux, int64_t id)
2512 {
2513 2 AVFormatContext *oc = mux->fc;
2514
2515
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 for (unsigned i = 0; i < oc->nb_stream_groups; i++)
2516
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (oc->stream_groups[i]->id == id)
2517 2 return oc->stream_groups[i]->index;
2518
2519 return AVERROR(EINVAL);
2520 }
2521
2522 4 static int of_map_group(Muxer *mux, AVDictionary **dict, AVBPrint *bp, const char *map)
2523 {
2524 AVStreamGroup *stg;
2525 int ret, file_idx, stream_idx;
2526 char *ptr;
2527
2528 4 file_idx = strtol(map, &ptr, 0);
2529
3/6
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
4 if (file_idx >= nb_input_files || file_idx < 0 || map == ptr) {
2530 av_log(mux, AV_LOG_ERROR, "Invalid input file index: %d.\n", file_idx);
2531 return AVERROR(EINVAL);
2532 }
2533
2534
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 stream_idx = strtol(*ptr == '=' ? ptr + 1 : ptr, &ptr, 0);
2535
3/6
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
4 if (*ptr || stream_idx >= input_files[file_idx]->ctx->nb_stream_groups || stream_idx < 0) {
2536 av_log(mux, AV_LOG_ERROR, "Invalid input stream group index: %d.\n", stream_idx);
2537 return AVERROR(EINVAL);
2538 }
2539
2540 4 stg = input_files[file_idx]->ctx->stream_groups[stream_idx];
2541 4 ret = of_serialize_options(mux, stg, bp);
2542
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0)
2543 return ret;
2544
2545 4 ret = av_dict_parse_string(dict, bp->str, "=", ":", 0);
2546
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0)
2547 av_log(mux, AV_LOG_ERROR, "Error parsing mapped group specification %s\n", ptr);
2548 4 av_dict_set_int(dict, "type", stg->type, 0);
2549
2550 4 av_bprint_clear(bp);
2551
2/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
4 switch(stg->type) {
2552 2 case AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT: {
2553 2 AVIAMFAudioElement *audio_element = stg->params.iamf_audio_element;
2554
2555
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (audio_element->demixing_info) {
2556 1 AVIAMFParamDefinition *demixing_info = audio_element->demixing_info;
2557 1 av_bprintf(bp, ",demixing=");
2558
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 SERIALIZE(audio_element, demixing_info);
2559
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)
2560 1 av_bprintf(bp, ":");
2561
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);
2562 }
2563
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (audio_element->recon_gain_info) {
2564 1 AVIAMFParamDefinition *recon_gain_info = audio_element->recon_gain_info;
2565 1 av_bprintf(bp, ",recon_gain=");
2566
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 SERIALIZE(audio_element, recon_gain_info);
2567
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)
2568 1 av_bprintf(bp, ":");
2569
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);
2570 }
2571
3/4
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 2 times.
5 SERIALIZE_LOOP(audio_element, layer, s, ",");
2572 2 break;
2573 }
2574 2 case AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION: {
2575 2 AVIAMFMixPresentation *mix = stg->params.iamf_mix_presentation;
2576
2577
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (int i = 0; i < mix->nb_submixes; i++) {
2578 2 AVIAMFSubmix *submix = mix->submixes[i];
2579 2 AVIAMFParamDefinition *output_mix_config = submix->output_mix_config;
2580
2581 2 av_bprintf(bp, ",submix=");
2582
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 SERIALIZE(mix, submixes[i]);
2583
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (ret && output_mix_config->nb_subblocks)
2584 av_bprintf(bp, ":");
2585
1/4
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
2 SERIALIZE_LOOP_SUBBLOCK(output_mix_config);
2586
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (int j = 0; j < submix->nb_elements; j++) {
2587 2 AVIAMFSubmixElement *element = submix->elements[j];
2588 2 AVIAMFParamDefinition *element_mix_config = element->element_mix_config;
2589 2 int64_t id = get_stream_group_index_from_id(mux, element->audio_element_id);
2590
2591
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (id < 0) {
2592 av_log(mux, AV_LOG_ERROR, "Invalid or missing stream group index in"
2593 "submix element");
2594 return id;
2595 }
2596
2597 2 av_bprintf(bp, "|element=");
2598
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 SERIALIZE(submix, elements[j]);
2599
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (ret && element_mix_config->nb_subblocks)
2600 av_bprintf(bp, ":");
2601
1/4
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
2 SERIALIZE_LOOP_SUBBLOCK(element_mix_config);
2602
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (ret)
2603 2 av_bprintf(bp, ":");
2604 2 av_bprintf(bp, "stg=%"PRId64, id);
2605 }
2606
3/4
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 2 times.
5 SERIALIZE_LOOP(submix, layout, s, "|");
2607 }
2608 2 break;
2609 }
2610 case AV_STREAM_GROUP_PARAMS_LCEVC:
2611 case AV_STREAM_GROUP_PARAMS_TREF:
2612 case AV_STREAM_GROUP_PARAMS_DOLBY_VISION:
2613 break;
2614 default:
2615 av_log(mux, AV_LOG_ERROR, "Unsupported mapped group type %d.\n", stg->type);
2616 ret = AVERROR(EINVAL);
2617 break;
2618 }
2619 4 return 0;
2620 }
2621
2622 27 static int of_parse_group_token(Muxer *mux, const char *token, char *ptr)
2623 {
2624 27 AVFormatContext *oc = mux->fc;
2625 AVStreamGroup *stg;
2626 27 AVDictionary *dict = NULL, *tmp = NULL;
2627 27 char *mapped_string = NULL;
2628 const AVDictionaryEntry *e;
2629 27 const AVOption opts[] = {
2630 { "type", "Set group type", offsetof(AVStreamGroup, type), AV_OPT_TYPE_INT,
2631 { .i64 = 0 }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, .unit = "type" },
2632 { "iamf_audio_element", NULL, 0, AV_OPT_TYPE_CONST,
2633 { .i64 = AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT }, .unit = "type" },
2634 { "iamf_mix_presentation", NULL, 0, AV_OPT_TYPE_CONST,
2635 { .i64 = AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION }, .unit = "type" },
2636 { "lcevc", NULL, 0, AV_OPT_TYPE_CONST,
2637 { .i64 = AV_STREAM_GROUP_PARAMS_LCEVC }, .unit = "type" },
2638 { "tref", NULL, 0, AV_OPT_TYPE_CONST,
2639 { .i64 = AV_STREAM_GROUP_PARAMS_TREF }, .unit = "type" },
2640 { NULL },
2641 };
2642 27 const AVClass class = {
2643 .class_name = "StreamGroupType",
2644 .item_name = av_default_item_name,
2645 .option = opts,
2646 .version = LIBAVUTIL_VERSION_INT,
2647 };
2648 27 const AVClass *pclass = &class;
2649 int type, ret;
2650
2651 27 ret = av_dict_parse_string(&dict, token, "=", ":", AV_DICT_MULTIKEY);
2652
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (ret < 0) {
2653 av_log(mux, AV_LOG_ERROR, "Error parsing group specification %s\n", token);
2654 return ret;
2655 }
2656
2657 27 av_dict_copy(&tmp, dict, 0);
2658 27 e = av_dict_get(dict, "map", NULL, 0);
2659
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 23 times.
27 if (e) {
2660 AVBPrint bp;
2661
2662
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ptr) {
2663 av_log(mux, AV_LOG_ERROR, "Unexpected extra parameters when mapping a"
2664 " stream group\n");
2665 ret = AVERROR(EINVAL);
2666 goto end;
2667 }
2668
2669 4 av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC);
2670 4 ret = of_map_group(mux, &tmp, &bp, e->value);
2671
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0) {
2672 av_bprint_finalize(&bp, NULL);
2673 goto end;
2674 }
2675
2676 4 av_bprint_finalize(&bp, &mapped_string);
2677 4 ptr = mapped_string;
2678 }
2679
2680 // "type" is not a user settable AVOption in AVStreamGroup, so handle it here
2681 27 e = av_dict_get(tmp, "type", NULL, 0);
2682
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (!e) {
2683 av_log(mux, AV_LOG_ERROR, "No type specified for Stream Group in \"%s\"\n", token);
2684 ret = AVERROR(EINVAL);
2685 goto end;
2686 }
2687
2688 27 ret = av_opt_eval_int(&pclass, opts, e->value, &type);
2689
2/4
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 27 times.
27 if (!ret && type == AV_STREAM_GROUP_PARAMS_NONE)
2690 ret = AVERROR(EINVAL);
2691
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (ret < 0) {
2692 av_log(mux, AV_LOG_ERROR, "Invalid group type \"%s\"\n", e->value);
2693 goto end;
2694 }
2695
2696 27 stg = avformat_stream_group_create(oc, type, &tmp);
2697
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (!stg) {
2698 ret = AVERROR(ENOMEM);
2699 goto end;
2700 }
2701
2702 27 e = NULL;
2703
2/2
✓ Branch 1 taken 65 times.
✓ Branch 2 taken 27 times.
92 while (e = av_dict_get(dict, "st", e, 0)) {
2704 char *endptr;
2705 65 int64_t idx = strtoll(e->value, &endptr, 0);
2706
3/6
✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 65 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 65 times.
65 if (*endptr || idx < 0 || idx >= oc->nb_streams) {
2707 av_log(mux, AV_LOG_ERROR, "Invalid stream index %"PRId64"\n", idx);
2708 ret = AVERROR(EINVAL);
2709 goto end;
2710 }
2711 65 ret = avformat_stream_group_add_stream(stg, oc->streams[idx]);
2712
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 if (ret < 0)
2713 goto end;
2714 65 OutputStream *ost = mux->of.streams[idx];
2715
3/4
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 57 times.
65 if (ost->enc && (type == AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT ||
2716 type == AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION))
2717 57 ost->enc->flags2 |= AV_CODEC_FLAG2_FIXED_FRAME_SIZE;
2718 }
2719
2/2
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 27 times.
40 while (e = av_dict_get(dict, "stg", e, 0)) {
2720 char *endptr;
2721 13 int64_t idx = strtoll(e->value, &endptr, 0);
2722
3/6
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 13 times.
13 if (*endptr || idx < 0 || idx >= oc->nb_stream_groups - 1) {
2723 av_log(mux, AV_LOG_ERROR, "Invalid stream group index %"PRId64"\n", idx);
2724 ret = AVERROR(EINVAL);
2725 goto end;
2726 }
2727
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 13 times.
77 for (unsigned i = 0; i < oc->stream_groups[idx]->nb_streams; i++) {
2728 64 ret = avformat_stream_group_add_stream(stg, oc->stream_groups[idx]->streams[i]);
2729
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
64 if (ret < 0)
2730 goto end;
2731 }
2732 }
2733
2734
2/3
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
27 switch(type) {
2735 14 case AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT:
2736 14 ret = of_parse_iamf_audio_element_layers(mux, stg, ptr);
2737 14 break;
2738 13 case AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION:
2739 13 ret = of_parse_iamf_submixes(mux, stg, ptr);
2740 13 break;
2741 default:
2742 break;
2743 }
2744
2745
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (ret < 0)
2746 goto end;
2747
2748 // make sure that nothing but "st" and "stg" entries are left in the dict
2749 27 e = NULL;
2750 27 av_dict_set(&tmp, "map", NULL, 0);
2751 27 av_dict_set(&tmp, "type", NULL, 0);
2752
2/2
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 27 times.
54 while (e = av_dict_iterate(tmp, e)) {
2753
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
27 if (!strcmp(e->key, "st") || !strcmp(e->key, "stg"))
2754 27 continue;
2755
2756 av_log(mux, AV_LOG_FATAL, "Unknown group key %s.\n", e->key);
2757 ret = AVERROR(EINVAL);
2758 goto end;
2759 }
2760
2761 27 ret = 0;
2762 27 end:
2763 27 av_free(mapped_string);
2764 27 av_dict_free(&dict);
2765 27 av_dict_free(&tmp);
2766
2767 27 return ret;
2768 }
2769
2770 8818 static int of_add_groups(Muxer *mux, const OptionsContext *o)
2771 {
2772 /* process manually set groups */
2773
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 8818 times.
8845 for (int i = 0; i < o->stream_groups.nb_opt; i++) {
2774 const char *token;
2775 27 char *str, *ptr = NULL;
2776 27 int ret = 0;
2777
2778 27 str = av_strdup(o->stream_groups.opt[i].u.str);
2779
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (!str)
2780 return ret;
2781
2782 27 token = av_strtok(str, ",", &ptr);
2783
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 if (token) {
2784
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 4 times.
27 if (ptr)
2785 23 ptr += strspn(ptr, " \n\t\r");
2786 27 ret = of_parse_group_token(mux, token, ptr);
2787 }
2788
2789 27 av_free(str);
2790
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (ret < 0)
2791 return ret;
2792 }
2793
2794 8818 return 0;
2795 }
2796
2797 8818 static int of_add_programs(Muxer *mux, const OptionsContext *o)
2798 {
2799 8818 AVFormatContext *oc = mux->fc;
2800 /* process manually set programs */
2801
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8818 times.
8818 for (int i = 0; i < o->program.nb_opt; i++) {
2802 AVDictionary *dict = NULL;
2803 const AVDictionaryEntry *e;
2804 AVProgram *program;
2805 int ret, progid = i + 1;
2806
2807 ret = av_dict_parse_string(&dict, o->program.opt[i].u.str, "=", ":",
2808 AV_DICT_MULTIKEY);
2809 if (ret < 0) {
2810 av_log(mux, AV_LOG_ERROR, "Error parsing program specification %s\n",
2811 o->program.opt[i].u.str);
2812 return ret;
2813 }
2814
2815 e = av_dict_get(dict, "program_num", NULL, 0);
2816 if (e) {
2817 progid = strtol(e->value, NULL, 0);
2818 av_dict_set(&dict, e->key, NULL, 0);
2819 }
2820
2821 program = av_new_program(oc, progid);
2822 if (!program) {
2823 ret = AVERROR(ENOMEM);
2824 goto fail;
2825 }
2826
2827 e = av_dict_get(dict, "title", NULL, 0);
2828 if (e) {
2829 av_dict_set(&program->metadata, e->key, e->value, 0);
2830 av_dict_set(&dict, e->key, NULL, 0);
2831 }
2832
2833 e = NULL;
2834 while (e = av_dict_get(dict, "st", e, 0)) {
2835 int st_num = strtol(e->value, NULL, 0);
2836 av_program_add_stream_index(oc, progid, st_num);
2837 }
2838
2839 // make sure that nothing but "st" entries are left in the dict
2840 e = NULL;
2841 while (e = av_dict_iterate(dict, e)) {
2842 if (!strcmp(e->key, "st"))
2843 continue;
2844
2845 av_log(mux, AV_LOG_FATAL, "Unknown program key %s.\n", e->key);
2846 ret = AVERROR(EINVAL);
2847 goto fail;
2848 }
2849
2850 fail:
2851 av_dict_free(&dict);
2852 if (ret < 0)
2853 return ret;
2854 }
2855
2856 8818 return 0;
2857 }
2858
2859 /**
2860 * Parse a metadata specifier passed as 'arg' parameter.
2861 * @param arg metadata string to parse
2862 * @param type metadata type is written here -- g(lobal)/s(tream)/c(hapter)/p(rogram)
2863 * @param index for type c/p, chapter/program index is written here
2864 * @param stream_spec for type s, the stream specifier is written here
2865 */
2866 453 static int parse_meta_type(void *logctx, const char *arg,
2867 char *type, int *index, const char **stream_spec)
2868 {
2869
2/2
✓ Branch 0 taken 189 times.
✓ Branch 1 taken 264 times.
453 if (*arg) {
2870 189 *type = *arg;
2871
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) {
2872 27 case 'g':
2873 27 break;
2874 149 case 's':
2875
2/4
✓ Branch 0 taken 149 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 149 times.
149 if (*(++arg) && *arg != ':') {
2876 av_log(logctx, AV_LOG_FATAL, "Invalid metadata specifier %s.\n", arg);
2877 return AVERROR(EINVAL);
2878 }
2879
1/2
✓ Branch 0 taken 149 times.
✗ Branch 1 not taken.
149 *stream_spec = *arg == ':' ? arg + 1 : "";
2880 149 break;
2881 12 case 'c':
2882 case 'p':
2883
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1 times.
12 if (*(++arg) == ':')
2884 11 *index = strtol(++arg, NULL, 0);
2885 12 break;
2886 1 default:
2887 1 av_log(logctx, AV_LOG_FATAL, "Invalid metadata type %c.\n", *arg);
2888 1 return AVERROR(EINVAL);
2889 }
2890 } else
2891 264 *type = 'g';
2892
2893 452 return 0;
2894 }
2895
2896 8818 static int of_add_metadata(OutputFile *of, AVFormatContext *oc,
2897 const OptionsContext *o)
2898 {
2899
2/2
✓ Branch 0 taken 259 times.
✓ Branch 1 taken 8818 times.
9077 for (int i = 0; i < o->metadata.nb_opt; i++) {
2900 AVDictionary **m;
2901 char type, *val;
2902 const char *stream_spec;
2903 259 int index = 0, ret = 0;
2904
2905 259 val = strchr(o->metadata.opt[i].u.str, '=');
2906
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 259 times.
259 if (!val) {
2907 av_log(of, AV_LOG_FATAL, "No '=' character in metadata string %s.\n",
2908 o->metadata.opt[i].u.str);
2909 return AVERROR(EINVAL);
2910 }
2911 259 *val++ = 0;
2912
2913 259 ret = parse_meta_type(of, o->metadata.opt[i].specifier, &type, &index, &stream_spec);
2914
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 259 times.
259 if (ret < 0)
2915 return ret;
2916
2917
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 214 times.
259 if (type == 's') {
2918
2/2
✓ Branch 0 taken 223 times.
✓ Branch 1 taken 45 times.
268 for (int j = 0; j < oc->nb_streams; j++) {
2919
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) {
2920
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);
2921
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 179 times.
179 } else if (ret < 0)
2922 return ret;
2923 }
2924 } else {
2925
2/4
✓ Branch 0 taken 209 times.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
214 switch (type) {
2926 209 case 'g':
2927 209 m = &oc->metadata;
2928 209 break;
2929 5 case 'c':
2930
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) {
2931 av_log(of, AV_LOG_FATAL, "Invalid chapter index %d in metadata specifier.\n", index);
2932 return AVERROR(EINVAL);
2933 }
2934 5 m = &oc->chapters[index]->metadata;
2935 5 break;
2936 case 'p':
2937 if (index < 0 || index >= oc->nb_programs) {
2938 av_log(of, AV_LOG_FATAL, "Invalid program index %d in metadata specifier.\n", index);
2939 return AVERROR(EINVAL);
2940 }
2941 m = &oc->programs[index]->metadata;
2942 break;
2943 default:
2944 av_log(of, AV_LOG_FATAL, "Invalid metadata specifier %s.\n", o->metadata.opt[i].specifier);
2945 return AVERROR(EINVAL);
2946 }
2947
2/2
✓ Branch 0 taken 213 times.
✓ Branch 1 taken 1 times.
214 av_dict_set(m, o->metadata.opt[i].u.str, *val ? val : NULL, 0);
2948 }
2949 }
2950
2951 8818 return 0;
2952 }
2953
2954 39 static int copy_chapters(InputFile *ifile, OutputFile *ofile, AVFormatContext *os,
2955 int copy_metadata)
2956 {
2957 39 AVFormatContext *is = ifile->ctx;
2958 AVChapter **tmp;
2959
2960 39 tmp = av_realloc_f(os->chapters, is->nb_chapters + os->nb_chapters, sizeof(*os->chapters));
2961
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (!tmp)
2962 return AVERROR(ENOMEM);
2963 39 os->chapters = tmp;
2964
2965
2/2
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 36 times.
113 for (int i = 0; i < is->nb_chapters; i++) {
2966 77 AVChapter *in_ch = is->chapters[i], *out_ch;
2967
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;
2968 77 int64_t ts_off = av_rescale_q(start_time - ifile->ts_offset,
2969 77 AV_TIME_BASE_Q, in_ch->time_base);
2970
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 52 times.
77 int64_t rt = (ofile->recording_time == INT64_MAX) ? INT64_MAX :
2971 25 av_rescale_q(ofile->recording_time, AV_TIME_BASE_Q, in_ch->time_base);
2972
2973
2974
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 if (in_ch->end < ts_off)
2975 continue;
2976
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)
2977 3 break;
2978
2979 74 out_ch = av_mallocz(sizeof(AVChapter));
2980
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 74 times.
74 if (!out_ch)
2981 return AVERROR(ENOMEM);
2982
2983 74 out_ch->id = in_ch->id;
2984 74 out_ch->time_base = in_ch->time_base;
2985 74 out_ch->start = FFMAX(0, in_ch->start - ts_off);
2986 74 out_ch->end = FFMIN(rt, in_ch->end - ts_off);
2987
2988
1/2
✓ Branch 0 taken 74 times.
✗ Branch 1 not taken.
74 if (copy_metadata)
2989 74 av_dict_copy(&out_ch->metadata, in_ch->metadata, 0);
2990
2991 74 os->chapters[os->nb_chapters++] = out_ch;
2992 }
2993 39 return 0;
2994 }
2995
2996 28 static int copy_metadata(Muxer *mux, AVFormatContext *ic,
2997 const char *outspec, const char *inspec,
2998 int *metadata_global_manual, int *metadata_streams_manual,
2999 int *metadata_chapters_manual)
3000 {
3001 28 AVFormatContext *oc = mux->fc;
3002 28 AVDictionary **meta_in = NULL;
3003 28 AVDictionary **meta_out = NULL;
3004 28 int i, ret = 0;
3005 char type_in, type_out;
3006 28 const char *istream_spec = NULL, *ostream_spec = NULL;
3007 28 int idx_in = 0, idx_out = 0;
3008
3009 28 ret = parse_meta_type(mux, inspec, &type_in, &idx_in, &istream_spec);
3010
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 if (ret >= 0)
3011 28 ret = parse_meta_type(mux, outspec, &type_out, &idx_out, &ostream_spec);
3012
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (ret < 0)
3013 return ret;
3014
3015
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))
3016 25 *metadata_global_manual = 1;
3017
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))
3018 22 *metadata_streams_manual = 1;
3019
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))
3020 18 *metadata_chapters_manual = 1;
3021
3022 /* ic is NULL when just disabling automatic mappings */
3023
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 8 times.
28 if (!ic)
3024 20 return 0;
3025
3026 #define METADATA_CHECK_INDEX(index, nb_elems, desc)\
3027 if ((index) < 0 || (index) >= (nb_elems)) {\
3028 av_log(mux, AV_LOG_FATAL, "Invalid %s index %d while processing metadata maps.\n",\
3029 (desc), (index));\
3030 return AVERROR(EINVAL);\
3031 }
3032
3033 #define SET_DICT(type, meta, context, index)\
3034 switch (type) {\
3035 case 'g':\
3036 meta = &context->metadata;\
3037 break;\
3038 case 'c':\
3039 METADATA_CHECK_INDEX(index, context->nb_chapters, "chapter")\
3040 meta = &context->chapters[index]->metadata;\
3041 break;\
3042 case 'p':\
3043 METADATA_CHECK_INDEX(index, context->nb_programs, "program")\
3044 meta = &context->programs[index]->metadata;\
3045 break;\
3046 case 's':\
3047 break; /* handled separately below */ \
3048 default: av_assert0(0);\
3049 }\
3050
3051
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);
3052
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);
3053
3054 /* for input streams choose first matching stream */
3055
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
8 if (type_in == 's') {
3056
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 for (i = 0; i < ic->nb_streams; i++) {
3057
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) {
3058 3 meta_in = &ic->streams[i]->metadata;
3059 3 break;
3060
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 } else if (ret < 0)
3061 return ret;
3062 }
3063
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!meta_in) {
3064 av_log(mux, AV_LOG_FATAL, "Stream specifier %s does not match any streams.\n", istream_spec);
3065 return AVERROR(EINVAL);
3066 }
3067 }
3068
3069
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 if (type_out == 's') {
3070
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 4 times.
13 for (i = 0; i < oc->nb_streams; i++) {
3071
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) {
3072 4 meta_out = &oc->streams[i]->metadata;
3073 4 av_dict_copy(meta_out, *meta_in, AV_DICT_DONT_OVERWRITE);
3074
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 } else if (ret < 0)
3075 return ret;
3076 }
3077 } else
3078 4 av_dict_copy(meta_out, *meta_in, AV_DICT_DONT_OVERWRITE);
3079
3080 8 return 0;
3081 }
3082
3083 #define REENC_MASK(type) (1u << (type))
3084 #define REENC_AUDIO_ONLY REENC_MASK(AVMEDIA_TYPE_AUDIO)
3085 #define REENC_VIDEO_ONLY REENC_MASK(AVMEDIA_TYPE_VIDEO)
3086 #define REENC_ANY (REENC_AUDIO_ONLY | REENC_VIDEO_ONLY)
3087
3088 static const struct {
3089 const char *key;
3090 int flags;
3091 unsigned reenc_mask; /* 0 = always delete; non-zero = bit-mask of
3092 * REENC_* values whose re-encoding triggers
3093 * deletion of this key */
3094 } reenc_delete_keys[] = {
3095 // Note: "encoder" is intentionally absent — set_encoder_id() stamps it
3096 // after copy_meta() runs, so it always reflects the current encoder.
3097
3098 // iTunes gapless playback: encoder-specific sample counts and padding;
3099 // gapless_playback is the M4A/MOV equivalent of iTunPGAP
3100 { "iTunPGAP", 0, REENC_AUDIO_ONLY },
3101 { "comment-iTunPGAP-eng", 0, REENC_AUDIO_ONLY },
3102 { "iTunSMPB", 0, REENC_AUDIO_ONLY },
3103 { "comment-iTunSMPB-eng", 0, REENC_AUDIO_ONLY },
3104 { "gapless_playback", 0, REENC_AUDIO_ONLY },
3105 // iTunes Sound Check: peak amplitude computed from the original waveform
3106 { "iTunNORM", 0, REENC_AUDIO_ONLY },
3107 { "comment-iTunNORM-eng", 0, REENC_AUDIO_ONLY },
3108 // encoding provenance: describe the original encoder, not the new one
3109 { "encoded_by", 0, REENC_ANY },
3110 { "encoding_tool", 0, REENC_ANY },
3111 // MOV/MP4 stream: vendor 4CC identifies the original encoder
3112 { "vendor_id", 0, REENC_ANY },
3113 // Matroska stream stats written by mkvmerge; all are invalidated by re-encoding
3114 { "BPS", AV_DICT_IGNORE_SUFFIX, REENC_ANY },
3115 { "DURATION", AV_DICT_IGNORE_SUFFIX, REENC_ANY },
3116 { "NUMBER_OF_BYTES", AV_DICT_IGNORE_SUFFIX, REENC_ANY },
3117 { "NUMBER_OF_FRAMES", AV_DICT_IGNORE_SUFFIX, REENC_ANY },
3118 { "_STATISTICS_TAGS", AV_DICT_IGNORE_SUFFIX, REENC_ANY },
3119 { "_STATISTICS_WRITING_APP", AV_DICT_IGNORE_SUFFIX, REENC_ANY },
3120 { "_STATISTICS_WRITING_DATE_UTC", AV_DICT_IGNORE_SUFFIX, REENC_ANY },
3121
3122 // MOV/MP4: source container brand written by the demuxer; muxer ignores
3123 // these keys and writes its own ftyp, so they always describe the source file
3124 { "major_brand", 0, 0 },
3125 { "minor_version", 0, 0 },
3126 { "compatible_brands", 0, 0 },
3127 { NULL }
3128 };
3129
3130 127 static int meta_spec_matches(void *log_ctx, AVFormatContext *oc, AVStream *st,
3131 const char *spec)
3132 {
3133 char type;
3134 127 int index = 0;
3135 127 const char *stream_spec = NULL;
3136
3137
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 127 times.
127 if (parse_meta_type(log_ctx, spec, &type, &index, &stream_spec) < 0)
3138 return 0;
3139
3140
2/2
✓ Branch 0 taken 101 times.
✓ Branch 1 taken 26 times.
127 if (*spec) {
3141
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)
3142 return 0;
3143
2/2
✓ Branch 0 taken 90 times.
✓ Branch 1 taken 11 times.
101 if (type == 's') {
3144 int ret;
3145
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 42 times.
90 if (!st)
3146 48 return 0;
3147 42 ret = check_stream_specifier(oc, st, stream_spec);
3148
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 return ret < 0 ? ret : ret > 0;
3149 }
3150
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')
3151 7 return 0;
3152 }
3153 30 return 1;
3154 }
3155
3156 1823 static int reenc_delete_metadata_key(const OptionsContext *o, void *log_ctx,
3157 AVFormatContext *oc, AVStream *st,
3158 const char *family, const char *key, int flags)
3159 {
3160
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 1818 times.
1872 for (int i = 0; i < o->keep_metadata.nb_opt; i++) {
3161 54 int ret = meta_spec_matches(log_ctx, oc, st, o->keep_metadata.opt[i].specifier);
3162
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 if (ret < 0)
3163 return ret;
3164
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 36 times.
54 if (!ret)
3165 18 continue;
3166 36 const char *keep = o->keep_metadata.opt[i].u.str;
3167
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 8 times.
36 if (flags & AV_DICT_IGNORE_SUFFIX) {
3168 /* accept the unsuffixed family name (e.g. NUMBER_OF_BYTES keeps
3169 * NUMBER_OF_BYTES-eng) or the exact matched key; an arbitrary
3170 * prefix like NUMBER does not match NUMBER_OF_BYTES-eng */
3171
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))
3172 3 return 0;
3173 } else {
3174
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
8 if (!strcmp(key, keep))
3175 2 return 0;
3176 }
3177 }
3178
2/2
✓ Branch 0 taken 74 times.
✓ Branch 1 taken 1817 times.
1891 for (int i = 0; i < o->metadata.nb_opt; i++) {
3179 int ret;
3180 /* plain -metadata (empty specifier) applies to global metadata only,
3181 * matching of_add_metadata(); don't let it suppress stream-level pruning */
3182
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)
3183 1 continue;
3184 73 ret = meta_spec_matches(log_ctx, oc, st, o->metadata.opt[i].specifier);
3185
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
73 if (ret < 0)
3186 return ret;
3187
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 15 times.
73 if (!ret)
3188 58 continue;
3189 15 size_t klen = strcspn(o->metadata.opt[i].u.str, "=");
3190
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')
3191 1 return 0;
3192 }
3193 1817 return 1;
3194 }
3195
3196 18145 static int reenc_delete_stale_metadata(const OptionsContext *o, void *log_ctx,
3197 AVFormatContext *oc, AVStream *st,
3198 AVDictionary **dict, const char *kind,
3199 unsigned reenc_mask)
3200 {
3201
2/2
✓ Branch 0 taken 362900 times.
✓ Branch 1 taken 18145 times.
381045 for (int i = 0; reenc_delete_keys[i].key; i++) {
3202 362900 const char *key = reenc_delete_keys[i].key;
3203 362900 int flags = reenc_delete_keys[i].flags;
3204 const AVDictionaryEntry *e;
3205 int ret;
3206
3207
4/4
✓ Branch 0 taken 308465 times.
✓ Branch 1 taken 54435 times.
✓ Branch 2 taken 124027 times.
✓ Branch 3 taken 184438 times.
362900 if (reenc_delete_keys[i].reenc_mask && !(reenc_delete_keys[i].reenc_mask & reenc_mask))
3208 124027 continue;
3209
3210 238873 e = NULL;
3211
2/2
✓ Branch 1 taken 1823 times.
✓ Branch 2 taken 238873 times.
240696 while ((e = av_dict_get(*dict, key, e, flags | AV_DICT_MATCH_CASE))) {
3212 1823 ret = reenc_delete_metadata_key(o, log_ctx, oc, st, key, e->key, flags);
3213
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1823 times.
1823 if (ret < 0)
3214 return ret;
3215
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1817 times.
1823 if (!ret)
3216 6 continue;
3217
2/2
✓ Branch 0 taken 396 times.
✓ Branch 1 taken 1421 times.
1817 if (reenc_mask & reenc_delete_keys[i].reenc_mask)
3218 396 av_log(log_ctx, AV_LOG_WARNING,
3219 "Discarding %s metadata '%s' because %s stream is being "
3220 "re-encoded. Use '-keep_metadata %s' to keep it.\n",
3221 396 kind, e->key,
3222
2/2
✓ Branch 0 taken 330 times.
✓ Branch 1 taken 66 times.
396 !strcmp(kind, "stream") ? "the" : "a", e->key);
3223 1817 av_dict_set(dict, e->key, NULL, 0);
3224 1817 e = NULL;
3225 }
3226 }
3227 18145 return 0;
3228 }
3229
3230 8820 static int copy_meta(Muxer *mux, const OptionsContext *o)
3231 {
3232 8820 OutputFile *of = &mux->of;
3233 8820 AVFormatContext *oc = mux->fc;
3234 8820 int chapters_input_file = o->chapters_input_file;
3235 8820 int metadata_global_manual = 0;
3236 8820 int metadata_streams_manual = 0;
3237 8820 int metadata_chapters_manual = 0;
3238 int ret;
3239
3240 /* copy metadata */
3241
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 8820 times.
8848 for (int i = 0; i < o->metadata_map.nb_opt; i++) {
3242 char *p;
3243 28 int in_file_index = strtol(o->metadata_map.opt[i].u.str, &p, 0);
3244
3245
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (in_file_index >= nb_input_files) {
3246 av_log(mux, AV_LOG_FATAL, "Invalid input file index %d while "
3247 "processing metadata maps\n", in_file_index);
3248 return AVERROR(EINVAL);
3249 }
3250 51 ret = copy_metadata(mux,
3251 8 in_file_index >= 0 ? input_files[in_file_index]->ctx : NULL,
3252
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,
3253 &metadata_global_manual, &metadata_streams_manual,
3254 &metadata_chapters_manual);
3255
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (ret < 0)
3256 return ret;
3257 }
3258
3259 /* copy chapters */
3260
1/2
✓ Branch 0 taken 8820 times.
✗ Branch 1 not taken.
8820 if (chapters_input_file >= nb_input_files) {
3261
1/2
✓ Branch 0 taken 8820 times.
✗ Branch 1 not taken.
8820 if (chapters_input_file == INT_MAX) {
3262 /* copy chapters from the first input file that has them*/
3263 8820 chapters_input_file = -1;
3264
2/2
✓ Branch 0 taken 7724 times.
✓ Branch 1 taken 8781 times.
16505 for (int i = 0; i < nb_input_files; i++)
3265
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 7685 times.
7724 if (input_files[i]->ctx->nb_chapters) {
3266 39 chapters_input_file = i;
3267 39 break;
3268 }
3269 } else {
3270 av_log(mux, AV_LOG_FATAL, "Invalid input file index %d in chapter mapping.\n",
3271 chapters_input_file);
3272 return AVERROR(EINVAL);
3273 }
3274 }
3275
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 8781 times.
8820 if (chapters_input_file >= 0)
3276 39 copy_chapters(input_files[chapters_input_file], of, oc,
3277 !metadata_chapters_manual);
3278
3279 /* copy global metadata by default */
3280
4/4
✓ Branch 0 taken 8796 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 7599 times.
✓ Branch 3 taken 1197 times.
8820 if (!metadata_global_manual && nb_input_files){
3281 7599 av_dict_copy(&oc->metadata, input_files[0]->ctx->metadata,
3282 AV_DICT_DONT_OVERWRITE);
3283
2/2
✓ Branch 0 taken 236 times.
✓ Branch 1 taken 7363 times.
7599 if (of->recording_time != INT64_MAX)
3284 236 av_dict_set(&oc->metadata, "duration", NULL, 0);
3285 7599 av_dict_set(&oc->metadata, "creation_time", NULL, 0);
3286 7599 av_dict_set(&oc->metadata, "company_name", NULL, 0);
3287 7599 av_dict_set(&oc->metadata, "product_name", NULL, 0);
3288 7599 av_dict_set(&oc->metadata, "product_version", NULL, 0);
3289
3290 }
3291
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 8818 times.
8829 for (int i = 0; i < o->keep_metadata.nb_opt; i++) {
3292 char type;
3293 11 int index = 0;
3294 11 const char *stream_spec = NULL;
3295 11 const char *spec = o->keep_metadata.opt[i].specifier;
3296 11 ret = parse_meta_type(mux, spec, &type, &index, &stream_spec);
3297
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10 times.
11 if (ret < 0)
3298 2 return ret;
3299
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') {
3300 av_log(mux, AV_LOG_WARNING,
3301 "-keep_metadata:%s: chapter and program metadata filtering "
3302 "is not supported and will be ignored.\n", spec);
3303
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 3 times.
10 } else if (type == 's') {
3304
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 6 times.
13 for (int j = 0; j < oc->nb_streams; j++) {
3305 7 ret = check_stream_specifier(oc, oc->streams[j], stream_spec);
3306
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
7 if (ret < 0)
3307 1 return ret;
3308 }
3309 }
3310 }
3311
3312 /* reenc_mask keys only apply when an audio/video stream is re-encoded;
3313 * subtitle/attachment re-encodes do not affect format-level tags.
3314 * Runs unconditionally so -map_metadata does not bypass the pruning. */
3315 {
3316 8818 unsigned reenc_mask = 0;
3317
2/2
✓ Branch 0 taken 9327 times.
✓ Branch 1 taken 8818 times.
18145 for (int i = 0; i < of->nb_streams; i++) {
3318 9327 OutputStream *ost = of->streams[i];
3319
2/2
✓ Branch 0 taken 8421 times.
✓ Branch 1 taken 906 times.
9327 if (ost->enc)
3320 8421 reenc_mask |= REENC_MASK(ost->st->codecpar->codec_type);
3321 }
3322 8818 ret = reenc_delete_stale_metadata(o, mux, oc, NULL, &oc->metadata, "format", reenc_mask);
3323
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8818 times.
8818 if (ret < 0)
3324 return ret;
3325 }
3326
2/2
✓ Branch 0 taken 8797 times.
✓ Branch 1 taken 21 times.
8818 if (!metadata_streams_manual)
3327
2/2
✓ Branch 0 taken 9303 times.
✓ Branch 1 taken 8797 times.
18100 for (int i = 0; i < of->nb_streams; i++) {
3328 9303 OutputStream *ost = of->streams[i];
3329
3330
2/2
✓ Branch 0 taken 1406 times.
✓ Branch 1 taken 7897 times.
9303 if (!ost->ist) /* this is true e.g. for attached files */
3331 1406 continue;
3332 7897 av_dict_copy(&ost->st->metadata, ost->ist->st->metadata, AV_DICT_DONT_OVERWRITE);
3333 }
3334 /* runs unconditionally so -map_metadata does not bypass the pruning;
3335 * applies to all output streams, including filter outputs without ost->ist */
3336
2/2
✓ Branch 0 taken 9327 times.
✓ Branch 1 taken 8818 times.
18145 for (int i = 0; i < of->nb_streams; i++) {
3337 9327 OutputStream *ost = of->streams[i];
3338
3339 9327 ret = reenc_delete_stale_metadata(o, ost, oc, ost->st, &ost->st->metadata, "stream",
3340
2/2
✓ Branch 0 taken 8421 times.
✓ Branch 1 taken 906 times.
9327 ost->enc ? REENC_MASK(ost->st->codecpar->codec_type) : 0);
3341
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9327 times.
9327 if (ret < 0)
3342 return ret;
3343 }
3344
3345 8818 return 0;
3346 }
3347
3348 8818 static int set_dispositions(Muxer *mux, const OptionsContext *o)
3349 {
3350 8818 OutputFile *of = &mux->of;
3351 8818 AVFormatContext *ctx = mux->fc;
3352
3353 // indexed by type+1, because AVMEDIA_TYPE_UNKNOWN=-1
3354 8818 int nb_streams[AVMEDIA_TYPE_NB + 1] = { 0 };
3355 8818 int have_default[AVMEDIA_TYPE_NB + 1] = { 0 };
3356 8818 int have_manual = 0;
3357 8818 int ret = 0;
3358
3359 const char **dispositions;
3360
3361 8818 dispositions = av_calloc(ctx->nb_streams, sizeof(*dispositions));
3362
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8818 times.
8818 if (!dispositions)
3363 return AVERROR(ENOMEM);
3364
3365 // reset any apic flag set for option stream-spec matching in ost_add
3366
2/2
✓ Branch 0 taken 9327 times.
✓ Branch 1 taken 8818 times.
18145 for (int i = 0; i < ctx->nb_streams; i++) {
3367 9327 of->streams[i]->st->disposition = 0;
3368 }
3369
3370 // first, copy the input dispositions
3371
2/2
✓ Branch 0 taken 9327 times.
✓ Branch 1 taken 8818 times.
18145 for (int i = 0; i < ctx->nb_streams; i++) {
3372 9327 OutputStream *ost = of->streams[i];
3373
3374 9327 nb_streams[ost->type + 1]++;
3375
3376 9327 opt_match_per_stream_str(ost, &o->disposition, ctx, ost->st, &dispositions[i]);
3377
3378 9327 have_manual |= !!dispositions[i];
3379
3380
2/2
✓ Branch 0 taken 7920 times.
✓ Branch 1 taken 1407 times.
9327 if (ost->ist) {
3381 7920 ost->st->disposition = ost->ist->st->disposition;
3382
3383
2/2
✓ Branch 0 taken 924 times.
✓ Branch 1 taken 6996 times.
7920 if (ost->st->disposition & AV_DISPOSITION_DEFAULT)
3384 924 have_default[ost->type + 1] = 1;
3385 }
3386 }
3387
3388
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 8809 times.
8818 if (have_manual) {
3389 // process manually set dispositions - they override the above copy
3390
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 9 times.
34 for (int i = 0; i < ctx->nb_streams; i++) {
3391 25 OutputStream *ost = of->streams[i];
3392 25 const char *disp = dispositions[i];
3393
3394
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 17 times.
25 if (!disp)
3395 8 continue;
3396
3397 17 ret = av_opt_set(ost->st, "disposition", disp, 0);
3398
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if (ret < 0)
3399 goto finish;
3400 }
3401 } else {
3402 // For each media type with more than one stream, find a suitable stream to
3403 // mark as default, unless one is already marked default.
3404 // "Suitable" means the first of that type, skipping attached pictures.
3405
2/2
✓ Branch 0 taken 9302 times.
✓ Branch 1 taken 8809 times.
18111 for (int i = 0; i < ctx->nb_streams; i++) {
3406 9302 OutputStream *ost = of->streams[i];
3407 9302 enum AVMediaType type = ost->type;
3408
3409
4/4
✓ Branch 0 taken 407 times.
✓ Branch 1 taken 8895 times.
✓ Branch 2 taken 81 times.
✓ Branch 3 taken 326 times.
9302 if (nb_streams[type + 1] < 2 || have_default[type + 1] ||
3410
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 49 times.
81 ost->st->disposition & AV_DISPOSITION_ATTACHED_PIC)
3411 9253 continue;
3412
3413 49 ost->st->disposition |= AV_DISPOSITION_DEFAULT;
3414 49 have_default[type + 1] = 1;
3415 }
3416 }
3417
3418 8809 finish:
3419 8818 av_freep(&dispositions);
3420
3421 8818 return ret;
3422 }
3423
3424 static const char *const forced_keyframes_const_names[] = {
3425 "n",
3426 "n_forced",
3427 "prev_forced_n",
3428 "prev_forced_t",
3429 "t",
3430 NULL
3431 };
3432
3433 1 static int compare_int64(const void *a, const void *b)
3434 {
3435 1 return FFDIFFSIGN(*(const int64_t *)a, *(const int64_t *)b);
3436 }
3437
3438 1 static int parse_forced_key_frames(void *log, KeyframeForceCtx *kf,
3439 const Muxer *mux, const char *spec)
3440 {
3441 1 int n = 1, i, ret, size, index = 0;
3442 int64_t t, *pts;
3443
3444
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 1 times.
14 for (const char *p = spec; *p; p++)
3445
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12 times.
13 if (*p == ',')
3446 1 n++;
3447 1 size = n;
3448
3449 1 char *spec_dup = av_strdup(spec);
3450 1 pts = av_malloc_array(size, sizeof(*pts));
3451
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) {
3452 ret = AVERROR(ENOMEM);
3453 goto fail;
3454 }
3455
3456 1 char *p = spec_dup;
3457
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 for (i = 0; i < n; i++) {
3458 2 char *next = strchr(p, ',');
3459
3460
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (next)
3461 1 *next++ = 0;
3462
3463
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (strstr(p, "chapters") == p) {
3464 AVChapter * const *ch = mux->fc->chapters;
3465 unsigned int nb_ch = mux->fc->nb_chapters;
3466 int j;
3467
3468 if (nb_ch > INT_MAX - size) {
3469 ret = AVERROR(ERANGE);
3470 goto fail;
3471 }
3472 size += nb_ch - 1;
3473 pts = av_realloc_f(pts, size, sizeof(*pts));
3474 if (!pts) {
3475 ret = AVERROR(ENOMEM);
3476 goto fail;
3477 }
3478
3479 if (p[8]) {
3480 ret = av_parse_time(&t, p + 8, 1);
3481 if (ret < 0) {
3482 av_log(log, AV_LOG_ERROR,
3483 "Invalid chapter time offset: %s\n", p + 8);
3484 goto fail;
3485 }
3486 } else
3487 t = 0;
3488
3489 for (j = 0; j < nb_ch; j++) {
3490 const AVChapter *c = ch[j];
3491 av_assert1(index < size);
3492 pts[index++] = av_rescale_q(c->start, c->time_base,
3493 AV_TIME_BASE_Q) + t;
3494 }
3495
3496 } else {
3497 av_assert1(index < size);
3498 2 ret = av_parse_time(&t, p, 1);
3499
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0) {
3500 av_log(log, AV_LOG_ERROR, "Invalid keyframe time: %s\n", p);
3501 goto fail;
3502 }
3503
3504 2 pts[index++] = t;
3505 }
3506
3507 2 p = next;
3508 }
3509
3510
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 av_assert0(index == size);
3511 1 qsort(pts, size, sizeof(*pts), compare_int64);
3512 1 kf->nb_pts = size;
3513 1 kf->pts = pts;
3514
3515 1 av_freep(&spec_dup);
3516
3517 1 return 0;
3518 fail:
3519 av_freep(&spec_dup);
3520 av_freep(&pts);
3521 return ret;
3522 }
3523
3524 8818 static int process_forced_keyframes(Muxer *mux, const OptionsContext *o)
3525 {
3526
2/2
✓ Branch 0 taken 9327 times.
✓ Branch 1 taken 8818 times.
18145 for (int i = 0; i < mux->of.nb_streams; i++) {
3527 9327 OutputStream *ost = mux->of.streams[i];
3528 9327 const char *forced_keyframes = NULL;
3529
3530 9327 opt_match_per_stream_str(ost, &o->forced_key_frames,
3531 mux->fc, ost->st, &forced_keyframes);
3532
3533
2/2
✓ Branch 0 taken 7385 times.
✓ Branch 1 taken 1942 times.
9327 if (!(ost->type == AVMEDIA_TYPE_VIDEO &&
3534
4/4
✓ Branch 0 taken 6930 times.
✓ Branch 1 taken 455 times.
✓ Branch 2 taken 6925 times.
✓ Branch 3 taken 5 times.
7385 ost->enc && forced_keyframes))
3535 9322 continue;
3536
3537
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!strncmp(forced_keyframes, "expr:", 5)) {
3538 int ret = av_expr_parse(&ost->kf.pexpr, forced_keyframes + 5,
3539 forced_keyframes_const_names, NULL, NULL, NULL, NULL, 0, NULL);
3540 if (ret < 0) {
3541 av_log(ost, AV_LOG_ERROR,
3542 "Invalid force_key_frames expression '%s'\n", forced_keyframes + 5);
3543 return ret;
3544 }
3545 ost->kf.expr_const_values[FKF_N] = 0;
3546 ost->kf.expr_const_values[FKF_N_FORCED] = 0;
3547 ost->kf.expr_const_values[FKF_PREV_FORCED_N] = NAN;
3548 ost->kf.expr_const_values[FKF_PREV_FORCED_T] = NAN;
3549
3550 // Don't parse the 'forced_keyframes' in case of 'keep-source-keyframes',
3551 // parse it only for static kf timings
3552
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
5 } else if (!strcmp(forced_keyframes, "source")) {
3553 3 ost->kf.type = KF_FORCE_SOURCE;
3554
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 } else if (!strcmp(forced_keyframes, "scd_metadata")) {
3555 1 ost->kf.type = KF_FORCE_SCD_METADATA;
3556 } else {
3557 1 int ret = parse_forced_key_frames(ost, &ost->kf, mux, forced_keyframes);
3558
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
3559 return ret;
3560 }
3561 }
3562
3563 8818 return 0;
3564 }
3565
3566 9353 static const char *output_file_item_name(void *obj)
3567 {
3568 9353 const Muxer *mux = obj;
3569
3570 9353 return mux->log_name;
3571 }
3572
3573 static const AVClass output_file_class = {
3574 .class_name = "OutputFile",
3575 .version = LIBAVUTIL_VERSION_INT,
3576 .item_name = output_file_item_name,
3577 .category = AV_CLASS_CATEGORY_MUXER,
3578 };
3579
3580 8823 static Muxer *mux_alloc(void)
3581 {
3582 8823 Muxer *mux = allocate_array_elem(&output_files, sizeof(*mux), &nb_output_files);
3583
3584
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8823 times.
8823 if (!mux)
3585 return NULL;
3586
3587 8823 mux->of.class = &output_file_class;
3588 8823 mux->of.index = nb_output_files - 1;
3589
3590 8823 snprintf(mux->log_name, sizeof(mux->log_name), "out#%d", mux->of.index);
3591
3592 8823 return mux;
3593 }
3594
3595 8823 int of_open(const OptionsContext *o, const char *filename, Scheduler *sch)
3596 {
3597 Muxer *mux;
3598 AVFormatContext *oc;
3599 int err;
3600 OutputFile *of;
3601
3602 8823 int64_t recording_time = o->recording_time;
3603 8823 int64_t stop_time = o->stop_time;
3604
3605 8823 mux = mux_alloc();
3606
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8823 times.
8823 if (!mux)
3607 return AVERROR(ENOMEM);
3608
3609 8823 of = &mux->of;
3610
3611
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8823 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8823 if (stop_time != INT64_MAX && recording_time != INT64_MAX) {
3612 stop_time = INT64_MAX;
3613 av_log(mux, AV_LOG_WARNING, "-t and -to cannot be used together; using -t.\n");
3614 }
3615
3616
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8823 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8823 if (stop_time != INT64_MAX && recording_time == INT64_MAX) {
3617 int64_t start_time = o->start_time == AV_NOPTS_VALUE ? 0 : o->start_time;
3618 if (stop_time <= start_time) {
3619 av_log(mux, AV_LOG_ERROR, "-to value smaller than -ss; aborting.\n");
3620 return AVERROR(EINVAL);
3621 } else {
3622 recording_time = stop_time - start_time;
3623 }
3624 }
3625
3626
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8822 times.
8823 if (recording_time < 0) {
3627 1 av_log(mux, AV_LOG_ERROR, "-t value must be non-negative; aborting.\n");
3628 1 return AVERROR(EINVAL);
3629 }
3630
3631 8822 of->recording_time = recording_time;
3632 8822 of->start_time = o->start_time;
3633
3634 8822 mux->limit_filesize = o->limit_filesize;
3635 8822 av_dict_copy(&mux->opts, o->g->format_opts, 0);
3636
3637
2/2
✓ Branch 0 taken 2898 times.
✓ Branch 1 taken 5924 times.
8822 if (!strcmp(filename, "-"))
3638 2898 filename = "pipe:";
3639
3640 8822 err = avformat_alloc_output_context2(&oc, NULL, o->format, filename);
3641
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8822 times.
8822 if (!oc) {
3642 av_log(mux, AV_LOG_FATAL, "Error initializing the muxer for %s: %s\n",
3643 filename, av_err2str(err));
3644 return err;
3645 }
3646 8822 mux->fc = oc;
3647
3648 8822 av_strlcat(mux->log_name, "/", sizeof(mux->log_name));
3649 8822 av_strlcat(mux->log_name, oc->oformat->name, sizeof(mux->log_name));
3650
3651
3652
2/2
✓ Branch 0 taken 1349 times.
✓ Branch 1 taken 7473 times.
8822 if (recording_time != INT64_MAX)
3653 1349 oc->duration = recording_time;
3654
3655 8822 oc->interrupt_callback = int_cb;
3656
3657
2/2
✓ Branch 0 taken 1982 times.
✓ Branch 1 taken 6840 times.
8822 if (o->bitexact) {
3658 1982 oc->flags |= AVFMT_FLAG_BITEXACT;
3659 1982 of->bitexact = 1;
3660 } else {
3661 6840 of->bitexact = check_opt_bitexact(oc, mux->opts, "fflags",
3662 AVFMT_FLAG_BITEXACT);
3663 }
3664
3665 8822 err = sch_add_mux(sch, muxer_thread, mux_check_init, mux,
3666 8822 !strcmp(oc->oformat->name, "rtp"), o->thread_queue_size);
3667
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8822 times.
8822 if (err < 0)
3668 return err;
3669 8822 mux->sch = sch;
3670 8822 mux->sch_idx = err;
3671
3672 /* create all output streams for this file */
3673 8822 err = create_streams(mux, o);
3674
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8821 times.
8822 if (err < 0)
3675 1 return err;
3676
3677 /* check if all codec options have been used */
3678 8821 err = check_avoptions_used(o->g->codec_opts, mux->enc_opts_used, mux, 0);
3679 8821 av_dict_free(&mux->enc_opts_used);
3680
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8821 times.
8821 if (err < 0)
3681 return err;
3682
3683 /* check filename in case of an image number is expected */
3684
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8821 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
8821 if (oc->oformat->flags & AVFMT_NEEDNUMBER && !av_filename_number_test(oc->url)) {
3685 av_log(mux, AV_LOG_FATAL,
3686 "Output filename '%s' does not contain a numeric pattern like "
3687 "'%%d', which is required by output format '%s'.\n",
3688 oc->url, oc->oformat->name);
3689 return AVERROR(EINVAL);
3690 }
3691
3692
2/2
✓ Branch 0 taken 8682 times.
✓ Branch 1 taken 139 times.
8821 if (!(oc->oformat->flags & AVFMT_NOFILE)) {
3693 /* test if it already exists to avoid losing precious files */
3694 8682 err = assert_file_overwrite(filename);
3695
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8681 times.
8682 if (err < 0)
3696 1 return err;
3697
3698 /* open the file */
3699
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8681 times.
8681 if ((err = avio_open2(&oc->pb, filename, AVIO_FLAG_WRITE,
3700 8681 &oc->interrupt_callback,
3701 &mux->opts)) < 0) {
3702 av_log(mux, AV_LOG_FATAL, "Error opening output %s: %s\n",
3703 filename, av_err2str(err));
3704 return err;
3705 }
3706
4/4
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 76 times.
✓ Branch 3 taken 11 times.
✓ Branch 4 taken 52 times.
139 } else if (strcmp(oc->oformat->name, "image2")==0 && !av_filename_number_test(filename)) {
3707 11 err = assert_file_overwrite(filename);
3708
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (err < 0)
3709 return err;
3710 }
3711
3712
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8820 times.
8820 if (o->mux_preload) {
3713 av_dict_set_int(&mux->opts, "preload", o->mux_preload*AV_TIME_BASE, 0);
3714 }
3715 8820 oc->max_delay = (int)(o->mux_max_delay * AV_TIME_BASE);
3716
3717 /* copy metadata and chapters from input files */
3718 8820 err = copy_meta(mux, o);
3719
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8818 times.
8820 if (err < 0)
3720 2 return err;
3721
3722 8818 err = of_add_groups(mux, o);
3723
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8818 times.
8818 if (err < 0)
3724 return err;
3725
3726 8818 err = of_add_programs(mux, o);
3727
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8818 times.
8818 if (err < 0)
3728 return err;
3729
3730 8818 err = of_add_metadata(of, oc, o);
3731
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8818 times.
8818 if (err < 0)
3732 return err;
3733
3734 8818 err = set_dispositions(mux, o);
3735
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8818 times.
8818 if (err < 0) {
3736 av_log(mux, AV_LOG_FATAL, "Error setting output stream dispositions\n");
3737 return err;
3738 }
3739
3740 // parse forced keyframe specifications;
3741 // must be done after chapters are created
3742 8818 err = process_forced_keyframes(mux, o);
3743
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8818 times.
8818 if (err < 0) {
3744 av_log(mux, AV_LOG_FATAL, "Error processing forced keyframes\n");
3745 return err;
3746 }
3747
3748 8818 err = setup_sync_queues(mux, oc, o->shortest_buf_duration * AV_TIME_BASE,
3749 8818 o->shortest);
3750
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8818 times.
8818 if (err < 0) {
3751 av_log(mux, AV_LOG_FATAL, "Error setting up output sync queues\n");
3752 return err;
3753 }
3754
3755 8818 of->url = filename;
3756
3757 /* initialize streamcopy streams. */
3758
2/2
✓ Branch 0 taken 9327 times.
✓ Branch 1 taken 8818 times.
18145 for (int i = 0; i < of->nb_streams; i++) {
3759 9327 OutputStream *ost = of->streams[i];
3760
3761
2/2
✓ Branch 0 taken 906 times.
✓ Branch 1 taken 8421 times.
9327 if (!ost->enc) {
3762 906 err = of_stream_init(of, ost, NULL);
3763
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 906 times.
906 if (err < 0)
3764 return err;
3765 }
3766 }
3767
3768 8818 return 0;
3769 }
3770