Merge commit '77cc958f60f73963be4281d6e82ef81707e40c26'
authorMichael Niedermayer <michaelni@gmx.at>
Mon, 5 Aug 2013 07:21:53 +0000 (09:21 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Mon, 5 Aug 2013 07:22:18 +0000 (09:22 +0200)
* commit '77cc958f60f73963be4281d6e82ef81707e40c26':
  lavfi: add const to the AVFilter parameter of avfilter_graph_create_filter()

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

diff --combined libavfilter/avfilter.h
index 6de0f66ae0ef0383b92ef1635ce60049aca74839,c5efdb8374f32fcdb830080eec06eff8c20fb59a..b8d7cc39fd8030a89d10c5bcb4694eb7e1933896
@@@ -2,20 -2,20 +2,20 @@@
   * 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
   */
  
   * @{
   */
  
 +#include <stddef.h>
 +
  #include "libavutil/attributes.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"
  
@@@ -61,6 -61,7 +61,6 @@@ const char *avfilter_configuration(void
   */
  const char *avfilter_license(void);
  
 -
  typedef struct AVFilterContext AVFilterContext;
  typedef struct AVFilterLink    AVFilterLink;
  typedef struct AVFilterPad     AVFilterPad;
@@@ -113,9 -114,6 +113,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;
  
  /**
@@@ -191,8 -186,6 +191,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;
  
  /**
@@@ -236,19 -229,11 +236,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.
@@@ -267,29 -252,22 +267,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);
@@@ -434,28 -407,6 +434,28 @@@ enum AVMediaType avfilter_pad_get_type(
   * and processing them concurrently.
   */
  #define AVFILTER_FLAG_SLICE_THREADS         (1 << 2)
 +/**
 + * Some filters support a generic "enable" expression option that can be used
 + * to enable or disable a filter in the timeline. Filters supporting this
 + * option have this flag set. When the enable expression is false, the default
 + * no-op filter_frame() function is called in place of the filter_frame()
 + * callback defined on each input pad, thus the frame is passed unchanged to
 + * the next filters.
 + */
 +#define AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC  (1 << 16)
 +/**
 + * Same as AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, except that the filter will
 + * have its filter_frame() callback(s) called as usual even when the enable
 + * expression is false. The filter will disable filtering within the
 + * filter_frame() callback(s) itself, for example executing code depending on
 + * the AVFilterContext->is_disabled value.
 + */
 +#define AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL (1 << 17)
 +/**
 + * Handy mask to test whether the filter supports or no the timeline feature
 + * (internally or generically).
 + */
 +#define AVFILTER_FLAG_SUPPORT_TIMELINE (AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL)
  
  /**
   * Filter definition. This defines the pads a filter contains, and all the
@@@ -593,27 -544,6 +593,27 @@@ typedef struct AVFilter 
       * code.
       */
      struct AVFilter *next;
 +
 +    /**
 +     * 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, void *opaque);
  } AVFilter;
  
  /**
@@@ -625,7 -555,7 +625,7 @@@ typedef struct AVFilterInternal AVFilte
  
  /** An instance of a filter */
  struct AVFilterContext {
 -    const AVClass *av_class;              ///< needed for av_log()
 +    const AVClass *av_class;        ///< needed for av_log() and filters common options
  
      const AVFilter *filter;         ///< the AVFilter of which this is an instance
  
       * An opaque struct for libavfilter internal use.
       */
      AVFilterInternal *internal;
 +
 +    struct AVFilterCommand *command_queue;
 +
 +    char *enable_str;               ///< enable expression string
 +    void *enable;                   ///< parsed expression (AVExpr*)
 +    double *var_values;             ///< variable values for the enable expression
 +    int is_disabled;                ///< the enabled state from the last expression evaluation
  };
  
  /**
@@@ -700,7 -623,7 +700,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;
 +
 +    /**
 +     * Number of past frames sent through the link.
 +     */
 +    int64_t frame_count;
  };
  
  /**
  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.
   *
@@@ -905,16 -713,13 +905,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
@@@ -929,40 -734,8 +929,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);
  
@@@ -979,7 -752,7 +979,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);
@@@ -1130,7 -903,7 +1130,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
       * Opaque object for libavfilter internal use.
       */
      AVFilterGraphInternal *internal;
 +
 +    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;
  
  /**
@@@ -1242,25 -1001,10 +1242,25 @@@ int avfilter_graph_add_filter(AVFilterG
   * @return a negative AVERROR error code in case of failure, a non
   * negative value otherwise
   */
- int avfilter_graph_create_filter(AVFilterContext **filt_ctx, AVFilter *filt,
+ int avfilter_graph_create_filter(AVFilterContext **filt_ctx, const AVFilter *filt,
                                   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.
   *
@@@ -1312,20 -1056,10 +1312,20 @@@ AVFilterInOut *avfilter_inout_alloc(voi
   */
  void avfilter_inout_free(AVFilterInOut **inout);
  
 +#if AV_HAVE_INCOMPATIBLE_LIBAV_ABI || !FF_API_OLD_GRAPH_PARSE
  /**
   * Add a graph described by a string to a graph.
   *
 - * @param graph   the filter graph where to link the parsed graph context
 + * @note The caller must provide the lists of inputs and outputs,
 + * which therefore must be known before calling the function.
 + *
 + * @note The inputs parameter describes inputs of the already existing
 + * part of the graph; i.e. from the point of view of the newly created
 + * part, they are outputs. Similarly the outputs parameter describes
 + * outputs of the already existing filters, which are provided as
 + * inputs to the parsed filters.
 + *
 + * @param graph   the filter graph where to link the parsed grap 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
  int avfilter_graph_parse(AVFilterGraph *graph, const char *filters,
                           AVFilterInOut *inputs, AVFilterInOut *outputs,
                           void *log_ctx);
 +#else
 +/**
 + * Add a graph described by a string to a graph.
 + *
 + * @param graph   the filter graph where to link the parsed graph context
 + * @param filters string to be parsed
 + * @param inputs  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
 + * @deprecated Use avfilter_graph_parse_ptr() instead.
 + */
 +attribute_deprecated
 +int avfilter_graph_parse(AVFilterGraph *graph, const char *filters,
 +                         AVFilterInOut **inputs, AVFilterInOut **outputs,
 +                         void *log_ctx);
 +#endif
 +
 +/**
 + * Add a graph described by a string to a graph.
 + *
 + * @param graph   the filter graph where to link the parsed graph context
 + * @param filters string to be parsed
 + * @param inputs  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_ptr(AVFilterGraph *graph, const char *filters,
 +                             AVFilterInOut **inputs, AVFilterInOut **outputs,
 +                             void *log_ctx);
  
  /**
   * Add a graph described by a string to a graph.
   *                     caller using avfilter_inout_free().
   * @return zero on success, a negative AVERROR code on error
   *
 - * @note the difference between avfilter_graph_parse2() and
 - * avfilter_graph_parse() is that in avfilter_graph_parse(), the caller provides
 - * the lists of inputs and outputs, which therefore must be known before calling
 - * the function. On the other hand, avfilter_graph_parse2() \em returns the
 - * inputs and outputs that are left unlinked after parsing the graph and the
 - * caller then deals with them. Another difference is that in
 - * avfilter_graph_parse(), the inputs parameter describes inputs of the
 - * <em>already existing</em> part of the graph; i.e. from the point of view of
 - * the newly created part, they are outputs. Similarly the outputs parameter
 - * describes outputs of the already existing filters, which are provided as
 - * inputs to the parsed filters.
 - * avfilter_graph_parse2() takes the opposite approach -- it makes no reference
 - * whatsoever to already existing parts of the graph and the inputs parameter
 - * will on return contain inputs of the newly parsed part of the graph.
 - * Analogously the outputs parameter will contain outputs of the newly created
 + * @note This function returns the inputs and outputs that are left
 + * unlinked after parsing the graph and the caller then deals with
 + * them.
 + * @note This function makes no reference whatsoever to already
 + * existing parts of the graph and the inputs parameter will on return
 + * contain inputs of the newly parsed part of the graph.  Analogously
 + * the outputs parameter will contain outputs of the newly created
   * filters.
   */
  int avfilter_graph_parse2(AVFilterGraph *graph, const char *filters,
                            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 send, 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);
 +
  /**
   * @}
   */
index 52edb6b2708f115c5bf29bb747b76588b1277cb4,de827355b8e8ff58c935c09cc23c4d23774ff45d..fb78a87de36d9080649e5485c37e02f46947330a
@@@ -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/internal.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 "thread.h"
  
  #define OFFSET(x) offsetof(AVFilterGraph, x)
 -#define FLAGS AV_OPT_FLAG_VIDEO_PARAM
 +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
  static const AVOption filtergraph_options[] = {
      { "thread_type", "Allowed thread types", OFFSET(thread_type), AV_OPT_TYPE_FLAGS,
          { .i64 = AVFILTER_THREAD_SLICE }, 0, INT_MAX, FLAGS, "thread_type" },
          { "slice", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AVFILTER_THREAD_SLICE }, .flags = FLAGS, .unit = "thread_type" },
      { "threads",     "Maximum number of threads", OFFSET(nb_threads),
          AV_OPT_TYPE_INT,   { .i64 = 0 }, 0, INT_MAX, FLAGS },
 +    {"scale_sws_opts"       , "default scale filter options"        , OFFSET(scale_sws_opts)        ,
 +        AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS },
 +    {"aresample_swr_opts"   , "default aresample filter options"    , OFFSET(aresample_swr_opts)    ,
 +        AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS },
      { NULL },
  };
  
@@@ -58,7 -53,6 +58,7 @@@ static const AVClass filtergraph_class 
      .item_name  = av_default_item_name,
      .version    = LIBAVUTIL_VERSION_INT,
      .option     = filtergraph_options,
 +    .category   = AV_CLASS_CATEGORY_FILTER,
  };
  
  #if !HAVE_THREADS
@@@ -115,10 -109,7 +115,10 @@@ void avfilter_graph_free(AVFilterGraph 
  
      ff_graph_thread_free(*graph);
  
 +    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)->internal);
@@@ -138,7 -129,7 +138,7 @@@ int avfilter_graph_add_filter(AVFilterG
  
  #if FF_API_FOO_COUNT
  FF_DISABLE_DEPRECATION_WARNINGS
 -    graph->filter_count = graph->nb_filters;
 +    graph->filter_count_unused = graph->nb_filters;
  FF_ENABLE_DEPRECATION_WARNINGS
  #endif
  
  }
  #endif
  
- int avfilter_graph_create_filter(AVFilterContext **filt_ctx, AVFilter *filt,
+ int avfilter_graph_create_filter(AVFilterContext **filt_ctx, const AVFilter *filt,
                                   const char *name, const char *args, void *opaque,
                                   AVFilterGraph *graph_ctx)
  {
@@@ -171,11 -162,6 +171,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)
  
  #if FF_API_FOO_COUNT
  FF_DISABLE_DEPRECATION_WARNINGS
 -    graph->filter_count = graph->nb_filters;
 +    graph->filter_count_unused = graph->nb_filters;
  FF_ENABLE_DEPRECATION_WARNINGS
  #endif
  
@@@ -228,25 -214,22 +228,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);
              }
          }
@@@ -288,156 -271,17 +288,156 @@@ 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 AVFilterFormats *clone_filter_formats(AVFilterFormats *arg)
 +{
 +    AVFilterFormats *a = av_memdup(arg, sizeof(*arg));
 +    if (a) {
 +        a->refcount = 0;
 +        a->refs     = NULL;
 +        a->formats  = av_memdup(a->formats, sizeof(*a->formats) * a->nb_formats);
 +        if (!a->formats && arg->formats)
 +            av_freep(&a);
 +    }
 +    return a;
 +}
 +
 +static int can_merge_formats(AVFilterFormats *a_arg,
 +                             AVFilterFormats *b_arg,
 +                             enum AVMediaType type,
 +                             int is_sample_rate)
 +{
 +    AVFilterFormats *a, *b, *ret;
 +    if (a_arg == b_arg)
 +        return 1;
 +    a = clone_filter_formats(a_arg);
 +    b = clone_filter_formats(b_arg);
 +    if (is_sample_rate) {
 +        ret = ff_merge_samplerates(a, b);
 +    } else {
 +        ret = ff_merge_formats(a, b, type);
 +    }
 +    if (ret) {
 +        av_freep(&ret->formats);
 +        av_freep(&ret->refs);
 +        av_freep(&ret);
 +        return 1;
 +    } else {
 +        av_freep(&a->formats);
 +        av_freep(&b->formats);
 +        av_freep(&a);
 +        av_freep(&b);
 +        return 0;
 +    }
 +}
 +
 +/**
 + * Perform one round of query_formats() and merging formats lists on the
 + * filter graph.
 + * @return  >=0 if all links formats lists could be queried and merged;
 + *          AVERROR(EAGAIN) some progress was made in the queries or merging
 + *          and a later call may succeed;
 + *          AVERROR(EIO) (may be changed) plus a log message if no progress
 + *          was made and the negotiation is stuck;
 + *          a negative error code if some other error happened
 + */
  static int query_formats(AVFilterGraph *graph, AVClass *log_ctx)
  {
      int i, j, ret;
      int scaler_count = 0, resampler_count = 0;
 +    int count_queried = 0;        /* successful calls to query_formats() */
 +    int count_merged = 0;         /* successful merge of formats lists */
 +    int count_already_merged = 0; /* lists already merged */
 +    int count_delayed = 0;        /* lists that need to be merged later */
  
 -    /* 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;
 +        /* note: EAGAIN could indicate a partial success, not counted yet */
 +        count_queried += ret >= 0;
      }
  
      /* 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))
 +            if (link->in_formats != link->out_formats
 +                && link->in_formats && link->out_formats)
 +                if (!can_merge_formats(link->in_formats, link->out_formats,
 +                                      link->type, 0))
                      convert_needed = 1;
 +            if (link->type == AVMEDIA_TYPE_AUDIO) {
 +                if (link->in_samplerates != link->out_samplerates
 +                    && link->in_samplerates && link->out_samplerates)
 +                    if (!can_merge_formats(link->in_samplerates,
 +                                           link->out_samplerates,
 +                                           0, 1))
 +                        convert_needed = 1;
 +            }
 +
 +#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 if (!convert_needed) {                                    \
 +                count_merged++;                                              \
 +                statement                                                    \
              }
  
 +            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;
 +                )
 +            }
 +            MERGE_DISPATCH(formats,
 +                if (!ff_merge_formats(link->in_formats, link->out_formats,
 +                                      link->type))
 +                    convert_needed = 1;
 +            )
 +#undef MERGE_DISPATCH
 +
              if (convert_needed) {
                  AVFilterContext *convert;
                  AVFilter *filter;
                          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 > 0, one filter at least did set its formats,
 +           that will give additional information to its neighbour;
 +           if count_merged > 0, one pair of formats lists at least was merged,
 +           that will give additional information to all connected filters;
 +           in both cases, progress was made and a new round must be done */
 +        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->nb_formats; 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->nb_formats,
 +                   av_get_pix_fmt_name(ref->format), has_alpha);
 +            link->in_formats->formats[0] = best;
 +        }
 +    }
 +
      link->in_formats->nb_formats = 1;
      link->format = link->in_formats->formats[0];
  
          link->in_samplerates->nb_formats = 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);
@@@ -678,7 -450,6 +678,7 @@@ do 
                                                                         \
              if (!out_link->in_ ## list->nb) {                          \
                  add_format(&out_link->in_ ##list, fmt);                \
 +                ret = 1;                                               \
                  break;                                                 \
              }                                                          \
                                                                         \
@@@ -701,42 -472,8 +701,42 @@@ static int reduce_formats_on_filter(AVF
                     nb_formats, ff_add_format);
      REDUCE_FORMATS(int,      AVFilterFormats,        samplerates,     formats,
                     nb_formats, 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;
  }
@@@ -864,23 -601,7 +864,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++) {
@@@ -1003,50 -724,15 +1003,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->nb_formats == 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->nb_formats == 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;
@@@ -1060,9 -746,7 +1060,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;
@@@ -1174,131 -816,6 +1174,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;
 +}