[FFmpeg-devel] [PATCH] lavfi: add pp filter.
Stefano Sabatini
stefasab at gmail.com
Wed Dec 12 13:18:55 CET 2012
On date Wednesday 2012-12-12 04:49:49 +0100, Clément Bœsch encoded:
> Ported from MPlayer. Original author is A'rpi, with various
> contributions from Michael Niedermayer. The original documentation was
> mostly written by Diego Biurrun. See the MPlayer history for full
> credits.
>
> The filter is under GPL like the original filter, even if it differs
> quite a lot. There is not much point in making it LGPL since pp is under
> GPL.
>
> TODO: fix FATE
> TODO: bump minor
> TODO: Changelog
> ---
> Some insight about current FATE failure: the 3 first pp tests fail because of a
> mismatch between linesize and width (for the chroma planes), which is not
> present with mp=pp, where linesize==width all the time for some reason. It
> might be a bug in libpostproc, but I need someone familiar with it to confirm
> this.
>
> A quick and dirty hack to make linesize and width match for the fate test is to
> change the av_image_alloc from 32 to 16 in lavfi/video.c. Of course this is not
> a solution, but it's useful for testing purpose since this change allow to pass
> all the pp FATE tests.
> ---
> LICENSE | 1 +
> configure | 1 +
> doc/filters.texi | 164 ++++++++++++++++++++++++++++++++++++++++++++
> libavfilter/Makefile | 1 +
> libavfilter/allfilters.c | 1 +
> libavfilter/vf_pp.c | 169 ++++++++++++++++++++++++++++++++++++++++++++++
> tests/lavfi-regression.sh | 12 ++--
> 7 files changed, 343 insertions(+), 6 deletions(-)
> create mode 100644 libavfilter/vf_pp.c
>
> diff --git a/LICENSE b/LICENSE
> index a1204f4..d083e56 100644
> --- a/LICENSE
> +++ b/LICENSE
> @@ -34,6 +34,7 @@ Specifically, the GPL parts of FFmpeg are
> - vf_hqdn3d.c
> - vf_hue.c
> - vf_mp.c
> + - vf_pp.c
> - vf_smartblur.c
> - vf_super2xsai.c
> - vf_tinterlace.c
> diff --git a/configure b/configure
> index 7f3202e..4c30e63 100755
> --- a/configure
> +++ b/configure
> @@ -1987,6 +1987,7 @@ negate_filter_deps="lut_filter"
> resample_filter_deps="avresample"
> ocv_filter_deps="libopencv"
> pan_filter_deps="swresample"
> +pp_filter_deps="gpl"
> removelogo_filter_deps="avcodec avformat swscale"
> scale_filter_deps="swscale"
> smartblur_filter_deps="gpl swscale"
> diff --git a/doc/filters.texi b/doc/filters.texi
> index b840cac..9e89dd0 100644
> --- a/doc/filters.texi
> +++ b/doc/filters.texi
> @@ -3301,6 +3301,170 @@ format=monow, pixdesctest
>
> can be used to test the monowhite pixel format descriptor definition.
>
> + at section pp
> +
> +Enables the specified chain of postprocessing subfilters using libpostproc.
Nit: "Enable" for overall consistency.
Also mention that this needs libpostproc to be enabled (mentioning
--enable-gpl may also avoid some user complaints).
> +Subfilters must be separated by '/' and can be disabled by prepending a '-'.
> +Each subfilter and some options have a short and a long name that can be used
> +interchangeably, i.e. dr/dering are the same.
Missing description of how to specify options.
> +All subfilters share common options to determine their scope:
I believe that libpp parameters/library deserve a dedicated document
(for the same reason libswresample/libswscale parameters should not be
documented in filters.texi).
> +
> + at table @option
> + at item a/autoq
> +Automatically switch the subfilter off if the CPU is too slow.
> +
> + at item c/chrom
> +Do chrominance filtering, too (default).
> +
> + at item y/nochrom
> +Do luminance filtering only (no chrominance).
> +
> + at item n/noluma
> +Do chrominance filtering only (no luminance).
> + at end table
> +
> +Available subfilters are:
> +
> + at table @option
> + at item hb/hdeblock[:difference[:flatness]]
> +Horizontal deblocking filter
> + at table @option
> + at item difference
> +Difference factor where higher values mean more deblocking (default: @code{32}).
> + at item flatness
> +Flatness threshold where lower values mean more deblocking (default: @code{39}).
> + at end table
> +
> + at item vb/vdeblock[:difference[:flatness]]
> +Vertical deblocking filter
> + at table @option
> + at item difference
> +Difference factor where higher values mean more deblocking (default: @code{32}).
> + at item flatness
> +Flatness threshold where lower values mean more deblocking (default: @code{39}).
> + at end table
> +
> + at item ha/hadeblock[:difference[:flatness]]
> +Accurate horizontal deblocking filter
> + at table @option
> + at item difference
> +Difference factor where higher values mean more deblocking (default: @code{32}).
> + at item flatness
> +Flatness threshold where lower values mean more deblocking (default: @code{39}).
> + at end table
> +
> + at item va/vadeblock[:difference[:flatness]]
> +Accurate vertical deblocking filter
> + at table @option
> + at item difference
> +Difference factor where higher values mean more deblocking (default: @code{32}).
> + at item flatness
> +Flatness threshold where lower values mean more deblocking (default: @code{39}).
> + at end table
> + at end table
> +
> +The horizontal and vertical deblocking filters share the difference and
> +flatness values so you cannot set different horizontal and vertical
> +thresholds.
> +
> + at table @option
> + at item h1/x1hdeblock
> +Experimental horizontal deblocking filter
> +
> + at item v1/x1vdeblock
> +Experimental vertical deblocking filter
> +
> + at item dr/dering
> +Deringing filter
> +
> + at item tn/tmpnoise[:threshold1[:threshold2[:threshold3]]], temporal noise reducer
> + at table @option
> + at item threshold1
> +larger -> stronger filtering
> + at item threshold2
> +larger -> stronger filtering
> + at item threshold3
> +larger -> stronger filtering
> + at end table
> +
> + at item al/autolevels[:f/fullyrange], automatic brightness / contrast correction
> + at table @option
> + at item f/fullyrange
> +Stretch luminance to @code{0-255}.
> + at end table
> +
> + at item lb/linblenddeint
> +Linear blend deinterlacing filter that deinterlaces the given block by
> +filtering all lines with a @code{(1 2 1)} filter.
> +
> + at item li/linipoldeint
> +Linear interpolating deinterlacing filter that deinterlaces the given block by
> +linearly interpolating every second line.
> +
> + at item ci/cubicipoldeint
> +Cubic interpolating deinterlacing filter deinterlaces the given block by
> +cubically interpolating every second line.
> +
> + at item md/mediandeint
> +Median deinterlacing filter that deinterlaces the given block by applying a
> +median filter to every second line.
> +
> + at item fd/ffmpegdeint
> +FFmpeg deinterlacing filter that deinterlaces the given block by filtering every
> +second line with a @code{(-1 4 2 4 -1)} filter.
> +
> + at item l5/lowpass5
> +Vertically applied FIR lowpass deinterlacing filter that deinterlaces the given
> +block by filtering all lines with a @code{(-1 2 6 2 -1)} filter.
> +
> + at item fq/forceQuant[:quantizer]
> +Overrides the quantizer table from the input with the constant quantizer you
> +specify.
> + at table @option
> + at item quantizer
> +Quantizer to use
> + at end table
> +
> + at item de/default
> +Default pp filter combination (@code{hb:a,vb:a,dr:a})
> +
> + at item fa/fast
> +Fast pp filter combination (@code{h1:a,v1:a,dr:a})
> +
> + at item ac
> +High quality pp filter combination (@code{ha:a:128:7,va:a,dr:a})
> + at end table
> +
> + at subsection Examples
> +
> + at itemize
> + at item
> +Horizontal and vertical deblocking, deringing and automatic brightness/contrast:
> + at example
> +-vf pp=hb/vb/dr/al
> + at end example
Note: we usually omit the -vf part, and for good reasons, since
filters.texi is not meant to be bound to ff* tools syntax.
> +
> + at item
> +Default filters without brightness/contrast correction:
> + at example
> +-vf pp=de/-al
> + at end example
> +
> + at item
> +Enable default filters & temporal denoiser:
> + at example
> +-vf pp=default/tmpnoise:1:2:3
> + at end example
> +
> + at item
> +Horizontal deblocking on luminance only and switch vertical deblocking on or
The verb missing.
> +off automatically depending on available CPU time:
> + at example
> +-vf pp=hb:y/vb:a
> + at end example
> + at end itemize
> +
> @section removelogo
>
> Suppress a TV station logo, using an image file to determine which
> diff --git a/libavfilter/Makefile b/libavfilter/Makefile
> index 191e3e1..dddcd6f 100644
> --- a/libavfilter/Makefile
> +++ b/libavfilter/Makefile
> @@ -122,6 +122,7 @@ OBJS-$(CONFIG_OCV_FILTER) += vf_libopencv.o
> OBJS-$(CONFIG_OVERLAY_FILTER) += vf_overlay.o
> OBJS-$(CONFIG_PAD_FILTER) += vf_pad.o
> OBJS-$(CONFIG_PIXDESCTEST_FILTER) += vf_pixdesctest.o
> +OBJS-$(CONFIG_PP_FILTER) += vf_pp.o
> OBJS-$(CONFIG_REMOVELOGO_FILTER) += bbox.o lswsutils.o lavfutils.o vf_removelogo.o
> OBJS-$(CONFIG_SCALE_FILTER) += vf_scale.o
> OBJS-$(CONFIG_SELECT_FILTER) += vf_select.o
> diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c
> index ffde5ce..c100de4 100644
> --- a/libavfilter/allfilters.c
> +++ b/libavfilter/allfilters.c
> @@ -114,6 +114,7 @@ void avfilter_register_all(void)
> REGISTER_FILTER (OVERLAY, overlay, vf);
> REGISTER_FILTER (PAD, pad, vf);
> REGISTER_FILTER (PIXDESCTEST, pixdesctest, vf);
> + REGISTER_FILTER (PP, pp, vf);
> REGISTER_FILTER (REMOVELOGO, removelogo, vf);
> REGISTER_FILTER (SCALE, scale, vf);
> REGISTER_FILTER (SELECT, select, vf);
> diff --git a/libavfilter/vf_pp.c b/libavfilter/vf_pp.c
> new file mode 100644
> index 0000000..32b0674
> --- /dev/null
> +++ b/libavfilter/vf_pp.c
> @@ -0,0 +1,169 @@
> +/*
> + * Copyright (c) 2002 A'rpi
> + * Copyright (C) 2012 Clément Bœsch
> + *
> + * 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.
> + */
> +
> +/**
> + * @file
> + * libpostproc filter, ported from MPlayer.
> + */
> +
> +#include "libavutil/avassert.h"
> +#include "libavutil/opt.h"
> +#include "internal.h"
> +
> +#include "libpostproc/postprocess.h"
> +
> +typedef struct {
> + int mode_id;
> + pp_mode *modes[PP_QUALITY_MAX + 1];
> + void *pp_ctx;
> +} PPFilterContext;
> +
> +static av_cold int pp_init(AVFilterContext *ctx, const char *args)
> +{
> + int i;
> + PPFilterContext *pp = ctx->priv;
> +
> + if (!args || !*args)
> + args = "de";
> +
> + for (i = 0; i <= PP_QUALITY_MAX; i++) {
> + pp->modes[i] = pp_get_mode_by_name_and_quality(args, i);
> + if (!pp->modes[i])
> + return AVERROR_EXTERNAL;
> + }
> + pp->mode_id = PP_QUALITY_MAX;
> + return 0;
Not blocking, but maybe we can think about adding support for
options. For example it may be useful to be able to set quality.
> +}
> +
> +static int pp_process_command(AVFilterContext *ctx, const char *cmd, const char *args,
> + char *res, int res_len, int flags)
> +{
> + PPFilterContext *pp = ctx->priv;
> +
> + if (!strcmp(cmd, "quality")) {
> + pp->mode_id = av_clip(strtol(args, NULL, 10), 0, PP_QUALITY_MAX);
> + return 0;
> + }
> + return AVERROR(ENOSYS);
> +}
> +
> +static int pp_query_formats(AVFilterContext *ctx)
> +{
> + static const enum PixelFormat pix_fmts[] = {
> + AV_PIX_FMT_YUV420P,
> + AV_PIX_FMT_YUV422P,
> + AV_PIX_FMT_YUV411P,
> + AV_PIX_FMT_YUV444P,
> + AV_PIX_FMT_NONE
> + };
> + ff_set_common_formats(ctx, ff_make_format_list(pix_fmts));
> + return 0;
> +}
> +
> +static int pp_config_props(AVFilterLink *inlink)
> +{
> + int flags = PP_CPU_CAPS_AUTO;
> + PPFilterContext *pp = inlink->dst->priv;
> +
> + switch (inlink->format) {
> + case AV_PIX_FMT_YUV420P: flags |= PP_FORMAT_420; break;
> + case AV_PIX_FMT_YUV422P: flags |= PP_FORMAT_422; break;
> + case AV_PIX_FMT_YUV411P: flags |= PP_FORMAT_411; break;
> + case AV_PIX_FMT_YUV444P: flags |= PP_FORMAT_444; break;
> + default: av_assert0(0);
> + }
> +
> + pp->pp_ctx = pp_get_context(inlink->w, inlink->h, flags);
> + if (!pp->pp_ctx)
> + return AVERROR(ENOMEM);
> + return 0;
> +}
> +
> +static int pp_filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in)
I hate too generic variable names (in... inlink? inframe? inpad?) as
they harm readability and slow me down when reading code.
> +{
> + AVFilterContext *ctx = inlink->dst;
> + PPFilterContext *pp = ctx->priv;
> + AVFilterLink *outlink = ctx->outputs[0];
> + const int aligned_w = FFALIGN(outlink->w, 8);
> + const int aligned_h = FFALIGN(outlink->h, 8);
> + AVFilterBufferRef *out;
> +
> + out = ff_get_video_buffer(outlink, AV_PERM_WRITE, aligned_w, aligned_h);
> + if (!out) {
> + avfilter_unref_buffer(in);
> + return AVERROR(ENOMEM);
> + }
> + avfilter_copy_buffer_ref_props(out, in);
> +
> + pp_postprocess((const uint8_t **)in->data, in->linesize,
> + out->data, out->linesize,
> + aligned_w, outlink->h,
> + out->video->qp_table,
> + out->video->qp_table_linesize,
> + pp->modes[pp->mode_id],
> + pp->pp_ctx,
> + out->video->pict_type);
> +
> + avfilter_unref_buffer(in);
> + return ff_filter_frame(outlink, out);
> +}
> +
> +static av_cold void pp_uninit(AVFilterContext *ctx)
> +{
> + int i;
> + PPFilterContext *pp = ctx->priv;
> +
> + for (i = 0; i <= PP_QUALITY_MAX; i++)
> + pp_free_mode(pp->modes[i]);
> + if (pp->pp_ctx)
> + pp_free_context(pp->pp_ctx);
> +}
> +
> +static const AVFilterPad pp_inputs[] = {
> + {
> + .name = "default",
> + .type = AVMEDIA_TYPE_VIDEO,
> + .config_props = pp_config_props,
> + .filter_frame = pp_filter_frame,
> + .min_perms = AV_PERM_READ,
> + },
> + { NULL }
> +};
> +
> +static const AVFilterPad pp_outputs[] = {
> + {
> + .name = "default",
> + .type = AVMEDIA_TYPE_VIDEO,
> + },
> + { NULL }
> +};
> +
> +AVFilter avfilter_vf_pp = {
> + .name = "pp",
> + .description = NULL_IF_CONFIG_SMALL("filter video using libpostproc"),
"Filter video ... libpostproc."
[...]
--
FFmpeg = Fantastic and Freak Multimedia Problematic Erotic Gem
More information about the ffmpeg-devel
mailing list