FFmpeg: libavfilter/graphparser.c Source File
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
30
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 */
44 {
45 const char *start = *buf;
47 (*buf)++;
48
52
55 "Bad (empty?) label found in the following: \"%s\".\n", start);
57 }
58
59 if (**buf != ']') {
61 "Mismatched '[' found in the following: \"%s\".\n", start);
65 }
66 (*buf)++;
67
69 }
70
72 {
74 }
75
77 {
78 while (*inout) {
82 *inout = next;
83 }
84 }
85
87 {
89
90 while (*
links && (!(*links)->name || strcmp((*links)->name, label)))
91 links = &((*links)->next);
92
94
98 }
99
101 }
102
104 {
105 while (*inouts && (*inouts)->
next)
106 inouts = &((*inouts)->next);
107
108 if (!*inouts)
109 *inouts = *element;
110 else
111 (*inouts)->
next = *element;
113 }
114
116 {
117 char *
p = strchr(*buf,
';');
118
119 if (strncmp(*buf, "sws_flags=", 10))
120 return 0;
121
125 }
126
127 *buf += 4; // keep the 'flags=' part
128
133
135 return 0;
136 }
137
141 {
144
148
152 goto end;
153
154 return 0;
155
156 end:
160
162 }
163
167 {
170
173
174 /* First input can be omitted if it is "[in]" */
180 "Not enough inputs specified for the \"%s\" filter.\n",
184 }
186 continue;
192 }
193
194 /* Last output can be omitted if it is "[out]" */
200 "Invalid filterchain containing an unlabelled output pad: \"%s\"\n",
204 }
206 continue;
212 }
213
219 }
225 }
226
228 {
230
231 if (!fpp)
232 return;
233
235
237 }
238
240 {
242
244 return;
245
246 for (
unsigned i = 0;
i <
p->nb_inputs;
i++)
249
250 for (
unsigned i = 0;
i <
p->nb_outputs;
i++)
253
255
258
260 }
261
263 {
265
266 if (!ch)
267 return;
268
272
274 }
275
277 {
279
280 if (!seg)
281 return;
282
286
288
290 }
291
294 {
296 int nb = 0;
298
299 while (**linklabels == '[') {
300 char *label;
302
304 if (!label) {
307 }
308
310 if (!par) {
314 }
315
317
322 }
323
325 }
326
327 *res = pp;
328 *nb_res = nb;
329
330 return 0;
332 for (
unsigned i = 0;
i < nb;
i++)
336 }
337
340 {
342 char *inst_name;
344
348
352
354 if (!
p->filter_name) {
357 }
358
359 inst_name = strchr(
p->filter_name,
'@');
360 if (inst_name) {
361 *inst_name++ = 0;
363 if (!
p->instance_name) {
366 }
367 }
368
372
373 (*filter)++;
374
379 }
380
386 }
387
391
393
395 return 0;
398 "Error parsing a filter description around: %s\n", *
filter);
401 }
402
405 {
406 const char *chain = *pchain;
408 int ret, nb_filters = 0;
409
411
413 if (!ch)
415
416 while (*chain) {
418 char chr;
419
423
428 }
430
431 // a filter ends with one of: , ; end-of-string
432 chr = *chain;
433 if (chr && chr != ',' && chr != ';') {
435 "Trailing garbage after a filter: %s\n", chain);
438 }
439
440 if (chr) {
441 chain++;
443
444 if (chr == ';')
445 break;
446 }
447 }
448
449 *pchain = chain;
450 *pch = ch;
451
452 return 0;
455 "Error parsing filterchain '%s' around: %s\n", *pchain, chain);
458 }
459
462 {
464 int ret, nb_chains = 0;
465
467
470
472 if (!seg)
474
476
478
482
484
485 while (*graph_str) {
487
491
496 }
498
500 }
501
506 }
507
508 *pseg = seg;
509
510 return 0;
514 }
515
517 {
518 size_t idx = 0;
519
522
528 }
529
532
537
538 // skip already processed filters
539 if (
p->filter || !
p->filter_name)
540 continue;
541
544 "No such filter: '%s'\n",
p->filter_name);
546 }
547
548 if (!
p->instance_name)
550 else
552
556
559 "=", ":");
564 }
565 }
566
569
570 idx++;
571 }
572 }
573
574 return 0;
575 }
576
579 {
581 "A creation-pending filter '%s' present in the segment. All filters "
582 "must be created or disabled before calling %s().\n",
fn,
func);
584 }
585
587 {
588 int ret, leftover_opts = 0;
589
592
595
598
601 if (!
p->filter || !
p->opts)
602 continue;
603
607
609 leftover_opts = 1;
610 }
611 }
612
614 }
615
617 {
620
623
627
632 continue;
633
637 }
638 }
639
640 return 0;
641 }
642
643 static unsigned
645 int output,
size_t idx_chain,
size_t idx_filter,
647 {
648 for (; idx_chain < seg->
nb_chains; idx_chain++) {
650
651 for (; idx_filter < ch->
nb_filters; idx_filter++) {
654 unsigned nb_io =
output ?
p->nb_outputs :
p->nb_inputs;
656 unsigned nb_l;
657
659 continue;
660
661 l =
output ?
p->filter->outputs :
p->filter->inputs;
662 nb_l =
output ?
p->filter->nb_outputs :
p->filter->nb_inputs;
663
664 for (
unsigned i = 0;
i <
FFMIN(nb_io, nb_l);
i++)
665 if (!l[
i] && io[
i]->label && !strcmp(io[
i]->label, label)) {
668 }
669 }
670
671 idx_filter = 0;
672 }
673
675 return 0;
676 }
677
679 const char *label)
680 {
682
683 if (!io)
685
688
689 if (label) {
694 }
695 }
696
698
699 return 0;
700 }
701
704 {
708
710
711 if (
f->nb_inputs <
p->nb_inputs) {
713 "More input link labels specified for filter '%s' than "
714 "it has inputs: %u > %d\n",
f->filter->name,
715 p->nb_inputs,
f->nb_inputs);
717 }
718
719 for (
unsigned in = 0; in <
f->nb_inputs; in++) {
720 const char *label = (in <
p->nb_inputs) ?
p->inputs[in]->label :
NULL;
721
722 // skip already linked inputs
724 continue;
725
726 if (label) {
728 unsigned idx =
find_linklabel(seg, label, 1, idx_chain, idx_filter, &po);
729
730 if (po) {
734
735 continue;
736 }
737 }
738
742 }
743
744 return 0;
745 }
746
749 {
753
755
756 if (
f->nb_outputs <
p->nb_outputs) {
758 "More output link labels specified for filter '%s' than "
759 "it has outputs: %u > %d\n",
f->filter->name,
760 p->nb_outputs,
f->nb_outputs);
762 }
763 for (
unsigned out = 0;
out <
f->nb_outputs;
out++) {
764 char *label = (
out <
p->nb_outputs) ?
p->outputs[
out]->label :
NULL;
765
766 // skip already linked outputs
768 continue;
769
770 if (label) {
772 unsigned idx =
find_linklabel(seg, label, 0, idx_chain, idx_filter, &po);
773
774 if (po) {
778
779 continue;
780 }
781 }
782
783 // if this output is unlabeled, try linking it to an unlabeled
784 // input in the next non-disabled filter in the chain
785 for (
size_t i = idx_filter + 1;
i < ch->
nb_filters && !label;
i++) {
787
789 continue;
790
797
798 goto cont;
799 }
800 }
801 break;
802 }
803
807
808 cont:;
809 }
810
811 return 0;
812 }
813
817 {
819
822
825
826 for (
size_t idx_chain = 0; idx_chain < seg->
nb_chains; idx_chain++) {
828
829 for (
size_t idx_filter = 0; idx_filter < ch->
nb_filters; idx_filter++) {
831
832 if (
p->filter_name) {
835 }
836
838 continue;
839
843
847 }
848 }
849 return 0;
854 }
855
856 // print an error message if some options were not found
858 {
861
865
867 continue;
868
870
871 if (e) {
873 "Could not set non-existent option '%s' to value '%s'\n",
875 return;
876 }
877 }
878 }
879
880 }
881
885 {
887
890
895 }
896
903 }
904
909 }
910
915 }
916
917 return 0;
918 }
919
922 void *log_ctx)
923 {
926
932
935 goto end;
936
939 goto end;
940
945 goto end;
946 }
947
950 goto end;
951
952 /* First input pad, assume it is "[in]" if not specified */
954 if (
p->filter->nb_inputs == 1 && !
p->inputs) {
955 const char *
tmp =
"[in]";
956
959 goto end;
960 }
961
962 /* Last output pad, assume it is "[out]" if not specified */
965 if (
p->filter->nb_outputs == 1 && !
p->outputs) {
966 const char *
tmp =
"[out]";
967
970 goto end;
971 }
972
976 goto end;
977
978 // process user-supplied inputs/outputs
981
985
988
989 if (match) {
995 goto end;
996 } else
998 }
1001
1005
1008
1009 if (match) {
1015 goto end;
1016 } else
1018 }
1019
1020 end:
1022
1026
1030 }
1031
1032 /* clear open_in/outputs only if not passed as parameters */
1033 if (open_inputs_ptr) *open_inputs_ptr = user_inputs;
1035 if (open_outputs_ptr) *open_outputs_ptr = user_outputs;
1037
1040
1042 }
#define AV_OPT_SEARCH_CHILDREN
Search in possible children of the given object first.
static int link_inputs(AVFilterGraphSegment *seg, size_t idx_chain, size_t idx_filter, AVFilterInOut **inputs)
int(* func)(AVBPrint *dst, const char *in, const char *arg)
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
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
static int inout_add(AVFilterInOut **inouts, AVFilterContext *f, unsigned pad_idx, const char *label)
int avfilter_graph_segment_create_filters(AVFilterGraphSegment *seg, int flags)
Create filters specified in a graph segment.
int ff_filter_opt_parse(void *logctx, const AVClass *priv_class, AVDictionary **options, const char *args)
Parse filter options into a dictionary.
int av_dict_count(const AVDictionary *m)
Get number of entries in dictionary.
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
static int parse_sws_flags(const char **buf, char **dst, void *log_ctx)
struct AVFilterInOut * next
next input/input in the list, NULL if this is the last
static int fail_creation_pending(AVFilterGraphSegment *seg, const char *fn, const char *func)
void(* filter)(uint8_t *src, int stride, int qscale)
const char * name
Filter name.
AVFilterPadParams ** inputs
A link between two filters.
static int chain_parse(void *logctx, const char **pchain, AVFilterChain **pch)
static void append_inout(AVFilterInOut **inouts, AVFilterInOut **element)
AVFilterContext * avfilter_graph_alloc_filter(AVFilterGraph *graph, const AVFilter *filter, const char *name)
Create a new filter instance in a filter graph.
static void pad_params_free(AVFilterPadParams **pfpp)
int avfilter_graph_segment_link(AVFilterGraphSegment *seg, int flags, AVFilterInOut **inputs, AVFilterInOut **outputs)
Link filters in a graph segment.
#define AVERROR_OPTION_NOT_FOUND
Option not found.
void avfilter_graph_segment_free(AVFilterGraphSegment **pseg)
Free the provided AVFilterGraphSegment and everything associated with it.
int avfilter_graph_segment_parse(AVFilterGraph *graph, const char *graph_str, int flags, AVFilterGraphSegment **pseg)
Parse a textual filtergraph description into an intermediate form.
void avfilter_inout_free(AVFilterInOut **inout)
Free the supplied list of AVFilterInOut and set *inout to NULL.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
static unsigned find_linklabel(AVFilterGraphSegment *seg, const char *label, int output, size_t idx_chain, size_t idx_filter, AVFilterParams **pp)
AVFilterParams ** filters
static void chain_free(AVFilterChain **pch)
#define filters(fmt, type, inverse, clp, inverset, clip, one, clip_fn, packed)
int avfilter_graph_segment_init(AVFilterGraphSegment *seg, int flags)
Initialize all filter instances in a graph segment.
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.
char * label
An av_malloc()'ed string containing the pad label.
const AVFilter * avfilter_get_by_name(const char *name)
Get a filter definition matching the given name.
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.
Parameters describing a filter to be created in a filtergraph.
AVFilterContext * filter
The filter context.
AVFilterContext ** filters
AVFilterLink ** inputs
array of pointers to input links
@ AV_CLASS_STATE_INITIALIZED
Object initialization has finished and it is now in the 'runtime' stage.
AVFilterInOut * avfilter_inout_alloc(void)
Allocate a single AVFilterInOut entry.
AVFilterChain ** chains
A list of filter chain contained in this segment.
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_parse2(AVFilterGraph *graph, const char *filters, AVFilterInOut **inputs, AVFilterInOut **outputs)
Add a graph described by a string to a graph.
A parsed representation of a filtergraph segment.
int pad_idx
index of the filt_ctx pad to use for linking
char * scale_sws_opts
sws options to use for the auto-inserted scale filters
unsigned nb_inputs
number of input pads
AVFilterContext * filter_ctx
filter context associated to this input/output
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
int avfilter_link(AVFilterContext *src, unsigned srcpad, AVFilterContext *dst, unsigned dstpad)
Link two filters together.
static char * parse_link_name(const char **buf, void *log_ctx)
Parse the name of a link, which has the format "[linkname]".
char * scale_sws_opts
A string containing a colon-separated list of key=value options applied to all scale filters in this ...
static int link_outputs(AVFilterGraphSegment *seg, size_t idx_chain, size_t idx_filter, AVFilterInOut **outputs)
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
AVFilterGraph * graph
The filtergraph this segment is associated with.
#define i(width, name, range_min, range_max)
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.
int av_opt_set_dict2(void *obj, AVDictionary **options, int search_flags)
Set all the options from a given dictionary on an object.
static AVFilterInOut * extract_inout(const char *label, AVFilterInOut **links)
static FFFilterContext * fffilterctx(AVFilterContext *ctx)
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
const char * name
Pad name.
static const AVFilterPad outputs[]
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
int av_dynarray_add_nofree(void *tab_ptr, int *nb_ptr, void *elem)
Add an element to a dynamic array.
static int linklabels_parse(void *logctx, const char **linklabels, AVFilterPadParams ***res, unsigned *nb_res)
int avfilter_init_dict(AVFilterContext *ctx, AVDictionary **options)
Initialize a filter with the supplied dictionary of options.
A filterchain is a list of filter specifications.
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...
static void log_unknown_opt(const AVFilterGraphSegment *seg)
IDirect3DDxgiInterfaceAccess _COM_Outptr_ void ** p
#define AVERROR_FILTER_NOT_FOUND
Filter not found.
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.
char * av_strdup(const char *s)
Duplicate a string.
void avfilter_free(AVFilterContext *filter)
Free a filter context.
static void filter_params_free(AVFilterParams **pp)
char * name
unique name for this input/output in the list
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.
int avfilter_graph_segment_apply_opts(AVFilterGraphSegment *seg, int flags)
Apply parsed options to filter instances in a graph segment.
const AVFilter * filter
the AVFilter of which this is an instance
A linked-list of the inputs/outputs of the filter chain.
static int filter_parse(void *logctx, const char **filter, AVFilterParams **pp)
const AVDictionaryEntry * av_dict_iterate(const AVDictionary *m, const AVDictionaryEntry *prev)
Iterate over a dictionary.
Parameters of a filter's input or output pad.
Generated on Thu Oct 16 2025 19:23:05 for FFmpeg by
doxygen
1.8.17