History

I should not have merged the graph parser with the graph framework. Split it.

Commited in SoC by Vitor Sessak on 2008-04-03 16:29:07 Originally committed as revision 12746 to svn://svn.ffmpeg.org/ffmpeg/trunk

Vitor Sessak committed 18 years ago

Commit d2027ba1 parent 966b8f22 files · +8 −370Browse files

Showing the changes to libavfilter/avfiltergraph.c (1 of 2 files). Show all

Unified · Split

libavfilter/avfiltergraph.c+6−361
@@ -26,21 +26,6 @@ · 25 unmodified lines
26#include "avfilter.h"26#include "avfilter.h"
27#include "avfiltergraph.h"27#include "avfiltergraph.h"
28 28
29/**
30 * For use in av_log
31 */
32static const char *log_name(void *p)
33{
34 return "Filter parser";
35}
36
37static const AVClass filter_parser_class = {
38 "Filter parser",
39 log_name
40};
41
42static const AVClass *log_ctx = &filter_parser_class;
43
44void avfilter_destroy_graph(AVFilterGraph *graph)29void avfilter_destroy_graph(AVFilterGraph *graph)
45{30{
46 for(; graph->filter_count > 0; graph->filter_count --)31 for(; graph->filter_count > 0; graph->filter_count --)
@@ -48,7 +33,9 @@ void avfilter_destroy_graph(AVFilterGraph *graph) · 1 unmodified line
48 av_freep(&graph->filters);33 av_freep(&graph->filters);
49}34}
50 35
51/* TODO: insert in sorted order */36/**
37 * @todo insert in sorted order
38 */
52void avfilter_graph_add_filter(AVFilterGraph *graph, AVFilterContext *filter)39void avfilter_graph_add_filter(AVFilterGraph *graph, AVFilterContext *filter)
53{40{
54 graph->filters = av_realloc(graph->filters,41 graph->filters = av_realloc(graph->filters,
@@ -56,7 +43,9 @@ void avfilter_graph_add_filter(AVFilterGraph *graph, AVFilterContext *filter) · 1 unmodified line
56 graph->filters[graph->filter_count - 1] = filter;43 graph->filters[graph->filter_count - 1] = filter;
57}44}
58 45
59/* search intelligently, once we insert in order */46/*
47 * @todo search intelligently, once we insert in order
48 */
60AVFilterContext *avfilter_graph_get_filter(AVFilterGraph *graph, char *name)49AVFilterContext *avfilter_graph_get_filter(AVFilterGraph *graph, char *name)
61{50{
62 int i;51 int i;
@@ -160,347 +149,3 @@ int avfilter_graph_config_formats(AVFilterGraph *graph) · 97 unmodified lines
160 return 0;149 return 0;
161}150}
162 151
163static int create_filter(AVFilterGraph *ctx, int index, char *name,
164 char *args)
165{
166 AVFilterContext *filt;
167
168 AVFilter *filterdef;
169 char tmp[20];
170
171 snprintf(tmp, 20, "%d", index);
172 if(!(filterdef = avfilter_get_by_name(name)) ||
173 !(filt = avfilter_open(filterdef, tmp))) {
174 av_log(&log_ctx, AV_LOG_ERROR,
175 "error creating filter '%s'\n", name);
176 return -1;
177 }
178 avfilter_graph_add_filter(ctx, filt);
179 if(avfilter_init_filter(filt, args, NULL)) {
180 av_log(&log_ctx, AV_LOG_ERROR,
181 "error initializing filter '%s'\n", name);
182 return -1;
183 }
184
185 return 0;
186}
187
188static int link_filter(AVFilterGraph *ctx, int src, int srcpad,
189 int dst, int dstpad)
190{
191 AVFilterContext *filt, *filtb;
192
193 char tmp[20];
194
195 snprintf(tmp, 20, "%d", src);
196 if(!(filt = avfilter_graph_get_filter(ctx, tmp))) {
197 av_log(&log_ctx, AV_LOG_ERROR, "link source does not exist in graph\n");
198 return -1;
199 }
200 snprintf(tmp, 20, "%d", dst);
201 if(!(filtb = avfilter_graph_get_filter(ctx, tmp))) {
202 av_log(&log_ctx, AV_LOG_ERROR, "link destination does not exist in graph\n");
203 return -1;
204 }
205 if(avfilter_link(filt, srcpad, filtb, dstpad)) {
206 av_log(&log_ctx, AV_LOG_ERROR, "cannot create link between source and destination filters\n");
207 return -1;
208 }
209
210 return 0;
211}
212
213static void consume_whitespace(const char **buf)
214{
215 *buf += strspn(*buf, " \n\t");
216}
217
218/**
219 * Copy the first size bytes of input string to a null-terminated string,
220 * removing any control character. Ex: "aaa'bb'c\'c\\" -> "aaabbc'c\"
221 */
222static void copy_unquoted(char *out, const char *in, int size)
223{
224 int i;
225 for (i=0; i < size; i++) {
226 if (in[i] == '\'')
227 continue;
228 else if (in[i] == '\\') {
229 if (i+1 == size) {
230 *out = 0;
231 return;
232 }
233 i++;
234 }
235 *out++ = in[i];
236 }
237 *out=0;
238}
239
240/**
241 * Consumes a string from *buf.
242 * @return a copy of the consumed string, which should be free'd after use
243 */
244static char *consume_string(const char **buf)
245{
246 const char *start;
247 char *ret;
248 int size;
249
250 consume_whitespace(buf);
251
252 if (!(**buf))
253 return av_mallocz(1);
254
255 start = *buf;
256
257 while(1) {
258 *buf += strcspn(*buf, " ()=,'\\");
259 if (**buf == '\\')
260 *buf+=2;
261 else
262 break;
263 }
264
265 if (**buf == '\'') {
266 const char *p = *buf;
267 do {
268 p++;
269 p = strchr(p, '\'');
270 } while (p && p[-1] == '\\');
271 if (p)
272 *buf = p + 1;
273 else
274 *buf += strlen(*buf); // Move the pointer to the null end byte
275 }
276
277 size = *buf - start + 1;
278 ret = av_malloc(size);
279 copy_unquoted(ret, start, size-1);
280
281 return ret;
282}
283
284/**
285 * Parse "(linkname)"
286 * @arg name a pointer (that need to be free'd after use) to the name between
287 * parenthesis
288 */
289static void parse_link_name(const char **buf, char **name)
290{
291 (*buf)++;
292
293 *name = consume_string(buf);
294
295 if (!*name[0])
296 goto fail;
297
298 if (*(*buf)++ != ')')
299 goto fail;
300
301 return;
302 fail:
303 av_freep(name);
304 av_log(&log_ctx, AV_LOG_ERROR, "Could not parse link name!\n");
305}
306
307/**
308 * Parse "filter=params"
309 * @arg name a pointer (that need to be free'd after use) to the name of the
310 * filter
311 * @arg ars a pointer (that need to be free'd after use) to the args of the
312 * filter
313 */
314static int parse_filter(const char **buf, AVFilterGraph *graph, int index)
315{
316 char *name, *opts;
317 name = consume_string(buf);
318
319 if (**buf == '=') {
320 (*buf)++;
321 opts = consume_string(buf);
322 } else {
323 opts = NULL;
324 }
325
326 return create_filter(graph, index, name, opts);
327}
328
329enum LinkType {
330 LinkTypeIn,
331 LinkTypeOut,
332};
333
334/**
335 * A linked-list of the inputs/outputs of the filter chain.
336 */
337typedef struct AVFilterInOut {
338 enum LinkType type;
339 char *name;
340 int instance;
341 int pad_idx;
342
343 struct AVFilterInOut *next;
344} AVFilterInOut;
345
346static void free_inout(AVFilterInOut *head)
347{
348 while (head) {
349 AVFilterInOut *next;
350 next = head->next;
351 av_free(head);
352 head = next;
353 }
354}
355
356/**
357 * Parse "(a1)(link2) ... (etc)"
358 */
359static int parse_inouts(const char **buf, AVFilterInOut **inout, int firstpad,
360 enum LinkType type, int instance)
361{
362 int pad = firstpad;
363 while (**buf == '(') {
364 AVFilterInOut *inoutn = av_malloc(sizeof(AVFilterInOut));
365 parse_link_name(buf, &inoutn->name);
366 inoutn->type = type;
367 inoutn->instance = instance;
368 inoutn->pad_idx = pad++;
369 inoutn->next = *inout;
370 *inout = inoutn;
371 }
372 return pad;
373}
374
375/**
376 * Parse a string describing a filter graph.
377 */
378int avfilter_graph_parse_chain(AVFilterGraph *graph, const char *filters, AVFilterContext *in, int inpad, AVFilterContext *out, int outpad)
379{
380 AVFilterInOut *inout=NULL;
381 AVFilterInOut *head=NULL;
382
383 int index = 0;
384 char chr = 0;
385 int pad = 0;
386 int has_out = 0;
387
388 char tmp[20];
389 AVFilterContext *filt;
390
391 consume_whitespace(&filters);
392
393 do {
394 int oldpad = pad;
395
396 pad = parse_inouts(&filters, &inout, chr == ',', LinkTypeIn, index);
397
398 if (parse_filter(&filters, graph, index) < 0)
399 goto fail;
400
401 // If the first filter has an input and none was given, it is
402 // implicitly the input of the whole graph.
403 if (pad == 0 && graph->filters[graph->filter_count-1]->input_count == 1) {
404 snprintf(tmp, 20, "%d", index);
405 if(!(filt = avfilter_graph_get_filter(graph, tmp))) {
406 av_log(&log_ctx, AV_LOG_ERROR, "filter owning exported pad does not exist\n");
407 goto fail;
408 }
409 if(avfilter_link(in, inpad, filt, 0)) {
410 av_log(&log_ctx, AV_LOG_ERROR, "cannot create link between source and destination filters\n");
411 goto fail;
412 }
413 }
414
415 if(chr == ',') {
416 if (link_filter(graph, index-1, oldpad, index, 0) < 0)
417 goto fail;
418
419 }
420 pad = parse_inouts(&filters, &inout, 0, LinkTypeOut, index);
421 chr = *filters++;
422 index++;
423 } while (chr == ',' || chr == ';');
424
425 head = inout;
426 for (; inout != NULL; inout = inout->next) {
427 if (inout->instance == -1)
428 continue; // Already processed
429
430 if (!strcmp(inout->name, "in")) {
431 snprintf(tmp, 20, "%d", inout->instance);
432 if(!(filt = avfilter_graph_get_filter(graph, tmp))) {
433 av_log(&log_ctx, AV_LOG_ERROR, "filter owning exported pad does not exist\n");
434 goto fail;
435 }
436 if(avfilter_link(in, inpad, filt, inout->pad_idx)) {
437 av_log(&log_ctx, AV_LOG_ERROR, "cannot create link between source and destination filters\n");
438 goto fail;
439 }
440 } else if (!strcmp(inout->name, "out")) {
441 has_out = 1;
442 snprintf(tmp, 20, "%d", inout->instance);
443 if(!(filt = avfilter_graph_get_filter(graph, tmp))) {
444 av_log(&log_ctx, AV_LOG_ERROR, "filter owning exported pad does not exist\n");
445 goto fail;
446 }
447
448 if(avfilter_link(filt, inout->pad_idx, out, outpad)) {
449 av_log(&log_ctx, AV_LOG_ERROR, "cannot create link between source and destination filters\n");
450 goto fail;
451 }
452
453 } else {
454 AVFilterInOut *p, *src, *dst;
455 for (p = inout->next;
456 p && strcmp(p->name,inout->name); p = p->next);
457
458 if (!p) {
459 av_log(&log_ctx, AV_LOG_ERROR, "Unmatched link: %s.\n",
460 inout->name);
461 goto fail;
462 }
463
464 if (p->type == LinkTypeIn && inout->type == LinkTypeOut) {
465 src = inout;
466 dst = p;
467 } else if (p->type == LinkTypeOut && inout->type == LinkTypeIn) {
468 src = p;
469 dst = inout;
470 } else {
471 av_log(&log_ctx, AV_LOG_ERROR, "Two links named '%s' are either both input or both output\n",
472 inout->name);
473 goto fail;
474 }
475
476 if (link_filter(graph, src->instance, src->pad_idx, dst->instance, dst->pad_idx) < 0)
477 goto fail;
478
479 src->instance = -1;
480 dst->instance = -1;
481 }
482 }
483
484 free_inout(head);
485
486 if (!has_out) {
487 snprintf(tmp, 20, "%d", index-1);
488 if(!(filt = avfilter_graph_get_filter(graph, tmp))) {
489 av_log(&log_ctx, AV_LOG_ERROR, "filter owning exported pad does not exist\n");
490 goto fail;
491 }
492
493 if(avfilter_link(filt, pad, out, outpad)) {
494 av_log(&log_ctx, AV_LOG_ERROR, "cannot create link between source and destination filters\n");
495 goto fail;
496 }
497
498 }
499
500 return 0;
501
502 fail:
503 free_inout(head);
504 avfilter_destroy_graph(graph);
505 return -1;
506}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t