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
184184 {
185185 AVFilterInOut *ret;
186186
187− while (*links && strcmp((*links)->name, label))
187+ while (*links && (!(*links)->name || strcmp((*links)->name, label)))
188188 links = &((*links)->next);
189189
190190 ret = *links;
191191
192− if (ret)
192+ if (ret) {
193193 *links = ret->next;
194+ ret->next = NULL;
195+ }
194196
195197 return ret;
196198 }
@@ -201,6 +203,18 @@ static void insert_inout(AVFilterInOut **inouts, AVFilterInOut *element) · 4 unmodified lines
201203 *inouts = element;
202204 }
203205
206+static 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+
204218 static int link_filter_inouts(AVFilterContext *filt_ctx,
205219 AVFilterInOut **curr_inputs,
206220 AVFilterInOut **open_inputs, void *log_ctx)
@@ -209,14 +223,11 @@ static int link_filter_inouts(AVFilterContext *filt_ctx, · 2 unmodified lines
209223
210224 while (pad--) {
211225 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− }
218226
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);
220231
221232 if (p->filter_ctx) {
222233 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
329340 return pad;
330341 }
331342
332−int avfilter_graph_parse(AVFilterGraph *graph, const char *filters,
333− AVFilterInOut *open_inputs,
334− AVFilterInOut *open_outputs, void *log_ctx)
343+#if FF_API_GRAPH_AVCLASS
344+#define log_ctx graph
345+#else
346+#define log_ctx NULL
347+#endif
348+int avfilter_graph_parse2(AVFilterGraph *graph, const char *filters,
349+ AVFilterInOut **inputs,
350+ AVFilterInOut **outputs)
335351 {
336352 int index = 0, ret;
337353 char chr = 0;
338354
339− AVFilterInOut *curr_inputs = NULL;
355+ AVFilterInOut *curr_inputs = NULL, *open_inputs = NULL, *open_outputs = NULL;
340356
341357 do {
342358 AVFilterContext *filter;
343− const char *filterchain = filters;
344359 filters += strspn(filters, WHITESPACES);
345360
346361 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
349364 if ((ret = parse_filter(&filter, &filters, graph, index, log_ctx)) < 0)
350365 goto fail;
351366
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− }
358367
359368 if ((ret = link_filter_inouts(filter, &curr_inputs, &open_inputs, log_ctx)) < 0)
360369 goto fail;
@@ -366,13 +375,8 @@ int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, · 5 unmodified lines
366375 filters += strspn(filters, WHITESPACES);
367376 chr = *filters++;
368377
369− if (chr == ';' && curr_inputs) {
370− av_log(log_ctx, AV_LOG_ERROR,
371− "Invalid filterchain containing an unlabelled output pad: \"%s\"\n",
372− filterchain);
373− ret = AVERROR(EINVAL);
374− goto fail;
375− }
378+ if (chr == ';' && curr_inputs)
379+ append_inout(&open_outputs, &curr_inputs);
376380 index++;
377381 } while (chr == ',' || chr == ';');
378382
@@ -384,14 +388,10 @@ int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, · 5 unmodified lines
384388 goto fail;
385389 }
386390
387− if (open_inputs && !strcmp(open_inputs->name, "out") && 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− }
391+ append_inout(&open_outputs, &curr_inputs);
394392
393+ *inputs = open_inputs;
394+ *outputs = open_outputs;
395395 return 0;
396396
397397 fail:
@@ -401,5 +401,73 @@ int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, · 3 unmodified lines
401401 free_inout(open_inputs);
402402 free_inout(open_outputs);
403403 free_inout(curr_inputs);
404+
405+ *inputs = NULL;
406+ *outputs = NULL;
407+
408+ return ret;
409+}
410+#undef log_ctx
411+
412+int 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);
404472 return ret;
405473 }

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