History

graphparser: add avfilter_graph_parse2().

Unlike avfilter_graph_parse(), it returns unlinked inputs and outputs to the caller, which allows parsing of graphs where inputs/outputs are not known in advance.

Anton Khirnov committed 14 years ago

Commit d7bcc711 parent 7ae7c412 files · +141 −39Browse files

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

Unified · Split

libavfilter/graphparser.c+102−34
@@ -184,13 +184,15 @@ static AVFilterInOut *extract_inout(const char *label, AVFilterInOut **links) · 183 unmodified lines
184{184{
185 AVFilterInOut *ret;185 AVFilterInOut *ret;
186 186
187 while (*links && strcmp((*links)->name, label))187 while (*links && (!(*links)->name || strcmp((*links)->name, label)))
188 links = &((*links)->next);188 links = &((*links)->next);
189 189
190 ret = *links;190 ret = *links;
191 191
192 if (ret)192 if (ret) {
193 *links = ret->next;193 *links = ret->next;
194 ret->next = NULL;
195 }
194 196
195 return ret;197 return ret;
196}198}
@@ -201,6 +203,18 @@ static void insert_inout(AVFilterInOut **inouts, AVFilterInOut *element) · 4 unmodified lines
201 *inouts = element;203 *inouts = element;
202}204}
203 205
206static void append_inout(AVFilterInOut **inouts, AVFilterInOut **element)
207{
208 while (*inouts && (*inouts)->next)
209 inouts = &((*inouts)->next);
210
211 if (!*inouts)
212 *inouts = *element;
213 else
214 (*inouts)->next = *element;
215 *element = NULL;
216}
217
204static int link_filter_inouts(AVFilterContext *filt_ctx,218static int link_filter_inouts(AVFilterContext *filt_ctx,
205 AVFilterInOut **curr_inputs,219 AVFilterInOut **curr_inputs,
206 AVFilterInOut **open_inputs, void *log_ctx)220 AVFilterInOut **open_inputs, void *log_ctx)
@@ -209,14 +223,11 @@ static int link_filter_inouts(AVFilterContext *filt_ctx, · 2 unmodified lines
209 223
210 while (pad--) {224 while (pad--) {
211 AVFilterInOut *p = *curr_inputs;225 AVFilterInOut *p = *curr_inputs;
212 if (!p) {
213 av_log(log_ctx, AV_LOG_ERROR,
214 "Not enough inputs specified for the \"%s\" filter.\n",
215 filt_ctx->filter->name);
216 return AVERROR(EINVAL);
217 }
218 226
219 *curr_inputs = (*curr_inputs)->next;227 if (p)
228 *curr_inputs = (*curr_inputs)->next;
229 else if (!(p = av_mallocz(sizeof(*p))))
230 return AVERROR(ENOMEM);
220 231
221 if (p->filter_ctx) {232 if (p->filter_ctx) {
222 if ((ret = link_filter(p->filter_ctx, p->pad_idx, filt_ctx, pad, log_ctx)) < 0)233 if ((ret = link_filter(p->filter_ctx, p->pad_idx, filt_ctx, pad, log_ctx)) < 0)
@@ -329,18 +340,22 @@ static int parse_outputs(const char **buf, AVFilterInOut **curr_inputs, · 106 unmodified lines
329 return pad;340 return pad;
330}341}
331 342
332int avfilter_graph_parse(AVFilterGraph *graph, const char *filters,343#if FF_API_GRAPH_AVCLASS
333 AVFilterInOut *open_inputs,344#define log_ctx graph
334 AVFilterInOut *open_outputs, void *log_ctx)345#else
346#define log_ctx NULL
347#endif
348int avfilter_graph_parse2(AVFilterGraph *graph, const char *filters,
349 AVFilterInOut **inputs,
350 AVFilterInOut **outputs)
335{351{
336 int index = 0, ret;352 int index = 0, ret;
337 char chr = 0;353 char chr = 0;
338 354
339 AVFilterInOut *curr_inputs = NULL;355 AVFilterInOut *curr_inputs = NULL, *open_inputs = NULL, *open_outputs = NULL;
340 356
341 do {357 do {
342 AVFilterContext *filter;358 AVFilterContext *filter;
343 const char *filterchain = filters;
344 filters += strspn(filters, WHITESPACES);359 filters += strspn(filters, WHITESPACES);
345 360
346 if ((ret = parse_inputs(&filters, &curr_inputs, &open_outputs, log_ctx)) < 0)361 if ((ret = parse_inputs(&filters, &curr_inputs, &open_outputs, log_ctx)) < 0)
@@ -349,12 +364,6 @@ int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, · 2 unmodified lines
349 if ((ret = parse_filter(&filter, &filters, graph, index, log_ctx)) < 0)364 if ((ret = parse_filter(&filter, &filters, graph, index, log_ctx)) < 0)
350 goto fail;365 goto fail;
351 366
352 if (filter->input_count == 1 && !curr_inputs && !index) {
353 /* First input can be omitted if it is "[in]" */
354 const char *tmp = "[in]";
355 if ((ret = parse_inputs(&tmp, &curr_inputs, &open_outputs, log_ctx)) < 0)
356 goto fail;
357 }
358 367
359 if ((ret = link_filter_inouts(filter, &curr_inputs, &open_inputs, log_ctx)) < 0)368 if ((ret = link_filter_inouts(filter, &curr_inputs, &open_inputs, log_ctx)) < 0)
360 goto fail;369 goto fail;
@@ -366,13 +375,8 @@ int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, · 5 unmodified lines
366 filters += strspn(filters, WHITESPACES);375 filters += strspn(filters, WHITESPACES);
367 chr = *filters++;376 chr = *filters++;
368 377
369 if (chr == ';' && curr_inputs) {378 if (chr == ';' && curr_inputs)
370 av_log(log_ctx, AV_LOG_ERROR,379 append_inout(&open_outputs, &curr_inputs);
371 "Invalid filterchain containing an unlabelled output pad: \"%s\"\n",
372 filterchain);
373 ret = AVERROR(EINVAL);
374 goto fail;
375 }
376 index++;380 index++;
377 } while (chr == ',' || chr == ';');381 } while (chr == ',' || chr == ';');
378 382
@@ -384,14 +388,10 @@ int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, · 5 unmodified lines
384 goto fail;388 goto fail;
385 }389 }
386 390
387 if (open_inputs && !strcmp(open_inputs->name, "out") && curr_inputs) {391 append_inout(&open_outputs, &curr_inputs);
388 /* Last output can be omitted if it is "[out]" */
389 const char *tmp = "[out]";
390 if ((ret = parse_outputs(&tmp, &curr_inputs, &open_inputs, &open_outputs,
391 log_ctx)) < 0)
392 goto fail;
393 }
394 392
393 *inputs = open_inputs;
394 *outputs = open_outputs;
395 return 0;395 return 0;
396 396
397 fail:397 fail:
@@ -401,5 +401,73 @@ int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, · 3 unmodified lines
401 free_inout(open_inputs);401 free_inout(open_inputs);
402 free_inout(open_outputs);402 free_inout(open_outputs);
403 free_inout(curr_inputs);403 free_inout(curr_inputs);
404
405 *inputs = NULL;
406 *outputs = NULL;
407
408 return ret;
409}
410#undef log_ctx
411
412int avfilter_graph_parse(AVFilterGraph *graph, const char *filters,
413 AVFilterInOut *open_inputs,
414 AVFilterInOut *open_outputs, void *log_ctx)
415{
416 int ret;
417 AVFilterInOut *cur, *match, *inputs = NULL, *outputs = NULL;
418
419 if ((ret = avfilter_graph_parse2(graph, filters, &inputs, &outputs)) < 0)
420 goto fail;
421
422 /* First input can be omitted if it is "[in]" */
423 if (inputs && !inputs->name)
424 inputs->name = av_strdup("in");
425 for (cur = inputs; cur; cur = cur->next) {
426 if (!cur->name) {
427 av_log(log_ctx, AV_LOG_ERROR,
428 "Not enough inputs specified for the \"%s\" filter.\n",
429 cur->filter_ctx->filter->name);
430 ret = AVERROR(EINVAL);
431 goto fail;
432 }
433 if (!(match = extract_inout(cur->name, &open_outputs)))
434 continue;
435 ret = avfilter_link(match->filter_ctx, match->pad_idx,
436 cur->filter_ctx, cur->pad_idx);
437 free_inout(match);
438 if (ret < 0)
439 goto fail;
440 }
441
442 /* Last output can be omitted if it is "[out]" */
443 if (outputs && !outputs->name)
444 outputs->name = av_strdup("out");
445 for (cur = outputs; cur; cur = cur->next) {
446 if (!cur->name) {
447 av_log(log_ctx, AV_LOG_ERROR,
448 "Invalid filterchain containing an unlabelled output pad: \"%s\"\n",
449 filters);
450 ret = AVERROR(EINVAL);
451 goto fail;
452 }
453 if (!(match = extract_inout(cur->name, &open_inputs)))
454 continue;
455 ret = avfilter_link(cur->filter_ctx, cur->pad_idx,
456 match->filter_ctx, match->pad_idx);
457 free_inout(match);
458 if (ret < 0)
459 goto fail;
460 }
461
462 fail:
463 if (ret < 0) {
464 for (; graph->filter_count > 0; graph->filter_count--)
465 avfilter_free(graph->filters[graph->filter_count - 1]);
466 av_freep(&graph->filters);
467 }
468 free_inout(inputs);
469 free_inout(outputs);
470 free_inout(open_inputs);
471 free_inout(open_outputs);
404 return ret;472 return ret;
405}473}

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