FFmpeg
graphparser.c
Go to the documentation of this file.
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 "internal.h"
33 
34 #define WHITESPACES " \n\t\r"
35 
36 /**
37  * Parse the name of a link, which has the format "[linkname]".
38  *
39  * @return a pointer (that need to be freed after use) to the name
40  * between parenthesis
41  */
42 static char *parse_link_name(const char **buf, void *log_ctx)
43 {
44  const char *start = *buf;
45  char *name;
46  (*buf)++;
47 
48  name = av_get_token(buf, "]");
49  if (!name)
50  return NULL;
51 
52  if (!name[0]) {
53  av_log(log_ctx, AV_LOG_ERROR,
54  "Bad (empty?) label found in the following: \"%s\".\n", start);
55  goto fail;
56  }
57 
58  if (**buf != ']') {
59  av_log(log_ctx, AV_LOG_ERROR,
60  "Mismatched '[' found in the following: \"%s\".\n", start);
61  fail:
62  av_freep(&name);
63  return NULL;
64  }
65  (*buf)++;
66 
67  return name;
68 }
69 
71 {
72  return av_mallocz(sizeof(AVFilterInOut));
73 }
74 
76 {
77  while (*inout) {
78  AVFilterInOut *next = (*inout)->next;
79  av_freep(&(*inout)->name);
80  av_freep(inout);
81  *inout = next;
82  }
83 }
84 
85 static AVFilterInOut *extract_inout(const char *label, AVFilterInOut **links)
86 {
88 
89  while (*links && (!(*links)->name || strcmp((*links)->name, label)))
90  links = &((*links)->next);
91 
92  ret = *links;
93 
94  if (ret) {
95  *links = ret->next;
96  ret->next = NULL;
97  }
98 
99  return ret;
100 }
101 
102 static void append_inout(AVFilterInOut **inouts, AVFilterInOut **element)
103 {
104  while (*inouts && (*inouts)->next)
105  inouts = &((*inouts)->next);
106 
107  if (!*inouts)
108  *inouts = *element;
109  else
110  (*inouts)->next = *element;
111  *element = NULL;
112 }
113 
114 static int parse_sws_flags(const char **buf, char **dst, void *log_ctx)
115 {
116  char *p = strchr(*buf, ';');
117 
118  if (strncmp(*buf, "sws_flags=", 10))
119  return 0;
120 
121  if (!p) {
122  av_log(log_ctx, AV_LOG_ERROR, "sws_flags not terminated with ';'.\n");
123  return AVERROR(EINVAL);
124  }
125 
126  *buf += 4; // keep the 'flags=' part
127 
128  av_freep(dst);
129  if (!(*dst = av_mallocz(p - *buf + 1)))
130  return AVERROR(ENOMEM);
131  av_strlcpy(*dst, *buf, p - *buf + 1);
132 
133  *buf = p + 1;
134  return 0;
135 }
136 
140 {
142  int ret;
143 
144  ret = avfilter_graph_segment_parse(graph, filters, 0, &seg);
145  if (ret < 0)
146  return ret;
147 
150  if (ret < 0)
151  goto end;
152 
153  return 0;
154 
155 end:
156  while (graph->nb_filters)
157  avfilter_free(graph->filters[0]);
158  av_freep(&graph->filters);
159 
160  return ret;
161 }
162 
164  AVFilterInOut *open_inputs,
165  AVFilterInOut *open_outputs, void *log_ctx)
166 {
167  int ret;
168  AVFilterInOut *cur, *match, *inputs = NULL, *outputs = NULL;
169 
170  if ((ret = avfilter_graph_parse2(graph, filters, &inputs, &outputs)) < 0)
171  goto fail;
172 
173  /* First input can be omitted if it is "[in]" */
174  if (inputs && !inputs->name)
175  inputs->name = av_strdup("in");
176  for (cur = inputs; cur; cur = cur->next) {
177  if (!cur->name) {
178  av_log(log_ctx, AV_LOG_ERROR,
179  "Not enough inputs specified for the \"%s\" filter.\n",
180  cur->filter_ctx->filter->name);
181  ret = AVERROR(EINVAL);
182  goto fail;
183  }
184  if (!(match = extract_inout(cur->name, &open_outputs)))
185  continue;
186  ret = avfilter_link(match->filter_ctx, match->pad_idx,
187  cur->filter_ctx, cur->pad_idx);
188  avfilter_inout_free(&match);
189  if (ret < 0)
190  goto fail;
191  }
192 
193  /* Last output can be omitted if it is "[out]" */
194  if (outputs && !outputs->name)
195  outputs->name = av_strdup("out");
196  for (cur = outputs; cur; cur = cur->next) {
197  if (!cur->name) {
198  av_log(log_ctx, AV_LOG_ERROR,
199  "Invalid filterchain containing an unlabelled output pad: \"%s\"\n",
200  filters);
201  ret = AVERROR(EINVAL);
202  goto fail;
203  }
204  if (!(match = extract_inout(cur->name, &open_inputs)))
205  continue;
206  ret = avfilter_link(cur->filter_ctx, cur->pad_idx,
207  match->filter_ctx, match->pad_idx);
208  avfilter_inout_free(&match);
209  if (ret < 0)
210  goto fail;
211  }
212 
213  fail:
214  if (ret < 0) {
215  while (graph->nb_filters)
216  avfilter_free(graph->filters[0]);
217  av_freep(&graph->filters);
218  }
221  avfilter_inout_free(&open_inputs);
222  avfilter_inout_free(&open_outputs);
223  return ret;
224 }
225 
227 {
228  AVFilterPadParams *fpp = *pfpp;
229 
230  if (!fpp)
231  return;
232 
233  av_freep(&fpp->label);
234 
235  av_freep(pfpp);
236 }
237 
239 {
240  AVFilterParams *p = *pp;
241 
242  if (!p)
243  return;
244 
245  for (unsigned i = 0; i < p->nb_inputs; i++)
246  pad_params_free(&p->inputs[i]);
247  av_freep(&p->inputs);
248 
249  for (unsigned i = 0; i < p->nb_outputs; i++)
250  pad_params_free(&p->outputs[i]);
251  av_freep(&p->outputs);
252 
253  av_dict_free(&p->opts);
254 
255  av_freep(&p->filter_name);
256  av_freep(&p->instance_name);
257 
258  av_freep(pp);
259 }
260 
261 static void chain_free(AVFilterChain **pch)
262 {
263  AVFilterChain *ch = *pch;
264 
265  if (!ch)
266  return;
267 
268  for (size_t i = 0; i < ch->nb_filters; i++)
270  av_freep(&ch->filters);
271 
272  av_freep(pch);
273 }
274 
276 {
277  AVFilterGraphSegment *seg = *pseg;
278 
279  if (!seg)
280  return;
281 
282  for (size_t i = 0; i < seg->nb_chains; i++)
283  chain_free(&seg->chains[i]);
284  av_freep(&seg->chains);
285 
286  av_freep(&seg->scale_sws_opts);
287 
288  av_freep(pseg);
289 }
290 
291 static int linklabels_parse(void *logctx, const char **linklabels,
292  AVFilterPadParams ***res, unsigned *nb_res)
293 {
294  AVFilterPadParams **pp = NULL;
295  int nb = 0;
296  int ret;
297 
298  while (**linklabels == '[') {
299  char *label;
300  AVFilterPadParams *par;
301 
302  label = parse_link_name(linklabels, logctx);
303  if (!label) {
304  ret = AVERROR(EINVAL);
305  goto fail;
306  }
307 
308  par = av_mallocz(sizeof(*par));
309  if (!par) {
310  av_freep(&label);
311  ret = AVERROR(ENOMEM);
312  goto fail;
313  }
314 
315  par->label = label;
316 
317  ret = av_dynarray_add_nofree(&pp, &nb, par);
318  if (ret < 0) {
319  pad_params_free(&par);
320  goto fail;
321  }
322 
323  *linklabels += strspn(*linklabels, WHITESPACES);
324  }
325 
326  *res = pp;
327  *nb_res = nb;
328 
329  return 0;
330 fail:
331  for (unsigned i = 0; i < nb; i++)
332  pad_params_free(&pp[i]);
333  av_freep(&pp);
334  return ret;
335 }
336 
337 static int filter_parse(void *logctx, const char **filter,
338  AVFilterParams **pp)
339 {
340  AVFilterParams *p;
341  char *inst_name;
342  int ret;
343 
344  p = av_mallocz(sizeof(*p));
345  if (!p)
346  return AVERROR(ENOMEM);
347 
348  ret = linklabels_parse(logctx, filter, &p->inputs, &p->nb_inputs);
349  if (ret < 0)
350  goto fail;
351 
352  p->filter_name = av_get_token(filter, "=,;[");
353  if (!p->filter_name) {
354  ret = AVERROR(ENOMEM);
355  goto fail;
356  }
357 
358  inst_name = strchr(p->filter_name, '@');
359  if (inst_name) {
360  *inst_name++ = 0;
361  p->instance_name = av_strdup(inst_name);
362  if (!p->instance_name) {
363  ret = AVERROR(ENOMEM);
364  goto fail;
365  }
366  }
367 
368  if (**filter == '=') {
370  char *opts;
371 
372  (*filter)++;
373 
374  opts = av_get_token(filter, "[],;");
375  if (!opts) {
376  ret = AVERROR(ENOMEM);
377  goto fail;
378  }
379 
380  ret = ff_filter_opt_parse(logctx, f ? f->priv_class : NULL,
381  &p->opts, opts);
382  av_freep(&opts);
383  if (ret < 0)
384  goto fail;
385  }
386 
387  ret = linklabels_parse(logctx, filter, &p->outputs, &p->nb_outputs);
388  if (ret < 0)
389  goto fail;
390 
391  *filter += strspn(*filter, WHITESPACES);
392 
393  *pp = p;
394  return 0;
395 fail:
396  av_log(logctx, AV_LOG_ERROR,
397  "Error parsing a filter description around: %s\n", *filter);
398  filter_params_free(&p);
399  return ret;
400 }
401 
402 static int chain_parse(void *logctx, const char **pchain,
403  AVFilterChain **pch)
404 {
405  const char *chain = *pchain;
406  AVFilterChain *ch;
407  int ret, nb_filters = 0;
408 
409  *pch = NULL;
410 
411  ch = av_mallocz(sizeof(*ch));
412  if (!ch)
413  return AVERROR(ENOMEM);
414 
415  while (*chain) {
416  AVFilterParams *p;
417  char chr;
418 
419  ret = filter_parse(logctx, &chain, &p);
420  if (ret < 0)
421  goto fail;
422 
423  ret = av_dynarray_add_nofree(&ch->filters, &nb_filters, p);
424  if (ret < 0) {
425  filter_params_free(&p);
426  goto fail;
427  }
428  ch->nb_filters = nb_filters;
429 
430  // a filter ends with one of: , ; end-of-string
431  chr = *chain;
432  if (chr && chr != ',' && chr != ';') {
433  av_log(logctx, AV_LOG_ERROR,
434  "Trailing garbage after a filter: %s\n", chain);
435  ret = AVERROR(EINVAL);
436  goto fail;
437  }
438 
439  if (chr) {
440  chain++;
441  chain += strspn(chain, WHITESPACES);
442 
443  if (chr == ';')
444  break;
445  }
446  }
447 
448  *pchain = chain;
449  *pch = ch;
450 
451  return 0;
452 fail:
453  av_log(logctx, AV_LOG_ERROR,
454  "Error parsing filterchain '%s' around: %s\n", *pchain, chain);
455  chain_free(&ch);
456  return ret;
457 }
458 
459 int avfilter_graph_segment_parse(AVFilterGraph *graph, const char *graph_str,
460  int flags, AVFilterGraphSegment **pseg)
461 {
463  int ret, nb_chains = 0;
464 
465  *pseg = NULL;
466 
467  if (flags)
468  return AVERROR(ENOSYS);
469 
470  seg = av_mallocz(sizeof(*seg));
471  if (!seg)
472  return AVERROR(ENOMEM);
473 
474  seg->graph = graph;
475 
476  graph_str += strspn(graph_str, WHITESPACES);
477 
478  ret = parse_sws_flags(&graph_str, &seg->scale_sws_opts, &graph);
479  if (ret < 0)
480  goto fail;
481 
482  graph_str += strspn(graph_str, WHITESPACES);
483 
484  while (*graph_str) {
485  AVFilterChain *ch;
486 
487  ret = chain_parse(graph, &graph_str, &ch);
488  if (ret < 0)
489  goto fail;
490 
491  ret = av_dynarray_add_nofree(&seg->chains, &nb_chains, ch);
492  if (ret < 0) {
493  chain_free(&ch);
494  goto fail;
495  }
496  seg->nb_chains = nb_chains;
497 
498  graph_str += strspn(graph_str, WHITESPACES);
499  }
500 
501  if (!seg->nb_chains) {
502  av_log(graph, AV_LOG_ERROR, "No filters specified in the graph description\n");
503  ret = AVERROR(EINVAL);
504  goto fail;
505  }
506 
507  *pseg = seg;
508 
509  return 0;
510 fail:
512  return ret;
513 }
514 
516 {
517  size_t idx = 0;
518 
519  if (flags)
520  return AVERROR(ENOSYS);
521 
522  if (seg->scale_sws_opts) {
523  av_freep(&seg->graph->scale_sws_opts);
525  if (!seg->graph->scale_sws_opts)
526  return AVERROR(ENOMEM);
527  }
528 
529  for (size_t i = 0; i < seg->nb_chains; i++) {
530  AVFilterChain *ch = seg->chains[i];
531 
532  for (size_t j = 0; j < ch->nb_filters; j++) {
533  AVFilterParams *p = ch->filters[j];
535  char inst_name[30], *name = p->instance_name ? p->instance_name :
536  inst_name;
537 
538  // skip already processed filters
539  if (p->filter || !p->filter_name)
540  continue;
541 
542  if (!f) {
543  av_log(seg->graph, AV_LOG_ERROR,
544  "No such filter: '%s'\n", p->filter_name);
546  }
547 
548  if (!p->instance_name)
549  snprintf(inst_name, sizeof(inst_name), "Parsed_%s_%zu", f->name, idx);
550 
552  if (!p->filter)
553  return AVERROR(ENOMEM);
554 
555  if (!strcmp(f->name, "scale") && seg->graph->scale_sws_opts) {
557  "=", ":");
558  if (ret < 0) {
559  avfilter_free(p->filter);
560  p->filter = NULL;
561  return ret;
562  }
563  }
564 
565  av_freep(&p->filter_name);
566  av_freep(&p->instance_name);
567 
568  idx++;
569  }
570  }
571 
572  return 0;
573 }
574 
575 static int fail_creation_pending(AVFilterGraphSegment *seg, const char *fn,
576  const char *func)
577 {
578  av_log(seg->graph, AV_LOG_ERROR,
579  "A creation-pending filter '%s' present in the segment. All filters "
580  "must be created or disabled before calling %s().\n", fn, func);
581  return AVERROR(EINVAL);
582 }
583 
585 {
586  int ret, leftover_opts = 0;
587 
588  if (flags)
589  return AVERROR(ENOSYS);
590 
591  for (size_t i = 0; i < seg->nb_chains; i++) {
592  AVFilterChain *ch = seg->chains[i];
593 
594  for (size_t j = 0; j < ch->nb_filters; j++) {
595  AVFilterParams *p = ch->filters[j];
596 
597  if (p->filter_name)
598  return fail_creation_pending(seg, p->filter_name, __func__);
599  if (!p->filter || !p->opts)
600  continue;
601 
603  if (ret < 0)
604  return ret;
605 
606  if (av_dict_count(p->opts))
607  leftover_opts = 1;
608  }
609  }
610 
611  return leftover_opts ? AVERROR_OPTION_NOT_FOUND : 0;
612 }
613 
615 {
616  if (flags)
617  return AVERROR(ENOSYS);
618 
619  for (size_t i = 0; i < seg->nb_chains; i++) {
620  AVFilterChain *ch = seg->chains[i];
621 
622  for (size_t j = 0; j < ch->nb_filters; j++) {
623  AVFilterParams *p = ch->filters[j];
624  int ret;
625 
626  if (p->filter_name)
627  return fail_creation_pending(seg, p->filter_name, __func__);
628  if (!p->filter || p->filter->internal->initialized)
629  continue;
630 
632  if (ret < 0)
633  return ret;
634  }
635  }
636 
637  return 0;
638 }
639 
640 static unsigned
641 find_linklabel(AVFilterGraphSegment *seg, const char *label,
642  int output, size_t idx_chain, size_t idx_filter,
643  AVFilterParams **pp)
644 {
645  for (; idx_chain < seg->nb_chains; idx_chain++) {
646  AVFilterChain *ch = seg->chains[idx_chain];
647 
648  for (; idx_filter < ch->nb_filters; idx_filter++) {
649  AVFilterParams *p = ch->filters[idx_filter];
650  AVFilterPadParams **io = output ? p->outputs : p->inputs;
651  unsigned nb_io = output ? p->nb_outputs : p->nb_inputs;
652  AVFilterLink **l;
653  unsigned nb_l;
654 
655  if (!p->filter)
656  continue;
657 
658  l = output ? p->filter->outputs : p->filter->inputs;
659  nb_l = output ? p->filter->nb_outputs : p->filter->nb_inputs;
660 
661  for (unsigned i = 0; i < FFMIN(nb_io, nb_l); i++)
662  if (!l[i] && io[i]->label && !strcmp(io[i]->label, label)) {
663  *pp = p;
664  return i;
665  }
666  }
667 
668  idx_filter = 0;
669  }
670 
671  *pp = NULL;
672  return 0;
673 }
674 
675 static int inout_add(AVFilterInOut **inouts, AVFilterContext *f, unsigned pad_idx,
676  const char *label)
677 {
678  AVFilterInOut *io = av_mallocz(sizeof(*io));
679 
680  if (!io)
681  return AVERROR(ENOMEM);
682 
683  io->filter_ctx = f;
684  io->pad_idx = pad_idx;
685 
686  if (label) {
687  io->name = av_strdup(label);
688  if (!io->name) {
689  avfilter_inout_free(&io);
690  return AVERROR(ENOMEM);
691  }
692  }
693 
694  append_inout(inouts, &io);
695 
696  return 0;
697 }
698 
699 static int link_inputs(AVFilterGraphSegment *seg, size_t idx_chain,
700  size_t idx_filter, AVFilterInOut **inputs)
701 {
702  AVFilterChain *ch = seg->chains[idx_chain];
703  AVFilterParams *p = ch->filters[idx_filter];
704  AVFilterContext *f = p->filter;
705 
706  int ret;
707 
708  if (f->nb_inputs < p->nb_inputs) {
709  av_log(seg->graph, AV_LOG_ERROR,
710  "More input link labels specified for filter '%s' than "
711  "it has inputs: %u > %d\n", f->filter->name,
712  p->nb_inputs, f->nb_inputs);
713  return AVERROR(EINVAL);
714  }
715 
716  for (unsigned in = 0; in < f->nb_inputs; in++) {
717  const char *label = (in < p->nb_inputs) ? p->inputs[in]->label : NULL;
718 
719  // skip already linked inputs
720  if (f->inputs[in])
721  continue;
722 
723  if (label) {
724  AVFilterParams *po = NULL;
725  unsigned idx = find_linklabel(seg, label, 1, idx_chain, idx_filter, &po);
726 
727  if (po) {
728  ret = avfilter_link(po->filter, idx, f, in);
729  if (ret < 0)
730  return ret;
731 
732  continue;
733  }
734  }
735 
736  ret = inout_add(inputs, f, in, label);
737  if (ret < 0)
738  return ret;
739  }
740 
741  return 0;
742 }
743 
744 static int link_outputs(AVFilterGraphSegment *seg, size_t idx_chain,
745  size_t idx_filter, AVFilterInOut **outputs)
746 {
747  AVFilterChain *ch = seg->chains[idx_chain];
748  AVFilterParams *p = ch->filters[idx_filter];
749  AVFilterContext *f = p->filter;
750 
751  int ret;
752 
753  if (f->nb_outputs < p->nb_outputs) {
754  av_log(seg->graph, AV_LOG_ERROR,
755  "More output link labels specified for filter '%s' than "
756  "it has outputs: %u > %d\n", f->filter->name,
757  p->nb_outputs, f->nb_outputs);
758  return AVERROR(EINVAL);
759  }
760  for (unsigned out = 0; out < f->nb_outputs; out++) {
761  char *label = (out < p->nb_outputs) ? p->outputs[out]->label : NULL;
762 
763  // skip already linked outputs
764  if (f->outputs[out])
765  continue;
766 
767  if (label) {
768  AVFilterParams *po = NULL;
769  unsigned idx = find_linklabel(seg, label, 0, idx_chain, idx_filter, &po);
770 
771  if (po) {
772  ret = avfilter_link(f, out, po->filter, idx);
773  if (ret < 0)
774  return ret;
775 
776  continue;
777  }
778  }
779 
780  // if this output is unlabeled, try linking it to an unlabeled
781  // input in the next non-disabled filter in the chain
782  for (size_t i = idx_filter + 1; i < ch->nb_filters && !label; i++) {
783  AVFilterParams *p_next = ch->filters[i];
784 
785  if (!p_next->filter)
786  continue;
787 
788  for (unsigned in = 0; in < p_next->filter->nb_inputs; in++) {
789  if (!p_next->filter->inputs[in] &&
790  (in >= p_next->nb_inputs || !p_next->inputs[in]->label)) {
791  ret = avfilter_link(f, out, p_next->filter, in);
792  if (ret < 0)
793  return ret;
794 
795  goto cont;
796  }
797  }
798  break;
799  }
800 
801  ret = inout_add(outputs, f, out, label);
802  if (ret < 0)
803  return ret;
804 
805 cont:;
806  }
807 
808  return 0;
809 }
810 
814 {
815  int ret;
816 
817  *inputs = NULL;
818  *outputs = NULL;
819 
820  if (flags)
821  return AVERROR(ENOSYS);
822 
823  for (size_t idx_chain = 0; idx_chain < seg->nb_chains; idx_chain++) {
824  AVFilterChain *ch = seg->chains[idx_chain];
825 
826  for (size_t idx_filter = 0; idx_filter < ch->nb_filters; idx_filter++) {
827  AVFilterParams *p = ch->filters[idx_filter];
828 
829  if (p->filter_name) {
830  ret = fail_creation_pending(seg, p->filter_name, __func__);
831  goto fail;
832  }
833 
834  if (!p->filter)
835  continue;
836 
837  ret = link_inputs(seg, idx_chain, idx_filter, inputs);
838  if (ret < 0)
839  goto fail;
840 
841  ret = link_outputs(seg, idx_chain, idx_filter, outputs);
842  if (ret < 0)
843  goto fail;
844  }
845  }
846  return 0;
847 fail:
850  return ret;
851 }
852 
856 {
857  int ret;
858 
859  if (flags)
860  return AVERROR(ENOSYS);
861 
863  if (ret < 0) {
864  av_log(seg->graph, AV_LOG_ERROR, "Error creating filters\n");
865  return ret;
866  }
867 
869  if (ret < 0) {
870  av_log(seg->graph, AV_LOG_ERROR, "Error applying filter options\n");
871  return ret;
872  }
873 
875  if (ret < 0) {
876  av_log(seg->graph, AV_LOG_ERROR, "Error initializing filters\n");
877  return ret;
878  }
879 
881  if (ret < 0) {
882  av_log(seg->graph, AV_LOG_ERROR, "Error linking filters\n");
883  return ret;
884  }
885 
886  return 0;
887 }
888 
890  AVFilterInOut **open_inputs_ptr, AVFilterInOut **open_outputs_ptr,
891  void *log_ctx)
892 {
893  AVFilterInOut *user_inputs = open_inputs_ptr ? *open_inputs_ptr : NULL;
894  AVFilterInOut *user_outputs = open_outputs_ptr ? *open_outputs_ptr : NULL;
895 
897  AVFilterGraphSegment *seg = NULL;
898  AVFilterChain *ch;
899  AVFilterParams *p;
900  int ret;
901 
902  ret = avfilter_graph_segment_parse(graph, filters, 0, &seg);
903  if (ret < 0)
904  goto end;
905 
907  if (ret < 0)
908  goto end;
909 
911  if (ret < 0)
912  goto end;
913 
915  if (ret < 0)
916  goto end;
917 
918  /* First input pad, assume it is "[in]" if not specified */
919  p = seg->chains[0]->filters[0];
920  if (p->filter->nb_inputs == 1 && !p->inputs) {
921  const char *tmp = "[in]";
922 
923  ret = linklabels_parse(graph, &tmp, &p->inputs, &p->nb_inputs);
924  if (ret < 0)
925  goto end;
926  }
927 
928  /* Last output pad, assume it is "[out]" if not specified */
929  ch = seg->chains[seg->nb_chains - 1];
930  p = ch->filters[ch->nb_filters - 1];
931  if (p->filter->nb_outputs == 1 && !p->outputs) {
932  const char *tmp = "[out]";
933 
934  ret = linklabels_parse(graph, &tmp, &p->outputs, &p->nb_outputs);
935  if (ret < 0)
936  goto end;
937  }
938 
941  if (ret < 0)
942  goto end;
943 
944  // process user-supplied inputs/outputs
945  while (inputs) {
946  AVFilterInOut *cur, *match = NULL;
947 
948  cur = inputs;
949  inputs = cur->next;
950  cur->next = NULL;
951 
952  if (cur->name)
953  match = extract_inout(cur->name, &user_outputs);
954 
955  if (match) {
956  ret = avfilter_link(match->filter_ctx, match->pad_idx,
957  cur->filter_ctx, cur->pad_idx);
958  avfilter_inout_free(&match);
959  avfilter_inout_free(&cur);
960  if (ret < 0)
961  goto end;
962  } else
963  append_inout(&user_inputs, &cur);
964  }
965  while (outputs) {
966  AVFilterInOut *cur, *match = NULL;
967 
968  cur = outputs;
969  outputs = cur->next;
970  cur->next = NULL;
971 
972  if (cur->name)
973  match = extract_inout(cur->name, &user_inputs);
974 
975  if (match) {
976  ret = avfilter_link(cur->filter_ctx, cur->pad_idx,
977  match->filter_ctx, match->pad_idx);
978  avfilter_inout_free(&match);
979  avfilter_inout_free(&cur);
980  if (ret < 0)
981  goto end;
982  } else
983  append_inout(&user_outputs, &cur);
984  }
985 
986 end:
988 
989  if (ret < 0) {
990  while (graph->nb_filters)
991  avfilter_free(graph->filters[0]);
992  av_freep(&graph->filters);
993  }
994 
995  /* clear open_in/outputs only if not passed as parameters */
996  if (open_inputs_ptr) *open_inputs_ptr = user_inputs;
997  else avfilter_inout_free(&user_inputs);
998  if (open_outputs_ptr) *open_outputs_ptr = user_outputs;
999  else avfilter_inout_free(&user_outputs);
1000 
1003 
1004  return ret;
1005 }
link_inputs
static int link_inputs(AVFilterGraphSegment *seg, size_t idx_chain, size_t idx_filter, AVFilterInOut **inputs)
Definition: graphparser.c:699
func
int(* func)(AVBPrint *dst, const char *in, const char *arg)
Definition: jacosubdec.c:68
name
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default minimum maximum flags name is the option name
Definition: writing_filters.txt:88
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
opt.h
inout_add
static int inout_add(AVFilterInOut **inouts, AVFilterContext *f, unsigned pad_idx, const char *label)
Definition: graphparser.c:675
AVFilterParams::instance_name
char * instance_name
Name to be used for this filter instance.
Definition: avfilter.h:1174
avfilter_graph_segment_create_filters
int avfilter_graph_segment_create_filters(AVFilterGraphSegment *seg, int flags)
Create filters specified in a graph segment.
Definition: graphparser.c:515
out
FILE * out
Definition: movenc.c:54
ff_filter_opt_parse
int ff_filter_opt_parse(void *logctx, const AVClass *priv_class, AVDictionary **options, const char *args)
Parse filter options into a dictionary.
Definition: avfilter.c:784
av_dict_count
int av_dict_count(const AVDictionary *m)
Get number of entries in dictionary.
Definition: dict.c:37
output
filter_frame For filters that do not use the this method is called when a frame is pushed to the filter s input It can be called at any time except in a reentrant way If the input frame is enough to produce output
Definition: filter_design.txt:225
parse_sws_flags
static int parse_sws_flags(const char **buf, char **dst, void *log_ctx)
Definition: graphparser.c:114
tmp
static uint8_t tmp[11]
Definition: aes_ctr.c:28
AVFilterInOut::next
struct AVFilterInOut * next
next input/input in the list, NULL if this is the last
Definition: avfilter.h:1026
fail_creation_pending
static int fail_creation_pending(AVFilterGraphSegment *seg, const char *fn, const char *func)
Definition: graphparser.c:575
AVFilterContext::nb_outputs
unsigned nb_outputs
number of output pads
Definition: avfilter.h:405
filter
filter_frame For filters that do not use the this method is called when a frame is pushed to the filter s input It can be called at any time except in a reentrant way If the input frame is enough to produce then the filter should push the output frames on the output link immediately As an exception to the previous rule if the input frame is enough to produce several output frames then the filter needs output only at least one per link The additional frames can be left buffered in the filter
Definition: filter_design.txt:228
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:165
AVFilterInternal::initialized
int initialized
Definition: internal.h:143
AVFilterParams::inputs
AVFilterPadParams ** inputs
Definition: avfilter.h:1188
chain_parse
static int chain_parse(void *logctx, const char **pchain, AVFilterChain **pch)
Definition: graphparser.c:402
AVFilterParams::outputs
AVFilterPadParams ** outputs
Definition: avfilter.h:1191
av_set_options_string
int av_set_options_string(void *ctx, const char *opts, const char *key_val_sep, const char *pairs_sep)
Parse the key/value pairs list in opts.
Definition: opt.c:1587
append_inout
static void append_inout(AVFilterInOut **inouts, AVFilterInOut **element)
Definition: graphparser.c:102
avfilter_graph_alloc_filter
AVFilterContext * avfilter_graph_alloc_filter(AVFilterGraph *graph, const AVFilter *filter, const char *name)
Create a new filter instance in a filter graph.
Definition: avfiltergraph.c:165
pad_params_free
static void pad_params_free(AVFilterPadParams **pfpp)
Definition: graphparser.c:226
avfilter_graph_segment_link
int avfilter_graph_segment_link(AVFilterGraphSegment *seg, int flags, AVFilterInOut **inputs, AVFilterInOut **outputs)
Link filters in a graph segment.
Definition: graphparser.c:811
fail
#define fail()
Definition: checkasm.h:134
fn
#define fn(a)
Definition: afir_template.c:51
AVERROR_OPTION_NOT_FOUND
#define AVERROR_OPTION_NOT_FOUND
Option not found.
Definition: error.h:63
avfilter_graph_segment_free
void avfilter_graph_segment_free(AVFilterGraphSegment **pseg)
Free the provided AVFilterGraphSegment and everything associated with it.
Definition: graphparser.c:275
avfilter_graph_segment_parse
int avfilter_graph_segment_parse(AVFilterGraph *graph, const char *graph_str, int flags, AVFilterGraphSegment **pseg)
Parse a textual filtergraph description into an intermediate form.
Definition: graphparser.c:459
avfilter_inout_free
void avfilter_inout_free(AVFilterInOut **inout)
Free the supplied list of AVFilterInOut and set *inout to NULL.
Definition: graphparser.c:75
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
find_linklabel
static unsigned find_linklabel(AVFilterGraphSegment *seg, const char *label, int output, size_t idx_chain, size_t idx_filter, AVFilterParams **pp)
Definition: graphparser.c:641
AVFilterChain::filters
AVFilterParams ** filters
Definition: avfilter.h:1202
chain_free
static void chain_free(AVFilterChain **pch)
Definition: graphparser.c:261
filters
#define filters(fmt, type, inverse, clp, inverset, clip, one, clip_fn, packed)
Definition: af_crystalizer.c:55
outputs
static const AVFilterPad outputs[]
Definition: af_acontrast.c:172
avfilter_graph_segment_init
int avfilter_graph_segment_init(AVFilterGraphSegment *seg, int flags)
Initialize all filter instances in a graph segment.
Definition: graphparser.c:614
AVFilterPadParams::label
char * label
An av_malloc()'ed string containing the pad label.
Definition: avfilter.h:1125
if
if(ret)
Definition: filter_design.txt:179
avfilter_get_by_name
const AVFilter * avfilter_get_by_name(const char *name)
Get a filter definition matching the given name.
Definition: allfilters.c:611
opts
AVDictionary * opts
Definition: movenc.c:50
avfilter_graph_segment_apply
int avfilter_graph_segment_apply(AVFilterGraphSegment *seg, int flags, AVFilterInOut **inputs, AVFilterInOut **outputs)
Apply all filter/link descriptions from a graph segment to the associated filtergraph.
Definition: graphparser.c:853
NULL
#define NULL
Definition: coverity.c:32
AVFilterParams
Parameters describing a filter to be created in a filtergraph.
Definition: avfilter.h:1134
AVFilterParams::filter
AVFilterContext * filter
The filter context.
Definition: avfilter.h:1145
AVFilterChain::nb_filters
size_t nb_filters
Definition: avfilter.h:1203
AVFilterParams::filter_name
char * filter_name
Name of the AVFilter to be used.
Definition: avfilter.h:1162
AVFilterGraph::filters
AVFilterContext ** filters
Definition: avfilter.h:857
AVFilterContext::inputs
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:400
avfilter_inout_alloc
AVFilterInOut * avfilter_inout_alloc(void)
Allocate a single AVFilterInOut entry.
Definition: graphparser.c:70
AVFilterGraphSegment::chains
AVFilterChain ** chains
A list of filter chain contained in this segment.
Definition: avfilter.h:1226
AVFilterGraph
Definition: avfilter.h:855
inputs
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several inputs
Definition: filter_design.txt:243
avfilter_graph_parse2
int avfilter_graph_parse2(AVFilterGraph *graph, const char *filters, AVFilterInOut **inputs, AVFilterInOut **outputs)
Add a graph described by a string to a graph.
Definition: graphparser.c:137
AVFilterParams::nb_outputs
unsigned nb_outputs
Definition: avfilter.h:1192
AVFilterGraphSegment
A parsed representation of a filtergraph segment.
Definition: avfilter.h:1215
AVFilterInOut::pad_idx
int pad_idx
index of the filt_ctx pad to use for linking
Definition: avfilter.h:1023
AVFilterGraph::scale_sws_opts
char * scale_sws_opts
sws options to use for the auto-inserted scale filters
Definition: avfilter.h:860
f
f
Definition: af_crystalizer.c:122
AVFilterContext::nb_inputs
unsigned nb_inputs
number of input pads
Definition: avfilter.h:401
AVFilterInOut::filter_ctx
AVFilterContext * filter_ctx
filter context associated to this input/output
Definition: avfilter.h:1020
avfilter_link
int avfilter_link(AVFilterContext *src, unsigned srcpad, AVFilterContext *dst, unsigned dstpad)
Link two filters together.
Definition: avfilter.c:148
parse_link_name
static char * parse_link_name(const char **buf, void *log_ctx)
Parse the name of a link, which has the format "[linkname]".
Definition: graphparser.c:42
WHITESPACES
#define WHITESPACES
Definition: graphparser.c:34
AVFilterGraphSegment::scale_sws_opts
char * scale_sws_opts
A string containing a colon-separated list of key=value options applied to all scale filters in this ...
Definition: avfilter.h:1237
AV_OPT_SEARCH_CHILDREN
#define AV_OPT_SEARCH_CHILDREN
Search in possible children of the given object first.
Definition: opt.h:563
link_outputs
static int link_outputs(AVFilterGraphSegment *seg, size_t idx_chain, size_t idx_filter, AVFilterInOut **outputs)
Definition: graphparser.c:744
av_opt_set_dict2
int av_opt_set_dict2(void *obj, AVDictionary **options, int search_flags)
Set all the options from a given dictionary on an object.
Definition: opt.c:1743
av_dict_free
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
Definition: dict.c:223
internal.h
AVFilterParams::nb_inputs
unsigned nb_inputs
Definition: avfilter.h:1189
AVFilterGraphSegment::graph
AVFilterGraph * graph
The filtergraph this segment is associated with.
Definition: avfilter.h:1220
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
avfilter_graph_parse_ptr
int avfilter_graph_parse_ptr(AVFilterGraph *graph, const char *filters, AVFilterInOut **open_inputs_ptr, AVFilterInOut **open_outputs_ptr, void *log_ctx)
Add a graph described by a string to a graph.
Definition: graphparser.c:889
extract_inout
static AVFilterInOut * extract_inout(const char *label, AVFilterInOut **links)
Definition: graphparser.c:85
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:254
AVFilterPad::name
const char * name
Pad name.
Definition: internal.h:55
AVFilter
Filter definition.
Definition: avfilter.h:161
ret
ret
Definition: filter_design.txt:187
links
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output links
Definition: filter_design.txt:14
AVFilterParams::opts
AVDictionary * opts
Options to be apllied to the filter.
Definition: avfilter.h:1186
dict.h
av_dynarray_add_nofree
int av_dynarray_add_nofree(void *tab_ptr, int *nb_ptr, void *elem)
Add an element to a dynamic array.
Definition: mem.c:313
linklabels_parse
static int linklabels_parse(void *logctx, const char **linklabels, AVFilterPadParams ***res, unsigned *nb_res)
Definition: graphparser.c:291
avfilter_init_dict
int avfilter_init_dict(AVFilterContext *ctx, AVDictionary **options)
Initialize a filter with the supplied dictionary of options.
Definition: avfilter.c:855
AVFilterChain
A filterchain is a list of filter specifications.
Definition: avfilter.h:1201
avfilter.h
av_get_token
char * av_get_token(const char **buf, const char *term)
Unescape the given string until a non escaped terminating char, and return the token corresponding to...
Definition: avstring.c:144
AVFilterContext::internal
AVFilterInternal * internal
An opaque struct for libavfilter internal use.
Definition: avfilter.h:432
AVERROR_FILTER_NOT_FOUND
#define AVERROR_FILTER_NOT_FOUND
Filter not found.
Definition: error.h:60
AVFilterGraphSegment::nb_chains
size_t nb_chains
Definition: avfilter.h:1227
AVFilterContext
An instance of a filter.
Definition: avfilter.h:392
avfilter_graph_parse
int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, AVFilterInOut *open_inputs, AVFilterInOut *open_outputs, void *log_ctx)
Add a graph described by a string to a graph.
Definition: graphparser.c:163
av_strdup
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:270
mem.h
avfilter_free
void avfilter_free(AVFilterContext *filter)
Free a filter context.
Definition: avfilter.c:731
filter_params_free
static void filter_params_free(AVFilterParams **pp)
Definition: graphparser.c:238
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
AVFilterInOut::name
char * name
unique name for this input/output in the list
Definition: avfilter.h:1017
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:561
av_strlcpy
size_t av_strlcpy(char *dst, const char *src, size_t size)
Copy the string src to dst, but no more than size - 1 bytes, and null-terminate dst.
Definition: avstring.c:86
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
avfilter_graph_segment_apply_opts
int avfilter_graph_segment_apply_opts(AVFilterGraphSegment *seg, int flags)
Apply parsed options to filter instances in a graph segment.
Definition: graphparser.c:584
AVFilterGraph::nb_filters
unsigned nb_filters
Definition: avfilter.h:858
avstring.h
AVFilterContext::filter
const AVFilter * filter
the AVFilter of which this is an instance
Definition: avfilter.h:395
AVFilterInOut
A linked-list of the inputs/outputs of the filter chain.
Definition: avfilter.h:1015
snprintf
#define snprintf
Definition: snprintf.h:34
filter_parse
static int filter_parse(void *logctx, const char **filter, AVFilterParams **pp)
Definition: graphparser.c:337
AVFilterPadParams
Parameters of a filter's input or output pad.
Definition: avfilter.h:1117
AVFilterContext::outputs
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:404