Merge commit '1565cbc65cbb9f95c11367314a080068895e0cf0'
authorMichael Niedermayer <michaelni@gmx.at>
Thu, 11 Apr 2013 22:54:05 +0000 (00:54 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Thu, 11 Apr 2013 22:54:05 +0000 (00:54 +0200)
* commit '1565cbc65cbb9f95c11367314a080068895e0cf0':
  lavfi: make avfilter_free() remove the filter from its graph.

Conflicts:
libavfilter/avfilter.c
libavfilter/avfiltergraph.c
libavfilter/graphparser.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
libavfilter/avfilter.c
libavfilter/avfilter.h
libavfilter/avfiltergraph.c
libavfilter/graphparser.c
libavfilter/internal.h

diff --combined libavfilter/avfilter.c
@@@ -2,24 -2,25 +2,24 @@@
   * filter layer
   * Copyright (c) 2007 Bobby Bingham
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * 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 Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
 -/* #define DEBUG */
 -
 +#include "libavutil/avassert.h"
  #include "libavutil/avstring.h"
  #include "libavutil/channel_layout.h"
  #include "libavutil/common.h"
  #include "avfilter.h"
  #include "formats.h"
  #include "internal.h"
 -#include "video.h"
 +#include "audio.h"
 +
 +static int ff_filter_frame_framed(AVFilterLink *link, AVFrame *frame);
 +
 +void ff_tlog_ref(void *ctx, AVFrame *ref, int end)
 +{
 +    av_unused char buf[16];
 +    ff_tlog(ctx,
 +            "ref[%p buf:%p data:%p linesize[%d, %d, %d, %d] pts:%"PRId64" pos:%"PRId64,
 +            ref, ref->buf, ref->data[0],
 +            ref->linesize[0], ref->linesize[1], ref->linesize[2], ref->linesize[3],
 +            ref->pts, av_frame_get_pkt_pos(ref));
 +
 +    if (ref->width) {
 +        ff_tlog(ctx, " a:%d/%d s:%dx%d i:%c iskey:%d type:%c",
 +                ref->sample_aspect_ratio.num, ref->sample_aspect_ratio.den,
 +                ref->width, ref->height,
 +                !ref->interlaced_frame     ? 'P' :         /* Progressive  */
 +                ref->top_field_first ? 'T' : 'B',    /* Top / Bottom */
 +                ref->key_frame,
 +                av_get_picture_type_char(ref->pict_type));
 +    }
 +    if (ref->nb_samples) {
 +        ff_tlog(ctx, " cl:%"PRId64"d n:%d r:%d",
 +                ref->channel_layout,
 +                ref->nb_samples,
 +                ref->sample_rate);
 +    }
 +
 +    ff_tlog(ctx, "]%s", end ? "\n" : "");
 +}
  
  unsigned avfilter_version(void) {
 +    av_assert0(LIBAVFILTER_VERSION_MICRO >= 100);
      return LIBAVFILTER_VERSION_INT;
  }
  
  const char *avfilter_configuration(void)
  {
 -    return LIBAV_CONFIGURATION;
 +    return FFMPEG_CONFIGURATION;
  }
  
  const char *avfilter_license(void)
  {
  #define LICENSE_PREFIX "libavfilter license: "
 -    return LICENSE_PREFIX LIBAV_LICENSE + sizeof(LICENSE_PREFIX) - 1;
 +    return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1;
 +}
 +
 +void ff_command_queue_pop(AVFilterContext *filter)
 +{
 +    AVFilterCommand *c= filter->command_queue;
 +    av_freep(&c->arg);
 +    av_freep(&c->command);
 +    filter->command_queue= c->next;
 +    av_free(c);
  }
  
  void ff_insert_pad(unsigned idx, unsigned *count, size_t padidx_off,
@@@ -122,9 -83,8 +122,9 @@@ int avfilter_link(AVFilterContext *src
  
      if (src->output_pads[srcpad].type != dst->input_pads[dstpad].type) {
          av_log(src, AV_LOG_ERROR,
 -               "Media type mismatch between the '%s' filter output pad %d and the '%s' filter input pad %d\n",
 -               src->name, srcpad, dst->name, dstpad);
 +               "Media type mismatch between the '%s' filter output pad %d (%s) and the '%s' filter input pad %d (%s)\n",
 +               src->name, srcpad, (char *)av_x_if_null(av_get_media_type_string(src->output_pads[srcpad].type), "?"),
 +               dst->name, dstpad, (char *)av_x_if_null(av_get_media_type_string(dst-> input_pads[dstpad].type), "?"));
          return AVERROR(EINVAL);
      }
  
      link->srcpad  = &src->output_pads[srcpad];
      link->dstpad  = &dst->input_pads[dstpad];
      link->type    = src->output_pads[srcpad].type;
 -    assert(AV_PIX_FMT_NONE == -1 && AV_SAMPLE_FMT_NONE == -1);
 +    av_assert0(AV_PIX_FMT_NONE == -1 && AV_SAMPLE_FMT_NONE == -1);
      link->format  = -1;
  
      return 0;
  }
  
 +void avfilter_link_free(AVFilterLink **link)
 +{
 +    if (!*link)
 +        return;
 +
 +    av_frame_free(&(*link)->partial_buf);
 +
 +    av_freep(link);
 +}
 +
 +int avfilter_link_get_channels(AVFilterLink *link)
 +{
 +    return link->channels;
 +}
 +
 +void avfilter_link_set_closed(AVFilterLink *link, int closed)
 +{
 +    link->closed = closed;
 +}
 +
  int avfilter_insert_filter(AVFilterLink *link, AVFilterContext *filt,
                             unsigned filt_srcpad_idx, unsigned filt_dstpad_idx)
  {
      if (link->out_formats)
          ff_formats_changeref(&link->out_formats,
                                     &filt->outputs[filt_dstpad_idx]->out_formats);
 +
      if (link->out_samplerates)
          ff_formats_changeref(&link->out_samplerates,
                                     &filt->outputs[filt_dstpad_idx]->out_samplerates);
@@@ -208,13 -147,9 +208,13 @@@ int avfilter_config_links(AVFilterConte
  
      for (i = 0; i < filter->nb_inputs; i ++) {
          AVFilterLink *link = filter->inputs[i];
 +        AVFilterLink *inlink;
  
          if (!link) continue;
  
 +        inlink = link->src->nb_inputs ? link->src->inputs[0] : NULL;
 +        link->current_pts = AV_NOPTS_VALUE;
 +
          switch (link->init_state) {
          case AVLINK_INIT:
              continue;
                  return ret;
              }
  
 -            if (link->time_base.num == 0 && link->time_base.den == 0)
 -                link->time_base = link->src && link->src->nb_inputs ?
 -                    link->src->inputs[0]->time_base : AV_TIME_BASE_Q;
 +            switch (link->type) {
 +            case AVMEDIA_TYPE_VIDEO:
 +                if (!link->time_base.num && !link->time_base.den)
 +                    link->time_base = inlink ? inlink->time_base : AV_TIME_BASE_Q;
  
 -            if (link->type == AVMEDIA_TYPE_VIDEO) {
                  if (!link->sample_aspect_ratio.num && !link->sample_aspect_ratio.den)
 -                    link->sample_aspect_ratio = link->src->nb_inputs ?
 -                        link->src->inputs[0]->sample_aspect_ratio : (AVRational){1,1};
 +                    link->sample_aspect_ratio = inlink ?
 +                        inlink->sample_aspect_ratio : (AVRational){1,1};
  
 -                if (link->src->nb_inputs) {
 +                if (inlink && !link->frame_rate.num && !link->frame_rate.den)
 +                    link->frame_rate = inlink->frame_rate;
 +
 +                if (inlink) {
                      if (!link->w)
 -                        link->w = link->src->inputs[0]->w;
 +                        link->w = inlink->w;
                      if (!link->h)
 -                        link->h = link->src->inputs[0]->h;
 +                        link->h = inlink->h;
                  } else if (!link->w || !link->h) {
                      av_log(link->src, AV_LOG_ERROR,
                             "Video source filters must set their output link's "
                             "width and height\n");
                      return AVERROR(EINVAL);
                  }
 +                break;
 +
 +            case AVMEDIA_TYPE_AUDIO:
 +                if (inlink) {
 +                    if (!link->time_base.num && !link->time_base.den)
 +                        link->time_base = inlink->time_base;
 +                }
 +
 +                if (!link->time_base.num && !link->time_base.den)
 +                    link->time_base = (AVRational) {1, link->sample_rate};
              }
  
              if ((config_link = link->dstpad->config_props))
      return 0;
  }
  
 -void ff_dlog_link(void *ctx, AVFilterLink *link, int end)
 +void ff_tlog_link(void *ctx, AVFilterLink *link, int end)
  {
      if (link->type == AVMEDIA_TYPE_VIDEO) {
 -        av_dlog(ctx,
 -                "link[%p s:%dx%d fmt:%-16s %-16s->%-16s]%s",
 +        ff_tlog(ctx,
 +                "link[%p s:%dx%d fmt:%s %s->%s]%s",
                  link, link->w, link->h,
                  av_get_pix_fmt_name(link->format),
                  link->src ? link->src->filter->name : "",
          char buf[128];
          av_get_channel_layout_string(buf, sizeof(buf), -1, link->channel_layout);
  
 -        av_dlog(ctx,
 -                "link[%p r:%d cl:%s fmt:%-16s %-16s->%-16s]%s",
 -                link, link->sample_rate, buf,
 +        ff_tlog(ctx,
 +                "link[%p r:%d cl:%s fmt:%s %s->%s]%s",
 +                link, (int)link->sample_rate, buf,
                  av_get_sample_fmt_name(link->format),
                  link->src ? link->src->filter->name : "",
                  link->dst ? link->dst->filter->name : "",
  
  int ff_request_frame(AVFilterLink *link)
  {
 -    FF_DPRINTF_START(NULL, request_frame); ff_dlog_link(NULL, link, 1);
 -
 -    if (link->srcpad->request_frame)
 -        return link->srcpad->request_frame(link);
 -    else if (link->src->inputs[0])
 -        return ff_request_frame(link->src->inputs[0]);
 -    else return -1;
 +    int ret = -1;
 +    FF_TPRINTF_START(NULL, request_frame); ff_tlog_link(NULL, link, 1);
 +
 +    if (link->closed)
 +        return AVERROR_EOF;
 +    av_assert0(!link->frame_requested);
 +    link->frame_requested = 1;
 +    while (link->frame_requested) {
 +        if (link->srcpad->request_frame)
 +            ret = link->srcpad->request_frame(link);
 +        else if (link->src->inputs[0])
 +            ret = ff_request_frame(link->src->inputs[0]);
 +        if (ret == AVERROR_EOF && link->partial_buf) {
 +            AVFrame *pbuf = link->partial_buf;
 +            link->partial_buf = NULL;
 +            ret = ff_filter_frame_framed(link, pbuf);
 +        }
 +        if (ret < 0) {
 +            link->frame_requested = 0;
 +            if (ret == AVERROR_EOF)
 +                link->closed = 1;
 +        } else {
 +            av_assert0(!link->frame_requested ||
 +                       link->flags & FF_LINK_FLAG_REQUEST_LOOP);
 +        }
 +    }
 +    return ret;
  }
  
  int ff_poll_frame(AVFilterLink *link)
      return min;
  }
  
 -#define MAX_REGISTERED_AVFILTERS_NB 64
 +void ff_update_link_current_pts(AVFilterLink *link, int64_t pts)
 +{
 +    if (pts == AV_NOPTS_VALUE)
 +        return;
 +    link->current_pts = av_rescale_q(pts, link->time_base, AV_TIME_BASE_Q);
 +    /* TODO use duration */
 +    if (link->graph && link->age_index >= 0)
 +        ff_avfilter_graph_update_heap(link->graph, link);
 +}
 +
 +int avfilter_process_command(AVFilterContext *filter, const char *cmd, const char *arg, char *res, int res_len, int flags)
 +{
 +    if(!strcmp(cmd, "ping")){
 +        av_strlcatf(res, res_len, "pong from:%s %s\n", filter->filter->name, filter->name);
 +        return 0;
 +    }else if(filter->filter->process_command) {
 +        return filter->filter->process_command(filter, cmd, arg, res, res_len, flags);
 +    }
 +    return AVERROR(ENOSYS);
 +}
 +
 +#define MAX_REGISTERED_AVFILTERS_NB 256
  
  static AVFilter *registered_avfilters[MAX_REGISTERED_AVFILTERS_NB + 1];
  
@@@ -405,21 -286,8 +405,21 @@@ AVFilter *avfilter_get_by_name(const ch
  
  int avfilter_register(AVFilter *filter)
  {
 -    if (next_registered_avfilter_idx == MAX_REGISTERED_AVFILTERS_NB)
 -        return -1;
 +    int i;
 +
 +    if (next_registered_avfilter_idx == MAX_REGISTERED_AVFILTERS_NB) {
 +        av_log(NULL, AV_LOG_ERROR,
 +               "Maximum number of registered filters %d reached, "
 +               "impossible to register filter with name '%s'\n",
 +               MAX_REGISTERED_AVFILTERS_NB, filter->name);
 +        return AVERROR(ENOMEM);
 +    }
 +
 +    for(i=0; filter->inputs && filter->inputs[i].name; i++) {
 +        const AVFilterPad *input = &filter->inputs[i];
 +        av_assert0(     !input->filter_frame
 +                    || (!input->start_frame && !input->end_frame));
 +    }
  
      registered_avfilters[next_registered_avfilter_idx++] = filter;
      return 0;
@@@ -447,10 -315,10 +447,10 @@@ static int pad_count(const AVFilterPad 
      return count;
  }
  
 -static const char *filter_name(void *p)
 +static const char *default_filter_name(void *filter_ctx)
  {
 -    AVFilterContext *filter = p;
 -    return filter->filter->name;
 +    AVFilterContext *ctx = filter_ctx;
 +    return ctx->name ? ctx->name : ctx->filter->name;
  }
  
  static void *filter_child_next(void *obj, void *prev)
@@@ -465,27 -333,21 +465,27 @@@ static const AVClass *filter_child_clas
  {
      AVFilter **f = NULL;
  
 +    /* find the filter that corresponds to prev */
      while (prev && *(f = av_filter_next(f)))
          if ((*f)->priv_class == prev)
              break;
  
 +    /* could not find filter corresponding to prev */
 +    if (prev && !(*f))
 +        return NULL;
 +
 +    /* find next filter with specific options */
      while (*(f = av_filter_next(f)))
          if ((*f)->priv_class)
              return (*f)->priv_class;
 -
      return NULL;
  }
  
  static const AVClass avfilter_class = {
      .class_name = "AVFilter",
 -    .item_name  = filter_name,
 +    .item_name  = default_filter_name,
      .version    = LIBAVUTIL_VERSION_INT,
 +    .category   = AV_CLASS_CATEGORY_FILTER,
      .child_next = filter_child_next,
      .child_class_next = filter_child_class_next,
  };
@@@ -568,9 -430,9 +568,12 @@@ void avfilter_free(AVFilterContext *fil
      int i;
      AVFilterLink *link;
  
 +    if (!filter)
 +        return;
 +
+     if (filter->graph)
+         ff_filter_graph_remove_filter(filter->graph, filter);
      if (filter->filter->uninit)
          filter->filter->uninit(filter);
  
              ff_channel_layouts_unref(&link->in_channel_layouts);
              ff_channel_layouts_unref(&link->out_channel_layouts);
          }
 -        av_freep(&link);
 +        avfilter_link_free(&link);
      }
      for (i = 0; i < filter->nb_outputs; i++) {
          if ((link = filter->outputs[i])) {
              ff_channel_layouts_unref(&link->in_channel_layouts);
              ff_channel_layouts_unref(&link->out_channel_layouts);
          }
 -        av_freep(&link);
 +        avfilter_link_free(&link);
      }
  
 -    if (filter->filter->priv_class)
 +    if (filter->filter->priv_class || filter->filter->shorthand)
          av_opt_free(filter->priv);
  
      av_freep(&filter->name);
      av_freep(&filter->inputs);
      av_freep(&filter->outputs);
      av_freep(&filter->priv);
 +    while(filter->command_queue){
 +        ff_command_queue_pop(filter);
 +    }
      av_free(filter);
  }
  
 -/* process a list of value1:value2:..., each value corresponding
 - * to subsequent AVOption, in the order they are declared */
 -static int process_unnamed_options(AVFilterContext *ctx, AVDictionary **options,
 -                                   const char *args)
 +static int process_options(AVFilterContext *ctx, AVDictionary **options,
 +                           const char *args)
  {
      const AVOption *o = NULL;
 -    const char *p = args;
 -    char *val;
 +    int ret, count = 0;
 +    char *av_uninit(parsed_key), *av_uninit(value);
 +    const char *key;
 +    int offset= -1;
 +
 +    if (!args)
 +        return 0;
 +
 +    while (*args) {
 +        const char *shorthand = NULL;
  
 -    while (*p) {
          o = av_opt_next(ctx->priv, o);
 -        if (!o) {
 -            av_log(ctx, AV_LOG_ERROR, "More options provided than "
 -                   "this filter supports.\n");
 -            return AVERROR(EINVAL);
 +        if (o) {
 +            if (o->type == AV_OPT_TYPE_CONST || o->offset == offset)
 +                continue;
 +            offset = o->offset;
 +            shorthand = o->name;
          }
 -        if (o->type == AV_OPT_TYPE_CONST)
 -            continue;
  
 -        val = av_get_token(&p, ":");
 -        if (!val)
 -            return AVERROR(ENOMEM);
 +        ret = av_opt_get_key_value(&args, "=", ":",
 +                                   shorthand ? AV_OPT_FLAG_IMPLICIT_KEY : 0,
 +                                   &parsed_key, &value);
 +        if (ret < 0) {
 +            if (ret == AVERROR(EINVAL))
 +                av_log(ctx, AV_LOG_ERROR, "No option name near '%s'\n", args);
 +            else
 +                av_log(ctx, AV_LOG_ERROR, "Unable to parse '%s': %s\n", args,
 +                       av_err2str(ret));
 +            return ret;
 +        }
 +        if (*args)
 +            args++;
 +        if (parsed_key) {
 +            key = parsed_key;
 +            while ((o = av_opt_next(ctx->priv, o))); /* discard all remaining shorthand */
 +        } else {
 +            key = shorthand;
 +        }
  
 -        av_dict_set(options, o->name, val, 0);
 +        av_log(ctx, AV_LOG_DEBUG, "Setting '%s' to value '%s'\n", key, value);
 +        av_dict_set(options, key, value, 0);
 +        if ((ret = av_opt_set(ctx->priv, key, value, 0)) < 0) {
 +            if (!av_opt_find(ctx->priv, key, NULL, 0, AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ)) {
 +            if (ret == AVERROR_OPTION_NOT_FOUND)
 +                av_log(ctx, AV_LOG_ERROR, "Option '%s' not found\n", key);
 +            av_free(value);
 +            av_free(parsed_key);
 +            return ret;
 +            }
 +        }
  
 -        av_freep(&val);
 -        if (*p)
 -            p++;
 +        av_free(value);
 +        av_free(parsed_key);
 +        count++;
      }
 +    return count;
 +}
  
 +// TODO: drop me
 +static const char *const filters_left_to_update[] = {
 +    "abuffer",
 +#if FF_API_ACONVERT_FILTER
 +    "aconvert",
 +#endif
 +    "atempo",
 +    "buffer",
 +    "pan",
 +    "scale",
 +};
 +
 +static int filter_use_deprecated_init(const char *name)
 +{
 +    int i;
 +    for (i = 0; i < FF_ARRAY_ELEMS(filters_left_to_update); i++)
 +        if (!strcmp(name, filters_left_to_update[i]))
 +            return 1;
      return 0;
  }
  
@@@ -704,22 -513,8 +707,22 @@@ int avfilter_init_filter(AVFilterContex
      AVDictionary *options = NULL;
      AVDictionaryEntry *e;
      int ret=0;
 +    int deprecated_init = filter_use_deprecated_init(filter->filter->name);
 +
 +    // TODO: remove old shorthand
 +    if (filter->filter->shorthand) {
 +        av_assert0(filter->priv);
 +        av_assert0(filter->filter->priv_class);
 +        *(const AVClass **)filter->priv = filter->filter->priv_class;
 +        av_opt_set_defaults(filter->priv);
 +        ret = av_opt_set_from_string(filter->priv, args,
 +                                     filter->filter->shorthand, "=", ":");
 +        if (ret < 0)
 +            return ret;
 +        args = NULL;
 +    }
  
 -    if (args && *args) {
 +    if (!deprecated_init && args && *args) {
          if (!filter->filter->priv_class) {
              av_log(filter, AV_LOG_ERROR, "This filter does not take any "
                     "options, but options were provided: %s.\n", args);
                  ret = av_dict_parse_string(&options, p, "=", ":", 0);
              }
              if (ret >= 0)
 -                ret = process_unnamed_options(filter, &options, copy);
 +                ret = process_options(filter, &options, copy);
              av_freep(&copy);
  
              if (ret < 0)
                  goto fail;
 -        } else
 -#endif
 -
 -        if (strchr(args, '=')) {
 -            /* assume a list of key1=value1:key2=value2:... */
 -            ret = av_dict_parse_string(&options, args, "=", ":", 0);
 -            if (ret < 0)
 -                goto fail;
 -#if FF_API_OLD_FILTER_OPTS
          } else if (!strcmp(filter->filter->name, "format")     ||
                     !strcmp(filter->filter->name, "noformat")   ||
                     !strcmp(filter->filter->name, "frei0r")     ||
                     !strcmp(filter->filter->name, "frei0r_src") ||
 -                   !strcmp(filter->filter->name, "ocv")) {
 +                   !strcmp(filter->filter->name, "ocv")        ||
 +                   !strcmp(filter->filter->name, "pp")         ||
 +                   !strcmp(filter->filter->name, "aevalsrc")) {
              /* a hack for compatibility with the old syntax
               * replace colons with |s */
              char *copy = av_strdup(args);
              char *p    = copy;
              int nb_leading = 0; // number of leading colons to skip
 +            int deprecated = 0;
  
              if (!copy) {
                  ret = AVERROR(ENOMEM);
                  p++;
              }
  
 -            if (strchr(p, ':')) {
 -                av_log(filter, AV_LOG_WARNING, "This syntax is deprecated. Use "
 -                       "'|' to separate the list items.\n");
 -            }
 -
 +            deprecated = strchr(p, ':') != NULL;
 +
 +            if (!strcmp(filter->filter->name, "aevalsrc")) {
 +                deprecated = 0;
 +                while ((p = strchr(p, ':')) && p[1] != ':') {
 +                    const char *epos = strchr(p + 1, '=');
 +                    const char *spos = strchr(p + 1, ':');
 +                    const int next_token_is_opt = epos && (!spos || epos < spos);
 +                    if (next_token_is_opt) {
 +                        p++;
 +                        break;
 +                    }
 +                    /* next token does not contain a '=', assume a channel expression */
 +                    deprecated = 1;
 +                    *p++ = '|';
 +                }
 +                if (p && *p == ':') { // double sep '::' found
 +                    deprecated = 1;
 +                    memmove(p, p + 1, strlen(p));
 +                }
 +            } else
              while ((p = strchr(p, ':')))
                  *p++ = '|';
  
 -            ret = process_unnamed_options(filter, &options, copy);
 +            if (deprecated)
 +                av_log(filter, AV_LOG_WARNING, "This syntax is deprecated. Use "
 +                       "'|' to separate the list items.\n");
 +
 +            av_log(filter, AV_LOG_DEBUG, "compat: called with args=[%s]\n", copy);
 +            ret = process_options(filter, &options, copy);
              av_freep(&copy);
  
              if (ret < 0)
                  goto fail;
  #endif
          } else {
 -            ret = process_unnamed_options(filter, &options, args);
 +#if CONFIG_MP_FILTER
 +            if (!strcmp(filter->filter->name, "mp")) {
 +                char *escaped;
 +
 +                if (!strncmp(args, "filter=", 7))
 +                    args += 7;
 +                ret = av_escape(&escaped, args, ":=", AV_ESCAPE_MODE_BACKSLASH, 0);
 +                if (ret < 0) {
 +                    av_log(filter, AV_LOG_ERROR, "Unable to escape MPlayer filters arg '%s'\n", args);
 +                    goto fail;
 +                }
 +                ret = process_options(filter, &options, escaped);
 +                av_free(escaped);
 +            } else
 +#endif
 +            ret = process_options(filter, &options, args);
              if (ret < 0)
                  goto fail;
          }
      }
  
 -    if (filter->filter->priv_class) {
 +    if (!deprecated_init && filter->filter->priv_class) {
          ret = av_opt_set_dict(filter->priv, &options);
          if (ret < 0) {
              av_log(filter, AV_LOG_ERROR, "Error applying options to the filter.\n");
          }
      }
  
 -    if (filter->filter->init)
 -        ret = filter->filter->init(filter);
 +    if (filter->filter->init_opaque)
 +        ret = filter->filter->init_opaque(filter, args, opaque);
 +    else if (filter->filter->init)
 +        ret = filter->filter->init(filter, args);
      else if (filter->filter->init_dict)
          ret = filter->filter->init_dict(filter, &options);
      if (ret < 0)
@@@ -888,19 -651,14 +891,19 @@@ static int default_filter_frame(AVFilte
      return ff_filter_frame(link->dst->outputs[0], frame);
  }
  
 -int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
 +static int ff_filter_frame_framed(AVFilterLink *link, AVFrame *frame)
  {
      int (*filter_frame)(AVFilterLink *, AVFrame *);
      AVFilterPad *dst = link->dstpad;
      AVFrame *out;
 +    int ret;
 +    AVFilterCommand *cmd= link->dst->command_queue;
 +    int64_t pts;
  
 -    FF_DPRINTF_START(NULL, filter_frame);
 -    ff_dlog_link(NULL, link, 1);
 +    if (link->closed) {
 +        av_frame_free(&frame);
 +        return AVERROR_EOF;
 +    }
  
      if (!(filter_frame = dst->filter_frame))
          filter_frame = default_filter_frame;
      if (dst->needs_writable && !av_frame_is_writable(frame)) {
          av_log(link->dst, AV_LOG_DEBUG, "Copying data in avfilter.\n");
  
 +        /* Maybe use ff_copy_buffer_ref instead? */
          switch (link->type) {
          case AVMEDIA_TYPE_VIDEO:
              out = ff_get_video_buffer(link, link->w, link->h);
  
          switch (link->type) {
          case AVMEDIA_TYPE_VIDEO:
 -            av_image_copy(out->data, out->linesize, frame->data, frame->linesize,
 +            av_image_copy(out->data, out->linesize, (const uint8_t **)frame->data, frame->linesize,
                            frame->format, frame->width, frame->height);
              break;
          case AVMEDIA_TYPE_AUDIO:
      } else
          out = frame;
  
 -    return filter_frame(link, out);
 +    while(cmd && cmd->time <= out->pts * av_q2d(link->time_base)){
 +        av_log(link->dst, AV_LOG_DEBUG,
 +               "Processing command time:%f command:%s arg:%s\n",
 +               cmd->time, cmd->command, cmd->arg);
 +        avfilter_process_command(link->dst, cmd->command, cmd->arg, 0, 0, cmd->flags);
 +        ff_command_queue_pop(link->dst);
 +        cmd= link->dst->command_queue;
 +    }
 +
 +    pts = out->pts;
 +    ret = filter_frame(link, out);
 +    link->frame_requested = 0;
 +    ff_update_link_current_pts(link, pts);
 +    return ret;
 +}
 +
 +static int ff_filter_frame_needs_framing(AVFilterLink *link, AVFrame *frame)
 +{
 +    int insamples = frame->nb_samples, inpos = 0, nb_samples;
 +    AVFrame *pbuf = link->partial_buf;
 +    int nb_channels = av_frame_get_channels(frame);
 +    int ret = 0;
 +
 +    link->flags |= FF_LINK_FLAG_REQUEST_LOOP;
 +    /* Handle framing (min_samples, max_samples) */
 +    while (insamples) {
 +        if (!pbuf) {
 +            AVRational samples_tb = { 1, link->sample_rate };
 +            pbuf = ff_get_audio_buffer(link, link->partial_buf_size);
 +            if (!pbuf) {
 +                av_log(link->dst, AV_LOG_WARNING,
 +                       "Samples dropped due to memory allocation failure.\n");
 +                return 0;
 +            }
 +            av_frame_copy_props(pbuf, frame);
 +            pbuf->pts = frame->pts +
 +                        av_rescale_q(inpos, samples_tb, link->time_base);
 +            pbuf->nb_samples = 0;
 +        }
 +        nb_samples = FFMIN(insamples,
 +                           link->partial_buf_size - pbuf->nb_samples);
 +        av_samples_copy(pbuf->extended_data, frame->extended_data,
 +                        pbuf->nb_samples, inpos,
 +                        nb_samples, nb_channels, link->format);
 +        inpos                   += nb_samples;
 +        insamples               -= nb_samples;
 +        pbuf->nb_samples += nb_samples;
 +        if (pbuf->nb_samples >= link->min_samples) {
 +            ret = ff_filter_frame_framed(link, pbuf);
 +            pbuf = NULL;
 +        }
 +    }
 +    av_frame_free(&frame);
 +    link->partial_buf = pbuf;
 +    return ret;
 +}
 +
 +int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
 +{
 +    FF_TPRINTF_START(NULL, filter_frame); ff_tlog_link(NULL, link, 1); ff_tlog(NULL, " "); ff_tlog_ref(NULL, frame, 1);
 +
 +    /* Consistency checks */
 +    if (link->type == AVMEDIA_TYPE_VIDEO) {
 +        if (strcmp(link->dst->filter->name, "scale")) {
 +            av_assert1(frame->format                 == link->format);
 +            av_assert1(frame->width               == link->w);
 +            av_assert1(frame->height               == link->h);
 +        }
 +    } else {
 +        av_assert1(frame->format                == link->format);
 +        av_assert1(av_frame_get_channels(frame) == link->channels);
 +        av_assert1(frame->channel_layout        == link->channel_layout);
 +        av_assert1(frame->sample_rate           == link->sample_rate);
 +    }
 +
 +    /* Go directly to actual filtering if possible */
 +    if (link->type == AVMEDIA_TYPE_AUDIO &&
 +        link->min_samples &&
 +        (link->partial_buf ||
 +         frame->nb_samples < link->min_samples ||
 +         frame->nb_samples > link->max_samples)) {
 +        return ff_filter_frame_needs_framing(link, frame);
 +    } else {
 +        return ff_filter_frame_framed(link, frame);
 +    }
  }
  
  const AVClass *avfilter_get_class(void)
diff --combined libavfilter/avfilter.h
@@@ -2,46 -2,35 +2,46 @@@
   * filter layer
   * Copyright (c) 2007 Bobby Bingham
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * 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 Libav; if not, write to the Free Software
 + * 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
  
 +/**
 + * @file
 + * @ingroup lavfi
 + * external API header
 + */
 +
 +/**
 + * @defgroup lavfi Libavfilter
 + * @{
 + */
 +
 +#include <stddef.h>
 +
  #include "libavutil/avutil.h"
 +#include "libavutil/dict.h"
  #include "libavutil/frame.h"
  #include "libavutil/log.h"
  #include "libavutil/samplefmt.h"
  #include "libavutil/pixfmt.h"
  #include "libavutil/rational.h"
 -#include "libavcodec/avcodec.h"
 -
 -#include <stddef.h>
  
  #include "libavfilter/version.h"
  
@@@ -60,6 -49,7 +60,6 @@@ const char *avfilter_configuration(void
   */
  const char *avfilter_license(void);
  
 -
  typedef struct AVFilterContext AVFilterContext;
  typedef struct AVFilterLink    AVFilterLink;
  typedef struct AVFilterPad     AVFilterPad;
@@@ -112,9 -102,6 +112,9 @@@ typedef struct AVFilterBuffer 
  #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
  #define AV_PERM_NEG_LINESIZES 0x20  ///< the buffer requested can have negative linesizes
 +#define AV_PERM_ALIGN    0x40   ///< the buffer must be aligned
 +
 +#define AVFILTER_ALIGN 16 //not part of ABI
  
  /**
   * Audio specific properties in a reference to an AVFilterBuffer. Since
   */
  typedef struct AVFilterBufferRefAudioProps {
      uint64_t channel_layout;    ///< channel layout of audio buffer
 -    int nb_samples;             ///< number of audio samples
 +    int nb_samples;             ///< number of audio samples per channel
      int sample_rate;            ///< audio buffer sample rate
 -    int planar;                 ///< audio buffer - planar or packed
 +    int channels;               ///< number of channels (do not access directly)
  } AVFilterBufferRefAudioProps;
  
  /**
  typedef struct AVFilterBufferRefVideoProps {
      int w;                      ///< image width
      int h;                      ///< image height
 -    AVRational pixel_aspect;    ///< pixel aspect ratio
 +    AVRational sample_aspect_ratio; ///< sample aspect ratio
      int interlaced;             ///< is frame interlaced
      int top_field_first;        ///< field order
      enum AVPictureType pict_type; ///< picture type of the frame
      int key_frame;              ///< 1 -> keyframe, 0-> not
 +    int qp_table_linesize;                ///< qp_table stride
 +    int qp_table_size;            ///< qp_table size
 +    int8_t *qp_table;             ///< array of Quantization Parameters
  } AVFilterBufferRefVideoProps;
  
  /**
@@@ -190,8 -174,6 +190,8 @@@ typedef struct AVFilterBufferRef 
      int perms;                  ///< permissions, see the AV_PERM_* flags
  
      enum AVMediaType type;      ///< media type of buffer data
 +
 +    AVDictionary *metadata;     ///< dictionary containing metadata key=value tags
  } AVFilterBufferRef;
  
  /**
@@@ -235,19 -217,11 +235,19 @@@ attribute_deprecate
  void avfilter_unref_bufferp(AVFilterBufferRef **ref);
  #endif
  
 +/**
 + * Get the number of channels of a buffer reference.
 + */
 +attribute_deprecated
 +int avfilter_ref_get_channels(AVFilterBufferRef *ref);
 +
  #if FF_API_AVFILTERPAD_PUBLIC
  /**
   * A filter pad used for either input or output.
   *
 - * @warning this struct will be removed from public API.
 + * See doc/filter_design.txt for details on how to implement the methods.
 + *
 + * @warning this struct might be removed from public API.
   * users should call avfilter_pad_get_name() and avfilter_pad_get_type()
   * to access the name and type fields; there should be no need to access
   * any other fields from outside of libavfilter.
@@@ -266,29 -240,22 +266,29 @@@ struct AVFilterPad 
      enum AVMediaType type;
  
      /**
 +     * Input pads:
       * 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.
 +     * Output pads:
 +     * Guaranteed permissions on outgoing buffers. Any buffer pushed on the
 +     * link must have at least these permissions; this fact is checked by
 +     * asserts. It can be used to optimize buffer allocation.
       */
      attribute_deprecated int min_perms;
  
      /**
 +     * Input pads:
       * 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.
 +     * Output pads:
 +     * Permissions which are automatically removed on outgoing buffers. It
 +     * can be used to optimize buffer allocation.
       */
      attribute_deprecated int rej_perms;
  
  
      /**
       * Callback function to get a video buffer. If NULL, the filter system will
 -     * use avfilter_default_get_video_buffer().
 +     * use ff_default_get_video_buffer().
       *
       * Input video pads only.
       */
  
      /**
       * Callback function to get an audio buffer. If NULL, the filter system will
 -     * use avfilter_default_get_audio_buffer().
 +     * use ff_default_get_audio_buffer().
       *
       * Input audio pads only.
       */
       * Input pads only.
       *
       * @return >= 0 on success, a negative AVERROR on error. This function
 -     * must ensure that samplesref is properly unreferenced on error if it
 +     * must ensure that frame is properly unreferenced on error if it
       * hasn't been passed on to another filter.
       */
      int (*filter_frame)(AVFilterLink *link, AVFrame *frame);
       * 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.
 +     * See ff_request_frame() for the error codes with a specific
 +     * meaning.
       *
       * Output pads only.
       */
      /**
       * 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
 +     * For output pads, this should set the following link properties:
 +     * video: width, height, sample_aspect_ratio, time_base
 +     * audio: sample_rate.
 +     *
 +     * This should NOT set properties such as format, channel_layout, etc which
 +     * are 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,
 +     * For both input and output pads, this should return zero on success,
       * and another value on error.
       */
      int (*config_props)(AVFilterLink *link);
@@@ -441,10 -403,10 +441,10 @@@ typedef struct AVFilter 
       */
  
      /**
 -     * Filter initialization function. Called when all the options have been
 -     * set.
 +     * Filter initialization function. Args contains the user-supplied
 +     * parameters. FIXME: maybe an AVOption-based system would be better?
       */
 -    int (*init)(AVFilterContext *ctx);
 +    int (*init)(AVFilterContext *ctx, const char *args);
  
      /**
       * Should be set instead of init by the filters that want to pass a
      void (*uninit)(AVFilterContext *ctx);
  
      /**
 -     * Queries formats supported by the filter and its pads, and sets the
 -     * in_formats for links connected to its output pads, and out_formats
 -     * for links connected to its input pads.
 +     * Queries formats/layouts supported by the filter and its pads, and sets
 +     * the in_formats/in_chlayouts for links connected to its output pads,
 +     * and out_formats/out_chlayouts for links connected to its input pads.
       *
       * @return zero on success, a negative value corresponding to an
       * AVERROR code otherwise
      int (*query_formats)(AVFilterContext *);
  
      int priv_size;      ///< size of private data to allocate for the filter
 +
 +    /**
 +     * Make the filter instance process a command.
 +     *
 +     * @param cmd    the command to process, for handling simplicity all commands must be alphanumeric only
 +     * @param arg    the argument for the command
 +     * @param res    a buffer with size res_size where the filter(s) can return a response. This must not change when the command is not supported.
 +     * @param flags  if AVFILTER_CMD_FLAG_FAST is set and the command would be
 +     *               time consuming then a filter should treat it like an unsupported command
 +     *
 +     * @returns >=0 on success otherwise an error code.
 +     *          AVERROR(ENOSYS) on unsupported commands
 +     */
 +    int (*process_command)(AVFilterContext *, const char *cmd, const char *arg, char *res, int res_len, int flags);
 +
 +    /**
 +     * Filter initialization function, alternative to the init()
 +     * callback. Args contains the user-supplied parameters, opaque is
 +     * used for providing binary data.
 +     */
 +    int (*init_opaque)(AVFilterContext *ctx, const char *args, void *opaque);
 +
 +    /**
 +     * Shorthand syntax for init arguments.
 +     * If this field is set (even to an empty list), just before init the
 +     * private class will be set and the arguments string will be parsed
 +     * using av_opt_set_from_string() with "=" and ":" delimiters, and
 +     * av_opt_free() will be called just after uninit.
 +     */
 +    const char *const *shorthand;
  } AVFilter;
  
  /** An instance of a filter */
  struct AVFilterContext {
 -    const AVClass *av_class;              ///< needed for av_log()
 +    const AVClass *av_class;        ///< needed for av_log()
  
      const AVFilter *filter;         ///< the AVFilter of which this is an instance
  
      void *priv;                     ///< private data for use by the filter
  
      struct AVFilterGraph *graph;    ///< filtergraph this filter belongs to
 +
 +    struct AVFilterCommand *command_queue;
  };
  
  /**
@@@ -552,7 -482,7 +552,7 @@@ struct AVFilterLink 
      int w;                      ///< agreed upon image width
      int h;                      ///< agreed upon image height
      AVRational sample_aspect_ratio; ///< agreed upon sample aspect ratio
 -    /* These two parameters apply only to audio */
 +    /* These parameters apply only to audio */
      uint64_t channel_layout;    ///< channel layout of current buffer (see libavutil/channel_layout.h)
      int sample_rate;            ///< samples per second
  
       *****************************************************************
       */
      /**
 -     * 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.
 +     * Lists of formats and channel layouts 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 and
 +     * channel_layout members, above, when chosen.
 +     *
       */
      AVFilterFormats *in_formats;
      AVFilterFormats *out_formats;
          AVLINK_STARTINIT,       ///< started, but incomplete
          AVLINK_INIT             ///< complete
      } init_state;
 +
 +    struct AVFilterPool *pool;
 +
 +    /**
 +     * Graph the filter belongs to.
 +     */
 +    struct AVFilterGraph *graph;
 +
 +    /**
 +     * Current timestamp of the link, as defined by the most recent
 +     * frame(s), in AV_TIME_BASE units.
 +     */
 +    int64_t current_pts;
 +
 +    /**
 +     * Index in the age array.
 +     */
 +    int age_index;
 +
 +    /**
 +     * Frame rate of the stream on the link, or 1/0 if unknown;
 +     * if left to 0/0, will be automatically be copied from the first input
 +     * of the source filter if it exists.
 +     *
 +     * Sources should set it to the best estimation of the real frame rate.
 +     * Filters should update it if necessary depending on their function.
 +     * Sinks can use it to set a default output frame rate.
 +     * It is similar to the r_frame_rate field in AVStream.
 +     */
 +    AVRational frame_rate;
 +
 +    /**
 +     * Buffer partially filled with samples to achieve a fixed/minimum size.
 +     */
 +    AVFrame *partial_buf;
 +
 +    /**
 +     * Size of the partial buffer to allocate.
 +     * Must be between min_samples and max_samples.
 +     */
 +    int partial_buf_size;
 +
 +    /**
 +     * Minimum number of samples to filter at once. If filter_frame() is
 +     * called with fewer samples, it will accumulate them in partial_buf.
 +     * This field and the related ones must not be changed after filtering
 +     * has started.
 +     * If 0, all related fields are ignored.
 +     */
 +    int min_samples;
 +
 +    /**
 +     * Maximum number of samples to filter at once. If filter_frame() is
 +     * called with more samples, it will split them.
 +     */
 +    int max_samples;
 +
 +    /**
 +     * The buffer reference currently being received across the link by the
 +     * destination filter. This is used internally by the filter system to
 +     * allow automatic copying of buffers which do not have sufficient
 +     * permissions for the destination. This should not be accessed directly
 +     * by the filters.
 +     */
 +    AVFilterBufferRef *cur_buf_copy;
 +
 +    /**
 +     * True if the link is closed.
 +     * If set, all attemps of start_frame, filter_frame or request_frame
 +     * will fail with AVERROR_EOF, and if necessary the reference will be
 +     * destroyed.
 +     * If request_frame returns AVERROR_EOF, this flag is set on the
 +     * corresponding link.
 +     * It can be set also be set by either the source or the destination
 +     * filter.
 +     */
 +    int closed;
 +
 +    /**
 +     * Number of channels.
 +     */
 +    int channels;
 +
 +    /**
 +     * True if a frame is being requested on the link.
 +     * Used internally by the framework.
 +     */
 +    unsigned frame_requested;
 +
 +    /**
 +     * Link processing flags.
 +     */
 +    unsigned flags;
  };
  
  /**
  int avfilter_link(AVFilterContext *src, unsigned srcpad,
                    AVFilterContext *dst, unsigned dstpad);
  
 +/**
 + * Free the link in *link, and set its pointer to NULL.
 + */
 +void avfilter_link_free(AVFilterLink **link);
 +
 +/**
 + * Get the number of channels of a link.
 + */
 +int avfilter_link_get_channels(AVFilterLink *link);
 +
 +/**
 + * Set the closed field of a link.
 + */
 +void avfilter_link_set_closed(AVFilterLink *link, int closed);
 +
  /**
   * Negotiate the media format, dimensions, etc of all inputs to a filter.
   *
@@@ -752,16 -572,13 +752,16 @@@ int avfilter_config_links(AVFilterConte
   */
  attribute_deprecated
  AVFilterBufferRef *
 -avfilter_get_video_buffer_ref_from_arrays(uint8_t *data[4], int linesize[4], int perms,
 +avfilter_get_video_buffer_ref_from_arrays(uint8_t * const data[4], const int linesize[4], int perms,
                                            int w, int h, enum AVPixelFormat format);
  
  /**
   * Create an audio buffer reference wrapped around an already
   * allocated samples buffer.
   *
 + * See avfilter_get_audio_buffer_ref_from_arrays_channels() for a version
 + * that can handle unknown channel layouts.
 + *
   * @param data           pointers to the samples plane buffers
   * @param linesize       linesize for the samples plane buffers
   * @param perms          the required access permissions
@@@ -776,40 -593,8 +776,40 @@@ AVFilterBufferRef *avfilter_get_audio_b
                                                               int nb_samples,
                                                               enum AVSampleFormat sample_fmt,
                                                               uint64_t channel_layout);
 +/**
 + * Create an audio buffer reference wrapped around an already
 + * allocated samples buffer.
 + *
 + * @param data           pointers to the samples plane buffers
 + * @param linesize       linesize for the samples plane buffers
 + * @param perms          the required access permissions
 + * @param nb_samples     number of samples per channel
 + * @param sample_fmt     the format of each sample in the buffer to allocate
 + * @param channels       the number of channels of the buffer
 + * @param channel_layout the channel layout of the buffer,
 + *                       must be either 0 or consistent with channels
 + */
 +attribute_deprecated
 +AVFilterBufferRef *avfilter_get_audio_buffer_ref_from_arrays_channels(uint8_t **data,
 +                                                                      int linesize,
 +                                                                      int perms,
 +                                                                      int nb_samples,
 +                                                                      enum AVSampleFormat sample_fmt,
 +                                                                      int channels,
 +                                                                      uint64_t channel_layout);
 +
  #endif
  
 +
 +#define AVFILTER_CMD_FLAG_ONE   1 ///< Stop once a filter understood the command (for target=all for example), fast filters are favored automatically
 +#define AVFILTER_CMD_FLAG_FAST  2 ///< Only execute command when its fast (like a video out that supports contrast adjustment in hw)
 +
 +/**
 + * Make the filter instance process a command.
 + * It is recommended to use avfilter_graph_send_command().
 + */
 +int avfilter_process_command(AVFilterContext *filter, const char *cmd, const char *arg, char *res, int res_len, int flags);
 +
  /** Initialize the filter system. Register all builtin filters. */
  void avfilter_register_all(void);
  
@@@ -823,7 -608,7 +823,7 @@@ void avfilter_uninit(void)
   * is not registered.
   *
   * @param filter the filter to register
 - * @return 0 if the registration was succesfull, a negative value
 + * @return 0 if the registration was successful, a negative value
   * otherwise
   */
  int avfilter_register(AVFilter *filter);
@@@ -873,7 -658,8 +873,8 @@@ int avfilter_open(AVFilterContext **fil
  int avfilter_init_filter(AVFilterContext *filter, const char *args, void *opaque);
  
  /**
-  * Free a filter context.
+  * Free a filter context. This will also remove the filter from its
+  * filtergraph's list of filters.
   *
   * @param filter the filter to free
   */
@@@ -922,7 -708,7 +923,7 @@@ typedef struct AVFilterGraph 
      const AVClass *av_class;
  #if FF_API_FOO_COUNT
      attribute_deprecated
 -    unsigned filter_count;
 +    unsigned filter_count_unused;
  #endif
      AVFilterContext **filters;
  #if !FF_API_FOO_COUNT
  #if FF_API_FOO_COUNT
      unsigned nb_filters;
  #endif
 +    char *aresample_swr_opts; ///< swr options to use for the auto-inserted aresample filters, Access ONLY through AVOptions
 +
 +    /**
 +     * Private fields
 +     *
 +     * The following fields are for internal use only.
 +     * Their type, offset, number and semantic can change without notice.
 +     */
 +
 +    AVFilterLink **sink_links;
 +    int sink_links_count;
 +
 +    unsigned disable_auto_convert;
  } AVFilterGraph;
  
  /**
@@@ -1011,21 -784,6 +1012,21 @@@ int avfilter_graph_create_filter(AVFilt
                                   const char *name, const char *args, void *opaque,
                                   AVFilterGraph *graph_ctx);
  
 +/**
 + * Enable or disable automatic format conversion inside the graph.
 + *
 + * Note that format conversion can still happen inside explicitly inserted
 + * scale and aresample filters.
 + *
 + * @param flags  any of the AVFILTER_AUTO_CONVERT_* constants
 + */
 +void avfilter_graph_set_auto_convert(AVFilterGraph *graph, unsigned flags);
 +
 +enum {
 +    AVFILTER_AUTO_CONVERT_ALL  =  0, /**< all automatic conversions enabled */
 +    AVFILTER_AUTO_CONVERT_NONE = -1, /**< all automatic conversions disabled */
 +};
 +
  /**
   * Check validity and configure all the links and formats in the graph.
   *
@@@ -1082,16 -840,12 +1083,16 @@@ void avfilter_inout_free(AVFilterInOut 
   *
   * @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, a negative AVERROR code on error
 + * @param inputs  pointer to a linked list to the inputs of the graph, may be NULL.
 + *                If non-NULL, *inputs is updated to contain the list of open inputs
 + *                after the parsing, should be freed with avfilter_inout_free().
 + * @param outputs pointer to a linked list to the outputs of the graph, may be NULL.
 + *                If non-NULL, *outputs is updated to contain the list of open outputs
 + *                after the parsing, should be freed with avfilter_inout_free().
 + * @return non negative on success, a negative AVERROR code on error
   */
  int avfilter_graph_parse(AVFilterGraph *graph, const char *filters,
 -                         AVFilterInOut *inputs, AVFilterInOut *outputs,
 +                         AVFilterInOut **inputs, AVFilterInOut **outputs,
                           void *log_ctx);
  
  /**
@@@ -1128,72 -882,4 +1129,72 @@@ int avfilter_graph_parse2(AVFilterGrap
                            AVFilterInOut **inputs,
                            AVFilterInOut **outputs);
  
 +/**
 + * Send a command to one or more filter instances.
 + *
 + * @param graph  the filter graph
 + * @param target the filter(s) to which the command should be sent
 + *               "all" sends to all filters
 + *               otherwise it can be a filter or filter instance name
 + *               which will send the command to all matching filters.
 + * @param cmd    the command to sent, for handling simplicity all commands must be alphanumeric only
 + * @param arg    the argument for the command
 + * @param res    a buffer with size res_size where the filter(s) can return a response.
 + *
 + * @returns >=0 on success otherwise an error code.
 + *              AVERROR(ENOSYS) on unsupported commands
 + */
 +int avfilter_graph_send_command(AVFilterGraph *graph, const char *target, const char *cmd, const char *arg, char *res, int res_len, int flags);
 +
 +/**
 + * Queue a command for one or more filter instances.
 + *
 + * @param graph  the filter graph
 + * @param target the filter(s) to which the command should be sent
 + *               "all" sends to all filters
 + *               otherwise it can be a filter or filter instance name
 + *               which will send the command to all matching filters.
 + * @param cmd    the command to sent, for handling simplicity all commands must be alphanummeric only
 + * @param arg    the argument for the command
 + * @param ts     time at which the command should be sent to the filter
 + *
 + * @note As this executes commands after this function returns, no return code
 + *       from the filter is provided, also AVFILTER_CMD_FLAG_ONE is not supported.
 + */
 +int avfilter_graph_queue_command(AVFilterGraph *graph, const char *target, const char *cmd, const char *arg, int flags, double ts);
 +
 +
 +/**
 + * Dump a graph into a human-readable string representation.
 + *
 + * @param graph    the graph to dump
 + * @param options  formatting options; currently ignored
 + * @return  a string, or NULL in case of memory allocation failure;
 + *          the string must be freed using av_free
 + */
 +char *avfilter_graph_dump(AVFilterGraph *graph, const char *options);
 +
 +/**
 + * Request a frame on the oldest sink link.
 + *
 + * If the request returns AVERROR_EOF, try the next.
 + *
 + * Note that this function is not meant to be the sole scheduling mechanism
 + * of a filtergraph, only a convenience function to help drain a filtergraph
 + * in a balanced way under normal circumstances.
 + *
 + * Also note that AVERROR_EOF does not mean that frames did not arrive on
 + * some of the sinks during the process.
 + * When there are multiple sink links, in case the requested link
 + * returns an EOF, this may cause a filter to flush pending frames
 + * which are sent to another sink link, although unrequested.
 + *
 + * @return  the return value of ff_request_frame(),
 + *          or AVERROR_EOF if all links returned AVERROR_EOF
 + */
 +int avfilter_graph_request_oldest(AVFilterGraph *graph);
 +
 +/**
 + * @}
 + */
  #endif /* AVFILTER_AVFILTER_H */
@@@ -3,20 -3,20 +3,20 @@@
   * Copyright (c) 2008 Vitor Sessak
   * Copyright (c) 2007 Bobby Bingham
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * 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 Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
  
  #include "libavutil/avassert.h"
  #include "libavutil/avstring.h"
 +#include "libavutil/bprint.h"
  #include "libavutil/channel_layout.h"
 -#include "libavutil/common.h"
 -#include "libavutil/log.h"
 +#include "libavutil/opt.h"
 +#include "libavutil/pixdesc.h"
 +#include "libavcodec/avcodec.h" // avcodec_find_best_pix_fmt_of_2()
  #include "avfilter.h"
  #include "formats.h"
  #include "internal.h"
  
 +#define OFFSET(x) offsetof(AVFilterGraph,x)
 +
 +static const AVOption options[]={
 +{"scale_sws_opts"       , "default scale filter options"        , OFFSET(scale_sws_opts)        ,  AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, 0 },
 +{"aresample_swr_opts"   , "default aresample filter options"    , OFFSET(aresample_swr_opts)    ,  AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, 0 },
 +{0}
 +};
 +
 +
  static const AVClass filtergraph_class = {
      .class_name = "AVFilterGraph",
      .item_name  = av_default_item_name,
 +    .option     = options,
      .version    = LIBAVUTIL_VERSION_INT,
 +    .category   = AV_CLASS_CATEGORY_FILTER,
  };
  
  AVFilterGraph *avfilter_graph_alloc(void)
      return ret;
  }
  
+ void ff_filter_graph_remove_filter(AVFilterGraph *graph, AVFilterContext *filter)
+ {
+     int i;
+     for (i = 0; i < graph->nb_filters; i++) {
+         if (graph->filters[i] == filter) {
+             FFSWAP(AVFilterContext*, graph->filters[i],
+                    graph->filters[graph->nb_filters - 1]);
+             graph->nb_filters--;
+             return;
+         }
+     }
+ }
  void avfilter_graph_free(AVFilterGraph **graph)
  {
      if (!*graph)
          return;
-     for (; (*graph)->nb_filters > 0; (*graph)->nb_filters--)
-         avfilter_free((*graph)->filters[(*graph)->nb_filters - 1]);
+     while ((*graph)->nb_filters)
+         avfilter_free((*graph)->filters[0]);
 +    av_freep(&(*graph)->sink_links);
      av_freep(&(*graph)->scale_sws_opts);
 +    av_freep(&(*graph)->aresample_swr_opts);
      av_freep(&(*graph)->resample_lavr_opts);
      av_freep(&(*graph)->filters);
      av_freep(graph);
@@@ -85,7 -85,7 +100,7 @@@ int avfilter_graph_add_filter(AVFilterG
      graph->filters[graph->nb_filters++] = filter;
  
  #if FF_API_FOO_COUNT
 -    graph->filter_count = graph->nb_filters;
 +    graph->filter_count_unused = graph->nb_filters;
  #endif
  
      filter->graph = graph;
@@@ -103,10 -103,8 +118,8 @@@ int avfilter_graph_create_filter(AVFilt
      *filt_ctx = avfilter_graph_alloc_filter(graph_ctx, filt, name);
      if (!*filt_ctx)
          return AVERROR(ENOMEM);
-     if ((ret = avfilter_init_filter(*filt_ctx, args, opaque)) < 0) {
-         graph_ctx->filters[graph_ctx->nb_filters-1] = NULL;
+     if ((ret = avfilter_init_filter(*filt_ctx, args, opaque)) < 0)
          goto fail;
-     }
  
      return 0;
  
@@@ -117,11 -115,6 +130,11 @@@ fail
      return ret;
  }
  
 +void avfilter_graph_set_auto_convert(AVFilterGraph *graph, unsigned flags)
 +{
 +    graph->disable_auto_convert = flags;
 +}
 +
  AVFilterContext *avfilter_graph_alloc_filter(AVFilterGraph *graph,
                                               const AVFilter *filter,
                                               const char *name)
      graph->filters[graph->nb_filters++] = s;
  
  #if FF_API_FOO_COUNT
 -    graph->filter_count = graph->nb_filters;
 +    graph->filter_count_unused = graph->nb_filters;
  #endif
  
      s->graph = graph;
@@@ -164,25 -157,22 +177,25 @@@ static int graph_check_validity(AVFilte
      int i, j;
  
      for (i = 0; i < graph->nb_filters; i++) {
 +        const AVFilterPad *pad;
          filt = graph->filters[i];
  
          for (j = 0; j < filt->nb_inputs; j++) {
              if (!filt->inputs[j] || !filt->inputs[j]->src) {
 +                pad = &filt->input_pads[j];
                  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);
 +                       "Input pad \"%s\" with type %s of the filter instance \"%s\" of %s not connected to any source\n",
 +                       pad->name, av_get_media_type_string(pad->type), filt->name, filt->filter->name);
                  return AVERROR(EINVAL);
              }
          }
  
          for (j = 0; j < filt->nb_outputs; j++) {
              if (!filt->outputs[j] || !filt->outputs[j]->dst) {
 +                pad = &filt->output_pads[j];
                  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);
 +                       "Output pad \"%s\" with type %s of the filter instance \"%s\" of %s not connected to any destination\n",
 +                       pad->name, av_get_media_type_string(pad->type), filt->name, filt->filter->name);
                  return AVERROR(EINVAL);
              }
          }
@@@ -224,101 -214,17 +237,101 @@@ AVFilterContext *avfilter_graph_get_fil
      return NULL;
  }
  
 +static void sanitize_channel_layouts(void *log, AVFilterChannelLayouts *l)
 +{
 +    if (!l)
 +        return;
 +    if (l->nb_channel_layouts) {
 +        if (l->all_layouts || l->all_counts)
 +            av_log(log, AV_LOG_WARNING, "All layouts set on non-empty list\n");
 +        l->all_layouts = l->all_counts = 0;
 +    } else {
 +        if (l->all_counts && !l->all_layouts)
 +            av_log(log, AV_LOG_WARNING, "All counts without all layouts\n");
 +        l->all_layouts = 1;
 +    }
 +}
 +
 +static int filter_query_formats(AVFilterContext *ctx)
 +{
 +    int ret, i;
 +    AVFilterFormats *formats;
 +    AVFilterChannelLayouts *chlayouts;
 +    AVFilterFormats *samplerates;
 +    enum AVMediaType type = ctx->inputs  && ctx->inputs [0] ? ctx->inputs [0]->type :
 +                            ctx->outputs && ctx->outputs[0] ? ctx->outputs[0]->type :
 +                            AVMEDIA_TYPE_VIDEO;
 +
 +    if ((ret = ctx->filter->query_formats(ctx)) < 0) {
 +        if (ret != AVERROR(EAGAIN))
 +            av_log(ctx, AV_LOG_ERROR, "Query format failed for '%s': %s\n",
 +                   ctx->name, av_err2str(ret));
 +        return ret;
 +    }
 +
 +    for (i = 0; i < ctx->nb_inputs; i++)
 +        sanitize_channel_layouts(ctx, ctx->inputs[i]->out_channel_layouts);
 +    for (i = 0; i < ctx->nb_outputs; i++)
 +        sanitize_channel_layouts(ctx, ctx->outputs[i]->in_channel_layouts);
 +
 +    formats = ff_all_formats(type);
 +    if (!formats)
 +        return AVERROR(ENOMEM);
 +    ff_set_common_formats(ctx, formats);
 +    if (type == AVMEDIA_TYPE_AUDIO) {
 +        samplerates = ff_all_samplerates();
 +        if (!samplerates)
 +            return AVERROR(ENOMEM);
 +        ff_set_common_samplerates(ctx, samplerates);
 +        chlayouts = ff_all_channel_layouts();
 +        if (!chlayouts)
 +            return AVERROR(ENOMEM);
 +        ff_set_common_channel_layouts(ctx, chlayouts);
 +    }
 +    return 0;
 +}
 +
 +static int formats_declared(AVFilterContext *f)
 +{
 +    int i;
 +
 +    for (i = 0; i < f->nb_inputs; i++) {
 +        if (!f->inputs[i]->out_formats)
 +            return 0;
 +        if (f->inputs[i]->type == AVMEDIA_TYPE_AUDIO &&
 +            !(f->inputs[i]->out_samplerates &&
 +              f->inputs[i]->out_channel_layouts))
 +            return 0;
 +    }
 +    for (i = 0; i < f->nb_outputs; i++) {
 +        if (!f->outputs[i]->in_formats)
 +            return 0;
 +        if (f->outputs[i]->type == AVMEDIA_TYPE_AUDIO &&
 +            !(f->outputs[i]->in_samplerates &&
 +              f->outputs[i]->in_channel_layouts))
 +            return 0;
 +    }
 +    return 1;
 +}
 +
  static int query_formats(AVFilterGraph *graph, AVClass *log_ctx)
  {
      int i, j, ret;
      int scaler_count = 0, resampler_count = 0;
 +    int count_queried = 0, count_merged = 0, count_already_merged = 0,
 +        count_delayed = 0;
  
 -    /* ask all the sub-filters for their supported media formats */
      for (i = 0; i < graph->nb_filters; i++) {
 -        if (graph->filters[i]->filter->query_formats)
 -            graph->filters[i]->filter->query_formats(graph->filters[i]);
 +        AVFilterContext *f = graph->filters[i];
 +        if (formats_declared(f))
 +            continue;
 +        if (f->filter->query_formats)
 +            ret = filter_query_formats(f);
          else
 -            ff_default_query_formats(graph->filters[i]);
 +            ret = ff_default_query_formats(f);
 +        if (ret < 0 && ret != AVERROR(EAGAIN))
 +            return ret;
 +        count_queried++;
      }
  
      /* go through and merge as many format lists as possible */
              if (!link)
                  continue;
  
 -            if (link->in_formats != link->out_formats &&
 -                !ff_merge_formats(link->in_formats,
 -                                        link->out_formats))
 -                convert_needed = 1;
 -            if (link->type == AVMEDIA_TYPE_AUDIO) {
 -                if (link->in_channel_layouts != link->out_channel_layouts &&
 -                    !ff_merge_channel_layouts(link->in_channel_layouts,
 -                                              link->out_channel_layouts))
 -                    convert_needed = 1;
 -                if (link->in_samplerates != link->out_samplerates &&
 -                    !ff_merge_samplerates(link->in_samplerates,
 -                                          link->out_samplerates))
 +#define MERGE_DISPATCH(field, statement)                                     \
 +            if (!(link->in_ ## field && link->out_ ## field)) {              \
 +                count_delayed++;                                             \
 +            } else if (link->in_ ## field == link->out_ ## field) {          \
 +                count_already_merged++;                                      \
 +            } else {                                                         \
 +                count_merged++;                                              \
 +                statement                                                    \
 +            }
 +            MERGE_DISPATCH(formats,
 +                if (!ff_merge_formats(link->in_formats, link->out_formats,
 +                                      link->type))
                      convert_needed = 1;
 +            )
 +            if (link->type == AVMEDIA_TYPE_AUDIO) {
 +                MERGE_DISPATCH(channel_layouts,
 +                    if (!ff_merge_channel_layouts(link->in_channel_layouts,
 +                                                  link->out_channel_layouts))
 +                        convert_needed = 1;
 +                )
 +                MERGE_DISPATCH(samplerates,
 +                    if (!ff_merge_samplerates(link->in_samplerates,
 +                                              link->out_samplerates))
 +                        convert_needed = 1;
 +                )
              }
 +#undef MERGE_DISPATCH
  
              if (convert_needed) {
                  AVFilterContext *convert;
                          return ret;
                      break;
                  case AVMEDIA_TYPE_AUDIO:
 -                    if (!(filter = avfilter_get_by_name("resample"))) {
 -                        av_log(log_ctx, AV_LOG_ERROR, "'resample' filter "
 +                    if (!(filter = avfilter_get_by_name("aresample"))) {
 +                        av_log(log_ctx, AV_LOG_ERROR, "'aresample' filter "
                                 "not present, cannot convert audio formats.\n");
                          return AVERROR(EINVAL);
                      }
                      snprintf(inst_name, sizeof(inst_name), "auto-inserted resampler %d",
                               resampler_count++);
                      scale_args[0] = '\0';
 -                    if (graph->resample_lavr_opts)
 +                    if (graph->aresample_swr_opts)
                          snprintf(scale_args, sizeof(scale_args), "%s",
 -                                 graph->resample_lavr_opts);
 +                                 graph->aresample_swr_opts);
                      if ((ret = avfilter_graph_create_filter(&convert, filter,
 -                                                            inst_name, scale_args,
 +                                                            inst_name, graph->aresample_swr_opts,
                                                              NULL, graph)) < 0)
                          return ret;
                      break;
                  if ((ret = avfilter_insert_filter(link, convert, 0, 0)) < 0)
                      return ret;
  
 -                convert->filter->query_formats(convert);
 +                filter_query_formats(convert);
                  inlink  = convert->inputs[0];
                  outlink = convert->outputs[0];
 -                if (!ff_merge_formats( inlink->in_formats,  inlink->out_formats) ||
 -                    !ff_merge_formats(outlink->in_formats, outlink->out_formats))
 +                if (!ff_merge_formats( inlink->in_formats,  inlink->out_formats,  inlink->type) ||
 +                    !ff_merge_formats(outlink->in_formats, outlink->out_formats, outlink->type))
                      ret |= AVERROR(ENOSYS);
                  if (inlink->type == AVMEDIA_TYPE_AUDIO &&
                      (!ff_merge_samplerates(inlink->in_samplerates,
          }
      }
  
 +    av_log(graph, AV_LOG_DEBUG, "query_formats: "
 +           "%d queried, %d merged, %d already done, %d delayed\n",
 +           count_queried, count_merged, count_already_merged, count_delayed);
 +    if (count_delayed) {
 +        AVBPrint bp;
 +
 +        if (count_queried || count_merged)
 +            return AVERROR(EAGAIN);
 +        av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC);
 +        for (i = 0; i < graph->nb_filters; i++)
 +            if (!formats_declared(graph->filters[i]))
 +                av_bprintf(&bp, "%s%s", bp.len ? ", " : "",
 +                          graph->filters[i]->name);
 +        av_log(graph, AV_LOG_ERROR,
 +               "The following filters could not choose their formats: %s\n"
 +               "Consider inserting the (a)format filter near their input or "
 +               "output.\n", bp.str);
 +        return AVERROR(EIO);
 +    }
      return 0;
  }
  
 -static int pick_format(AVFilterLink *link)
 +static int pick_format(AVFilterLink *link, AVFilterLink *ref)
  {
      if (!link || !link->in_formats)
          return 0;
  
 +    if (link->type == AVMEDIA_TYPE_VIDEO) {
 +        if(ref && ref->type == AVMEDIA_TYPE_VIDEO){
 +            int has_alpha= av_pix_fmt_desc_get(ref->format)->nb_components % 2 == 0;
 +            enum AVPixelFormat best= AV_PIX_FMT_NONE;
 +            int i;
 +            for (i=0; i<link->in_formats->format_count; i++) {
 +                enum AVPixelFormat p = link->in_formats->formats[i];
 +                best= avcodec_find_best_pix_fmt_of_2(best, p, ref->format, has_alpha, NULL);
 +            }
 +            av_log(link->src,AV_LOG_DEBUG, "picking %s out of %d ref:%s alpha:%d\n",
 +                   av_get_pix_fmt_name(best), link->in_formats->format_count,
 +                   av_get_pix_fmt_name(ref->format), has_alpha);
 +            link->in_formats->formats[0] = best;
 +        }
 +    }
 +
      link->in_formats->format_count = 1;
      link->format = link->in_formats->formats[0];
  
          link->in_samplerates->format_count = 1;
          link->sample_rate = link->in_samplerates->formats[0];
  
 -        if (!link->in_channel_layouts->nb_channel_layouts) {
 +        if (link->in_channel_layouts->all_layouts) {
              av_log(link->src, AV_LOG_ERROR, "Cannot select channel layout for"
 -                   "the link between filters %s and %s.\n", link->src->name,
 +                   " the link between filters %s and %s.\n", link->src->name,
                     link->dst->name);
              return AVERROR(EINVAL);
          }
          link->in_channel_layouts->nb_channel_layouts = 1;
          link->channel_layout = link->in_channel_layouts->channel_layouts[0];
 +        if ((link->channels = FF_LAYOUT2COUNT(link->channel_layout)))
 +            link->channel_layout = 0;
 +        else
 +            link->channels = av_get_channel_layout_nb_channels(link->channel_layout);
      }
  
      ff_formats_unref(&link->in_formats);
@@@ -565,42 -419,8 +578,42 @@@ static int reduce_formats_on_filter(AVF
                     format_count, ff_add_format);
      REDUCE_FORMATS(int,      AVFilterFormats,        samplerates,     formats,
                     format_count, ff_add_format);
 -    REDUCE_FORMATS(uint64_t, AVFilterChannelLayouts, channel_layouts,
 -                   channel_layouts, nb_channel_layouts, ff_add_channel_layout);
 +
 +    /* reduce channel layouts */
 +    for (i = 0; i < filter->nb_inputs; i++) {
 +        AVFilterLink *inlink = filter->inputs[i];
 +        uint64_t fmt;
 +
 +        if (!inlink->out_channel_layouts ||
 +            inlink->out_channel_layouts->nb_channel_layouts != 1)
 +            continue;
 +        fmt = inlink->out_channel_layouts->channel_layouts[0];
 +
 +        for (j = 0; j < filter->nb_outputs; j++) {
 +            AVFilterLink *outlink = filter->outputs[j];
 +            AVFilterChannelLayouts *fmts;
 +
 +            fmts = outlink->in_channel_layouts;
 +            if (inlink->type != outlink->type || fmts->nb_channel_layouts == 1)
 +                continue;
 +
 +            if (fmts->all_layouts) {
 +                /* Turn the infinite list into a singleton */
 +                fmts->all_layouts = fmts->all_counts  = 0;
 +                ff_add_channel_layout(&outlink->in_channel_layouts, fmt);
 +                break;
 +            }
 +
 +            for (k = 0; k < outlink->in_channel_layouts->nb_channel_layouts; k++) {
 +                if (fmts->channel_layouts[k] == fmt) {
 +                    fmts->channel_layouts[0]  = fmt;
 +                    fmts->nb_channel_layouts = 1;
 +                    ret = 1;
 +                    break;
 +                }
 +            }
 +        }
 +    }
  
      return ret;
  }
@@@ -728,23 -548,7 +741,23 @@@ static void swap_channel_layouts_on_fil
              int out_channels      = av_get_channel_layout_nb_channels(out_chlayout);
              int count_diff        = out_channels - in_channels;
              int matched_channels, extra_channels;
 -            int score = 0;
 +            int score = 100000;
 +
 +            if (FF_LAYOUT2COUNT(in_chlayout) || FF_LAYOUT2COUNT(out_chlayout)) {
 +                /* Compute score in case the input or output layout encodes
 +                   a channel count; in this case the score is not altered by
 +                   the computation afterwards, as in_chlayout and
 +                   out_chlayout have both been set to 0 */
 +                if (FF_LAYOUT2COUNT(in_chlayout))
 +                    in_channels = FF_LAYOUT2COUNT(in_chlayout);
 +                if (FF_LAYOUT2COUNT(out_chlayout))
 +                    out_channels = FF_LAYOUT2COUNT(out_chlayout);
 +                score -= 10000 + FFABS(out_channels - in_channels) +
 +                         (in_channels > out_channels ? 10000 : 0);
 +                in_chlayout = out_chlayout = 0;
 +                /* Let the remaining computation run, even if the score
 +                   value is not altered */
 +            }
  
              /* channel substitution */
              for (k = 0; k < FF_ARRAY_ELEMS(ch_subst); k++) {
@@@ -867,50 -671,15 +880,50 @@@ static void swap_sample_fmts(AVFilterGr
  static int pick_formats(AVFilterGraph *graph)
  {
      int i, j, ret;
 +    int change;
 +
 +    do{
 +        change = 0;
 +        for (i = 0; i < graph->nb_filters; i++) {
 +            AVFilterContext *filter = graph->filters[i];
 +            if (filter->nb_inputs){
 +                for (j = 0; j < filter->nb_inputs; j++){
 +                    if(filter->inputs[j]->in_formats && filter->inputs[j]->in_formats->format_count == 1) {
 +                        if ((ret = pick_format(filter->inputs[j], NULL)) < 0)
 +                            return ret;
 +                        change = 1;
 +                    }
 +                }
 +            }
 +            if (filter->nb_outputs){
 +                for (j = 0; j < filter->nb_outputs; j++){
 +                    if(filter->outputs[j]->in_formats && filter->outputs[j]->in_formats->format_count == 1) {
 +                        if ((ret = pick_format(filter->outputs[j], NULL)) < 0)
 +                            return ret;
 +                        change = 1;
 +                    }
 +                }
 +            }
 +            if (filter->nb_inputs && filter->nb_outputs && filter->inputs[0]->format>=0) {
 +                for (j = 0; j < filter->nb_outputs; j++) {
 +                    if(filter->outputs[j]->format<0) {
 +                        if ((ret = pick_format(filter->outputs[j], filter->inputs[0])) < 0)
 +                            return ret;
 +                        change = 1;
 +                    }
 +                }
 +            }
 +        }
 +    }while(change);
  
      for (i = 0; i < graph->nb_filters; i++) {
          AVFilterContext *filter = graph->filters[i];
  
          for (j = 0; j < filter->nb_inputs; j++)
 -            if ((ret = pick_format(filter->inputs[j])) < 0)
 +            if ((ret = pick_format(filter->inputs[j], NULL)) < 0)
                  return ret;
          for (j = 0; j < filter->nb_outputs; j++)
 -            if ((ret = pick_format(filter->outputs[j])) < 0)
 +            if ((ret = pick_format(filter->outputs[j], NULL)) < 0)
                  return ret;
      }
      return 0;
@@@ -924,9 -693,7 +937,9 @@@ static int graph_config_formats(AVFilte
      int ret;
  
      /* find supported formats from sub-filters, and merge along links */
 -    if ((ret = query_formats(graph, log_ctx)) < 0)
 +    while ((ret = query_formats(graph, log_ctx)) == AVERROR(EAGAIN))
 +        av_log(graph, AV_LOG_DEBUG, "query_formats not finished\n");
 +    if (ret < 0)
          return ret;
  
      /* Once everything is merged, it's possible that we'll still have
      return 0;
  }
  
 +static int ff_avfilter_graph_config_pointers(AVFilterGraph *graph,
 +                                             AVClass *log_ctx)
 +{
 +    unsigned i, j;
 +    int sink_links_count = 0, n = 0;
 +    AVFilterContext *f;
 +    AVFilterLink **sinks;
 +
 +    for (i = 0; i < graph->nb_filters; i++) {
 +        f = graph->filters[i];
 +        for (j = 0; j < f->nb_inputs; j++) {
 +            f->inputs[j]->graph     = graph;
 +            f->inputs[j]->age_index = -1;
 +        }
 +        for (j = 0; j < f->nb_outputs; j++) {
 +            f->outputs[j]->graph    = graph;
 +            f->outputs[j]->age_index= -1;
 +        }
 +        if (!f->nb_outputs) {
 +            if (f->nb_inputs > INT_MAX - sink_links_count)
 +                return AVERROR(EINVAL);
 +            sink_links_count += f->nb_inputs;
 +        }
 +    }
 +    sinks = av_calloc(sink_links_count, sizeof(*sinks));
 +    if (!sinks)
 +        return AVERROR(ENOMEM);
 +    for (i = 0; i < graph->nb_filters; i++) {
 +        f = graph->filters[i];
 +        if (!f->nb_outputs) {
 +            for (j = 0; j < f->nb_inputs; j++) {
 +                sinks[n] = f->inputs[j];
 +                f->inputs[j]->age_index = n++;
 +            }
 +        }
 +    }
 +    av_assert0(n == sink_links_count);
 +    graph->sink_links       = sinks;
 +    graph->sink_links_count = sink_links_count;
 +    return 0;
 +}
 +
  static int graph_insert_fifos(AVFilterGraph *graph, AVClass *log_ctx)
  {
      AVFilterContext *f;
@@@ -1038,131 -763,6 +1051,131 @@@ int avfilter_graph_config(AVFilterGrap
          return ret;
      if ((ret = graph_config_links(graphctx, log_ctx)))
          return ret;
 +    if ((ret = ff_avfilter_graph_config_pointers(graphctx, log_ctx)))
 +        return ret;
  
      return 0;
  }
 +
 +int avfilter_graph_send_command(AVFilterGraph *graph, const char *target, const char *cmd, const char *arg, char *res, int res_len, int flags)
 +{
 +    int i, r = AVERROR(ENOSYS);
 +
 +    if(!graph)
 +        return r;
 +
 +    if((flags & AVFILTER_CMD_FLAG_ONE) && !(flags & AVFILTER_CMD_FLAG_FAST)) {
 +        r=avfilter_graph_send_command(graph, target, cmd, arg, res, res_len, flags | AVFILTER_CMD_FLAG_FAST);
 +        if(r != AVERROR(ENOSYS))
 +            return r;
 +    }
 +
 +    if(res_len && res)
 +        res[0]= 0;
 +
 +    for (i = 0; i < graph->nb_filters; i++) {
 +        AVFilterContext *filter = graph->filters[i];
 +        if(!strcmp(target, "all") || (filter->name && !strcmp(target, filter->name)) || !strcmp(target, filter->filter->name)){
 +            r = avfilter_process_command(filter, cmd, arg, res, res_len, flags);
 +            if(r != AVERROR(ENOSYS)) {
 +                if((flags & AVFILTER_CMD_FLAG_ONE) || r<0)
 +                    return r;
 +            }
 +        }
 +    }
 +
 +    return r;
 +}
 +
 +int avfilter_graph_queue_command(AVFilterGraph *graph, const char *target, const char *command, const char *arg, int flags, double ts)
 +{
 +    int i;
 +
 +    if(!graph)
 +        return 0;
 +
 +    for (i = 0; i < graph->nb_filters; i++) {
 +        AVFilterContext *filter = graph->filters[i];
 +        if(filter && (!strcmp(target, "all") || !strcmp(target, filter->name) || !strcmp(target, filter->filter->name))){
 +            AVFilterCommand **queue = &filter->command_queue, *next;
 +            while (*queue && (*queue)->time <= ts)
 +                queue = &(*queue)->next;
 +            next = *queue;
 +            *queue = av_mallocz(sizeof(AVFilterCommand));
 +            (*queue)->command = av_strdup(command);
 +            (*queue)->arg     = av_strdup(arg);
 +            (*queue)->time    = ts;
 +            (*queue)->flags   = flags;
 +            (*queue)->next    = next;
 +            if(flags & AVFILTER_CMD_FLAG_ONE)
 +                return 0;
 +        }
 +    }
 +
 +    return 0;
 +}
 +
 +static void heap_bubble_up(AVFilterGraph *graph,
 +                           AVFilterLink *link, int index)
 +{
 +    AVFilterLink **links = graph->sink_links;
 +
 +    while (index) {
 +        int parent = (index - 1) >> 1;
 +        if (links[parent]->current_pts >= link->current_pts)
 +            break;
 +        links[index] = links[parent];
 +        links[index]->age_index = index;
 +        index = parent;
 +    }
 +    links[index] = link;
 +    link->age_index = index;
 +}
 +
 +static void heap_bubble_down(AVFilterGraph *graph,
 +                             AVFilterLink *link, int index)
 +{
 +    AVFilterLink **links = graph->sink_links;
 +
 +    while (1) {
 +        int child = 2 * index + 1;
 +        if (child >= graph->sink_links_count)
 +            break;
 +        if (child + 1 < graph->sink_links_count &&
 +            links[child + 1]->current_pts < links[child]->current_pts)
 +            child++;
 +        if (link->current_pts < links[child]->current_pts)
 +            break;
 +        links[index] = links[child];
 +        links[index]->age_index = index;
 +        index = child;
 +    }
 +    links[index] = link;
 +    link->age_index = index;
 +}
 +
 +void ff_avfilter_graph_update_heap(AVFilterGraph *graph, AVFilterLink *link)
 +{
 +    heap_bubble_up  (graph, link, link->age_index);
 +    heap_bubble_down(graph, link, link->age_index);
 +}
 +
 +
 +int avfilter_graph_request_oldest(AVFilterGraph *graph)
 +{
 +    while (graph->sink_links_count) {
 +        AVFilterLink *oldest = graph->sink_links[0];
 +        int r = ff_request_frame(oldest);
 +        if (r != AVERROR_EOF)
 +            return r;
 +        av_log(oldest->dst, AV_LOG_DEBUG, "EOF on sink link %s:%s.\n",
 +               oldest->dst ? oldest->dst->name : "unknown",
 +               oldest->dstpad ? oldest->dstpad->name : "unknown");
 +        /* EOF: remove the link from the heap */
 +        if (oldest->age_index < --graph->sink_links_count)
 +            heap_bubble_down(graph, graph->sink_links[graph->sink_links_count],
 +                             oldest->age_index);
 +        oldest->age_index = -1;
 +    }
 +    return AVERROR_EOF;
 +}
@@@ -3,20 -3,20 +3,20 @@@
   * Copyright (c) 2008 Vitor Sessak
   * Copyright (c) 2007 Bobby Bingham
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * 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 Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -99,7 -99,7 +99,7 @@@ static int create_filter(AVFilterContex
      char tmp_args[256];
      int ret;
  
 -    snprintf(inst_name, sizeof(inst_name), "Parsed filter %d %s", index, filt_name);
 +    snprintf(inst_name, sizeof(inst_name), "Parsed_%s_%d", filt_name, index);
  
      filt = avfilter_get_by_name(filt_name);
  
@@@ -379,7 -379,7 +379,7 @@@ int avfilter_graph_parse2(AVFilterGrap
                            AVFilterInOut **inputs,
                            AVFilterInOut **outputs)
  {
 -    int index = 0, ret;
 +    int index = 0, ret = 0;
      char chr = 0;
  
      AVFilterInOut *curr_inputs = NULL, *open_inputs = NULL, *open_outputs = NULL;
          filters += strspn(filters, WHITESPACES);
  
          if ((ret = parse_inputs(&filters, &curr_inputs, &open_outputs, graph)) < 0)
 -            goto fail;
 -
 +            goto end;
          if ((ret = parse_filter(&filter, &filters, graph, index, graph)) < 0)
 -            goto fail;
 +            goto end;
  
  
          if ((ret = link_filter_inouts(filter, &curr_inputs, &open_inputs, graph)) < 0)
 -            goto fail;
 +            goto end;
  
          if ((ret = parse_outputs(&filters, &curr_inputs, &open_inputs, &open_outputs,
                                   graph)) < 0)
 -            goto fail;
 +            goto end;
  
          filters += strspn(filters, WHITESPACES);
          chr = *filters++;
                 "Unable to parse graph description substring: \"%s\"\n",
                 filters - 1);
          ret = AVERROR(EINVAL);
 -        goto fail;
 +        goto end;
      }
  
      append_inout(&open_outputs, &curr_inputs);
  
 +
      *inputs  = open_inputs;
      *outputs = open_outputs;
      return 0;
  
 - fail:
 + fail:end:
-     for (; graph->nb_filters > 0; graph->nb_filters--)
-         avfilter_free(graph->filters[graph->nb_filters - 1]);
+     while (graph->nb_filters)
+         avfilter_free(graph->filters[0]);
      av_freep(&graph->filters);
      avfilter_inout_free(&open_inputs);
      avfilter_inout_free(&open_outputs);
  }
  
  int avfilter_graph_parse(AVFilterGraph *graph, const char *filters,
 -                         AVFilterInOut *open_inputs,
 -                         AVFilterInOut *open_outputs, void *log_ctx)
 +                         AVFilterInOut **open_inputs_ptr, AVFilterInOut **open_outputs_ptr,
 +                         void *log_ctx)
  {
 +#if 0
      int ret;
 +    AVFilterInOut *open_inputs  = open_inputs_ptr  ? *open_inputs_ptr  : NULL;
 +    AVFilterInOut *open_outputs = open_outputs_ptr ? *open_outputs_ptr : NULL;
      AVFilterInOut *cur, *match, *inputs = NULL, *outputs = NULL;
  
      if ((ret = avfilter_graph_parse2(graph, filters, &inputs, &outputs)) < 0)
  
   fail:
      if (ret < 0) {
-         for (; graph->nb_filters > 0; graph->nb_filters--)
-             avfilter_free(graph->filters[graph->nb_filters - 1]);
+         while (graph->nb_filters)
+             avfilter_free(graph->filters[0]);
          av_freep(&graph->filters);
      }
      avfilter_inout_free(&inputs);
      avfilter_inout_free(&outputs);
 -    avfilter_inout_free(&open_inputs);
 -    avfilter_inout_free(&open_outputs);
 +    /* clear open_in/outputs only if not passed as parameters */
 +    if (open_inputs_ptr) *open_inputs_ptr = open_inputs;
 +    else avfilter_inout_free(&open_inputs);
 +    if (open_outputs_ptr) *open_outputs_ptr = open_outputs;
 +    else avfilter_inout_free(&open_outputs);
      return ret;
  }
 +#else
 +    int index = 0, ret = 0;
 +    char chr = 0;
 +
 +    AVFilterInOut *curr_inputs = NULL;
 +    AVFilterInOut *open_inputs  = open_inputs_ptr  ? *open_inputs_ptr  : NULL;
 +    AVFilterInOut *open_outputs = open_outputs_ptr ? *open_outputs_ptr : NULL;
 +
 +    if ((ret = parse_sws_flags(&filters, graph)) < 0)
 +        goto end;
 +
 +    do {
 +        AVFilterContext *filter;
 +        const char *filterchain = filters;
 +        filters += strspn(filters, WHITESPACES);
 +
 +        if ((ret = parse_inputs(&filters, &curr_inputs, &open_outputs, log_ctx)) < 0)
 +            goto end;
 +
 +        if ((ret = parse_filter(&filter, &filters, graph, index, log_ctx)) < 0)
 +            goto end;
 +
 +        if (filter->input_count == 1 && !curr_inputs && !index) {
 +            /* First input pad, assume it is "[in]" if not specified */
 +            const char *tmp = "[in]";
 +            if ((ret = parse_inputs(&tmp, &curr_inputs, &open_outputs, log_ctx)) < 0)
 +                goto end;
 +        }
 +
 +        if ((ret = link_filter_inouts(filter, &curr_inputs, &open_inputs, log_ctx)) < 0)
 +            goto end;
 +
 +        if ((ret = parse_outputs(&filters, &curr_inputs, &open_inputs, &open_outputs,
 +                                 log_ctx)) < 0)
 +            goto end;
 +
 +        filters += strspn(filters, WHITESPACES);
 +        chr = *filters++;
 +
 +        if (chr == ';' && curr_inputs) {
 +            av_log(log_ctx, AV_LOG_ERROR,
 +                   "Invalid filterchain containing an unlabelled output pad: \"%s\"\n",
 +                   filterchain);
 +            ret = AVERROR(EINVAL);
 +            goto end;
 +        }
 +        index++;
 +    } while (chr == ',' || chr == ';');
 +
 +    if (chr) {
 +        av_log(log_ctx, AV_LOG_ERROR,
 +               "Unable to parse graph description substring: \"%s\"\n",
 +               filters - 1);
 +        ret = AVERROR(EINVAL);
 +        goto end;
 +    }
 +
 +    if (curr_inputs) {
 +        /* Last output pad, assume it is "[out]" if not specified */
 +        const char *tmp = "[out]";
 +        if ((ret = parse_outputs(&tmp, &curr_inputs, &open_inputs, &open_outputs,
 +                                 log_ctx)) < 0)
 +            goto end;
 +    }
 +
 +end:
 +    /* clear open_in/outputs only if not passed as parameters */
 +    if (open_inputs_ptr) *open_inputs_ptr = open_inputs;
 +    else avfilter_inout_free(&open_inputs);
 +    if (open_outputs_ptr) *open_outputs_ptr = open_outputs;
 +    else avfilter_inout_free(&open_outputs);
 +    avfilter_inout_free(&curr_inputs);
 +
 +    if (ret < 0) {
 +        for (; graph->nb_filters > 0; graph->nb_filters--)
 +            avfilter_free(graph->filters[graph->nb_filters - 1]);
 +        av_freep(&graph->filters);
 +    }
 +    return ret;
 +}
 +
 +#endif
diff --combined libavfilter/internal.h
@@@ -1,18 -1,18 +1,18 @@@
  /*
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * 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 Libav; if not, write to the Free Software
 + * 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"
 +#include "avfiltergraph.h"
 +#include "formats.h"
 +#include "video.h"
 +
 +#define POOL_SIZE 32
 +typedef struct AVFilterPool {
 +    AVFilterBufferRef *pic[POOL_SIZE];
 +    int count;
 +    int refcount;
 +    int draining;
 +} AVFilterPool;
 +
 +typedef struct AVFilterCommand {
 +    double time;                ///< time expressed in seconds
 +    char *command;              ///< command
 +    char *arg;                  ///< optional argument for the command
 +    int flags;
 +    struct AVFilterCommand *next;
 +} AVFilterCommand;
 +
 +/**
 + * Update the position of a link in the age heap.
 + */
 +void ff_avfilter_graph_update_heap(AVFilterGraph *graph, AVFilterLink *link);
  
  #if !FF_API_AVFILTERPAD_PUBLIC
  /**
@@@ -69,7 -45,7 +69,7 @@@ struct AVFilterPad 
  
      /**
       * Callback function to get a video buffer. If NULL, the filter system will
 -     * use avfilter_default_get_video_buffer().
 +     * use ff_default_get_video_buffer().
       *
       * Input video pads only.
       */
@@@ -77,7 -53,7 +77,7 @@@
  
      /**
       * Callback function to get an audio buffer. If NULL, the filter system will
 -     * use avfilter_default_get_audio_buffer().
 +     * use ff_default_get_audio_buffer().
       *
       * Input audio pads only.
       */
@@@ -147,91 -123,9 +147,91 @@@ void ff_avfilter_default_free_buffer(AV
  /** Tell is a format is contained in the provided list terminated by -1. */
  int ff_fmt_is_in(int fmt, const int *fmts);
  
 -#define FF_DPRINTF_START(ctx, func) av_dlog(NULL, "%-16s: ", #func)
 +/**
 + * Return a copy of a list of integers terminated by -1, or NULL in
 + * case of copy failure.
 + */
 +int *ff_copy_int_list(const int * const list);
 +
 +/**
 + * Return a copy of a list of 64-bit integers, or NULL in case of
 + * copy failure.
 + */
 +int64_t *ff_copy_int64_list(const int64_t * const list);
 +
 +/* Functions to parse audio format arguments */
 +
 +/**
 + * Parse a pixel format.
 + *
 + * @param ret pixel format pointer to where the value should be written
 + * @param arg string to parse
 + * @param log_ctx log context
 + * @return 0 in case of success, a negative AVERROR code on error
 + */
 +int ff_parse_pixel_format(enum AVPixelFormat *ret, const char *arg, void *log_ctx);
 +
 +/**
 + * Parse a sample rate.
 + *
 + * @param ret unsigned integer pointer to where the value should be written
 + * @param arg string to parse
 + * @param log_ctx log context
 + * @return 0 in case of success, a negative AVERROR code on error
 + */
 +int ff_parse_sample_rate(int *ret, const char *arg, void *log_ctx);
 +
 +/**
 + * Parse a time base.
 + *
 + * @param ret unsigned AVRational pointer to where the value should be written
 + * @param arg string to parse
 + * @param log_ctx log context
 + * @return 0 in case of success, a negative AVERROR code on error
 + */
 +int ff_parse_time_base(AVRational *ret, const char *arg, void *log_ctx);
 +
 +/**
 + * Parse a sample format name or a corresponding integer representation.
 + *
 + * @param ret integer pointer to where the value should be written
 + * @param arg string to parse
 + * @param log_ctx log context
 + * @return 0 in case of success, a negative AVERROR code on error
 + */
 +int ff_parse_sample_format(int *ret, const char *arg, void *log_ctx);
 +
 +/**
 + * Parse a channel layout or a corresponding integer representation.
 + *
 + * @param ret 64bit integer pointer to where the value should be written.
 + * @param arg string to parse
 + * @param log_ctx log context
 + * @return 0 in case of success, a negative AVERROR code on error
 + */
 +int ff_parse_channel_layout(int64_t *ret, const char *arg, void *log_ctx);
 +
 +void ff_update_link_current_pts(AVFilterLink *link, int64_t pts);
 +
 +void ff_command_queue_pop(AVFilterContext *filter);
 +
 +/* misc trace functions */
  
 -void ff_dlog_link(void *ctx, AVFilterLink *link, int end);
 +/* #define FF_AVFILTER_TRACE */
 +
 +#ifdef FF_AVFILTER_TRACE
 +#    define ff_tlog(pctx, ...) av_log(pctx, AV_LOG_DEBUG, __VA_ARGS__)
 +#else
 +#    define ff_tlog(pctx, ...) do { if (0) av_log(pctx, AV_LOG_DEBUG, __VA_ARGS__); } while (0)
 +#endif
 +
 +#define FF_TPRINTF_START(ctx, func) ff_tlog(NULL, "%-16s: ", #func)
 +
 +char *ff_get_ref_perms_string(char *buf, size_t buf_size, int perms);
 +
 +void ff_tlog_ref(void *ctx, AVFrame *ref, int end);
 +
 +void ff_tlog_link(void *ctx, AVFilterLink *link, int end);
  
  /**
   * Insert a new pad.
@@@ -289,29 -183,6 +289,29 @@@ int ff_poll_frame(AVFilterLink *link)
   */
  int ff_request_frame(AVFilterLink *link);
  
 +#define AVFILTER_DEFINE_CLASS(fname)            \
 +    static const AVClass fname##_class = {      \
 +        .class_name = #fname,                   \
 +        .item_name  = av_default_item_name,     \
 +        .option     = fname##_options,          \
 +        .version    = LIBAVUTIL_VERSION_INT,    \
 +        .category   = AV_CLASS_CATEGORY_FILTER, \
 +    }
 +
 +AVFilterBufferRef *ff_copy_buffer_ref(AVFilterLink *outlink,
 +                                      AVFilterBufferRef *ref);
 +
 +/**
 + * Find the index of a link.
 + *
 + * I.e. find i such that link == ctx->(in|out)puts[i]
 + */
 +#define FF_INLINK_IDX(link)  ((int)((link)->dstpad - (link)->dst->input_pads))
 +#define FF_OUTLINK_IDX(link) ((int)((link)->srcpad - (link)->src->output_pads))
 +
 +int ff_buffersink_read_compat(AVFilterContext *ctx, AVFilterBufferRef **buf);
 +int ff_buffersink_read_samples_compat(AVFilterContext *ctx, AVFilterBufferRef **pbuf,
 +                                      int nb_samples);
  /**
   * Send a frame of data to the next filter.
   *
   */
  int ff_filter_frame(AVFilterLink *link, AVFrame *frame);
  
 +/**
 + * Flags for AVFilterLink.flags.
 + */
 +enum {
 +
 +    /**
 +     * Frame requests may need to loop in order to be fulfilled.
 +     * A filter must set this flags on an output link if it may return 0 in
 +     * request_frame() without filtering a frame.
 +     */
 +    FF_LINK_FLAG_REQUEST_LOOP = 1,
 +
 +};
 +
  /**
   * Allocate a new filter context and return it.
   *
   */
  AVFilterContext *ff_filter_alloc(const AVFilter *filter, const char *inst_name);
  
+ /**
+  * Remove a filter from a graph;
+  */
+ void ff_filter_graph_remove_filter(AVFilterGraph *graph, AVFilterContext *filter);
  #endif /* AVFILTER_INTERNAL_H */