Merge remote-tracking branch 'qatar/master'
authorMichael Niedermayer <michaelni@gmx.at>
Thu, 10 May 2012 20:41:29 +0000 (22:41 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Thu, 10 May 2012 21:30:42 +0000 (23:30 +0200)
* qatar/master: (25 commits)
  rv40dsp x86: MMX/MMX2/3DNow/SSE2/SSSE3 implementations of MC
  ape: Use unsigned integer maths
  arm: dsputil: fix overreads in put/avg_pixels functions
  h264: K&R formatting cosmetics for header files (part II/II)
  h264: K&R formatting cosmetics for header files (part I/II)
  rtmp: Implement check bandwidth notification.
  rtmp: Support 'rtmp_swfurl', an option which specifies the URL of the SWF player.
  rtmp: Support 'rtmp_flashver', an option which overrides the version of the Flash plugin.
  rtmp: Support 'rtmp_tcurl', an option which overrides the URL of the target stream.
  cmdutils: Add fallback case to switch in check_stream_specifier().
  sctp: be consistent with socket option level
  configure: Add _XOPEN_SOURCE=600 to Solaris preprocessor flags.
  vcr1enc: drop pointless empty encode_init() wrapper function
  vcr1: drop pointless write-only AVCodecContext member from VCR1Context
  vcr1: group encoder code together to save #ifdefs
  vcr1: cosmetics: K&R prettyprinting, typos, parentheses, dead code, comments
  mov: make one comment slightly more specific
  lavr: replace the SSE version of ff_conv_fltp_to_flt_6ch() with SSE4 and AVX
  lavfi: move audio-related functions to a separate file.
  lavfi: remove some audio-related function from public API.
  ...

Conflicts:
cmdutils.c
libavcodec/h264.h
libavcodec/h264_mvpred.h
libavcodec/vcr1.c
libavfilter/avfilter.c
libavfilter/avfilter.h
libavfilter/defaults.c
libavfilter/internal.h

Merged-by: Michael Niedermayer <michaelni@gmx.at>
40 files changed:
1  2 
cmdutils.c
configure
libavcodec/apedec.c
libavcodec/arm/dsputil_neon.S
libavcodec/h264.h
libavcodec/h264_mvpred.h
libavcodec/h264data.h
libavcodec/h264dsp.h
libavcodec/h264pred.h
libavcodec/vcr1.c
libavcodec/x86/dsputil_mmx.c
libavcodec/x86/dsputil_mmx.h
libavcodec/x86/rv40dsp.asm
libavfilter/Makefile
libavfilter/af_aconvert.c
libavfilter/af_aformat.c
libavfilter/af_amerge.c
libavfilter/af_anull.c
libavfilter/af_aresample.c
libavfilter/af_ashowinfo.c
libavfilter/af_asplit.c
libavfilter/af_astreamsync.c
libavfilter/af_earwax.c
libavfilter/af_pan.c
libavfilter/af_silencedetect.c
libavfilter/af_volume.c
libavfilter/asrc_aevalsrc.c
libavfilter/asrc_anullsrc.c
libavfilter/audio.c
libavfilter/audio.h
libavfilter/avfilter.c
libavfilter/avfilter.h
libavfilter/defaults.c
libavfilter/internal.h
libavfilter/src_buffer.c
libavfilter/src_movie.c
libavfilter/version.h
libavformat/mov.c
libavformat/rtmpproto.c
libavutil/x86/x86util.asm

diff --cc cmdutils.c
  #include "libavdevice/avdevice.h"
  #include "libavresample/avresample.h"
  #include "libswscale/swscale.h"
 +#include "libswresample/swresample.h"
 +#if CONFIG_POSTPROC
 +#include "libpostproc/postprocess.h"
 +#endif
+ #include "libavutil/avassert.h"
  #include "libavutil/avstring.h"
  #include "libavutil/mathematics.h"
  #include "libavutil/parseutils.h"
diff --cc configure
Simple merge
Simple merge
Simple merge
  #include "rectangle.h"
  
  #define interlaced_dct interlaced_dct_is_a_bad_name
- #define mb_intra mb_intra_is_not_initialized_see_mb_type
+ #define mb_intra       mb_intra_is_not_initialized_see_mb_type
  
- #define MAX_SPS_COUNT 32
- #define MAX_PPS_COUNT 256
+ #define MAX_SPS_COUNT          32
+ #define MAX_PPS_COUNT         256
  
- #define MAX_MMCO_COUNT 66
+ #define MAX_MMCO_COUNT         66
  
- #define MAX_DELAYED_PIC_COUNT 16
+ #define MAX_DELAYED_PIC_COUNT  16
  
 +#define MAX_MBPAIR_SIZE (256*1024) // a tighter bound could be calculated if someone cares about a few bytes
 +
  /* Compiling in interlaced support reduces the speed
   * of progressive decoding by about 2%. */
  #define ALLOW_INTERLACE
@@@ -225,14 -221,14 +224,14 @@@ typedef struct PPS 
      int init_qs;                ///< pic_init_qs_minus26 + 26
      int chroma_qp_index_offset[2];
      int deblocking_filter_parameters_present; ///< deblocking_filter_parameters_present_flag
-     int constrained_intra_pred; ///< constrained_intra_pred_flag
-     int redundant_pic_cnt_present; ///< redundant_pic_cnt_present_flag
-     int transform_8x8_mode;     ///< transform_8x8_mode_flag
+     int constrained_intra_pred;     ///< constrained_intra_pred_flag
+     int redundant_pic_cnt_present;  ///< redundant_pic_cnt_present_flag
+     int transform_8x8_mode;         ///< transform_8x8_mode_flag
      uint8_t scaling_matrix4[6][16];
      uint8_t scaling_matrix8[6][64];
 -    uint8_t chroma_qp_table[2][64]; ///< pre-scaled (with chroma_qp_index_offset) version of qp_table
 +    uint8_t chroma_qp_table[2][QP_MAX_NUM+1];  ///< pre-scaled (with chroma_qp_index_offset) version of qp_table
      int chroma_qp_diff;
- }PPS;
+ } PPS;
  
  /**
   * Memory management control operation opcode.
@@@ -574,34 -569,18 +572,33 @@@ typedef struct H264Context 
       * frames.
       */
      int sei_recovery_frame_cnt;
 +    /**
 +     * recovery_frame is the frame_num at which the next frame should
 +     * be fully constructed.
 +     *
 +     * Set to -1 when not expecting a recovery point.
 +     */
 +    int recovery_frame;
  
-     int luma_weight_flag[2];   ///< 7.4.3.2 luma_weight_lX_flag
-     int chroma_weight_flag[2]; ///< 7.4.3.2 chroma_weight_lX_flag
+     int luma_weight_flag[2];    ///< 7.4.3.2 luma_weight_lX_flag
+     int chroma_weight_flag[2];  ///< 7.4.3.2 chroma_weight_lX_flag
  
      // Timestamp stuff
-     int sei_buffering_period_present;  ///< Buffering period SEI flag
-     int initial_cpb_removal_delay[32]; ///< Initial timestamps for CPBs
+     int sei_buffering_period_present;   ///< Buffering period SEI flag
+     int initial_cpb_removal_delay[32];  ///< Initial timestamps for CPBs
  
      int cur_chroma_format_idc;
- }H264Context;
 +
 +    int16_t slice_row[MAX_SLICES]; ///< to detect when MAX_SLICES is too low
 +
 +    int sync;                      ///< did we had a keyframe or recovery point
 +
 +    uint8_t parse_history[4];
 +    int parse_history_count;
 +    int parse_last_mb;
+ } H264Context;
  
- extern const uint8_t ff_h264_chroma_qp[5][QP_MAX_NUM+1]; ///< One chroma qp table for each possible bit depth (8-12).
 -extern const uint8_t ff_h264_chroma_qp[3][QP_MAX_NUM + 1]; ///< One chroma qp table for each supported bit depth (8, 9, 10).
++extern const uint8_t ff_h264_chroma_qp[5][QP_MAX_NUM + 1]; ///< One chroma qp table for each possible bit depth (8-12).
  extern const uint16_t ff_h264_mb_sizes[4];
  
  /**
@@@ -625,23 -659,26 +659,26 @@@ static void fill_decode_caches(H264Cont
                  }
              }
  
-             if(USES_LIST(topright_type, list)){
-                 const int b_xy= h->mb2b_xy[topright_xy] + 3*b_stride;
-                 AV_COPY32(mv_cache[4 - 1*8], mv[b_xy]);
-                 ref_cache[4 - 1*8]= ref[4*topright_xy + 2];
-             }else{
-                 AV_ZERO32(mv_cache[4 - 1*8]);
-                 ref_cache[4 - 1*8]= topright_type ? LIST_NOT_USED : PART_NOT_AVAILABLE;
+             if (USES_LIST(topright_type, list)) {
+                 const int b_xy = h->mb2b_xy[topright_xy] + 3 * b_stride;
+                 AV_COPY32(mv_cache[4 - 1 * 8], mv[b_xy]);
+                 ref_cache[4 - 1 * 8] = ref[4 * topright_xy + 2];
+             } else {
+                 AV_ZERO32(mv_cache[4 - 1 * 8]);
+                 ref_cache[4 - 1 * 8] = topright_type ? LIST_NOT_USED
+                                                      : PART_NOT_AVAILABLE;
              }
 -            if (ref_cache[4 - 1 * 8] < 0) {
 +            if(ref_cache[2 - 1*8] < 0 || ref_cache[4 - 1*8] < 0){
-                 if(USES_LIST(topleft_type, list)){
-                     const int b_xy = h->mb2b_xy[topleft_xy] + 3 + b_stride + (h->topleft_partition & 2*b_stride);
-                     const int b8_xy= 4*topleft_xy + 1 + (h->topleft_partition & 2);
-                     AV_COPY32(mv_cache[-1 - 1*8], mv[b_xy]);
-                     ref_cache[-1 - 1*8]= ref[b8_xy];
-                 }else{
-                     AV_ZERO32(mv_cache[-1 - 1*8]);
-                     ref_cache[-1 - 1*8]= topleft_type ? LIST_NOT_USED : PART_NOT_AVAILABLE;
+                 if (USES_LIST(topleft_type, list)) {
+                     const int b_xy  = h->mb2b_xy[topleft_xy] + 3 + b_stride +
+                                       (h->topleft_partition & 2 * b_stride);
+                     const int b8_xy = 4 * topleft_xy + 1 + (h->topleft_partition & 2);
+                     AV_COPY32(mv_cache[-1 - 1 * 8], mv[b_xy]);
+                     ref_cache[-1 - 1 * 8] = ref[b8_xy];
+                 } else {
+                     AV_ZERO32(mv_cache[-1 - 1 * 8]);
+                     ref_cache[-1 - 1 * 8] = topleft_type ? LIST_NOT_USED
+                                                          : PART_NOT_AVAILABLE;
                  }
              }
  
Simple merge
Simple merge
Simple merge
@@@ -41,28 -33,48 +33,54 @@@ typedef struct VCR1Context 
      int offset[4];
  } VCR1Context;
  
- static int decode_frame(AVCodecContext *avctx,
-                         void *data, int *data_size,
-                         AVPacket *avpkt)
+ static av_cold void common_init(AVCodecContext *avctx)
+ {
+     VCR1Context *const a = avctx->priv_data;
+     avctx->coded_frame = &a->picture;
++    avcodec_get_frame_defaults(&a->picture);
+ }
+ static av_cold int decode_init(AVCodecContext *avctx)
+ {
+     common_init(avctx);
+     avctx->pix_fmt = PIX_FMT_YUV410P;
+     return 0;
+ }
+ static av_cold int decode_end(AVCodecContext *avctx)
+ {
+     VCR1Context *s = avctx->priv_data;
+     if (s->picture.data[0])
+         avctx->release_buffer(avctx, &s->picture);
+     return 0;
+ }
+ static int decode_frame(AVCodecContext *avctx, void *data,
+                         int *data_size, AVPacket *avpkt)
  {
-     const uint8_t *buf = avpkt->data;
-     int buf_size = avpkt->size;
-     VCR1Context * const a = avctx->priv_data;
-     AVFrame *picture = data;
-     AVFrame * const p = &a->picture;
-     const uint8_t *bytestream= buf;
+     const uint8_t *buf        = avpkt->data;
+     int buf_size              = avpkt->size;
+     VCR1Context *const a      = avctx->priv_data;
+     AVFrame *picture          = data;
+     AVFrame *const p          = &a->picture;
+     const uint8_t *bytestream = buf;
      int i, x, y;
  
-     if(p->data[0])
+     if (p->data[0])
          avctx->release_buffer(avctx, p);
  
-     p->reference= 0;
-     if(avctx->get_buffer(avctx, p) < 0){
 +    if(buf_size < 16 + avctx->height + avctx->width*avctx->height*5/8){
 +        av_log(avctx, AV_LOG_ERROR, "Insufficient input data.\n");
 +        return AVERROR(EINVAL);
 +    }
 +
+     p->reference = 0;
+     if (avctx->get_buffer(avctx, p) < 0) {
          av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
          return -1;
      }
Simple merge
Simple merge
Simple merge
Simple merge
index 8c1b5dc,0000000..e0f3474
mode 100644,000000..100644
--- /dev/null
@@@ -1,177 -1,0 +1,177 @@@
-     AVFilterBufferRef *outsamplesref = avfilter_get_audio_buffer(outlink, AV_PERM_WRITE, n);
 +/*
 + * Copyright (c) 2010 S.N. Hemanth Meenakshisundaram <smeenaks@ucsd.edu>
 + * Copyright (c) 2011 Stefano Sabatini
 + * Copyright (c) 2011 Mina Nagy Zaki
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +/**
 + * @file
 + * sample format and channel layout conversion audio filter
 + */
 +
 +#include "libavutil/avstring.h"
 +#include "libswresample/swresample.h"
 +#include "avfilter.h"
 +#include "internal.h"
 +
 +typedef struct {
 +    enum AVSampleFormat  out_sample_fmt;
 +    int64_t              out_chlayout;
 +    struct SwrContext *swr;
 +} AConvertContext;
 +
 +static av_cold int init(AVFilterContext *ctx, const char *args0, void *opaque)
 +{
 +    AConvertContext *aconvert = ctx->priv;
 +    char *arg, *ptr = NULL;
 +    int ret = 0;
 +    char *args = av_strdup(args0);
 +
 +    aconvert->out_sample_fmt  = AV_SAMPLE_FMT_NONE;
 +    aconvert->out_chlayout    = 0;
 +
 +    if ((arg = av_strtok(args, ":", &ptr)) && strcmp(arg, "auto")) {
 +        if ((ret = ff_parse_sample_format(&aconvert->out_sample_fmt, arg, ctx)) < 0)
 +            goto end;
 +    }
 +    if ((arg = av_strtok(NULL, ":", &ptr)) && strcmp(arg, "auto")) {
 +        if ((ret = ff_parse_channel_layout(&aconvert->out_chlayout, arg, ctx)) < 0)
 +            goto end;
 +    }
 +
 +end:
 +    av_freep(&args);
 +    return ret;
 +}
 +
 +static av_cold void uninit(AVFilterContext *ctx)
 +{
 +    AConvertContext *aconvert = ctx->priv;
 +    swr_free(&aconvert->swr);
 +}
 +
 +static int query_formats(AVFilterContext *ctx)
 +{
 +    AVFilterFormats *formats = NULL;
 +    AConvertContext *aconvert = ctx->priv;
 +    AVFilterLink *inlink  = ctx->inputs[0];
 +    AVFilterLink *outlink = ctx->outputs[0];
 +    int out_packing = av_sample_fmt_is_planar(aconvert->out_sample_fmt);
 +
 +    avfilter_formats_ref(avfilter_make_all_formats(AVMEDIA_TYPE_AUDIO),
 +                         &inlink->out_formats);
 +    if (aconvert->out_sample_fmt != AV_SAMPLE_FMT_NONE) {
 +        formats = NULL;
 +        avfilter_add_format(&formats, aconvert->out_sample_fmt);
 +        avfilter_formats_ref(formats, &outlink->in_formats);
 +    } else
 +        avfilter_formats_ref(avfilter_make_all_formats(AVMEDIA_TYPE_AUDIO),
 +                             &outlink->in_formats);
 +
 +    avfilter_formats_ref(avfilter_make_all_channel_layouts(),
 +                         &inlink->out_chlayouts);
 +    if (aconvert->out_chlayout != 0) {
 +        formats = NULL;
 +        avfilter_add_format(&formats, aconvert->out_chlayout);
 +        avfilter_formats_ref(formats, &outlink->in_chlayouts);
 +    } else
 +        avfilter_formats_ref(avfilter_make_all_channel_layouts(),
 +                             &outlink->in_chlayouts);
 +
 +    avfilter_formats_ref(avfilter_make_all_packing_formats(),
 +                         &inlink->out_packing);
 +    formats = NULL;
 +    avfilter_add_format(&formats, out_packing);
 +    avfilter_formats_ref(formats, &outlink->in_packing);
 +
 +    return 0;
 +}
 +
 +static int config_output(AVFilterLink *outlink)
 +{
 +    int ret;
 +    AVFilterContext *ctx = outlink->src;
 +    AVFilterLink *inlink = ctx->inputs[0];
 +    AConvertContext *aconvert = ctx->priv;
 +    char buf1[64], buf2[64];
 +
 +    /* if not specified in args, use the format and layout of the output */
 +    if (aconvert->out_sample_fmt == AV_SAMPLE_FMT_NONE)
 +        aconvert->out_sample_fmt = outlink->format;
 +    if (aconvert->out_chlayout   == 0)
 +        aconvert->out_chlayout   = outlink->channel_layout;
 +
 +    aconvert->swr = swr_alloc_set_opts(aconvert->swr,
 +                                       aconvert->out_chlayout, aconvert->out_sample_fmt, inlink->sample_rate,
 +                                       inlink->channel_layout, inlink->format,           inlink->sample_rate,
 +                                       0, ctx);
 +    if (!aconvert->swr)
 +        return AVERROR(ENOMEM);
 +    ret = swr_init(aconvert->swr);
 +    if (ret < 0)
 +        return ret;
 +
 +    av_get_channel_layout_string(buf1, sizeof(buf1),
 +                                 -1, inlink ->channel_layout);
 +    av_get_channel_layout_string(buf2, sizeof(buf2),
 +                                 -1, outlink->channel_layout);
 +    av_log(ctx, AV_LOG_INFO,
 +           "fmt:%s cl:%s planar:%i -> fmt:%s cl:%s planar:%i\n",
 +           av_get_sample_fmt_name(inlink ->format), buf1, inlink ->planar,
 +           av_get_sample_fmt_name(outlink->format), buf2, outlink->planar);
 +
 +    return 0;
 +}
 +
 +static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamplesref)
 +{
 +    AConvertContext *aconvert = inlink->dst->priv;
 +    const int n = insamplesref->audio->nb_samples;
 +    AVFilterLink *const outlink = inlink->dst->outputs[0];
-     avfilter_filter_samples(outlink, outsamplesref);
++    AVFilterBufferRef *outsamplesref = ff_get_audio_buffer(outlink, AV_PERM_WRITE, n);
 +
 +    swr_convert(aconvert->swr, outsamplesref->data, n,
 +                        (void *)insamplesref->data, n);
 +
 +    avfilter_copy_buffer_ref_props(outsamplesref, insamplesref);
 +    outsamplesref->audio->channel_layout = outlink->channel_layout;
 +    outsamplesref->audio->planar         = outlink->planar;
 +
++    ff_filter_samples(outlink, outsamplesref);
 +    avfilter_unref_buffer(insamplesref);
 +}
 +
 +AVFilter avfilter_af_aconvert = {
 +    .name          = "aconvert",
 +    .description   = NULL_IF_CONFIG_SMALL("Convert the input audio to sample_fmt:channel_layout:packed_fmt."),
 +    .priv_size     = sizeof(AConvertContext),
 +    .init          = init,
 +    .uninit        = uninit,
 +    .query_formats = query_formats,
 +
 +    .inputs    = (const AVFilterPad[]) {{ .name      = "default",
 +                                    .type            = AVMEDIA_TYPE_AUDIO,
 +                                    .filter_samples  = filter_samples,
 +                                    .min_perms       = AV_PERM_READ, },
 +                                  { .name = NULL}},
 +    .outputs   = (const AVFilterPad[]) {{ .name      = "default",
 +                                    .type            = AVMEDIA_TYPE_AUDIO,
 +                                    .config_props    = config_output, },
 +                                  { .name = NULL}},
 +};
index e7ef7f0,0000000..ab64840
mode 100644,000000..100644
--- /dev/null
@@@ -1,109 -1,0 +1,109 @@@
-     avfilter_filter_samples(inlink->dst->outputs[0], insamplesref);
 +/*
 + * Copyright (c) 2011 Mina Nagy Zaki
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +/**
 + * @file
 + * format audio filter
 + */
 +
 +#include "libavutil/audioconvert.h"
 +#include "libavutil/avstring.h"
 +#include "avfilter.h"
 +#include "internal.h"
 +
 +typedef struct {
 +    AVFilterFormats *formats, *chlayouts, *packing;
 +} AFormatContext;
 +
 +static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
 +{
 +    AFormatContext * const aformat = ctx->priv;
 +    char *fmts_str = NULL, *fmt_str, *ptr = NULL;
 +    int64_t fmt;
 +    int ret;
 +
 +    if (!args)
 +        goto arg_fail;
 +
 +#define ADD_FORMATS(all_formats, fmt_name, fmt_type, fmts_list) do {    \
 +    fmts_str = av_get_token(&args, ":");                                \
 +    if (!fmts_str || !*fmts_str)                                        \
 +        goto arg_fail;                                                  \
 +    if (!strcmp(fmts_str, "all")) {                                     \
 +        aformat->fmts_list = all_formats;                               \
 +    } else {                                                            \
 +        for (fmt_str = fmts_str;                                        \
 +             fmt_str = av_strtok(fmt_str, ",", &ptr); fmt_str = NULL) { \
 +            if ((ret = ff_parse_##fmt_name((fmt_type *)&fmt,            \
 +                                           fmt_str, ctx)) < 0) {        \
 +                av_freep(&fmts_str);                                    \
 +                return ret;                                             \
 +            }                                                           \
 +            avfilter_add_format(&aformat->fmts_list, fmt);              \
 +        }                                                               \
 +    }                                                                   \
 +    av_freep(&fmts_str);                                                \
 +    if (*args)                                                          \
 +        args++;                                                         \
 +} while (0)
 +
 +    ADD_FORMATS(avfilter_make_all_formats(AVMEDIA_TYPE_AUDIO), sample_format, int, formats);
 +    ADD_FORMATS(avfilter_make_all_channel_layouts(), channel_layout, int64_t, chlayouts);
 +    ADD_FORMATS(avfilter_make_all_packing_formats(), packing_format, int, packing);
 +
 +    return 0;
 +
 +arg_fail:
 +    av_log(ctx, AV_LOG_ERROR, "Invalid arguments, they must be of the form "
 +                              "sample_fmts:channel_layouts:packing_fmts\n");
 +    av_freep(&fmts_str);
 +    return AVERROR(EINVAL);
 +}
 +
 +static int query_formats(AVFilterContext *ctx)
 +{
 +    AFormatContext * const aformat = ctx->priv;
 +
 +    avfilter_set_common_sample_formats (ctx, aformat->formats);
 +    avfilter_set_common_channel_layouts(ctx, aformat->chlayouts);
 +    avfilter_set_common_packing_formats(ctx, aformat->packing);
 +    return 0;
 +}
 +
 +static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamplesref)
 +{
++    ff_filter_samples(inlink->dst->outputs[0], insamplesref);
 +}
 +
 +AVFilter avfilter_af_aformat = {
 +    .name          = "aformat",
 +    .description   = NULL_IF_CONFIG_SMALL("Convert the input audio to one of the specified formats."),
 +    .init          = init,
 +    .query_formats = query_formats,
 +    .priv_size     = sizeof(AFormatContext),
 +
 +    .inputs        = (const AVFilterPad[]) {{ .name      = "default",
 +                                        .type            = AVMEDIA_TYPE_AUDIO,
 +                                        .filter_samples  = filter_samples},
 +                                      { .name = NULL}},
 +    .outputs       = (const AVFilterPad[]) {{ .name      = "default",
 +                                        .type            = AVMEDIA_TYPE_AUDIO},
 +                                      { .name = NULL}},
 +};
index a160391,0000000..6d141fe
mode 100644,000000..100644
--- /dev/null
@@@ -1,296 -1,0 +1,296 @@@
-     outbuf = avfilter_get_audio_buffer(ctx->outputs[0], AV_PERM_WRITE,
 +/*
 + * Copyright (c) 2011 Nicolas George <nicolas.george@normalesup.org>
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +/**
 + * @file
 + * Audio merging filter
 + */
 +
 +#include "libswresample/swresample.h" // only for SWR_CH_MAX
 +#include "avfilter.h"
 +#include "internal.h"
 +
 +#define QUEUE_SIZE 16
 +
 +typedef struct {
 +    int nb_in_ch[2];       /**< number of channels for each input */
 +    int route[SWR_CH_MAX]; /**< channels routing, see copy_samples */
 +    int bps;
 +    struct amerge_queue {
 +        AVFilterBufferRef *buf[QUEUE_SIZE];
 +        int nb_buf, nb_samples, pos;
 +    } queue[2];
 +} AMergeContext;
 +
 +static av_cold void uninit(AVFilterContext *ctx)
 +{
 +    AMergeContext *am = ctx->priv;
 +    int i, j;
 +
 +    for (i = 0; i < 2; i++)
 +        for (j = 0; j < am->queue[i].nb_buf; j++)
 +            avfilter_unref_buffer(am->queue[i].buf[j]);
 +}
 +
 +static int query_formats(AVFilterContext *ctx)
 +{
 +    AMergeContext *am = ctx->priv;
 +    int64_t inlayout[2], outlayout;
 +    const int packing_fmts[] = { AVFILTER_PACKED, -1 };
 +    AVFilterFormats *formats;
 +    int i;
 +
 +    for (i = 0; i < 2; i++) {
 +        if (!ctx->inputs[i]->in_chlayouts ||
 +            !ctx->inputs[i]->in_chlayouts->format_count) {
 +            av_log(ctx, AV_LOG_ERROR,
 +                   "No channel layout for input %d\n", i + 1);
 +            return AVERROR(EINVAL);
 +        }
 +        inlayout[i] = ctx->inputs[i]->in_chlayouts->formats[0];
 +        if (ctx->inputs[i]->in_chlayouts->format_count > 1) {
 +            char buf[256];
 +            av_get_channel_layout_string(buf, sizeof(buf), 0, inlayout[i]);
 +            av_log(ctx, AV_LOG_INFO, "Using \"%s\" for input %d\n", buf, i + 1);
 +        }
 +        am->nb_in_ch[i] = av_get_channel_layout_nb_channels(inlayout[i]);
 +    }
 +    if (am->nb_in_ch[0] + am->nb_in_ch[1] > SWR_CH_MAX) {
 +        av_log(ctx, AV_LOG_ERROR, "Too many channels (max %d)\n", SWR_CH_MAX);
 +        return AVERROR(EINVAL);
 +    }
 +    if (inlayout[0] & inlayout[1]) {
 +        av_log(ctx, AV_LOG_WARNING,
 +               "Inputs overlap: output layout will be meaningless\n");
 +        for (i = 0; i < am->nb_in_ch[0] + am->nb_in_ch[1]; i++)
 +            am->route[i] = i;
 +        outlayout = av_get_default_channel_layout(am->nb_in_ch[0] +
 +                                                  am->nb_in_ch[1]);
 +        if (!outlayout)
 +            outlayout = ((int64_t)1 << (am->nb_in_ch[0] + am->nb_in_ch[1])) - 1;
 +    } else {
 +        int *route[2] = { am->route, am->route + am->nb_in_ch[0] };
 +        int c, out_ch_number = 0;
 +
 +        outlayout = inlayout[0] | inlayout[1];
 +        for (c = 0; c < 64; c++)
 +            for (i = 0; i < 2; i++)
 +                if ((inlayout[i] >> c) & 1)
 +                    *(route[i]++) = out_ch_number++;
 +    }
 +    formats = avfilter_make_all_formats(AVMEDIA_TYPE_AUDIO);
 +    avfilter_set_common_sample_formats(ctx, formats);
 +    formats = avfilter_make_format_list(packing_fmts);
 +    avfilter_set_common_packing_formats(ctx, formats);
 +    for (i = 0; i < 2; i++) {
 +        formats = NULL;
 +        avfilter_add_format(&formats, inlayout[i]);
 +        avfilter_formats_ref(formats, &ctx->inputs[i]->out_chlayouts);
 +    }
 +    formats = NULL;
 +    avfilter_add_format(&formats, outlayout);
 +    avfilter_formats_ref(formats, &ctx->outputs[0]->in_chlayouts);
 +    return 0;
 +}
 +
 +static int config_output(AVFilterLink *outlink)
 +{
 +    AVFilterContext *ctx = outlink->src;
 +    AMergeContext *am = ctx->priv;
 +    int64_t layout;
 +    char name[3][256];
 +    int i;
 +
 +    if (ctx->inputs[0]->sample_rate != ctx->inputs[1]->sample_rate) {
 +        av_log(ctx, AV_LOG_ERROR,
 +               "Inputs must have the same sample rate "
 +               "(%"PRIi64" vs %"PRIi64")\n",
 +               ctx->inputs[0]->sample_rate, ctx->inputs[1]->sample_rate);
 +        return AVERROR(EINVAL);
 +    }
 +    am->bps = av_get_bytes_per_sample(ctx->outputs[0]->format);
 +    outlink->sample_rate = ctx->inputs[0]->sample_rate;
 +    outlink->time_base   = ctx->inputs[0]->time_base;
 +    for (i = 0; i < 3; i++) {
 +        layout = (i < 2 ? ctx->inputs[i] : ctx->outputs[0])->channel_layout;
 +        av_get_channel_layout_string(name[i], sizeof(name[i]), -1, layout);
 +    }
 +    av_log(ctx, AV_LOG_INFO,
 +           "in1:%s + in2:%s -> out:%s\n", name[0], name[1], name[2]);
 +    return 0;
 +}
 +
 +static int request_frame(AVFilterLink *outlink)
 +{
 +    AVFilterContext *ctx = outlink->src;
 +    AMergeContext *am = ctx->priv;
 +    int i, ret;
 +
 +    for (i = 0; i < 2; i++)
 +        if (!am->queue[i].nb_samples)
 +            if ((ret = avfilter_request_frame(ctx->inputs[i])) < 0)
 +                return ret;
 +    return 0;
 +}
 +
 +/**
 + * Copy samples from two input streams to one output stream.
 + * @param nb_in_ch  number of channels in each input stream
 + * @param route     routing values;
 + *                  input channel i goes to output channel route[i];
 + *                  i <  nb_in_ch[0] are the channels from the first output;
 + *                  i >= nb_in_ch[0] are the channels from the second output
 + * @param ins       pointer to the samples of each inputs, in packed format;
 + *                  will be left at the end of the copied samples
 + * @param outs      pointer to the samples of the output, in packet format;
 + *                  must point to a buffer big enough;
 + *                  will be left at the end of the copied samples
 + * @param ns        number of samples to copy
 + * @param bps       bytes per sample
 + */
 +static inline void copy_samples(int nb_in_ch[2], int *route, uint8_t *ins[2],
 +                                uint8_t **outs, int ns, int bps)
 +{
 +    int *route_cur;
 +    int i, c;
 +
 +    while (ns--) {
 +        route_cur = route;
 +        for (i = 0; i < 2; i++) {
 +            for (c = 0; c < nb_in_ch[i]; c++) {
 +                memcpy((*outs) + bps * *(route_cur++), ins[i], bps);
 +                ins[i] += bps;
 +            }
 +        }
 +        *outs += (nb_in_ch[0] + nb_in_ch[1]) * bps;
 +    }
 +}
 +
 +static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples)
 +{
 +    AVFilterContext *ctx = inlink->dst;
 +    AMergeContext *am = ctx->priv;
 +    AVFilterLink *const outlink = ctx->outputs[0];
 +    int input_number = inlink == ctx->inputs[1];
 +    struct amerge_queue *inq = &am->queue[input_number];
 +    int nb_samples, ns, i;
 +    AVFilterBufferRef *outbuf, **inbuf[2];
 +    uint8_t *ins[2], *outs;
 +
 +    if (inq->nb_buf == QUEUE_SIZE) {
 +        av_log(ctx, AV_LOG_ERROR, "Packet queue overflow; dropped\n");
 +        avfilter_unref_buffer(insamples);
 +        return;
 +    }
 +    inq->buf[inq->nb_buf++] = avfilter_ref_buffer(insamples, AV_PERM_READ |
 +                                                             AV_PERM_PRESERVE);
 +    inq->nb_samples += insamples->audio->nb_samples;
 +    avfilter_unref_buffer(insamples);
 +    if (!am->queue[!input_number].nb_samples)
 +        return;
 +
 +    nb_samples = FFMIN(am->queue[0].nb_samples,
 +                       am->queue[1].nb_samples);
-     avfilter_filter_samples(ctx->outputs[0], outbuf);
++    outbuf = ff_get_audio_buffer(ctx->outputs[0], AV_PERM_WRITE,
 +                                       nb_samples);
 +    outs = outbuf->data[0];
 +    for (i = 0; i < 2; i++) {
 +        inbuf[i] = am->queue[i].buf;
 +        ins[i] = (*inbuf[i])->data[0] +
 +                 am->queue[i].pos * am->nb_in_ch[i] * am->bps;
 +    }
 +
 +    avfilter_copy_buffer_ref_props(outbuf, *inbuf[0]);
 +    outbuf->audio->nb_samples     = nb_samples;
 +    outbuf->audio->channel_layout = outlink->channel_layout;
 +    outbuf->audio->planar         = outlink->planar;
 +
 +    while (nb_samples) {
 +        ns = nb_samples;
 +        for (i = 0; i < 2; i++)
 +            ns = FFMIN(ns, (*inbuf[i])->audio->nb_samples - am->queue[i].pos);
 +        /* Unroll the most common sample formats: speed +~350% for the loop,
 +           +~13% overall (including two common decoders) */
 +        switch (am->bps) {
 +            case 1:
 +                copy_samples(am->nb_in_ch, am->route, ins, &outs, ns, 1);
 +                break;
 +            case 2:
 +                copy_samples(am->nb_in_ch, am->route, ins, &outs, ns, 2);
 +                break;
 +            case 4:
 +                copy_samples(am->nb_in_ch, am->route, ins, &outs, ns, 4);
 +                break;
 +            default:
 +                copy_samples(am->nb_in_ch, am->route, ins, &outs, ns, am->bps);
 +                break;
 +        }
 +
 +        nb_samples -= ns;
 +        for (i = 0; i < 2; i++) {
 +            am->queue[i].nb_samples -= ns;
 +            am->queue[i].pos += ns;
 +            if (am->queue[i].pos == (*inbuf[i])->audio->nb_samples) {
 +                am->queue[i].pos = 0;
 +                avfilter_unref_buffer(*inbuf[i]);
 +                *inbuf[i] = NULL;
 +                inbuf[i]++;
 +                ins[i] = *inbuf[i] ? (*inbuf[i])->data[0] : NULL;
 +            }
 +        }
 +    }
 +    for (i = 0; i < 2; i++) {
 +        int nbufused = inbuf[i] - am->queue[i].buf;
 +        if (nbufused) {
 +            am->queue[i].nb_buf -= nbufused;
 +            memmove(am->queue[i].buf, inbuf[i],
 +                    am->queue[i].nb_buf * sizeof(**inbuf));
 +        }
 +    }
++    ff_filter_samples(ctx->outputs[0], outbuf);
 +}
 +
 +AVFilter avfilter_af_amerge = {
 +    .name          = "amerge",
 +    .description   = NULL_IF_CONFIG_SMALL("Merge two audio streams into "
 +                                          "a single multi-channel stream."),
 +    .priv_size     = sizeof(AMergeContext),
 +    .uninit        = uninit,
 +    .query_formats = query_formats,
 +
 +    .inputs    = (const AVFilterPad[]) {
 +        { .name             = "in1",
 +          .type             = AVMEDIA_TYPE_AUDIO,
 +          .filter_samples   = filter_samples,
 +          .min_perms        = AV_PERM_READ, },
 +        { .name             = "in2",
 +          .type             = AVMEDIA_TYPE_AUDIO,
 +          .filter_samples   = filter_samples,
 +          .min_perms        = AV_PERM_READ, },
 +        { .name = NULL }
 +    },
 +    .outputs   = (const AVFilterPad[]) {
 +        { .name             = "default",
 +          .type             = AVMEDIA_TYPE_AUDIO,
 +          .config_props     = config_output,
 +          .request_frame    = request_frame, },
 +        { .name = NULL }
 +    },
 +};
@@@ -29,13 -30,13 +30,13 @@@ AVFilter avfilter_af_anull = 
  
      .priv_size = 0,
  
 -    .inputs    = (AVFilterPad[]) {{ .name             = "default",
 +    .inputs    = (const AVFilterPad[]) {{ .name       = "default",
                                      .type             = AVMEDIA_TYPE_AUDIO,
-                                     .get_audio_buffer = avfilter_null_get_audio_buffer,
-                                     .filter_samples   = avfilter_null_filter_samples },
+                                     .get_audio_buffer = ff_null_get_audio_buffer,
+                                     .filter_samples   = ff_null_filter_samples },
                                    { .name = NULL}},
  
 -    .outputs   = (AVFilterPad[]) {{ .name             = "default",
 +    .outputs   = (const AVFilterPad[]) {{ .name       = "default",
                                      .type             = AVMEDIA_TYPE_AUDIO, },
                                    { .name = NULL}},
  };
index 786fb85,0000000..23980d1
mode 100644,000000..100644
--- /dev/null
@@@ -1,126 -1,0 +1,126 @@@
-     AVFilterBufferRef *outsamplesref = avfilter_get_audio_buffer(outlink, AV_PERM_WRITE, n_out);
 +/*
 + * Copyright (c) 2011 Stefano Sabatini
 + * Copyright (c) 2011 Mina Nagy Zaki
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +/**
 + * @file
 + * resampling audio filter
 + */
 +
 +#include "libswresample/swresample.h"
 +#include "avfilter.h"
 +#include "internal.h"
 +
 +typedef struct {
 +    int out_rate;
 +    double ratio;
 +    struct SwrContext *swr;
 +} AResampleContext;
 +
 +static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
 +{
 +    AResampleContext *aresample = ctx->priv;
 +    int ret;
 +
 +    if (args) {
 +        if ((ret = ff_parse_sample_rate(&aresample->out_rate, args, ctx)) < 0)
 +            return ret;
 +    } else {
 +        aresample->out_rate = -1;
 +    }
 +
 +    return 0;
 +}
 +
 +static av_cold void uninit(AVFilterContext *ctx)
 +{
 +    AResampleContext *aresample = ctx->priv;
 +    swr_free(&aresample->swr);
 +}
 +
 +static int config_output(AVFilterLink *outlink)
 +{
 +    int ret;
 +    AVFilterContext *ctx = outlink->src;
 +    AVFilterLink *inlink = ctx->inputs[0];
 +    AResampleContext *aresample = ctx->priv;
 +
 +    if (aresample->out_rate == -1)
 +        aresample->out_rate = outlink->sample_rate;
 +    else
 +        outlink->sample_rate = aresample->out_rate;
 +    outlink->time_base = (AVRational) {1, aresample->out_rate};
 +
 +    //TODO: make the resampling parameters (filter size, phrase shift, linear, cutoff) configurable
 +    aresample->swr = swr_alloc_set_opts(aresample->swr,
 +                                        inlink->channel_layout, inlink->format, aresample->out_rate,
 +                                        inlink->channel_layout, inlink->format, inlink->sample_rate,
 +                                        0, ctx);
 +    if (!aresample->swr)
 +        return AVERROR(ENOMEM);
 +    ret = swr_init(aresample->swr);
 +    if (ret < 0)
 +        return ret;
 +
 +    aresample->ratio = (double)outlink->sample_rate / inlink->sample_rate;
 +
 +    av_log(ctx, AV_LOG_INFO, "r:%"PRId64"Hz -> r:%"PRId64"Hz\n",
 +           inlink->sample_rate, outlink->sample_rate);
 +    return 0;
 +}
 +
 +static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamplesref)
 +{
 +    AResampleContext *aresample = inlink->dst->priv;
 +    const int n_in  = insamplesref->audio->nb_samples;
 +    int n_out       = n_in * aresample->ratio;
 +    AVFilterLink *const outlink = inlink->dst->outputs[0];
-     avfilter_filter_samples(outlink, outsamplesref);
++    AVFilterBufferRef *outsamplesref = ff_get_audio_buffer(outlink, AV_PERM_WRITE, n_out);
 +
 +    n_out = swr_convert(aresample->swr, outsamplesref->data, n_out,
 +                                 (void *)insamplesref->data, n_in);
 +
 +    avfilter_copy_buffer_ref_props(outsamplesref, insamplesref);
 +    outsamplesref->audio->sample_rate = outlink->sample_rate;
 +    outsamplesref->audio->nb_samples  = n_out;
 +    outsamplesref->pts = insamplesref->pts == AV_NOPTS_VALUE ? AV_NOPTS_VALUE :
 +        av_rescale(outlink->sample_rate, insamplesref->pts, inlink ->sample_rate);
 +
++    ff_filter_samples(outlink, outsamplesref);
 +    avfilter_unref_buffer(insamplesref);
 +}
 +
 +AVFilter avfilter_af_aresample = {
 +    .name          = "aresample",
 +    .description   = NULL_IF_CONFIG_SMALL("Resample audio data."),
 +    .init          = init,
 +    .uninit        = uninit,
 +    .priv_size     = sizeof(AResampleContext),
 +
 +    .inputs    = (const AVFilterPad[]) {{ .name      = "default",
 +                                    .type            = AVMEDIA_TYPE_AUDIO,
 +                                    .filter_samples  = filter_samples,
 +                                    .min_perms       = AV_PERM_READ, },
 +                                  { .name = NULL}},
 +    .outputs   = (const AVFilterPad[]) {{ .name      = "default",
 +                                    .config_props    = config_output,
 +                                    .type            = AVMEDIA_TYPE_AUDIO, },
 +                                  { .name = NULL}},
 +};
index 12d0315,0000000..c336c52
mode 100644,000000..100644
--- /dev/null
@@@ -1,106 -1,0 +1,106 @@@
-     avfilter_filter_samples(inlink->dst->outputs[0], samplesref);
 +/*
 + * Copyright (c) 2011 Stefano Sabatini
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +/**
 + * @file
 + * filter for showing textual audio frame information
 + */
 +
 +#include "libavutil/adler32.h"
 +#include "libavutil/audioconvert.h"
 +#include "libavutil/timestamp.h"
 +#include "avfilter.h"
 +
 +typedef struct {
 +    unsigned int frame;
 +} ShowInfoContext;
 +
 +static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
 +{
 +    ShowInfoContext *showinfo = ctx->priv;
 +    showinfo->frame = 0;
 +    return 0;
 +}
 +
 +static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *samplesref)
 +{
 +    AVFilterContext *ctx = inlink->dst;
 +    ShowInfoContext *showinfo = ctx->priv;
 +    uint32_t plane_checksum[8] = {0}, checksum = 0;
 +    char chlayout_str[128];
 +    int plane;
 +    int linesize =
 +        samplesref->audio->nb_samples *
 +        av_get_bytes_per_sample(samplesref->format);
 +    if (!samplesref->audio->planar) /* packed layout */
 +        linesize *= av_get_channel_layout_nb_channels(samplesref->audio->channel_layout);
 +
 +    for (plane = 0; samplesref->data[plane] && plane < 8; plane++) {
 +        uint8_t *data = samplesref->data[plane];
 +
 +        plane_checksum[plane] = av_adler32_update(plane_checksum[plane],
 +                                                  data, linesize);
 +        checksum = av_adler32_update(checksum, data, linesize);
 +    }
 +
 +    av_get_channel_layout_string(chlayout_str, sizeof(chlayout_str), -1,
 +                                 samplesref->audio->channel_layout);
 +
 +    av_log(ctx, AV_LOG_INFO,
 +           "n:%d pts:%s pts_time:%s pos:%"PRId64" "
 +           "fmt:%s chlayout:%s nb_samples:%d rate:%d planar:%d "
 +           "checksum:%08X plane_checksum[%08X",
 +           showinfo->frame,
 +           av_ts2str(samplesref->pts), av_ts2timestr(samplesref->pts, &inlink->time_base),
 +           samplesref->pos,
 +           av_get_sample_fmt_name(samplesref->format),
 +           chlayout_str,
 +           samplesref->audio->nb_samples,
 +           samplesref->audio->sample_rate,
 +           samplesref->audio->planar,
 +           checksum,
 +           plane_checksum[0]);
 +
 +    for (plane = 1; samplesref->data[plane] && plane < 8; plane++)
 +        av_log(ctx, AV_LOG_INFO, " %08X", plane_checksum[plane]);
 +    av_log(ctx, AV_LOG_INFO, "]\n");
 +
 +    showinfo->frame++;
-                                     .get_audio_buffer = avfilter_null_get_audio_buffer,
++    ff_filter_samples(inlink->dst->outputs[0], samplesref);
 +}
 +
 +AVFilter avfilter_af_ashowinfo = {
 +    .name        = "ashowinfo",
 +    .description = NULL_IF_CONFIG_SMALL("Show textual information for each audio frame."),
 +
 +    .priv_size = sizeof(ShowInfoContext),
 +    .init      = init,
 +
 +    .inputs    = (const AVFilterPad[]) {{ .name       = "default",
 +                                    .type             = AVMEDIA_TYPE_AUDIO,
++                                    .get_audio_buffer = ff_null_get_audio_buffer,
 +                                    .filter_samples   = filter_samples,
 +                                    .min_perms        = AV_PERM_READ, },
 +                                  { .name = NULL}},
 +
 +    .outputs   = (const AVFilterPad[]) {{ .name       = "default",
 +                                    .type             = AVMEDIA_TYPE_AUDIO },
 +                                  { .name = NULL}},
 +};
index ec5032b,0000000..3bdbeac
mode 100644,000000..100644
--- /dev/null
@@@ -1,55 -1,0 +1,55 @@@
-     avfilter_filter_samples(inlink->dst->outputs[0],
 +/*
 + * Copyright (c) 2011 Stefano Sabatini
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +/**
 + * @file
 + * audio splitter
 + */
 +
 +#include "avfilter.h"
 +
 +static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples)
 +{
-     avfilter_filter_samples(inlink->dst->outputs[1],
++    ff_filter_samples(inlink->dst->outputs[0],
 +                            avfilter_ref_buffer(insamples, ~AV_PERM_WRITE));
-           .get_audio_buffer = avfilter_null_get_audio_buffer,
++    ff_filter_samples(inlink->dst->outputs[1],
 +                            avfilter_ref_buffer(insamples, ~AV_PERM_WRITE));
 +    avfilter_unref_buffer(insamples);
 +}
 +
 +AVFilter avfilter_af_asplit = {
 +    .name        = "asplit",
 +    .description = NULL_IF_CONFIG_SMALL("Pass on the audio input to two outputs."),
 +
 +    .inputs = (const AVFilterPad[]) {
 +        { .name             = "default",
 +          .type             = AVMEDIA_TYPE_AUDIO,
++          .get_audio_buffer = ff_null_get_audio_buffer,
 +          .filter_samples   = filter_samples, },
 +        { .name = NULL}
 +    },
 +    .outputs = (const AVFilterPad[]) {
 +        { .name             = "output1",
 +          .type             = AVMEDIA_TYPE_AUDIO, },
 +        { .name             = "output2",
 +          .type             = AVMEDIA_TYPE_AUDIO, },
 +        { .name = NULL}
 +    },
 +};
index ccf55c0,0000000..2e8a02c
mode 100644,000000..100644
--- /dev/null
@@@ -1,208 -1,0 +1,208 @@@
-     avfilter_filter_samples(ctx->outputs[out_id], buf);
 +/*
 + * Copyright (c) 2011 Nicolas George <nicolas.george@normalesup.org>
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +/**
 + * @file
 + * Stream (de)synchronization filter
 + */
 +
 +#include "libavutil/eval.h"
 +#include "avfilter.h"
 +#include "internal.h"
 +
 +#define QUEUE_SIZE 16
 +
 +static const char * const var_names[] = {
 +    "b1", "b2",
 +    "s1", "s2",
 +    "t1", "t2",
 +    NULL
 +};
 +
 +enum var_name {
 +    VAR_B1, VAR_B2,
 +    VAR_S1, VAR_S2,
 +    VAR_T1, VAR_T2,
 +    VAR_NB
 +};
 +
 +typedef struct {
 +    AVExpr *expr;
 +    double var_values[VAR_NB];
 +    struct buf_queue {
 +        AVFilterBufferRef *buf[QUEUE_SIZE];
 +        unsigned tail, nb;
 +        /* buf[tail] is the oldest,
 +           buf[(tail + nb) % QUEUE_SIZE] is where the next is added */
 +    } queue[2];
 +    int req[2];
 +    int next_out;
 +    int eof; /* bitmask, one bit for each stream */
 +} AStreamSyncContext;
 +
 +static const char *default_expr = "t1-t2";
 +
 +static av_cold int init(AVFilterContext *ctx, const char *args0, void *opaque)
 +{
 +    AStreamSyncContext *as = ctx->priv;
 +    const char *expr = args0 ? args0 : default_expr;
 +    int r, i;
 +
 +    r = av_expr_parse(&as->expr, expr, var_names,
 +                      NULL, NULL, NULL, NULL, 0, ctx);
 +    if (r < 0) {
 +        av_log(ctx, AV_LOG_ERROR, "Error in expression \"%s\"\n", expr);
 +        return r;
 +    }
 +    for (i = 0; i < 42; i++)
 +        av_expr_eval(as->expr, as->var_values, NULL); /* exercize prng */
 +    return 0;
 +}
 +
 +static int query_formats(AVFilterContext *ctx)
 +{
 +    int i;
 +    AVFilterFormats *formats;
 +
 +    for (i = 0; i < 2; i++) {
 +        formats = ctx->inputs[i]->in_formats;
 +        avfilter_formats_ref(formats, &ctx->inputs[i]->out_formats);
 +        avfilter_formats_ref(formats, &ctx->outputs[i]->in_formats);
 +        formats = ctx->inputs[i]->in_packing;
 +        avfilter_formats_ref(formats, &ctx->inputs[i]->out_packing);
 +        avfilter_formats_ref(formats, &ctx->outputs[i]->in_packing);
 +        formats = ctx->inputs[i]->in_chlayouts;
 +        avfilter_formats_ref(formats, &ctx->inputs[i]->out_chlayouts);
 +        avfilter_formats_ref(formats, &ctx->outputs[i]->in_chlayouts);
 +    }
 +    return 0;
 +}
 +
 +static int config_output(AVFilterLink *outlink)
 +{
 +    AVFilterContext *ctx = outlink->src;
 +    int id = outlink == ctx->outputs[1];
 +
 +    outlink->sample_rate = ctx->inputs[id]->sample_rate;
 +    outlink->time_base   = ctx->inputs[id]->time_base;
 +    return 0;
 +}
 +
 +static void send_out(AVFilterContext *ctx, int out_id)
 +{
 +    AStreamSyncContext *as = ctx->priv;
 +    struct buf_queue *queue = &as->queue[out_id];
 +    AVFilterBufferRef *buf = queue->buf[queue->tail];
 +
 +    queue->buf[queue->tail] = NULL;
 +    as->var_values[VAR_B1 + out_id]++;
 +    as->var_values[VAR_S1 + out_id] += buf->audio->nb_samples;
 +    if (buf->pts != AV_NOPTS_VALUE)
 +        as->var_values[VAR_T1 + out_id] =
 +            av_q2d(ctx->outputs[out_id]->time_base) * buf->pts;
 +    as->var_values[VAR_T1 + out_id] += buf->audio->nb_samples /
 +                                   (double)ctx->inputs[out_id]->sample_rate;
++    ff_filter_samples(ctx->outputs[out_id], buf);
 +    queue->nb--;
 +    queue->tail = (queue->tail + 1) % QUEUE_SIZE;
 +    if (as->req[out_id])
 +        as->req[out_id]--;
 +}
 +
 +static void send_next(AVFilterContext *ctx)
 +{
 +    AStreamSyncContext *as = ctx->priv;
 +    int i;
 +
 +    while (1) {
 +        if (!as->queue[as->next_out].nb)
 +            break;
 +        send_out(ctx, as->next_out);
 +        if (!as->eof)
 +            as->next_out = av_expr_eval(as->expr, as->var_values, NULL) >= 0;
 +    }
 +    for (i = 0; i < 2; i++)
 +        if (as->queue[i].nb == QUEUE_SIZE)
 +            send_out(ctx, i);
 +}
 +
 +static int request_frame(AVFilterLink *outlink)
 +{
 +    AVFilterContext *ctx = outlink->src;
 +    AStreamSyncContext *as = ctx->priv;
 +    int id = outlink == ctx->outputs[1];
 +
 +    as->req[id]++;
 +    while (as->req[id] && !(as->eof & (1 << id))) {
 +        if (as->queue[as->next_out].nb) {
 +            send_next(ctx);
 +        } else {
 +            as->eof |= 1 << as->next_out;
 +            avfilter_request_frame(ctx->inputs[as->next_out]);
 +            if (as->eof & (1 << as->next_out))
 +                as->next_out = !as->next_out;
 +        }
 +    }
 +    return 0;
 +}
 +
 +static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples)
 +{
 +    AVFilterContext *ctx = inlink->dst;
 +    AStreamSyncContext *as = ctx->priv;
 +    int id = inlink == ctx->inputs[1];
 +
 +    as->queue[id].buf[(as->queue[id].tail + as->queue[id].nb++) % QUEUE_SIZE] =
 +        insamples;
 +    as->eof &= ~(1 << id);
 +    send_next(ctx);
 +}
 +
 +AVFilter avfilter_af_astreamsync = {
 +    .name          = "astreamsync",
 +    .description   = NULL_IF_CONFIG_SMALL("Copy two streams of audio data "
 +                                          "in a configurable order."),
 +    .priv_size     = sizeof(AStreamSyncContext),
 +    .init          = init,
 +    .query_formats = query_formats,
 +
 +    .inputs    = (const AVFilterPad[]) {
 +        { .name             = "in1",
 +          .type             = AVMEDIA_TYPE_AUDIO,
 +          .filter_samples   = filter_samples,
 +          .min_perms        = AV_PERM_READ, },
 +        { .name             = "in2",
 +          .type             = AVMEDIA_TYPE_AUDIO,
 +          .filter_samples   = filter_samples,
 +          .min_perms        = AV_PERM_READ, },
 +        { .name = NULL }
 +    },
 +    .outputs   = (const AVFilterPad[]) {
 +        { .name             = "out1",
 +          .type             = AVMEDIA_TYPE_AUDIO,
 +          .config_props     = config_output,
 +          .request_frame    = request_frame, },
 +        { .name             = "out2",
 +          .type             = AVMEDIA_TYPE_AUDIO,
 +          .config_props     = config_output,
 +          .request_frame    = request_frame, },
 +        { .name = NULL }
 +    },
 +};
index 7caeb2f,0000000..da5c06e
mode 100644,000000..100644
--- /dev/null
@@@ -1,163 -1,0 +1,163 @@@
-         avfilter_get_audio_buffer(inlink, AV_PERM_WRITE,
 +/*
 + * Copyright (c) 2011 Mina Nagy Zaki
 + * Copyright (c) 2000 Edward Beingessner And Sundry Contributors.
 + * This source code is freely redistributable and may be used for any purpose.
 + * This copyright notice must be maintained.  Edward Beingessner And Sundry
 + * Contributors are not responsible for the consequences of using this
 + * software.
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +/**
 + * @file
 + * Stereo Widening Effect. Adds audio cues to move stereo image in
 + * front of the listener. Adapted from the libsox earwax effect.
 + */
 +
 +#include "libavutil/audioconvert.h"
 +#include "avfilter.h"
 +
 +#define NUMTAPS 64
 +
 +static const int8_t filt[NUMTAPS] = {
 +/* 30°  330° */
 +    4,   -6,     /* 32 tap stereo FIR filter. */
 +    4,  -11,     /* One side filters as if the */
 +   -1,   -5,     /* signal was from 30 degrees */
 +    3,    3,     /* from the ear, the other as */
 +   -2,    5,     /* if 330 degrees. */
 +   -5,    0,
 +    9,    1,
 +    6,    3,     /*                         Input                         */
 +   -4,   -1,     /*                   Left         Right                  */
 +   -5,   -3,     /*                __________   __________                */
 +   -2,   -5,     /*               |          | |          |               */
 +   -7,    1,     /*           .---|  Hh,0(f) | |  Hh,0(f) |---.           */
 +    6,   -7,     /*          /    |__________| |__________|    \          */
 +   30,  -29,     /*         /                \ /                \         */
 +   12,   -3,     /*        /                  X                  \        */
 +  -11,    4,     /*       /                  / \                  \       */
 +   -3,    7,     /*  ____V_____   __________V   V__________   _____V____  */
 +  -20,   23,     /* |          | |          |   |          | |          | */
 +    2,    0,     /* | Hh,30(f) | | Hh,330(f)|   | Hh,330(f)| | Hh,30(f) | */
 +    1,   -6,     /* |__________| |__________|   |__________| |__________| */
 +  -14,   -5,     /*      \     ___      /           \      ___     /      */
 +   15,  -18,     /*       \   /   \    /    _____    \    /   \   /       */
 +    6,    7,     /*        `->| + |<--'    /     \    `-->| + |<-'        */
 +   15,  -10,     /*           \___/      _/       \_      \___/           */
 +  -14,   22,     /*               \     / \       / \     /               */
 +   -7,   -2,     /*                `--->| |       | |<---'                */
 +   -4,    9,     /*                     \_/       \_/                     */
 +    6,  -12,     /*                                                       */
 +    6,   -6,     /*                       Headphones                      */
 +    0,  -11,
 +    0,   -5,
 +    4,    0};
 +
 +typedef struct {
 +    int16_t taps[NUMTAPS * 2];
 +} EarwaxContext;
 +
 +static int query_formats(AVFilterContext *ctx)
 +{
 +    AVFilterFormats *formats = NULL;
 +    avfilter_add_format(&formats, AV_SAMPLE_FMT_S16);
 +    avfilter_set_common_sample_formats(ctx, formats);
 +    formats = NULL;
 +    avfilter_add_format(&formats, AV_CH_LAYOUT_STEREO);
 +    avfilter_set_common_channel_layouts(ctx, formats);
 +    formats = NULL;
 +    avfilter_add_format(&formats, AVFILTER_PACKED);
 +    avfilter_set_common_packing_formats(ctx, formats);
 +
 +    return 0;
 +}
 +
 +static int config_input(AVFilterLink *inlink)
 +{
 +    if (inlink->sample_rate != 44100) {
 +        av_log(inlink->dst, AV_LOG_ERROR,
 +               "The earwax filter only works for 44.1kHz audio. Insert "
 +               "a resample filter before this\n");
 +        return AVERROR(EINVAL);
 +    }
 +    return 0;
 +}
 +
 +//FIXME: replace with DSPContext.scalarproduct_int16
 +static inline int16_t *scalarproduct(const int16_t *in, const int16_t *endin, int16_t *out)
 +{
 +    int32_t sample;
 +    int16_t j;
 +
 +    while (in < endin) {
 +        sample = 32;
 +        for (j = 0; j < NUMTAPS; j++)
 +            sample += in[j] * filt[j];
 +        *out = sample >> 6;
 +        out++;
 +        in++;
 +    }
 +
 +    return out;
 +}
 +
 +static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples)
 +{
 +    AVFilterLink *outlink = inlink->dst->outputs[0];
 +    int16_t *taps, *endin, *in, *out;
 +    AVFilterBufferRef *outsamples =
-     avfilter_filter_samples(outlink, outsamples);
++        ff_get_audio_buffer(inlink, AV_PERM_WRITE,
 +                                  insamples->audio->nb_samples);
 +    avfilter_copy_buffer_ref_props(outsamples, insamples);
 +
 +    taps  = ((EarwaxContext *)inlink->dst->priv)->taps;
 +    out   = (int16_t *)outsamples->data[0];
 +    in    = (int16_t *)insamples ->data[0];
 +
 +    // copy part of new input and process with saved input
 +    memcpy(taps+NUMTAPS, in, NUMTAPS * sizeof(*taps));
 +    out   = scalarproduct(taps, taps + NUMTAPS, out);
 +
 +    // process current input
 +    endin = in + insamples->audio->nb_samples * 2 - NUMTAPS;
 +    out   = scalarproduct(in, endin, out);
 +
 +    // save part of input for next round
 +    memcpy(taps, endin, NUMTAPS * sizeof(*taps));
 +
++    ff_filter_samples(outlink, outsamples);
 +    avfilter_unref_buffer(insamples);
 +}
 +
 +AVFilter avfilter_af_earwax = {
 +    .name           = "earwax",
 +    .description    = NULL_IF_CONFIG_SMALL("Widen the stereo image."),
 +    .query_formats  = query_formats,
 +    .priv_size      = sizeof(EarwaxContext),
 +    .inputs  = (const AVFilterPad[])  {{  .name     = "default",
 +                                    .type           = AVMEDIA_TYPE_AUDIO,
 +                                    .filter_samples = filter_samples,
 +                                    .config_props   = config_input,
 +                                    .min_perms      = AV_PERM_READ, },
 +                                 {  .name = NULL}},
 +
 +    .outputs = (const AVFilterPad[])  {{  .name     = "default",
 +                                    .type           = AVMEDIA_TYPE_AUDIO, },
 +                                 {  .name = NULL}},
 +};
index 30d5d1b,0000000..dba930e
mode 100644,000000..100644
--- /dev/null
@@@ -1,382 -1,0 +1,382 @@@
-     AVFilterBufferRef *outsamples = avfilter_get_audio_buffer(outlink, AV_PERM_WRITE, n);
 +/*
 + * Copyright (c) 2002 Anders Johansson <ajh@atri.curtin.edu.au>
 + * Copyright (c) 2011 Clément Bœsch <ubitux@gmail.com>
 + * Copyright (c) 2011 Nicolas George <nicolas.george@normalesup.org>
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +/**
 + * @file
 + * Audio panning filter (channels mixing)
 + * Original code written by Anders Johansson for MPlayer,
 + * reimplemented for FFmpeg.
 + */
 +
 +#include <stdio.h>
 +#include "libavutil/avstring.h"
 +#include "libavutil/opt.h"
 +#include "libswresample/swresample.h"
 +#include "avfilter.h"
 +
 +#define MAX_CHANNELS 63
 +
 +typedef struct PanContext {
 +    int64_t out_channel_layout;
 +    double gain[MAX_CHANNELS][MAX_CHANNELS];
 +    int64_t need_renorm;
 +    int need_renumber;
 +    int nb_input_channels;
 +    int nb_output_channels;
 +
 +    int pure_gains;
 +    /* channel mapping specific */
 +    int channel_map[SWR_CH_MAX];
 +    struct SwrContext *swr;
 +} PanContext;
 +
 +static int parse_channel_name(char **arg, int *rchannel, int *rnamed)
 +{
 +    char buf[8];
 +    int len, i, channel_id = 0;
 +    int64_t layout, layout0;
 +
 +    /* try to parse a channel name, e.g. "FL" */
 +    if (sscanf(*arg, " %7[A-Z] %n", buf, &len)) {
 +        layout0 = layout = av_get_channel_layout(buf);
 +        /* channel_id <- first set bit in layout */
 +        for (i = 32; i > 0; i >>= 1) {
 +            if (layout >= (int64_t)1 << i) {
 +                channel_id += i;
 +                layout >>= i;
 +            }
 +        }
 +        /* reject layouts that are not a single channel */
 +        if (channel_id >= MAX_CHANNELS || layout0 != (int64_t)1 << channel_id)
 +            return AVERROR(EINVAL);
 +        *rchannel = channel_id;
 +        *rnamed = 1;
 +        *arg += len;
 +        return 0;
 +    }
 +    /* try to parse a channel number, e.g. "c2" */
 +    if (sscanf(*arg, " c%d %n", &channel_id, &len) &&
 +        channel_id >= 0 && channel_id < MAX_CHANNELS) {
 +        *rchannel = channel_id;
 +        *rnamed = 0;
 +        *arg += len;
 +        return 0;
 +    }
 +    return AVERROR(EINVAL);
 +}
 +
 +static void skip_spaces(char **arg)
 +{
 +    int len = 0;
 +
 +    sscanf(*arg, " %n", &len);
 +    *arg += len;
 +}
 +
 +static av_cold int init(AVFilterContext *ctx, const char *args0, void *opaque)
 +{
 +    PanContext *const pan = ctx->priv;
 +    char *arg, *arg0, *tokenizer, *args = av_strdup(args0);
 +    int out_ch_id, in_ch_id, len, named;
 +    int nb_in_channels[2] = { 0, 0 }; // number of unnamed and named input channels
 +    double gain;
 +
 +    if (!args0) {
 +        av_log(ctx, AV_LOG_ERROR,
 +               "pan filter needs a channel layout and a set "
 +               "of channels definitions as parameter\n");
 +        return AVERROR(EINVAL);
 +    }
 +    if (!args)
 +        return AVERROR(ENOMEM);
 +    arg = av_strtok(args, ":", &tokenizer);
 +    pan->out_channel_layout = av_get_channel_layout(arg);
 +    if (!pan->out_channel_layout) {
 +        av_log(ctx, AV_LOG_ERROR, "Unknown channel layout \"%s\"\n", arg);
 +        return AVERROR(EINVAL);
 +    }
 +    pan->nb_output_channels = av_get_channel_layout_nb_channels(pan->out_channel_layout);
 +
 +    /* parse channel specifications */
 +    while ((arg = arg0 = av_strtok(NULL, ":", &tokenizer))) {
 +        /* channel name */
 +        if (parse_channel_name(&arg, &out_ch_id, &named)) {
 +            av_log(ctx, AV_LOG_ERROR,
 +                   "Expected out channel name, got \"%.8s\"\n", arg);
 +            return AVERROR(EINVAL);
 +        }
 +        if (named) {
 +            if (!((pan->out_channel_layout >> out_ch_id) & 1)) {
 +                av_log(ctx, AV_LOG_ERROR,
 +                       "Channel \"%.8s\" does not exist in the chosen layout\n", arg0);
 +                return AVERROR(EINVAL);
 +            }
 +            /* get the channel number in the output channel layout:
 +             * out_channel_layout & ((1 << out_ch_id) - 1) are all the
 +             * channels that come before out_ch_id,
 +             * so their count is the index of out_ch_id */
 +            out_ch_id = av_get_channel_layout_nb_channels(pan->out_channel_layout & (((int64_t)1 << out_ch_id) - 1));
 +        }
 +        if (out_ch_id < 0 || out_ch_id >= pan->nb_output_channels) {
 +            av_log(ctx, AV_LOG_ERROR,
 +                   "Invalid out channel name \"%.8s\"\n", arg0);
 +            return AVERROR(EINVAL);
 +        }
 +        if (*arg == '=') {
 +            arg++;
 +        } else if (*arg == '<') {
 +            pan->need_renorm |= (int64_t)1 << out_ch_id;
 +            arg++;
 +        } else {
 +            av_log(ctx, AV_LOG_ERROR,
 +                   "Syntax error after channel name in \"%.8s\"\n", arg0);
 +            return AVERROR(EINVAL);
 +        }
 +        /* gains */
 +        while (1) {
 +            gain = 1;
 +            if (sscanf(arg, " %lf %n* %n", &gain, &len, &len))
 +                arg += len;
 +            if (parse_channel_name(&arg, &in_ch_id, &named)){
 +                av_log(ctx, AV_LOG_ERROR,
 +                       "Expected in channel name, got \"%.8s\"\n", arg);
 +                return AVERROR(EINVAL);
 +            }
 +            nb_in_channels[named]++;
 +            if (nb_in_channels[!named]) {
 +                av_log(ctx, AV_LOG_ERROR,
 +                       "Can not mix named and numbered channels\n");
 +                return AVERROR(EINVAL);
 +            }
 +            pan->gain[out_ch_id][in_ch_id] = gain;
 +            if (!*arg)
 +                break;
 +            if (*arg != '+') {
 +                av_log(ctx, AV_LOG_ERROR, "Syntax error near \"%.8s\"\n", arg);
 +                return AVERROR(EINVAL);
 +            }
 +            arg++;
 +            skip_spaces(&arg);
 +        }
 +    }
 +    pan->need_renumber = !!nb_in_channels[1];
 +
 +    av_free(args);
 +    return 0;
 +}
 +
 +static int are_gains_pure(const PanContext *pan)
 +{
 +    int i, j;
 +
 +    for (i = 0; i < MAX_CHANNELS; i++) {
 +        int nb_gain = 0;
 +
 +        for (j = 0; j < MAX_CHANNELS; j++) {
 +            double gain = pan->gain[i][j];
 +
 +            /* channel mapping is effective only if 0% or 100% of a channel is
 +             * selected... */
 +            if (gain != 0. && gain != 1.)
 +                return 0;
 +            /* ...and if the output channel is only composed of one input */
 +            if (gain && nb_gain++)
 +                return 0;
 +        }
 +    }
 +    return 1;
 +}
 +
 +static int query_formats(AVFilterContext *ctx)
 +{
 +    PanContext *pan = ctx->priv;
 +    AVFilterLink *inlink  = ctx->inputs[0];
 +    AVFilterLink *outlink = ctx->outputs[0];
 +    AVFilterFormats *formats;
 +
 +    pan->pure_gains = are_gains_pure(pan);
 +    /* libswr supports any sample and packing formats */
 +    avfilter_set_common_sample_formats(ctx, avfilter_make_all_formats(AVMEDIA_TYPE_AUDIO));
 +    avfilter_set_common_packing_formats(ctx, avfilter_make_all_packing_formats());
 +
 +    // inlink supports any channel layout
 +    formats = avfilter_make_all_channel_layouts();
 +    avfilter_formats_ref(formats, &inlink->out_chlayouts);
 +
 +    // outlink supports only requested output channel layout
 +    formats = NULL;
 +    avfilter_add_format(&formats, pan->out_channel_layout);
 +    avfilter_formats_ref(formats, &outlink->in_chlayouts);
 +    return 0;
 +}
 +
 +static int config_props(AVFilterLink *link)
 +{
 +    AVFilterContext *ctx = link->dst;
 +    PanContext *pan = ctx->priv;
 +    char buf[1024], *cur;
 +    int i, j, k, r;
 +    double t;
 +
 +    pan->nb_input_channels = av_get_channel_layout_nb_channels(link->channel_layout);
 +    if (pan->need_renumber) {
 +        // input channels were given by their name: renumber them
 +        for (i = j = 0; i < MAX_CHANNELS; i++) {
 +            if ((link->channel_layout >> i) & 1) {
 +                for (k = 0; k < pan->nb_output_channels; k++)
 +                    pan->gain[k][j] = pan->gain[k][i];
 +                j++;
 +            }
 +        }
 +    }
 +
 +    // sanity check; can't be done in query_formats since the inlink
 +    // channel layout is unknown at that time
 +    if (pan->nb_input_channels > SWR_CH_MAX ||
 +        pan->nb_output_channels > SWR_CH_MAX) {
 +        av_log(ctx, AV_LOG_ERROR,
 +               "libswresample support a maximum of %d channels. "
 +               "Feel free to ask for a higher limit.\n", SWR_CH_MAX);
 +        return AVERROR_PATCHWELCOME;
 +    }
 +
 +    // init libswresample context
 +    pan->swr = swr_alloc_set_opts(pan->swr,
 +                                  pan->out_channel_layout, link->format, link->sample_rate,
 +                                  link->channel_layout,    link->format, link->sample_rate,
 +                                  0, ctx);
 +    if (!pan->swr)
 +        return AVERROR(ENOMEM);
 +
 +    // gains are pure, init the channel mapping
 +    if (pan->pure_gains) {
 +
 +        // get channel map from the pure gains
 +        for (i = 0; i < pan->nb_output_channels; i++) {
 +            int ch_id = -1;
 +            for (j = 0; j < pan->nb_input_channels; j++) {
 +                if (pan->gain[i][j]) {
 +                    ch_id = j;
 +                    break;
 +                }
 +            }
 +            pan->channel_map[i] = ch_id;
 +        }
 +
 +        av_opt_set_int(pan->swr, "icl", pan->out_channel_layout, 0);
 +        av_opt_set_int(pan->swr, "uch", pan->nb_output_channels, 0);
 +        swr_set_channel_mapping(pan->swr, pan->channel_map);
 +    } else {
 +        // renormalize
 +        for (i = 0; i < pan->nb_output_channels; i++) {
 +            if (!((pan->need_renorm >> i) & 1))
 +                continue;
 +            t = 0;
 +            for (j = 0; j < pan->nb_input_channels; j++)
 +                t += pan->gain[i][j];
 +            if (t > -1E-5 && t < 1E-5) {
 +                // t is almost 0 but not exactly, this is probably a mistake
 +                if (t)
 +                    av_log(ctx, AV_LOG_WARNING,
 +                           "Degenerate coefficients while renormalizing\n");
 +                continue;
 +            }
 +            for (j = 0; j < pan->nb_input_channels; j++)
 +                pan->gain[i][j] /= t;
 +        }
 +        av_opt_set_int(pan->swr, "icl", link->channel_layout, 0);
 +        av_opt_set_int(pan->swr, "ocl", pan->out_channel_layout, 0);
 +        swr_set_matrix(pan->swr, pan->gain[0], pan->gain[1] - pan->gain[0]);
 +    }
 +
 +    r = swr_init(pan->swr);
 +    if (r < 0)
 +        return r;
 +
 +    // summary
 +    for (i = 0; i < pan->nb_output_channels; i++) {
 +        cur = buf;
 +        for (j = 0; j < pan->nb_input_channels; j++) {
 +            r = snprintf(cur, buf + sizeof(buf) - cur, "%s%.3g i%d",
 +                         j ? " + " : "", pan->gain[i][j], j);
 +            cur += FFMIN(buf + sizeof(buf) - cur, r);
 +        }
 +        av_log(ctx, AV_LOG_INFO, "o%d = %s\n", i, buf);
 +    }
 +    // add channel mapping summary if possible
 +    if (pan->pure_gains) {
 +        av_log(ctx, AV_LOG_INFO, "Pure channel mapping detected:");
 +        for (i = 0; i < pan->nb_output_channels; i++)
 +            if (pan->channel_map[i] < 0)
 +                av_log(ctx, AV_LOG_INFO, " M");
 +            else
 +                av_log(ctx, AV_LOG_INFO, " %d", pan->channel_map[i]);
 +        av_log(ctx, AV_LOG_INFO, "\n");
 +        return 0;
 +    }
 +    return 0;
 +}
 +
 +static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples)
 +{
 +    int n = insamples->audio->nb_samples;
 +    AVFilterLink *const outlink = inlink->dst->outputs[0];
-     avfilter_filter_samples(outlink, outsamples);
++    AVFilterBufferRef *outsamples = ff_get_audio_buffer(outlink, AV_PERM_WRITE, n);
 +    PanContext *pan = inlink->dst->priv;
 +
 +    swr_convert(pan->swr, outsamples->data, n, (void *)insamples->data, n);
 +    avfilter_copy_buffer_ref_props(outsamples, insamples);
 +    outsamples->audio->channel_layout = outlink->channel_layout;
 +    outsamples->audio->planar         = outlink->planar;
 +
++    ff_filter_samples(outlink, outsamples);
 +    avfilter_unref_buffer(insamples);
 +}
 +
 +static av_cold void uninit(AVFilterContext *ctx)
 +{
 +    PanContext *pan = ctx->priv;
 +    swr_free(&pan->swr);
 +}
 +
 +AVFilter avfilter_af_pan = {
 +    .name          = "pan",
 +    .description   = NULL_IF_CONFIG_SMALL("Remix channels with coefficients (panning)."),
 +    .priv_size     = sizeof(PanContext),
 +    .init          = init,
 +    .uninit        = uninit,
 +    .query_formats = query_formats,
 +
 +    .inputs    = (const AVFilterPad[]) {
 +        { .name             = "default",
 +          .type             = AVMEDIA_TYPE_AUDIO,
 +          .config_props     = config_props,
 +          .filter_samples   = filter_samples,
 +          .min_perms        = AV_PERM_READ, },
 +        { .name = NULL}
 +    },
 +    .outputs   = (const AVFilterPad[]) {
 +        { .name             = "default",
 +          .type             = AVMEDIA_TYPE_AUDIO, },
 +        { .name = NULL}
 +    },
 +};
index 4f95b54,0000000..94197d7
mode 100644,000000..100644
--- /dev/null
@@@ -1,175 -1,0 +1,175 @@@
-     avfilter_filter_samples(inlink->dst->outputs[0], insamples);
 +/*
 + * Copyright (c) 2012 Clément Bœsch <ubitux@gmail.com>
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +/**
 + * @file
 + * Audio silence detector
 + */
 +
 +#include "libavutil/opt.h"
 +#include "libavutil/timestamp.h"
 +#include "avfilter.h"
 +
 +typedef struct {
 +    const AVClass *class;
 +    char *noise_str;            ///< noise option string
 +    double noise;               ///< noise amplitude ratio
 +    int duration;               ///< minimum duration of silence until notification
 +    int64_t nb_null_samples;    ///< current number of continuous zero samples
 +    int64_t start;              ///< if silence is detected, this value contains the time of the first zero sample
 +    int last_sample_rate;       ///< last sample rate to check for sample rate changes
 +} SilenceDetectContext;
 +
 +#define OFFSET(x) offsetof(SilenceDetectContext, x)
 +static const AVOption silencedetect_options[] = {
 +    { "n",         "set noise tolerance",              OFFSET(noise_str), AV_OPT_TYPE_STRING, {.str="-60dB"}, CHAR_MIN, CHAR_MAX },
 +    { "noise",     "set noise tolerance",              OFFSET(noise_str), AV_OPT_TYPE_STRING, {.str="-60dB"}, CHAR_MIN, CHAR_MAX },
 +    { "d",         "set minimum duration in seconds",  OFFSET(duration),  AV_OPT_TYPE_INT,    {.dbl=2},    0, INT_MAX},
 +    { "duration",  "set minimum duration in seconds",  OFFSET(duration),  AV_OPT_TYPE_INT,    {.dbl=2},    0, INT_MAX},
 +    { NULL },
 +};
 +
 +static const char *silencedetect_get_name(void *ctx)
 +{
 +    return "silencedetect";
 +}
 +
 +static const AVClass silencedetect_class = {
 +    .class_name = "SilenceDetectContext",
 +    .item_name  = silencedetect_get_name,
 +    .option     = silencedetect_options,
 +};
 +
 +static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
 +{
 +    int ret;
 +    char *tail;
 +    SilenceDetectContext *silence = ctx->priv;
 +
 +    silence->class = &silencedetect_class;
 +    av_opt_set_defaults(silence);
 +
 +    if ((ret = av_set_options_string(silence, args, "=", ":")) < 0) {
 +        av_log(ctx, AV_LOG_ERROR, "Error parsing options string: '%s'\n", args);
 +        return ret;
 +    }
 +
 +    silence->noise = strtod(silence->noise_str, &tail);
 +    if (!strcmp(tail, "dB")) {
 +        silence->noise = pow(10, silence->noise/20);
 +    } else if (*tail) {
 +        av_log(ctx, AV_LOG_ERROR, "Invalid value '%s' for noise parameter.\n",
 +               silence->noise_str);
 +        return AVERROR(EINVAL);
 +    }
 +
 +    return 0;
 +}
 +
 +static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples)
 +{
 +    int i;
 +    SilenceDetectContext *silence = inlink->dst->priv;
 +    const int nb_channels           = av_get_channel_layout_nb_channels(inlink->channel_layout);
 +    const int srate                 = inlink->sample_rate;
 +    const int nb_samples            = insamples->audio->nb_samples * nb_channels;
 +    const int64_t nb_samples_notify = srate * silence->duration    * nb_channels;
 +
 +    // scale number of null samples to the new sample rate
 +    if (silence->last_sample_rate && silence->last_sample_rate != srate)
 +        silence->nb_null_samples =
 +            srate * silence->nb_null_samples / silence->last_sample_rate;
 +    silence->last_sample_rate = srate;
 +
 +    // TODO: support more sample formats
 +    if (insamples->format == AV_SAMPLE_FMT_DBL) {
 +        double *p = (double *)insamples->data[0];
 +
 +        for (i = 0; i < nb_samples; i++, p++) {
 +            if (*p < silence->noise && *p > -silence->noise) {
 +                if (!silence->start) {
 +                    silence->nb_null_samples++;
 +                    if (silence->nb_null_samples >= nb_samples_notify) {
 +                        silence->start = insamples->pts - silence->duration / av_q2d(inlink->time_base);
 +                        av_log(silence, AV_LOG_INFO,
 +                               "silence_start: %s\n", av_ts2timestr(silence->start, &inlink->time_base));
 +                    }
 +                }
 +            } else {
 +                if (silence->start)
 +                    av_log(silence, AV_LOG_INFO,
 +                           "silence_end: %s | silence_duration: %s\n",
 +                           av_ts2timestr(insamples->pts,                  &inlink->time_base),
 +                           av_ts2timestr(insamples->pts - silence->start, &inlink->time_base));
 +                silence->nb_null_samples = silence->start = 0;
 +            }
 +        }
 +    }
 +
-           .get_audio_buffer = avfilter_null_get_audio_buffer,
++    ff_filter_samples(inlink->dst->outputs[0], insamples);
 +}
 +
 +static int query_formats(AVFilterContext *ctx)
 +{
 +    AVFilterFormats *formats = NULL;
 +    enum AVSampleFormat sample_fmts[] = {
 +        AV_SAMPLE_FMT_DBL,
 +        AV_SAMPLE_FMT_NONE
 +    };
 +    int packing_fmts[] = { AVFILTER_PACKED, -1 };
 +
 +    formats = avfilter_make_all_channel_layouts();
 +    if (!formats)
 +        return AVERROR(ENOMEM);
 +    avfilter_set_common_channel_layouts(ctx, formats);
 +
 +    formats = avfilter_make_format_list(sample_fmts);
 +    if (!formats)
 +        return AVERROR(ENOMEM);
 +    avfilter_set_common_sample_formats(ctx, formats);
 +
 +    formats = avfilter_make_format_list(packing_fmts);
 +    if (!formats)
 +        return AVERROR(ENOMEM);
 +    avfilter_set_common_packing_formats(ctx, formats);
 +
 +    return 0;
 +}
 +
 +AVFilter avfilter_af_silencedetect = {
 +    .name          = "silencedetect",
 +    .description   = NULL_IF_CONFIG_SMALL("Detect silence."),
 +    .priv_size     = sizeof(SilenceDetectContext),
 +    .init          = init,
 +    .query_formats = query_formats,
 +
 +    .inputs = (const AVFilterPad[]) {
 +        { .name             = "default",
 +          .type             = AVMEDIA_TYPE_AUDIO,
++          .get_audio_buffer = ff_null_get_audio_buffer,
 +          .filter_samples   = filter_samples, },
 +        { .name = NULL }
 +    },
 +    .outputs = (const AVFilterPad[]) {
 +        { .name = "default",
 +          .type = AVMEDIA_TYPE_AUDIO, },
 +        { .name = NULL }
 +    },
 +};
index 99ae8b8,0000000..881a451
mode 100644,000000..100644
--- /dev/null
@@@ -1,189 -1,0 +1,189 @@@
-     avfilter_filter_samples(outlink, insamples);
 +/*
 + * Copyright (c) 2011 Stefano Sabatini
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +/**
 + * @file
 + * audio volume filter
 + * based on ffmpeg.c code
 + */
 +
 +#include "libavutil/audioconvert.h"
 +#include "libavutil/eval.h"
 +#include "avfilter.h"
 +
 +typedef struct {
 +    double volume;
 +    int    volume_i;
 +} VolumeContext;
 +
 +static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
 +{
 +    VolumeContext *vol = ctx->priv;
 +    char *tail;
 +    int ret = 0;
 +
 +    vol->volume = 1.0;
 +
 +    if (args) {
 +        /* parse the number as a decimal number */
 +        double d = strtod(args, &tail);
 +
 +        if (*tail) {
 +            if (!strcmp(tail, "dB")) {
 +                /* consider the argument an adjustement in decibels */
 +                d = pow(10, d/20);
 +            } else {
 +                /* parse the argument as an expression */
 +                ret = av_expr_parse_and_eval(&d, args, NULL, NULL,
 +                                             NULL, NULL, NULL, NULL,
 +                                             NULL, 0, ctx);
 +            }
 +        }
 +
 +        if (ret < 0) {
 +            av_log(ctx, AV_LOG_ERROR,
 +                   "Invalid volume argument '%s'\n", args);
 +            return AVERROR(EINVAL);
 +        }
 +
 +        if (d < 0 || d > 65536) { /* 65536 = INT_MIN / (128 * 256) */
 +            av_log(ctx, AV_LOG_ERROR,
 +                   "Negative or too big volume value %f\n", d);
 +            return AVERROR(EINVAL);
 +        }
 +
 +        vol->volume = d;
 +    }
 +
 +    vol->volume_i = (int)(vol->volume * 256 + 0.5);
 +    av_log(ctx, AV_LOG_INFO, "volume=%f\n", vol->volume);
 +    return 0;
 +}
 +
 +static int query_formats(AVFilterContext *ctx)
 +{
 +    AVFilterFormats *formats = NULL;
 +    enum AVSampleFormat sample_fmts[] = {
 +        AV_SAMPLE_FMT_U8,
 +        AV_SAMPLE_FMT_S16,
 +        AV_SAMPLE_FMT_S32,
 +        AV_SAMPLE_FMT_FLT,
 +        AV_SAMPLE_FMT_DBL,
 +        AV_SAMPLE_FMT_NONE
 +    };
 +    int packing_fmts[] = { AVFILTER_PACKED, -1 };
 +
 +    formats = avfilter_make_all_channel_layouts();
 +    if (!formats)
 +        return AVERROR(ENOMEM);
 +    avfilter_set_common_channel_layouts(ctx, formats);
 +
 +    formats = avfilter_make_format_list(sample_fmts);
 +    if (!formats)
 +        return AVERROR(ENOMEM);
 +    avfilter_set_common_sample_formats(ctx, formats);
 +
 +    formats = avfilter_make_format_list(packing_fmts);
 +    if (!formats)
 +        return AVERROR(ENOMEM);
 +    avfilter_set_common_packing_formats(ctx, formats);
 +
 +    return 0;
 +}
 +
 +static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples)
 +{
 +    VolumeContext *vol = inlink->dst->priv;
 +    AVFilterLink *outlink = inlink->dst->outputs[0];
 +    const int nb_samples = insamples->audio->nb_samples *
 +        av_get_channel_layout_nb_channels(insamples->audio->channel_layout);
 +    const double volume   = vol->volume;
 +    const int    volume_i = vol->volume_i;
 +    int i;
 +
 +    if (volume_i != 256) {
 +        switch (insamples->format) {
 +        case AV_SAMPLE_FMT_U8:
 +        {
 +            uint8_t *p = (void *)insamples->data[0];
 +            for (i = 0; i < nb_samples; i++) {
 +                int v = (((*p - 128) * volume_i + 128) >> 8) + 128;
 +                *p++ = av_clip_uint8(v);
 +            }
 +            break;
 +        }
 +        case AV_SAMPLE_FMT_S16:
 +        {
 +            int16_t *p = (void *)insamples->data[0];
 +            for (i = 0; i < nb_samples; i++) {
 +                int v = ((int64_t)*p * volume_i + 128) >> 8;
 +                *p++ = av_clip_int16(v);
 +            }
 +            break;
 +        }
 +        case AV_SAMPLE_FMT_S32:
 +        {
 +            int32_t *p = (void *)insamples->data[0];
 +            for (i = 0; i < nb_samples; i++) {
 +                int64_t v = (((int64_t)*p * volume_i + 128) >> 8);
 +                *p++ = av_clipl_int32(v);
 +            }
 +            break;
 +        }
 +        case AV_SAMPLE_FMT_FLT:
 +        {
 +            float *p = (void *)insamples->data[0];
 +            float scale = (float)volume;
 +            for (i = 0; i < nb_samples; i++) {
 +                *p++ *= scale;
 +            }
 +            break;
 +        }
 +        case AV_SAMPLE_FMT_DBL:
 +        {
 +            double *p = (void *)insamples->data[0];
 +            for (i = 0; i < nb_samples; i++) {
 +                *p *= volume;
 +                p++;
 +            }
 +            break;
 +        }
 +        }
 +    }
++    ff_filter_samples(outlink, insamples);
 +}
 +
 +AVFilter avfilter_af_volume = {
 +    .name           = "volume",
 +    .description    = NULL_IF_CONFIG_SMALL("Change input volume."),
 +    .query_formats  = query_formats,
 +    .priv_size      = sizeof(VolumeContext),
 +    .init           = init,
 +
 +    .inputs  = (const AVFilterPad[])  {{ .name     = "default",
 +                                   .type           = AVMEDIA_TYPE_AUDIO,
 +                                   .filter_samples = filter_samples,
 +                                   .min_perms      = AV_PERM_READ|AV_PERM_WRITE},
 +                                 { .name = NULL}},
 +
 +    .outputs = (const AVFilterPad[])  {{ .name     = "default",
 +                                   .type           = AVMEDIA_TYPE_AUDIO, },
 +                                 { .name = NULL}},
 +};
index 7bd6a89,0000000..11750bb
mode 100644,000000..100644
--- /dev/null
@@@ -1,247 -1,0 +1,247 @@@
-     samplesref = avfilter_get_audio_buffer(outlink, AV_PERM_WRITE, eval->nb_samples);
 +/*
 + * Copyright (c) 2011 Stefano Sabatini
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +/**
 + * @file
 + * eval audio source
 + */
 +
 +#include "libavutil/audioconvert.h"
 +#include "libavutil/avassert.h"
 +#include "libavutil/avstring.h"
 +#include "libavutil/eval.h"
 +#include "libavutil/opt.h"
 +#include "libavutil/parseutils.h"
 +#include "avfilter.h"
 +#include "internal.h"
 +
 +static const char * const var_names[] = {
 +    "n",            ///< number of frame
 +    "t",            ///< timestamp expressed in seconds
 +    "s",            ///< sample rate
 +    NULL
 +};
 +
 +enum var_name {
 +    VAR_N,
 +    VAR_T,
 +    VAR_S,
 +    VAR_VARS_NB
 +};
 +
 +typedef struct {
 +    const AVClass *class;
 +    char *sample_rate_str;
 +    int sample_rate;
 +    int64_t chlayout;
 +    int nb_channels;
 +    int64_t pts;
 +    AVExpr *expr[8];
 +    char *expr_str[8];
 +    int nb_samples;             ///< number of samples per requested frame
 +    char *duration_str;         ///< total duration of the generated audio
 +    double duration;
 +    uint64_t n;
 +    double var_values[VAR_VARS_NB];
 +} EvalContext;
 +
 +#define OFFSET(x) offsetof(EvalContext, x)
 +
 +static const AVOption eval_options[]= {
 +    { "nb_samples",  "set the number of samples per requested frame", OFFSET(nb_samples),      AV_OPT_TYPE_INT,    {.dbl = 1024},    0,        INT_MAX },
 +    { "n",           "set the number of samples per requested frame", OFFSET(nb_samples),      AV_OPT_TYPE_INT,    {.dbl = 1024},    0,        INT_MAX },
 +    { "sample_rate", "set the sample rate",                           OFFSET(sample_rate_str), AV_OPT_TYPE_STRING, {.str = "44100"}, CHAR_MIN, CHAR_MAX },
 +    { "s",           "set the sample rate",                           OFFSET(sample_rate_str), AV_OPT_TYPE_STRING, {.str = "44100"}, CHAR_MIN, CHAR_MAX },
 +    { "duration",    "set audio duration", OFFSET(duration_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0 },
 +    { "d",           "set audio duration", OFFSET(duration_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0 },
 +{NULL},
 +};
 +
 +static const char *eval_get_name(void *ctx)
 +{
 +    return "aevalsrc";
 +}
 +
 +static const AVClass eval_class = {
 +    "AEvalSrcContext",
 +    eval_get_name,
 +    eval_options
 +};
 +
 +static int init(AVFilterContext *ctx, const char *args, void *opaque)
 +{
 +    EvalContext *eval = ctx->priv;
 +    char *args1 = av_strdup(args);
 +    char *expr, *buf, *bufptr;
 +    int ret, i;
 +
 +    eval->class = &eval_class;
 +    av_opt_set_defaults(eval);
 +
 +    /* parse expressions */
 +    buf = args1;
 +    i = 0;
 +    while (expr = av_strtok(buf, ":", &bufptr)) {
 +        if (i >= 8) {
 +            av_log(ctx, AV_LOG_ERROR,
 +                   "More than 8 expressions provided, unsupported.\n");
 +            ret = AVERROR(EINVAL);
 +            return ret;
 +        }
 +        ret = av_expr_parse(&eval->expr[i], expr, var_names,
 +                            NULL, NULL, NULL, NULL, 0, ctx);
 +        if (ret < 0)
 +            goto end;
 +        i++;
 +        if (bufptr && *bufptr == ':') { /* found last expression */
 +            bufptr++;
 +            break;
 +        }
 +        buf = NULL;
 +    }
 +
 +    /* guess channel layout from nb expressions/channels */
 +    eval->nb_channels = i;
 +    eval->chlayout = av_get_default_channel_layout(eval->nb_channels);
 +    if (!eval->chlayout) {
 +        av_log(ctx, AV_LOG_ERROR, "Invalid number of channels '%d' provided\n",
 +               eval->nb_channels);
 +        ret = AVERROR(EINVAL);
 +        goto end;
 +    }
 +
 +    if (bufptr && (ret = av_set_options_string(eval, bufptr, "=", ":")) < 0)
 +        goto end;
 +
 +    if ((ret = ff_parse_sample_rate(&eval->sample_rate, eval->sample_rate_str, ctx)))
 +        goto end;
 +
 +    eval->duration = -1;
 +    if (eval->duration_str) {
 +        int64_t us = -1;
 +        if ((ret = av_parse_time(&us, eval->duration_str, 1)) < 0) {
 +            av_log(ctx, AV_LOG_ERROR, "Invalid duration: '%s'\n", eval->duration_str);
 +            goto end;
 +        }
 +        eval->duration = (double)us / 1000000;
 +    }
 +    eval->n = 0;
 +
 +end:
 +    av_free(args1);
 +    return ret;
 +}
 +
 +static void uninit(AVFilterContext *ctx)
 +{
 +    EvalContext *eval = ctx->priv;
 +    int i;
 +
 +    for (i = 0; i < 8; i++) {
 +        av_expr_free(eval->expr[i]);
 +        eval->expr[i] = NULL;
 +    }
 +    av_freep(&eval->duration_str);
 +    av_freep(&eval->sample_rate_str);
 +}
 +
 +static int config_props(AVFilterLink *outlink)
 +{
 +    EvalContext *eval = outlink->src->priv;
 +    char buf[128];
 +
 +    outlink->time_base = (AVRational){1, eval->sample_rate};
 +    outlink->sample_rate = eval->sample_rate;
 +
 +    eval->var_values[VAR_S] = eval->sample_rate;
 +
 +    av_get_channel_layout_string(buf, sizeof(buf), 0, eval->chlayout);
 +
 +    av_log(outlink->src, AV_LOG_INFO,
 +           "sample_rate:%d chlayout:%s duration:%f\n",
 +           eval->sample_rate, buf, eval->duration);
 +
 +    return 0;
 +}
 +
 +static int query_formats(AVFilterContext *ctx)
 +{
 +    EvalContext *eval = ctx->priv;
 +    enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_NONE };
 +    int64_t chlayouts[] = { eval->chlayout, -1 };
 +    int packing_fmts[] = { AVFILTER_PLANAR, -1 };
 +
 +    avfilter_set_common_sample_formats (ctx, avfilter_make_format_list(sample_fmts));
 +    avfilter_set_common_channel_layouts(ctx, avfilter_make_format64_list(chlayouts));
 +    avfilter_set_common_packing_formats(ctx, avfilter_make_format_list(packing_fmts));
 +
 +    return 0;
 +}
 +
 +static int request_frame(AVFilterLink *outlink)
 +{
 +    EvalContext *eval = outlink->src->priv;
 +    AVFilterBufferRef *samplesref;
 +    int i, j;
 +    double t = eval->var_values[VAR_N] * (double)1/eval->sample_rate;
 +
 +    if (eval->duration >= 0 && t > eval->duration)
 +        return AVERROR_EOF;
 +
-     avfilter_filter_samples(outlink, samplesref);
++    samplesref = ff_get_audio_buffer(outlink, AV_PERM_WRITE, eval->nb_samples);
 +
 +    /* evaluate expression for each single sample and for each channel */
 +    for (i = 0; i < eval->nb_samples; i++, eval->n++) {
 +        eval->var_values[VAR_N] = eval->n;
 +        eval->var_values[VAR_T] = eval->var_values[VAR_N] * (double)1/eval->sample_rate;
 +
 +        for (j = 0; j < eval->nb_channels; j++) {
 +            *((double *) samplesref->data[j] + i) =
 +                av_expr_eval(eval->expr[j], eval->var_values, NULL);
 +        }
 +    }
 +
 +    samplesref->pts = eval->pts;
 +    samplesref->pos = -1;
 +    samplesref->audio->sample_rate = eval->sample_rate;
 +    eval->pts += eval->nb_samples;
 +
++    ff_filter_samples(outlink, samplesref);
 +
 +    return 0;
 +}
 +
 +AVFilter avfilter_asrc_aevalsrc = {
 +    .name        = "aevalsrc",
 +    .description = NULL_IF_CONFIG_SMALL("Generate an audio signal generated by an expression."),
 +
 +    .query_formats = query_formats,
 +    .init        = init,
 +    .uninit      = uninit,
 +    .priv_size   = sizeof(EvalContext),
 +
 +    .inputs      = (const AVFilterPad[]) {{ .name = NULL}},
 +
 +    .outputs     = (const AVFilterPad[]) {{ .name = "default",
 +                                      .type = AVMEDIA_TYPE_AUDIO,
 +                                      .config_props = config_props,
 +                                      .request_frame = request_frame, },
 +                                    { .name = NULL}},
 +};
@@@ -102,23 -74,9 +102,23 @@@ static int config_props(AVFilterLink *o
      return 0;
  }
  
 -static int request_frame(AVFilterLink *link)
 +static int request_frame(AVFilterLink *outlink)
  {
 -    return -1;
 +    ANullContext *null = outlink->src->priv;
 +    AVFilterBufferRef *samplesref;
 +
 +    samplesref =
-         avfilter_get_audio_buffer(outlink, AV_PERM_WRITE, null->nb_samples);
++        ff_get_audio_buffer(outlink, AV_PERM_WRITE, null->nb_samples);
 +    samplesref->pts = null->pts;
 +    samplesref->pos = -1;
 +    samplesref->audio->channel_layout = null->channel_layout;
 +    samplesref->audio->sample_rate = outlink->sample_rate;
 +
-     avfilter_filter_samples(outlink, avfilter_ref_buffer(samplesref, ~0));
++    ff_filter_samples(outlink, avfilter_ref_buffer(samplesref, ~0));
 +    avfilter_unref_buffer(samplesref);
 +
 +    null->pts += null->nb_samples;
 +    return 0;
  }
  
  AVFilter avfilter_asrc_anullsrc = {
index 0000000,3e12c69..31f6796
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,209 +1,291 @@@
 - * This file is part of Libav.
+ /*
 - * Libav is free software; you can redistribute it and/or
++ * Copyright (c) Stefano Sabatini | stefasab at gmail.com
++ * Copyright (c) S.N. Hemanth Meenakshisundaram | smeenaks at ucsd.edu
+  *
 - * Libav is distributed in the hope that it will be useful,
++ * This file is part of FFmpeg.
++ *
++ * FFmpeg is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU Lesser General Public
+  * License as published by the Free Software Foundation; either
+  * version 2.1 of the License, or (at your option) any later version.
+  *
 - * License along with Libav; if not, write to the Free Software
++ * 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
 -    samplesref = avfilter_get_audio_buffer_ref_from_arrays(data, linesize, perms,
++ * 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/audioconvert.h"
+ #include "audio.h"
+ #include "avfilter.h"
+ #include "internal.h"
+ AVFilterBufferRef *ff_null_get_audio_buffer(AVFilterLink *link, int perms,
+                                             int nb_samples)
+ {
+     return ff_get_audio_buffer(link->dst->outputs[0], perms, nb_samples);
+ }
+ AVFilterBufferRef *ff_default_get_audio_buffer(AVFilterLink *link, int perms,
++                                                     int nb_samples)
++{
++    AVFilterBufferRef *samplesref = NULL;
++    int linesize[8] = {0};
++    uint8_t *data[8] = {0};
++    int ch, nb_channels = av_get_channel_layout_nb_channels(link->channel_layout);
++
++    /* right now we don't support more than 8 channels */
++    av_assert0(nb_channels <= 8);
++
++    /* Calculate total buffer size, round to multiple of 16 to be SIMD friendly */
++    if (av_samples_alloc(data, linesize,
++                         nb_channels, nb_samples,
++                         av_get_alt_sample_fmt(link->format, link->planar),
++                         16) < 0)
++        return NULL;
++
++    for (ch = 1; link->planar && ch < nb_channels; ch++)
++        linesize[ch] = linesize[0];
++    samplesref =
++        avfilter_get_audio_buffer_ref_from_arrays(data, linesize, perms,
++                                                  nb_samples, link->format,
++                                                  link->channel_layout, link->planar);
++    if (!samplesref) {
++        av_free(data[0]);
++        return NULL;
++    }
++
++    return samplesref;
++}
++
++static AVFilterBufferRef *ff_default_get_audio_buffer_alt(AVFilterLink *link, int perms,
+                                                int nb_samples)
+ {
+     AVFilterBufferRef *samplesref = NULL;
+     uint8_t **data;
+     int planar      = av_sample_fmt_is_planar(link->format);
+     int nb_channels = av_get_channel_layout_nb_channels(link->channel_layout);
+     int planes      = planar ? nb_channels : 1;
+     int linesize;
+     if (!(data = av_mallocz(sizeof(*data) * planes)))
+         goto fail;
+     if (av_samples_alloc(data, &linesize, nb_channels, nb_samples, link->format, 0) < 0)
+         goto fail;
 -AVFilterBufferRef* avfilter_get_audio_buffer_ref_from_arrays(uint8_t **data,
++    samplesref = avfilter_get_audio_buffer_ref_from_arrays_alt(data, linesize, perms,
+                                                            nb_samples, link->format,
+                                                            link->channel_layout);
+     if (!samplesref)
+         goto fail;
+     av_freep(&data);
+ fail:
+     if (data)
+         av_freep(&data[0]);
+     av_freep(&data);
+     return samplesref;
+ }
+ AVFilterBufferRef *ff_get_audio_buffer(AVFilterLink *link, int perms,
+                                        int nb_samples)
+ {
+     AVFilterBufferRef *ret = NULL;
+     if (link->dstpad->get_audio_buffer)
+         ret = link->dstpad->get_audio_buffer(link, perms, nb_samples);
+     if (!ret)
+         ret = ff_default_get_audio_buffer(link, perms, nb_samples);
+     if (ret)
+         ret->type = AVMEDIA_TYPE_AUDIO;
+     return ret;
+ }
 -
++AVFilterBufferRef *
++avfilter_get_audio_buffer_ref_from_arrays(uint8_t *data[8], int linesize[8], int perms,
++                                          int nb_samples, enum AVSampleFormat sample_fmt,
++                                          uint64_t channel_layout, int planar)
++{
++    AVFilterBuffer *samples = av_mallocz(sizeof(AVFilterBuffer));
++    AVFilterBufferRef *samplesref = av_mallocz(sizeof(AVFilterBufferRef));
++
++    if (!samples || !samplesref)
++        goto fail;
++
++    samplesref->buf = samples;
++    samplesref->buf->free = ff_avfilter_default_free_buffer;
++    if (!(samplesref->audio = av_mallocz(sizeof(AVFilterBufferRefAudioProps))))
++        goto fail;
++
++    samplesref->audio->nb_samples     = nb_samples;
++    samplesref->audio->channel_layout = channel_layout;
++    samplesref->audio->planar         = planar;
++
++    /* make sure the buffer gets read permission or it's useless for output */
++    samplesref->perms = perms | AV_PERM_READ;
++
++    samples->refcount = 1;
++    samplesref->type = AVMEDIA_TYPE_AUDIO;
++    samplesref->format = sample_fmt;
++
++    memcpy(samples->data,        data,     sizeof(samples->data));
++    memcpy(samples->linesize,    linesize, sizeof(samples->linesize));
++    memcpy(samplesref->data,     data,     sizeof(samplesref->data));
++    memcpy(samplesref->linesize, linesize, sizeof(samplesref->linesize));
++
++    return samplesref;
++
++fail:
++    if (samplesref && samplesref->audio)
++        av_freep(&samplesref->audio);
++    av_freep(&samplesref);
++    av_freep(&samples);
++    return NULL;
++}
++
++AVFilterBufferRef* avfilter_get_audio_buffer_ref_from_arrays_alt(uint8_t **data,
+                                                              int linesize,int perms,
+                                                              int nb_samples,
+                                                              enum AVSampleFormat sample_fmt,
+                                                              uint64_t channel_layout)
+ {
+     int planes;
+     AVFilterBuffer    *samples    = av_mallocz(sizeof(*samples));
+     AVFilterBufferRef *samplesref = av_mallocz(sizeof(*samplesref));
+     if (!samples || !samplesref)
+         goto fail;
+     samplesref->buf         = samples;
+     samplesref->buf->free   = ff_avfilter_default_free_buffer;
+     if (!(samplesref->audio = av_mallocz(sizeof(*samplesref->audio))))
+         goto fail;
+     samplesref->audio->nb_samples     = nb_samples;
+     samplesref->audio->channel_layout = channel_layout;
+     samplesref->audio->planar         = av_sample_fmt_is_planar(sample_fmt);
+     planes = samplesref->audio->planar ? av_get_channel_layout_nb_channels(channel_layout) : 1;
+     /* make sure the buffer gets read permission or it's useless for output */
+     samplesref->perms = perms | AV_PERM_READ;
+     samples->refcount  = 1;
+     samplesref->type   = AVMEDIA_TYPE_AUDIO;
+     samplesref->format = sample_fmt;
+     memcpy(samples->data, data,
+            FFMIN(FF_ARRAY_ELEMS(samples->data), planes)*sizeof(samples->data[0]));
+     memcpy(samplesref->data, samples->data, sizeof(samples->data));
+     samples->linesize[0] = samplesref->linesize[0] = linesize;
+     if (planes > FF_ARRAY_ELEMS(samples->data)) {
+         samples->   extended_data = av_mallocz(sizeof(*samples->extended_data) *
+                                                planes);
+         samplesref->extended_data = av_mallocz(sizeof(*samplesref->extended_data) *
+                                                planes);
+         if (!samples->extended_data || !samplesref->extended_data)
+             goto fail;
+         memcpy(samples->   extended_data, data, sizeof(*data)*planes);
+         memcpy(samplesref->extended_data, data, sizeof(*data)*planes);
+     } else {
+         samples->extended_data    = samples->data;
+         samplesref->extended_data = samplesref->data;
+     }
+     return samplesref;
+ fail:
+     if (samples && samples->extended_data != samples->data)
+         av_freep(&samples->extended_data);
+     if (samplesref) {
+         av_freep(&samplesref->audio);
+         if (samplesref->extended_data != samplesref->data)
+             av_freep(&samplesref->extended_data);
+     }
+     av_freep(&samplesref);
+     av_freep(&samples);
+     return NULL;
+ }
+ void ff_null_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref)
+ {
+     ff_filter_samples(link->dst->outputs[0], samplesref);
+ }
+ /* FIXME: samplesref is same as link->cur_buf. Need to consider removing the redundant parameter. */
+ void ff_default_filter_samples(AVFilterLink *inlink, AVFilterBufferRef *samplesref)
+ {
+     AVFilterLink *outlink = NULL;
+     if (inlink->dst->output_count)
+         outlink = inlink->dst->outputs[0];
+     if (outlink) {
+         outlink->out_buf = ff_default_get_audio_buffer(inlink, AV_PERM_WRITE,
+                                                        samplesref->audio->nb_samples);
+         outlink->out_buf->pts                = samplesref->pts;
+         outlink->out_buf->audio->sample_rate = samplesref->audio->sample_rate;
+         ff_filter_samples(outlink, avfilter_ref_buffer(outlink->out_buf, ~0));
+         avfilter_unref_buffer(outlink->out_buf);
+         outlink->out_buf = NULL;
+     }
+     avfilter_unref_buffer(samplesref);
+     inlink->cur_buf = NULL;
+ }
+ void ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref)
+ {
+     void (*filter_samples)(AVFilterLink *, AVFilterBufferRef *);
+     AVFilterPad *dst = link->dstpad;
++    int64_t pts;
+     FF_DPRINTF_START(NULL, filter_samples); ff_dlog_link(NULL, link, 1);
+     if (!(filter_samples = dst->filter_samples))
+         filter_samples = ff_default_filter_samples;
+     /* prepare to copy the samples if the buffer has insufficient permissions */
+     if ((dst->min_perms & samplesref->perms) != dst->min_perms ||
+         dst->rej_perms & samplesref->perms) {
+         int  i, planar = av_sample_fmt_is_planar(samplesref->format);
+         int planes = !planar ? 1:
+                      av_get_channel_layout_nb_channels(samplesref->audio->channel_layout);
+         av_log(link->dst, AV_LOG_DEBUG,
+                "Copying audio data in avfilter (have perms %x, need %x, reject %x)\n",
+                samplesref->perms, link->dstpad->min_perms, link->dstpad->rej_perms);
+         link->cur_buf = ff_default_get_audio_buffer(link, dst->min_perms,
+                                                     samplesref->audio->nb_samples);
+         link->cur_buf->pts                = samplesref->pts;
+         link->cur_buf->audio->sample_rate = samplesref->audio->sample_rate;
+         /* Copy actual data into new samples buffer */
++        for (i = 0; samplesref->data[i] && i < 8; i++)
++            memcpy(link->cur_buf->data[i], samplesref->data[i], samplesref->linesize[0]);
+         for (i = 0; i < planes; i++)
+             memcpy(link->cur_buf->extended_data[i], samplesref->extended_data[i], samplesref->linesize[0]);
+         avfilter_unref_buffer(samplesref);
+     } else
+         link->cur_buf = samplesref;
++    pts = link->cur_buf->pts;
+     filter_samples(link, link->cur_buf);
++    ff_update_link_current_pts(link, pts);
+ }
index 0000000,935bec5..051efb2
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,61 +1,65 @@@
 - * This file is part of Libav.
+ /*
 - * Libav is free software; you can redistribute it and/or
++ * Copyright (c) Stefano Sabatini | stefasab at gmail.com
++ * Copyright (c) S.N. Hemanth Meenakshisundaram | smeenaks at ucsd.edu
+  *
 - * Libav is distributed in the hope that it will be useful,
++ * This file is part of FFmpeg.
++ *
++ * FFmpeg is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU Lesser General Public
+  * License as published by the Free Software Foundation; either
+  * version 2.1 of the License, or (at your option) any later version.
+  *
 - * License along with Libav; if not, write to the Free Software
++ * FFmpeg is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
+  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+  */
+ #ifndef AVFILTER_AUDIO_H
+ #define AVFILTER_AUDIO_H
+ #include "avfilter.h"
++
+ /** default handler for get_audio_buffer() for audio inputs */
+ AVFilterBufferRef *ff_default_get_audio_buffer(AVFilterLink *link, int perms,
+                                                      int nb_samples);
+ /** get_audio_buffer() handler for filters which simply pass audio along */
+ AVFilterBufferRef *ff_null_get_audio_buffer(AVFilterLink *link, int perms,
+                                                   int nb_samples);
+ /**
+  * Request an audio samples buffer with a specific set of permissions.
+  *
+  * @param link           the output link to the filter from which the buffer will
+  *                       be requested
+  * @param perms          the required access permissions
+  * @param nb_samples     the number of samples per channel
+  * @return               A reference to the samples. This must be unreferenced with
+  *                       avfilter_unref_buffer when you are finished with it.
+  */
+ AVFilterBufferRef *ff_get_audio_buffer(AVFilterLink *link, int perms,
+                                              int nb_samples);
+ /** default handler for filter_samples() for audio inputs */
+ void ff_default_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref);
+ /** filter_samples() handler for filters which simply pass audio along */
+ void ff_null_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref);
+ /**
+  * Send a buffer of audio samples to the next filter.
+  *
+  * @param link       the output link over which the audio samples are being sent
+  * @param samplesref a reference to the buffer of audio samples being sent. The
+  *                   receiving filter will free this reference when it no longer
+  *                   needs it or pass it on to the next filter.
+  */
+ void ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref);
+ #endif /* AVFILTER_AUDIO_H */
@@@ -25,8 -25,8 +25,9 @@@
  #include "libavutil/rational.h"
  #include "libavutil/audioconvert.h"
  #include "libavutil/imgutils.h"
 -#include "libavcodec/avcodec.h"
 +#include "libavutil/avassert.h"
 +#include "libavutil/avstring.h"
  #include "avfilter.h"
  #include "internal.h"
  
@@@ -657,15 -394,6 +529,15 @@@ int avfilter_poll_frame(AVFilterLink *l
      return min;
  }
  
- static void update_link_current_pts(AVFilterLink *link, int64_t pts)
++void ff_update_link_current_pts(AVFilterLink *link, int64_t pts)
 +{
 +    if (pts == AV_NOPTS_VALUE)
 +        return;
 +    link->current_pts =  pts; /* TODO use duration */
 +    if (link->graph && link->age_index >= 0)
 +        ff_avfilter_graph_update_heap(link->graph, link);
 +}
 +
  /* XXX: should we do the duplicating of the picture ref here, instead of
   * forcing the source filter to do it? */
  void avfilter_start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
      else
          link->cur_buf = picref;
  
 +    while(cmd && cmd->time <= picref->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);
 +        command_queue_pop(link->dst);
 +        cmd= link->dst->command_queue;
 +    }
 +
      start_frame(link, link->cur_buf);
-     update_link_current_pts(link, link->cur_buf->pts);
++    ff_update_link_current_pts(link, link->cur_buf->pts);
  }
  
  void avfilter_end_frame(AVFilterLink *link)
@@@ -767,56 -484,7 +639,18 @@@ void avfilter_draw_slice(AVFilterLink *
      draw_slice(link, y, h, slice_dir);
  }
  
 -#define MAX_REGISTERED_AVFILTERS_NB 64
 +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);
 +}
 +
- void avfilter_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref)
- {
-     void (*filter_samples)(AVFilterLink *, AVFilterBufferRef *);
-     AVFilterPad *dst = link->dstpad;
-     int i;
-     int64_t pts;
-     FF_DPRINTF_START(NULL, filter_samples); ff_dlog_link(NULL, link, 1);
-     if (!(filter_samples = dst->filter_samples))
-         filter_samples = avfilter_default_filter_samples;
-     /* prepare to copy the samples if the buffer has insufficient permissions */
-     if ((dst->min_perms & samplesref->perms) != dst->min_perms ||
-         dst->rej_perms & samplesref->perms) {
-         av_log(link->dst, AV_LOG_DEBUG,
-                "Copying audio data in avfilter (have perms %x, need %x, reject %x)\n",
-                samplesref->perms, link->dstpad->min_perms, link->dstpad->rej_perms);
-         link->cur_buf = avfilter_default_get_audio_buffer(link, dst->min_perms,
-                                                           samplesref->audio->nb_samples);
-         link->cur_buf->pts                = samplesref->pts;
-         link->cur_buf->audio->sample_rate = samplesref->audio->sample_rate;
-         /* Copy actual data into new samples buffer */
-         for (i = 0; samplesref->data[i] && i < 8; i++)
-             memcpy(link->cur_buf->data[i], samplesref->data[i], samplesref->linesize[0]);
-         avfilter_unref_buffer(samplesref);
-     } else
-         link->cur_buf = samplesref;
-     pts = link->cur_buf->pts;
-     filter_samples(link, link->cur_buf);
-     update_link_current_pts(link, pts);
- }
 +#define MAX_REGISTERED_AVFILTERS_NB 128
  
  static AVFilter *registered_avfilters[MAX_REGISTERED_AVFILTERS_NB + 1];
  
@@@ -508,26 -460,19 +509,20 @@@ void avfilter_default_draw_slice(AVFilt
  /** default handler for end_frame() for video inputs */
  void avfilter_default_end_frame(AVFilterLink *link);
  
- /** default handler for filter_samples() for audio inputs */
- void avfilter_default_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref);
 -/** default handler for config_props() for audio/video outputs */
 -int avfilter_default_config_output_link(AVFilterLink *link);
--
  /** default handler for get_video_buffer() for video inputs */
  AVFilterBufferRef *avfilter_default_get_video_buffer(AVFilterLink *link,
                                                       int perms, int w, int h);
  
- /** default handler for get_audio_buffer() for audio inputs */
- AVFilterBufferRef *avfilter_default_get_audio_buffer(AVFilterLink *link,
-                                                      int perms, int nb_samples);
 +
  /**
 - * A helper for query_formats() which sets all links to the same list of
 - * formats. If there are no links hooked to this filter, the list of formats is
 - * freed.
 + * Helpers for query_formats() which set all links to the same list of
 + * formats/layouts. If there are no links hooked to this filter, the list
 + * of formats is freed.
   */
 -void avfilter_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats);
 +void avfilter_set_common_pixel_formats(AVFilterContext *ctx, AVFilterFormats *formats);
 +void avfilter_set_common_sample_formats(AVFilterContext *ctx, AVFilterFormats *formats);
 +void avfilter_set_common_channel_layouts(AVFilterContext *ctx, AVFilterFormats *formats);
 +void avfilter_set_common_packing_formats(AVFilterContext *ctx, AVFilterFormats *formats);
  
  /** Default handler for query_formats() */
  int avfilter_default_query_formats(AVFilterContext *ctx);
@@@ -663,9 -580,9 +651,9 @@@ 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/audioconvert.h)
- #if LIBAVFILTER_VERSION_MAJOR < 3
+ #if FF_API_SAMPLERATE64
      int64_t sample_rate;        ///< samples per second
  #else
      int sample_rate;            ///< samples per second
@@@ -895,26 -739,7 +870,16 @@@ void avfilter_end_frame(AVFilterLink *l
   */
  void avfilter_draw_slice(AVFilterLink *link, int y, int h, int slice_dir);
  
- /**
-  * Send a buffer of audio samples to the next filter.
-  *
-  * @param link       the output link over which the audio samples are being sent
-  * @param samplesref a reference to the buffer of audio samples being sent. The
-  *                   receiving filter will free this reference when it no longer
-  *                   needs it or pass it on to the next filter.
-  */
- void avfilter_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref);
- /** Initialize the filter system. Register all built-in filters. */
 +#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);
  
  /** Uninitialize the filter system. Unregister all filters. */
@@@ -1024,4 -849,20 +989,6 @@@ static inline void avfilter_insert_outp
                          &f->output_pads, &f->outputs, p);
  }
  
 -/**
 - * Copy the frame properties of src to dst, without copying the actual
 - * image data.
 - *
 - * @return 0 on success, a negative number on error.
 - */
 -int avfilter_copy_frame_props(AVFilterBufferRef *dst, const AVFrame *src);
 -
 -/**
 - * Copy the frame properties and data pointers of src to dst, without copying
 - * the actual data.
 - *
 - * @return 0 on success, a negative number on error.
 - */
 -int avfilter_copy_buf_props(AVFrame *dst, const AVFilterBufferRef *src);
++#include "audio.h"
  #endif /* AVFILTER_AVFILTER_H */
@@@ -163,74 -102,59 +132,53 @@@ void avfilter_default_end_frame(AVFilte
      }
  }
  
- /* FIXME: samplesref is same as link->cur_buf. Need to consider removing the redundant parameter. */
- void avfilter_default_filter_samples(AVFilterLink *inlink, AVFilterBufferRef *samplesref)
- {
-     AVFilterLink *outlink = NULL;
-     if (inlink->dst->output_count)
-         outlink = inlink->dst->outputs[0];
-     if (outlink) {
-         outlink->out_buf = avfilter_default_get_audio_buffer(inlink, AV_PERM_WRITE,
-                                                              samplesref->audio->nb_samples);
-         outlink->out_buf->pts                = samplesref->pts;
-         outlink->out_buf->audio->sample_rate = samplesref->audio->sample_rate;
-         avfilter_filter_samples(outlink, avfilter_ref_buffer(outlink->out_buf, ~0));
-         avfilter_unref_buffer(outlink->out_buf);
-         outlink->out_buf = NULL;
-     }
-     avfilter_unref_buffer(samplesref);
-     inlink->cur_buf = NULL;
- }
 -/**
 - * default config_link() implementation for output video links to simplify
 - * the implementation of one input one output video filters */
 -int avfilter_default_config_output_link(AVFilterLink *link)
 +static void set_common_formats(AVFilterContext *ctx, AVFilterFormats *fmts,
 +                               enum AVMediaType type, int offin, int offout)
  {
 -    if (link->src->input_count && link->src->inputs[0]) {
 -        if (link->type == AVMEDIA_TYPE_VIDEO) {
 -            link->w = link->src->inputs[0]->w;
 -            link->h = link->src->inputs[0]->h;
 -            link->time_base = link->src->inputs[0]->time_base;
 -        } else if (link->type == AVMEDIA_TYPE_AUDIO) {
 -            link->channel_layout = link->src->inputs[0]->channel_layout;
 -            link->sample_rate    = link->src->inputs[0]->sample_rate;
 -        }
 -    } else {
 -        /* XXX: any non-simple filter which would cause this branch to be taken
 -         * really should implement its own config_props() for this link. */
 -        return -1;
 +    int i;
 +    for (i = 0; i < ctx->input_count; i++)
 +        if (ctx->inputs[i] && ctx->inputs[i]->type == type)
 +            avfilter_formats_ref(fmts,
 +                                 (AVFilterFormats **)((uint8_t *)ctx->inputs[i]+offout));
 +
 +    for (i = 0; i < ctx->output_count; i++)
 +        if (ctx->outputs[i] && ctx->outputs[i]->type == type)
 +            avfilter_formats_ref(fmts,
 +                                 (AVFilterFormats **)((uint8_t *)ctx->outputs[i]+offin));
 +
 +    if (!fmts->refcount) {
 +        av_free(fmts->formats);
 +        av_free(fmts->refs);
 +        av_free(fmts);
      }
 +}
  
 -    return 0;
 +void avfilter_set_common_pixel_formats(AVFilterContext *ctx, AVFilterFormats *formats)
 +{
 +    set_common_formats(ctx, formats, AVMEDIA_TYPE_VIDEO,
 +                       offsetof(AVFilterLink, in_formats),
 +                       offsetof(AVFilterLink, out_formats));
  }
  
 -/**
 - * A helper for query_formats() which sets all links to the same list of
 - * formats. If there are no links hooked to this filter, the list of formats is
 - * freed.
 - *
 - * FIXME: this will need changed for filters with a mix of pad types
 - * (video + audio, etc)
 - */
 -void avfilter_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats)
 +void avfilter_set_common_sample_formats(AVFilterContext *ctx, AVFilterFormats *formats)
  {
 -    int count = 0, i;
 +    set_common_formats(ctx, formats, AVMEDIA_TYPE_AUDIO,
 +                       offsetof(AVFilterLink, in_formats),
 +                       offsetof(AVFilterLink, out_formats));
 +}
  
 -    for (i = 0; i < ctx->input_count; i++) {
 -        if (ctx->inputs[i]) {
 -            avfilter_formats_ref(formats, &ctx->inputs[i]->out_formats);
 -            count++;
 -        }
 -    }
 -    for (i = 0; i < ctx->output_count; i++) {
 -        if (ctx->outputs[i]) {
 -            avfilter_formats_ref(formats, &ctx->outputs[i]->in_formats);
 -            count++;
 -        }
 -    }
 +void avfilter_set_common_channel_layouts(AVFilterContext *ctx, AVFilterFormats *formats)
 +{
 +    set_common_formats(ctx, formats, AVMEDIA_TYPE_AUDIO,
 +                       offsetof(AVFilterLink, in_chlayouts),
 +                       offsetof(AVFilterLink, out_chlayouts));
 +}
  
 -    if (!count) {
 -        av_free(formats->formats);
 -        av_free(formats->refs);
 -        av_free(formats);
 -    }
 +void avfilter_set_common_packing_formats(AVFilterContext *ctx, AVFilterFormats *formats)
 +{
 +    set_common_formats(ctx, formats, AVMEDIA_TYPE_AUDIO,
 +                       offsetof(AVFilterLink, in_packing),
 +                       offsetof(AVFilterLink, out_packing));
  }
  
  int avfilter_default_query_formats(AVFilterContext *ctx)
@@@ -76,77 -55,8 +76,83 @@@ 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);
  
 +/**
 + * 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 PixelFormat *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 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);
 +
 +/**
 + * Parse a packing format 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_packing_format(int *ret, const char *arg, void *log_ctx);
 +
 +/**
 + * Pass video frame along and keep an internal reference for later use.
 + */
 +static inline void ff_null_start_frame_keep_ref(AVFilterLink *inlink,
 +                                                AVFilterBufferRef *picref)
 +{
 +    avfilter_start_frame(inlink->dst->outputs[0], avfilter_ref_buffer(picref, ~0));
 +}
 +
++void ff_update_link_current_pts(AVFilterLink *link, int64_t pts);
++
+ #define FF_DPRINTF_START(ctx, func) av_dlog(NULL, "%-16s: ", #func)
+ void ff_dlog_link(void *ctx, AVFilterLink *link, int end);
  #endif /* AVFILTER_INTERNAL_H */
index 19c49a3,0000000..f6c67f4
mode 100644,000000..100644
--- /dev/null
@@@ -1,675 -1,0 +1,675 @@@
-         buf = avfilter_get_audio_buffer(outlink, AV_PERM_WRITE,
 +/*
 + * Copyright (c) 2008 Vitor Sessak
 + * Copyright (c) 2010 S.N. Hemanth Meenakshisundaram
 + * Copyright (c) 2011 Mina Nagy Zaki
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +/**
 + * @file
 + * memory buffer source filter
 + */
 +
 +#include "avfilter.h"
 +#include "internal.h"
 +#include "avcodec.h"
 +#include "buffersrc.h"
 +#include "vsrc_buffer.h"
 +#include "asrc_abuffer.h"
 +#include "libavutil/audioconvert.h"
 +#include "libavutil/avstring.h"
 +#include "libavutil/fifo.h"
 +#include "libavutil/imgutils.h"
 +
 +typedef struct {
 +    AVFifoBuffer     *fifo;
 +    AVRational        time_base;     ///< time_base to set in the output link
 +    int eof;
 +    unsigned          nb_failed_requests;
 +
 +    /* Video only */
 +    AVFilterContext  *scale;
 +    int               h, w;
 +    enum PixelFormat  pix_fmt;
 +    AVRational        sample_aspect_ratio;
 +    char              sws_param[256];
 +
 +    /* Audio only */
 +    // Audio format of incoming buffers
 +    int sample_rate;
 +    unsigned int sample_format;
 +    int64_t channel_layout;
 +    int packing_format;
 +
 +    // Normalization filters
 +    AVFilterContext *aconvert;
 +    AVFilterContext *aresample;
 +} BufferSourceContext;
 +
 +#define FIFO_SIZE 8
 +
 +#define CHECK_PARAM_CHANGE(s, c, width, height, format)\
 +    if (c->w != width || c->h != height || c->pix_fmt != format) {\
 +        av_log(s, AV_LOG_ERROR, "Changing frame properties on the fly is not supported.\n");\
 +        return AVERROR(EINVAL);\
 +    }
 +
 +static void buf_free(AVFilterBuffer *ptr)
 +{
 +    av_free(ptr);
 +    return;
 +}
 +
 +static void set_link_source(AVFilterContext *src, AVFilterLink *link)
 +{
 +    link->src       = src;
 +    link->srcpad    = &(src->output_pads[0]);
 +    src->outputs[0] = link;
 +}
 +
 +static int reconfigure_filter(BufferSourceContext *abuffer, AVFilterContext *filt_ctx)
 +{
 +    int ret;
 +    AVFilterLink * const inlink  = filt_ctx->inputs[0];
 +    AVFilterLink * const outlink = filt_ctx->outputs[0];
 +
 +    inlink->format         = abuffer->sample_format;
 +    inlink->channel_layout = abuffer->channel_layout;
 +    inlink->planar         = abuffer->packing_format;
 +    inlink->sample_rate    = abuffer->sample_rate;
 +
 +    filt_ctx->filter->uninit(filt_ctx);
 +    memset(filt_ctx->priv, 0, filt_ctx->filter->priv_size);
 +    if ((ret = filt_ctx->filter->init(filt_ctx, NULL , NULL)) < 0)
 +        return ret;
 +    if ((ret = inlink->srcpad->config_props(inlink)) < 0)
 +        return ret;
 +    return outlink->srcpad->config_props(outlink);
 +}
 +
 +static int insert_filter(BufferSourceContext *abuffer,
 +                         AVFilterLink *link, AVFilterContext **filt_ctx,
 +                         const char *filt_name)
 +{
 +    int ret;
 +
 +    if ((ret = avfilter_open(filt_ctx, avfilter_get_by_name(filt_name), NULL)) < 0)
 +        return ret;
 +
 +    link->src->outputs[0] = NULL;
 +    if ((ret = avfilter_link(link->src, 0, *filt_ctx, 0)) < 0) {
 +        link->src->outputs[0] = link;
 +        return ret;
 +    }
 +
 +    set_link_source(*filt_ctx, link);
 +
 +    if ((ret = reconfigure_filter(abuffer, *filt_ctx)) < 0) {
 +        avfilter_free(*filt_ctx);
 +        return ret;
 +    }
 +
 +    return 0;
 +}
 +
 +static void remove_filter(AVFilterContext **filt_ctx)
 +{
 +    AVFilterLink *outlink = (*filt_ctx)->outputs[0];
 +    AVFilterContext *src  = (*filt_ctx)->inputs[0]->src;
 +
 +    (*filt_ctx)->outputs[0] = NULL;
 +    avfilter_free(*filt_ctx);
 +    *filt_ctx = NULL;
 +
 +    set_link_source(src, outlink);
 +}
 +
 +static inline void log_input_change(void *ctx, AVFilterLink *link, AVFilterBufferRef *ref)
 +{
 +    char old_layout_str[16], new_layout_str[16];
 +    av_get_channel_layout_string(old_layout_str, sizeof(old_layout_str),
 +                                 -1, link->channel_layout);
 +    av_get_channel_layout_string(new_layout_str, sizeof(new_layout_str),
 +                                 -1, ref->audio->channel_layout);
 +    av_log(ctx, AV_LOG_INFO,
 +           "Audio input format changed: "
 +           "%s:%s:%d -> %s:%s:%d, normalizing\n",
 +           av_get_sample_fmt_name(link->format),
 +           old_layout_str, (int)link->sample_rate,
 +           av_get_sample_fmt_name(ref->format),
 +           new_layout_str, ref->audio->sample_rate);
 +}
 +
 +static int check_format_change_video(AVFilterContext *buffer_filter,
 +                                     AVFilterBufferRef *picref)
 +{
 +    BufferSourceContext *c = buffer_filter->priv;
 +    int ret;
 +
 +    if (picref->video->w != c->w || picref->video->h != c->h || picref->format != c->pix_fmt) {
 +        AVFilterContext *scale = buffer_filter->outputs[0]->dst;
 +        AVFilterLink *link;
 +        char scale_param[1024];
 +
 +        av_log(buffer_filter, AV_LOG_INFO,
 +               "Buffer video input changed from size:%dx%d fmt:%s to size:%dx%d fmt:%s\n",
 +               c->w, c->h, av_pix_fmt_descriptors[c->pix_fmt].name,
 +               picref->video->w, picref->video->h, av_pix_fmt_descriptors[picref->format].name);
 +
 +        if (!scale || strcmp(scale->filter->name, "scale")) {
 +            AVFilter *f = avfilter_get_by_name("scale");
 +
 +            av_log(buffer_filter, AV_LOG_INFO, "Inserting scaler filter\n");
 +            if ((ret = avfilter_open(&scale, f, "Input equalizer")) < 0)
 +                return ret;
 +
 +            c->scale = scale;
 +
 +            snprintf(scale_param, sizeof(scale_param)-1, "%d:%d:%s", c->w, c->h, c->sws_param);
 +            if ((ret = avfilter_init_filter(scale, scale_param, NULL)) < 0) {
 +                return ret;
 +            }
 +
 +            if ((ret = avfilter_insert_filter(buffer_filter->outputs[0], scale, 0, 0)) < 0) {
 +                return ret;
 +            }
 +            scale->outputs[0]->time_base = scale->inputs[0]->time_base;
 +
 +            scale->outputs[0]->format= c->pix_fmt;
 +        } else if (!strcmp(scale->filter->name, "scale")) {
 +            snprintf(scale_param, sizeof(scale_param)-1, "%d:%d:%s",
 +                     scale->outputs[0]->w, scale->outputs[0]->h, c->sws_param);
 +            scale->filter->init(scale, scale_param, NULL);
 +        }
 +
 +        c->pix_fmt = scale->inputs[0]->format = picref->format;
 +        c->w       = scale->inputs[0]->w      = picref->video->w;
 +        c->h       = scale->inputs[0]->h      = picref->video->h;
 +
 +        link = scale->outputs[0];
 +        if ((ret =  link->srcpad->config_props(link)) < 0)
 +            return ret;
 +    }
 +    return 0;
 +}
 +
 +static int check_format_change_audio(AVFilterContext *ctx,
 +                                     AVFilterBufferRef *samplesref)
 +{
 +    BufferSourceContext *abuffer = ctx->priv;
 +    AVFilterLink *link;
 +    int ret, logged = 0;
 +
 +    link = ctx->outputs[0];
 +    if (samplesref->audio->sample_rate != link->sample_rate) {
 +
 +        log_input_change(ctx, link, samplesref);
 +        logged = 1;
 +
 +        abuffer->sample_rate = samplesref->audio->sample_rate;
 +
 +        if (!abuffer->aresample) {
 +            ret = insert_filter(abuffer, link, &abuffer->aresample, "aresample");
 +            if (ret < 0) return ret;
 +        } else {
 +            link = abuffer->aresample->outputs[0];
 +            if (samplesref->audio->sample_rate == link->sample_rate)
 +                remove_filter(&abuffer->aresample);
 +            else
 +                if ((ret = reconfigure_filter(abuffer, abuffer->aresample)) < 0)
 +                    return ret;
 +        }
 +    }
 +
 +    link = ctx->outputs[0];
 +    if (samplesref->format                != link->format         ||
 +        samplesref->audio->channel_layout != link->channel_layout ||
 +        samplesref->audio->planar         != link->planar) {
 +
 +        if (!logged) log_input_change(ctx, link, samplesref);
 +
 +        abuffer->sample_format  = samplesref->format;
 +        abuffer->channel_layout = samplesref->audio->channel_layout;
 +        abuffer->packing_format = samplesref->audio->planar;
 +
 +        if (!abuffer->aconvert) {
 +            ret = insert_filter(abuffer, link, &abuffer->aconvert, "aconvert");
 +            if (ret < 0) return ret;
 +        } else {
 +            link = abuffer->aconvert->outputs[0];
 +            if (samplesref->format                == link->format         &&
 +                samplesref->audio->channel_layout == link->channel_layout &&
 +                samplesref->audio->planar         == link->planar
 +               )
 +                remove_filter(&abuffer->aconvert);
 +            else
 +                if ((ret = reconfigure_filter(abuffer, abuffer->aconvert)) < 0)
 +                    return ret;
 +        }
 +    }
 +
 +    return 0;
 +}
 +
 +static int check_format_change(AVFilterContext *buffer_filter,
 +                               AVFilterBufferRef *picref)
 +{
 +    switch (buffer_filter->outputs[0]->type) {
 +    case AVMEDIA_TYPE_VIDEO:
 +        return check_format_change_video(buffer_filter, picref);
 +    case AVMEDIA_TYPE_AUDIO:
 +        return check_format_change_audio(buffer_filter, picref);
 +    default:
 +        return AVERROR(ENOSYS);
 +    }
 +}
 +
 +static AVFilterBufferRef *copy_buffer_ref(AVFilterContext *ctx,
 +                                          AVFilterBufferRef *ref)
 +{
 +    AVFilterLink *outlink = ctx->outputs[0];
 +    AVFilterBufferRef *buf;
 +    int channels, data_size, i;
 +
 +    switch (outlink->type) {
 +
 +    case AVMEDIA_TYPE_VIDEO:
 +        buf = avfilter_get_video_buffer(outlink, AV_PERM_WRITE,
 +                                        ref->video->w, ref->video->h);
 +        av_image_copy(buf->data, buf->linesize,
 +                      (void*)ref->data, ref->linesize,
 +                      ref->format, ref->video->w, ref->video->h);
 +        break;
 +
 +    case AVMEDIA_TYPE_AUDIO:
-         avfilter_filter_samples(link, avfilter_ref_buffer(buf, ~0));
++        buf = ff_get_audio_buffer(outlink, AV_PERM_WRITE,
 +                                        ref->audio->nb_samples);
 +        channels = av_get_channel_layout_nb_channels(ref->audio->channel_layout);
 +        data_size = av_samples_get_buffer_size(NULL, channels,
 +                                               ref->audio->nb_samples,
 +                                               ref->format, 1);
 +        for (i = 0; i < FF_ARRAY_ELEMS(ref->buf->data) && ref->buf->data[i]; i++)
 +            memcpy(buf->buf->data[i], ref->buf->data[i], data_size);
 +        break;
 +
 +    default:
 +        return NULL;
 +    }
 +    avfilter_copy_buffer_ref_props(buf, ref);
 +    return buf;
 +}
 +
 +int av_buffersrc_add_ref(AVFilterContext *buffer_filter,
 +                         AVFilterBufferRef *picref, int flags)
 +{
 +    BufferSourceContext *c = buffer_filter->priv;
 +    AVFilterBufferRef *buf;
 +    int ret;
 +
 +    if (!picref) {
 +        c->eof = 1;
 +        return 0;
 +    } else if (c->eof)
 +        return AVERROR(EINVAL);
 +
 +    if (!av_fifo_space(c->fifo) &&
 +        (ret = av_fifo_realloc2(c->fifo, av_fifo_size(c->fifo) +
 +                                         sizeof(buf))) < 0)
 +        return ret;
 +
 +    if (!(flags & AV_BUFFERSRC_FLAG_NO_CHECK_FORMAT)) {
 +        ret = check_format_change(buffer_filter, picref);
 +        if (ret < 0)
 +            return ret;
 +    }
 +    if (flags & AV_BUFFERSRC_FLAG_NO_COPY)
 +        buf = picref;
 +    else
 +        buf = copy_buffer_ref(buffer_filter, picref);
 +
 +    if ((ret = av_fifo_generic_write(c->fifo, &buf, sizeof(buf), NULL)) < 0) {
 +        if (buf != picref)
 +            avfilter_unref_buffer(buf);
 +        return ret;
 +    }
 +    c->nb_failed_requests = 0;
 +
 +    return 0;
 +}
 +
 +int av_vsrc_buffer_add_video_buffer_ref(AVFilterContext *buffer_filter,
 +                                        AVFilterBufferRef *picref, int flags)
 +{
 +    return av_buffersrc_add_ref(buffer_filter, picref, 0);
 +}
 +
 +#if CONFIG_AVCODEC
 +#include "avcodec.h"
 +
 +int av_buffersrc_add_frame(AVFilterContext *buffer_src,
 +                           const AVFrame *frame, int flags)
 +{
 +    AVFilterBufferRef *picref;
 +    int ret;
 +
 +    if (!frame) /* NULL for EOF */
 +        return av_buffersrc_add_ref(buffer_src, NULL, flags);
 +
 +    switch (buffer_src->outputs[0]->type) {
 +    case AVMEDIA_TYPE_VIDEO:
 +        picref = avfilter_get_video_buffer_ref_from_frame(frame, AV_PERM_WRITE);
 +        break;
 +    case AVMEDIA_TYPE_AUDIO:
 +        picref = avfilter_get_audio_buffer_ref_from_frame(frame, AV_PERM_WRITE);
 +        break;
 +    default:
 +        return AVERROR(ENOSYS);
 +    }
 +    if (!picref)
 +        return AVERROR(ENOMEM);
 +    ret = av_buffersrc_add_ref(buffer_src, picref, flags);
 +    picref->buf->data[0] = NULL;
 +    avfilter_unref_buffer(picref);
 +    return ret;
 +}
 +
 +int av_vsrc_buffer_add_frame(AVFilterContext *buffer_src,
 +                             const AVFrame *frame, int flags)
 +{
 +    return av_buffersrc_add_frame(buffer_src, frame, 0);
 +}
 +#endif
 +
 +unsigned av_buffersrc_get_nb_failed_requests(AVFilterContext *buffer_src)
 +{
 +    return ((BufferSourceContext *)buffer_src->priv)->nb_failed_requests;
 +}
 +
 +unsigned av_vsrc_buffer_get_nb_failed_requests(AVFilterContext *buffer_src)
 +{
 +    return ((BufferSourceContext *)buffer_src->priv)->nb_failed_requests;
 +}
 +
 +static av_cold int init_video(AVFilterContext *ctx, const char *args, void *opaque)
 +{
 +    BufferSourceContext *c = ctx->priv;
 +    char pix_fmt_str[128];
 +    int ret, n = 0;
 +    *c->sws_param = 0;
 +
 +    if (!args ||
 +        (n = sscanf(args, "%d:%d:%127[^:]:%d:%d:%d:%d:%255c", &c->w, &c->h, pix_fmt_str,
 +                    &c->time_base.num, &c->time_base.den,
 +                    &c->sample_aspect_ratio.num, &c->sample_aspect_ratio.den, c->sws_param)) < 7) {
 +        av_log(ctx, AV_LOG_ERROR, "Expected at least 7 arguments, but only %d found in '%s'\n", n, args);
 +        return AVERROR(EINVAL);
 +    }
 +
 +    if ((ret = ff_parse_pixel_format(&c->pix_fmt, pix_fmt_str, ctx)) < 0)
 +        return ret;
 +
 +    if (!(c->fifo = av_fifo_alloc(sizeof(AVFilterBufferRef*))))
 +        return AVERROR(ENOMEM);
 +
 +    av_log(ctx, AV_LOG_INFO, "w:%d h:%d pixfmt:%s tb:%d/%d sar:%d/%d sws_param:%s\n",
 +           c->w, c->h, av_pix_fmt_descriptors[c->pix_fmt].name,
 +           c->time_base.num, c->time_base.den,
 +           c->sample_aspect_ratio.num, c->sample_aspect_ratio.den, c->sws_param);
 +    return 0;
 +}
 +
 +static av_cold int init_audio(AVFilterContext *ctx, const char *args0, void *opaque)
 +{
 +    BufferSourceContext *abuffer = ctx->priv;
 +    char *arg = NULL, *ptr, chlayout_str[16];
 +    char *args = av_strdup(args0);
 +    int ret;
 +
 +    arg = av_strtok(args, ":", &ptr);
 +
 +#define ADD_FORMAT(fmt_name)                                            \
 +    if (!arg)                                                           \
 +        goto arg_fail;                                                  \
 +    if ((ret = ff_parse_##fmt_name(&abuffer->fmt_name, arg, ctx)) < 0) { \
 +        av_freep(&args);                                                \
 +        return ret;                                                     \
 +    }                                                                   \
 +    if (*args)                                                          \
 +        arg = av_strtok(NULL, ":", &ptr)
 +
 +    ADD_FORMAT(sample_rate);
 +    ADD_FORMAT(sample_format);
 +    ADD_FORMAT(channel_layout);
 +    ADD_FORMAT(packing_format);
 +
 +    abuffer->fifo = av_fifo_alloc(FIFO_SIZE*sizeof(AVFilterBufferRef*));
 +    if (!abuffer->fifo) {
 +        av_log(ctx, AV_LOG_ERROR, "Failed to allocate fifo, filter init failed.\n");
 +        return AVERROR(ENOMEM);
 +    }
 +
 +    av_get_channel_layout_string(chlayout_str, sizeof(chlayout_str),
 +                                 -1, abuffer->channel_layout);
 +    av_log(ctx, AV_LOG_INFO, "format:%s layout:%s rate:%d\n",
 +           av_get_sample_fmt_name(abuffer->sample_format), chlayout_str,
 +           abuffer->sample_rate);
 +    av_freep(&args);
 +
 +    return 0;
 +
 +arg_fail:
 +    av_log(ctx, AV_LOG_ERROR, "Invalid arguments, must be of the form "
 +                              "sample_rate:sample_fmt:channel_layout:packing\n");
 +    av_freep(&args);
 +    return AVERROR(EINVAL);
 +}
 +
 +static av_cold void uninit(AVFilterContext *ctx)
 +{
 +    BufferSourceContext *s = ctx->priv;
 +    while (s->fifo && av_fifo_size(s->fifo)) {
 +        AVFilterBufferRef *buf;
 +        av_fifo_generic_read(s->fifo, &buf, sizeof(buf), NULL);
 +        avfilter_unref_buffer(buf);
 +    }
 +    av_fifo_free(s->fifo);
 +    s->fifo = NULL;
 +    avfilter_free(s->scale);
 +    s->scale = NULL;
 +}
 +
 +static int query_formats_video(AVFilterContext *ctx)
 +{
 +    BufferSourceContext *c = ctx->priv;
 +    enum PixelFormat pix_fmts[] = { c->pix_fmt, PIX_FMT_NONE };
 +
 +    avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts));
 +    return 0;
 +}
 +
 +static int query_formats_audio(AVFilterContext *ctx)
 +{
 +    BufferSourceContext *abuffer = ctx->priv;
 +    AVFilterFormats *formats;
 +
 +    formats = NULL;
 +    avfilter_add_format(&formats, abuffer->sample_format);
 +    avfilter_set_common_sample_formats(ctx, formats);
 +
 +    formats = NULL;
 +    avfilter_add_format(&formats, abuffer->channel_layout);
 +    avfilter_set_common_channel_layouts(ctx, formats);
 +
 +    formats = NULL;
 +    avfilter_add_format(&formats, abuffer->packing_format);
 +    avfilter_set_common_packing_formats(ctx, formats);
 +
 +    return 0;
 +}
 +
 +static int config_output_video(AVFilterLink *link)
 +{
 +    BufferSourceContext *c = link->src->priv;
 +
 +    link->w = c->w;
 +    link->h = c->h;
 +    link->sample_aspect_ratio = c->sample_aspect_ratio;
 +    link->time_base = c->time_base;
 +
 +    return 0;
 +}
 +
 +static int config_output_audio(AVFilterLink *outlink)
 +{
 +    BufferSourceContext *abuffer = outlink->src->priv;
 +    outlink->sample_rate = abuffer->sample_rate;
 +    return 0;
 +}
 +
 +static int request_frame(AVFilterLink *link)
 +{
 +    BufferSourceContext *c = link->src->priv;
 +    AVFilterBufferRef *buf;
 +
 +    if (!av_fifo_size(c->fifo)) {
 +        if (c->eof)
 +            return AVERROR_EOF;
 +        c->nb_failed_requests++;
 +        return AVERROR(EAGAIN);
 +    }
 +    av_fifo_generic_read(c->fifo, &buf, sizeof(buf), NULL);
 +
 +    switch (link->type) {
 +    case AVMEDIA_TYPE_VIDEO:
 +        avfilter_start_frame(link, avfilter_ref_buffer(buf, ~0));
 +        avfilter_draw_slice(link, 0, link->h, 1);
 +        avfilter_end_frame(link);
 +        avfilter_unref_buffer(buf);
 +        break;
 +    case AVMEDIA_TYPE_AUDIO:
++        ff_filter_samples(link, avfilter_ref_buffer(buf, ~0));
 +        avfilter_unref_buffer(buf);
 +        break;
 +    default:
 +        return AVERROR(ENOSYS);
 +    }
 +    return 0;
 +}
 +
 +static int poll_frame(AVFilterLink *link)
 +{
 +    BufferSourceContext *c = link->src->priv;
 +    int size = av_fifo_size(c->fifo);
 +    if (!size && c->eof)
 +        return AVERROR_EOF;
 +    return size/sizeof(AVFilterBufferRef*);
 +}
 +
 +int av_asrc_buffer_add_audio_buffer_ref(AVFilterContext *ctx,
 +                                        AVFilterBufferRef *samplesref,
 +                                        int av_unused flags)
 +{
 +    return av_buffersrc_add_ref(ctx, samplesref, AV_BUFFERSRC_FLAG_NO_COPY);
 +}
 +
 +int av_asrc_buffer_add_samples(AVFilterContext *ctx,
 +                               uint8_t *data[8], int linesize[8],
 +                               int nb_samples, int sample_rate,
 +                               int sample_fmt, int64_t channel_layout, int planar,
 +                               int64_t pts, int av_unused flags)
 +{
 +    AVFilterBufferRef *samplesref;
 +
 +    samplesref = avfilter_get_audio_buffer_ref_from_arrays(
 +                     data, linesize, AV_PERM_WRITE,
 +                     nb_samples,
 +                     sample_fmt, channel_layout, planar);
 +    if (!samplesref)
 +        return AVERROR(ENOMEM);
 +
 +    samplesref->buf->free  = buf_free;
 +    samplesref->pts = pts;
 +    samplesref->audio->sample_rate = sample_rate;
 +
 +    AV_NOWARN_DEPRECATED(
 +    return av_asrc_buffer_add_audio_buffer_ref(ctx, samplesref, 0);
 +    )
 +}
 +
 +int av_asrc_buffer_add_buffer(AVFilterContext *ctx,
 +                              uint8_t *buf, int buf_size, int sample_rate,
 +                              int sample_fmt, int64_t channel_layout, int planar,
 +                              int64_t pts, int av_unused flags)
 +{
 +    uint8_t *data[8] = {0};
 +    int linesize[8];
 +    int nb_channels = av_get_channel_layout_nb_channels(channel_layout),
 +        nb_samples  = buf_size / nb_channels / av_get_bytes_per_sample(sample_fmt);
 +
 +    av_samples_fill_arrays(data, linesize,
 +                           buf, nb_channels, nb_samples,
 +                           sample_fmt, 16);
 +
 +    AV_NOWARN_DEPRECATED(
 +    return av_asrc_buffer_add_samples(ctx,
 +                                      data, linesize, nb_samples,
 +                                      sample_rate,
 +                                      sample_fmt, channel_layout, planar,
 +                                      pts, flags);
 +    )
 +}
 +
 +AVFilter avfilter_vsrc_buffer = {
 +    .name      = "buffer",
 +    .description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them accessible to the filterchain."),
 +    .priv_size = sizeof(BufferSourceContext),
 +    .query_formats = query_formats_video,
 +
 +    .init      = init_video,
 +    .uninit    = uninit,
 +
 +    .inputs    = (const AVFilterPad[]) {{ .name = NULL }},
 +    .outputs   = (const AVFilterPad[]) {{ .name      = "default",
 +                                    .type            = AVMEDIA_TYPE_VIDEO,
 +                                    .request_frame   = request_frame,
 +                                    .poll_frame      = poll_frame,
 +                                    .config_props    = config_output_video, },
 +                                  { .name = NULL}},
 +};
 +
 +#if CONFIG_ABUFFER_FILTER
 +
 +AVFilter avfilter_asrc_abuffer = {
 +    .name        = "abuffer",
 +    .description = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them accessible to the filterchain."),
 +    .priv_size   = sizeof(BufferSourceContext),
 +    .query_formats = query_formats_audio,
 +
 +    .init        = init_audio,
 +    .uninit      = uninit,
 +
 +    .inputs      = (const AVFilterPad[]) {{ .name = NULL }},
 +    .outputs     = (const AVFilterPad[]) {{ .name      = "default",
 +                                      .type            = AVMEDIA_TYPE_AUDIO,
 +                                      .request_frame   = request_frame,
 +                                      .poll_frame      = poll_frame,
 +                                      .config_props    = config_output_audio, },
 +                                    { .name = NULL}},
 +};
 +
 +#endif
index 1d65ade,0000000..15b82ab
mode 100644,000000..100644
--- /dev/null
@@@ -1,489 -1,0 +1,489 @@@
-             avfilter_get_audio_buffer(outlink, AV_PERM_WRITE, nb_samples);
 +/*
 + * Copyright (c) 2010 Stefano Sabatini
 + * Copyright (c) 2008 Victor Paesa
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +/**
 + * @file
 + * movie video source
 + *
 + * @todo use direct rendering (no allocation of a new frame)
 + * @todo support a PTS correction mechanism
 + * @todo support more than one output stream
 + */
 +
 +/* #define DEBUG */
 +
 +#include <float.h>
 +#include "libavutil/avstring.h"
 +#include "libavutil/opt.h"
 +#include "libavutil/imgutils.h"
 +#include "libavformat/avformat.h"
 +#include "avcodec.h"
 +#include "avfilter.h"
 +
 +typedef struct {
 +    /* common A/V fields */
 +    const AVClass *class;
 +    int64_t seek_point;   ///< seekpoint in microseconds
 +    double seek_point_d;
 +    char *format_name;
 +    char *file_name;
 +    int stream_index;
 +    int loop_count;
 +
 +    AVFormatContext *format_ctx;
 +    AVCodecContext *codec_ctx;
 +    int is_done;
 +    AVFrame *frame;   ///< video frame to store the decoded images in
 +
 +    /* video-only fields */
 +    int w, h;
 +    AVFilterBufferRef *picref;
 +
 +    /* audio-only fields */
 +    int bps;            ///< bytes per sample
 +    AVPacket pkt, pkt0;
 +    AVFilterBufferRef *samplesref;
 +} MovieContext;
 +
 +#define OFFSET(x) offsetof(MovieContext, x)
 +
 +static const AVOption movie_options[]= {
 +{"format_name",  "set format name",         OFFSET(format_name),  AV_OPT_TYPE_STRING, {.str =  0},  CHAR_MIN, CHAR_MAX },
 +{"f",            "set format name",         OFFSET(format_name),  AV_OPT_TYPE_STRING, {.str =  0},  CHAR_MIN, CHAR_MAX },
 +{"stream_index", "set stream index",        OFFSET(stream_index), AV_OPT_TYPE_INT,    {.dbl = -1},  -1,       INT_MAX  },
 +{"si",           "set stream index",        OFFSET(stream_index), AV_OPT_TYPE_INT,    {.dbl = -1},  -1,       INT_MAX  },
 +{"seek_point",   "set seekpoint (seconds)", OFFSET(seek_point_d), AV_OPT_TYPE_DOUBLE, {.dbl =  0},  0,        (INT64_MAX-1) / 1000000 },
 +{"sp",           "set seekpoint (seconds)", OFFSET(seek_point_d), AV_OPT_TYPE_DOUBLE, {.dbl =  0},  0,        (INT64_MAX-1) / 1000000 },
 +{"loop",         "set loop count",          OFFSET(loop_count),   AV_OPT_TYPE_INT,    {.dbl =  1},  0,        INT_MAX  },
 +{NULL},
 +};
 +
 +static const char *movie_get_name(void *ctx)
 +{
 +    return "movie";
 +}
 +
 +static const AVClass movie_class = {
 +    "MovieContext",
 +    movie_get_name,
 +    movie_options
 +};
 +
 +static av_cold int movie_common_init(AVFilterContext *ctx, const char *args, void *opaque,
 +                                     enum AVMediaType type)
 +{
 +    MovieContext *movie = ctx->priv;
 +    AVInputFormat *iformat = NULL;
 +    AVCodec *codec;
 +    int64_t timestamp;
 +    int ret;
 +
 +    movie->class = &movie_class;
 +    av_opt_set_defaults(movie);
 +
 +    if (args)
 +        movie->file_name = av_get_token(&args, ":");
 +    if (!movie->file_name || !*movie->file_name) {
 +        av_log(ctx, AV_LOG_ERROR, "No filename provided!\n");
 +        return AVERROR(EINVAL);
 +    }
 +
 +    if (*args++ == ':' && (ret = av_set_options_string(movie, args, "=", ":")) < 0) {
 +        av_log(ctx, AV_LOG_ERROR, "Error parsing options string: '%s'\n", args);
 +        return ret;
 +    }
 +
 +    movie->seek_point = movie->seek_point_d * 1000000 + 0.5;
 +
 +    av_register_all();
 +
 +    // Try to find the movie format (container)
 +    iformat = movie->format_name ? av_find_input_format(movie->format_name) : NULL;
 +
 +    movie->format_ctx = NULL;
 +    if ((ret = avformat_open_input(&movie->format_ctx, movie->file_name, iformat, NULL)) < 0) {
 +        av_log(ctx, AV_LOG_ERROR,
 +               "Failed to avformat_open_input '%s'\n", movie->file_name);
 +        return ret;
 +    }
 +    if ((ret = avformat_find_stream_info(movie->format_ctx, NULL)) < 0)
 +        av_log(ctx, AV_LOG_WARNING, "Failed to find stream info\n");
 +
 +    // if seeking requested, we execute it
 +    if (movie->seek_point > 0) {
 +        timestamp = movie->seek_point;
 +        // add the stream start time, should it exist
 +        if (movie->format_ctx->start_time != AV_NOPTS_VALUE) {
 +            if (timestamp > INT64_MAX - movie->format_ctx->start_time) {
 +                av_log(ctx, AV_LOG_ERROR,
 +                       "%s: seek value overflow with start_time:%"PRId64" seek_point:%"PRId64"\n",
 +                       movie->file_name, movie->format_ctx->start_time, movie->seek_point);
 +                return AVERROR(EINVAL);
 +            }
 +            timestamp += movie->format_ctx->start_time;
 +        }
 +        if ((ret = av_seek_frame(movie->format_ctx, -1, timestamp, AVSEEK_FLAG_BACKWARD)) < 0) {
 +            av_log(ctx, AV_LOG_ERROR, "%s: could not seek to position %"PRId64"\n",
 +                   movie->file_name, timestamp);
 +            return ret;
 +        }
 +    }
 +
 +    /* select the media stream */
 +    if ((ret = av_find_best_stream(movie->format_ctx, type,
 +                                   movie->stream_index, -1, NULL, 0)) < 0) {
 +        av_log(ctx, AV_LOG_ERROR, "No %s stream with index '%d' found\n",
 +               av_get_media_type_string(type), movie->stream_index);
 +        return ret;
 +    }
 +    movie->stream_index = ret;
 +    movie->codec_ctx = movie->format_ctx->streams[movie->stream_index]->codec;
 +
 +    /*
 +     * So now we've got a pointer to the so-called codec context for our video
 +     * stream, but we still have to find the actual codec and open it.
 +     */
 +    codec = avcodec_find_decoder(movie->codec_ctx->codec_id);
 +    if (!codec) {
 +        av_log(ctx, AV_LOG_ERROR, "Failed to find any codec\n");
 +        return AVERROR(EINVAL);
 +    }
 +
 +    if ((ret = avcodec_open2(movie->codec_ctx, codec, NULL)) < 0) {
 +        av_log(ctx, AV_LOG_ERROR, "Failed to open codec\n");
 +        return ret;
 +    }
 +
 +    av_log(ctx, AV_LOG_INFO, "seek_point:%"PRIi64" format_name:%s file_name:%s stream_index:%d\n",
 +           movie->seek_point, movie->format_name, movie->file_name,
 +           movie->stream_index);
 +
 +    if (!(movie->frame = avcodec_alloc_frame()) ) {
 +        av_log(ctx, AV_LOG_ERROR, "Failed to alloc frame\n");
 +        return AVERROR(ENOMEM);
 +    }
 +
 +    return 0;
 +}
 +
 +static av_cold void movie_common_uninit(AVFilterContext *ctx)
 +{
 +    MovieContext *movie = ctx->priv;
 +
 +    av_free(movie->file_name);
 +    av_free(movie->format_name);
 +    if (movie->codec_ctx)
 +        avcodec_close(movie->codec_ctx);
 +    if (movie->format_ctx)
 +        avformat_close_input(&movie->format_ctx);
 +
 +    avfilter_unref_buffer(movie->picref);
 +    av_freep(&movie->frame);
 +
 +    avfilter_unref_buffer(movie->samplesref);
 +}
 +
 +#if CONFIG_MOVIE_FILTER
 +
 +static av_cold int movie_init(AVFilterContext *ctx, const char *args, void *opaque)
 +{
 +    MovieContext *movie = ctx->priv;
 +    int ret;
 +
 +    if ((ret = movie_common_init(ctx, args, opaque, AVMEDIA_TYPE_VIDEO)) < 0)
 +        return ret;
 +
 +    movie->w = movie->codec_ctx->width;
 +    movie->h = movie->codec_ctx->height;
 +
 +    return 0;
 +}
 +
 +static int movie_query_formats(AVFilterContext *ctx)
 +{
 +    MovieContext *movie = ctx->priv;
 +    enum PixelFormat pix_fmts[] = { movie->codec_ctx->pix_fmt, PIX_FMT_NONE };
 +
 +    avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts));
 +    return 0;
 +}
 +
 +static int movie_config_output_props(AVFilterLink *outlink)
 +{
 +    MovieContext *movie = outlink->src->priv;
 +
 +    outlink->w = movie->w;
 +    outlink->h = movie->h;
 +    outlink->time_base = movie->format_ctx->streams[movie->stream_index]->time_base;
 +
 +    return 0;
 +}
 +
 +static int movie_get_frame(AVFilterLink *outlink)
 +{
 +    MovieContext *movie = outlink->src->priv;
 +    AVPacket pkt;
 +    int ret, frame_decoded;
 +    AVStream *st = movie->format_ctx->streams[movie->stream_index];
 +
 +    if (movie->is_done == 1)
 +        return 0;
 +
 +    while (1) {
 +        ret = av_read_frame(movie->format_ctx, &pkt);
 +        if (ret == AVERROR_EOF) {
 +            int64_t timestamp;
 +            if (movie->loop_count != 1) {
 +                timestamp = movie->seek_point;
 +                if (movie->format_ctx->start_time != AV_NOPTS_VALUE)
 +                    timestamp += movie->format_ctx->start_time;
 +                if (av_seek_frame(movie->format_ctx, -1, timestamp, AVSEEK_FLAG_BACKWARD) < 0) {
 +                    movie->is_done = 1;
 +                    break;
 +                } else if (movie->loop_count>1)
 +                    movie->loop_count--;
 +                continue;
 +            } else {
 +                movie->is_done = 1;
 +                break;
 +            }
 +        } else if (ret < 0)
 +            break;
 +
 +        // Is this a packet from the video stream?
 +        if (pkt.stream_index == movie->stream_index) {
 +            avcodec_decode_video2(movie->codec_ctx, movie->frame, &frame_decoded, &pkt);
 +
 +            if (frame_decoded) {
 +                /* FIXME: avoid the memcpy */
 +                movie->picref = avfilter_get_video_buffer(outlink, AV_PERM_WRITE | AV_PERM_PRESERVE |
 +                                                          AV_PERM_REUSE2, outlink->w, outlink->h);
 +                av_image_copy(movie->picref->data, movie->picref->linesize,
 +                              (void*)movie->frame->data,  movie->frame->linesize,
 +                              movie->picref->format, outlink->w, outlink->h);
 +                avfilter_copy_frame_props(movie->picref, movie->frame);
 +
 +                /* FIXME: use a PTS correction mechanism as that in
 +                 * ffplay.c when some API will be available for that */
 +                /* use pkt_dts if pkt_pts is not available */
 +                movie->picref->pts = movie->frame->pkt_pts == AV_NOPTS_VALUE ?
 +                    movie->frame->pkt_dts : movie->frame->pkt_pts;
 +
 +                if (!movie->frame->sample_aspect_ratio.num)
 +                    movie->picref->video->sample_aspect_ratio = st->sample_aspect_ratio;
 +                av_dlog(outlink->src,
 +                        "movie_get_frame(): file:'%s' pts:%"PRId64" time:%lf pos:%"PRId64" aspect:%d/%d\n",
 +                        movie->file_name, movie->picref->pts,
 +                        (double)movie->picref->pts * av_q2d(st->time_base),
 +                        movie->picref->pos,
 +                        movie->picref->video->sample_aspect_ratio.num,
 +                        movie->picref->video->sample_aspect_ratio.den);
 +                // We got it. Free the packet since we are returning
 +                av_free_packet(&pkt);
 +
 +                return 0;
 +            }
 +        }
 +        // Free the packet that was allocated by av_read_frame
 +        av_free_packet(&pkt);
 +    }
 +
 +    return ret;
 +}
 +
 +static int movie_request_frame(AVFilterLink *outlink)
 +{
 +    AVFilterBufferRef *outpicref;
 +    MovieContext *movie = outlink->src->priv;
 +    int ret;
 +
 +    if (movie->is_done)
 +        return AVERROR_EOF;
 +    if ((ret = movie_get_frame(outlink)) < 0)
 +        return ret;
 +
 +    outpicref = avfilter_ref_buffer(movie->picref, ~0);
 +    avfilter_start_frame(outlink, outpicref);
 +    avfilter_draw_slice(outlink, 0, outlink->h, 1);
 +    avfilter_end_frame(outlink);
 +    avfilter_unref_buffer(movie->picref);
 +    movie->picref = NULL;
 +
 +    return 0;
 +}
 +
 +AVFilter avfilter_vsrc_movie = {
 +    .name          = "movie",
 +    .description   = NULL_IF_CONFIG_SMALL("Read from a movie source."),
 +    .priv_size     = sizeof(MovieContext),
 +    .init          = movie_init,
 +    .uninit        = movie_common_uninit,
 +    .query_formats = movie_query_formats,
 +
 +    .inputs    = (const AVFilterPad[]) {{ .name = NULL }},
 +    .outputs   = (const AVFilterPad[]) {{ .name      = "default",
 +                                    .type            = AVMEDIA_TYPE_VIDEO,
 +                                    .request_frame   = movie_request_frame,
 +                                    .config_props    = movie_config_output_props, },
 +                                  { .name = NULL}},
 +};
 +
 +#endif  /* CONFIG_MOVIE_FILTER */
 +
 +#if CONFIG_AMOVIE_FILTER
 +
 +static av_cold int amovie_init(AVFilterContext *ctx, const char *args, void *opaque)
 +{
 +    MovieContext *movie = ctx->priv;
 +    int ret;
 +
 +    if ((ret = movie_common_init(ctx, args, opaque, AVMEDIA_TYPE_AUDIO)) < 0)
 +        return ret;
 +
 +    movie->bps = av_get_bytes_per_sample(movie->codec_ctx->sample_fmt);
 +    return 0;
 +}
 +
 +static int amovie_query_formats(AVFilterContext *ctx)
 +{
 +    MovieContext *movie = ctx->priv;
 +    AVCodecContext *c = movie->codec_ctx;
 +
 +    enum AVSampleFormat sample_fmts[] = { c->sample_fmt, -1 };
 +    int packing_fmts[] = { AVFILTER_PACKED, -1 };
 +    int64_t chlayouts[] = { c->channel_layout ? c->channel_layout :
 +                            av_get_default_channel_layout(c->channels), -1 };
 +
 +    avfilter_set_common_sample_formats (ctx, avfilter_make_format_list(sample_fmts));
 +    avfilter_set_common_packing_formats(ctx, avfilter_make_format_list(packing_fmts));
 +    avfilter_set_common_channel_layouts(ctx, avfilter_make_format64_list(chlayouts));
 +
 +    return 0;
 +}
 +
 +static int amovie_config_output_props(AVFilterLink *outlink)
 +{
 +    MovieContext *movie = outlink->src->priv;
 +    AVCodecContext *c = movie->codec_ctx;
 +
 +    outlink->sample_rate = c->sample_rate;
 +    outlink->time_base = movie->format_ctx->streams[movie->stream_index]->time_base;
 +
 +    return 0;
 +}
 +
 +static int amovie_get_samples(AVFilterLink *outlink)
 +{
 +    MovieContext *movie = outlink->src->priv;
 +    AVPacket pkt;
 +    int ret, got_frame = 0;
 +
 +    if (!movie->pkt.size && movie->is_done == 1)
 +        return AVERROR_EOF;
 +
 +    /* check for another frame, in case the previous one was completely consumed */
 +    if (!movie->pkt.size) {
 +        while ((ret = av_read_frame(movie->format_ctx, &pkt)) >= 0) {
 +            // Is this a packet from the selected stream?
 +            if (pkt.stream_index != movie->stream_index) {
 +                av_free_packet(&pkt);
 +                continue;
 +            } else {
 +                movie->pkt0 = movie->pkt = pkt;
 +                break;
 +            }
 +        }
 +
 +        if (ret == AVERROR_EOF) {
 +            movie->is_done = 1;
 +            return ret;
 +        }
 +    }
 +
 +    /* decode and update the movie pkt */
 +    avcodec_get_frame_defaults(movie->frame);
 +    ret = avcodec_decode_audio4(movie->codec_ctx, movie->frame, &got_frame, &movie->pkt);
 +    if (ret < 0) {
 +        movie->pkt.size = 0;
 +        return ret;
 +    }
 +    movie->pkt.data += ret;
 +    movie->pkt.size -= ret;
 +
 +    /* wrap the decoded data in a samplesref */
 +    if (got_frame) {
 +        int nb_samples = movie->frame->nb_samples;
 +        int data_size =
 +            av_samples_get_buffer_size(NULL, movie->codec_ctx->channels,
 +                                       nb_samples, movie->codec_ctx->sample_fmt, 1);
 +        if (data_size < 0)
 +            return data_size;
 +        movie->samplesref =
-     avfilter_filter_samples(outlink, avfilter_ref_buffer(movie->samplesref, ~0));
++            ff_get_audio_buffer(outlink, AV_PERM_WRITE, nb_samples);
 +        memcpy(movie->samplesref->data[0], movie->frame->data[0], data_size);
 +        movie->samplesref->pts = movie->pkt.pts;
 +        movie->samplesref->pos = movie->pkt.pos;
 +        movie->samplesref->audio->sample_rate = movie->codec_ctx->sample_rate;
 +    }
 +
 +    // We got it. Free the packet since we are returning
 +    if (movie->pkt.size <= 0)
 +        av_free_packet(&movie->pkt0);
 +
 +    return 0;
 +}
 +
 +static int amovie_request_frame(AVFilterLink *outlink)
 +{
 +    MovieContext *movie = outlink->src->priv;
 +    int ret;
 +
 +    if (movie->is_done)
 +        return AVERROR_EOF;
 +    do {
 +        if ((ret = amovie_get_samples(outlink)) < 0)
 +            return ret;
 +    } while (!movie->samplesref);
 +
++    ff_filter_samples(outlink, avfilter_ref_buffer(movie->samplesref, ~0));
 +    avfilter_unref_buffer(movie->samplesref);
 +    movie->samplesref = NULL;
 +
 +    return 0;
 +}
 +
 +AVFilter avfilter_asrc_amovie = {
 +    .name          = "amovie",
 +    .description   = NULL_IF_CONFIG_SMALL("Read audio from a movie source."),
 +    .priv_size     = sizeof(MovieContext),
 +    .init          = amovie_init,
 +    .uninit        = movie_common_uninit,
 +    .query_formats = amovie_query_formats,
 +
 +    .inputs    = (const AVFilterPad[]) {{ .name = NULL }},
 +    .outputs   = (const AVFilterPad[]) {{ .name      = "default",
 +                                    .type            = AVMEDIA_TYPE_AUDIO,
 +                                    .request_frame   = amovie_request_frame,
 +                                    .config_props    = amovie_config_output_props, },
 +                                  { .name = NULL}},
 +};
 +
 +#endif /* CONFIG_AMOVIE_FILTER */
Simple merge
Simple merge
Simple merge
Simple merge