Statistics
| Branch: | Revision:

ffmpeg / libavfilter / graphparser.c @ 63613fe6

History | View | Annotate | Download (9.41 KB)

1 27afb09d Vitor Sessak
/*
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
26 6a0c770b Vitor Sessak
#include "graphparser.h"
27 27afb09d Vitor Sessak
#include "avfilter.h"
28
#include "avfiltergraph.h"
29 dd04911c Stefano Sabatini
#include "parseutils.h"
30 27afb09d Vitor Sessak
31 fd548e5b Stefano Sabatini
#define WHITESPACES " \n\t"
32
33 9710beaf Vitor Sessak
static int link_filter(AVFilterContext *src, int srcpad,
34 3a70bb2d Vitor Sessak
                       AVFilterContext *dst, int dstpad,
35
                       AVClass *log_ctx)
36 27afb09d Vitor Sessak
{
37 9710beaf Vitor Sessak
    if(avfilter_link(src, srcpad, dst, dstpad)) {
38 3a70bb2d Vitor Sessak
        av_log(log_ctx, AV_LOG_ERROR,
39 9710beaf Vitor Sessak
               "cannot create the link %s:%d -> %s:%d\n",
40
               src->filter->name, srcpad, dst->filter->name, dstpad);
41 27afb09d Vitor Sessak
        return -1;
42
    }
43
44
    return 0;
45
}
46
47
/**
48 ffac8784 Vitor Sessak
 * Parse "[linkname]"
49 69fa7e80 Vitor Sessak
 * @param name a pointer (that need to be free'd after use) to the name between
50
 *        parenthesis
51 27afb09d Vitor Sessak
 */
52 bd80b349 Vitor Sessak
static char *parse_link_name(const char **buf, AVClass *log_ctx)
53 27afb09d Vitor Sessak
{
54 22260824 Vitor Sessak
    const char *start = *buf;
55 bd80b349 Vitor Sessak
    char *name;
56 27afb09d Vitor Sessak
    (*buf)++;
57
58 dd04911c Stefano Sabatini
    name = av_get_token(buf, "]");
59 27afb09d Vitor Sessak
60 bd80b349 Vitor Sessak
    if(!name[0]) {
61 3a70bb2d Vitor Sessak
        av_log(log_ctx, AV_LOG_ERROR,
62 22260824 Vitor Sessak
               "Bad (empty?) label found in the following: \"%s\".\n", start);
63 27afb09d Vitor Sessak
        goto fail;
64 22260824 Vitor Sessak
    }
65 27afb09d Vitor Sessak
66 22260824 Vitor Sessak
    if(*(*buf)++ != ']') {
67 3a70bb2d Vitor Sessak
        av_log(log_ctx, AV_LOG_ERROR,
68 22260824 Vitor Sessak
               "Mismatched '[' found in the following: \"%s\".\n", start);
69 85cb8af7 Vitor Sessak
    fail:
70 bd80b349 Vitor Sessak
        av_freep(&name);
71 22260824 Vitor Sessak
    }
72 bd80b349 Vitor Sessak
73
    return name;
74 27afb09d Vitor Sessak
}
75
76 8e74c889 Vitor Sessak
static AVFilterContext *create_filter(AVFilterGraph *ctx, int index,
77 e4a5f397 Stefano Sabatini
                                      const char *filt_name, const char *args,
78 8e74c889 Vitor Sessak
                                      AVClass *log_ctx)
79
{
80 e4a5f397 Stefano Sabatini
    AVFilterContext *filt_ctx;
81 8e74c889 Vitor Sessak
82 e4a5f397 Stefano Sabatini
    AVFilter *filt;
83 8e74c889 Vitor Sessak
    char inst_name[30];
84
85
    snprintf(inst_name, sizeof(inst_name), "Parsed filter %d", index);
86
87 e4a5f397 Stefano Sabatini
    filt = avfilter_get_by_name(filt_name);
88 5e600185 Vitor Sessak
89 e4a5f397 Stefano Sabatini
    if(!filt) {
90 8e74c889 Vitor Sessak
        av_log(log_ctx, AV_LOG_ERROR,
91 e4a5f397 Stefano Sabatini
               "no such filter: '%s'\n", filt_name);
92 8e74c889 Vitor Sessak
        return NULL;
93
    }
94
95 e4a5f397 Stefano Sabatini
    filt_ctx = avfilter_open(filt, inst_name);
96
    if(!filt_ctx) {
97 8e74c889 Vitor Sessak
        av_log(log_ctx, AV_LOG_ERROR,
98 e4a5f397 Stefano Sabatini
               "error creating filter '%s'\n", filt_name);
99 8e74c889 Vitor Sessak
        return NULL;
100
    }
101
102 e4a5f397 Stefano Sabatini
    if(avfilter_graph_add_filter(ctx, filt_ctx) < 0) {
103
        avfilter_destroy(filt_ctx);
104 8e74c889 Vitor Sessak
        return NULL;
105 64b164f4 Vitor Sessak
    }
106 8e74c889 Vitor Sessak
107 e4a5f397 Stefano Sabatini
    if(avfilter_init_filter(filt_ctx, args, NULL)) {
108 8e74c889 Vitor Sessak
        av_log(log_ctx, AV_LOG_ERROR,
109 e4a5f397 Stefano Sabatini
               "error initializing filter '%s' with args '%s'\n", filt_name, args);
110 8e74c889 Vitor Sessak
        return NULL;
111
    }
112
113 e4a5f397 Stefano Sabatini
    return filt_ctx;
114 8e74c889 Vitor Sessak
}
115
116 f5cbde2e Vitor Sessak
/**
117
 * Parse "filter=params"
118
 */
119
static AVFilterContext *parse_filter(const char **buf, AVFilterGraph *graph,
120
                                     int index, AVClass *log_ctx)
121
{
122 ba3fed2f Vitor Sessak
    char *opts = NULL;
123 b755a754 Vitor Sessak
    char *name = av_get_token(buf, "=,[");
124 64b164f4 Vitor Sessak
    AVFilterContext *ret;
125 f5cbde2e Vitor Sessak
126 12849837 Vitor Sessak
    if(**buf == '=') {
127 f5cbde2e Vitor Sessak
        (*buf)++;
128 dd04911c Stefano Sabatini
        opts = av_get_token(buf, "[],\n");
129 12849837 Vitor Sessak
    }
130 f5cbde2e Vitor Sessak
131 64b164f4 Vitor Sessak
    ret = create_filter(graph, index, name, opts, log_ctx);
132
    av_free(name);
133
    av_free(opts);
134
    return ret;
135 f5cbde2e Vitor Sessak
}
136
137 27afb09d Vitor Sessak
static void free_inout(AVFilterInOut *head)
138
{
139 487c0e67 Vitor Sessak
    while(head) {
140 55672c83 Vitor Sessak
        AVFilterInOut *next = head->next;
141 64b164f4 Vitor Sessak
        av_free(head->name);
142 27afb09d Vitor Sessak
        av_free(head);
143
        head = next;
144
    }
145
}
146
147 c9987633 Vitor Sessak
static AVFilterInOut *extract_inout(const char *label, AVFilterInOut **links)
148
{
149
    AVFilterInOut *ret;
150
151 fec2e513 Vitor Sessak
    while(*links && strcmp((*links)->name, label))
152 f6557d5e Vitor Sessak
        links = &((*links)->next);
153 c9987633 Vitor Sessak
154 f6557d5e Vitor Sessak
    ret = *links;
155 c9987633 Vitor Sessak
156 fec2e513 Vitor Sessak
    if(ret)
157 f6557d5e Vitor Sessak
        *links = ret->next;
158 c9987633 Vitor Sessak
159
    return ret;
160
}
161
162 e97908ee Vitor Sessak
static void insert_inout(AVFilterInOut **inouts, AVFilterInOut *element)
163
{
164
    element->next = *inouts;
165
    *inouts = element;
166
}
167 c9987633 Vitor Sessak
168
static int link_filter_inouts(AVFilterContext *filter,
169 7f9b3266 Stefano Sabatini
                              AVFilterInOut **curr_inputs,
170
                              AVFilterInOut **open_inputs, AVClass *log_ctx)
171 c9987633 Vitor Sessak
{
172 90ed076c Vitor Sessak
    int pad = filter->input_count;
173 c9987633 Vitor Sessak
174 4fd9d074 Vitor Sessak
    while(pad--) {
175 7f9b3266 Stefano Sabatini
        AVFilterInOut *p = *curr_inputs;
176 c9987633 Vitor Sessak
        if(!p) {
177
            av_log(log_ctx, AV_LOG_ERROR,
178
                   "Not enough inputs specified for the \"%s\" filter.\n",
179 089d3714 Vitor Sessak
                   filter->filter->name);
180 c9987633 Vitor Sessak
            return -1;
181
        }
182
183 7f9b3266 Stefano Sabatini
        *curr_inputs = (*curr_inputs)->next;
184 4d11beb2 Vitor Sessak
185 c9987633 Vitor Sessak
        if(p->filter) {
186
            if(link_filter(p->filter, p->pad_idx, filter, pad, log_ctx))
187
                return -1;
188 64b164f4 Vitor Sessak
            av_free(p->name);
189 c9987633 Vitor Sessak
            av_free(p);
190
        } else {
191
            p->filter = filter;
192
            p->pad_idx = pad;
193 7f9b3266 Stefano Sabatini
            insert_inout(open_inputs, p);
194 c9987633 Vitor Sessak
        }
195
    }
196
197 7f9b3266 Stefano Sabatini
    if(*curr_inputs) {
198 c9987633 Vitor Sessak
        av_log(log_ctx, AV_LOG_ERROR,
199
               "Too many inputs specified for the \"%s\" filter.\n",
200 089d3714 Vitor Sessak
               filter->filter->name);
201 c9987633 Vitor Sessak
        return -1;
202
    }
203
204
    pad = filter->output_count;
205 4fd9d074 Vitor Sessak
    while(pad--) {
206 c956dd43 Vitor Sessak
        AVFilterInOut *currlinkn = av_mallocz(sizeof(AVFilterInOut));
207 c9987633 Vitor Sessak
        currlinkn->filter  = filter;
208
        currlinkn->pad_idx = pad;
209 7f9b3266 Stefano Sabatini
        insert_inout(curr_inputs, currlinkn);
210 c9987633 Vitor Sessak
    }
211
212
    return 0;
213
}
214
215 7f9b3266 Stefano Sabatini
static int parse_inputs(const char **buf, AVFilterInOut **curr_inputs,
216
                        AVFilterInOut **open_outputs, AVClass *log_ctx)
217 27afb09d Vitor Sessak
{
218 c9987633 Vitor Sessak
    int pad = 0;
219
220 487c0e67 Vitor Sessak
    while(**buf == '[') {
221 bd80b349 Vitor Sessak
        char *name = parse_link_name(buf, log_ctx);
222 b2ac16da Vitor Sessak
        AVFilterInOut *match;
223 22260824 Vitor Sessak
224 a4501887 Vitor Sessak
        if(!name)
225 22260824 Vitor Sessak
            return -1;
226
227 7f9b3266 Stefano Sabatini
        /* First check if the label is not in the open_outputs list */
228
        match = extract_inout(name, open_outputs);
229 cf4f7d38 Vitor Sessak
230 b2ac16da Vitor Sessak
        if(match) {
231 64fbf5e2 Vitor Sessak
            av_free(name);
232 0de3407b Vitor Sessak
        } else {
233
            /* Not in the list, so add it as an input */
234 c880791f Vitor Sessak
            match = av_mallocz(sizeof(AVFilterInOut));
235
            match->name    = name;
236
            match->pad_idx = pad;
237 cf4f7d38 Vitor Sessak
        }
238 e97908ee Vitor Sessak
239 7f9b3266 Stefano Sabatini
        insert_inout(curr_inputs, match);
240 e97908ee Vitor Sessak
241 fd548e5b Stefano Sabatini
        *buf += strspn(*buf, WHITESPACES);
242 c9987633 Vitor Sessak
        pad++;
243 27afb09d Vitor Sessak
    }
244 cf4f7d38 Vitor Sessak
245 27afb09d Vitor Sessak
    return pad;
246
}
247
248 7f9b3266 Stefano Sabatini
static int parse_outputs(const char **buf, AVFilterInOut **curr_inputs,
249
                         AVFilterInOut **open_inputs,
250
                         AVFilterInOut **open_outputs, AVClass *log_ctx)
251 9710beaf Vitor Sessak
{
252 c9987633 Vitor Sessak
    int pad = 0;
253
254 487c0e67 Vitor Sessak
    while(**buf == '[') {
255 bd80b349 Vitor Sessak
        char *name = parse_link_name(buf, log_ctx);
256 c9987633 Vitor Sessak
        AVFilterInOut *match;
257
258 7f9b3266 Stefano Sabatini
        AVFilterInOut *input = *curr_inputs;
259
        *curr_inputs = (*curr_inputs)->next;
260 443c10ef Vitor Sessak
261 c9987633 Vitor Sessak
        if(!name)
262
            return -1;
263
264 7f9b3266 Stefano Sabatini
        /* First check if the label is not in the open_inputs list */
265
        match = extract_inout(name, open_inputs);
266 c9987633 Vitor Sessak
267 0de3407b Vitor Sessak
        if(match) {
268 7baa6210 Vitor Sessak
            if(link_filter(input->filter, input->pad_idx,
269 c9987633 Vitor Sessak
                           match->filter, match->pad_idx, log_ctx) < 0)
270
                return -1;
271 64b164f4 Vitor Sessak
            av_free(match->name);
272
            av_free(name);
273 c9987633 Vitor Sessak
            av_free(match);
274 7baa6210 Vitor Sessak
            av_free(input);
275 0de3407b Vitor Sessak
        } else {
276 7f9b3266 Stefano Sabatini
            /* Not in the list, so add the first input as a open_output */
277 7baa6210 Vitor Sessak
            input->name = name;
278 7f9b3266 Stefano Sabatini
            insert_inout(open_outputs, input);
279 c9987633 Vitor Sessak
        }
280 fd548e5b Stefano Sabatini
        *buf += strspn(*buf, WHITESPACES);
281 c9987633 Vitor Sessak
        pad++;
282 8095a014 Vitor Sessak
    }
283 9710beaf Vitor Sessak
284 c9987633 Vitor Sessak
    return pad;
285
}
286 9710beaf Vitor Sessak
287 86a47378 Stefano Sabatini
int avfilter_graph_parse(AVFilterGraph *graph, const char *filters,
288 7f9b3266 Stefano Sabatini
                         AVFilterInOut *open_inputs,
289
                         AVFilterInOut *open_outputs, AVClass *log_ctx)
290 27afb09d Vitor Sessak
{
291
    int index = 0;
292
    char chr = 0;
293
294 7f9b3266 Stefano Sabatini
    AVFilterInOut *curr_inputs = NULL;
295 27afb09d Vitor Sessak
296
    do {
297 9710beaf Vitor Sessak
        AVFilterContext *filter;
298 fd548e5b Stefano Sabatini
        filters += strspn(filters, WHITESPACES);
299 27afb09d Vitor Sessak
300 7f9b3266 Stefano Sabatini
        if(parse_inputs(&filters, &curr_inputs, &open_outputs, log_ctx) < 0)
301 27afb09d Vitor Sessak
            goto fail;
302
303 5e600185 Vitor Sessak
        filter = parse_filter(&filters, graph, index, log_ctx);
304
305
        if(!filter)
306 22260824 Vitor Sessak
            goto fail;
307
308 7f9b3266 Stefano Sabatini
        if(filter->input_count == 1 && !curr_inputs && !index) {
309 e916c2ac Stefano Sabatini
            /* First input can be omitted if it is "[in]" */
310 c9987633 Vitor Sessak
            const char *tmp = "[in]";
311 7f9b3266 Stefano Sabatini
            if(parse_inputs(&tmp, &curr_inputs, &open_outputs, log_ctx) < 0)
312 27afb09d Vitor Sessak
                goto fail;
313
        }
314
315 7f9b3266 Stefano Sabatini
        if(link_filter_inouts(filter, &curr_inputs, &open_inputs, log_ctx) < 0)
316 c9987633 Vitor Sessak
            goto fail;
317 da790674 Vitor Sessak
318 7f9b3266 Stefano Sabatini
        if(parse_outputs(&filters, &curr_inputs, &open_inputs, &open_outputs,
319 e2b5fdaf Vitor Sessak
                         log_ctx) < 0)
320 e84f0b62 Vitor Sessak
            goto fail;
321
322 fd548e5b Stefano Sabatini
        filters += strspn(filters, WHITESPACES);
323 27afb09d Vitor Sessak
        chr = *filters++;
324
325 7f9b3266 Stefano Sabatini
        if(chr == ';' && curr_inputs) {
326 c9987633 Vitor Sessak
            av_log(log_ctx, AV_LOG_ERROR,
327
                   "Could not find a output to link when parsing \"%s\"\n",
328
                   filters - 1);
329
            goto fail;
330 27afb09d Vitor Sessak
        }
331 c9987633 Vitor Sessak
        index++;
332 487c0e67 Vitor Sessak
    } while(chr == ',' || chr == ';');
333 27afb09d Vitor Sessak
334 fd51ff16 Stefano Sabatini
    if (chr) {
335 78471234 Stefano Sabatini
        av_log(log_ctx, AV_LOG_ERROR,
336
               "Unable to parse graph description substring: \"%s\"\n",
337
               filters - 1);
338
        goto fail;
339
    }
340
341 7f9b3266 Stefano Sabatini
    if(open_inputs && !strcmp(open_inputs->name, "out") && curr_inputs) {
342 e916c2ac Stefano Sabatini
        /* Last output can be omitted if it is "[out]" */
343 c9987633 Vitor Sessak
        const char *tmp = "[out]";
344 7f9b3266 Stefano Sabatini
        if(parse_outputs(&tmp, &curr_inputs, &open_inputs,
345
                         &open_outputs, log_ctx) < 0)
346 27afb09d Vitor Sessak
            goto fail;
347
    }
348
349
    return 0;
350
351
 fail:
352 d7dbe558 Stefano Sabatini
    avfilter_graph_destroy(graph);
353 7f9b3266 Stefano Sabatini
    free_inout(open_inputs);
354
    free_inout(open_outputs);
355
    free_inout(curr_inputs);
356 27afb09d Vitor Sessak
    return -1;
357
}