Merge commit '4436f25a1682ada3f7226cb6fadf429946933161'
authorMichael Niedermayer <michaelni@gmx.at>
Thu, 11 Oct 2012 13:41:56 +0000 (15:41 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Thu, 11 Oct 2012 13:46:48 +0000 (15:46 +0200)
* commit '4436f25a1682ada3f7226cb6fadf429946933161':
  build: remove references to unused EXTRAOBJS variable
  lavfi: convert input/ouput list compound literals to named objects
  fate: add h263 obmc vsynth tests
  avconv: remove bogus warning when using avconv -h without parameter
  averror: explicitly define AVERROR_* values
  flashsv: propagate inflateReset() errors
  indeo4/5: remove constant parameter num_bands from wavelet recomposition
  mxfdec: return error if no segments are available in mxf_get_sorted_table_segments
  Double motion vector range for HPEL interlaced picture in proper place

Conflicts:
libavcodec/v210dec.h
libavfilter/af_aformat.c
libavfilter/af_amix.c
libavfilter/af_asyncts.c
libavfilter/af_channelmap.c
libavfilter/af_join.c
libavfilter/asrc_anullsrc.c
libavfilter/buffersrc.c
libavfilter/f_setpts.c
libavfilter/f_settb.c
libavfilter/fifo.c
libavfilter/src_movie.c
libavfilter/vf_ass.c
libavfilter/vf_blackframe.c
libavfilter/vf_boxblur.c
libavfilter/vf_delogo.c
libavfilter/vf_drawbox.c
libavfilter/vf_drawtext.c
libavfilter/vf_fade.c
libavfilter/vf_fieldorder.c
libavfilter/vf_fps.c
libavfilter/vf_hflip.c
libavfilter/vf_overlay.c
libavfilter/vf_pad.c
libavfilter/vf_select.c
libavfilter/vf_transpose.c
libavfilter/vf_yadif.c
libavfilter/vsrc_testsrc.c
libavformat/mxfdec.c
libavutil/error.h

Merged-by: Michael Niedermayer <michaelni@gmx.at>
59 files changed:
1  2 
ffmpeg_opt.c
libavcodec/flashsv.c
libavcodec/ivi_common.c
libavcodec/ivi_dsp.c
libavcodec/ivi_dsp.h
libavcodec/vc1.c
libavcodec/vc1dec.c
libavfilter/af_aformat.c
libavfilter/af_amix.c
libavfilter/af_anull.c
libavfilter/af_asyncts.c
libavfilter/af_channelmap.c
libavfilter/af_channelsplit.c
libavfilter/af_join.c
libavfilter/asink_anullsink.c
libavfilter/asrc_anullsrc.c
libavfilter/buffersink.c
libavfilter/buffersrc.c
libavfilter/f_setpts.c
libavfilter/f_settb.c
libavfilter/fifo.c
libavfilter/split.c
libavfilter/vf_aspect.c
libavfilter/vf_blackframe.c
libavfilter/vf_boxblur.c
libavfilter/vf_copy.c
libavfilter/vf_crop.c
libavfilter/vf_cropdetect.c
libavfilter/vf_delogo.c
libavfilter/vf_drawbox.c
libavfilter/vf_drawtext.c
libavfilter/vf_fade.c
libavfilter/vf_fieldorder.c
libavfilter/vf_format.c
libavfilter/vf_fps.c
libavfilter/vf_frei0r.c
libavfilter/vf_gradfun.c
libavfilter/vf_hflip.c
libavfilter/vf_hqdn3d.c
libavfilter/vf_libopencv.c
libavfilter/vf_null.c
libavfilter/vf_overlay.c
libavfilter/vf_pad.c
libavfilter/vf_pixdesctest.c
libavfilter/vf_scale.c
libavfilter/vf_select.c
libavfilter/vf_showinfo.c
libavfilter/vf_slicify.c
libavfilter/vf_transpose.c
libavfilter/vf_unsharp.c
libavfilter/vf_vflip.c
libavfilter/vf_yadif.c
libavfilter/vsink_nullsink.c
libavfilter/vsrc_testsrc.c
libavformat/mxfdec.c
library.mak
tests/fate/vcodec.mak
tests/ref/fate/vsynth1-h263-obmc
tests/ref/fate/vsynth2-h263-obmc

diff --cc ffmpeg_opt.c
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -133,11 -155,6 +149,7 @@@ AVFilter avfilter_af_aformat = 
      .query_formats = query_formats,
      .priv_size     = sizeof(AFormatContext),
  
-     .inputs        = (const AVFilterPad[]) {{ .name            = "default",
-                                               .type            = AVMEDIA_TYPE_AUDIO, },
-                                             { .name = NULL}},
-     .outputs       = (const AVFilterPad[]) {{ .name            = "default",
-                                               .type            = AVMEDIA_TYPE_AUDIO},
-                                             { .name = NULL}},
-     .priv_class = &aformat_class,
+     .inputs        = avfilter_af_aformat_inputs,
+     .outputs       = avfilter_af_aformat_outputs,
++    .priv_class    = &aformat_class,
  };
@@@ -552,10 -569,5 +562,6 @@@ AVFilter avfilter_af_amix = 
      .query_formats  = query_formats,
  
      .inputs    = NULL,
-     .outputs   = (const AVFilterPad[]) {{ .name          = "default",
-                                           .type          = AVMEDIA_TYPE_AUDIO,
-                                           .config_props  = config_output,
-                                           .request_frame = request_frame },
-                                         { .name = NULL}},
+     .outputs   = avfilter_af_amix_outputs,
 +    .priv_class = &amix_class,
  };
Simple merge
@@@ -242,14 -267,6 +261,7 @@@ AVFilter avfilter_af_asyncts = 
  
      .priv_size   = sizeof(ASyncContext),
  
-     .inputs      = (const AVFilterPad[]) {{ .name           = "default",
-                                             .type           = AVMEDIA_TYPE_AUDIO,
-                                             .filter_samples = filter_samples },
-                                           { NULL }},
-     .outputs     = (const AVFilterPad[]) {{ .name           = "default",
-                                             .type           = AVMEDIA_TYPE_AUDIO,
-                                             .config_props   = config_props,
-                                             .request_frame  = request_frame },
-                                           { NULL }},
+     .inputs      = avfilter_af_asyncts_inputs,
+     .outputs     = avfilter_af_asyncts_outputs,
 +    .priv_class = &asyncts_class,
  };
@@@ -385,6 -386,24 +385,25 @@@ static int channelmap_config_input(AVFi
      return err;
  }
  
+ static const AVFilterPad avfilter_af_channelmap_inputs[] = {
+     {
+         .name           = "default",
+         .type           = AVMEDIA_TYPE_AUDIO,
++        .min_perms      = AV_PERM_READ | AV_PERM_WRITE,
+         .filter_samples = channelmap_filter_samples,
+         .config_props   = channelmap_config_input
+     },
+     { NULL }
+ };
+ static const AVFilterPad avfilter_af_channelmap_outputs[] = {
+     {
+         .name = "default",
+         .type = AVMEDIA_TYPE_AUDIO
+     },
+     { NULL }
+ };
  AVFilter avfilter_af_channelmap = {
      .name          = "channelmap",
      .description   = NULL_IF_CONFIG_SMALL("Remap audio channels."),
      .query_formats = channelmap_query_formats,
      .priv_size     = sizeof(ChannelMapContext),
  
-     .inputs        = (const AVFilterPad[]) {{ .name            = "default",
-                                               .type            = AVMEDIA_TYPE_AUDIO,
-                                               .min_perms       = AV_PERM_READ | AV_PERM_WRITE,
-                                               .filter_samples  = channelmap_filter_samples,
-                                               .config_props    = channelmap_config_input },
-                                             { .name = NULL }},
-     .outputs       = (const AVFilterPad[]) {{ .name            = "default",
-                                               .type            = AVMEDIA_TYPE_AUDIO },
-                                             { .name = NULL }},
-     .priv_class = &channelmap_class,
+     .inputs        = avfilter_af_channelmap_inputs,
+     .outputs       = avfilter_af_channelmap_outputs,
++    .priv_class    = &channelmap_class,
  };
@@@ -138,10 -153,6 +147,7 @@@ AVFilter avfilter_af_channelsplit = 
      .init           = init,
      .query_formats  = query_formats,
  
-     .inputs  = (const AVFilterPad[]){{ .name           = "default",
-                                        .type           = AVMEDIA_TYPE_AUDIO,
-                                        .filter_samples = filter_samples, },
-                                      { NULL }},
+     .inputs  = avfilter_af_channelsplit_inputs,
      .outputs = NULL,
 +    .priv_class = &channelsplit_class,
  };
@@@ -495,10 -506,5 +505,6 @@@ AVFilter avfilter_af_join = 
      .query_formats  = join_query_formats,
  
      .inputs  = NULL,
-     .outputs = (const AVFilterPad[]){{ .name          = "default",
-                                        .type          = AVMEDIA_TYPE_AUDIO,
-                                        .config_props  = join_config_output,
-                                        .request_frame = join_request_frame, },
-                                      { NULL }},
+     .outputs = avfilter_af_join_outputs,
 +    .priv_class = &join_class,
  };
Simple merge
@@@ -100,38 -79,29 +100,44 @@@ 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 =
 +        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;
 +
 +    ff_filter_samples(outlink, avfilter_ref_buffer(samplesref, ~0));
 +    avfilter_unref_buffer(samplesref);
 +
 +    null->pts += null->nb_samples;
 +    return 0;
  }
  
+ static const AVFilterPad avfilter_asrc_anullsrc_outputs[] = {
+     {
+         .name          = "default",
+         .type          = AVMEDIA_TYPE_AUDIO,
+         .config_props  = config_props,
+         .request_frame = request_frame,
+     },
+     { NULL }
+ };
  AVFilter avfilter_asrc_anullsrc = {
      .name        = "anullsrc",
 -    .description = NULL_IF_CONFIG_SMALL("Null audio source, never return audio frames."),
 +    .description = NULL_IF_CONFIG_SMALL("Null audio source, return empty audio frames."),
  
      .init        = init,
      .priv_size   = sizeof(ANullContext),
  
      .inputs      = NULL,
  
-     .outputs     = (const AVFilterPad[]) {{ .name = "default",
-                                             .type = AVMEDIA_TYPE_AUDIO,
-                                             .config_props = config_props,
-                                             .request_frame = request_frame, },
-                                           { .name = NULL}},
+     .outputs     = avfilter_asrc_anullsrc_outputs,
 +    .priv_class = &anullsrc_class,
  };
@@@ -140,12 -140,19 +140,23 @@@ int ff_buffersink_read_samples_compat(A
      return ret;
  }
  
+ static const AVFilterPad avfilter_vsink_buffer_inputs[] = {
+     {
+         .name        = "default",
+         .type        = AVMEDIA_TYPE_VIDEO,
+         .start_frame = start_frame,
+         .min_perms   = AV_PERM_READ,
+         .needs_fifo  = 1
+     },
+     { NULL }
+ };
  AVFilter avfilter_vsink_buffer = {
 +#if AV_HAVE_INCOMPATIBLE_FORK_ABI
      .name      = "buffersink",
 +#else
 +    .name      = "buffersink_old",
 +#endif
      .description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them available to the end of the filter graph."),
      .priv_size = sizeof(BufferSinkContext),
      .uninit    = uninit,
      .outputs   = NULL,
  };
  
+ static const AVFilterPad avfilter_asink_abuffer_inputs[] = {
+     {
+         .name           = "default",
+         .type           = AVMEDIA_TYPE_AUDIO,
+         .filter_samples = start_frame,
+         .min_perms      = AV_PERM_READ,
+         .needs_fifo     = 1
+     },
+     { NULL }
+ };
  AVFilter avfilter_asink_abuffer = {
 +#if AV_HAVE_INCOMPATIBLE_FORK_ABI
      .name      = "abuffersink",
 +#else
 +    .name      = "abuffersink_old",
 +#endif
      .description = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them available to the end of the filter graph."),
      .priv_size = sizeof(BufferSinkContext),
      .uninit    = uninit,
@@@ -410,15 -376,20 +421,21 @@@ AVFilter avfilter_vsrc_buffer = 
      .uninit    = uninit,
  
      .inputs    = NULL,
-     .outputs   = (const AVFilterPad[]) {{ .name            = "default",
-                                           .type            = AVMEDIA_TYPE_VIDEO,
-                                           .request_frame   = request_frame,
-                                           .poll_frame      = poll_frame,
-                                           .config_props    = config_props, },
-                                         { .name = NULL}},
+     .outputs   = avfilter_vsrc_buffer_outputs,
 +    .priv_class = &buffer_class,
  };
  
+ static const AVFilterPad avfilter_asrc_abuffer_outputs[] = {
+     {
+         .name          = "default",
+         .type          = AVMEDIA_TYPE_AUDIO,
+         .request_frame = request_frame,
+         .poll_frame    = poll_frame,
+         .config_props  = config_props,
+     },
+     { NULL }
+ };
  AVFilter avfilter_asrc_abuffer = {
      .name          = "abuffer",
      .description   = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them accessible to the filterchain."),
      .uninit    = uninit,
  
      .inputs    = NULL,
-     .outputs   = (const AVFilterPad[]) {{ .name            = "default",
-                                           .type            = AVMEDIA_TYPE_AUDIO,
-                                           .request_frame   = request_frame,
-                                           .poll_frame      = poll_frame,
-                                           .config_props    = config_props, },
-                                         { .name = NULL}},
+     .outputs   = avfilter_asrc_abuffer_outputs,
 +    .priv_class = &abuffer_class,
  };
index 023dc1e,0000000..5a58ce3
mode 100644,000000..100644
--- /dev/null
@@@ -1,237 -1,0 +1,249 @@@
-     .inputs    = (const AVFilterPad[]) {{ .name             = "default",
-                                           .type             = AVMEDIA_TYPE_VIDEO,
-                                           .get_video_buffer = ff_null_get_video_buffer,
-                                           .config_props     = config_input,
-                                           .start_frame      = filter_frame, },
-                                         { .name = NULL }},
-     .outputs   = (const AVFilterPad[]) {{ .name             = "default",
-                                           .type             = AVMEDIA_TYPE_VIDEO, },
-                                         { .name = NULL}},
 +/*
 + * 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
 + * video presentation timestamp (PTS) modification filter
 + */
 +
 +/* #define DEBUG */
 +
 +#include "libavutil/eval.h"
 +#include "libavutil/internal.h"
 +#include "libavutil/mathematics.h"
 +#include "avfilter.h"
 +#include "internal.h"
 +#include "audio.h"
 +#include "video.h"
 +
 +static const char *const var_names[] = {
 +    "FRAME_RATE",  ///< defined only for constant frame-rate video
 +    "INTERLACED",  ///< tell if the current frame is interlaced
 +    "N",           ///< frame number (starting at zero)
 +    "NB_CONSUMED_SAMPLES", ///< number of samples consumed by the filter (only audio)
 +    "NB_SAMPLES",  ///< number of samples in the current frame (only audio)
 +    "POS",         ///< original position in the file of the frame
 +    "PREV_INPTS",  ///< previous  input PTS
 +    "PREV_INT",    ///< previous  input time in seconds
 +    "PREV_OUTPTS", ///< previous output PTS
 +    "PREV_OUTT",   ///< previous output time in seconds
 +    "PTS",         ///< original pts in the file of the frame
 +    "SAMPLE_RATE", ///< sample rate (only audio)
 +    "STARTPTS",    ///< PTS at start of movie
 +    "STARTT",      ///< time at start of movie
 +    "T",           ///< original time in the file of the frame
 +    "TB",          ///< timebase
 +    NULL
 +};
 +
 +enum var_name {
 +    VAR_FRAME_RATE,
 +    VAR_INTERLACED,
 +    VAR_N,
 +    VAR_NB_CONSUMED_SAMPLES,
 +    VAR_NB_SAMPLES,
 +    VAR_POS,
 +    VAR_PREV_INPTS,
 +    VAR_PREV_INT,
 +    VAR_PREV_OUTPTS,
 +    VAR_PREV_OUTT,
 +    VAR_PTS,
 +    VAR_SAMPLE_RATE,
 +    VAR_STARTPTS,
 +    VAR_STARTT,
 +    VAR_T,
 +    VAR_TB,
 +    VAR_VARS_NB
 +};
 +
 +typedef struct {
 +    AVExpr *expr;
 +    double var_values[VAR_VARS_NB];
 +    enum AVMediaType type;
 +} SetPTSContext;
 +
 +static av_cold int init(AVFilterContext *ctx, const char *args)
 +{
 +    SetPTSContext *setpts = ctx->priv;
 +    int ret;
 +
 +    if ((ret = av_expr_parse(&setpts->expr, args ? args : "PTS",
 +                             var_names, NULL, NULL, NULL, NULL, 0, ctx)) < 0) {
 +        av_log(ctx, AV_LOG_ERROR, "Error while parsing expression '%s'\n", args);
 +        return ret;
 +    }
 +
 +    setpts->var_values[VAR_N          ] = 0.0;
 +    setpts->var_values[VAR_PREV_INPTS ] = setpts->var_values[VAR_PREV_INT ] = NAN;
 +    setpts->var_values[VAR_PREV_OUTPTS] = setpts->var_values[VAR_PREV_OUTT] = NAN;
 +    setpts->var_values[VAR_STARTPTS   ] = setpts->var_values[VAR_STARTT   ] = NAN;
 +    return 0;
 +}
 +
 +static int config_input(AVFilterLink *inlink)
 +{
 +    AVFilterContext *ctx = inlink->dst;
 +    SetPTSContext *setpts = ctx->priv;
 +
 +    setpts->type = inlink->type;
 +    setpts->var_values[VAR_TB] = av_q2d(inlink->time_base);
 +
 +    setpts->var_values[VAR_SAMPLE_RATE] =
 +        setpts->type == AVMEDIA_TYPE_AUDIO ? inlink->sample_rate : NAN;
 +
 +    setpts->var_values[VAR_FRAME_RATE] = inlink->frame_rate.num && inlink->frame_rate.den ?
 +        av_q2d(inlink->frame_rate) : NAN;
 +
 +    av_log(inlink->src, AV_LOG_VERBOSE, "TB:%f FRAME_RATE:%f SAMPLE_RATE:%f\n",
 +           setpts->var_values[VAR_TB],
 +           setpts->var_values[VAR_FRAME_RATE],
 +           setpts->var_values[VAR_SAMPLE_RATE]);
 +    return 0;
 +}
 +
 +#define D2TS(d)  (isnan(d) ? AV_NOPTS_VALUE : (int64_t)(d))
 +#define TS2D(ts) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts))
 +#define TS2T(ts, tb) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts)*av_q2d(tb))
 +
 +static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
 +{
 +    SetPTSContext *setpts = inlink->dst->priv;
 +    double d;
 +    AVFilterBufferRef *outpicref = avfilter_ref_buffer(inpicref, ~0);
 +
 +    if (!outpicref)
 +        return AVERROR(ENOMEM);
 +
 +    if (isnan(setpts->var_values[VAR_STARTPTS])) {
 +        setpts->var_values[VAR_STARTPTS] = TS2D(inpicref->pts);
 +        setpts->var_values[VAR_STARTT  ] = TS2T(inpicref->pts, inlink->time_base);
 +    }
 +    setpts->var_values[VAR_PTS       ] = TS2D(inpicref->pts);
 +    setpts->var_values[VAR_T         ] = TS2T(inpicref->pts, inlink->time_base);
 +    setpts->var_values[VAR_POS       ] = inpicref->pos == -1 ? NAN : inpicref->pos;
 +
 +    switch (inlink->type) {
 +    case AVMEDIA_TYPE_VIDEO:
 +        setpts->var_values[VAR_INTERLACED] = inpicref->video->interlaced;
 +        break;
 +
 +    case AVMEDIA_TYPE_AUDIO:
 +        setpts->var_values[VAR_NB_SAMPLES] = inpicref->audio->nb_samples;
 +        break;
 +    }
 +
 +    d = av_expr_eval(setpts->expr, setpts->var_values, NULL);
 +    outpicref->pts = D2TS(d);
 +
 +    setpts->var_values[VAR_PREV_INPTS ] = TS2D(inpicref ->pts);
 +    setpts->var_values[VAR_PREV_INT   ] = TS2T(inpicref ->pts, inlink->time_base);
 +    setpts->var_values[VAR_PREV_OUTPTS] = TS2D(outpicref->pts);
 +    setpts->var_values[VAR_PREV_OUTT]   = TS2T(outpicref->pts, inlink->time_base);
 +
 +    av_dlog(inlink->dst,
 +            "n:%"PRId64" interlaced:%d nb_samples:%d nb_consumed_samples:%d "
 +            "pos:%"PRId64" pts:%"PRId64" t:%f -> pts:%"PRId64" t:%f\n",
 +            (int64_t)setpts->var_values[VAR_N],
 +            (int)setpts->var_values[VAR_INTERLACED],
 +            (int)setpts->var_values[VAR_NB_SAMPLES],
 +            (int)setpts->var_values[VAR_NB_CONSUMED_SAMPLES],
 +            (int64_t)setpts->var_values[VAR_POS],
 +            (int64_t)setpts->var_values[VAR_PREV_INPTS],
 +            setpts->var_values[VAR_PREV_INT],
 +            (int64_t)setpts->var_values[VAR_PREV_OUTPTS],
 +            setpts->var_values[VAR_PREV_OUTT]);
 +
 +    setpts->var_values[VAR_N] += 1.0;
 +    if (setpts->type == AVMEDIA_TYPE_AUDIO) {
 +        setpts->var_values[VAR_NB_CONSUMED_SAMPLES] += inpicref->audio->nb_samples;
 +        return ff_filter_samples(inlink->dst->outputs[0], outpicref);
 +    } else
 +        return ff_start_frame   (inlink->dst->outputs[0], outpicref);
 +}
 +
 +static av_cold void uninit(AVFilterContext *ctx)
 +{
 +    SetPTSContext *setpts = ctx->priv;
 +    av_expr_free(setpts->expr);
 +    setpts->expr = NULL;
 +}
 +
 +#if CONFIG_ASETPTS_FILTER
 +AVFilter avfilter_af_asetpts = {
 +    .name      = "asetpts",
 +    .description = NULL_IF_CONFIG_SMALL("Set PTS for the output audio frame."),
 +    .init      = init,
 +    .uninit    = uninit,
 +
 +    .priv_size = sizeof(SetPTSContext),
 +
 +    .inputs = (const AVFilterPad[]) {
 +        {
 +            .name             = "default",
 +            .type             = AVMEDIA_TYPE_AUDIO,
 +            .get_audio_buffer = ff_null_get_audio_buffer,
 +            .config_props     = config_input,
 +            .filter_samples   = filter_frame,
 +        },
 +        { .name = NULL }
 +    },
 +    .outputs = (const AVFilterPad[]) {
 +        {
 +            .name             = "default",
 +            .type             = AVMEDIA_TYPE_AUDIO,
 +        },
 +        { .name = NULL }
 +    },
 +};
 +#endif /* CONFIG_ASETPTS_FILTER */
 +
 +#if CONFIG_SETPTS_FILTER
++static const AVFilterPad avfilter_vf_setpts_inputs[] = {
++    {
++        .name             = "default",
++        .type             = AVMEDIA_TYPE_VIDEO,
++        .get_video_buffer = ff_null_get_video_buffer,
++        .config_props     = config_input,
++        .start_frame      = filter_frame,
++    },
++    { NULL }
++};
++
++static const AVFilterPad avfilter_vf_setpts_outputs[] = {
++    {
++        .name = "default",
++        .type = AVMEDIA_TYPE_VIDEO,
++    },
++    { NULL }
++};
++
 +AVFilter avfilter_vf_setpts = {
 +    .name      = "setpts",
 +    .description = NULL_IF_CONFIG_SMALL("Set PTS for the output video frame."),
 +    .init      = init,
 +    .uninit    = uninit,
 +
 +    .priv_size = sizeof(SetPTSContext),
 +
++    .inputs    = avfilter_vf_setpts_inputs,
++    .outputs   = avfilter_vf_setpts_outputs,
 +};
 +#endif /* CONFIG_SETPTS_FILTER */
@@@ -120,67 -125,34 +120,75 @@@ static int start_frame(AVFilterLink *in
      return ff_start_frame(outlink, picref);
  }
  
 +static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *samplesref)
 +{
 +    AVFilterContext *ctx = inlink->dst;
 +    AVFilterLink *outlink = ctx->outputs[0];
 +
 +    if (av_cmp_q(inlink->time_base, outlink->time_base)) {
 +        int64_t orig_pts = samplesref->pts;
 +        samplesref->pts = av_rescale_q(samplesref->pts, inlink->time_base, outlink->time_base);
 +        av_log(ctx, AV_LOG_DEBUG, "tb:%d/%d pts:%"PRId64" -> tb:%d/%d pts:%"PRId64"\n",
 +               inlink ->time_base.num, inlink ->time_base.den, orig_pts,
 +               outlink->time_base.num, outlink->time_base.den, samplesref->pts);
 +    }
 +
 +    return ff_filter_samples(outlink, samplesref);
 +}
 +
 +#if CONFIG_SETTB_FILTER
+ static const AVFilterPad avfilter_vf_settb_inputs[] = {
+     {
+         .name             = "default",
+         .type             = AVMEDIA_TYPE_VIDEO,
+         .get_video_buffer = ff_null_get_video_buffer,
+         .start_frame      = start_frame,
+         .end_frame        = ff_null_end_frame
+     },
+     { NULL }
+ };
+ static const AVFilterPad avfilter_vf_settb_outputs[] = {
+     {
+         .name         = "default",
+         .type         = AVMEDIA_TYPE_VIDEO,
+         .config_props = config_output_props,
+     },
+     { NULL }
+ };
  AVFilter avfilter_vf_settb = {
      .name      = "settb",
 -    .description = NULL_IF_CONFIG_SMALL("Set timebase for the output link."),
 +    .description = NULL_IF_CONFIG_SMALL("Set timebase for the video output link."),
      .init      = init,
  
      .priv_size = sizeof(SetTBContext),
  
-     .inputs    = (const AVFilterPad[]) {
-         { .name             = "default",
-           .type             = AVMEDIA_TYPE_VIDEO,
-           .get_video_buffer = ff_null_get_video_buffer,
-           .start_frame      = start_frame,
-           .end_frame        = ff_null_end_frame },
-         { .name = NULL }
-     },
-     .outputs   = (const AVFilterPad[]) {
-         { .name            = "default",
-           .type            = AVMEDIA_TYPE_VIDEO,
-           .config_props    = config_output_props, },
-         { .name = NULL}
-     },
+     .inputs    = avfilter_vf_settb_inputs,
 -
+     .outputs   = avfilter_vf_settb_outputs,
  };
 +#endif
 +
 +#if CONFIG_ASETTB_FILTER
 +AVFilter avfilter_af_asettb = {
 +    .name      = "asettb",
 +    .description = NULL_IF_CONFIG_SMALL("Set timebase for the audio output link."),
 +    .init      = init,
 +
 +    .priv_size = sizeof(SetTBContext),
 +
 +    .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,
 +          .config_props    = config_output_props, },
 +        { .name = NULL}
 +    },
 +};
 +#endif
@@@ -267,6 -267,28 +267,28 @@@ static int request_frame(AVFilterLink *
      return ret;
  }
  
 -        .rej_perms        = AV_PERM_REUSE2,
+ static const AVFilterPad avfilter_vf_fifo_inputs[] = {
+     {
+         .name             = "default",
+         .type             = AVMEDIA_TYPE_VIDEO,
+         .get_video_buffer = ff_null_get_video_buffer,
+         .start_frame      = add_to_queue,
+         .draw_slice       = draw_slice,
+         .end_frame        = end_frame,
++        .min_perms        = AV_PERM_PRESERVE,
+     },
+     { NULL }
+ };
+ static const AVFilterPad avfilter_vf_fifo_outputs[] = {
+     {
+         .name          = "default",
+         .type          = AVMEDIA_TYPE_VIDEO,
+         .request_frame = request_frame,
+     },
+     { NULL }
+ };
  AVFilter avfilter_vf_fifo = {
      .name      = "fifo",
      .description = NULL_IF_CONFIG_SMALL("Buffer input images and send them when they are requested."),
  
      .priv_size = sizeof(FifoContext),
  
-     .inputs    = (const AVFilterPad[]) {{ .name            = "default",
-                                           .type            = AVMEDIA_TYPE_VIDEO,
-                                           .get_video_buffer= ff_null_get_video_buffer,
-                                           .start_frame     = add_to_queue,
-                                           .draw_slice      = draw_slice,
-                                           .end_frame       = end_frame,
-                                           .min_perms       = AV_PERM_PRESERVE, },
-                                         { .name = NULL}},
-     .outputs   = (const AVFilterPad[]) {{ .name            = "default",
-                                           .type            = AVMEDIA_TYPE_VIDEO,
-                                           .request_frame   = request_frame, },
-                                         { .name = NULL}},
+     .inputs    = avfilter_vf_fifo_inputs,
+     .outputs   = avfilter_vf_fifo_outputs,
+ };
+ static const AVFilterPad avfilter_af_afifo_inputs[] = {
+     {
+         .name             = "default",
+         .type             = AVMEDIA_TYPE_AUDIO,
+         .get_audio_buffer = ff_null_get_audio_buffer,
+         .filter_samples   = add_to_queue,
 -        .rej_perms        = AV_PERM_REUSE2,
++        .min_perms        = AV_PERM_PRESERVE,
+     },
+     { NULL }
+ };
+ static const AVFilterPad avfilter_af_afifo_outputs[] = {
+     {
+         .name          = "default",
+         .type          = AVMEDIA_TYPE_AUDIO,
+         .request_frame = request_frame,
+     },
+     { NULL }
  };
  
  AVFilter avfilter_af_afifo = {
@@@ -119,9 -110,21 +119,21 @@@ static int end_frame(AVFilterLink *inli
      return ret;
  }
  
+ static const AVFilterPad avfilter_vf_split_inputs[] = {
+     {
+         .name             = "default",
+         .type             = AVMEDIA_TYPE_VIDEO,
+         .get_video_buffer = ff_null_get_video_buffer,
+         .start_frame      = start_frame,
+         .draw_slice       = draw_slice,
+         .end_frame        = end_frame,
+     },
+     { NULL }
+ };
  AVFilter avfilter_vf_split = {
      .name      = "split",
 -    .description = NULL_IF_CONFIG_SMALL("Pass on the input to two outputs."),
 +    .description = NULL_IF_CONFIG_SMALL("Pass on the input video to N outputs."),
  
      .init   = split_init,
      .uninit = split_uninit,
Simple merge
Simple merge
@@@ -328,10 -331,28 +328,30 @@@ static int end_frame(AVFilterLink *inli
                w[plane], h[plane], boxblur->radius[plane], boxblur->power[plane],
                boxblur->temp);
  
 -    return ff_draw_slice(outlink, y0, h0, slice_dir);
 +    ff_draw_slice(outlink, 0, inlink->h, 1);
 +    return ff_end_frame(outlink);
  }
  
 -        .draw_slice   = draw_slice,
+ static const AVFilterPad avfilter_vf_boxblur_inputs[] = {
+     {
+         .name         = "default",
+         .type         = AVMEDIA_TYPE_VIDEO,
+         .config_props = config_input,
++        .draw_slice   = null_draw_slice,
++        .end_frame    = end_frame,
+         .min_perms    = AV_PERM_READ
+     },
+     { NULL }
+ };
+ static const AVFilterPad avfilter_vf_boxblur_outputs[] = {
+     {
+         .name = "default",
+         .type = AVMEDIA_TYPE_VIDEO,
+     },
+     { NULL }
+ };
  AVFilter avfilter_vf_boxblur = {
      .name          = "boxblur",
      .description   = NULL_IF_CONFIG_SMALL("Blur the input."),
Simple merge
Simple merge
Simple merge
@@@ -245,6 -251,28 +245,27 @@@ static int end_frame(AVFilterLink *inli
      return 0;
  }
  
 -        .rej_perms        = AV_PERM_PRESERVE
+ static const AVFilterPad avfilter_vf_delogo_inputs[] = {
+     {
+         .name             = "default",
+         .type             = AVMEDIA_TYPE_VIDEO,
+         .get_video_buffer = ff_null_get_video_buffer,
+         .start_frame      = ff_inplace_start_frame,
+         .draw_slice       = null_draw_slice,
+         .end_frame        = end_frame,
+         .min_perms        = AV_PERM_WRITE | AV_PERM_READ,
+     },
+     { NULL }
+ };
+ static const AVFilterPad avfilter_vf_delogo_outputs[] = {
+     {
+         .name = "default",
+         .type = AVMEDIA_TYPE_VIDEO,
+     },
+     { NULL }
+ };
  AVFilter avfilter_vf_delogo = {
      .name          = "delogo",
      .description   = NULL_IF_CONFIG_SMALL("Remove logo from input video."),
@@@ -124,6 -124,29 +124,28 @@@ static int draw_slice(AVFilterLink *inl
      return ff_draw_slice(inlink->dst->outputs[0], y0, h, 1);
  }
  
 -        .rej_perms        = AV_PERM_PRESERVE
+ static const AVFilterPad avfilter_vf_drawbox_inputs[] = {
+     {
+         .name             = "default",
+         .type             = AVMEDIA_TYPE_VIDEO,
+         .config_props     = config_input,
+         .get_video_buffer = ff_null_get_video_buffer,
+         .start_frame      = ff_null_start_frame,
+         .draw_slice       = draw_slice,
+         .end_frame        = ff_null_end_frame,
+         .min_perms        = AV_PERM_WRITE | AV_PERM_READ,
+     },
+     { NULL }
+ };
+ static const AVFilterPad avfilter_vf_drawbox_outputs[] = {
+     {
+         .name = "default",
+         .type = AVMEDIA_TYPE_VIDEO,
+     },
+     { NULL }
+ };
  AVFilter avfilter_vf_drawbox = {
      .name      = "drawbox",
      .description = NULL_IF_CONFIG_SMALL("Draw a colored box on the input video."),
@@@ -810,6 -879,30 +810,29 @@@ static int end_frame(AVFilterLink *inli
      return 0;
  }
  
 -        .start_frame      = start_frame,
+ static const AVFilterPad avfilter_vf_drawtext_inputs[] = {
+     {
+         .name             = "default",
+         .type             = AVMEDIA_TYPE_VIDEO,
+         .get_video_buffer = ff_null_get_video_buffer,
 -        .rej_perms = AV_PERM_PRESERVE
++        .start_frame      = ff_null_start_frame,
+         .draw_slice       = null_draw_slice,
+         .end_frame        = end_frame,
+         .config_props     = config_input,
+         .min_perms        = AV_PERM_WRITE |
+                             AV_PERM_READ,
+     },
+     { NULL }
+ };
+ static const AVFilterPad avfilter_vf_drawtext_outputs[] = {
+     {
+         .name = "default",
+         .type = AVMEDIA_TYPE_VIDEO,
+     },
+     { NULL }
+ };
  AVFilter avfilter_vf_drawtext = {
      .name          = "drawtext",
      .description   = NULL_IF_CONFIG_SMALL("Draw text on top of video frames using libfreetype library."),
      .uninit        = uninit,
      .query_formats = query_formats,
  
-     .inputs    = (const AVFilterPad[]) {{ .name             = "default",
-                                           .type             = AVMEDIA_TYPE_VIDEO,
-                                           .get_video_buffer = ff_null_get_video_buffer,
-                                           .start_frame      = ff_null_start_frame,
-                                           .draw_slice       = null_draw_slice,
-                                           .end_frame        = end_frame,
-                                           .config_props     = config_input,
-                                           .min_perms        = AV_PERM_WRITE |
-                                                               AV_PERM_READ },
-                                         { .name = NULL}},
-     .outputs   = (const AVFilterPad[]) {{ .name             = "default",
-                                           .type             = AVMEDIA_TYPE_VIDEO, },
-                                         { .name = NULL}},
+     .inputs    = avfilter_vf_drawtext_inputs,
+     .outputs   = avfilter_vf_drawtext_outputs,
 +    .process_command = command,
 +    .priv_class = &drawtext_class,
  };
@@@ -276,25 -154,36 +276,37 @@@ static int end_frame(AVFilterLink *inli
      return ret;
  }
  
 -        .rej_perms        = AV_PERM_PRESERVE,
+ static const AVFilterPad avfilter_vf_fade_inputs[] = {
+     {
+         .name             = "default",
+         .type             = AVMEDIA_TYPE_VIDEO,
+         .config_props     = config_props,
+         .get_video_buffer = ff_null_get_video_buffer,
+         .start_frame      = ff_null_start_frame,
+         .draw_slice       = draw_slice,
+         .end_frame        = end_frame,
+         .min_perms        = AV_PERM_READ | AV_PERM_WRITE,
+     },
+     { NULL }
+ };
+ static const AVFilterPad avfilter_vf_fade_outputs[] = {
+     {
+         .name = "default",
+         .type = AVMEDIA_TYPE_VIDEO,
+     },
+     { NULL }
+ };
  AVFilter avfilter_vf_fade = {
      .name          = "fade",
 -    .description   = NULL_IF_CONFIG_SMALL("Fade in/out input video"),
 +    .description   = NULL_IF_CONFIG_SMALL("Fade in/out input video."),
      .init          = init,
 +    .uninit        = uninit,
      .priv_size     = sizeof(FadeContext),
      .query_formats = query_formats,
  
-     .inputs    = (const AVFilterPad[]) {{ .name            = "default",
-                                           .type            = AVMEDIA_TYPE_VIDEO,
-                                           .config_props    = config_props,
-                                           .get_video_buffer = ff_null_get_video_buffer,
-                                           .start_frame      = ff_null_start_frame,
-                                           .draw_slice      = draw_slice,
-                                           .end_frame       = end_frame,
-                                           .min_perms       = AV_PERM_READ | AV_PERM_WRITE },
-                                         { .name = NULL}},
-     .outputs   = (const AVFilterPad[]) {{ .name            = "default",
-                                           .type            = AVMEDIA_TYPE_VIDEO, },
-                                         { .name = NULL}},
+     .inputs    = avfilter_vf_fade_inputs,
+     .outputs   = avfilter_vf_fade_outputs,
 +    .priv_class = &fade_class,
  };
@@@ -234,6 -234,29 +234,28 @@@ static int end_frame(AVFilterLink *inli
      return ff_end_frame(outlink);
  }
  
 -        .min_perms        = AV_PERM_READ,
 -        .rej_perms        = AV_PERM_REUSE2 | AV_PERM_PRESERVE,
+ static const AVFilterPad avfilter_vf_fieldorder_inputs[] = {
+     {
+         .name             = "default",
+         .type             = AVMEDIA_TYPE_VIDEO,
+         .config_props     = config_input,
+         .start_frame      = start_frame,
+         .get_video_buffer = get_video_buffer,
+         .draw_slice       = draw_slice,
+         .end_frame        = end_frame,
++        .min_perms        = AV_PERM_READ | AV_PERM_PRESERVE,
+     },
+     { NULL }
+ };
+ static const AVFilterPad avfilter_vf_fieldorder_outputs[] = {
+     {
+         .name = "default",
+         .type = AVMEDIA_TYPE_VIDEO,
+     },
+     { NULL }
+ };
  AVFilter avfilter_vf_fieldorder = {
      .name          = "fieldorder",
      .description   = NULL_IF_CONFIG_SMALL("Set the field order."),
Simple merge
@@@ -279,6 -278,27 +279,29 @@@ static int null_draw_slice(AVFilterLin
      return 0;
  }
  
+ static const AVFilterPad avfilter_vf_fps_inputs[] = {
+     {
+         .name        = "default",
+         .type        = AVMEDIA_TYPE_VIDEO,
++        .min_perms   = AV_PERM_READ | AV_PERM_PRESERVE,
+         .start_frame = null_start_frame,
+         .draw_slice  = null_draw_slice,
+         .end_frame   = end_frame,
+     },
+     { NULL }
+ };
+ static const AVFilterPad avfilter_vf_fps_outputs[] = {
+     {
+         .name          = "default",
+         .type          = AVMEDIA_TYPE_VIDEO,
++        .rej_perms     = AV_PERM_WRITE,
+         .request_frame = request_frame,
+         .config_props  = config_props
+     },
+     { NULL }
+ };
  AVFilter avfilter_vf_fps = {
      .name        = "fps",
      .description = NULL_IF_CONFIG_SMALL("Force constant framerate"),
  
      .priv_size = sizeof(FPSContext),
  
-     .inputs    = (const AVFilterPad[]) {{ .name            = "default",
-                                           .type            = AVMEDIA_TYPE_VIDEO,
-                                           .min_perms       = AV_PERM_READ | AV_PERM_PRESERVE,
-                                           .start_frame     = null_start_frame,
-                                           .draw_slice      = null_draw_slice,
-                                           .end_frame       = end_frame, },
-                                         { .name = NULL}},
-     .outputs   = (const AVFilterPad[]) {{ .name            = "default",
-                                           .type            = AVMEDIA_TYPE_VIDEO,
-                                           .rej_perms       = AV_PERM_WRITE,
-                                           .request_frame   = request_frame,
-                                           .config_props    = config_props},
-                                         { .name = NULL}},
+     .inputs    = avfilter_vf_fps_inputs,
+     .outputs   = avfilter_vf_fps_outputs,
 +    .priv_class = &fps_class,
  };
Simple merge
Simple merge
@@@ -165,6 -148,25 +165,26 @@@ static int draw_slice(AVFilterLink *inl
      return ff_draw_slice(inlink->dst->outputs[0], y, h, slice_dir);
  }
  
+ static const AVFilterPad avfilter_vf_hflip_inputs[] = {
+     {
+         .name         = "default",
+         .type         = AVMEDIA_TYPE_VIDEO,
++        .start_frame  = start_frame,
+         .draw_slice   = draw_slice,
+         .config_props = config_props,
+         .min_perms    = AV_PERM_READ,
+     },
+     { NULL }
+ };
+ static const AVFilterPad avfilter_vf_hflip_outputs[] = {
+     {
+         .name = "default",
+         .type = AVMEDIA_TYPE_VIDEO,
+     },
+     { NULL }
+ };
  AVFilter avfilter_vf_hflip = {
      .name      = "hflip",
      .description = NULL_IF_CONFIG_SMALL("Horizontally flip the input video."),
Simple merge
Simple merge
Simple merge
@@@ -523,90 -301,115 +523,124 @@@ static int start_frame_main(AVFilterLin
      return 0;
  }
  
 -static int output_frame(AVFilterContext *ctx)
 +static int draw_slice_main(AVFilterLink *inlink, int y, int h, int slice_dir)
  {
 -    OverlayContext *s = ctx->priv;
 +    AVFilterContext *ctx = inlink->dst;
 +    OverlayContext *over = ctx->priv;
      AVFilterLink *outlink = ctx->outputs[0];
 -    int ret = ff_start_frame(outlink, s->main);
 -    if (ret >= 0)
 -        ret = ff_draw_slice(outlink, 0, outlink->h, 1);
 -    if (ret >= 0)
 -        ret = ff_end_frame(outlink);
 -    s->main = NULL;
 -
 -    return ret;
 +    AVFilterBufferRef *outpicref = outlink->out_buf;
 +
 +    if (!outpicref)
 +        return 0;
 +    if (over->overpicref &&
 +        y + h > over->y && y < over->y + over->overpicref->video->h) {
 +        blend_slice(ctx, outpicref, over->overpicref, over->x, over->y,
 +                    over->overpicref->video->w, over->overpicref->video->h,
 +                    y, outpicref->video->w, h);
 +    }
 +    return ff_draw_slice(outlink, y, h, slice_dir);
  }
  
 -static int handle_overlay_eof(AVFilterContext *ctx)
 +static int end_frame_main(AVFilterLink *inlink)
  {
 -    OverlayContext *s = ctx->priv;
 -    if (s->over_prev)
 -        blend_frame(ctx, s->main, s->over_prev, s->x, s->y);
 -    return output_frame(ctx);
 +    AVFilterContext *ctx = inlink->dst;
 +    AVFilterLink *outlink = ctx->outputs[0];
 +    AVFilterBufferRef *outpicref = outlink->out_buf;
 +    flush_frames(ctx);
 +
 +    if (!outpicref)
 +        return 0;
 +    return ff_end_frame(ctx->outputs[0]);
  }
  
 -static int request_frame(AVFilterLink *outlink)
 +static int start_frame_over(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
  {
 -    AVFilterContext *ctx = outlink->src;
 -    OverlayContext    *s = ctx->priv;
 -    AVRational tb_main = ctx->inputs[MAIN]->time_base;
 -    AVRational tb_over = ctx->inputs[OVERLAY]->time_base;
 -    int ret = 0;
 +    return 0;
 +}
  
 -    /* get a frame on the main input */
 -    if (!s->main) {
 -        ret = ff_request_frame(ctx->inputs[MAIN]);
 -        if (ret < 0)
 -            return ret;
 -    }
 +static int end_frame_over(AVFilterLink *inlink)
 +{
 +    AVFilterContext *ctx = inlink->dst;
 +    OverlayContext *over = ctx->priv;
 +    AVFilterBufferRef *inpicref = inlink->cur_buf;
 +    int ret;
  
 -    /* get a new frame on the overlay input, on EOF
 -     * reuse previous */
 -    if (!s->over_next) {
 -        ret = ff_request_frame(ctx->inputs[OVERLAY]);
 -        if (ret == AVERROR_EOF)
 -           return handle_overlay_eof(ctx);
 -        else if (ret < 0)
 -            return ret;
 -    }
 +    inlink->cur_buf = NULL;
  
 -    while (s->main->pts != AV_NOPTS_VALUE &&
 -           s->over_next->pts != AV_NOPTS_VALUE &&
 -           av_compare_ts(s->over_next->pts, tb_over, s->main->pts, tb_main) < 0) {
 -        avfilter_unref_bufferp(&s->over_prev);
 -        FFSWAP(AVFilterBufferRef*, s->over_prev, s->over_next);
 +    if ((ret = flush_frames(ctx)) < 0)
 +        return ret;
 +    ff_bufqueue_add(ctx, &over->queue_over, inpicref);
 +    ret = try_push_frame(ctx);
 +    return ret == AVERROR(EAGAIN) ? 0 : ret;
 +}
  
 -        ret = ff_request_frame(ctx->inputs[OVERLAY]);
 -        if (ret == AVERROR_EOF)
 -            return handle_overlay_eof(ctx);
 -        else if (ret < 0)
 +static int request_frame(AVFilterLink *outlink)
 +{
 +    AVFilterContext *ctx = outlink->src;
 +    OverlayContext *over = ctx->priv;
 +    int input, ret;
 +
 +    if (!try_push_frame(ctx))
 +        return 0;
 +    over->frame_requested = 1;
 +    while (over->frame_requested) {
 +        /* TODO if we had a frame duration, we could guess more accurately */
 +        input = !over->overlay_eof && (over->queue_main.available ||
 +                                       over->queue_over.available < 2) ?
 +                OVERLAY : MAIN;
 +        ret = ff_request_frame(ctx->inputs[input]);
 +        /* EOF on main is reported immediately */
 +        if (ret == AVERROR_EOF && input == OVERLAY) {
 +            over->overlay_eof = 1;
 +            if ((ret = try_start_next_frame(ctx)) != AVERROR(EAGAIN))
 +                return ret;
 +            ret = 0; /* continue requesting frames on main */
 +        }
 +        if (ret < 0)
              return ret;
      }
 +    return 0;
 +}
  
 -    if (s->main->pts == AV_NOPTS_VALUE ||
 -        s->over_next->pts == AV_NOPTS_VALUE ||
 -        !av_compare_ts(s->over_next->pts, tb_over, s->main->pts, tb_main)) {
 -        blend_frame(ctx, s->main, s->over_next, s->x, s->y);
 -        avfilter_unref_bufferp(&s->over_prev);
 -        FFSWAP(AVFilterBufferRef*, s->over_prev, s->over_next);
 -    } else if (s->over_prev) {
 -        blend_frame(ctx, s->main, s->over_prev, s->x, s->y);
 -    }
 -
 -    return output_frame(ctx);
 +static int null_draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
 +{
 +    return 0;
  }
  
 -        .start_frame  = null_start_frame,
+ static const AVFilterPad avfilter_vf_overlay_inputs[] = {
+     {
+         .name         = "main",
+         .type         = AVMEDIA_TYPE_VIDEO,
 -        .draw_slice   = null_draw_slice,
++        .get_video_buffer= get_video_buffer,
+         .config_props = config_input_main,
 -        .min_perms    = AV_PERM_READ,
 -        .rej_perms    = AV_PERM_REUSE2 | AV_PERM_PRESERVE,
 -        .needs_fifo   = 1,
++        .start_frame  = start_frame_main,
++        .draw_slice   = draw_slice_main,
+         .end_frame    = end_frame_main,
 -        .start_frame  = null_start_frame,
++        .min_perms    = AV_PERM_READ | AV_PERM_WRITE | AV_PERM_PRESERVE,
+     },
+     {
+         .name         = "overlay",
+         .type         = AVMEDIA_TYPE_VIDEO,
 -        .end_frame    = end_frame_overlay,
 -        .min_perms    = AV_PERM_READ,
 -        .rej_perms    = AV_PERM_REUSE2,
 -        .needs_fifo   = 1,
+         .config_props = config_input_overlay,
++        .start_frame  = start_frame_over,
+         .draw_slice   = null_draw_slice,
++        .end_frame    = end_frame_over,
++        .min_perms    = AV_PERM_READ | AV_PERM_PRESERVE,
+     },
+     { NULL }
+ };
+ static const AVFilterPad avfilter_vf_overlay_outputs[] = {
+     {
+         .name          = "default",
+         .type          = AVMEDIA_TYPE_VIDEO,
++        .rej_perms     = AV_PERM_WRITE,
+         .config_props  = config_output,
+         .request_frame = request_frame,
+     },
+     { NULL }
+ };
  AVFilter avfilter_vf_overlay = {
      .name      = "overlay",
      .description = NULL_IF_CONFIG_SMALL("Overlay a video source on top of the input."),
  
      .query_formats = query_formats,
  
-     .inputs    = (const AVFilterPad[]) {{ .name            = "main",
-                                           .type            = AVMEDIA_TYPE_VIDEO,
-                                           .get_video_buffer= get_video_buffer,
-                                           .config_props    = config_input_main,
-                                           .start_frame     = start_frame_main,
-                                           .draw_slice      = draw_slice_main,
-                                           .end_frame       = end_frame_main,
-                                           .min_perms       = AV_PERM_READ | AV_PERM_WRITE | AV_PERM_PRESERVE },
-                                         { .name            = "overlay",
-                                           .type            = AVMEDIA_TYPE_VIDEO,
-                                           .config_props    = config_input_overlay,
-                                           .start_frame     = start_frame_over,
-                                           .draw_slice      = null_draw_slice,
-                                           .end_frame       = end_frame_over,
-                                           .min_perms       = AV_PERM_READ | AV_PERM_PRESERVE },
-                                         { .name = NULL}},
-     .outputs   = (const AVFilterPad[]) {{ .name            = "default",
-                                           .type            = AVMEDIA_TYPE_VIDEO,
-                                           .rej_perms       = AV_PERM_WRITE,
-                                           .config_props    = config_output,
-                                           .request_frame   = request_frame, },
-                                         { .name = NULL}},
+     .inputs    = avfilter_vf_overlay_inputs,
+     .outputs   = avfilter_vf_overlay_outputs,
 +    .priv_class = &overlay_class,
  };
@@@ -388,24 -434,38 +388,36 @@@ static int draw_slice(AVFilterLink *lin
      return draw_send_bar_slice(link, y, h, slice_dir, -1);
  }
  
 -        .end_frame        = end_frame,
+ static const AVFilterPad avfilter_vf_pad_inputs[] = {
+     {
+         .name             = "default",
+         .type             = AVMEDIA_TYPE_VIDEO,
+         .config_props     = config_input,
+         .get_video_buffer = get_video_buffer,
+         .start_frame      = start_frame,
+         .draw_slice       = draw_slice,
+     },
+     { NULL }
+ };
+ static const AVFilterPad avfilter_vf_pad_outputs[] = {
+     {
+         .name         = "default",
+         .type         = AVMEDIA_TYPE_VIDEO,
+         .config_props = config_output,
+     },
+     { NULL }
+ };
  AVFilter avfilter_vf_pad = {
      .name          = "pad",
      .description   = NULL_IF_CONFIG_SMALL("Pad input image to width:height[:x:y[:color]] (default x and y: 0, default color: black)."),
  
      .priv_size     = sizeof(PadContext),
      .init          = init,
 -    .uninit        = uninit,
      .query_formats = query_formats,
  
-     .inputs    = (const AVFilterPad[]) {{ .name             = "default",
-                                           .type             = AVMEDIA_TYPE_VIDEO,
-                                           .config_props     = config_input,
-                                           .get_video_buffer = get_video_buffer,
-                                           .start_frame      = start_frame,
-                                           .draw_slice       = draw_slice, },
-                                         { .name = NULL}},
-     .outputs   = (const AVFilterPad[]) {{ .name             = "default",
-                                           .type             = AVMEDIA_TYPE_VIDEO,
-                                           .config_props     = config_output, },
-                                         { .name = NULL}},
+     .inputs    = avfilter_vf_pad_inputs,
+     .outputs   = avfilter_vf_pad_outputs,
  };
Simple merge
Simple merge
@@@ -391,32 -338,31 +391,56 @@@ static av_cold void uninit(AVFilterCont
          avfilter_unref_buffer(picref);
      av_fifo_free(select->pending_frames);
      select->pending_frames = NULL;
 +
 +    if (select->do_scene_detect) {
 +        avfilter_unref_bufferp(&select->prev_picref);
 +        if (select->avctx) {
 +            avcodec_close(select->avctx);
 +            av_freep(&select->avctx);
 +        }
 +    }
 +}
 +
 +static int query_formats(AVFilterContext *ctx)
 +{
 +    SelectContext *select = ctx->priv;
 +
 +    if (!select->do_scene_detect) {
 +        return ff_default_query_formats(ctx);
 +    } else {
 +        static const enum AVPixelFormat pix_fmts[] = {
 +            AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24,
 +            AV_PIX_FMT_NONE
 +        };
 +        ff_set_common_formats(ctx, ff_make_format_list(pix_fmts));
 +    }
 +    return 0;
  }
  
+ static const AVFilterPad avfilter_vf_select_inputs[] = {
+     {
+         .name             = "default",
+         .type             = AVMEDIA_TYPE_VIDEO,
+         .get_video_buffer = ff_null_get_video_buffer,
++        .min_perms        = AV_PERM_PRESERVE,
+         .config_props     = config_input,
+         .start_frame      = start_frame,
+         .draw_slice       = draw_slice,
+         .end_frame        = end_frame
+     },
+     { NULL }
+ };
+ static const AVFilterPad avfilter_vf_select_outputs[] = {
+     {
+         .name          = "default",
+         .type          = AVMEDIA_TYPE_VIDEO,
+         .poll_frame    = poll_frame,
+         .request_frame = request_frame,
+     },
+     { NULL }
+ };
  AVFilter avfilter_vf_select = {
      .name      = "select",
      .description = NULL_IF_CONFIG_SMALL("Select frames to pass in output."),
Simple merge
Simple merge
@@@ -259,13 -208,26 +259,35 @@@ static int end_frame(AVFilterLink *inli
      return 0;
  }
  
 +static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
 +{
 +    TransContext *trans = inlink->dst->priv;
 +
 +    return trans->passthrough ? ff_null_draw_slice(inlink, y, h, slice_dir) : 0;
 +}
 +
+ static const AVFilterPad avfilter_vf_transpose_inputs[] = {
+     {
+         .name        = "default",
+         .type        = AVMEDIA_TYPE_VIDEO,
++        .get_video_buffer= get_video_buffer,
+         .start_frame = start_frame,
++        .draw_slice  = draw_slice,
+         .end_frame   = end_frame,
+         .min_perms   = AV_PERM_READ,
+     },
+     { NULL }
+ };
+ static const AVFilterPad avfilter_vf_transpose_outputs[] = {
+     {
+         .name         = "default",
+         .config_props = config_props_output,
+         .type         = AVMEDIA_TYPE_VIDEO,
+     },
+     { NULL }
+ };
  AVFilter avfilter_vf_transpose = {
      .name      = "transpose",
      .description = NULL_IF_CONFIG_SMALL("Transpose input video."),
  
      .query_formats = query_formats,
  
-     .inputs    = (const AVFilterPad[]) {{ .name            = "default",
-                                           .type            = AVMEDIA_TYPE_VIDEO,
-                                           .get_video_buffer= get_video_buffer,
-                                           .start_frame     = start_frame,
-                                           .draw_slice      = draw_slice,
-                                           .end_frame       = end_frame,
-                                           .min_perms       = AV_PERM_READ, },
-                                         { .name = NULL}},
-     .outputs   = (const AVFilterPad[]) {{ .name            = "default",
-                                           .config_props    = config_props_output,
-                                           .type            = AVMEDIA_TYPE_VIDEO, },
-                                         { .name = NULL}},
+     .inputs    = avfilter_vf_transpose_inputs,
+     .outputs   = avfilter_vf_transpose_outputs,
 +    .priv_class = &transpose_class,
  };
Simple merge
Simple merge
@@@ -441,9 -424,32 +441,32 @@@ static int config_props(AVFilterLink *l
      return 0;
  }
  
 -        .get_video_buffer = get_video_buffer,
+ static const AVFilterPad avfilter_vf_yadif_inputs[] = {
+     {
+         .name             = "default",
+         .type             = AVMEDIA_TYPE_VIDEO,
+         .start_frame      = start_frame,
+         .draw_slice       = null_draw_slice,
+         .end_frame        = end_frame,
++        .min_perms        = AV_PERM_PRESERVE,
+     },
+     { NULL }
+ };
+ static const AVFilterPad avfilter_vf_yadif_outputs[] = {
+     {
+         .name          = "default",
+         .type          = AVMEDIA_TYPE_VIDEO,
+         .poll_frame    = poll_frame,
+         .request_frame = request_frame,
+         .config_props  = config_props,
+     },
+     { NULL }
+ };
  AVFilter avfilter_vf_yadif = {
      .name          = "yadif",
 -    .description   = NULL_IF_CONFIG_SMALL("Deinterlace the input image"),
 +    .description   = NULL_IF_CONFIG_SMALL("Deinterlace the input image."),
  
      .priv_size     = sizeof(YADIFContext),
      .init          = init,
Simple merge
@@@ -525,23 -359,27 +525,28 @@@ static int test_query_formats(AVFilterC
      return 0;
  }
  
+ static const AVFilterPad avfilter_vsrc_testsrc_outputs[] = {
+     {
+         .name          = "default",
+         .type          = AVMEDIA_TYPE_VIDEO,
+         .request_frame = request_frame,
+         .config_props  = config_props,
+     },
+     { NULL }
+ };
  AVFilter avfilter_vsrc_testsrc = {
 -    .name          = "testsrc",
 -    .description   = NULL_IF_CONFIG_SMALL("Generate test pattern."),
 -    .priv_size     = sizeof(TestSourceContext),
 -    .init          = test_init,
 +    .name      = "testsrc",
 +    .description = NULL_IF_CONFIG_SMALL("Generate test pattern."),
 +    .priv_size = sizeof(TestSourceContext),
 +    .init      = test_init,
 +    .uninit    = uninit,
  
 -    .query_formats = test_query_formats,
 +    .query_formats   = test_query_formats,
  
      .inputs    = NULL,
--
-     .outputs   = (const AVFilterPad[]) {{ .name = "default",
-                                           .type = AVMEDIA_TYPE_VIDEO,
-                                           .request_frame = request_frame,
-                                           .config_props  = config_props, },
-                                         { .name = NULL }},
+     .outputs   = avfilter_vsrc_testsrc_outputs,
 +    .priv_class = &testsrc_class,
  };
  
  #endif /* CONFIG_TESTSRC_FILTER */
@@@ -639,23 -492,27 +644,29 @@@ static int rgbtest_config_props(AVFilte
      return config_props(outlink);
  }
  
+ static const AVFilterPad avfilter_vsrc_rgbtestsrc_outputs[] = {
+     {
+         .name          = "default",
+         .type          = AVMEDIA_TYPE_VIDEO,
+         .request_frame = request_frame,
+         .config_props  = rgbtest_config_props,
+     },
+     { NULL }
+ };
  AVFilter avfilter_vsrc_rgbtestsrc = {
 -    .name          = "rgbtestsrc",
 -    .description   = NULL_IF_CONFIG_SMALL("Generate RGB test pattern."),
 -    .priv_size     = sizeof(TestSourceContext),
 -    .init          = rgbtest_init,
 +    .name      = "rgbtestsrc",
 +    .description = NULL_IF_CONFIG_SMALL("Generate RGB test pattern."),
 +    .priv_size = sizeof(TestSourceContext),
 +    .init      = rgbtest_init,
 +    .uninit    = uninit,
  
 -    .query_formats = rgbtest_query_formats,
 +    .query_formats   = rgbtest_query_formats,
  
      .inputs    = NULL,
  
-     .outputs   = (const AVFilterPad[]) {{ .name = "default",
-                                           .type = AVMEDIA_TYPE_VIDEO,
-                                           .request_frame = request_frame,
-                                           .config_props  = rgbtest_config_props, },
-                                         { .name = NULL }},
+     .outputs   = avfilter_vsrc_rgbtestsrc_outputs,
 +    .priv_class = &rgbtestsrc_class,
  };
  
  #endif /* CONFIG_RGBTESTSRC_FILTER */
@@@ -951,8 -950,12 +951,11 @@@ static int mxf_get_sorted_table_segment
          if (mxf->metadata_sets[i]->type == IndexTableSegment)
              nb_segments++;
  
 -    *sorted_segments  = av_mallocz(nb_segments * sizeof(**sorted_segments));
 -    unsorted_segments = av_mallocz(nb_segments * sizeof(*unsorted_segments));
 -    if (!sorted_segments || !unsorted_segments) {
+     if (!nb_segments)
+         return AVERROR_INVALIDDATA;
 +    if (!(unsorted_segments = av_calloc(nb_segments, sizeof(*unsorted_segments))) ||
 +        !(*sorted_segments  = av_calloc(nb_segments, sizeof(**sorted_segments)))) {
          av_freep(sorted_segments);
          av_free(unsorted_segments);
          return AVERROR(ENOMEM);
diff --cc library.mak
@@@ -43,15 -43,11 +43,15 @@@ $(EXAMPLES) $(TESTPROGS) $(TOOLS): %$(E
  $(SUBDIR)$(SLIBNAME): $(SUBDIR)$(SLIBNAME_WITH_MAJOR)
        $(Q)cd ./$(SUBDIR) && $(LN_S) $(SLIBNAME_WITH_MAJOR) $(SLIBNAME)
  
 -$(SUBDIR)$(SLIBNAME_WITH_MAJOR): $(OBJS) $(SUBDIR)lib$(NAME).ver $(DEP_LIBS)
 +$(SUBDIR)$(SLIBNAME_WITH_MAJOR): $(OBJS) $(SUBDIR)lib$(NAME).ver
        $(SLIB_CREATE_DEF_CMD)
-       $$(LD) $(SHFLAGS) $(LDFLAGS) $$(LD_O) $$(filter %.o,$$^) $(FFEXTRALIBS) $(EXTRAOBJS)
+       $$(LD) $(SHFLAGS) $(LDFLAGS) $$(LD_O) $$(filter %.o,$$^) $(FFEXTRALIBS)
        $(SLIB_EXTRA_CMD)
  
 +ifdef SUBDIR
 +$(SUBDIR)$(SLIBNAME_WITH_MAJOR): $(DEP_LIBS)
 +endif
 +
  clean::
        $(RM) $(addprefix $(SUBDIR),*-example$(EXESUF) *-test$(EXESUF) $(CLEANFILES) $(CLEANSUFFIXES) $(LIBSUFFIXES)) \
            $(CLEANSUFFIXES:%=$(SUBDIR)$(ARCH)/%) $(HOSTOBJS) $(HOSTPROGS)
Simple merge
index 0000000,b7e8f49..d82c425
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,4 +1,4 @@@
 -8a7be9f9f97673bf8b926b6dcf8a710d *tests/data/fate/vsynth1-h263-obmc.avi
 -657366 tests/data/fate/vsynth1-h263-obmc.avi
 -eba1d733a0c4b71322a78f718f312599 *tests/data/fate/vsynth1-h263-obmc.out.rawvideo
++bdd8f9cafa39df97f2e395110f4419e0 *tests/data/fate/vsynth1-h263-obmc.avi
++657328 tests/data/fate/vsynth1-h263-obmc.avi
++844f7ee27fa122e199fe20987b41a15c *tests/data/fate/vsynth1-h263-obmc.out.rawvideo
+ stddev:    8.16 PSNR: 29.89 MAXDIFF:  113 bytes:  7603200/  7603200
index 0000000,32c2341..d8a65db
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,4 +1,4 @@@
 -0c84ee18c2261070ffc91b5d606094ae *tests/data/fate/vsynth2-h263-obmc.avi
 -154728 tests/data/fate/vsynth2-h263-obmc.avi
 -6f326547cf1cbd95a8c0a5ddce9eb71a *tests/data/fate/vsynth2-h263-obmc.out.rawvideo
++482d48074d94ed72b0c7057b9c129b45 *tests/data/fate/vsynth2-h263-obmc.avi
++154738 tests/data/fate/vsynth2-h263-obmc.avi
++588d992d9d8096da8bdc5027268da914 *tests/data/fate/vsynth2-h263-obmc.out.rawvideo
+ stddev:    5.39 PSNR: 33.49 MAXDIFF:   82 bytes:  7603200/  7603200