[FFmpeg-devel] [PATCH] lavfi: port phase filter from libmpcodecs

Stefano Sabatini stefasab at gmail.com
Mon Sep 2 20:04:42 CEST 2013


On date Monday 2013-09-02 14:06:13 +0000, Paul B Mahol encoded:
> Signed-off-by: Paul B Mahol <onemda at gmail.com>
> ---
>  Changelog                |   1 +
>  LICENSE                  |   1 +
>  configure                |   1 +
>  doc/filters.texi         |  61 +++++++++
>  libavfilter/Makefile     |   1 +
>  libavfilter/allfilters.c |   1 +
>  libavfilter/version.h    |   4 +-
>  libavfilter/vf_phase.c   | 313 +++++++++++++++++++++++++++++++++++++++++++++++
>  8 files changed, 381 insertions(+), 2 deletions(-)
>  create mode 100644 libavfilter/vf_phase.c
> 
> diff --git a/Changelog b/Changelog
> index 1ec6e9b..6706d07 100644
> --- a/Changelog
> +++ b/Changelog
> @@ -16,6 +16,7 @@ version <next>
>  - incomplete Voxware MetaSound decoder
>  - read EXIF metadata from JPEG
>  - DVB teletext decoder
> +- phase filter ported from libmpcodecs
>  
>  
>  version 2.0:
> diff --git a/LICENSE b/LICENSE
> index 575824e..f765ce8 100644
> --- a/LICENSE
> +++ b/LICENSE
> @@ -40,6 +40,7 @@ Specifically, the GPL parts of FFmpeg are
>      - vf_noise.c
>      - vf_owdenoise.c
>      - vf_perspective.c
> +    - vf_phase.c
>      - vf_pp.c
>      - vf_sab.c
>      - vf_smartblur.c
> diff --git a/configure b/configure
> index 590d67f..62f258a 100755
> --- a/configure
> +++ b/configure
> @@ -2220,6 +2220,7 @@ resample_filter_deps="avresample"
>  ocv_filter_deps="libopencv"
>  owdenoise_filter_deps="gpl"
>  pan_filter_deps="swresample"
> +phase_filter_deps="gpl"
>  pp_filter_deps="gpl postproc"
>  removelogo_filter_deps="avcodec avformat swscale"
>  sab_filter_deps="gpl swscale"
> diff --git a/doc/filters.texi b/doc/filters.texi
> index 5d9a2df..11ebfd5 100644
> --- a/doc/filters.texi
> +++ b/doc/filters.texi
> @@ -5854,6 +5854,67 @@ It accepts the following values:
>  Default value is @samp{linear}.
>  @end table
>  
> + at section phase
> +
> +Delay interlaced video by one field time so that the field order changes.
> +
> +The intended use is to fix PAL movies that have been captured with the
> +opposite field order to the film-to-video transfer.
> +
> +A description of the accepted parameters follows.
> +
> + at table @option
> + at item mode
> +Set phase mode.
> +
> +It accepts the following values:
> + at table @samp
> + at item t
> +Capture field order top-first, transfer bottom-first.
> +Filter will delay the bottom field.
> +
> + at item b
> +Capture field order bottom-first, transfer top-first.
> +Filter will delay the top field.
> +
> + at item p
> +Capture and transfer with the same field order. This mode only exists
> +for the documentation of the other options to refer to, but if you
> +actually select it, the filter will faithfully do nothing.
> +
> + at item a
> +Capture field order determined automatically by field flags, transfer
> +opposite.
> +Filter selects among @samp{t} and @samp{b} modes on a frame by frame
> +basis using field flags. If no field information is available,
> +then this works just like @samp{u}.
> +
> + at item u
> +Capture unknown or varying, transfer opposite.
> +Filter selects among @samp{t} and @samp{b} on a frame by frame basis by
> +analyzing the images and selecting the alternative that produces best
> +match between the fields.
> +
> + at item T
> +Capture top-first, transfer unknown or varying.
> +Filter selects among @samp{t} and @samp{p} using image analysis.
> +
> + at item B
> +Capture bottom-first, transfer unknown or varying.
> +Filter selects among @samp{b} and @samp{p} using image analysis.
> +
> + at item A
> +Capture determined by field flags, transfer unknown or varying.

> +Filter selects among @samp{t} @samp{b} and @samp{p} using field flags and

@samp{t}, @samp{b}, and ..

> +image analysis. If no field information is available, then this works just

> +like @samp{U} This is the default mode.

missing dot

> +
> + at item U
> +Both capture and transfer unknown or varying.
> +Filter selects among @samp{t}, @samp{b} and @samp{p} using image analysis only.
> + at end table
> + at end table
> +
>  @section pixdesctest
>  
>  Pixel format descriptor test filter, mainly useful for internal
> diff --git a/libavfilter/Makefile b/libavfilter/Makefile
> index 3751d54..35f03c7 100644
> --- a/libavfilter/Makefile
> +++ b/libavfilter/Makefile
> @@ -168,6 +168,7 @@ OBJS-$(CONFIG_OWDENOISE_FILTER)              += vf_owdenoise.o
>  OBJS-$(CONFIG_PAD_FILTER)                    += vf_pad.o
>  OBJS-$(CONFIG_PERMS_FILTER)                  += f_perms.o
>  OBJS-$(CONFIG_PERSPECTIVE_FILTER)            += vf_perspective.o
> +OBJS-$(CONFIG_PHASE_FILTER)                  += vf_phase.o
>  OBJS-$(CONFIG_PIXDESCTEST_FILTER)            += vf_pixdesctest.o
>  OBJS-$(CONFIG_PP_FILTER)                     += vf_pp.o
>  OBJS-$(CONFIG_PSNR_FILTER)                   += vf_psnr.o dualinput.o
> diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c
> index bcebcfc..b1792bf 100644
> --- a/libavfilter/allfilters.c
> +++ b/libavfilter/allfilters.c
> @@ -163,6 +163,7 @@ void avfilter_register_all(void)
>      REGISTER_FILTER(PAD,            pad,            vf);
>      REGISTER_FILTER(PERMS,          perms,          vf);
>      REGISTER_FILTER(PERSPECTIVE,    perspective,    vf);
> +    REGISTER_FILTER(PHASE,          phase,          vf);
>      REGISTER_FILTER(PIXDESCTEST,    pixdesctest,    vf);
>      REGISTER_FILTER(PP,             pp,             vf);
>      REGISTER_FILTER(PSNR,           psnr,           vf);
> diff --git a/libavfilter/version.h b/libavfilter/version.h
> index 20ff257..cdae706 100644
> --- a/libavfilter/version.h
> +++ b/libavfilter/version.h
> @@ -30,8 +30,8 @@
>  #include "libavutil/avutil.h"
>  
>  #define LIBAVFILTER_VERSION_MAJOR  3
> -#define LIBAVFILTER_VERSION_MINOR  82
> -#define LIBAVFILTER_VERSION_MICRO 102
> +#define LIBAVFILTER_VERSION_MINOR  83
> +#define LIBAVFILTER_VERSION_MICRO 100
>  
>  #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
>                                                 LIBAVFILTER_VERSION_MINOR, \
> diff --git a/libavfilter/vf_phase.c b/libavfilter/vf_phase.c
> new file mode 100644
> index 0000000..66a387d
> --- /dev/null
> +++ b/libavfilter/vf_phase.c
> @@ -0,0 +1,313 @@
> +/*
> + * Copyright (c) 2004 Ville Saari
> + *
> + * This file is part of FFmpeg.
> + *
> + * FFmpeg is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public
> + * License as published by the Free Software Foundation; either
> + * version 2 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 General Public License along
> + * with FFmpeg; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> + */
> +
> +#include "libavutil/avassert.h"
> +#include "libavutil/imgutils.h"
> +#include "libavutil/pixdesc.h"
> +#include "libavutil/opt.h"
> +#include "avfilter.h"
> +#include "formats.h"
> +#include "internal.h"
> +#include "video.h"
> +
> +enum PhaseMode {
> +    PROGRESSIVE,
> +    TOP_FIRST,
> +    BOTTOM_FIRST,
> +    TOP_FIRST_ANALYZE,
> +    BOTTOM_FIRST_ANALYZE,
> +    ANALYZE,
> +    FULL_ANALYZE,
> +    AUTO,
> +    AUTO_ANALYZE
> +};
> +
> +typedef struct PhaseContext {
> +    const AVClass *class;
> +    enum PhaseMode mode;
> +    AVFrame *frame;
> +    int nb_planes;
> +    int planeheight[4];

> +    int stride[4];

nit++: linesize for internal consistency

> +} PhaseContext;
> +
> +#define OFFSET(x) offsetof(PhaseContext, x)
> +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
> +
> +static const AVOption phase_options[] = {
> +    { "mode", "set phase mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=AUTO_ANALYZE}, PROGRESSIVE, AUTO_ANALYZE, FLAGS, "mode" },
> +    { "p", "progressive", 0, AV_OPT_TYPE_CONST, {.i64=PROGRESSIVE}, 0, 0, FLAGS, "mode" },
> +    { "t", "top first", 0, AV_OPT_TYPE_CONST, {.i64=TOP_FIRST}, 0, 0, FLAGS, "mode" },
> +    { "b", "bottom first", 0, AV_OPT_TYPE_CONST, {.i64=BOTTOM_FIRST}, 0, 0, FLAGS, "mode" },
> +    { "T", "top first analyze", 0, AV_OPT_TYPE_CONST, {.i64=TOP_FIRST_ANALYZE}, 0, 0, FLAGS, "mode" },
> +    { "B", "bottom first analyze", 0, AV_OPT_TYPE_CONST, {.i64=BOTTOM_FIRST_ANALYZE}, 0, 0, FLAGS, "mode" },
> +    { "u", "analyze", 0, AV_OPT_TYPE_CONST, {.i64=ANALYZE}, 0, 0, FLAGS, "mode" },
> +    { "U", "full analyze", 0, AV_OPT_TYPE_CONST, {.i64=FULL_ANALYZE}, 0, 0, FLAGS, "mode" },
> +    { "a", "auto", 0, AV_OPT_TYPE_CONST, {.i64=AUTO}, 0, 0, FLAGS, "mode" },
> +    { "A", "auto analyze", 0, AV_OPT_TYPE_CONST, {.i64=AUTO_ANALYZE}, 0, 0, FLAGS, "mode" },
> +    { NULL }
> +};
> +
> +AVFILTER_DEFINE_CLASS(phase);
> +
> +static int query_formats(AVFilterContext *ctx)
> +{
> +    static const enum AVPixelFormat pix_fmts[] = {
> +        AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA420P,
> +        AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_YUVJ422P,AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ411P,
> +        AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P,
> +        AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE
> +    };
> +
> +    ff_set_common_formats(ctx, ff_make_format_list(pix_fmts));
> +    return 0;
> +}
> +
> +static int config_input(AVFilterLink *inlink)
> +{
> +    PhaseContext *s = inlink->dst->priv;
> +    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
> +    int ret;
> +
> +    if ((ret = av_image_fill_linesizes(s->stride, inlink->format, inlink->w)) < 0)
> +        return ret;
> +
> +    s->planeheight[1] = s->planeheight[2] = FF_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
> +    s->planeheight[0] = s->planeheight[3] = inlink->h;
> +
> +    s->nb_planes = av_pix_fmt_count_planes(inlink->format);
> +
> +    return 0;
> +}
> +
> +/*
> + * This macro interpolates the value of both fields at a point halfway
> + * between lines and takes the squared difference. In field resolution
> + * the point is a quarter pixel below a line in one field and a quarter
> + * pixel above a line in other.
> + *
> + * (The result is actually multiplied by 25)
> + */
> +#define DIFF(a, as, b, bs) (t = ((*a - b[bs]) << 2) + a[as << 1] - b[-bs], t * t)
> +
> +/*
> + * Find which field combination has the smallest average squared difference
> + * between the fields.
> + */
> +static enum PhaseMode analyze_plane(AVFilterContext *ctx, PhaseContext *s, AVFrame *old, AVFrame *new)
> +{
[...]

Should be fine assuming that it's bit identical with mp=phase.

Looks fine otherwise, but please wait one day so I can have a more
indepth look at the algorithm.
-- 
FFmpeg = Frightening and Fundamentalist Moronic Portentous Elaborated Gladiator


More information about the ffmpeg-devel mailing list