FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/fftools/ffmpeg_mux_init.c
Date: 2026-08-26 01:27:24
Exec Total Coverage
Lines: 1448 2128 68.0%
Functions: 46 53 86.8%
Branches: 1001 1658 60.4%

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