[FFmpeg-soc] [soc]: r4319 - in afilters: . README TODO allfilters.c avfilter.c avfilter.h avfiltergraph.c avfiltergraph.h checkout.sh defaults.c formats.c graphparser.c graphparser.h parseutils.c parseutils.h

kdub subversion at mplayerhq.hu
Thu May 28 05:19:13 CEST 2009


Author: kdub
Date: Thu May 28 05:19:12 2009
New Revision: 4319

Log:
initial afilters commit, with build system for initial devwork

Added:
   afilters/
   afilters/README
   afilters/TODO
   afilters/allfilters.c
   afilters/avfilter.c
   afilters/avfilter.h
   afilters/avfiltergraph.c
   afilters/avfiltergraph.h
   afilters/checkout.sh   (contents, props changed)
   afilters/defaults.c
   afilters/formats.c
   afilters/graphparser.c
   afilters/graphparser.h
   afilters/parseutils.c
   afilters/parseutils.h

Added: afilters/README
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ afilters/README	Thu May 28 05:19:12 2009	(r4319)
@@ -0,0 +1,7 @@
+Alright, here's how to get libavfilter up and compiling.
+
+If you've found this README, you've also found checkout.sh.
+* Running that script will check out a fresh ffmpeg from svn, and hardlink the .c and .h files you see here to the ffmpeg/libavfilter/ directory.
+* You can run configure and make as normal, but you'll have to descend to ffmpeg/libavfilter and run make to get libavfilter.a
+
+See the TODO for what works and doesnt work at this point :)

Added: afilters/TODO
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ afilters/TODO	Thu May 28 05:19:12 2009	(r4319)
@@ -0,0 +1,13 @@
+
+At current, I still need to
+
+Phase 1:
+* Finalize Audio API
+* Keep the filters fast
+* Create method for converting between different PCM formats, and linking the chain together correctly
+
+Phase 2:
+* Write a few filters for the API
+* Integrate libavfilter into the ffmpeg executable
+* Document
+

Added: afilters/allfilters.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ afilters/allfilters.c	Thu May 28 05:19:12 2009	(r4319)
@@ -0,0 +1,39 @@
+/*
+ * filter registration
+ * copyright (c) 2008 Vitor Sessak
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "avfilter.h"
+
+
+#define REGISTER_FILTER(X,x,y) { \
+          extern AVFilter avfilter_##y##_##x ; \
+          if(CONFIG_##X##_FILTER )  avfilter_register(&avfilter_##y##_##x ); }
+
+void avfilter_register_all(void)
+{
+    static int initialized;
+
+    if (initialized)
+        return;
+    initialized = 1;
+
+//    REGISTER_FILTER (CROP,crop,vf);
+
+}

Added: afilters/avfilter.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ afilters/avfilter.c	Thu May 28 05:19:12 2009	(r4319)
@@ -0,0 +1,404 @@
+/*
+ * filter layer
+ * copyright (c) 2007 Bobby Bingham
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavcodec/imgconvert.h"
+#include "avfilter.h"
+
+unsigned avfilter_version(void) {
+    return LIBAVFILTER_VERSION_INT;
+}
+
+/** list of registered filters */
+static struct FilterList
+{
+    AVFilter *filter;
+    struct FilterList *next;
+} *filters = NULL;
+
+/** helper macros to get the in/out pad on the dst/src filter */
+#define link_dpad(link)     link->dst-> input_pads[link->dstpad]
+#define link_spad(link)     link->src->output_pads[link->srcpad]
+
+AVFilterPicRef *avfilter_ref_pic(AVFilterPicRef *ref, int pmask)
+{
+    AVFilterPicRef *ret = av_malloc(sizeof(AVFilterPicRef));
+    *ret = *ref;
+    ret->perms &= pmask;
+    ret->pic->refcount ++;
+    return ret;
+}
+
+void avfilter_unref_pic(AVFilterPicRef *ref)
+{
+    if(!(--ref->pic->refcount))
+        ref->pic->free(ref->pic);
+    av_free(ref);
+}
+
+void avfilter_insert_pad(unsigned idx, unsigned *count, size_t padidx_off,
+                         AVFilterPad **pads, AVFilterLink ***links,
+                         AVFilterPad *newpad)
+{
+    unsigned i;
+
+    idx = FFMIN(idx, *count);
+
+    *pads  = av_realloc(*pads,  sizeof(AVFilterPad)   * (*count + 1));
+    *links = av_realloc(*links, sizeof(AVFilterLink*) * (*count + 1));
+    memmove(*pads +idx+1, *pads +idx, sizeof(AVFilterPad)   * (*count-idx));
+    memmove(*links+idx+1, *links+idx, sizeof(AVFilterLink*) * (*count-idx));
+    memcpy(*pads+idx, newpad, sizeof(AVFilterPad));
+    (*links)[idx] = NULL;
+
+    (*count) ++;
+    for(i = idx+1; i < *count; i ++)
+        if(*links[i])
+            (*(unsigned *)((uint8_t *) *links[i] + padidx_off)) ++;
+}
+
+int avfilter_link(AVFilterContext *src, unsigned srcpad,
+                  AVFilterContext *dst, unsigned dstpad)
+{
+    AVFilterLink *link;
+
+    if(src->output_count <= srcpad || dst->input_count <= dstpad ||
+       src->outputs[srcpad]        || dst->inputs[dstpad])
+        return -1;
+
+    src->outputs[srcpad] =
+    dst-> inputs[dstpad] = link = av_mallocz(sizeof(AVFilterLink));
+
+    link->src     = src;
+    link->dst     = dst;
+    link->srcpad  = srcpad;
+    link->dstpad  = dstpad;
+    link->format  = PIX_FMT_NONE;
+
+    return 0;
+}
+
+int avfilter_insert_filter(AVFilterLink *link, AVFilterContext *filt,
+                           unsigned in, unsigned out)
+{
+    av_log(link->dst, AV_LOG_INFO, "auto-inserting filter '%s'\n",
+            filt->filter->name);
+
+    link->dst->inputs[link->dstpad] = NULL;
+    if(avfilter_link(filt, out, link->dst, link->dstpad)) {
+        /* failed to link output filter to new filter */
+        link->dst->inputs[link->dstpad] = link;
+        return -1;
+    }
+
+    /* re-hookup the link to the new destination filter we inserted */
+    link->dst = filt;
+    link->dstpad = in;
+    filt->inputs[in] = link;
+
+    /* if any information on supported colorspaces already exists on the
+     * link, we need to preserve that */
+    if(link->out_formats)
+        avfilter_formats_changeref(&link->out_formats,
+                                   &filt->outputs[out]->out_formats);
+
+    return 0;
+}
+
+int avfilter_config_links(AVFilterContext *filter)
+{
+    int (*config_link)(AVFilterLink *);
+    unsigned i;
+
+    for(i = 0; i < filter->input_count; i ++) {
+        AVFilterLink *link = filter->inputs[i];
+
+        if(!link) continue;
+
+        switch(link->init_state) {
+        case AVLINK_INIT:
+            continue;
+        case AVLINK_STARTINIT:
+            av_log(filter, AV_LOG_INFO, "circular filter chain detected\n");
+            return 0;
+        case AVLINK_UNINIT:
+            link->init_state = AVLINK_STARTINIT;
+
+            if(avfilter_config_links(link->src))
+                return -1;
+
+            if(!(config_link = link_spad(link).config_props))
+                config_link  = avfilter_default_config_output_link;
+            if(config_link(link))
+                return -1;
+
+            if((config_link = link_dpad(link).config_props))
+                if(config_link(link))
+                    return -1;
+
+            link->init_state = AVLINK_INIT;
+        }
+    }
+
+    return 0;
+}
+
+AVFilterPicRef *avfilter_get_video_buffer(AVFilterLink *link, int perms)
+{
+    AVFilterPicRef *ret = NULL;
+
+    if(link_dpad(link).get_video_buffer)
+        ret = link_dpad(link).get_video_buffer(link, perms);
+
+    if(!ret)
+        ret = avfilter_default_get_video_buffer(link, perms);
+
+    return ret;
+}
+
+int avfilter_request_frame(AVFilterLink *link)
+{
+    if(link_spad(link).request_frame)
+        return link_spad(link).request_frame(link);
+    else if(link->src->inputs[0])
+        return avfilter_request_frame(link->src->inputs[0]);
+    else return -1;
+}
+
+int avfilter_poll_frame(AVFilterLink *link)
+{
+    int i, min=INT_MAX;
+
+    if(link_spad(link).poll_frame)
+        return link_spad(link).poll_frame(link);
+
+    for (i=0; i<link->src->input_count; i++) {
+        if(!link->src->inputs[i])
+            return -1;
+        min = FFMIN(min, avfilter_poll_frame(link->src->inputs[i]));
+    }
+
+    return min;
+}
+
+/* XXX: should we do the duplicating of the picture ref here, instead of
+ * forcing the source filter to do it? */
+void avfilter_start_frame(AVFilterLink *link, AVFilterPicRef *picref)
+{
+    void (*start_frame)(AVFilterLink *, AVFilterPicRef *);
+    AVFilterPad *dst = &link_dpad(link);
+
+    if(!(start_frame = dst->start_frame))
+        start_frame = avfilter_default_start_frame;
+
+    /* prepare to copy the picture if it has insufficient permissions */
+    if((dst->min_perms & picref->perms) != dst->min_perms ||
+        dst->rej_perms & picref->perms) {
+        /*
+        av_log(link->dst, AV_LOG_INFO,
+                "frame copy needed (have perms %x, need %x, reject %x)\n",
+                picref->perms,
+                link_dpad(link).min_perms, link_dpad(link).rej_perms);
+        */
+
+        link->cur_pic = avfilter_default_get_video_buffer(link, dst->min_perms);
+        link->srcpic = picref;
+        link->cur_pic->pts = link->srcpic->pts;
+        link->cur_pic->pixel_aspect = link->srcpic->pixel_aspect;
+    }
+    else
+        link->cur_pic = picref;
+
+    start_frame(link, link->cur_pic);
+}
+
+void avfilter_end_frame(AVFilterLink *link)
+{
+    void (*end_frame)(AVFilterLink *);
+
+    if(!(end_frame = link_dpad(link).end_frame))
+        end_frame = avfilter_default_end_frame;
+
+    end_frame(link);
+
+    /* unreference the source picture if we're feeding the destination filter
+     * a copied version dues to permission issues */
+    if(link->srcpic) {
+        avfilter_unref_pic(link->srcpic);
+        link->srcpic = NULL;
+    }
+
+}
+
+void avfilter_draw_slice(AVFilterLink *link, int y, int h)
+{
+    uint8_t *src[4], *dst[4];
+    int i, j, hsub, vsub;
+    void (*draw_slice)(AVFilterLink *, int, int);
+
+    /* copy the slice if needed for permission reasons */
+    if(link->srcpic) {
+        avcodec_get_chroma_sub_sample(link->format, &hsub, &vsub);
+
+        for(i = 0; i < 4; i ++) {
+            if(link->srcpic->data[i]) {
+                src[i] = link->srcpic-> data[i] +
+                    (y >> (i==0 ? 0 : vsub)) * link->srcpic-> linesize[i];
+                dst[i] = link->cur_pic->data[i] +
+                    (y >> (i==0 ? 0 : vsub)) * link->cur_pic->linesize[i];
+            } else
+                src[i] = dst[i] = NULL;
+        }
+
+        for(i = 0; i < 4; i ++) {
+            int planew =
+                ff_get_plane_bytewidth(link->format, link->cur_pic->w, i);
+
+            if(!src[i]) continue;
+
+            for(j = 0; j < h >> (i==0 ? 0 : vsub); j ++) {
+                memcpy(dst[i], src[i], planew);
+                src[i] += link->srcpic ->linesize[i];
+                dst[i] += link->cur_pic->linesize[i];
+            }
+        }
+    }
+
+    if(!(draw_slice = link_dpad(link).draw_slice))
+        draw_slice = avfilter_default_draw_slice;
+    draw_slice(link, y, h);
+}
+
+AVFilter *avfilter_get_by_name(const char *name)
+{
+    struct FilterList *filt;
+
+    for(filt = filters; filt; filt = filt->next)
+        if(!strcmp(filt->filter->name, name))
+            return filt->filter;
+
+    return NULL;
+}
+
+void avfilter_register(AVFilter *filter)
+{
+    struct FilterList *newfilt = av_malloc(sizeof(struct FilterList));
+
+    newfilt->filter = filter;
+    newfilt->next   = filters;
+    filters         = newfilt;
+}
+
+void avfilter_uninit(void)
+{
+    struct FilterList *tmp;
+
+    for(; filters; filters = tmp) {
+        tmp = filters->next;
+        av_free(filters);
+    }
+}
+
+static int pad_count(const AVFilterPad *pads)
+{
+    int count;
+
+    for(count = 0; pads->name; count ++) pads ++;
+    return count;
+}
+
+static const char *filter_name(void *p)
+{
+    AVFilterContext *filter = p;
+    return filter->filter->name;
+}
+
+static const AVClass avfilter_class = {
+    "AVFilter",
+    filter_name
+};
+
+AVFilterContext *avfilter_open(AVFilter *filter, const char *inst_name)
+{
+    AVFilterContext *ret;
+
+    if (!filter)
+        return 0;
+
+    ret = av_mallocz(sizeof(AVFilterContext));
+
+    ret->av_class = &avfilter_class;
+    ret->filter   = filter;
+    ret->name     = inst_name ? av_strdup(inst_name) : NULL;
+    ret->priv     = av_mallocz(filter->priv_size);
+
+    ret->input_count  = pad_count(filter->inputs);
+    if (ret->input_count) {
+        ret->input_pads   = av_malloc(sizeof(AVFilterPad) * ret->input_count);
+        memcpy(ret->input_pads, filter->inputs, sizeof(AVFilterPad) * ret->input_count);
+        ret->inputs       = av_mallocz(sizeof(AVFilterLink*) * ret->input_count);
+    }
+
+    ret->output_count = pad_count(filter->outputs);
+    if (ret->output_count) {
+        ret->output_pads  = av_malloc(sizeof(AVFilterPad) * ret->output_count);
+        memcpy(ret->output_pads, filter->outputs, sizeof(AVFilterPad) * ret->output_count);
+        ret->outputs      = av_mallocz(sizeof(AVFilterLink*) * ret->output_count);
+    }
+
+    return ret;
+}
+
+void avfilter_destroy(AVFilterContext *filter)
+{
+    int i;
+
+    if(filter->filter->uninit)
+        filter->filter->uninit(filter);
+
+    for(i = 0; i < filter->input_count; i ++) {
+        if(filter->inputs[i])
+            filter->inputs[i]->src->outputs[filter->inputs[i]->srcpad] = NULL;
+        av_freep(&filter->inputs[i]);
+    }
+    for(i = 0; i < filter->output_count; i ++) {
+        if(filter->outputs[i])
+            filter->outputs[i]->dst->inputs[filter->outputs[i]->dstpad] = NULL;
+        av_freep(&filter->outputs[i]);
+    }
+
+    av_freep(&filter->name);
+    av_freep(&filter->input_pads);
+    av_freep(&filter->output_pads);
+    av_freep(&filter->inputs);
+    av_freep(&filter->outputs);
+    av_freep(&filter->priv);
+    av_free(filter);
+}
+
+int avfilter_init_filter(AVFilterContext *filter, const char *args, void *opaque)
+{
+    int ret=0;
+
+    if(filter->filter->init)
+        ret = filter->filter->init(filter, args, opaque);
+    return ret;
+}
+

Added: afilters/avfilter.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ afilters/avfilter.h	Thu May 28 05:19:12 2009	(r4319)
@@ -0,0 +1,635 @@
+/*
+ * filter layer
+ * copyright (c) 2007 Bobby Bingham
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVFILTER_AVFILTER_H
+#define AVFILTER_AVFILTER_H
+
+#define LIBAVFILTER_VERSION_MAJOR  0
+#define LIBAVFILTER_VERSION_MINOR  5
+#define LIBAVFILTER_VERSION_MICRO  0
+
+#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
+                                               LIBAVFILTER_VERSION_MINOR, \
+                                               LIBAVFILTER_VERSION_MICRO)
+#define LIBAVFILTER_VERSION     AV_VERSION(LIBAVFILTER_VERSION_MAJOR,   \
+                                           LIBAVFILTER_VERSION_MINOR,   \
+                                           LIBAVFILTER_VERSION_MICRO)
+#define LIBAVFILTER_BUILD       LIBAVFILTER_VERSION_INT
+
+#include <stddef.h>
+#include "libavcodec/avcodec.h"
+
+/**
+ * Returns the LIBAVFILTER_VERSION_INT constant.
+ */
+unsigned avfilter_version(void);
+
+typedef struct AVFilterContext AVFilterContext;
+typedef struct AVFilterLink    AVFilterLink;
+typedef struct AVFilterPad     AVFilterPad;
+
+/* TODO: look for other flags which may be useful in this structure (interlace
+ * flags, etc)
+ */
+/**
+ * A reference-counted picture data type used by the filter system. Filters
+ * should not store pointers to this structure directly, but instead use the
+ * AVFilterPicRef structure below.
+ */
+typedef struct AVFilterPic
+{
+    uint8_t *data[4];           ///< picture data for each plane
+    int linesize[4];            ///< number of bytes per line
+    enum PixelFormat format;    ///< colorspace
+
+    unsigned refcount;          ///< number of references to this image
+
+    /** private data to be used by a custom free function */
+    void *priv;
+    /**
+     * A pointer to the function to deallocate this image if the default
+     * function is not sufficient. This could, for example, add the memory
+     * back into a memory pool to be reused later without the overhead of
+     * reallocating it from scratch.
+     */
+    void (*free)(struct AVFilterPic *pic);
+} AVFilterPic;
+
+/**
+ * A reference to an AVFilterPic. Since filters can manipulate the origin of
+ * a picture to, for example, crop image without any memcpy, the picture origin
+ * and dimensions are per-reference properties. Linesize is also useful for
+ * image flipping, frame to field filters, etc, and so is also per-reference.
+ *
+ * TODO: add anything necessary for frame reordering
+ */
+typedef struct AVFilterPicRef
+{
+    AVFilterPic *pic;           ///< the picture that this is a reference to
+    uint8_t *data[4];           ///< picture data for each plane
+    int linesize[4];            ///< number of bytes per line
+    int w;                      ///< image width
+    int h;                      ///< image height
+
+    int64_t pts;                ///< presentation timestamp in units of 1/AV_TIME_BASE
+
+    AVRational pixel_aspect;    ///< pixel aspect ratio
+
+    int perms;                  ///< permissions
+#define AV_PERM_READ     0x01   ///< can read from the buffer
+#define AV_PERM_WRITE    0x02   ///< can write to the buffer
+#define AV_PERM_PRESERVE 0x04   ///< nobody else can overwrite the buffer
+#define AV_PERM_REUSE    0x08   ///< can output the buffer multiple times, with the same contents each time
+#define AV_PERM_REUSE2   0x10   ///< can output the buffer multiple times, modified each time
+} AVFilterPicRef;
+
+/**
+ * Adds a new reference to a picture.
+ * @param ref   an existing reference to the picture
+ * @param pmask a bitmask containing the allowable permissions in the new
+ *              reference
+ * @return      a new reference to the picture with the same properties as the
+ *              old, excluding any permissions denied by pmask
+ */
+AVFilterPicRef *avfilter_ref_pic(AVFilterPicRef *ref, int pmask);
+
+/**
+ * Removes a reference to a picture. If this is the last reference to the
+ * picture, the picture itself is also automatically freed.
+ * @param ref reference to the picture
+ */
+void avfilter_unref_pic(AVFilterPicRef *ref);
+
+/**
+ * A list of supported formats for one end of a filter link. This is used
+ * during the format negotiation process to try to pick the best format to
+ * use to minimize the number of necessary conversions. Each filter gives a
+ * list of the formats supported by each input and output pad. The list
+ * given for each pad need not be distinct - they may be references to the
+ * same list of formats, as is often the case when a filter supports multiple
+ * formats, but will always output the same format as it is given in input.
+ *
+ * In this way, a list of possible input formats and a list of possible
+ * output formats are associated with each link. When a set of formats is
+ * negotiated over a link, the input and output lists are merged to form a
+ * new list containing only the common elements of each list. In the case
+ * that there were no common elements, a format conversion is necessary.
+ * Otherwise, the lists are merged, and all other links which reference
+ * either of the format lists involved in the merge are also affected.
+ *
+ * For example, consider the filter chain:
+ * filter (a) --> (b) filter (b) --> (c) filter
+ *
+ * where the letters in parenthesis indicate a list of formats supported on
+ * the input or output of the link. Suppose the lists are as follows:
+ * (a) = {A, B}
+ * (b) = {A, B, C}
+ * (c) = {B, C}
+ *
+ * First, the first link's lists are merged, yielding:
+ * filter (a) --> (a) filter (a) --> (c) filter
+ *
+ * Notice that format list (b) now refers to the same list as filter list (a).
+ * Next, the lists for the second link are merged, yielding:
+ * filter (a) --> (a) filter (a) --> (a) filter
+ *
+ * where (a) = {B}.
+ *
+ * Unfortunately, when the format lists at the two ends of a link are merged,
+ * we must ensure that all links which reference either pre-merge format list
+ * get updated as well. Therefore, we have the format list structure store a
+ * pointer to each of the pointers to itself.
+ */
+typedef struct AVFilterFormats AVFilterFormats;
+struct AVFilterFormats
+{
+    unsigned format_count;      ///< number of formats
+    int *formats;               ///< list of formats
+
+    unsigned refcount;          ///< number of references to this list
+    AVFilterFormats ***refs;    ///< references to this list
+};
+
+/**
+ * Helper function to create a list of supported formats.  This is intended
+ * for use in AVFilter->query_formats().
+ * @param len the number of formats supported
+ * @param ... a list of the supported formats
+ * @return    the format list, with no existing references
+ */
+AVFilterFormats *avfilter_make_format_list(int len, ...);
+
+/**
+ * Returns a list of all colorspaces supported by FFmpeg.
+ */
+AVFilterFormats *avfilter_all_colorspaces(void);
+
+/**
+ * Returns a format list which contains the intersection of the formats of
+ * a and b. Also, all the references of a, all the references of b, and
+ * a and b themselves will be deallocated.
+ *
+ * If a and b do not share any common formats, neither is modified, and NULL
+ * is returned.
+ */
+AVFilterFormats *avfilter_merge_formats(AVFilterFormats *a, AVFilterFormats *b);
+
+/**
+ * Adds *ref as a new reference to formats.
+ * That is the pointers will point like in the ascii art below:
+ *   ________
+ *  |formats |<--------.
+ *  |  ____  |     ____|___________________
+ *  | |refs| |    |  __|_
+ *  | |* * | |    | |  | |  AVFilterLink
+ *  | |* *--------->|*ref|
+ *  | |____| |    | |____|
+ *  |________|    |________________________
+ */
+void avfilter_formats_ref(AVFilterFormats *formats, AVFilterFormats **ref);
+
+/**
+ * Removes *ref as a reference to the format list it currently points to,
+ * deallocates that list if this was the last reference, and sets *ref to NULL.
+ *
+ *         Before                                 After
+ *   ________                               ________         NULL
+ *  |formats |<--------.                   |formats |         ^
+ *  |  ____  |     ____|________________   |  ____  |     ____|________________
+ *  | |refs| |    |  __|_                  | |refs| |    |  __|_
+ *  | |* * | |    | |  | |  AVFilterLink   | |* * | |    | |  | |  AVFilterLink
+ *  | |* *--------->|*ref|                 | |*   | |    | |*ref|
+ *  | |____| |    | |____|                 | |____| |    | |____|
+ *  |________|    |_____________________   |________|    |_____________________
+ */
+void avfilter_formats_unref(AVFilterFormats **ref);
+
+/**
+ *
+ *         Before                                 After
+ *   ________                         ________
+ *  |formats |<---------.            |formats |<---------.
+ *  |  ____  |       ___|___         |  ____  |       ___|___
+ *  | |refs| |      |   |   |        | |refs| |      |   |   |   NULL
+ *  | |* *--------->|*oldref|        | |* *--------->|*newref|     ^
+ *  | |* * | |      |_______|        | |* * | |      |_______|  ___|___
+ *  | |____| |                       | |____| |                |   |   |
+ *  |________|                       |________|                |*oldref|
+ *                                                             |_______|
+ */
+void avfilter_formats_changeref(AVFilterFormats **oldref,
+                                AVFilterFormats **newref);
+
+/**
+ * A filter pad used for either input or output.
+ */
+struct AVFilterPad
+{
+    /**
+     * Pad name. The name is unique among inputs and among outputs, but an
+     * input may have the same name as an output. This may be NULL if this
+     * pad has no need to ever be referenced by name.
+     */
+    const char *name;
+
+    /**
+     * AVFilterPad type. Only video supported now, hopefully someone will
+     * add audio in the future.
+     */
+    enum CodecType type;
+
+    /**
+     * Minimum required permissions on incoming buffers. Any buffer with
+     * insufficient permissions will be automatically copied by the filter
+     * system to a new buffer which provides the needed access permissions.
+     *
+     * Input pads only.
+     */
+    int min_perms;
+
+    /**
+     * Permissions which are not accepted on incoming buffers. Any buffer
+     * which has any of these permissions set will be automatically copied
+     * by the filter system to a new buffer which does not have those
+     * permissions. This can be used to easily disallow buffers with
+     * AV_PERM_REUSE.
+     *
+     * Input pads only.
+     */
+    int rej_perms;
+
+    /**
+     * Callback called before passing the first slice of a new frame. If
+     * NULL, the filter layer will default to storing a reference to the
+     * picture inside the link structure.
+     *
+     * Input video pads only.
+     */
+    void (*start_frame)(AVFilterLink *link, AVFilterPicRef *picref);
+
+    /**
+     * Callback function to get a buffer. If NULL, the filter system will
+     * handle buffer requests.
+     *
+     * Input video pads only.
+     */
+    AVFilterPicRef *(*get_video_buffer)(AVFilterLink *link, int perms);
+
+    /**
+     * Callback called after the slices of a frame are completely sent. If
+     * NULL, the filter layer will default to releasing the reference stored
+     * in the link structure during start_frame().
+     *
+     * Input video pads only.
+     */
+    void (*end_frame)(AVFilterLink *link);
+
+    /**
+     * Slice drawing callback. This is where a filter receives video data
+     * and should do its processing.
+     *
+     * Input video pads only.
+     */
+    void (*draw_slice)(AVFilterLink *link, int y, int height);
+
+    /**
+     * Frame poll callback. This returns the number of immediately available
+     * frames. It should return a positive value if the next request_frame()
+     * is guaranteed to return one frame (with no delay).
+     *
+     * Defaults to just calling the source poll_frame() method.
+     *
+     * Output video pads only.
+     */
+    int (*poll_frame)(AVFilterLink *link);
+
+    /**
+     * Frame request callback. A call to this should result in at least one
+     * frame being output over the given link. This should return zero on
+     * success, and another value on error.
+     *
+     * Output video pads only.
+     */
+    int (*request_frame)(AVFilterLink *link);
+
+    /**
+     * Link configuration callback.
+     *
+     * For output pads, this should set the link properties such as
+     * width/height. This should NOT set the format property - that is
+     * negotiated between filters by the filter system using the
+     * query_formats() callback before this function is called.
+     *
+     * For input pads, this should check the properties of the link, and update
+     * the filter's internal state as necessary.
+     *
+     * For both input and output filters, this should return zero on success,
+     * and another value on error.
+     */
+    int (*config_props)(AVFilterLink *link);
+};
+
+/** default handler for start_frame() for video inputs */
+void avfilter_default_start_frame(AVFilterLink *link, AVFilterPicRef *picref);
+/** default handler for draw_slice() for video inputs */
+void avfilter_default_draw_slice(AVFilterLink *link, int y, int h);
+/** default handler for end_frame() for video inputs */
+void avfilter_default_end_frame(AVFilterLink *link);
+/** default handler for config_props() for video outputs */
+int avfilter_default_config_output_link(AVFilterLink *link);
+/** default handler for config_props() for video inputs */
+int avfilter_default_config_input_link (AVFilterLink *link);
+/** default handler for get_video_buffer() for video inputs */
+AVFilterPicRef *avfilter_default_get_video_buffer(AVFilterLink *link,
+                                                  int perms);
+/**
+ * A helper for query_formats() which sets all links to the same list of
+ * formats. If there are no links hooked to this filter, the list of formats is
+ * freed.
+ */
+void avfilter_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats);
+/** Default handler for query_formats() */
+int avfilter_default_query_formats(AVFilterContext *ctx);
+
+/**
+ * Filter definition. This defines the pads a filter contains, and all the
+ * callback functions used to interact with the filter.
+ */
+typedef struct
+{
+    const char *name;         ///< filter name
+
+    int priv_size;      ///< size of private data to allocate for the filter
+
+    /**
+     * Filter initialization function. Args contains the user-supplied
+     * parameters. FIXME: maybe an AVOption-based system would be better?
+     * opaque is data provided by the code requesting creation of the filter,
+     * and is used to pass data to the filter.
+     */
+    int (*init)(AVFilterContext *ctx, const char *args, void *opaque);
+
+    /**
+     * Filter uninitialization function. Should deallocate any memory held
+     * by the filter, release any picture references, etc. This does not need
+     * to deallocate the AVFilterContext->priv memory itself.
+     */
+    void (*uninit)(AVFilterContext *ctx);
+
+    /**
+     * Query formats supported by the filter and its pads. Should set the
+     * in_formats for links connected to its output pads, and out_formats
+     * for links connected to its input pads.
+     *
+     * Should return zero on success.
+     */
+    int (*query_formats)(AVFilterContext *);
+
+    const AVFilterPad *inputs;  ///< NULL terminated list of inputs. NULL if none
+    const AVFilterPad *outputs; ///< NULL terminated list of outputs. NULL if none
+} AVFilter;
+
+/** An instance of a filter */
+struct AVFilterContext
+{
+    const AVClass *av_class;              ///< needed for av_log()
+
+    AVFilter *filter;               ///< the AVFilter of which this is an instance
+
+    char *name;                     ///< name of this filter instance
+
+    unsigned input_count;           ///< number of input pads
+    AVFilterPad   *input_pads;      ///< array of input pads
+    AVFilterLink **inputs;          ///< array of pointers to input links
+
+    unsigned output_count;          ///< number of output pads
+    AVFilterPad   *output_pads;     ///< array of output pads
+    AVFilterLink **outputs;         ///< array of pointers to output links
+
+    void *priv;                     ///< private data for use by the filter
+};
+
+/**
+ * A link between two filters. This contains pointers to the source and
+ * destination filters between which this link exists, and the indexes of
+ * the pads involved. In addition, this link also contains the parameters
+ * which have been negotiated and agreed upon between the filter, such as
+ * image dimensions, format, etc.
+ */
+struct AVFilterLink
+{
+    AVFilterContext *src;       ///< source filter
+    unsigned int srcpad;        ///< index of the output pad on the source filter
+
+    AVFilterContext *dst;       ///< dest filter
+    unsigned int dstpad;        ///< index of the input pad on the dest filter
+
+    /** stage of the initialization of the link properties (dimensions, etc) */
+    enum {
+        AVLINK_UNINIT = 0,      ///< not started
+        AVLINK_STARTINIT,       ///< started, but incomplete
+        AVLINK_INIT             ///< complete
+    } init_state;
+
+    int w;                      ///< agreed upon image width
+    int h;                      ///< agreed upon image height
+    enum PixelFormat format;    ///< agreed upon image colorspace
+
+    /**
+     * Lists of formats supported by the input and output filters respectively.
+     * These lists are used for negotiating the format to actually be used,
+     * which will be loaded into the format member, above, when chosen.
+     */
+    AVFilterFormats *in_formats;
+    AVFilterFormats *out_formats;
+
+    /**
+     * The picture reference currently being sent across the link by the source
+     * filter. This is used internally by the filter system to allow
+     * automatic copying of pictures which do not have sufficient permissions
+     * for the destination. This should not be accessed directly by the
+     * filters.
+     */
+    AVFilterPicRef *srcpic;
+
+    AVFilterPicRef *cur_pic;
+    AVFilterPicRef *outpic;
+};
+
+/**
+ * Links two filters together.
+ * @param src    the source filter
+ * @param srcpad index of the output pad on the source filter
+ * @param dst    the destination filter
+ * @param dstpad index of the input pad on the destination filter
+ * @return       zero on success
+ */
+int avfilter_link(AVFilterContext *src, unsigned srcpad,
+                  AVFilterContext *dst, unsigned dstpad);
+
+/**
+ * Negotiates the colorspace, dimensions, etc of all inputs to a filter.
+ * @param filter the filter to negotiate the properties for its inputs
+ * @return       zero on successful negotiation
+ */
+int avfilter_config_links(AVFilterContext *filter);
+
+/**
+ * Requests a picture buffer with a specific set of permissions.
+ * @param link  the output link to the filter from which the picture will
+ *              be requested
+ * @param perms the required access permissions
+ * @return      A reference to the picture. This must be unreferenced with
+ *              avfilter_unref_pic when you are finished with it.
+ */
+AVFilterPicRef *avfilter_get_video_buffer(AVFilterLink *link, int perms);
+
+/**
+ * Requests an input frame from the filter at the other end of the link.
+ * @param link the input link
+ * @return     zero on success
+ */
+int avfilter_request_frame(AVFilterLink *link);
+
+/**
+ * Polls a frame from the filter chain.
+ * @param  link the input link
+ * @return the number of immediately available frames, a negative
+ * number in case of error
+ */
+int avfilter_poll_frame(AVFilterLink *link);
+
+/**
+ * Notifies the next filter of the start of a frame.
+ * @param link   the output link the frame will be sent over
+ * @param picref A reference to the frame about to be sent. The data for this
+ *               frame need only be valid once draw_slice() is called for that
+ *               portion. The receiving filter will free this reference when
+ *               it no longer needs it.
+ */
+void avfilter_start_frame(AVFilterLink *link, AVFilterPicRef *picref);
+
+/**
+ * Notifies the next filter that the current frame has finished.
+ * @param link the output link the frame was sent over
+ */
+void avfilter_end_frame(AVFilterLink *link);
+
+/**
+ * Sends a slice to the next filter.
+ * @param link the output link over which the frame is being sent
+ * @param y    offset in pixels from the top of the image for this slice
+ * @param h    height of this slice in pixels
+ */
+void avfilter_draw_slice(AVFilterLink *link, int y, int h);
+
+/** Initialize the filter system. Registers all builtin filters */
+void avfilter_register_all(void);
+
+/** Uninitialize the filter system. Unregisters all filters */
+void avfilter_uninit(void);
+
+/**
+ * Registers a filter. This is only needed if you plan to use
+ * avfilter_get_by_name later to lookup the AVFilter structure by name. A
+ * filter can still by instantiated with avfilter_open even if it is not
+ * registered.
+ * @param filter the filter to register
+ */
+void avfilter_register(AVFilter *filter);
+
+/**
+ * Gets a filter definition matching the given name.
+ * @param name the filter name to find
+ * @return     the filter definition, if any matching one is registered.
+ *             NULL if none found.
+ */
+AVFilter *avfilter_get_by_name(const char *name);
+
+/**
+ * Creates a filter instance.
+ * @param filter    the filter to create an instance of
+ * @param inst_name Name to give to the new instance. Can be NULL for none.
+ * @return          Pointer to the new instance on success. NULL on failure.
+ */
+AVFilterContext *avfilter_open(AVFilter *filter, const char *inst_name);
+
+/**
+ * Initializes a filter.
+ * @param filter the filter to initialize
+ * @param args   A string of parameters to use when initializing the filter.
+ *               The format and meaning of this string varies by filter.
+ * @param opaque Any extra non-string data needed by the filter. The meaning
+ *               of this parameter varies by filter.
+ * @return       zero on success
+ */
+int avfilter_init_filter(AVFilterContext *filter, const char *args, void *opaque);
+
+/**
+ * Destroys a filter.
+ * @param filter the filter to destroy
+ */
+void avfilter_destroy(AVFilterContext *filter);
+
+/**
+ * Inserts a filter in the middle of an existing link.
+ * @param link the link into which the filter should be inserted
+ * @param filt the filter to be inserted
+ * @param in   the input pad on the filter to connect
+ * @param out  the output pad on the filter to connect
+ * @return     zero on success
+ */
+int avfilter_insert_filter(AVFilterLink *link, AVFilterContext *filt,
+                           unsigned in, unsigned out);
+
+/**
+ * Inserts a new pad.
+ * @param idx Insertion point. Pad is inserted at the end if this point
+ *            is beyond the end of the list of pads.
+ * @param count Pointer to the number of pads in the list
+ * @param padidx_off Offset within an AVFilterLink structure to the element
+ *                   to increment when inserting a new pad causes link
+ *                   numbering to change
+ * @param pads Pointer to the pointer to the beginning of the list of pads
+ * @param links Pointer to the pointer to the beginning of the list of links
+ * @param newpad The new pad to add. A copy is made when adding.
+ */
+void avfilter_insert_pad(unsigned idx, unsigned *count, size_t padidx_off,
+                         AVFilterPad **pads, AVFilterLink ***links,
+                         AVFilterPad *newpad);
+
+/** Inserts a new input pad for the filter. */
+static inline void avfilter_insert_inpad(AVFilterContext *f, unsigned index,
+                                         AVFilterPad *p)
+{
+    avfilter_insert_pad(index, &f->input_count, offsetof(AVFilterLink, dstpad),
+                        &f->input_pads, &f->inputs, p);
+}
+
+/** Inserts a new output pad for the filter. */
+static inline void avfilter_insert_outpad(AVFilterContext *f, unsigned index,
+                                          AVFilterPad *p)
+{
+    avfilter_insert_pad(index, &f->output_count, offsetof(AVFilterLink, srcpad),
+                        &f->output_pads, &f->outputs, p);
+}
+
+#endif  /* AVFILTER_AVFILTER_H */

Added: afilters/avfiltergraph.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ afilters/avfiltergraph.c	Thu May 28 05:19:12 2009	(r4319)
@@ -0,0 +1,184 @@
+/*
+ * filter graphs
+ * copyright (c) 2008 Vitor Sessak
+ * copyright (c) 2007 Bobby Bingham
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <ctype.h>
+#include <string.h>
+
+#include "avfilter.h"
+#include "avfiltergraph.h"
+
+void avfilter_graph_destroy(AVFilterGraph *graph)
+{
+    for(; graph->filter_count > 0; graph->filter_count --)
+        avfilter_destroy(graph->filters[graph->filter_count - 1]);
+    av_freep(&graph->scale_sws_opts);
+    av_freep(&graph->filters);
+}
+
+int avfilter_graph_add_filter(AVFilterGraph *graph, AVFilterContext *filter)
+{
+    graph->filters = av_realloc(graph->filters,
+                                sizeof(AVFilterContext*) * ++graph->filter_count);
+
+    if (!graph->filters)
+        return -1;
+
+    graph->filters[graph->filter_count - 1] = filter;
+
+    return 0;
+}
+
+int avfilter_graph_check_validity(AVFilterGraph *graph, AVClass *log_ctx)
+{
+    AVFilterContext *filt;
+    int i, j;
+
+    for (i=0; i < graph->filter_count; i++) {
+        filt = graph->filters[i];
+
+        for (j = 0; j < filt->input_count; j++) {
+            if (!filt->inputs[j] || !filt->inputs[j]->src) {
+                av_log(log_ctx, AV_LOG_ERROR,
+                       "Input pad \"%s\" for the filter \"%s\" of type \"%s\" not connected to any source\n",
+                       filt->input_pads[j].name, filt->name, filt->filter->name);
+                return -1;
+            }
+        }
+
+        for (j = 0; j < filt->output_count; j++) {
+            if (!filt->outputs[j] || !filt->outputs[j]->dst) {
+                av_log(log_ctx, AV_LOG_ERROR,
+                       "Output pad \"%s\" for the filter \"%s\" of type \"%s\" not connected to any destination\n",
+                       filt->output_pads[j].name, filt->name, filt->filter->name);
+                return -1;
+            }
+        }
+    }
+
+    return 0;
+}
+
+AVFilterContext *avfilter_graph_get_filter(AVFilterGraph *graph, char *name)
+{
+    int i;
+
+    for(i = 0; i < graph->filter_count; i ++)
+        if(graph->filters[i]->name && !strcmp(name, graph->filters[i]->name))
+            return graph->filters[i];
+
+    return NULL;
+}
+
+static int query_formats(AVFilterGraph *graph)
+{
+    int i, j;
+    int scaler_count = 0;
+    char inst_name[30];
+
+    /* ask all the sub-filters for their supported colorspaces */
+    for(i = 0; i < graph->filter_count; i ++) {
+        if(graph->filters[i]->filter->query_formats)
+            graph->filters[i]->filter->query_formats(graph->filters[i]);
+        else
+            avfilter_default_query_formats(graph->filters[i]);
+    }
+
+    /* go through and merge as many format lists as possible */
+    for(i = 0; i < graph->filter_count; i ++) {
+        AVFilterContext *filter = graph->filters[i];
+
+        for(j = 0; j < filter->input_count; j ++) {
+            AVFilterLink *link = filter->inputs[j];
+            if(link && link->in_formats != link->out_formats) {
+                if(!avfilter_merge_formats(link->in_formats,
+                                           link->out_formats)) {
+                    AVFilterContext *scale;
+                    char scale_args[256];
+                    /* couldn't merge format lists. auto-insert scale filter */
+                    snprintf(inst_name, sizeof(inst_name), "auto-inserted scaler %d",
+                             scaler_count);
+                    scale =
+                        avfilter_open(avfilter_get_by_name("scale"),inst_name);
+
+                    snprintf(scale_args, sizeof(scale_args), "0:0:%s", graph->scale_sws_opts);
+                    if(!scale || scale->filter->init(scale, scale_args, NULL) ||
+                                 avfilter_insert_filter(link, scale, 0, 0)) {
+                        avfilter_destroy(scale);
+                        return -1;
+                    }
+
+                    if (avfilter_graph_add_filter(graph, scale) < 0)
+                        return -1;
+
+                    scale->filter->query_formats(scale);
+                    if(!avfilter_merge_formats(scale-> inputs[0]->in_formats,
+                                               scale-> inputs[0]->out_formats)||
+                       !avfilter_merge_formats(scale->outputs[0]->in_formats,
+                                               scale->outputs[0]->out_formats))
+                        return -1;
+                }
+            }
+        }
+    }
+
+    return 0;
+}
+
+static void pick_format(AVFilterLink *link)
+{
+    if(!link || !link->in_formats)
+        return;
+
+    link->in_formats->format_count = 1;
+    link->format = link->in_formats->formats[0];
+
+    avfilter_formats_unref(&link->in_formats);
+    avfilter_formats_unref(&link->out_formats);
+}
+
+static void pick_formats(AVFilterGraph *graph)
+{
+    int i, j;
+
+    for(i = 0; i < graph->filter_count; i ++) {
+        AVFilterContext *filter = graph->filters[i];
+
+        for(j = 0; j < filter->input_count; j ++)
+            pick_format(filter->inputs[j]);
+        for(j = 0; j < filter->output_count; j ++)
+            pick_format(filter->outputs[j]);
+    }
+}
+
+int avfilter_graph_config_formats(AVFilterGraph *graph)
+{
+    /* find supported formats from sub-filters, and merge along links */
+    if(query_formats(graph))
+        return -1;
+
+    /* Once everything is merged, it's possible that we'll still have
+     * multiple valid colorspace choices. We pick the first one. */
+    pick_formats(graph);
+
+    return 0;
+}
+

Added: afilters/avfiltergraph.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ afilters/avfiltergraph.h	Thu May 28 05:19:12 2009	(r4319)
@@ -0,0 +1,69 @@
+/*
+ * Filter graphs
+ * copyright (c) 2007 Bobby Bingham
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVFILTER_AVFILTERGRAPH_H
+#define AVFILTER_AVFILTERGRAPH_H
+
+#include "avfilter.h"
+
+typedef struct AVFilterGraph {
+    unsigned filter_count;
+    AVFilterContext **filters;
+
+    char *scale_sws_opts; ///< sws options to use for the auto-inserted scale filters
+} AVFilterGraph;
+
+/**
+ * Gets a filter instance with name name from graph.
+ *
+ * @return the pointer to the found filter instance or NULL if it
+ * cannot be found.
+ */
+AVFilterContext *avfilter_graph_get_filter(AVFilterGraph *graph, char *name);
+
+/**
+ * Adds an existing filter instance to a filter graph.
+ * @param graph  The filter graph
+ * @param filter The filter to be added
+ */
+int avfilter_graph_add_filter(AVFilterGraph *graphctx, AVFilterContext *filter);
+
+/**
+ * Checks for the validity of graph.
+ *
+ * A graph is considered valid if all its input and output pads are
+ * connected.
+ *
+ * @return 0 in case of success, a negative value otherwise
+ */
+int avfilter_graph_check_validity(AVFilterGraph *graphctx, AVClass *log_ctx);
+
+/**
+ * Configures the formats of all the links in the graph.
+ */
+int avfilter_graph_config_formats(AVFilterGraph *graphctx);
+
+/**
+ * Frees a graph and destroys its links.
+ */
+void avfilter_graph_destroy(AVFilterGraph *graph);
+
+#endif  /* AVFILTER_AVFILTERGRAPH_H */

Added: afilters/checkout.sh
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ afilters/checkout.sh	Thu May 28 05:19:12 2009	(r4319)
@@ -0,0 +1,18 @@
+#!/bin/sh
+echo "checking clean ffmpeg svn"
+svn checkout svn://svn.ffmpeg.org/ffmpeg/trunk ffmpeg
+
+echo "deleting source files in libavfilter..."
+rm ffmpeg/libavfilter/*.c ffmpeg/libavfilter/*.h
+
+
+
+echo "linking SoC files where we just deleted the avfilter files from pristine"
+
+for i in `ls *.c *.h`; do
+echo "Linking $i"
+ln $i ffmpeg/libavfilter/$i
+done
+
+echo "linking the SoC avfilter files into SVN..."
+echo "Done, now just do a regular configure and make to build."

Added: afilters/defaults.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ afilters/defaults.c	Thu May 28 05:19:12 2009	(r4319)
@@ -0,0 +1,165 @@
+/*
+ * Filter layer - default implementations
+ * copyright (c) 2007 Bobby Bingham
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavcodec/imgconvert.h"
+#include "avfilter.h"
+
+/* TODO: buffer pool.  see comment for avfilter_default_get_video_buffer() */
+void avfilter_default_free_video_buffer(AVFilterPic *pic)
+{
+    av_free(pic->data[0]);
+    av_free(pic);
+}
+
+/* TODO: set the buffer's priv member to a context structure for the whole
+ * filter chain.  This will allow for a buffer pool instead of the constant
+ * alloc & free cycle currently implemented. */
+AVFilterPicRef *avfilter_default_get_video_buffer(AVFilterLink *link, int perms)
+{
+    AVFilterPic *pic = av_mallocz(sizeof(AVFilterPic));
+    AVFilterPicRef *ref = av_mallocz(sizeof(AVFilterPicRef));
+    int i, tempsize;
+    char *buf;
+
+    ref->pic   = pic;
+    ref->w     = link->w;
+    ref->h     = link->h;
+
+    /* make sure the buffer gets read permission or it's useless for output */
+    ref->perms = perms | AV_PERM_READ;
+
+    pic->refcount = 1;
+    pic->format   = link->format;
+    pic->free     = avfilter_default_free_video_buffer;
+    ff_fill_linesize((AVPicture *)pic, pic->format, ref->w);
+
+    for (i=0; i<4;i++)
+        pic->linesize[i] = FFALIGN(pic->linesize[i], 16);
+
+    tempsize = ff_fill_pointer((AVPicture *)pic, NULL, pic->format, ref->h);
+    buf = av_malloc(tempsize);
+    ff_fill_pointer((AVPicture *)pic, buf, pic->format, ref->h);
+
+    memcpy(ref->data,     pic->data,     sizeof(pic->data));
+    memcpy(ref->linesize, pic->linesize, sizeof(pic->linesize));
+
+    return ref;
+}
+
+void avfilter_default_start_frame(AVFilterLink *link, AVFilterPicRef *picref)
+{
+    AVFilterLink *out = NULL;
+
+    if(link->dst->output_count)
+        out = link->dst->outputs[0];
+
+    if(out) {
+        out->outpic      = avfilter_get_video_buffer(out, AV_PERM_WRITE);
+        out->outpic->pts = picref->pts;
+        avfilter_start_frame(out, avfilter_ref_pic(out->outpic, ~0));
+    }
+}
+
+void avfilter_default_draw_slice(AVFilterLink *link, int y, int h)
+{
+    AVFilterLink *out = NULL;
+
+    if(link->dst->output_count)
+        out = link->dst->outputs[0];
+
+    if(out)
+        avfilter_draw_slice(out, y, h);
+}
+
+void avfilter_default_end_frame(AVFilterLink *link)
+{
+    AVFilterLink *out = NULL;
+
+    if(link->dst->output_count)
+        out = link->dst->outputs[0];
+
+    avfilter_unref_pic(link->cur_pic);
+    link->cur_pic = NULL;
+
+    if(out) {
+        if(out->outpic) {
+            avfilter_unref_pic(out->outpic);
+            out->outpic = NULL;
+        }
+        avfilter_end_frame(out);
+    }
+}
+
+/**
+ * default config_link() implementation for output video links to simplify
+ * the implementation of one input one output video filters */
+int avfilter_default_config_output_link(AVFilterLink *link)
+{
+    if(link->src->input_count && link->src->inputs[0]) {
+        link->w = link->src->inputs[0]->w;
+        link->h = link->src->inputs[0]->h;
+    } else {
+        /* XXX: any non-simple filter which would cause this branch to be taken
+         * really should implement its own config_props() for this link. */
+        return -1;
+    }
+
+    return 0;
+}
+
+/**
+ * A helper for query_formats() which sets all links to the same list of
+ * formats. If there are no links hooked to this filter, the list of formats is
+ * freed.
+ *
+ * FIXME: this will need changed for filters with a mix of pad types
+ * (video + audio, etc)
+ */
+void avfilter_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats)
+{
+    int count = 0, i;
+
+    for(i = 0; i < ctx->input_count; i ++) {
+        if(ctx->inputs[i]) {
+            avfilter_formats_ref(formats, &ctx->inputs[i]->out_formats);
+            count ++;
+        }
+    }
+    for(i = 0; i < ctx->output_count; i ++) {
+        if(ctx->outputs[i]) {
+            avfilter_formats_ref(formats, &ctx->outputs[i]->in_formats);
+            count ++;
+        }
+    }
+
+    if(!count) {
+        av_free(formats->formats);
+        av_free(formats->refs);
+        av_free(formats);
+    }
+}
+
+int avfilter_default_query_formats(AVFilterContext *ctx)
+{
+    avfilter_set_common_formats(ctx, avfilter_all_colorspaces());
+    return 0;
+}
+

Added: afilters/formats.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ afilters/formats.c	Thu May 28 05:19:12 2009	(r4319)
@@ -0,0 +1,148 @@
+/*
+ * Filter layer - format negotiation
+ * copyright (c) 2007 Bobby Bingham
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "avfilter.h"
+
+/**
+ * Add all refs from a to ret and destroy a.
+ */
+static void merge_ref(AVFilterFormats *ret, AVFilterFormats *a)
+{
+    int i;
+
+    for(i = 0; i < a->refcount; i ++) {
+        ret->refs[ret->refcount] = a->refs[i];
+        *ret->refs[ret->refcount++] = ret;
+    }
+
+    av_free(a->refs);
+    av_free(a->formats);
+    av_free(a);
+}
+
+AVFilterFormats *avfilter_merge_formats(AVFilterFormats *a, AVFilterFormats *b)
+{
+    AVFilterFormats *ret;
+    unsigned i, j, k = 0;
+
+    ret = av_mallocz(sizeof(AVFilterFormats));
+
+    /* merge list of formats */
+    ret->formats = av_malloc(sizeof(*ret->formats) * FFMIN(a->format_count,
+                                                           b->format_count));
+    for(i = 0; i < a->format_count; i ++)
+        for(j = 0; j < b->format_count; j ++)
+            if(a->formats[i] == b->formats[j])
+                ret->formats[k++] = a->formats[i];
+
+    ret->format_count = k;
+    /* check that there was at least one common format */
+    if(!ret->format_count) {
+        av_free(ret->formats);
+        av_free(ret);
+        return NULL;
+    }
+
+    ret->refs = av_malloc(sizeof(AVFilterFormats**)*(a->refcount+b->refcount));
+
+    merge_ref(ret, a);
+    merge_ref(ret, b);
+
+    return ret;
+}
+
+AVFilterFormats *avfilter_make_format_list(int len, ...)
+{
+    AVFilterFormats *ret;
+    int i;
+    va_list vl;
+
+    ret = av_mallocz(sizeof(AVFilterFormats));
+    ret->formats = av_malloc(sizeof(*ret->formats) * len);
+    ret->format_count = len;
+
+    va_start(vl, len);
+    for(i = 0; i < len; i ++)
+        ret->formats[i] = va_arg(vl, int);
+    va_end(vl);
+
+    return ret;
+}
+
+AVFilterFormats *avfilter_all_colorspaces(void)
+{
+    AVFilterFormats *ret;
+    int i;
+
+    ret = av_mallocz(sizeof(AVFilterFormats));
+    ret->formats = av_malloc(sizeof(*ret->formats) * PIX_FMT_NB);
+    ret->format_count = PIX_FMT_NB;
+
+    for(i = 0; i < PIX_FMT_NB; i ++)
+        ret->formats[i] = i;
+
+    return ret;
+}
+
+void avfilter_formats_ref(AVFilterFormats *f, AVFilterFormats **ref)
+{
+    *ref = f;
+    f->refs = av_realloc(f->refs, sizeof(AVFilterFormats**) * ++f->refcount);
+    f->refs[f->refcount-1] = ref;
+}
+
+static int find_ref_index(AVFilterFormats **ref)
+{
+    int i;
+    for(i = 0; i < (*ref)->refcount; i ++)
+        if((*ref)->refs[i] == ref)
+            return i;
+    return -1;
+}
+
+void avfilter_formats_unref(AVFilterFormats **ref)
+{
+    int idx = find_ref_index(ref);
+
+    if(idx >= 0)
+        memmove((*ref)->refs + idx, (*ref)->refs + idx+1,
+            sizeof(AVFilterFormats**) * ((*ref)->refcount-idx-1));
+
+    if(!--(*ref)->refcount) {
+        av_free((*ref)->formats);
+        av_free((*ref)->refs);
+        av_free(*ref);
+    }
+    *ref = NULL;
+}
+
+void avfilter_formats_changeref(AVFilterFormats **oldref,
+                                AVFilterFormats **newref)
+{
+    int idx = find_ref_index(oldref);
+
+    if(idx >= 0) {
+        (*oldref)->refs[idx] = newref;
+        *newref = *oldref;
+        *oldref = NULL;
+    }
+}
+

Added: afilters/graphparser.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ afilters/graphparser.c	Thu May 28 05:19:12 2009	(r4319)
@@ -0,0 +1,357 @@
+/*
+ * filter graph parser
+ * copyright (c) 2008 Vitor Sessak
+ * copyright (c) 2007 Bobby Bingham
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <ctype.h>
+#include <string.h>
+
+#include "graphparser.h"
+#include "avfilter.h"
+#include "avfiltergraph.h"
+#include "parseutils.h"
+
+#define WHITESPACES " \n\t"
+
+static int link_filter(AVFilterContext *src, int srcpad,
+                       AVFilterContext *dst, int dstpad,
+                       AVClass *log_ctx)
+{
+    if(avfilter_link(src, srcpad, dst, dstpad)) {
+        av_log(log_ctx, AV_LOG_ERROR,
+               "cannot create the link %s:%d -> %s:%d\n",
+               src->filter->name, srcpad, dst->filter->name, dstpad);
+        return -1;
+    }
+
+    return 0;
+}
+
+/**
+ * Parse "[linkname]"
+ * @param name a pointer (that need to be free'd after use) to the name between
+ *        parenthesis
+ */
+static char *parse_link_name(const char **buf, AVClass *log_ctx)
+{
+    const char *start = *buf;
+    char *name;
+    (*buf)++;
+
+    name = av_get_token(buf, "]");
+
+    if(!name[0]) {
+        av_log(log_ctx, AV_LOG_ERROR,
+               "Bad (empty?) label found in the following: \"%s\".\n", start);
+        goto fail;
+    }
+
+    if(*(*buf)++ != ']') {
+        av_log(log_ctx, AV_LOG_ERROR,
+               "Mismatched '[' found in the following: \"%s\".\n", start);
+    fail:
+        av_freep(&name);
+    }
+
+    return name;
+}
+
+static AVFilterContext *create_filter(AVFilterGraph *ctx, int index,
+                                      const char *filt_name, const char *args,
+                                      AVClass *log_ctx)
+{
+    AVFilterContext *filt_ctx;
+
+    AVFilter *filt;
+    char inst_name[30];
+
+    snprintf(inst_name, sizeof(inst_name), "Parsed filter %d", index);
+
+    filt = avfilter_get_by_name(filt_name);
+
+    if(!filt) {
+        av_log(log_ctx, AV_LOG_ERROR,
+               "no such filter: '%s'\n", filt_name);
+        return NULL;
+    }
+
+    filt_ctx = avfilter_open(filt, inst_name);
+    if(!filt_ctx) {
+        av_log(log_ctx, AV_LOG_ERROR,
+               "error creating filter '%s'\n", filt_name);
+        return NULL;
+    }
+
+    if(avfilter_graph_add_filter(ctx, filt_ctx) < 0) {
+        avfilter_destroy(filt_ctx);
+        return NULL;
+    }
+
+    if(avfilter_init_filter(filt_ctx, args, NULL)) {
+        av_log(log_ctx, AV_LOG_ERROR,
+               "error initializing filter '%s' with args '%s'\n", filt_name, args);
+        return NULL;
+    }
+
+    return filt_ctx;
+}
+
+/**
+ * Parse "filter=params"
+ */
+static AVFilterContext *parse_filter(const char **buf, AVFilterGraph *graph,
+                                     int index, AVClass *log_ctx)
+{
+    char *opts = NULL;
+    char *name = av_get_token(buf, "=,[");
+    AVFilterContext *ret;
+
+    if(**buf == '=') {
+        (*buf)++;
+        opts = av_get_token(buf, "[],\n");
+    }
+
+    ret = create_filter(graph, index, name, opts, log_ctx);
+    av_free(name);
+    av_free(opts);
+    return ret;
+}
+
+static void free_inout(AVFilterInOut *head)
+{
+    while(head) {
+        AVFilterInOut *next = head->next;
+        av_free(head->name);
+        av_free(head);
+        head = next;
+    }
+}
+
+static AVFilterInOut *extract_inout(const char *label, AVFilterInOut **links)
+{
+    AVFilterInOut *ret;
+
+    while(*links && strcmp((*links)->name, label))
+        links = &((*links)->next);
+
+    ret = *links;
+
+    if(ret)
+        *links = ret->next;
+
+    return ret;
+}
+
+static void insert_inout(AVFilterInOut **inouts, AVFilterInOut *element)
+{
+    element->next = *inouts;
+    *inouts = element;
+}
+
+static int link_filter_inouts(AVFilterContext *filter,
+                              AVFilterInOut **curr_inputs,
+                              AVFilterInOut **open_inputs, AVClass *log_ctx)
+{
+    int pad = filter->input_count;
+
+    while(pad--) {
+        AVFilterInOut *p = *curr_inputs;
+        if(!p) {
+            av_log(log_ctx, AV_LOG_ERROR,
+                   "Not enough inputs specified for the \"%s\" filter.\n",
+                   filter->filter->name);
+            return -1;
+        }
+
+        *curr_inputs = (*curr_inputs)->next;
+
+        if(p->filter) {
+            if(link_filter(p->filter, p->pad_idx, filter, pad, log_ctx))
+                return -1;
+            av_free(p->name);
+            av_free(p);
+        } else {
+            p->filter = filter;
+            p->pad_idx = pad;
+            insert_inout(open_inputs, p);
+        }
+    }
+
+    if(*curr_inputs) {
+        av_log(log_ctx, AV_LOG_ERROR,
+               "Too many inputs specified for the \"%s\" filter.\n",
+               filter->filter->name);
+        return -1;
+    }
+
+    pad = filter->output_count;
+    while(pad--) {
+        AVFilterInOut *currlinkn = av_mallocz(sizeof(AVFilterInOut));
+        currlinkn->filter  = filter;
+        currlinkn->pad_idx = pad;
+        insert_inout(curr_inputs, currlinkn);
+    }
+
+    return 0;
+}
+
+static int parse_inputs(const char **buf, AVFilterInOut **curr_inputs,
+                        AVFilterInOut **open_outputs, AVClass *log_ctx)
+{
+    int pad = 0;
+
+    while(**buf == '[') {
+        char *name = parse_link_name(buf, log_ctx);
+        AVFilterInOut *match;
+
+        if(!name)
+            return -1;
+
+        /* First check if the label is not in the open_outputs list */
+        match = extract_inout(name, open_outputs);
+
+        if(match) {
+            av_free(name);
+        } else {
+            /* Not in the list, so add it as an input */
+            match = av_mallocz(sizeof(AVFilterInOut));
+            match->name    = name;
+            match->pad_idx = pad;
+        }
+
+        insert_inout(curr_inputs, match);
+
+        *buf += strspn(*buf, WHITESPACES);
+        pad++;
+    }
+
+    return pad;
+}
+
+static int parse_outputs(const char **buf, AVFilterInOut **curr_inputs,
+                         AVFilterInOut **open_inputs,
+                         AVFilterInOut **open_outputs, AVClass *log_ctx)
+{
+    int pad = 0;
+
+    while(**buf == '[') {
+        char *name = parse_link_name(buf, log_ctx);
+        AVFilterInOut *match;
+
+        AVFilterInOut *input = *curr_inputs;
+        *curr_inputs = (*curr_inputs)->next;
+
+        if(!name)
+            return -1;
+
+        /* First check if the label is not in the open_inputs list */
+        match = extract_inout(name, open_inputs);
+
+        if(match) {
+            if(link_filter(input->filter, input->pad_idx,
+                           match->filter, match->pad_idx, log_ctx) < 0)
+                return -1;
+            av_free(match->name);
+            av_free(name);
+            av_free(match);
+            av_free(input);
+        } else {
+            /* Not in the list, so add the first input as a open_output */
+            input->name = name;
+            insert_inout(open_outputs, input);
+        }
+        *buf += strspn(*buf, WHITESPACES);
+        pad++;
+    }
+
+    return pad;
+}
+
+int avfilter_graph_parse(AVFilterGraph *graph, const char *filters,
+                         AVFilterInOut *open_inputs,
+                         AVFilterInOut *open_outputs, AVClass *log_ctx)
+{
+    int index = 0;
+    char chr = 0;
+
+    AVFilterInOut *curr_inputs = NULL;
+
+    do {
+        AVFilterContext *filter;
+        filters += strspn(filters, WHITESPACES);
+
+        if(parse_inputs(&filters, &curr_inputs, &open_outputs, log_ctx) < 0)
+            goto fail;
+
+        filter = parse_filter(&filters, graph, index, log_ctx);
+
+        if(!filter)
+            goto fail;
+
+        if(filter->input_count == 1 && !curr_inputs && !index) {
+            /* First input can be omitted if it is "[in]" */
+            const char *tmp = "[in]";
+            if(parse_inputs(&tmp, &curr_inputs, &open_outputs, log_ctx) < 0)
+                goto fail;
+        }
+
+        if(link_filter_inouts(filter, &curr_inputs, &open_inputs, log_ctx) < 0)
+            goto fail;
+
+        if(parse_outputs(&filters, &curr_inputs, &open_inputs, &open_outputs,
+                         log_ctx) < 0)
+            goto fail;
+
+        filters += strspn(filters, WHITESPACES);
+        chr = *filters++;
+
+        if(chr == ';' && curr_inputs) {
+            av_log(log_ctx, AV_LOG_ERROR,
+                   "Could not find a output to link when parsing \"%s\"\n",
+                   filters - 1);
+            goto fail;
+        }
+        index++;
+    } while(chr == ',' || chr == ';');
+
+    if (chr) {
+        av_log(log_ctx, AV_LOG_ERROR,
+               "Unable to parse graph description substring: \"%s\"\n",
+               filters - 1);
+        goto fail;
+    }
+
+    if(open_inputs && !strcmp(open_inputs->name, "out") && curr_inputs) {
+        /* Last output can be omitted if it is "[out]" */
+        const char *tmp = "[out]";
+        if(parse_outputs(&tmp, &curr_inputs, &open_inputs,
+                         &open_outputs, log_ctx) < 0)
+            goto fail;
+    }
+
+    return 0;
+
+ fail:
+    avfilter_graph_destroy(graph);
+    free_inout(open_inputs);
+    free_inout(open_outputs);
+    free_inout(curr_inputs);
+    return -1;
+}

Added: afilters/graphparser.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ afilters/graphparser.h	Thu May 28 05:19:12 2009	(r4319)
@@ -0,0 +1,52 @@
+/*
+ * Filter graph parser
+ * copyright (c) 2007 Bobby Bingham
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVFILTER_GRAPHPARSER_H
+#define AVFILTER_GRAPHPARSER_H
+
+#include "avfilter.h"
+#include "avfiltergraph.h"
+
+/**
+ * A linked-list of the inputs/outputs of the filter chain.
+ */
+typedef struct AVFilterInOut {
+    const char *name;
+    AVFilterContext *filter;
+    int pad_idx;
+
+    struct AVFilterInOut *next;
+} AVFilterInOut;
+
+/**
+ * Adds a graph described by a string to a graph.
+ *
+ * @param graph   the filter graph where to link the parsed graph context
+ * @param filters string to be parsed
+ * @param inputs  linked list to the inputs of the graph
+ * @param outputs linked list to the outputs of the graph
+ * @return        zero on success, -1 on error
+ */
+int avfilter_graph_parse(AVFilterGraph *graph, const char *filters,
+                         AVFilterInOut *inputs, AVFilterInOut *outputs,
+                         AVClass *log_ctx);
+
+#endif  /* AVFILTER_GRAPHPARSER_H */

Added: afilters/parseutils.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ afilters/parseutils.c	Thu May 28 05:19:12 2009	(r4319)
@@ -0,0 +1,472 @@
+/*
+ * copyright (c) 2009 Stefano Sabatini
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file libavfilter/parseutils.c
+ * parsing utils
+ */
+
+#include <strings.h>
+#include "libavutil/avutil.h"
+#include "libavutil/random_seed.h"
+#include "parseutils.h"
+
+#define WHITESPACES " \n\t"
+
+char *av_get_token(const char **buf, const char *term)
+{
+    char *out = av_malloc(strlen(*buf) + 1);
+    char *ret= out, *end= out;
+    const char *p = *buf;
+    p += strspn(p, WHITESPACES);
+
+    while(*p && !strspn(p, term)) {
+        char c = *p++;
+        if(c == '\\' && *p){
+            *out++ = *p++;
+            end= out;
+        }else if(c == '\''){
+            while(*p && *p != '\'')
+                *out++ = *p++;
+            if(*p){
+                p++;
+                end= out;
+            }
+        }else{
+            *out++ = c;
+        }
+    }
+
+    do{
+        *out-- = 0;
+    }while(out >= end && strspn(out, WHITESPACES));
+
+    *buf = p;
+
+    return ret;
+}
+
+typedef struct {
+    const char *name;            ///< a string representing the name of the color
+    uint8_t     rgba_color[4];   ///< RGBA values for the color
+} ColorEntry;
+
+static ColorEntry color_table[] = {
+    { "AliceBlue",            { 0xF0, 0xF8, 0xFF } },
+    { "AntiqueWhite",         { 0xFA, 0xEB, 0xD7 } },
+    { "Aqua",                 { 0x00, 0xFF, 0xFF } },
+    { "Aquamarine",           { 0x7F, 0xFF, 0xD4 } },
+    { "Azure",                { 0xF0, 0xFF, 0xFF } },
+    { "Beige",                { 0xF5, 0xF5, 0xDC } },
+    { "Bisque",               { 0xFF, 0xE4, 0xC4 } },
+    { "Black",                { 0x00, 0x00, 0x00 } },
+    { "BlanchedAlmond",       { 0xFF, 0xEB, 0xCD } },
+    { "Blue",                 { 0x00, 0x00, 0xFF } },
+    { "BlueViolet",           { 0x8A, 0x2B, 0xE2 } },
+    { "Brown",                { 0xA5, 0x2A, 0x2A } },
+    { "BurlyWood",            { 0xDE, 0xB8, 0x87 } },
+    { "CadetBlue",            { 0x5F, 0x9E, 0xA0 } },
+    { "Chartreuse",           { 0x7F, 0xFF, 0x00 } },
+    { "Chocolate",            { 0xD2, 0x69, 0x1E } },
+    { "Coral",                { 0xFF, 0x7F, 0x50 } },
+    { "CornflowerBlue",       { 0x64, 0x95, 0xED } },
+    { "Cornsilk",             { 0xFF, 0xF8, 0xDC } },
+    { "Crimson",              { 0xDC, 0x14, 0x3C } },
+    { "Cyan",                 { 0x00, 0xFF, 0xFF } },
+    { "DarkBlue",             { 0x00, 0x00, 0x8B } },
+    { "DarkCyan",             { 0x00, 0x8B, 0x8B } },
+    { "DarkGoldenRod",        { 0xB8, 0x86, 0x0B } },
+    { "DarkGray",             { 0xA9, 0xA9, 0xA9 } },
+    { "DarkGreen",            { 0x00, 0x64, 0x00 } },
+    { "DarkKhaki",            { 0xBD, 0xB7, 0x6B } },
+    { "DarkMagenta",          { 0x8B, 0x00, 0x8B } },
+    { "DarkOliveGreen",       { 0x55, 0x6B, 0x2F } },
+    { "Darkorange",           { 0xFF, 0x8C, 0x00 } },
+    { "DarkOrchid",           { 0x99, 0x32, 0xCC } },
+    { "DarkRed",              { 0x8B, 0x00, 0x00 } },
+    { "DarkSalmon",           { 0xE9, 0x96, 0x7A } },
+    { "DarkSeaGreen",         { 0x8F, 0xBC, 0x8F } },
+    { "DarkSlateBlue",        { 0x48, 0x3D, 0x8B } },
+    { "DarkSlateGray",        { 0x2F, 0x4F, 0x4F } },
+    { "DarkTurquoise",        { 0x00, 0xCE, 0xD1 } },
+    { "DarkViolet",           { 0x94, 0x00, 0xD3 } },
+    { "DeepPink",             { 0xFF, 0x14, 0x93 } },
+    { "DeepSkyBlue",          { 0x00, 0xBF, 0xFF } },
+    { "DimGray",              { 0x69, 0x69, 0x69 } },
+    { "DodgerBlue",           { 0x1E, 0x90, 0xFF } },
+    { "FireBrick",            { 0xB2, 0x22, 0x22 } },
+    { "FloralWhite",          { 0xFF, 0xFA, 0xF0 } },
+    { "ForestGreen",          { 0x22, 0x8B, 0x22 } },
+    { "Fuchsia",              { 0xFF, 0x00, 0xFF } },
+    { "Gainsboro",            { 0xDC, 0xDC, 0xDC } },
+    { "GhostWhite",           { 0xF8, 0xF8, 0xFF } },
+    { "Gold",                 { 0xFF, 0xD7, 0x00 } },
+    { "GoldenRod",            { 0xDA, 0xA5, 0x20 } },
+    { "Gray",                 { 0x80, 0x80, 0x80 } },
+    { "Green",                { 0x00, 0x80, 0x00 } },
+    { "GreenYellow",          { 0xAD, 0xFF, 0x2F } },
+    { "HoneyDew",             { 0xF0, 0xFF, 0xF0 } },
+    { "HotPink",              { 0xFF, 0x69, 0xB4 } },
+    { "IndianRed",            { 0xCD, 0x5C, 0x5C } },
+    { "Indigo",               { 0x4B, 0x00, 0x82 } },
+    { "Ivory",                { 0xFF, 0xFF, 0xF0 } },
+    { "Khaki",                { 0xF0, 0xE6, 0x8C } },
+    { "Lavender",             { 0xE6, 0xE6, 0xFA } },
+    { "LavenderBlush",        { 0xFF, 0xF0, 0xF5 } },
+    { "LawnGreen",            { 0x7C, 0xFC, 0x00 } },
+    { "LemonChiffon",         { 0xFF, 0xFA, 0xCD } },
+    { "LightBlue",            { 0xAD, 0xD8, 0xE6 } },
+    { "LightCoral",           { 0xF0, 0x80, 0x80 } },
+    { "LightCyan",            { 0xE0, 0xFF, 0xFF } },
+    { "LightGoldenRodYellow", { 0xFA, 0xFA, 0xD2 } },
+    { "LightGrey",            { 0xD3, 0xD3, 0xD3 } },
+    { "LightGreen",           { 0x90, 0xEE, 0x90 } },
+    { "LightPink",            { 0xFF, 0xB6, 0xC1 } },
+    { "LightSalmon",          { 0xFF, 0xA0, 0x7A } },
+    { "LightSeaGreen",        { 0x20, 0xB2, 0xAA } },
+    { "LightSkyBlue",         { 0x87, 0xCE, 0xFA } },
+    { "LightSlateGray",       { 0x77, 0x88, 0x99 } },
+    { "LightSteelBlue",       { 0xB0, 0xC4, 0xDE } },
+    { "LightYellow",          { 0xFF, 0xFF, 0xE0 } },
+    { "Lime",                 { 0x00, 0xFF, 0x00 } },
+    { "LimeGreen",            { 0x32, 0xCD, 0x32 } },
+    { "Linen",                { 0xFA, 0xF0, 0xE6 } },
+    { "Magenta",              { 0xFF, 0x00, 0xFF } },
+    { "Maroon",               { 0x80, 0x00, 0x00 } },
+    { "MediumAquaMarine",     { 0x66, 0xCD, 0xAA } },
+    { "MediumBlue",           { 0x00, 0x00, 0xCD } },
+    { "MediumOrchid",         { 0xBA, 0x55, 0xD3 } },
+    { "MediumPurple",         { 0x93, 0x70, 0xD8 } },
+    { "MediumSeaGreen",       { 0x3C, 0xB3, 0x71 } },
+    { "MediumSlateBlue",      { 0x7B, 0x68, 0xEE } },
+    { "MediumSpringGreen",    { 0x00, 0xFA, 0x9A } },
+    { "MediumTurquoise",      { 0x48, 0xD1, 0xCC } },
+    { "MediumVioletRed",      { 0xC7, 0x15, 0x85 } },
+    { "MidnightBlue",         { 0x19, 0x19, 0x70 } },
+    { "MintCream",            { 0xF5, 0xFF, 0xFA } },
+    { "MistyRose",            { 0xFF, 0xE4, 0xE1 } },
+    { "Moccasin",             { 0xFF, 0xE4, 0xB5 } },
+    { "NavajoWhite",          { 0xFF, 0xDE, 0xAD } },
+    { "Navy",                 { 0x00, 0x00, 0x80 } },
+    { "OldLace",              { 0xFD, 0xF5, 0xE6 } },
+    { "Olive",                { 0x80, 0x80, 0x00 } },
+    { "OliveDrab",            { 0x6B, 0x8E, 0x23 } },
+    { "Orange",               { 0xFF, 0xA5, 0x00 } },
+    { "OrangeRed",            { 0xFF, 0x45, 0x00 } },
+    { "Orchid",               { 0xDA, 0x70, 0xD6 } },
+    { "PaleGoldenRod",        { 0xEE, 0xE8, 0xAA } },
+    { "PaleGreen",            { 0x98, 0xFB, 0x98 } },
+    { "PaleTurquoise",        { 0xAF, 0xEE, 0xEE } },
+    { "PaleVioletRed",        { 0xD8, 0x70, 0x93 } },
+    { "PapayaWhip",           { 0xFF, 0xEF, 0xD5 } },
+    { "PeachPuff",            { 0xFF, 0xDA, 0xB9 } },
+    { "Peru",                 { 0xCD, 0x85, 0x3F } },
+    { "Pink",                 { 0xFF, 0xC0, 0xCB } },
+    { "Plum",                 { 0xDD, 0xA0, 0xDD } },
+    { "PowderBlue",           { 0xB0, 0xE0, 0xE6 } },
+    { "Purple",               { 0x80, 0x00, 0x80 } },
+    { "Red",                  { 0xFF, 0x00, 0x00 } },
+    { "RosyBrown",            { 0xBC, 0x8F, 0x8F } },
+    { "RoyalBlue",            { 0x41, 0x69, 0xE1 } },
+    { "SaddleBrown",          { 0x8B, 0x45, 0x13 } },
+    { "Salmon",               { 0xFA, 0x80, 0x72 } },
+    { "SandyBrown",           { 0xF4, 0xA4, 0x60 } },
+    { "SeaGreen",             { 0x2E, 0x8B, 0x57 } },
+    { "SeaShell",             { 0xFF, 0xF5, 0xEE } },
+    { "Sienna",               { 0xA0, 0x52, 0x2D } },
+    { "Silver",               { 0xC0, 0xC0, 0xC0 } },
+    { "SkyBlue",              { 0x87, 0xCE, 0xEB } },
+    { "SlateBlue",            { 0x6A, 0x5A, 0xCD } },
+    { "SlateGray",            { 0x70, 0x80, 0x90 } },
+    { "Snow",                 { 0xFF, 0xFA, 0xFA } },
+    { "SpringGreen",          { 0x00, 0xFF, 0x7F } },
+    { "SteelBlue",            { 0x46, 0x82, 0xB4 } },
+    { "Tan",                  { 0xD2, 0xB4, 0x8C } },
+    { "Teal",                 { 0x00, 0x80, 0x80 } },
+    { "Thistle",              { 0xD8, 0xBF, 0xD8 } },
+    { "Tomato",               { 0xFF, 0x63, 0x47 } },
+    { "Turquoise",            { 0x40, 0xE0, 0xD0 } },
+    { "Violet",               { 0xEE, 0x82, 0xEE } },
+    { "Wheat",                { 0xF5, 0xDE, 0xB3 } },
+    { "White",                { 0xFF, 0xFF, 0xFF } },
+    { "WhiteSmoke",           { 0xF5, 0xF5, 0xF5 } },
+    { "Yellow",               { 0xFF, 0xFF, 0x00 } },
+    { "YellowGreen",          { 0x9A, 0xCD, 0x32 } },
+};
+
+static int color_table_compare(const void *lhs, const void *rhs)
+{
+    return strcasecmp(lhs, ((const ColorEntry *)rhs)->name);
+}
+
+int av_parse_color(uint8_t *rgba_color, const char *color_string, void *log_ctx)
+{
+    if (!strcasecmp(color_string, "random") || !strcasecmp(color_string, "bikeshed")) {
+        int rgba = ff_random_get_seed();
+        rgba_color[0] = rgba >> 24;
+        rgba_color[1] = rgba >> 16;
+        rgba_color[2] = rgba >> 8;
+        rgba_color[3] = rgba;
+    } else
+    if (!strncmp(color_string, "0x", 2)) {
+        char *tail;
+        int len = strlen(color_string);
+        int rgba = strtol(color_string, &tail, 16);
+
+        if (*tail || (len != 8 && len != 10)) {
+            av_log(log_ctx, AV_LOG_ERROR, "Invalid 0xRRGGBB[AA] color string: '%s'\n", color_string);
+            return -1;
+        }
+        if (len == 10) {
+            rgba_color[3] = rgba;
+            rgba >>= 8;
+        }
+        rgba_color[0] = rgba >> 16;
+        rgba_color[1] = rgba >> 8;
+        rgba_color[2] = rgba;
+    } else {
+        const ColorEntry *entry = bsearch(color_string,
+                                          color_table,
+                                          FF_ARRAY_ELEMS(color_table),
+                                          sizeof(ColorEntry),
+                                          color_table_compare);
+        if (!entry) {
+            av_log(log_ctx, AV_LOG_ERROR, "Cannot find color '%s'\n", color_string);
+            return -1;
+        }
+        memcpy(rgba_color, entry->rgba_color, 4);
+    }
+
+    return 0;
+}
+
+/**
+ * Stores the value in the field in ctx that is named like key.
+ * ctx must be an AVClass context, storing is done using AVOptions.
+ *
+ * @param buf the string to parse, buf will be updated to point at the
+ * separator just after the parsed key/value pair
+ * @param key_val_sep a 0-terminated list of characters used to
+ * separate key from value
+ * @param pairs_sep a 0-terminated list of characters used to separate
+ * two pairs from each other
+ * @return 0 if the key/value pair has been successfully parsed and
+ * set, or a negative value corresponding to an AVERROR code in case
+ * of error:
+ * AVERROR(EINVAL) if the key/value pair cannot be parsed,
+ * the error code issued by av_set_string3() if the key/value pair
+ * cannot be set
+ */
+static int parse_key_value_pair(void *ctx, const char **buf,
+                                const char *key_val_sep, const char *pairs_sep)
+{
+    char *key = av_get_token(buf, key_val_sep);
+    char *val;
+    int ret;
+
+    if (*key && strspn(*buf, key_val_sep)) {
+        (*buf)++;
+        val = av_get_token(buf, pairs_sep);
+    } else {
+        av_log(ctx, AV_LOG_ERROR, "Missing key or no key/value separator found after key '%s'\n", key);
+        av_free(key);
+        return AVERROR(EINVAL);
+    }
+
+    av_log(ctx, AV_LOG_DEBUG, "Setting value '%s' for key '%s'\n", val, key);
+
+    ret = av_set_string3(ctx, key, val, 1, NULL);
+
+    av_free(key);
+    av_free(val);
+    return ret;
+}
+
+int av_set_options_string(void *ctx, const char *opts,
+                          const char *key_val_sep, const char *pairs_sep)
+{
+    int ret, count = 0;
+
+    while (*opts) {
+        if ((ret = parse_key_value_pair(ctx, &opts, key_val_sep, pairs_sep)) < 0)
+            return ret;
+        count++;
+
+        if (*opts)
+            opts++;
+    }
+
+    return count;
+}
+
+#ifdef TEST
+
+#undef printf
+
+typedef struct TestContext
+{
+    const AVClass *class;
+    int num;
+    int toggle;
+    char *string;
+    int flags;
+    AVRational rational;
+} TestContext;
+
+#define OFFSET(x) offsetof(TestContext, x)
+
+#define TEST_FLAG_COOL 01
+#define TEST_FLAG_LAME 02
+#define TEST_FLAG_MU   04
+
+static const AVOption test_options[]= {
+{"num",      "set num",        OFFSET(num),      FF_OPT_TYPE_INT,      0,              0,        100                 },
+{"toggle",   "set toggle",     OFFSET(toggle),   FF_OPT_TYPE_INT,      0,              0,        1                   },
+{"rational", "set rational",   OFFSET(rational), FF_OPT_TYPE_RATIONAL, 0,              0,        10                  },
+{"string",   "set string",     OFFSET(string),   FF_OPT_TYPE_STRING,   0,              CHAR_MIN, CHAR_MAX            },
+{"flags",    "set flags",      OFFSET(flags),    FF_OPT_TYPE_FLAGS,    0,              0,        INT_MAX, 0, "flags" },
+{"cool",     "set cool flag ", 0,                FF_OPT_TYPE_CONST,    TEST_FLAG_COOL, INT_MIN,  INT_MAX, 0, "flags" },
+{"lame",     "set lame flag ", 0,                FF_OPT_TYPE_CONST,    TEST_FLAG_LAME, INT_MIN,  INT_MAX, 0, "flags" },
+{"mu",       "set mu flag ",   0,                FF_OPT_TYPE_CONST,    TEST_FLAG_MU,   INT_MIN,  INT_MAX, 0, "flags" },
+{NULL},
+};
+
+static const char *test_get_name(void *ctx)
+{
+    return "test";
+}
+
+static const AVClass test_class = {
+    "TestContext",
+    test_get_name,
+    test_options
+};
+
+int main(void)
+{
+    int i;
+
+    const char *strings[] = {
+        "''",
+        "",
+        ":",
+        "\\",
+        "'",
+        "    ''    :",
+        "    ''  ''  :",
+        "foo   '' :",
+        "'foo'",
+        "foo     ",
+        "foo\\",
+        "foo':  blah:blah",
+        "foo\\:  blah:blah",
+        "foo\'",
+        "'foo :  '  :blahblah",
+        "\\ :blah",
+        "     foo",
+        "      foo       ",
+        "      foo     \\ ",
+        "foo ':blah",
+        " foo   bar    :   blahblah",
+        "\\f\\o\\o",
+        "'foo : \\ \\  '   : blahblah",
+        "'\\fo\\o:': blahblah",
+        "\\'fo\\o\\:':  foo  '  :blahblah"
+    };
+
+    for (i=0; i < FF_ARRAY_ELEMS(strings); i++) {
+        const char *p= strings[i];
+        printf("|%s|", p);
+        printf(" -> |%s|", av_get_token(&p, ":"));
+        printf(" + |%s|\n", p);
+    }
+
+    printf("\nTesting av_parse_color()\n");
+    {
+        uint8_t rgba[4];
+        const char *color_names[] = {
+            "bikeshed",
+            "RaNdOm",
+            "foo",
+            "red",
+            "Red ",
+            "RED",
+            "Violet",
+            "Yellow",
+            "Red",
+            "0x000000",
+            "0x0000000",
+            "0x3e34ff",
+            "0x3e34ffaa",
+            "0xffXXee",
+            "0xfoobar",
+            "0xffffeeeeeeee",
+        };
+
+        av_log_set_level(AV_LOG_DEBUG);
+
+        for (int i = 0;  i < FF_ARRAY_ELEMS(color_names); i++) {
+            if (av_parse_color(rgba, color_names[i], NULL) >= 0)
+                printf("%s -> R(%d) G(%d) B(%d) A(%d)\n", color_names[i], rgba[0], rgba[1], rgba[2], rgba[3]);
+        }
+    }
+
+    printf("\nTesting av_set_options_string()\n");
+    {
+        TestContext test_ctx;
+        const char *options[] = {
+            "",
+            ":",
+            "=",
+            "foo=:",
+            ":=foo",
+            "=foo",
+            "foo=",
+            "foo",
+            "foo=val",
+            "foo==val",
+            "toggle=:",
+            "string=:",
+            "toggle=1 : foo",
+            "toggle=100",
+            "toggle==1",
+            "flags=+mu-lame : num=42: toggle=0",
+            "num=42 : string=blahblah",
+            "rational=0 : rational=1/2 : rational=1/-1",
+            "rational=-1/0",
+        };
+
+        test_ctx.class = &test_class;
+        av_opt_set_defaults2(&test_ctx, 0, 0);
+        test_ctx.string = av_strdup("default");
+
+        av_log_set_level(AV_LOG_DEBUG);
+
+        for (i=0; i < FF_ARRAY_ELEMS(options); i++) {
+            av_log(&test_ctx, AV_LOG_DEBUG, "Setting options string '%s'\n", options[i]);
+            if (av_set_options_string(&test_ctx, options[i], "=", ":") < 0)
+                av_log(&test_ctx, AV_LOG_ERROR, "Error setting options string: '%s'\n", options[i]);
+            printf("\n");
+        }
+    }
+
+    return 0;
+}
+
+#endif

Added: afilters/parseutils.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ afilters/parseutils.h	Thu May 28 05:19:12 2009	(r4319)
@@ -0,0 +1,75 @@
+/*
+ * copyright (c) 2009 Stefano Sabatini
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file libavfilter/parseutils.h
+ * parsing utils
+ */
+
+#ifndef AVFILTER_PARSEUTILS_H
+#define AVFILTER_PARSEUTILS_H
+
+#include "libavcodec/opt.h"
+
+/**
+ * Unescapes the given string until a non escaped terminating char,
+ * and returns the token corresponding to the unescaped string.
+ *
+ * The normal \ and ' escaping is supported. Leading and trailing
+ * whitespaces are removed.
+ *
+ * @param term a 0-terminated list of terminating chars
+ * @param buf the buffer to parse, buf will be updated to point to the
+ * terminating char
+ * @return the malloced unescaped string, which must be av_freed by
+ * the user
+ */
+char *av_get_token(const char **buf, const char *term);
+
+/**
+ * Puts the RGBA values that correspond to color_string in rgba_color.
+ *
+ * @param color_string a string specifying a color. It can be the name of
+ * a color (case insensitive match) or a 0xRRGGBB[AA] sequence.
+ * The string "random" will result in a random color.
+ * @return >= 0 in case of success, a negative value in case of
+ * failure (for example if color_string cannot be parsed).
+ */
+int av_parse_color(uint8_t *rgba_color, const char *color_string, void *log_ctx);
+
+/**
+ * Parses the key/value pairs list in opts. For each key/value pair
+ * found, stores the value in the field in ctx that is named like the
+ * key. ctx must be an AVClass context, storing is done using
+ * AVOptions.
+ *
+ * @param key_val_sep a 0-terminated list of characters used to
+ * separate key from value
+ * @param pairs_sep a 0-terminated list of characters used to separate
+ * two pairs from each other
+ * @return the number of successfully set key/value pairs, or a negative
+ * value corresponding to an AVERROR code in case of error:
+ * AVERROR(EINVAL) if opts cannot be parsed,
+ * the error code issued by av_set_string3() if a key/value pair
+ * cannot be set
+ */
+int av_set_options_string(void *ctx, const char *opts,
+                          const char *key_val_sep, const char *pairs_sep);
+
+#endif  /* AVFILTER_PARSEUTILS_H */


More information about the FFmpeg-soc mailing list