remove declaration inside for(), i is already declared
[libav.git] / libavfilter / graphparser.c
CommitLineData
27afb09d
VS
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 <ctype.h>
24#include <string.h>
25
372e2884 26#include "libavutil/avstring.h"
27afb09d
VS
27#include "avfilter.h"
28#include "avfiltergraph.h"
dd04911c 29#include "parseutils.h"
27afb09d 30
fd548e5b
SS
31#define WHITESPACES " \n\t"
32
d2874a9d
SS
33/**
34 * Link two filters together.
35 *
36 * @see avfilter_link()
37 */
9710beaf 38static int link_filter(AVFilterContext *src, int srcpad,
3a70bb2d
VS
39 AVFilterContext *dst, int dstpad,
40 AVClass *log_ctx)
27afb09d 41{
99ac59ca
SS
42 int ret;
43 if ((ret = avfilter_link(src, srcpad, dst, dstpad))) {
3a70bb2d 44 av_log(log_ctx, AV_LOG_ERROR,
bb90d855 45 "Cannot create the link %s:%d -> %s:%d\n",
9710beaf 46 src->filter->name, srcpad, dst->filter->name, dstpad);
99ac59ca 47 return ret;
27afb09d
VS
48 }
49
50 return 0;
51}
52
27afb09d 53/**
94b2120d
SS
54 * Parse the name of a link, which has the format "[linkname]".
55 *
56 * @return a pointer (that need to be freed after use) to the name
57 * between parenthesis
27afb09d 58 */
bd80b349 59static char *parse_link_name(const char **buf, AVClass *log_ctx)
27afb09d 60{
22260824 61 const char *start = *buf;
bd80b349 62 char *name;
27afb09d
VS
63 (*buf)++;
64
dd04911c 65 name = av_get_token(buf, "]");
27afb09d 66
f219eee5 67 if (!name[0]) {
3a70bb2d 68 av_log(log_ctx, AV_LOG_ERROR,
22260824 69 "Bad (empty?) label found in the following: \"%s\".\n", start);
27afb09d 70 goto fail;
22260824 71 }
27afb09d 72
f219eee5 73 if (*(*buf)++ != ']') {
3a70bb2d 74 av_log(log_ctx, AV_LOG_ERROR,
22260824 75 "Mismatched '[' found in the following: \"%s\".\n", start);
85cb8af7 76 fail:
bd80b349 77 av_freep(&name);
22260824 78 }
bd80b349
VS
79
80 return name;
27afb09d
VS
81}
82
98137a1a
SS
83/**
84 * Create an instance of a filter, initialize and insert it in the
85 * filtergraph in *ctx.
86 *
87 * @param ctx the filtergraph context
c58572f8 88 * @param put here a filter context in case of successful creation and configuration, NULL otherwise.
98137a1a
SS
89 * @param index an index which is supposed to be unique for each filter instance added to the filtergraph
90 * @param filt_name the name of the filter to create
91 * @param args the arguments provided to the filter during its initialization
92 * @param log_ctx the log context to use
c58572f8 93 * @return 0 in case of success, a negative AVERROR code otherwise
98137a1a 94 */
c58572f8
SS
95static int create_filter(AVFilterContext **filt_ctx, AVFilterGraph *ctx, int index,
96 const char *filt_name, const char *args, AVClass *log_ctx)
8e74c889 97{
e4a5f397 98 AVFilter *filt;
8e74c889 99 char inst_name[30];
b5049814 100 char tmp_args[256];
c58572f8 101 int ret;
8e74c889 102
03c3bb5c 103 snprintf(inst_name, sizeof(inst_name), "Filter %d %s", index, filt_name);
8e74c889 104
e4a5f397 105 filt = avfilter_get_by_name(filt_name);
5e600185 106
f219eee5 107 if (!filt) {
8e74c889 108 av_log(log_ctx, AV_LOG_ERROR,
bb90d855 109 "No such filter: '%s'\n", filt_name);
c58572f8 110 return AVERROR(EINVAL);
8e74c889
VS
111 }
112
c58572f8
SS
113 ret = avfilter_open(filt_ctx, filt, inst_name);
114 if (!*filt_ctx) {
8e74c889 115 av_log(log_ctx, AV_LOG_ERROR,
bb90d855 116 "Error creating filter '%s'\n", filt_name);
c58572f8 117 return ret;
8e74c889
VS
118 }
119
c58572f8 120 if ((ret = avfilter_graph_add_filter(ctx, *filt_ctx)) < 0) {
24de0edb 121 avfilter_free(*filt_ctx);
c58572f8 122 return ret;
64b164f4 123 }
8e74c889 124
b5049814
BC
125 if (!strcmp(filt_name, "scale") && !strstr(args, "flags")) {
126 snprintf(tmp_args, sizeof(tmp_args), "%s:%s",
127 args, ctx->scale_sws_opts);
128 args = tmp_args;
129 }
130
c58572f8 131 if ((ret = avfilter_init_filter(*filt_ctx, args, NULL)) < 0) {
8e74c889 132 av_log(log_ctx, AV_LOG_ERROR,
bb90d855 133 "Error initializing filter '%s' with args '%s'\n", filt_name, args);
c58572f8 134 return ret;
8e74c889
VS
135 }
136
c58572f8 137 return 0;
8e74c889
VS
138}
139
f5cbde2e 140/**
55b2a9ba
SS
141 * Parse a string of the form FILTER_NAME[=PARAMS], and create a
142 * corresponding filter instance which is added to graph with
143 * create_filter().
144 *
145 * @param filt_ctx put here a pointer to the created filter context on
146 * success, NULL otherwise
147 * @param buf pointer to the buffer to parse, *buf will be updated to
148 * point to the char next after the parsed string
149 * @param index an index which is assigned to the created filter
150 * instance, and which is supposed to be unique for each filter
151 * instance added to the filtergraph
152 * @return 0 in case of success, a negative AVERROR code otherwise
f5cbde2e 153 */
688b9dad
SS
154static int parse_filter(AVFilterContext **filt_ctx, const char **buf, AVFilterGraph *graph,
155 int index, AVClass *log_ctx)
f5cbde2e 156{
ba3fed2f 157 char *opts = NULL;
15a316c0 158 char *name = av_get_token(buf, "=,;[\n");
c58572f8 159 int ret;
f5cbde2e 160
f219eee5 161 if (**buf == '=') {
f5cbde2e 162 (*buf)++;
15a316c0 163 opts = av_get_token(buf, "[],;\n");
12849837 164 }
f5cbde2e 165
688b9dad 166 ret = create_filter(filt_ctx, graph, index, name, opts, log_ctx);
64b164f4
VS
167 av_free(name);
168 av_free(opts);
688b9dad 169 return ret;
f5cbde2e
VS
170}
171
27afb09d
VS
172static void free_inout(AVFilterInOut *head)
173{
f219eee5 174 while (head) {
55672c83 175 AVFilterInOut *next = head->next;
64b164f4 176 av_free(head->name);
27afb09d
VS
177 av_free(head);
178 head = next;
179 }
180}
181
c9987633
VS
182static AVFilterInOut *extract_inout(const char *label, AVFilterInOut **links)
183{
184 AVFilterInOut *ret;
c9987633 185
f219eee5 186 while (*links && strcmp((*links)->name, label))
f6557d5e 187 links = &((*links)->next);
c9987633 188
f6557d5e 189 ret = *links;
c9987633 190
f219eee5 191 if (ret)
f6557d5e 192 *links = ret->next;
c9987633
VS
193
194 return ret;
195}
196
e97908ee
VS
197static void insert_inout(AVFilterInOut **inouts, AVFilterInOut *element)
198{
199 element->next = *inouts;
200 *inouts = element;
201}
c9987633 202
ed581e65 203static int link_filter_inouts(AVFilterContext *filt_ctx,
7f9b3266
SS
204 AVFilterInOut **curr_inputs,
205 AVFilterInOut **open_inputs, AVClass *log_ctx)
c9987633 206{
ed581e65 207 int pad = filt_ctx->input_count, ret;
c9987633 208
f219eee5 209 while (pad--) {
7f9b3266 210 AVFilterInOut *p = *curr_inputs;
f219eee5 211 if (!p) {
c9987633
VS
212 av_log(log_ctx, AV_LOG_ERROR,
213 "Not enough inputs specified for the \"%s\" filter.\n",
ed581e65 214 filt_ctx->filter->name);
684ade49 215 return AVERROR(EINVAL);
c9987633
VS
216 }
217
7f9b3266 218 *curr_inputs = (*curr_inputs)->next;
4d11beb2 219
7313132b
SS
220 if (p->filter_ctx) {
221 if ((ret = link_filter(p->filter_ctx, p->pad_idx, filt_ctx, pad, log_ctx)) < 0)
684ade49 222 return ret;
64b164f4 223 av_free(p->name);
c9987633
VS
224 av_free(p);
225 } else {
7313132b 226 p->filter_ctx = filt_ctx;
c9987633 227 p->pad_idx = pad;
7f9b3266 228 insert_inout(open_inputs, p);
c9987633
VS
229 }
230 }
231
f219eee5 232 if (*curr_inputs) {
c9987633
VS
233 av_log(log_ctx, AV_LOG_ERROR,
234 "Too many inputs specified for the \"%s\" filter.\n",
ed581e65 235 filt_ctx->filter->name);
684ade49 236 return AVERROR(EINVAL);
c9987633
VS
237 }
238
ed581e65 239 pad = filt_ctx->output_count;
f219eee5 240 while (pad--) {
c956dd43 241 AVFilterInOut *currlinkn = av_mallocz(sizeof(AVFilterInOut));
fbd97184
SS
242 if (!currlinkn)
243 return AVERROR(ENOMEM);
7313132b 244 currlinkn->filter_ctx = filt_ctx;
c9987633 245 currlinkn->pad_idx = pad;
7f9b3266 246 insert_inout(curr_inputs, currlinkn);
c9987633
VS
247 }
248
249 return 0;
250}
251
7f9b3266
SS
252static int parse_inputs(const char **buf, AVFilterInOut **curr_inputs,
253 AVFilterInOut **open_outputs, AVClass *log_ctx)
27afb09d 254{
c9987633 255 int pad = 0;
c9987633 256
f219eee5 257 while (**buf == '[') {
bd80b349 258 char *name = parse_link_name(buf, log_ctx);
b2ac16da 259 AVFilterInOut *match;
22260824 260
f219eee5 261 if (!name)
42e7f6d7 262 return AVERROR(EINVAL);
22260824 263
7f9b3266
SS
264 /* First check if the label is not in the open_outputs list */
265 match = extract_inout(name, open_outputs);
cf4f7d38 266
f219eee5 267 if (match) {
64fbf5e2 268 av_free(name);
0de3407b
VS
269 } else {
270 /* Not in the list, so add it as an input */
00b3ca3c
SS
271 if (!(match = av_mallocz(sizeof(AVFilterInOut))))
272 return AVERROR(ENOMEM);
c880791f 273 match->name = name;
c880791f 274 match->pad_idx = pad;
cf4f7d38 275 }
e97908ee 276
7f9b3266 277 insert_inout(curr_inputs, match);
e97908ee 278
fd548e5b 279 *buf += strspn(*buf, WHITESPACES);
c9987633 280 pad++;
27afb09d 281 }
cf4f7d38 282
27afb09d
VS
283 return pad;
284}
285
7f9b3266
SS
286static int parse_outputs(const char **buf, AVFilterInOut **curr_inputs,
287 AVFilterInOut **open_inputs,
288 AVFilterInOut **open_outputs, AVClass *log_ctx)
9710beaf 289{
0cc8b659 290 int ret, pad = 0;
c9987633 291
f219eee5 292 while (**buf == '[') {
bd80b349 293 char *name = parse_link_name(buf, log_ctx);
c9987633
VS
294 AVFilterInOut *match;
295
7f9b3266
SS
296 AVFilterInOut *input = *curr_inputs;
297 *curr_inputs = (*curr_inputs)->next;
443c10ef 298
f219eee5 299 if (!name)
0cc8b659 300 return AVERROR(EINVAL);
c9987633 301
7f9b3266
SS
302 /* First check if the label is not in the open_inputs list */
303 match = extract_inout(name, open_inputs);
c9987633 304
f219eee5 305 if (match) {
7313132b
SS
306 if ((ret = link_filter(input->filter_ctx, input->pad_idx,
307 match->filter_ctx, match->pad_idx, log_ctx)) < 0)
0cc8b659 308 return ret;
64b164f4
VS
309 av_free(match->name);
310 av_free(name);
c9987633 311 av_free(match);
7baa6210 312 av_free(input);
0de3407b 313 } else {
7f9b3266 314 /* Not in the list, so add the first input as a open_output */
7baa6210 315 input->name = name;
7f9b3266 316 insert_inout(open_outputs, input);
c9987633 317 }
fd548e5b 318 *buf += strspn(*buf, WHITESPACES);
c9987633 319 pad++;
8095a014 320 }
9710beaf 321
c9987633
VS
322 return pad;
323}
9710beaf 324
86a47378 325int avfilter_graph_parse(AVFilterGraph *graph, const char *filters,
7f9b3266
SS
326 AVFilterInOut *open_inputs,
327 AVFilterInOut *open_outputs, AVClass *log_ctx)
27afb09d 328{
c24f76b9 329 int index = 0, ret;
27afb09d 330 char chr = 0;
27afb09d 331
7f9b3266 332 AVFilterInOut *curr_inputs = NULL;
27afb09d 333
27afb09d 334 do {
9710beaf 335 AVFilterContext *filter;
fd548e5b 336 filters += strspn(filters, WHITESPACES);
27afb09d 337
c24f76b9 338 if ((ret = parse_inputs(&filters, &curr_inputs, &open_outputs, log_ctx)) < 0)
27afb09d
VS
339 goto fail;
340
c24f76b9 341 if ((ret = parse_filter(&filter, &filters, graph, index, log_ctx)) < 0)
22260824
VS
342 goto fail;
343
f219eee5 344 if (filter->input_count == 1 && !curr_inputs && !index) {
e916c2ac 345 /* First input can be omitted if it is "[in]" */
c9987633 346 const char *tmp = "[in]";
c24f76b9 347 if ((ret = parse_inputs(&tmp, &curr_inputs, &open_outputs, log_ctx)) < 0)
27afb09d 348 goto fail;
27afb09d
VS
349 }
350
c24f76b9 351 if ((ret = link_filter_inouts(filter, &curr_inputs, &open_inputs, log_ctx)) < 0)
c9987633 352 goto fail;
da790674 353
c24f76b9
SS
354 if ((ret = parse_outputs(&filters, &curr_inputs, &open_inputs, &open_outputs,
355 log_ctx)) < 0)
e84f0b62
VS
356 goto fail;
357
fd548e5b 358 filters += strspn(filters, WHITESPACES);
27afb09d 359 chr = *filters++;
27afb09d 360
f219eee5 361 if (chr == ';' && curr_inputs) {
c9987633
VS
362 av_log(log_ctx, AV_LOG_ERROR,
363 "Could not find a output to link when parsing \"%s\"\n",
364 filters - 1);
c24f76b9 365 ret = AVERROR(EINVAL);
c9987633 366 goto fail;
27afb09d 367 }
c9987633 368 index++;
f219eee5 369 } while (chr == ',' || chr == ';');
27afb09d 370
fd51ff16 371 if (chr) {
78471234
SS
372 av_log(log_ctx, AV_LOG_ERROR,
373 "Unable to parse graph description substring: \"%s\"\n",
374 filters - 1);
c24f76b9 375 ret = AVERROR(EINVAL);
78471234
SS
376 goto fail;
377 }
378
f219eee5 379 if (open_inputs && !strcmp(open_inputs->name, "out") && curr_inputs) {
e916c2ac 380 /* Last output can be omitted if it is "[out]" */
c9987633 381 const char *tmp = "[out]";
c24f76b9
SS
382 if ((ret = parse_outputs(&tmp, &curr_inputs, &open_inputs, &open_outputs,
383 log_ctx)) < 0)
27afb09d 384 goto fail;
27afb09d
VS
385 }
386
387 return 0;
388
389 fail:
97dd1e4a 390 avfilter_graph_free(graph);
7f9b3266
SS
391 free_inout(open_inputs);
392 free_inout(open_outputs);
393 free_inout(curr_inputs);
c24f76b9 394 return ret;
27afb09d 395}