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 "avfilter_internal.h"
33 #include "internal.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 static char *parse_link_name(const char **buf, void *log_ctx)
44 {
45  const char *start = *buf;
46  char *name;
47  (*buf)++;
48 
49  name = av_get_token(buf, "]");
50  if (!name)
51  return NULL;
52 
53  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  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  (*buf)++;
67 
68  return name;
69 }
70 
72 {
73  return av_mallocz(sizeof(AVFilterInOut));
74 }
75 
77 {
78  while (*inout) {
79  AVFilterInOut *next = (*inout)->next;
80  av_freep(&(*inout)->name);
81  av_freep(inout);
82  *inout = next;
83  }
84 }
85 
86 static AVFilterInOut *extract_inout(const char *label, AVFilterInOut **links)
87 {
89 
90  while (*links && (!(*links)->name || strcmp((*links)->name, label)))
91  links = &((*links)->next);
92 
93  ret = *links;
94 
95  if (ret) {
96  *links = ret->next;
97  ret->next = NULL;
98  }
99 
100  return ret;
101 }
102 
103 static void append_inout(AVFilterInOut **inouts, AVFilterInOut **element)
104 {
105  while (*inouts && (*inouts)->next)
106  inouts = &((*inouts)->next);
107 
108  if (!*inouts)
109  *inouts = *element;
110  else
111  (*inouts)->next = *element;
112  *element = NULL;
113 }
114 
115 static int parse_sws_flags(const char **buf, char **dst, void *log_ctx)
116 {
117  char *p = strchr(*buf, ';');
118 
119  if (strncmp(*buf, "sws_flags=", 10))
120  return 0;
121 
122  if (!p) {
123  av_log(log_ctx, AV_LOG_ERROR, "sws_flags not terminated with ';'.\n");
124  return AVERROR(EINVAL);
125  }
126 
127  *buf += 4; // keep the 'flags=' part
128 
129  av_freep(dst);
130  if (!(*dst = av_mallocz(p - *buf + 1)))
131  return AVERROR(ENOMEM);
132  av_strlcpy(*dst, *buf, p - *buf + 1);
133 
134  *buf = p + 1;
135  return 0;
136 }
137 
141 {
143  int ret;
144 
145  ret = avfilter_graph_segment_parse(graph, filters, 0, &seg);
146  if (ret < 0)
147  return ret;
148 
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 
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  }
222  avfilter_inout_free(&open_inputs);
223  avfilter_inout_free(&open_outputs);
224  return ret;
225 }
226 
228 {
229  AVFilterPadParams *fpp = *pfpp;
230 
231  if (!fpp)
232  return;
233 
234  av_freep(&fpp->label);
235 
236  av_freep(pfpp);
237 }
238 
240 {
241  AVFilterParams *p = *pp;
242 
243  if (!p)
244  return;
245 
246  for (unsigned i = 0; i < p->nb_inputs; i++)
247  pad_params_free(&p->inputs[i]);
248  av_freep(&p->inputs);
249 
250  for (unsigned i = 0; i < p->nb_outputs; i++)
251  pad_params_free(&p->outputs[i]);
252  av_freep(&p->outputs);
253 
254  av_dict_free(&p->opts);
255 
256  av_freep(&p->filter_name);
257  av_freep(&p->instance_name);
258 
259  av_freep(pp);
260 }
261 
262 static void chain_free(AVFilterChain **pch)
263 {
264  AVFilterChain *ch = *pch;
265 
266  if (!ch)
267  return;
268 
269  for (size_t i = 0; i < ch->nb_filters; i++)
271  av_freep(&ch->filters);
272 
273  av_freep(pch);
274 }
275 
277 {
278  AVFilterGraphSegment *seg = *pseg;
279 
280  if (!seg)
281  return;
282 
283  for (size_t i = 0; i < seg->nb_chains; i++)
284  chain_free(&seg->chains[i]);
285  av_freep(&seg->chains);
286 
287  av_freep(&seg->scale_sws_opts);
288 
289  av_freep(pseg);
290 }
291 
292 static int linklabels_parse(void *logctx, const char **linklabels,
293  AVFilterPadParams ***res, unsigned *nb_res)
294 {
295  AVFilterPadParams **pp = NULL;
296  int nb = 0;
297  int ret;
298 
299  while (**linklabels == '[') {
300  char *label;
301  AVFilterPadParams *par;
302 
303  label = parse_link_name(linklabels, logctx);
304  if (!label) {
305  ret = AVERROR(EINVAL);
306  goto fail;
307  }
308 
309  par = av_mallocz(sizeof(*par));
310  if (!par) {
311  av_freep(&label);
312  ret = AVERROR(ENOMEM);
313  goto fail;
314  }
315 
316  par->label = label;
317 
318  ret = av_dynarray_add_nofree(&pp, &nb, par);
319  if (ret < 0) {
320  pad_params_free(&par);
321  goto fail;
322  }
323 
324  *linklabels += strspn(*linklabels, WHITESPACES);
325  }
326 
327  *res = pp;
328  *nb_res = nb;
329 
330  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 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  p = av_mallocz(sizeof(*p));
346  if (!p)
347  return AVERROR(ENOMEM);
348 
349  ret = linklabels_parse(logctx, filter, &p->inputs, &p->nb_inputs);
350  if (ret < 0)
351  goto fail;
352 
353  p->filter_name = av_get_token(filter, "=,;[");
354  if (!p->filter_name) {
355  ret = AVERROR(ENOMEM);
356  goto fail;
357  }
358 
359  inst_name = strchr(p->filter_name, '@');
360  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  if (**filter == '=') {
371  char *opts;
372 
373  (*filter)++;
374 
375  opts = av_get_token(filter, "[],;");
376  if (!opts) {
377  ret = AVERROR(ENOMEM);
378  goto fail;
379  }
380 
381  ret = ff_filter_opt_parse(logctx, f ? f->priv_class : NULL,
382  &p->opts, opts);
383  av_freep(&opts);
384  if (ret < 0)
385  goto fail;
386  }
387 
388  ret = linklabels_parse(logctx, filter, &p->outputs, &p->nb_outputs);
389  if (ret < 0)
390  goto fail;
391 
392  *filter += strspn(*filter, WHITESPACES);
393 
394  *pp = p;
395  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 static int chain_parse(void *logctx, const char **pchain,
404  AVFilterChain **pch)
405 {
406  const char *chain = *pchain;
407  AVFilterChain *ch;
408  int ret, nb_filters = 0;
409 
410  *pch = NULL;
411 
412  ch = av_mallocz(sizeof(*ch));
413  if (!ch)
414  return AVERROR(ENOMEM);
415 
416  while (*chain) {
417  AVFilterParams *p;
418  char chr;
419 
420  ret = filter_parse(logctx, &chain, &p);
421  if (ret < 0)
422  goto fail;
423 
424  ret = av_dynarray_add_nofree(&ch->filters, &nb_filters, p);
425  if (ret < 0) {
426  filter_params_free(&p);
427  goto fail;
428  }
429  ch->nb_filters = nb_filters;
430 
431  // a filter ends with one of: , ; end-of-string
432  chr = *chain;
433  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  if (chr) {
441  chain++;
442  chain += strspn(chain, WHITESPACES);
443 
444  if (chr == ';')
445  break;
446  }
447  }
448 
449  *pchain = chain;
450  *pch = ch;
451 
452  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 int avfilter_graph_segment_parse(AVFilterGraph *graph, const char *graph_str,
461  int flags, AVFilterGraphSegment **pseg)
462 {
464  int ret, nb_chains = 0;
465 
466  *pseg = NULL;
467 
468  if (flags)
469  return AVERROR(ENOSYS);
470 
471  seg = av_mallocz(sizeof(*seg));
472  if (!seg)
473  return AVERROR(ENOMEM);
474 
475  seg->graph = graph;
476 
477  graph_str += strspn(graph_str, WHITESPACES);
478 
479  ret = parse_sws_flags(&graph_str, &seg->scale_sws_opts, graph);
480  if (ret < 0)
481  goto fail;
482 
483  graph_str += strspn(graph_str, WHITESPACES);
484 
485  while (*graph_str) {
486  AVFilterChain *ch;
487 
488  ret = chain_parse(graph, &graph_str, &ch);
489  if (ret < 0)
490  goto fail;
491 
492  ret = av_dynarray_add_nofree(&seg->chains, &nb_chains, ch);
493  if (ret < 0) {
494  chain_free(&ch);
495  goto fail;
496  }
497  seg->nb_chains = nb_chains;
498 
499  graph_str += strspn(graph_str, WHITESPACES);
500  }
501 
502  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  *pseg = seg;
509 
510  return 0;
511 fail:
513  return ret;
514 }
515 
517 {
518  size_t idx = 0;
519 
520  if (flags)
521  return AVERROR(ENOSYS);
522 
523  if (seg->scale_sws_opts) {
524  av_freep(&seg->graph->scale_sws_opts);
526  if (!seg->graph->scale_sws_opts)
527  return AVERROR(ENOMEM);
528  }
529 
530  for (size_t i = 0; i < seg->nb_chains; i++) {
531  AVFilterChain *ch = seg->chains[i];
532 
533  for (size_t j = 0; j < ch->nb_filters; j++) {
534  AVFilterParams *p = ch->filters[j];
536  char name[64];
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(name, sizeof(name), "Parsed_%s_%zu", f->name, idx);
550  else
551  snprintf(name, sizeof(name), "%s@%s", f->name, p->instance_name);
552 
554  if (!p->filter)
555  return AVERROR(ENOMEM);
556 
557  if (!strcmp(f->name, "scale") && seg->graph->scale_sws_opts) {
559  "=", ":");
560  if (ret < 0) {
561  avfilter_free(p->filter);
562  p->filter = NULL;
563  return ret;
564  }
565  }
566 
567  av_freep(&p->filter_name);
568  av_freep(&p->instance_name);
569 
570  idx++;
571  }
572  }
573 
574  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 
587 {
588  int ret, leftover_opts = 0;
589 
590  if (flags)
591  return AVERROR(ENOSYS);
592 
593  for (size_t i = 0; i < seg->nb_chains; i++) {
594  AVFilterChain *ch = seg->chains[i];
595 
596  for (size_t j = 0; j < ch->nb_filters; j++) {
597  AVFilterParams *p = ch->filters[j];
598 
599  if (p->filter_name)
600  return fail_creation_pending(seg, p->filter_name, __func__);
601  if (!p->filter || !p->opts)
602  continue;
603 
605  if (ret < 0)
606  return ret;
607 
608  if (av_dict_count(p->opts))
609  leftover_opts = 1;
610  }
611  }
612 
613  return leftover_opts ? AVERROR_OPTION_NOT_FOUND : 0;
614 }
615 
617 {
618  if (flags)
619  return AVERROR(ENOSYS);
620 
621  for (size_t i = 0; i < seg->nb_chains; i++) {
622  AVFilterChain *ch = seg->chains[i];
623 
624  for (size_t j = 0; j < ch->nb_filters; j++) {
625  AVFilterParams *p = ch->filters[j];
626  int ret;
627 
628  if (p->filter_name)
629  return fail_creation_pending(seg, p->filter_name, __func__);
630  if (!p->filter || fffilterctx(p->filter)->initialized)
631  continue;
632 
634  if (ret < 0)
635  return ret;
636  }
637  }
638 
639  return 0;
640 }
641 
642 static unsigned
643 find_linklabel(AVFilterGraphSegment *seg, const char *label,
644  int output, size_t idx_chain, size_t idx_filter,
645  AVFilterParams **pp)
646 {
647  for (; idx_chain < seg->nb_chains; idx_chain++) {
648  AVFilterChain *ch = seg->chains[idx_chain];
649 
650  for (; idx_filter < ch->nb_filters; idx_filter++) {
651  AVFilterParams *p = ch->filters[idx_filter];
652  AVFilterPadParams **io = output ? p->outputs : p->inputs;
653  unsigned nb_io = output ? p->nb_outputs : p->nb_inputs;
654  AVFilterLink **l;
655  unsigned nb_l;
656 
657  if (!p->filter)
658  continue;
659 
660  l = output ? p->filter->outputs : p->filter->inputs;
661  nb_l = output ? p->filter->nb_outputs : p->filter->nb_inputs;
662 
663  for (unsigned i = 0; i < FFMIN(nb_io, nb_l); i++)
664  if (!l[i] && io[i]->label && !strcmp(io[i]->label, label)) {
665  *pp = p;
666  return i;
667  }
668  }
669 
670  idx_filter = 0;
671  }
672 
673  *pp = NULL;
674  return 0;
675 }
676 
677 static int inout_add(AVFilterInOut **inouts, AVFilterContext *f, unsigned pad_idx,
678  const char *label)
679 {
680  AVFilterInOut *io = av_mallocz(sizeof(*io));
681 
682  if (!io)
683  return AVERROR(ENOMEM);
684 
685  io->filter_ctx = f;
686  io->pad_idx = pad_idx;
687 
688  if (label) {
689  io->name = av_strdup(label);
690  if (!io->name) {
691  avfilter_inout_free(&io);
692  return AVERROR(ENOMEM);
693  }
694  }
695 
696  append_inout(inouts, &io);
697 
698  return 0;
699 }
700 
701 static int link_inputs(AVFilterGraphSegment *seg, size_t idx_chain,
702  size_t idx_filter, AVFilterInOut **inputs)
703 {
704  AVFilterChain *ch = seg->chains[idx_chain];
705  AVFilterParams *p = ch->filters[idx_filter];
706  AVFilterContext *f = p->filter;
707 
708  int ret;
709 
710  if (f->nb_inputs < p->nb_inputs) {
711  av_log(seg->graph, AV_LOG_ERROR,
712  "More input link labels specified for filter '%s' than "
713  "it has inputs: %u > %d\n", f->filter->name,
714  p->nb_inputs, f->nb_inputs);
715  return AVERROR(EINVAL);
716  }
717 
718  for (unsigned in = 0; in < f->nb_inputs; in++) {
719  const char *label = (in < p->nb_inputs) ? p->inputs[in]->label : NULL;
720 
721  // skip already linked inputs
722  if (f->inputs[in])
723  continue;
724 
725  if (label) {
726  AVFilterParams *po = NULL;
727  unsigned idx = find_linklabel(seg, label, 1, idx_chain, idx_filter, &po);
728 
729  if (po) {
730  ret = avfilter_link(po->filter, idx, f, in);
731  if (ret < 0)
732  return ret;
733 
734  continue;
735  }
736  }
737 
738  ret = inout_add(inputs, f, in, label);
739  if (ret < 0)
740  return ret;
741  }
742 
743  return 0;
744 }
745 
746 static int link_outputs(AVFilterGraphSegment *seg, size_t idx_chain,
747  size_t idx_filter, AVFilterInOut **outputs)
748 {
749  AVFilterChain *ch = seg->chains[idx_chain];
750  AVFilterParams *p = ch->filters[idx_filter];
751  AVFilterContext *f = p->filter;
752 
753  int ret;
754 
755  if (f->nb_outputs < p->nb_outputs) {
756  av_log(seg->graph, AV_LOG_ERROR,
757  "More output link labels specified for filter '%s' than "
758  "it has outputs: %u > %d\n", f->filter->name,
759  p->nb_outputs, f->nb_outputs);
760  return AVERROR(EINVAL);
761  }
762  for (unsigned out = 0; out < f->nb_outputs; out++) {
763  char *label = (out < p->nb_outputs) ? p->outputs[out]->label : NULL;
764 
765  // skip already linked outputs
766  if (f->outputs[out])
767  continue;
768 
769  if (label) {
770  AVFilterParams *po = NULL;
771  unsigned idx = find_linklabel(seg, label, 0, idx_chain, idx_filter, &po);
772 
773  if (po) {
774  ret = avfilter_link(f, out, po->filter, idx);
775  if (ret < 0)
776  return ret;
777 
778  continue;
779  }
780  }
781 
782  // if this output is unlabeled, try linking it to an unlabeled
783  // input in the next non-disabled filter in the chain
784  for (size_t i = idx_filter + 1; i < ch->nb_filters && !label; i++) {
785  AVFilterParams *p_next = ch->filters[i];
786 
787  if (!p_next->filter)
788  continue;
789 
790  for (unsigned in = 0; in < p_next->filter->nb_inputs; in++) {
791  if (!p_next->filter->inputs[in] &&
792  (in >= p_next->nb_inputs || !p_next->inputs[in]->label)) {
793  ret = avfilter_link(f, out, p_next->filter, in);
794  if (ret < 0)
795  return ret;
796 
797  goto cont;
798  }
799  }
800  break;
801  }
802 
803  ret = inout_add(outputs, f, out, label);
804  if (ret < 0)
805  return ret;
806 
807 cont:;
808  }
809 
810  return 0;
811 }
812 
816 {
817  int ret;
818 
819  *inputs = NULL;
820  *outputs = NULL;
821 
822  if (flags)
823  return AVERROR(ENOSYS);
824 
825  for (size_t idx_chain = 0; idx_chain < seg->nb_chains; idx_chain++) {
826  AVFilterChain *ch = seg->chains[idx_chain];
827 
828  for (size_t idx_filter = 0; idx_filter < ch->nb_filters; idx_filter++) {
829  AVFilterParams *p = ch->filters[idx_filter];
830 
831  if (p->filter_name) {
832  ret = fail_creation_pending(seg, p->filter_name, __func__);
833  goto fail;
834  }
835 
836  if (!p->filter)
837  continue;
838 
839  ret = link_inputs(seg, idx_chain, idx_filter, inputs);
840  if (ret < 0)
841  goto fail;
842 
843  ret = link_outputs(seg, idx_chain, idx_filter, outputs);
844  if (ret < 0)
845  goto fail;
846  }
847  }
848  return 0;
849 fail:
852  return ret;
853 }
854 
855 // print an error message if some options were not found
856 static void log_unknown_opt(const AVFilterGraphSegment *seg)
857 {
858  for (size_t i = 0; i < seg->nb_chains; i++) {
859  const AVFilterChain *ch = seg->chains[i];
860 
861  for (size_t j = 0; j < ch->nb_filters; j++) {
862  const AVFilterParams *p = ch->filters[j];
863  const AVDictionaryEntry *e;
864 
865  if (!p->filter)
866  continue;
867 
868  e = av_dict_iterate(p->opts, NULL);
869 
870  if (e) {
872  "Could not set non-existent option '%s' to value '%s'\n",
873  e->key, e->value);
874  return;
875  }
876  }
877  }
878 
879 }
880 
884 {
885  int ret;
886 
887  if (flags)
888  return AVERROR(ENOSYS);
889 
891  if (ret < 0) {
892  av_log(seg->graph, AV_LOG_ERROR, "Error creating filters\n");
893  return ret;
894  }
895 
897  if (ret < 0) {
899  log_unknown_opt(seg);
900  av_log(seg->graph, AV_LOG_ERROR, "Error applying filter options\n");
901  return ret;
902  }
903 
905  if (ret < 0) {
906  av_log(seg->graph, AV_LOG_ERROR, "Error initializing filters\n");
907  return ret;
908  }
909 
911  if (ret < 0) {
912  av_log(seg->graph, AV_LOG_ERROR, "Error linking filters\n");
913  return ret;
914  }
915 
916  return 0;
917 }
918 
920  AVFilterInOut **open_inputs_ptr, AVFilterInOut **open_outputs_ptr,
921  void *log_ctx)
922 {
923  AVFilterInOut *user_inputs = open_inputs_ptr ? *open_inputs_ptr : NULL;
924  AVFilterInOut *user_outputs = open_outputs_ptr ? *open_outputs_ptr : NULL;
925 
927  AVFilterGraphSegment *seg = NULL;
928  AVFilterChain *ch;
929  AVFilterParams *p;
930  int ret;
931 
932  ret = avfilter_graph_segment_parse(graph, filters, 0, &seg);
933  if (ret < 0)
934  goto end;
935 
937  if (ret < 0)
938  goto end;
939 
941  if (ret < 0) {
943  log_unknown_opt(seg);
944  goto end;
945  }
946 
948  if (ret < 0)
949  goto end;
950 
951  /* First input pad, assume it is "[in]" if not specified */
952  p = seg->chains[0]->filters[0];
953  if (p->filter->nb_inputs == 1 && !p->inputs) {
954  const char *tmp = "[in]";
955 
956  ret = linklabels_parse(graph, &tmp, &p->inputs, &p->nb_inputs);
957  if (ret < 0)
958  goto end;
959  }
960 
961  /* Last output pad, assume it is "[out]" if not specified */
962  ch = seg->chains[seg->nb_chains - 1];
963  p = ch->filters[ch->nb_filters - 1];
964  if (p->filter->nb_outputs == 1 && !p->outputs) {
965  const char *tmp = "[out]";
966 
967  ret = linklabels_parse(graph, &tmp, &p->outputs, &p->nb_outputs);
968  if (ret < 0)
969  goto end;
970  }
971 
974  if (ret < 0)
975  goto end;
976 
977  // process user-supplied inputs/outputs
978  while (inputs) {
979  AVFilterInOut *cur, *match = NULL;
980 
981  cur = inputs;
982  inputs = cur->next;
983  cur->next = NULL;
984 
985  if (cur->name)
986  match = extract_inout(cur->name, &user_outputs);
987 
988  if (match) {
989  ret = avfilter_link(match->filter_ctx, match->pad_idx,
990  cur->filter_ctx, cur->pad_idx);
991  avfilter_inout_free(&match);
992  avfilter_inout_free(&cur);
993  if (ret < 0)
994  goto end;
995  } else
996  append_inout(&user_inputs, &cur);
997  }
998  while (outputs) {
999  AVFilterInOut *cur, *match = NULL;
1000 
1001  cur = outputs;
1002  outputs = cur->next;
1003  cur->next = NULL;
1004 
1005  if (cur->name)
1006  match = extract_inout(cur->name, &user_inputs);
1007 
1008  if (match) {
1009  ret = avfilter_link(cur->filter_ctx, cur->pad_idx,
1010  match->filter_ctx, match->pad_idx);
1011  avfilter_inout_free(&match);
1012  avfilter_inout_free(&cur);
1013  if (ret < 0)
1014  goto end;
1015  } else
1016  append_inout(&user_outputs, &cur);
1017  }
1018 
1019 end:
1021 
1022  if (ret < 0) {
1023  av_log(graph, AV_LOG_ERROR, "Error processing filtergraph: %s\n",
1024  av_err2str(ret));
1025 
1026  while (graph->nb_filters)
1027  avfilter_free(graph->filters[0]);
1028  av_freep(&graph->filters);
1029  }
1030 
1031  /* clear open_in/outputs only if not passed as parameters */
1032  if (open_inputs_ptr) *open_inputs_ptr = user_inputs;
1033  else avfilter_inout_free(&user_inputs);
1034  if (open_outputs_ptr) *open_outputs_ptr = user_outputs;
1035  else avfilter_inout_free(&user_outputs);
1036 
1039 
1040  return ret;
1041 }
AV_OPT_SEARCH_CHILDREN
#define AV_OPT_SEARCH_CHILDREN
Search in possible children of the given object first.
Definition: opt.h:533
link_inputs
static int link_inputs(AVFilterGraphSegment *seg, size_t idx_chain, size_t idx_filter, AVFilterInOut **inputs)
Definition: graphparser.c:701
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:677
AVFilterParams::instance_name
char * instance_name
Name to be used for this filter instance.
Definition: avfilter.h:1115
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:516
out
FILE * out
Definition: movenc.c:55
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:834
av_dict_count
int av_dict_count(const AVDictionary *m)
Get number of entries in dictionary.
Definition: dict.c:39
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:115
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:967
fail_creation_pending
static int fail_creation_pending(AVFilterGraphSegment *seg, const char *fn, const char *func)
Definition: graphparser.c:577
AVFilterContext::nb_outputs
unsigned nb_outputs
number of output pads
Definition: avfilter.h:420
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:170
AVFilterParams::inputs
AVFilterPadParams ** inputs
Definition: avfilter.h:1129
chain_parse
static int chain_parse(void *logctx, const char **pchain, AVFilterChain **pch)
Definition: graphparser.c:403
AVFilterParams::outputs
AVFilterPadParams ** outputs
Definition: avfilter.h:1132
append_inout
static void append_inout(AVFilterInOut **inouts, AVFilterInOut **element)
Definition: graphparser.c:103
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:164
pad_params_free
static void pad_params_free(AVFilterPadParams **pfpp)
Definition: graphparser.c:227
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:813
fail
#define fail()
Definition: checkasm.h:182
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:276
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:460
avfilter_inout_free
void avfilter_inout_free(AVFilterInOut **inout)
Free the supplied list of AVFilterInOut and set *inout to NULL.
Definition: graphparser.c:76
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:643
FFFilterContext::initialized
int initialized
Definition: internal.h:126
AVFilterChain::filters
AVFilterParams ** filters
Definition: avfilter.h:1143
chain_free
static void chain_free(AVFilterChain **pch)
Definition: graphparser.c:262
AVDictionaryEntry::key
char * key
Definition: dict.h:90
filters
#define filters(fmt, type, inverse, clp, inverset, clip, one, clip_fn, packed)
Definition: af_crystalizer.c:54
avfilter_graph_segment_init
int avfilter_graph_segment_init(AVFilterGraphSegment *seg, int flags)
Initialize all filter instances in a graph segment.
Definition: graphparser.c:616
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:1793
AVFilterPadParams::label
char * label
An av_malloc()'ed string containing the pad label.
Definition: avfilter.h:1066
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:631
opts
AVDictionary * opts
Definition: movenc.c:51
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:881
NULL
#define NULL
Definition: coverity.c:32
AVFilterParams
Parameters describing a filter to be created in a filtergraph.
Definition: avfilter.h:1075
AVFilterParams::filter
AVFilterContext * filter
The filter context.
Definition: avfilter.h:1086
AVFilterChain::nb_filters
size_t nb_filters
Definition: avfilter.h:1144
AVFilterParams::filter_name
char * filter_name
Name of the AVFilter to be used.
Definition: avfilter.h:1103
AVFilterGraph::filters
AVFilterContext ** filters
Definition: avfilter.h:815
AVFilterContext::inputs
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:415
avfilter_inout_alloc
AVFilterInOut * avfilter_inout_alloc(void)
Allocate a single AVFilterInOut entry.
Definition: graphparser.c:71
AVFilterGraphSegment::chains
AVFilterChain ** chains
A list of filter chain contained in this segment.
Definition: avfilter.h:1167
avfilter_internal.h
AVFilterGraph
Definition: avfilter.h:813
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:138
AVFilterParams::nb_outputs
unsigned nb_outputs
Definition: avfilter.h:1133
AVFilterGraphSegment
A parsed representation of a filtergraph segment.
Definition: avfilter.h:1156
AVFilterInOut::pad_idx
int pad_idx
index of the filt_ctx pad to use for linking
Definition: avfilter.h:964
AVFilterGraph::scale_sws_opts
char * scale_sws_opts
sws options to use for the auto-inserted scale filters
Definition: avfilter.h:818
f
f
Definition: af_crystalizer.c:121
AVFilterContext::nb_inputs
unsigned nb_inputs
number of input pads
Definition: avfilter.h:416
AVFilterInOut::filter_ctx
AVFilterContext * filter_ctx
filter context associated to this input/output
Definition: avfilter.h:961
av_err2str
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition: error.h:122
avfilter_link
int avfilter_link(AVFilterContext *src, unsigned srcpad, AVFilterContext *dst, unsigned dstpad)
Link two filters together.
Definition: avfilter.c:149
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:43
WHITESPACES
#define WHITESPACES
Definition: graphparser.c:35
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:1178
fn
#define fn(a)
Definition: aap_template.c:37
link_outputs
static int link_outputs(AVFilterGraphSegment *seg, size_t idx_chain, size_t idx_filter, AVFilterInOut **outputs)
Definition: graphparser.c:746
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:1130
AVFilterGraphSegment::graph
AVFilterGraph * graph
The filtergraph this segment is associated with.
Definition: avfilter.h:1161
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
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:919
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:1938
extract_inout
static AVFilterInOut * extract_inout(const char *label, AVFilterInOut **links)
Definition: graphparser.c:86
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:256
AVFilterPad::name
const char * name
Pad name.
Definition: internal.h:39
outputs
static const AVFilterPad outputs[]
Definition: af_aap.c:311
AVFilter
Filter definition.
Definition: avfilter.h:166
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:1127
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:315
linklabels_parse
static int linklabels_parse(void *logctx, const char **linklabels, AVFilterPadParams ***res, unsigned *nb_res)
Definition: graphparser.c:292
avfilter_init_dict
int avfilter_init_dict(AVFilterContext *ctx, AVDictionary **options)
Initialize a filter with the supplied dictionary of options.
Definition: avfilter.c:900
AVFilterChain
A filterchain is a list of filter specifications.
Definition: avfilter.h:1142
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:143
log_unknown_opt
static void log_unknown_opt(const AVFilterGraphSegment *seg)
Definition: graphparser.c:856
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:1168
AVFilterContext
An instance of a filter.
Definition: avfilter.h:407
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:164
av_strdup
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:272
mem.h
avfilter_free
void avfilter_free(AVFilterContext *filter)
Free a filter context.
Definition: avfilter.c:782
AVDictionaryEntry
Definition: dict.h:89
filter_params_free
static void filter_params_free(AVFilterParams **pp)
Definition: graphparser.c:239
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:958
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:474
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:85
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:586
AVDictionaryEntry::value
char * value
Definition: dict.h:91
AVFilterGraph::nb_filters
unsigned nb_filters
Definition: avfilter.h:816
avstring.h
AVFilterContext::filter
const AVFilter * filter
the AVFilter of which this is an instance
Definition: avfilter.h:410
AVFilterInOut
A linked-list of the inputs/outputs of the filter chain.
Definition: avfilter.h:956
snprintf
#define snprintf
Definition: snprintf.h:34
filter_parse
static int filter_parse(void *logctx, const char **filter, AVFilterParams **pp)
Definition: graphparser.c:338
av_dict_iterate
const AVDictionaryEntry * av_dict_iterate(const AVDictionary *m, const AVDictionaryEntry *prev)
Iterate over a dictionary.
Definition: dict.c:44
fffilterctx
static FFFilterContext * fffilterctx(AVFilterContext *ctx)
Definition: internal.h:129
AVFilterPadParams
Parameters of a filter's input or output pad.
Definition: avfilter.h:1058
AVFilterContext::outputs
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:419