FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavfilter/graphparser.c
Date: 2026-09-28 04:46:15
Exec Total Coverage
Lines: 354 586 60.4%
Functions: 23 28 82.1%
Branches: 204 362 56.4%

Line Branch Exec Source
1 /*
2 * filter graph parser
3 * Copyright (c) 2008 Vitor Sessak
4 * Copyright (c) 2007 Bobby Bingham
5 *
6 * This file is part of FFmpeg.
7 *
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 #include <string.h>
24 #include <stdio.h>
25
26 #include "libavutil/avstring.h"
27 #include "libavutil/dict.h"
28 #include "libavutil/mem.h"
29 #include "libavutil/opt.h"
30
31 #include "avfilter.h"
32 #include "avfilter_internal.h"
33 #include "filters.h"
34
35 #define WHITESPACES " \n\t\r"
36
37 /**
38 * Parse the name of a link, which has the format "[linkname]".
39 *
40 * @return a pointer (that need to be freed after use) to the name
41 * between parenthesis
42 */
43 1239 static char *parse_link_name(const char **buf, void *log_ctx)
44 {
45 1239 const char *start = *buf;
46 char *name;
47 1239 (*buf)++;
48
49 1239 name = av_get_token(buf, "]");
50
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1239 times.
1239 if (!name)
51 ✗ return NULL;
52
53
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1239 times.
1239 if (!name[0]) {
54 ✗ av_log(log_ctx, AV_LOG_ERROR,
55 "Bad (empty?) label found in the following: \"%s\".\n", start);
56 ✗ goto fail;
57 }
58
59
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1239 times.
1239 if (**buf != ']') {
60 ✗ av_log(log_ctx, AV_LOG_ERROR,
61 "Mismatched '[' found in the following: \"%s\".\n", start);
62 ✗ fail:
63 ✗ av_freep(&name);
64 ✗ return NULL;
65 }
66 1239 (*buf)++;
67
68 1239 return name;
69 }
70
71 ✗ AVFilterInOut *avfilter_inout_alloc(void)
72 {
73 ✗ return av_mallocz(sizeof(AVFilterInOut));
74 }
75
76 33420 void avfilter_inout_free(AVFilterInOut **inout)
77 {
78
2/2
✓ Branch 0 taken 31277 times.
✓ Branch 1 taken 33420 times.
64697 while (*inout) {
79 31277 AVFilterInOut *next = (*inout)->next;
80 31277 av_freep(&(*inout)->name);
81 31277 av_freep(inout);
82 31277 *inout = next;
83 }
84 33420 }
85
86 78 static AVFilterInOut *extract_inout(const char *label, AVFilterInOut **links)
87 {
88 AVFilterInOut *ret;
89
90
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 78 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
78 while (*links && (!(*links)->name || strcmp((*links)->name, label)))
91 ✗ links = &((*links)->next);
92
93 78 ret = *links;
94
95
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 78 times.
78 if (ret) {
96 ✗ *links = ret->next;
97 ✗ ret->next = NULL;
98 }
99
100 78 return ret;
101 }
102
103 31355 static void append_inout(AVFilterInOut **inouts, AVFilterInOut **element)
104 {
105
4/4
✓ Branch 0 taken 5254 times.
✓ Branch 1 taken 30866 times.
✓ Branch 2 taken 4765 times.
✓ Branch 3 taken 489 times.
36120 while (*inouts && (*inouts)->next)
106 4765 inouts = &((*inouts)->next);
107
108
2/2
✓ Branch 0 taken 30866 times.
✓ Branch 1 taken 489 times.
31355 if (!*inouts)
109 30866 *inouts = *element;
110 else
111 489 (*inouts)->next = *element;
112 31355 *element = NULL;
113 31355 }
114
115 16635 static int parse_sws_flags(const char **buf, char **dst, void *log_ctx)
116 {
117
2/2
✓ Branch 0 taken 16584 times.
✓ Branch 1 taken 51 times.
16635 if (strncmp(*buf, "sws_flags=", 10))
118 16584 return 0;
119
120 51 const char *p = strchr(*buf, ';');
121
122
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
51 if (!p) {
123 ✗ av_log(log_ctx, AV_LOG_ERROR, "sws_flags not terminated with ';'.\n");
124 ✗ return AVERROR(EINVAL);
125 }
126
127 51 *buf += 4; // keep the 'flags=' part
128
129 51 av_freep(dst);
130
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 51 times.
51 if (!(*dst = av_mallocz(p - *buf + 1)))
131 ✗ return AVERROR(ENOMEM);
132 51 av_strlcpy(*dst, *buf, p - *buf + 1);
133
134 51 *buf = p + 1;
135 51 return 0;
136 }
137
138 ✗ int avfilter_graph_parse2(AVFilterGraph *graph, const char *filters,
139 AVFilterInOut **inputs,
140 AVFilterInOut **outputs)
141 {
142 AVFilterGraphSegment *seg;
143 int ret;
144
145 ✗ ret = avfilter_graph_segment_parse(graph, filters, 0, &seg);
146 ✗ if (ret < 0)
147 ✗ return ret;
148
149 ✗ ret = avfilter_graph_segment_apply(seg, 0, inputs, outputs);
150 ✗ avfilter_graph_segment_free(&seg);
151 ✗ if (ret < 0)
152 ✗ goto end;
153
154 ✗ return 0;
155
156 ✗ end:
157 ✗ while (graph->nb_filters)
158 ✗ avfilter_free(graph->filters[0]);
159 ✗ av_freep(&graph->filters);
160
161 ✗ return ret;
162 }
163
164 ✗ int avfilter_graph_parse(AVFilterGraph *graph, const char *filters,
165 AVFilterInOut *open_inputs,
166 AVFilterInOut *open_outputs, void *log_ctx)
167 {
168 int ret;
169 ✗ AVFilterInOut *cur, *match, *inputs = NULL, *outputs = NULL;
170
171 ✗ if ((ret = avfilter_graph_parse2(graph, filters, &inputs, &outputs)) < 0)
172 ✗ goto fail;
173
174 /* First input can be omitted if it is "[in]" */
175 ✗ if (inputs && !inputs->name)
176 ✗ inputs->name = av_strdup("in");
177 ✗ for (cur = inputs; cur; cur = cur->next) {
178 ✗ if (!cur->name) {
179 ✗ av_log(log_ctx, AV_LOG_ERROR,
180 "Not enough inputs specified for the \"%s\" filter.\n",
181 ✗ cur->filter_ctx->filter->name);
182 ✗ ret = AVERROR(EINVAL);
183 ✗ goto fail;
184 }
185 ✗ if (!(match = extract_inout(cur->name, &open_outputs)))
186 ✗ continue;
187 ✗ ret = avfilter_link(match->filter_ctx, match->pad_idx,
188 ✗ cur->filter_ctx, cur->pad_idx);
189 ✗ avfilter_inout_free(&match);
190 ✗ if (ret < 0)
191 ✗ goto fail;
192 }
193
194 /* Last output can be omitted if it is "[out]" */
195 ✗ if (outputs && !outputs->name)
196 ✗ outputs->name = av_strdup("out");
197 ✗ for (cur = outputs; cur; cur = cur->next) {
198 ✗ if (!cur->name) {
199 ✗ av_log(log_ctx, AV_LOG_ERROR,
200 "Invalid filterchain containing an unlabelled output pad: \"%s\"\n",
201 filters);
202 ✗ ret = AVERROR(EINVAL);
203 ✗ goto fail;
204 }
205 ✗ if (!(match = extract_inout(cur->name, &open_inputs)))
206 ✗ continue;
207 ✗ ret = avfilter_link(cur->filter_ctx, cur->pad_idx,
208 ✗ match->filter_ctx, match->pad_idx);
209 ✗ avfilter_inout_free(&match);
210 ✗ if (ret < 0)
211 ✗ goto fail;
212 }
213
214 ✗ fail:
215 ✗ if (ret < 0) {
216 ✗ while (graph->nb_filters)
217 ✗ avfilter_free(graph->filters[0]);
218 ✗ av_freep(&graph->filters);
219 }
220 ✗ avfilter_inout_free(&inputs);
221 ✗ avfilter_inout_free(&outputs);
222 ✗ avfilter_inout_free(&open_inputs);
223 ✗ avfilter_inout_free(&open_outputs);
224 ✗ return ret;
225 }
226
227 1239 static void pad_params_free(AVFilterPadParams **pfpp)
228 {
229 1239 AVFilterPadParams *fpp = *pfpp;
230
231
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1239 times.
1239 if (!fpp)
232 ✗ return;
233
234 1239 av_freep(&fpp->label);
235
236 1239 av_freep(pfpp);
237 }
238
239 37573 static void filter_params_free(AVFilterParams **pp)
240 {
241 37573 AVFilterParams *p = *pp;
242
243
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37573 times.
37573 if (!p)
244 ✗ return;
245
246
2/2
✓ Branch 0 taken 618 times.
✓ Branch 1 taken 37573 times.
38191 for (unsigned i = 0; i < p->nb_inputs; i++)
247 618 pad_params_free(&p->inputs[i]);
248 37573 av_freep(&p->inputs);
249
250
2/2
✓ Branch 0 taken 621 times.
✓ Branch 1 taken 37573 times.
38194 for (unsigned i = 0; i < p->nb_outputs; i++)
251 621 pad_params_free(&p->outputs[i]);
252 37573 av_freep(&p->outputs);
253
254 37573 av_dict_free(&p->opts);
255
256 37573 av_freep(&p->filter_name);
257 37573 av_freep(&p->instance_name);
258
259 37573 av_freep(pp);
260 }
261
262 17073 static void chain_free(AVFilterChain **pch)
263 {
264 17073 AVFilterChain *ch = *pch;
265
266
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17073 times.
17073 if (!ch)
267 ✗ return;
268
269
2/2
✓ Branch 0 taken 37573 times.
✓ Branch 1 taken 17073 times.
54646 for (size_t i = 0; i < ch->nb_filters; i++)
270 37573 filter_params_free(&ch->filters[i]);
271 17073 av_freep(&ch->filters);
272
273 17073 av_freep(pch);
274 }
275
276 16710 void avfilter_graph_segment_free(AVFilterGraphSegment **pseg)
277 {
278 16710 AVFilterGraphSegment *seg = *pseg;
279
280
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 16635 times.
16710 if (!seg)
281 75 return;
282
283
2/2
✓ Branch 0 taken 17073 times.
✓ Branch 1 taken 16635 times.
33708 for (size_t i = 0; i < seg->nb_chains; i++)
284 17073 chain_free(&seg->chains[i]);
285 16635 av_freep(&seg->chains);
286
287 16635 av_freep(&seg->scale_sws_opts);
288
289 16635 av_freep(pseg);
290 }
291
292 75213 static int linklabels_parse(void *logctx, const char **linklabels,
293 AVFilterPadParams ***res, unsigned *nb_res)
294 {
295 75213 AVFilterPadParams **pp = NULL;
296 75213 int nb = 0;
297 int ret;
298
299
2/2
✓ Branch 0 taken 1239 times.
✓ Branch 1 taken 75213 times.
76452 while (**linklabels == '[') {
300 char *label;
301 AVFilterPadParams *par;
302
303 1239 label = parse_link_name(linklabels, logctx);
304
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1239 times.
1239 if (!label) {
305 ✗ ret = AVERROR(EINVAL);
306 ✗ goto fail;
307 }
308
309 1239 par = av_mallocz(sizeof(*par));
310
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1239 times.
1239 if (!par) {
311 ✗ av_freep(&label);
312 ✗ ret = AVERROR(ENOMEM);
313 ✗ goto fail;
314 }
315
316 1239 par->label = label;
317
318 1239 ret = av_dynarray_add_nofree(&pp, &nb, par);
319
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1239 times.
1239 if (ret < 0) {
320 ✗ pad_params_free(&par);
321 ✗ goto fail;
322 }
323
324 1239 *linklabels += strspn(*linklabels, WHITESPACES);
325 }
326
327 75213 *res = pp;
328 75213 *nb_res = nb;
329
330 75213 return 0;
331 ✗ fail:
332 ✗ for (unsigned i = 0; i < nb; i++)
333 ✗ pad_params_free(&pp[i]);
334 ✗ av_freep(&pp);
335 ✗ return ret;
336 }
337
338 37573 static int filter_parse(void *logctx, const char **filter,
339 AVFilterParams **pp)
340 {
341 AVFilterParams *p;
342 char *inst_name;
343 int ret;
344
345 37573 p = av_mallocz(sizeof(*p));
346
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37573 times.
37573 if (!p)
347 ✗ return AVERROR(ENOMEM);
348
349 37573 ret = linklabels_parse(logctx, filter, &p->inputs, &p->nb_inputs);
350
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37573 times.
37573 if (ret < 0)
351 ✗ goto fail;
352
353 37573 p->filter_name = av_get_token(filter, "=,;[");
354
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37573 times.
37573 if (!p->filter_name) {
355 ✗ ret = AVERROR(ENOMEM);
356 ✗ goto fail;
357 }
358
359 37573 inst_name = strchr(p->filter_name, '@');
360
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37573 times.
37573 if (inst_name) {
361 ✗ *inst_name++ = 0;
362 ✗ p->instance_name = av_strdup(inst_name);
363 ✗ if (!p->instance_name) {
364 ✗ ret = AVERROR(ENOMEM);
365 ✗ goto fail;
366 }
367 }
368
369
2/2
✓ Branch 0 taken 23930 times.
✓ Branch 1 taken 13643 times.
37573 if (**filter == '=') {
370 23930 const AVFilter *f = avfilter_get_by_name(p->filter_name);
371 char *opts;
372
373 23930 (*filter)++;
374
375 23930 opts = av_get_token(filter, "[],;");
376
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23930 times.
23930 if (!opts) {
377 ✗ ret = AVERROR(ENOMEM);
378 ✗ goto fail;
379 }
380
381 23930 ret = ff_filter_opt_parse(logctx, f ? f->priv_class : NULL,
382
1/2
✓ Branch 0 taken 23930 times.
✗ Branch 1 not taken.
23930 &p->opts, opts);
383 23930 av_freep(&opts);
384
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23930 times.
23930 if (ret < 0)
385 ✗ goto fail;
386 }
387
388 37573 ret = linklabels_parse(logctx, filter, &p->outputs, &p->nb_outputs);
389
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37573 times.
37573 if (ret < 0)
390 ✗ goto fail;
391
392 37573 *filter += strspn(*filter, WHITESPACES);
393
394 37573 *pp = p;
395 37573 return 0;
396 ✗ fail:
397 ✗ av_log(logctx, AV_LOG_ERROR,
398 "Error parsing a filter description around: %s\n", *filter);
399 ✗ filter_params_free(&p);
400 ✗ return ret;
401 }
402
403 17073 static int chain_parse(void *logctx, const char **pchain,
404 AVFilterChain **pch)
405 {
406 17073 const char *chain = *pchain;
407 AVFilterChain *ch;
408 17073 int ret, nb_filters = 0;
409
410 17073 *pch = NULL;
411
412 17073 ch = av_mallocz(sizeof(*ch));
413
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17073 times.
17073 if (!ch)
414 ✗ return AVERROR(ENOMEM);
415
416
2/2
✓ Branch 0 taken 37573 times.
✓ Branch 1 taken 16613 times.
54186 while (*chain) {
417 AVFilterParams *p;
418 char chr;
419
420 37573 ret = filter_parse(logctx, &chain, &p);
421
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37573 times.
37573 if (ret < 0)
422 ✗ goto fail;
423
424 37573 ret = av_dynarray_add_nofree(&ch->filters, &nb_filters, p);
425
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37573 times.
37573 if (ret < 0) {
426 ✗ filter_params_free(&p);
427 ✗ goto fail;
428 }
429 37573 ch->nb_filters = nb_filters;
430
431 // a filter ends with one of: , ; end-of-string
432 37573 chr = *chain;
433
5/6
✓ Branch 0 taken 20960 times.
✓ Branch 1 taken 16613 times.
✓ Branch 2 taken 460 times.
✓ Branch 3 taken 20500 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 460 times.
37573 if (chr && chr != ',' && chr != ';') {
434 ✗ av_log(logctx, AV_LOG_ERROR,
435 "Trailing garbage after a filter: %s\n", chain);
436 ✗ ret = AVERROR(EINVAL);
437 ✗ goto fail;
438 }
439
440
2/2
✓ Branch 0 taken 20960 times.
✓ Branch 1 taken 16613 times.
37573 if (chr) {
441 20960 chain++;
442 20960 chain += strspn(chain, WHITESPACES);
443
444
2/2
✓ Branch 0 taken 460 times.
✓ Branch 1 taken 20500 times.
20960 if (chr == ';')
445 460 break;
446 }
447 }
448
449 17073 *pchain = chain;
450 17073 *pch = ch;
451
452 17073 return 0;
453 ✗ fail:
454 ✗ av_log(logctx, AV_LOG_ERROR,
455 "Error parsing filterchain '%s' around: %s\n", *pchain, chain);
456 ✗ chain_free(&ch);
457 ✗ return ret;
458 }
459
460 16635 int avfilter_graph_segment_parse(AVFilterGraph *graph, const char *graph_str,
461 int flags, AVFilterGraphSegment **pseg)
462 {
463 AVFilterGraphSegment *seg;
464 16635 int ret, nb_chains = 0;
465
466 16635 *pseg = NULL;
467
468
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16635 times.
16635 if (flags)
469 ✗ return AVERROR(ENOSYS);
470
471 16635 seg = av_mallocz(sizeof(*seg));
472
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16635 times.
16635 if (!seg)
473 ✗ return AVERROR(ENOMEM);
474
475 16635 seg->graph = graph;
476
477 16635 graph_str += strspn(graph_str, WHITESPACES);
478
479 16635 ret = parse_sws_flags(&graph_str, &seg->scale_sws_opts, graph);
480
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16635 times.
16635 if (ret < 0)
481 ✗ goto fail;
482
483 16635 graph_str += strspn(graph_str, WHITESPACES);
484
485
2/2
✓ Branch 0 taken 17073 times.
✓ Branch 1 taken 16635 times.
33708 while (*graph_str) {
486 AVFilterChain *ch;
487
488 17073 ret = chain_parse(graph, &graph_str, &ch);
489
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17073 times.
17073 if (ret < 0)
490 ✗ goto fail;
491
492 17073 ret = av_dynarray_add_nofree(&seg->chains, &nb_chains, ch);
493
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17073 times.
17073 if (ret < 0) {
494 ✗ chain_free(&ch);
495 ✗ goto fail;
496 }
497 17073 seg->nb_chains = nb_chains;
498
499 17073 graph_str += strspn(graph_str, WHITESPACES);
500 }
501
502
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16635 times.
16635 if (!seg->nb_chains) {
503 ✗ av_log(graph, AV_LOG_ERROR, "No filters specified in the graph description\n");
504 ✗ ret = AVERROR(EINVAL);
505 ✗ goto fail;
506 }
507
508 16635 *pseg = seg;
509
510 16635 return 0;
511 ✗ fail:
512 ✗ avfilter_graph_segment_free(&seg);
513 ✗ return ret;
514 }
515
516 33270 int avfilter_graph_segment_create_filters(AVFilterGraphSegment *seg, int flags)
517 {
518 33270 size_t idx = 0;
519
520
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33270 times.
33270 if (flags)
521 ✗ return AVERROR(ENOSYS);
522
523
2/2
✓ Branch 0 taken 102 times.
✓ Branch 1 taken 33168 times.
33270 if (seg->scale_sws_opts) {
524 102 av_freep(&seg->graph->scale_sws_opts);
525 102 seg->graph->scale_sws_opts = av_strdup(seg->scale_sws_opts);
526
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 102 times.
102 if (!seg->graph->scale_sws_opts)
527 ✗ return AVERROR(ENOMEM);
528 }
529
530
2/2
✓ Branch 0 taken 34146 times.
✓ Branch 1 taken 33270 times.
67416 for (size_t i = 0; i < seg->nb_chains; i++) {
531 34146 AVFilterChain *ch = seg->chains[i];
532
533
2/2
✓ Branch 0 taken 75146 times.
✓ Branch 1 taken 34146 times.
109292 for (size_t j = 0; j < ch->nb_filters; j++) {
534 75146 AVFilterParams *p = ch->filters[j];
535 75146 const AVFilter *f = avfilter_get_by_name(p->filter_name);
536 char name[64];
537
538 // skip already processed filters
539
3/4
✓ Branch 0 taken 37573 times.
✓ Branch 1 taken 37573 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 37573 times.
75146 if (p->filter || !p->filter_name)
540 37573 continue;
541
542
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37573 times.
37573 if (!f) {
543 ✗ av_log(seg->graph, AV_LOG_ERROR,
544 "No such filter: '%s'\n", p->filter_name);
545 ✗ return AVERROR_FILTER_NOT_FOUND;
546 }
547
548
1/2
✓ Branch 0 taken 37573 times.
✗ Branch 1 not taken.
37573 if (!p->instance_name)
549 37573 snprintf(name, sizeof(name), "Parsed_%s_%zu", f->name, idx);
550 else
551 ✗ snprintf(name, sizeof(name), "%s@%s", f->name, p->instance_name);
552
553 37573 p->filter = avfilter_graph_alloc_filter(seg->graph, f, name);
554
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37573 times.
37573 if (!p->filter)
555 ✗ return AVERROR(ENOMEM);
556
557
4/4
✓ Branch 0 taken 9209 times.
✓ Branch 1 taken 28364 times.
✓ Branch 2 taken 3141 times.
✓ Branch 3 taken 6068 times.
37573 if (!strcmp(f->name, "scale") && seg->graph->scale_sws_opts) {
558 3141 int ret = av_set_options_string(p->filter, seg->graph->scale_sws_opts,
559 "=", ":");
560
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3141 times.
3141 if (ret < 0) {
561 ✗ avfilter_free(p->filter);
562 ✗ p->filter = NULL;
563 ✗ return ret;
564 }
565 }
566
567 37573 av_freep(&p->filter_name);
568 37573 av_freep(&p->instance_name);
569
570 37573 idx++;
571 }
572 }
573
574 33270 return 0;
575 }
576
577 ✗ static int fail_creation_pending(AVFilterGraphSegment *seg, const char *fn,
578 const char *func)
579 {
580 ✗ av_log(seg->graph, AV_LOG_ERROR,
581 "A creation-pending filter '%s' present in the segment. All filters "
582 "must be created or disabled before calling %s().\n", fn, func);
583 ✗ return AVERROR(EINVAL);
584 }
585
586 16710 int avfilter_graph_segment_apply_opts(AVFilterGraphSegment *seg, int flags)
587 {
588 16710 int ret, leftover_opts = 0;
589
590
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16710 times.
16710 if (flags)
591 ✗ return AVERROR(ENOSYS);
592
593
2/2
✓ Branch 0 taken 17154 times.
✓ Branch 1 taken 16710 times.
33864 for (size_t i = 0; i < seg->nb_chains; i++) {
594 17154 AVFilterChain *ch = seg->chains[i];
595
596
2/2
✓ Branch 0 taken 37689 times.
✓ Branch 1 taken 17154 times.
54843 for (size_t j = 0; j < ch->nb_filters; j++) {
597 37689 AVFilterParams *p = ch->filters[j];
598
599
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37689 times.
37689 if (p->filter_name)
600 ✗ return fail_creation_pending(seg, p->filter_name, __func__);
601
3/4
✓ Branch 0 taken 37689 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 37581 times.
✓ Branch 3 taken 108 times.
37689 if (!p->filter || !p->opts)
602 37581 continue;
603
604 108 ret = av_opt_set_dict2(p->filter, &p->opts, AV_OPT_SEARCH_CHILDREN);
605
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 108 times.
108 if (ret < 0)
606 ✗ return ret;
607
608
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 108 times.
108 if (av_dict_count(p->opts))
609 ✗ leftover_opts = 1;
610 }
611 }
612
613
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16710 times.
16710 return leftover_opts ? AVERROR_OPTION_NOT_FOUND : 0;
614 }
615
616 16710 int avfilter_graph_segment_init(AVFilterGraphSegment *seg, int flags)
617 {
618
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16710 times.
16710 if (flags)
619 ✗ return AVERROR(ENOSYS);
620
621
2/2
✓ Branch 0 taken 17154 times.
✓ Branch 1 taken 16709 times.
33863 for (size_t i = 0; i < seg->nb_chains; i++) {
622 17154 AVFilterChain *ch = seg->chains[i];
623
624
2/2
✓ Branch 0 taken 37689 times.
✓ Branch 1 taken 17153 times.
54842 for (size_t j = 0; j < ch->nb_filters; j++) {
625 37689 AVFilterParams *p = ch->filters[j];
626 int ret;
627
628
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37689 times.
37689 if (p->filter_name)
629 ✗ return fail_creation_pending(seg, p->filter_name, __func__);
630
1/2
✓ Branch 0 taken 37689 times.
✗ Branch 1 not taken.
37689 if (!p->filter ||
631
2/2
✓ Branch 1 taken 116 times.
✓ Branch 2 taken 37573 times.
37689 (fffilterctx(p->filter)->state_flags & AV_CLASS_STATE_INITIALIZED))
632 116 continue;
633
634 37573 ret = avfilter_init_dict(p->filter, NULL);
635
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 37572 times.
37573 if (ret < 0)
636 1 return ret;
637 }
638 }
639
640 16709 return 0;
641 }
642
643 static unsigned
644 875 find_linklabel(AVFilterGraphSegment *seg, const char *label,
645 int output, size_t idx_chain, size_t idx_filter,
646 AVFilterParams **pp)
647 {
648
2/2
✓ Branch 0 taken 6498 times.
✓ Branch 1 taken 511 times.
7009 for (; idx_chain < seg->nb_chains; idx_chain++) {
649 6498 AVFilterChain *ch = seg->chains[idx_chain];
650
651
2/2
✓ Branch 0 taken 6568 times.
✓ Branch 1 taken 6134 times.
12702 for (; idx_filter < ch->nb_filters; idx_filter++) {
652 6568 AVFilterParams *p = ch->filters[idx_filter];
653
2/2
✓ Branch 0 taken 720 times.
✓ Branch 1 taken 5848 times.
6568 AVFilterPadParams **io = output ? p->outputs : p->inputs;
654
2/2
✓ Branch 0 taken 720 times.
✓ Branch 1 taken 5848 times.
6568 unsigned nb_io = output ? p->nb_outputs : p->nb_inputs;
655 AVFilterLink **l;
656 unsigned nb_l;
657
658
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6568 times.
6568 if (!p->filter)
659 ✗ continue;
660
661
2/2
✓ Branch 0 taken 720 times.
✓ Branch 1 taken 5848 times.
6568 l = output ? p->filter->outputs : p->filter->inputs;
662
2/2
✓ Branch 0 taken 720 times.
✓ Branch 1 taken 5848 times.
6568 nb_l = output ? p->filter->nb_outputs : p->filter->nb_inputs;
663
664
2/2
✓ Branch 0 taken 6194 times.
✓ Branch 1 taken 6204 times.
12398 for (unsigned i = 0; i < FFMIN(nb_io, nb_l); i++)
665
5/6
✓ Branch 0 taken 1756 times.
✓ Branch 1 taken 4438 times.
✓ Branch 2 taken 1756 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 364 times.
✓ Branch 5 taken 1392 times.
6194 if (!l[i] && io[i]->label && !strcmp(io[i]->label, label)) {
666 364 *pp = p;
667 364 return i;
668 }
669 }
670
671 6134 idx_filter = 0;
672 }
673
674 511 *pp = NULL;
675 511 return 0;
676 }
677
678 31277 static int inout_add(AVFilterInOut **inouts, AVFilterContext *f, unsigned pad_idx,
679 const char *label)
680 {
681 31277 AVFilterInOut *io = av_mallocz(sizeof(*io));
682
683
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31277 times.
31277 if (!io)
684 ✗ return AVERROR(ENOMEM);
685
686 31277 io->filter_ctx = f;
687 31277 io->pad_idx = pad_idx;
688
689
2/2
✓ Branch 0 taken 511 times.
✓ Branch 1 taken 30766 times.
31277 if (label) {
690 511 io->name = av_strdup(label);
691
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 511 times.
511 if (!io->name) {
692 ✗ avfilter_inout_free(&io);
693 ✗ return AVERROR(ENOMEM);
694 }
695 }
696
697 31277 append_inout(inouts, &io);
698
699 31277 return 0;
700 }
701
702 37572 static int link_inputs(AVFilterGraphSegment *seg, size_t idx_chain,
703 size_t idx_filter, AVFilterInOut **inputs)
704 {
705 37572 AVFilterChain *ch = seg->chains[idx_chain];
706 37572 AVFilterParams *p = ch->filters[idx_filter];
707 37572 AVFilterContext *f = p->filter;
708
709 int ret;
710
711
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37572 times.
37572 if (f->nb_inputs < p->nb_inputs) {
712 ✗ av_log(seg->graph, AV_LOG_ERROR,
713 "More input link labels specified for filter '%s' than "
714 ✗ "it has inputs: %u > %d\n", f->filter->name,
715 p->nb_inputs, f->nb_inputs);
716 ✗ return AVERROR(EINVAL);
717 }
718
719
2/2
✓ Branch 0 taken 35236 times.
✓ Branch 1 taken 37572 times.
72808 for (unsigned in = 0; in < f->nb_inputs; in++) {
720
2/2
✓ Branch 0 taken 618 times.
✓ Branch 1 taken 34618 times.
35236 const char *label = (in < p->nb_inputs) ? p->inputs[in]->label : NULL;
721
722 // skip already linked inputs
723
2/2
✓ Branch 0 taken 20862 times.
✓ Branch 1 taken 14374 times.
35236 if (f->inputs[in])
724 20862 continue;
725
726
2/2
✓ Branch 0 taken 258 times.
✓ Branch 1 taken 14116 times.
14374 if (label) {
727 258 AVFilterParams *po = NULL;
728 258 unsigned idx = find_linklabel(seg, label, 1, idx_chain, idx_filter, &po);
729
730
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 254 times.
258 if (po) {
731 4 ret = avfilter_link(po->filter, idx, f, in);
732
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0)
733 ✗ return ret;
734
735 4 continue;
736 }
737 }
738
739 14370 ret = inout_add(inputs, f, in, label);
740
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14370 times.
14370 if (ret < 0)
741 ✗ return ret;
742 }
743
744 37572 return 0;
745 }
746
747 37572 static int link_outputs(AVFilterGraphSegment *seg, size_t idx_chain,
748 size_t idx_filter, AVFilterInOut **outputs)
749 {
750 37572 AVFilterChain *ch = seg->chains[idx_chain];
751 37572 AVFilterParams *p = ch->filters[idx_filter];
752 37572 AVFilterContext *f = p->filter;
753
754 int ret;
755
756
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37572 times.
37572 if (f->nb_outputs < p->nb_outputs) {
757 ✗ av_log(seg->graph, AV_LOG_ERROR,
758 "More output link labels specified for filter '%s' than "
759 ✗ "it has outputs: %u > %d\n", f->filter->name,
760 p->nb_outputs, f->nb_outputs);
761 ✗ return AVERROR(EINVAL);
762 }
763
2/2
✓ Branch 0 taken 37773 times.
✓ Branch 1 taken 37572 times.
75345 for (unsigned out = 0; out < f->nb_outputs; out++) {
764
2/2
✓ Branch 0 taken 621 times.
✓ Branch 1 taken 37152 times.
37773 char *label = (out < p->nb_outputs) ? p->outputs[out]->label : NULL;
765
766 // skip already linked outputs
767
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 37769 times.
37773 if (f->outputs[out])
768 4 continue;
769
770
2/2
✓ Branch 0 taken 617 times.
✓ Branch 1 taken 37152 times.
37769 if (label) {
771 617 AVFilterParams *po = NULL;
772 617 unsigned idx = find_linklabel(seg, label, 0, idx_chain, idx_filter, &po);
773
774
2/2
✓ Branch 0 taken 360 times.
✓ Branch 1 taken 257 times.
617 if (po) {
775 360 ret = avfilter_link(f, out, po->filter, idx);
776
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 360 times.
360 if (ret < 0)
777 ✗ return ret;
778
779 360 continue;
780 }
781 }
782
783 // if this output is unlabeled, try linking it to an unlabeled
784 // input in the next non-disabled filter in the chain
785
3/4
✓ Branch 0 taken 20502 times.
✓ Branch 1 taken 16907 times.
✓ Branch 2 taken 20502 times.
✗ Branch 3 not taken.
37409 for (size_t i = idx_filter + 1; i < ch->nb_filters && !label; i++) {
786 20502 AVFilterParams *p_next = ch->filters[i];
787
788
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20502 times.
20502 if (!p_next->filter)
789 ✗ continue;
790
791
1/2
✓ Branch 0 taken 20506 times.
✗ Branch 1 not taken.
20506 for (unsigned in = 0; in < p_next->filter->nb_inputs; in++) {
792
2/2
✓ Branch 0 taken 20502 times.
✓ Branch 1 taken 4 times.
20506 if (!p_next->filter->inputs[in] &&
793
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 20502 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
20502 (in >= p_next->nb_inputs || !p_next->inputs[in]->label)) {
794 20502 ret = avfilter_link(f, out, p_next->filter, in);
795
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20502 times.
20502 if (ret < 0)
796 ✗ return ret;
797
798 20502 goto cont;
799 }
800 }
801 ✗ break;
802 }
803
804 16907 ret = inout_add(outputs, f, out, label);
805
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16907 times.
16907 if (ret < 0)
806 ✗ return ret;
807
808 37409 cont:;
809 }
810
811 37572 return 0;
812 }
813
814 16634 int avfilter_graph_segment_link(AVFilterGraphSegment *seg, int flags,
815 AVFilterInOut **inputs,
816 AVFilterInOut **outputs)
817 {
818 int ret;
819
820 16634 *inputs = NULL;
821 16634 *outputs = NULL;
822
823
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16634 times.
16634 if (flags)
824 ✗ return AVERROR(ENOSYS);
825
826
2/2
✓ Branch 0 taken 17072 times.
✓ Branch 1 taken 16634 times.
33706 for (size_t idx_chain = 0; idx_chain < seg->nb_chains; idx_chain++) {
827 17072 AVFilterChain *ch = seg->chains[idx_chain];
828
829
2/2
✓ Branch 0 taken 37572 times.
✓ Branch 1 taken 17072 times.
54644 for (size_t idx_filter = 0; idx_filter < ch->nb_filters; idx_filter++) {
830 37572 AVFilterParams *p = ch->filters[idx_filter];
831
832
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37572 times.
37572 if (p->filter_name) {
833 ✗ ret = fail_creation_pending(seg, p->filter_name, __func__);
834 ✗ goto fail;
835 }
836
837
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37572 times.
37572 if (!p->filter)
838 ✗ continue;
839
840 37572 ret = link_inputs(seg, idx_chain, idx_filter, inputs);
841
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37572 times.
37572 if (ret < 0)
842 ✗ goto fail;
843
844 37572 ret = link_outputs(seg, idx_chain, idx_filter, outputs);
845
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37572 times.
37572 if (ret < 0)
846 ✗ goto fail;
847 }
848 }
849 16634 return 0;
850 ✗ fail:
851 ✗ avfilter_inout_free(inputs);
852 ✗ avfilter_inout_free(outputs);
853 ✗ return ret;
854 }
855
856 // print an error message if some options were not found
857 ✗ static void log_unknown_opt(const AVFilterGraphSegment *seg)
858 {
859 ✗ for (size_t i = 0; i < seg->nb_chains; i++) {
860 ✗ const AVFilterChain *ch = seg->chains[i];
861
862 ✗ for (size_t j = 0; j < ch->nb_filters; j++) {
863 ✗ const AVFilterParams *p = ch->filters[j];
864 const AVDictionaryEntry *e;
865
866 ✗ if (!p->filter)
867 ✗ continue;
868
869 ✗ e = av_dict_iterate(p->opts, NULL);
870
871 ✗ if (e) {
872 ✗ av_log(p->filter, AV_LOG_ERROR,
873 "Could not set non-existent option '%s' to value '%s'\n",
874 ✗ e->key, e->value);
875 ✗ return;
876 }
877 }
878 }
879
880 }
881
882 16635 int avfilter_graph_segment_apply(AVFilterGraphSegment *seg, int flags,
883 AVFilterInOut **inputs,
884 AVFilterInOut **outputs)
885 {
886 int ret;
887
888
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16635 times.
16635 if (flags)
889 ✗ return AVERROR(ENOSYS);
890
891 16635 ret = avfilter_graph_segment_create_filters(seg, 0);
892
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16635 times.
16635 if (ret < 0) {
893 ✗ av_log(seg->graph, AV_LOG_ERROR, "Error creating filters\n");
894 ✗ return ret;
895 }
896
897 16635 ret = avfilter_graph_segment_apply_opts(seg, 0);
898
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16635 times.
16635 if (ret < 0) {
899 ✗ if (ret == AVERROR_OPTION_NOT_FOUND)
900 ✗ log_unknown_opt(seg);
901 ✗ av_log(seg->graph, AV_LOG_ERROR, "Error applying filter options\n");
902 ✗ return ret;
903 }
904
905 16635 ret = avfilter_graph_segment_init(seg, 0);
906
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 16634 times.
16635 if (ret < 0) {
907 1 av_log(seg->graph, AV_LOG_ERROR, "Error initializing filters\n");
908 1 return ret;
909 }
910
911 16634 ret = avfilter_graph_segment_link(seg, 0, inputs, outputs);
912
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16634 times.
16634 if (ret < 0) {
913 ✗ av_log(seg->graph, AV_LOG_ERROR, "Error linking filters\n");
914 ✗ return ret;
915 }
916
917 16634 return 0;
918 }
919
920 75 int avfilter_graph_parse_ptr(AVFilterGraph *graph, const char *filters,
921 AVFilterInOut **open_inputs_ptr, AVFilterInOut **open_outputs_ptr,
922 void *log_ctx)
923 {
924
1/2
✓ Branch 0 taken 75 times.
✗ Branch 1 not taken.
75 AVFilterInOut *user_inputs = open_inputs_ptr ? *open_inputs_ptr : NULL;
925
1/2
✓ Branch 0 taken 75 times.
✗ Branch 1 not taken.
75 AVFilterInOut *user_outputs = open_outputs_ptr ? *open_outputs_ptr : NULL;
926
927 75 AVFilterInOut *inputs = NULL, *outputs = NULL;
928 75 AVFilterGraphSegment *seg = NULL;
929 AVFilterChain *ch;
930 AVFilterParams *p;
931 int ret;
932
933 75 ret = avfilter_graph_segment_parse(graph, filters, 0, &seg);
934
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
75 if (ret < 0)
935 ✗ goto end;
936
937 75 ret = avfilter_graph_segment_create_filters(seg, 0);
938
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
75 if (ret < 0)
939 ✗ goto end;
940
941 75 ret = avfilter_graph_segment_apply_opts(seg, 0);
942
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
75 if (ret < 0) {
943 ✗ if (ret == AVERROR_OPTION_NOT_FOUND)
944 ✗ log_unknown_opt(seg);
945 ✗ goto end;
946 }
947
948 75 ret = avfilter_graph_segment_init(seg, 0);
949
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
75 if (ret < 0)
950 ✗ goto end;
951
952 /* First input pad, assume it is "[in]" if not specified */
953 75 p = seg->chains[0]->filters[0];
954
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
75 if (p->filter->nb_inputs == 1 && !p->inputs) {
955 ✗ const char *tmp = "[in]";
956
957 ✗ ret = linklabels_parse(graph, &tmp, &p->inputs, &p->nb_inputs);
958 ✗ if (ret < 0)
959 ✗ goto end;
960 }
961
962 /* Last output pad, assume it is "[out]" if not specified */
963 75 ch = seg->chains[seg->nb_chains - 1];
964 75 p = ch->filters[ch->nb_filters - 1];
965
4/4
✓ Branch 0 taken 74 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 67 times.
✓ Branch 3 taken 7 times.
75 if (p->filter->nb_outputs == 1 && !p->outputs) {
966 67 const char *tmp = "[out]";
967
968 67 ret = linklabels_parse(graph, &tmp, &p->outputs, &p->nb_outputs);
969
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 67 times.
67 if (ret < 0)
970 ✗ goto end;
971 }
972
973 75 ret = avfilter_graph_segment_apply(seg, 0, &inputs, &outputs);
974 75 avfilter_graph_segment_free(&seg);
975
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
75 if (ret < 0)
976 ✗ goto end;
977
978 // process user-supplied inputs/outputs
979
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
75 while (inputs) {
980 ✗ AVFilterInOut *cur, *match = NULL;
981
982 ✗ cur = inputs;
983 ✗ inputs = cur->next;
984 ✗ cur->next = NULL;
985
986 ✗ if (cur->name)
987 ✗ match = extract_inout(cur->name, &user_outputs);
988
989 ✗ if (match) {
990 ✗ ret = avfilter_link(match->filter_ctx, match->pad_idx,
991 ✗ cur->filter_ctx, cur->pad_idx);
992 ✗ avfilter_inout_free(&match);
993 ✗ avfilter_inout_free(&cur);
994 ✗ if (ret < 0)
995 ✗ goto end;
996 } else
997 ✗ append_inout(&user_inputs, &cur);
998 }
999
2/2
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 75 times.
153 while (outputs) {
1000 78 AVFilterInOut *cur, *match = NULL;
1001
1002 78 cur = outputs;
1003 78 outputs = cur->next;
1004 78 cur->next = NULL;
1005
1006
1/2
✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
78 if (cur->name)
1007 78 match = extract_inout(cur->name, &user_inputs);
1008
1009
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 78 times.
78 if (match) {
1010 ✗ ret = avfilter_link(cur->filter_ctx, cur->pad_idx,
1011 ✗ match->filter_ctx, match->pad_idx);
1012 ✗ avfilter_inout_free(&match);
1013 ✗ avfilter_inout_free(&cur);
1014 ✗ if (ret < 0)
1015 ✗ goto end;
1016 } else
1017 78 append_inout(&user_outputs, &cur);
1018 }
1019
1020 75 end:
1021 75 avfilter_graph_segment_free(&seg);
1022
1023
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
75 if (ret < 0) {
1024 ✗ av_log(graph, AV_LOG_ERROR, "Error processing filtergraph: %s\n",
1025 ✗ av_err2str(ret));
1026
1027 ✗ while (graph->nb_filters)
1028 ✗ avfilter_free(graph->filters[0]);
1029 ✗ av_freep(&graph->filters);
1030 }
1031
1032 /* clear open_in/outputs only if not passed as parameters */
1033
1/2
✓ Branch 0 taken 75 times.
✗ Branch 1 not taken.
75 if (open_inputs_ptr) *open_inputs_ptr = user_inputs;
1034 ✗ else avfilter_inout_free(&user_inputs);
1035
1/2
✓ Branch 0 taken 75 times.
✗ Branch 1 not taken.
75 if (open_outputs_ptr) *open_outputs_ptr = user_outputs;
1036 ✗ else avfilter_inout_free(&user_outputs);
1037
1038 75 avfilter_inout_free(&inputs);
1039 75 avfilter_inout_free(&outputs);
1040
1041 75 return ret;
1042 }
1043