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/mem.h"
28 #include "avfilter.h"
29 
30 #define WHITESPACES " \n\t\r"
31 
32 /**
33  * Link two filters together.
34  *
35  * @see avfilter_link()
36  */
37 static int link_filter(AVFilterContext *src, int srcpad,
38  AVFilterContext *dst, int dstpad,
39  void *log_ctx)
40 {
41  int ret;
42  if ((ret = avfilter_link(src, srcpad, dst, dstpad))) {
43  av_log(log_ctx, AV_LOG_ERROR,
44  "Cannot create the link %s:%d -> %s:%d\n",
45  src->filter->name, srcpad, dst->filter->name, dstpad);
46  return ret;
47  }
48 
49  return 0;
50 }
51 
52 /**
53  * Parse the name of a link, which has the format "[linkname]".
54  *
55  * @return a pointer (that need to be freed after use) to the name
56  * between parenthesis
57  */
58 static char *parse_link_name(const char **buf, void *log_ctx)
59 {
60  const char *start = *buf;
61  char *name;
62  (*buf)++;
63 
64  name = av_get_token(buf, "]");
65  if (!name)
66  return NULL;
67 
68  if (!name[0]) {
69  av_log(log_ctx, AV_LOG_ERROR,
70  "Bad (empty?) label found in the following: \"%s\".\n", start);
71  goto fail;
72  }
73 
74  if (**buf != ']') {
75  av_log(log_ctx, AV_LOG_ERROR,
76  "Mismatched '[' found in the following: \"%s\".\n", start);
77  fail:
78  av_freep(&name);
79  return NULL;
80  }
81  (*buf)++;
82 
83  return name;
84 }
85 
86 /**
87  * Create an instance of a filter, initialize and insert it in the
88  * filtergraph in *ctx.
89  *
90  * @param filt_ctx put here a filter context in case of successful creation and configuration, NULL otherwise.
91  * @param ctx the filtergraph context
92  * @param index an index which is supposed to be unique for each filter instance added to the filtergraph
93  * @param name the name of the filter to create, can be filter name or filter_name\@id as instance name
94  * @param args the arguments provided to the filter during its initialization
95  * @param log_ctx the log context to use
96  * @return >= 0 in case of success, a negative AVERROR code otherwise
97  */
98 static int create_filter(AVFilterContext **filt_ctx, AVFilterGraph *ctx, int index,
99  const char *name, const char *args, void *log_ctx)
100 {
101  const AVFilter *filt;
102  char name2[30];
103  const char *inst_name = NULL, *filt_name = NULL;
104  char *tmp_args = NULL;
105  int ret, k;
106 
107  av_strlcpy(name2, name, sizeof(name2));
108 
109  for (k = 0; name2[k]; k++) {
110  if (name2[k] == '@' && name[k+1]) {
111  name2[k] = 0;
112  inst_name = name;
113  filt_name = name2;
114  break;
115  }
116  }
117 
118  if (!inst_name) {
119  snprintf(name2, sizeof(name2), "Parsed_%s_%d", name, index);
120  inst_name = name2;
121  filt_name = name;
122  }
123 
124  filt = avfilter_get_by_name(filt_name);
125 
126  if (!filt) {
127  av_log(log_ctx, AV_LOG_ERROR,
128  "No such filter: '%s'\n", filt_name);
129  return AVERROR(EINVAL);
130  }
131 
132  *filt_ctx = avfilter_graph_alloc_filter(ctx, filt, inst_name);
133  if (!*filt_ctx) {
134  av_log(log_ctx, AV_LOG_ERROR,
135  "Error creating filter '%s'\n", filt_name);
136  return AVERROR(ENOMEM);
137  }
138 
139  if (!strcmp(filt_name, "scale") && (!args || !strstr(args, "flags")) &&
140  ctx->scale_sws_opts) {
141  if (args) {
142  tmp_args = av_asprintf("%s:%s",
143  args, ctx->scale_sws_opts);
144  if (!tmp_args)
145  return AVERROR(ENOMEM);
146  args = tmp_args;
147  } else
148  args = ctx->scale_sws_opts;
149  }
150 
151  ret = avfilter_init_str(*filt_ctx, args);
152  if (ret < 0) {
153  av_log(log_ctx, AV_LOG_ERROR,
154  "Error initializing filter '%s'", filt_name);
155  if (args)
156  av_log(log_ctx, AV_LOG_ERROR, " with args '%s'", args);
157  av_log(log_ctx, AV_LOG_ERROR, "\n");
158  avfilter_free(*filt_ctx);
159  *filt_ctx = NULL;
160  }
161 
162  av_free(tmp_args);
163  return ret;
164 }
165 
166 /**
167  * Parse a string of the form FILTER_NAME[=PARAMS], and create a
168  * corresponding filter instance which is added to graph with
169  * create_filter().
170  *
171  * @param filt_ctx Pointer that is set to the created and configured filter
172  * context on success, set to NULL on failure.
173  * @param filt_ctx put here a pointer to the created filter context on
174  * success, NULL otherwise
175  * @param buf pointer to the buffer to parse, *buf will be updated to
176  * point to the char next after the parsed string
177  * @param index an index which is assigned to the created filter
178  * instance, and which is supposed to be unique for each filter
179  * instance added to the filtergraph
180  * @return >= 0 in case of success, a negative AVERROR code otherwise
181  */
182 static int parse_filter(AVFilterContext **filt_ctx, const char **buf, AVFilterGraph *graph,
183  int index, void *log_ctx)
184 {
185  char *opts = NULL;
186  char *name = av_get_token(buf, "=,;[");
187  int ret;
188 
189  if (!name)
190  return AVERROR(ENOMEM);
191 
192  if (**buf == '=') {
193  (*buf)++;
194  opts = av_get_token(buf, "[],;");
195  if (!opts) {
196  av_free(name);
197  return AVERROR(ENOMEM);
198  }
199  }
200 
201  ret = create_filter(filt_ctx, graph, index, name, opts, log_ctx);
202  av_free(name);
203  av_free(opts);
204  return ret;
205 }
206 
208 {
209  return av_mallocz(sizeof(AVFilterInOut));
210 }
211 
213 {
214  while (*inout) {
215  AVFilterInOut *next = (*inout)->next;
216  av_freep(&(*inout)->name);
217  av_freep(inout);
218  *inout = next;
219  }
220 }
221 
222 static AVFilterInOut *extract_inout(const char *label, AVFilterInOut **links)
223 {
225 
226  while (*links && (!(*links)->name || strcmp((*links)->name, label)))
227  links = &((*links)->next);
228 
229  ret = *links;
230 
231  if (ret) {
232  *links = ret->next;
233  ret->next = NULL;
234  }
235 
236  return ret;
237 }
238 
239 static void insert_inout(AVFilterInOut **inouts, AVFilterInOut *element)
240 {
241  element->next = *inouts;
242  *inouts = element;
243 }
244 
245 static void append_inout(AVFilterInOut **inouts, AVFilterInOut **element)
246 {
247  while (*inouts && (*inouts)->next)
248  inouts = &((*inouts)->next);
249 
250  if (!*inouts)
251  *inouts = *element;
252  else
253  (*inouts)->next = *element;
254  *element = NULL;
255 }
256 
257 static int link_filter_inouts(AVFilterContext *filt_ctx,
258  AVFilterInOut **curr_inputs,
259  AVFilterInOut **open_inputs, void *log_ctx)
260 {
261  int pad, ret;
262 
263  for (pad = 0; pad < filt_ctx->nb_inputs; pad++) {
264  AVFilterInOut *p = *curr_inputs;
265 
266  if (p) {
267  *curr_inputs = (*curr_inputs)->next;
268  p->next = NULL;
269  } else if (!(p = av_mallocz(sizeof(*p))))
270  return AVERROR(ENOMEM);
271 
272  if (p->filter_ctx) {
273  ret = link_filter(p->filter_ctx, p->pad_idx, filt_ctx, pad, log_ctx);
274  av_freep(&p->name);
275  av_freep(&p);
276  if (ret < 0)
277  return ret;
278  } else {
279  p->filter_ctx = filt_ctx;
280  p->pad_idx = pad;
281  append_inout(open_inputs, &p);
282  }
283  }
284 
285  if (*curr_inputs) {
286  av_log(log_ctx, AV_LOG_ERROR,
287  "Too many inputs specified for the \"%s\" filter.\n",
288  filt_ctx->filter->name);
289  return AVERROR(EINVAL);
290  }
291 
292  pad = filt_ctx->nb_outputs;
293  while (pad--) {
294  AVFilterInOut *currlinkn = av_mallocz(sizeof(AVFilterInOut));
295  if (!currlinkn)
296  return AVERROR(ENOMEM);
297  currlinkn->filter_ctx = filt_ctx;
298  currlinkn->pad_idx = pad;
299  insert_inout(curr_inputs, currlinkn);
300  }
301 
302  return 0;
303 }
304 
305 static int parse_inputs(const char **buf, AVFilterInOut **curr_inputs,
306  AVFilterInOut **open_outputs, void *log_ctx)
307 {
308  AVFilterInOut *parsed_inputs = NULL;
309  int pad = 0;
310 
311  while (**buf == '[') {
312  char *name = parse_link_name(buf, log_ctx);
313  AVFilterInOut *match;
314 
315  if (!name) {
316  avfilter_inout_free(&parsed_inputs);
317  return AVERROR(EINVAL);
318  }
319 
320  /* First check if the label is not in the open_outputs list */
321  match = extract_inout(name, open_outputs);
322 
323  if (match) {
324  av_free(name);
325  } else {
326  /* Not in the list, so add it as an input */
327  if (!(match = av_mallocz(sizeof(AVFilterInOut)))) {
328  avfilter_inout_free(&parsed_inputs);
329  av_free(name);
330  return AVERROR(ENOMEM);
331  }
332  match->name = name;
333  match->pad_idx = pad;
334  }
335 
336  append_inout(&parsed_inputs, &match);
337 
338  *buf += strspn(*buf, WHITESPACES);
339  pad++;
340  }
341 
342  append_inout(&parsed_inputs, curr_inputs);
343  *curr_inputs = parsed_inputs;
344 
345  return pad;
346 }
347 
348 static int parse_outputs(const char **buf, AVFilterInOut **curr_inputs,
349  AVFilterInOut **open_inputs,
350  AVFilterInOut **open_outputs, void *log_ctx)
351 {
352  int ret, pad = 0;
353 
354  while (**buf == '[') {
355  char *name = parse_link_name(buf, log_ctx);
356  AVFilterInOut *match;
357 
358  AVFilterInOut *input = *curr_inputs;
359 
360  if (!name)
361  return AVERROR(EINVAL);
362 
363  if (!input) {
364  av_log(log_ctx, AV_LOG_ERROR,
365  "No output pad can be associated to link label '%s'.\n", name);
366  av_free(name);
367  return AVERROR(EINVAL);
368  }
369  *curr_inputs = (*curr_inputs)->next;
370 
371  /* First check if the label is not in the open_inputs list */
372  match = extract_inout(name, open_inputs);
373 
374  if (match) {
375  ret = link_filter(input->filter_ctx, input->pad_idx,
376  match->filter_ctx, match->pad_idx, log_ctx);
377  av_freep(&match->name);
378  av_freep(&name);
379  av_freep(&match);
380  av_freep(&input);
381  if (ret < 0)
382  return ret;
383  } else {
384  /* Not in the list, so add the first input as an open_output */
385  input->name = name;
386  insert_inout(open_outputs, input);
387  }
388  *buf += strspn(*buf, WHITESPACES);
389  pad++;
390  }
391 
392  return pad;
393 }
394 
395 static int parse_sws_flags(const char **buf, AVFilterGraph *graph)
396 {
397  char *p = strchr(*buf, ';');
398 
399  if (strncmp(*buf, "sws_flags=", 10))
400  return 0;
401 
402  if (!p) {
403  av_log(graph, AV_LOG_ERROR, "sws_flags not terminated with ';'.\n");
404  return AVERROR(EINVAL);
405  }
406 
407  *buf += 4; // keep the 'flags=' part
408 
409  av_freep(&graph->scale_sws_opts);
410  if (!(graph->scale_sws_opts = av_mallocz(p - *buf + 1)))
411  return AVERROR(ENOMEM);
412  av_strlcpy(graph->scale_sws_opts, *buf, p - *buf + 1);
413 
414  *buf = p + 1;
415  return 0;
416 }
417 
421 {
422  int index = 0, ret = 0;
423  char chr = 0;
424 
425  AVFilterInOut *curr_inputs = NULL, *open_inputs = NULL, *open_outputs = NULL;
426 
427  filters += strspn(filters, WHITESPACES);
428 
429  if ((ret = parse_sws_flags(&filters, graph)) < 0)
430  goto fail;
431 
432  do {
434  filters += strspn(filters, WHITESPACES);
435 
436  if ((ret = parse_inputs(&filters, &curr_inputs, &open_outputs, graph)) < 0)
437  goto end;
438  if ((ret = parse_filter(&filter, &filters, graph, index, graph)) < 0)
439  goto end;
440 
441 
442  if ((ret = link_filter_inouts(filter, &curr_inputs, &open_inputs, graph)) < 0)
443  goto end;
444 
445  if ((ret = parse_outputs(&filters, &curr_inputs, &open_inputs, &open_outputs,
446  graph)) < 0)
447  goto end;
448 
449  filters += strspn(filters, WHITESPACES);
450  chr = *filters++;
451 
452  if (chr == ';' && curr_inputs)
453  append_inout(&open_outputs, &curr_inputs);
454  index++;
455  } while (chr == ',' || chr == ';');
456 
457  if (chr) {
458  av_log(graph, AV_LOG_ERROR,
459  "Unable to parse graph description substring: \"%s\"\n",
460  filters - 1);
461  ret = AVERROR(EINVAL);
462  goto end;
463  }
464 
465  append_inout(&open_outputs, &curr_inputs);
466 
467 
468  *inputs = open_inputs;
469  *outputs = open_outputs;
470  return 0;
471 
472  fail:end:
473  while (graph->nb_filters)
474  avfilter_free(graph->filters[0]);
475  av_freep(&graph->filters);
476  avfilter_inout_free(&open_inputs);
477  avfilter_inout_free(&open_outputs);
478  avfilter_inout_free(&curr_inputs);
479 
480  *inputs = NULL;
481  *outputs = NULL;
482 
483  return ret;
484 }
485 
487  AVFilterInOut *open_inputs,
488  AVFilterInOut *open_outputs, void *log_ctx)
489 {
490  int ret;
491  AVFilterInOut *cur, *match, *inputs = NULL, *outputs = NULL;
492 
493  if ((ret = avfilter_graph_parse2(graph, filters, &inputs, &outputs)) < 0)
494  goto fail;
495 
496  /* First input can be omitted if it is "[in]" */
497  if (inputs && !inputs->name)
498  inputs->name = av_strdup("in");
499  for (cur = inputs; cur; cur = cur->next) {
500  if (!cur->name) {
501  av_log(log_ctx, AV_LOG_ERROR,
502  "Not enough inputs specified for the \"%s\" filter.\n",
503  cur->filter_ctx->filter->name);
504  ret = AVERROR(EINVAL);
505  goto fail;
506  }
507  if (!(match = extract_inout(cur->name, &open_outputs)))
508  continue;
509  ret = avfilter_link(match->filter_ctx, match->pad_idx,
510  cur->filter_ctx, cur->pad_idx);
511  avfilter_inout_free(&match);
512  if (ret < 0)
513  goto fail;
514  }
515 
516  /* Last output can be omitted if it is "[out]" */
517  if (outputs && !outputs->name)
518  outputs->name = av_strdup("out");
519  for (cur = outputs; cur; cur = cur->next) {
520  if (!cur->name) {
521  av_log(log_ctx, AV_LOG_ERROR,
522  "Invalid filterchain containing an unlabelled output pad: \"%s\"\n",
523  filters);
524  ret = AVERROR(EINVAL);
525  goto fail;
526  }
527  if (!(match = extract_inout(cur->name, &open_inputs)))
528  continue;
529  ret = avfilter_link(cur->filter_ctx, cur->pad_idx,
530  match->filter_ctx, match->pad_idx);
531  avfilter_inout_free(&match);
532  if (ret < 0)
533  goto fail;
534  }
535 
536  fail:
537  if (ret < 0) {
538  while (graph->nb_filters)
539  avfilter_free(graph->filters[0]);
540  av_freep(&graph->filters);
541  }
542  avfilter_inout_free(&inputs);
543  avfilter_inout_free(&outputs);
544  avfilter_inout_free(&open_inputs);
545  avfilter_inout_free(&open_outputs);
546  return ret;
547 }
548 
550  AVFilterInOut **open_inputs_ptr, AVFilterInOut **open_outputs_ptr,
551  void *log_ctx)
552 {
553  int index = 0, ret = 0;
554  char chr = 0;
555 
556  AVFilterInOut *curr_inputs = NULL;
557  AVFilterInOut *open_inputs = open_inputs_ptr ? *open_inputs_ptr : NULL;
558  AVFilterInOut *open_outputs = open_outputs_ptr ? *open_outputs_ptr : NULL;
559 
560  if ((ret = parse_sws_flags(&filters, graph)) < 0)
561  goto end;
562 
563  do {
565  const char *filterchain = filters;
566  filters += strspn(filters, WHITESPACES);
567 
568  if ((ret = parse_inputs(&filters, &curr_inputs, &open_outputs, log_ctx)) < 0)
569  goto end;
570 
571  if ((ret = parse_filter(&filter, &filters, graph, index, log_ctx)) < 0)
572  goto end;
573 
574  if (filter->nb_inputs == 1 && !curr_inputs && !index) {
575  /* First input pad, assume it is "[in]" if not specified */
576  const char *tmp = "[in]";
577  if ((ret = parse_inputs(&tmp, &curr_inputs, &open_outputs, log_ctx)) < 0)
578  goto end;
579  }
580 
581  if ((ret = link_filter_inouts(filter, &curr_inputs, &open_inputs, log_ctx)) < 0)
582  goto end;
583 
584  if ((ret = parse_outputs(&filters, &curr_inputs, &open_inputs, &open_outputs,
585  log_ctx)) < 0)
586  goto end;
587 
588  filters += strspn(filters, WHITESPACES);
589  chr = *filters++;
590 
591  if (chr == ';' && curr_inputs) {
592  av_log(log_ctx, AV_LOG_ERROR,
593  "Invalid filterchain containing an unlabelled output pad: \"%s\"\n",
594  filterchain);
595  ret = AVERROR(EINVAL);
596  goto end;
597  }
598  index++;
599  } while (chr == ',' || chr == ';');
600 
601  if (chr) {
602  av_log(log_ctx, AV_LOG_ERROR,
603  "Unable to parse graph description substring: \"%s\"\n",
604  filters - 1);
605  ret = AVERROR(EINVAL);
606  goto end;
607  }
608 
609  if (curr_inputs) {
610  /* Last output pad, assume it is "[out]" if not specified */
611  const char *tmp = "[out]";
612  if ((ret = parse_outputs(&tmp, &curr_inputs, &open_inputs, &open_outputs,
613  log_ctx)) < 0)
614  goto end;
615  }
616 
617 end:
618  /* clear open_in/outputs only if not passed as parameters */
619  if (open_inputs_ptr) *open_inputs_ptr = open_inputs;
620  else avfilter_inout_free(&open_inputs);
621  if (open_outputs_ptr) *open_outputs_ptr = open_outputs;
622  else avfilter_inout_free(&open_outputs);
623  avfilter_inout_free(&curr_inputs);
624 
625  if (ret < 0) {
626  while (graph->nb_filters)
627  avfilter_free(graph->filters[0]);
628  av_freep(&graph->filters);
629  }
630  return ret;
631 }
AVFilterContext ** filters
Definition: avfilter.h:855
#define NULL
Definition: coverity.c:32
void avfilter_free(AVFilterContext *filter)
Free a filter context.
Definition: avfilter.c:758
Main libavfilter public API header.
Memory handling functions.
void avfilter_inout_free(AVFilterInOut **inout)
Free the supplied list of AVFilterInOut and set *inout to NULL.
Definition: graphparser.c:212
struct AVFilterInOut * next
next input/input in the list, NULL if this is the last
Definition: avfilter.h:1027
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:237
char * scale_sws_opts
sws options to use for the auto-inserted scale filters
Definition: avfilter.h:858
int avfilter_link(AVFilterContext *src, unsigned srcpad, AVFilterContext *dst, unsigned dstpad)
Link two filters together.
Definition: avfilter.c:135
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:92
static void insert_inout(AVFilterInOut **inouts, AVFilterInOut *element)
Definition: graphparser.c:239
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:418
#define av_log(a,...)
static int parse_inputs(const char **buf, AVFilterInOut **curr_inputs, AVFilterInOut **open_outputs, void *log_ctx)
Definition: graphparser.c:305
#define src
Definition: vp8dsp.c:254
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
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
static AVFilterInOut * extract_inout(const char *label, AVFilterInOut **links)
Definition: graphparser.c:222
unsigned nb_outputs
number of output pads
Definition: avfilter.h:352
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:83
#define fail()
Definition: checkasm.h:123
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:151
static int create_filter(AVFilterContext **filt_ctx, AVFilterGraph *ctx, int index, const char *name, const char *args, void *log_ctx)
Create an instance of a filter, initialize and insert it in the filtergraph in *ctx.
Definition: graphparser.c:98
const AVFilter * avfilter_get_by_name(const char *name)
Get a filter definition matching the given name.
Definition: allfilters.c:521
char * av_asprintf(const char *fmt,...)
Definition: avstring.c:113
AVDictionary * opts
Definition: movenc.c:50
unsigned nb_inputs
number of input pads
Definition: avfilter.h:348
AVFormatContext * ctx
Definition: movenc.c:48
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
AVFilterContext * filter_ctx
filter context associated to this input/output
Definition: avfilter.h:1021
static const AVFilterPad outputs[]
Definition: af_acontrast.c:203
int avfilter_init_str(AVFilterContext *filter, const char *args)
Initialize a filter with the supplied parameters.
Definition: avfilter.c:935
A linked-list of the inputs/outputs of the filter chain.
Definition: avfilter.h:1016
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:253
static int parse_sws_flags(const char **buf, AVFilterGraph *graph)
Definition: graphparser.c:395
static void append_inout(AVFilterInOut **inouts, AVFilterInOut **element)
Definition: graphparser.c:245
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
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:486
Filter definition.
Definition: avfilter.h:145
int index
Definition: gxfenc.c:89
int pad_idx
index of the filt_ctx pad to use for linking
Definition: avfilter.h:1024
const char * name
Filter name.
Definition: avfilter.h:149
unsigned nb_filters
Definition: avfilter.h:856
and forward the test the status of outputs and forward it to the corresponding return FFERROR_NOT_READY If the filters stores internally one or a few frame for some input
#define snprintf
Definition: snprintf.h:34
static int parse_filter(AVFilterContext **filt_ctx, const char **buf, AVFilterGraph *graph, int index, void *log_ctx)
Parse a string of the form FILTER_NAME[=PARAMS], and create a corresponding filter instance which is ...
Definition: graphparser.c:182
char * name
unique name for this input/output in the list
Definition: avfilter.h:1018
static const int8_t filt[NUMTAPS]
Definition: af_earwax.c:39
static int parse_outputs(const char **buf, AVFilterInOut **curr_inputs, AVFilterInOut **open_inputs, AVFilterInOut **open_outputs, void *log_ctx)
Definition: graphparser.c:348
AVFilterInOut * avfilter_inout_alloc(void)
Allocate a single AVFilterInOut entry.
Definition: graphparser.c:207
static int link_filter(AVFilterContext *src, int srcpad, AVFilterContext *dst, int dstpad, void *log_ctx)
Link two filters together.
Definition: graphparser.c:37
#define av_free(p)
AVFilterContext * avfilter_graph_alloc_filter(AVFilterGraph *graph, const AVFilter *filter, const char *name)
Create a new filter instance in a filter graph.
static const struct PPFilter filters[]
Definition: postprocess.c:134
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:58
static int link_filter_inouts(AVFilterContext *filt_ctx, AVFilterInOut **curr_inputs, AVFilterInOut **open_inputs, void *log_ctx)
Definition: graphparser.c:257
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:549
An instance of a filter.
Definition: avfilter.h:339
#define WHITESPACES
Definition: graphparser.c:30
#define av_freep(p)
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
const AVFilter * filter
the AVFilter of which this is an instance
Definition: avfilter.h:342
const char * name
Definition: opengl_enc.c:102
static uint8_t tmp[11]
Definition: aes_ctr.c:26