History

Merge avfiltergraphdesc.c in avfiltergraph.c Commited in SoC by Vitor Sessak on 2008-03-24 20:46:50

Originally committed as revision 12735 to svn://svn.ffmpeg.org/ffmpeg/trunk

Vitor Sessak committed 18 years ago

Commit 5c2ff9f1 parent f2ee8081 file · +338 −0Browse files

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

Unified · Split

libavfilter/avfiltergraph.c+338−0
@@ -1,5 +1,6 @@
11 /*
22 * filter graphs
3+ * copyright (c) 2008 Vitor Sessak
34 * copyright (c) 2007 Bobby Bingham
45 *
56 * This file is part of FFmpeg.
@@ -19,6 +20,9 @@ · 13 unmodified lines
1920 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2021 */
2122
23+#include <ctype.h>
24+#include <string.h>
25+
2226 #include "avfilter.h"
2327 #include "avfiltergraph.h"
2428
@@ -249,3 +253,337 @@ fail: · 224 unmodified lines
249253 uninit(graph);
250254 return -1;
251255 }
256+
257+
258+static void consume_whitespace(const char **buf)
259+{
260+ *buf += strspn(*buf, " \n\t");
261+}
262+
263+/**
264+ * get the next non-whitespace char
265+ */
266+static char consume_char(const char **buf)
267+{
268+ char out;
269+ consume_whitespace(buf);
270+
271+ out = **buf;
272+
273+ if (out)
274+ (*buf)++;
275+
276+ return out;
277+}
278+
279+/**
280+ * remove the quotation marks from a string. Ex: "aaa'bb'cc" -> "aaabbcc"
281+ */
282+static void unquote(char *str)
283+{
284+ char *p1, *p2;
285+ p1=p2=str;
286+ while (*p1 != 0) {
287+ if (*p1 != '\'')
288+ *p2++ = *p1;
289+ p1++;
290+ }
291+
292+ *p2 = 0;
293+}
294+
295+/**
296+ * Consumes a string from *buf.
297+ * @return a copy of the consumed string, which should be free'd after use
298+ */
299+static char *consume_string(const char **buf)
300+{
301+ const char *start;
302+ char *ret;
303+ int size;
304+
305+ consume_whitespace(buf);
306+
307+ if (!(**buf))
308+ return av_mallocz(1);
309+
310+ start = *buf;
311+
312+ *buf += strcspn(*buf, " ()=,'");
313+
314+ if (**buf == '\'') {
315+ char *p = strchr(*buf + 1, '\'');
316+ if (p)
317+ *buf = p + 1;
318+ else
319+ *buf += strlen(*buf); // Move the pointer to the null end byte
320+ }
321+
322+ size = *buf - start + 1;
323+ ret = av_malloc(size);
324+ memcpy(ret, start, size - 1);
325+ ret[size-1] = 0;
326+
327+ unquote(ret);
328+
329+ return ret;
330+}
331+
332+/**
333+ * Parse "(linkname)"
334+ * @arg name a pointer (that need to be free'd after use) to the name between
335+ * parenthesis
336+ */
337+static void parse_link_name(const char **buf, char **name)
338+{
339+ consume_char(buf);
340+
341+ *name = consume_string(buf);
342+
343+ if (!*name[0])
344+ goto fail;
345+
346+ if (consume_char(buf) != ')')
347+ goto fail;
348+
349+ return;
350+ fail:
351+ av_freep(name);
352+ av_log(&log_ctx, AV_LOG_ERROR, "Could not parse link name!\n");
353+}
354+
355+/**
356+ * Parse "filter=params"
357+ * @arg name a pointer (that need to be free'd after use) to the name of the
358+ * filter
359+ * @arg ars a pointer (that need to be free'd after use) to the args of the
360+ * filter
361+ */
362+static void parse_filter(const char **buf, char **name, char **opts)
363+{
364+ *name = consume_string(buf);
365+
366+ if (**buf == '=') {
367+ consume_char(buf);
368+ *opts = consume_string(buf);
369+ } else {
370+ *opts = NULL;
371+ }
372+
373+}
374+
375+enum LinkType {
376+ LinkTypeIn,
377+ LinkTypeOut,
378+};
379+
380+/**
381+ * A linked-list of the inputs/outputs of the filter chain.
382+ */
383+typedef struct AVFilterInOut {
384+ enum LinkType type;
385+ char *name;
386+ int instance;
387+ int pad_idx;
388+
389+ struct AVFilterInOut *next;
390+} AVFilterInOut;
391+
392+static void free_inout(AVFilterInOut *head)
393+{
394+ while (head) {
395+ AVFilterInOut *next;
396+ next = head->next;
397+ av_free(head);
398+ head = next;
399+ }
400+}
401+
402+/**
403+ * Parse "(a1)(link2) ... (etc)"
404+ */
405+static int parse_inouts(const char **buf, AVFilterInOut **inout, int firstpad,
406+ enum LinkType type, int instance)
407+{
408+ int pad = firstpad;
409+ while (**buf == '(') {
410+ AVFilterInOut *inoutn = av_malloc(sizeof(AVFilterInOut));
411+ parse_link_name(buf, &inoutn->name);
412+ inoutn->type = type;
413+ inoutn->instance = instance;
414+ inoutn->pad_idx = pad++;
415+ inoutn->next = *inout;
416+ *inout = inoutn;
417+ }
418+ return pad;
419+}
420+
421+static AVFilterGraphDesc *parse_chain(const char *filters, int has_in)
422+{
423+ AVFilterGraphDesc *ret;
424+ AVFilterGraphDescFilter **filterp, *filtern;
425+ AVFilterGraphDescLink **linkp, *linkn;
426+ AVFilterInOut *inout=NULL;
427+ AVFilterInOut *head;
428+
429+ int index = 0;
430+ char chr = 0;
431+ int pad = 0;
432+ int has_out = 0;
433+
434+ consume_whitespace(&filters);
435+
436+ if(!(ret = av_mallocz(sizeof(AVFilterGraphDesc))))
437+ return NULL;
438+
439+ filterp = &ret->filters;
440+ linkp = &ret->links;
441+
442+ do {
443+ if(chr == ',') {
444+ linkn = av_mallocz(sizeof(AVFilterGraphDescLink));
445+ linkn->src = index-1;
446+ linkn->srcpad = pad;
447+ linkn->dst = index;
448+ linkn->dstpad = 0;
449+
450+ *linkp = linkn;
451+ linkp = &linkn->next;
452+ }
453+ pad = parse_inouts(&filters, &inout, chr == ',' || (!has_in),
454+ LinkTypeIn, index);
455+
456+ filtern = av_mallocz(sizeof(AVFilterGraphDescFilter));
457+ filtern->index = index;
458+ parse_filter(&filters, &filtern->filter, &filtern->args);
459+ *filterp = filtern;
460+ filterp = &filtern->next;
461+
462+ pad = parse_inouts(&filters, &inout, 0,
463+ LinkTypeOut, index);
464+ chr = consume_char(&filters);
465+ index++;
466+ } while (chr == ',' || chr == ';');
467+
468+ head = inout;
469+ for (; inout != NULL; inout = inout->next) {
470+ if (inout->instance == -1)
471+ continue; // Already processed
472+
473+ if (!strcmp(inout->name, "in")) {
474+ if (!has_in)
475+ goto fail;
476+ ret->inputs = av_mallocz(sizeof(AVFilterGraphDescExport));
477+ ret->inputs->filter = inout->instance;
478+ ret->inputs->pad = inout->pad_idx;
479+ } else if (!strcmp(inout->name, "out")) {
480+ has_out = 1;
481+ ret->outputs = av_mallocz(sizeof(AVFilterGraphDescExport));
482+ ret->outputs->filter = inout->instance;
483+ ret->outputs->pad = inout->pad_idx;
484+ } else {
485+ AVFilterInOut *p, *src, *dst;
486+ for (p = inout->next;
487+ p && strcmp(p->name,inout->name); p = p->next);
488+
489+ if (!p) {
490+ av_log(&log_ctx, AV_LOG_ERROR, "Unmatched link: %s.\n",
491+ inout->name);
492+ goto fail;
493+ }
494+
495+ if (p->type == LinkTypeIn && inout->type == LinkTypeOut) {
496+ src = inout;
497+ dst = p;
498+ } else if (p->type == LinkTypeOut && inout->type == LinkTypeIn) {
499+ src = p;
500+ dst = inout;
501+ } else {
502+ av_log(&log_ctx, AV_LOG_ERROR, "Two links named '%s' are either both input or both output\n",
503+ inout->name);
504+ goto fail;
505+ }
506+ linkn = av_mallocz(sizeof(AVFilterGraphDescLink));
507+
508+ linkn->src = src->instance;
509+ linkn->srcpad = src->pad_idx;
510+ linkn->dst = dst->instance;
511+ linkn->dstpad = dst->pad_idx;
512+
513+ *linkp = linkn;
514+ linkp = &linkn->next;
515+
516+ src->instance = -1;
517+ dst->instance = -1;
518+ }
519+ }
520+
521+ free_inout(head);
522+
523+ if (!has_in) {
524+ ret->inputs = av_mallocz(sizeof(AVFilterGraphDescExport));
525+ ret->inputs->filter = 0;
526+ }
527+ if (!has_out) {
528+ ret->outputs = av_mallocz(sizeof(AVFilterGraphDescExport));
529+ ret->outputs->filter = index-1;
530+ }
531+
532+ return ret;
533+
534+ fail:
535+ free_inout(head);
536+
537+ avfilter_graph_free_desc(ret);
538+ return NULL;
539+}
540+
541+/**
542+ * Parse a string describing a filter graph.
543+ */
544+AVFilterGraphDesc *avfilter_graph_parse_chain(const char *filters)
545+{
546+ AVFilterGraphDesc *ret;
547+
548+ /* Try first to parse supposing there is no (in) element */
549+ if ((ret = parse_chain(filters, 0)))
550+ return ret;
551+
552+ /* Parse supposing there is an (in) element */
553+ return parse_chain(filters, 1);
554+}
555+
556+/**
557+ * Free a graph description.
558+ */
559+void avfilter_graph_free_desc(AVFilterGraphDesc *desc)
560+{
561+ void *next;
562+
563+ while(desc->filters) {
564+ next = desc->filters->next;
565+ av_free(desc->filters->filter);
566+ av_free(desc->filters->args);
567+ av_free(desc->filters);
568+ desc->filters = next;
569+ }
570+
571+ while(desc->links) {
572+ next = desc->links->next;
573+ av_free(desc->links);
574+ desc->links = next;
575+ }
576+
577+ while(desc->inputs) {
578+ next = desc->inputs->next;
579+ av_free(desc->inputs);
580+ desc->inputs = next;
581+ }
582+
583+ while(desc->outputs) {
584+ next = desc->outputs->next;
585+ av_free(desc->outputs);
586+ desc->outputs = next;
587+ }
588+}
589+

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