[FFmpeg-devel] [PATCH] avfilter: add morpho filter
Lynne
dev at lynne.ee
Mon Sep 20 23:00:31 EEST 2021
Sep 20, 2021, 19:33 by onemda at gmail.com:
> Signed-off-by: Paul B Mahol <onemda at gmail.com>
> ---
> doc/filters.texi | 32 ++
> libavfilter/Makefile | 1 +
> libavfilter/allfilters.c | 1 +
> libavfilter/vf_morpho.c | 865 +++++++++++++++++++++++++++++++++++++++
> 4 files changed, 899 insertions(+)
> create mode 100644 libavfilter/vf_morpho.c
>
> diff --git a/doc/filters.texi b/doc/filters.texi
> index 0c45fb710d..b46556c12c 100644
> --- a/doc/filters.texi
> +++ b/doc/filters.texi
> @@ -10225,6 +10225,7 @@ A number representing position of the first frame with respect to the telecine
> pattern. This is to be used if the stream is cut. The default value is @code{0}.
> @end table
>
> + at anchor{dilation}
> @section dilation
>
> Apply dilation effect to the video.
> @@ -11541,6 +11542,7 @@ value.
>
> @end table
>
> + at anchor{erosion}
> @section erosion
>
> Apply erosion effect to the video.
> @@ -15316,6 +15318,36 @@ Default value is 0.
>
> This filter supports the all above options as @ref{commands}.
>
> + at section morpho
> +
> +This filter allows to apply main morphological grayscale transforms,
> +erode and dilate with arbitrary structures set in second input stream.
> +
> +Unlike naive implementation and much slower performance in @ref{erosion}
> +and @ref{dilation} filters, when speed is critical @code{morpho} filter
> +should be used instead.
> +
> +A description of accepted options follows,
> +
> + at table @option
> + at item mode
> +Set morphological transform to apply, can be @code{erode} or @code{dilate}.
> +Default is @code{erode}.
> +
> + at item planes
> +Set planes to filter, by default all planes except alpha are filtered.
> +
> + at item structure
> +Set which structure video frames will be processed from second input stream,
> +can be @var{first} or @var{all}. Default is @var{all}.
> + at end table
> +
> +The @code{morpho} filter also supports the @ref{framesync} options.
> +
> + at subsection Commands
> +
> +This filter supports same @ref{commands} as options.
> +
> @section mpdecimate
>
> Drop frames that do not differ greatly from the previous frame in
> diff --git a/libavfilter/Makefile b/libavfilter/Makefile
> index 272f876c07..06e01da38e 100644
> --- a/libavfilter/Makefile
> +++ b/libavfilter/Makefile
> @@ -350,6 +350,7 @@ OBJS-$(CONFIG_MIDEQUALIZER_FILTER) += vf_midequalizer.o framesync.o
> OBJS-$(CONFIG_MINTERPOLATE_FILTER) += vf_minterpolate.o motion_estimation.o
> OBJS-$(CONFIG_MIX_FILTER) += vf_mix.o framesync.o
> OBJS-$(CONFIG_MONOCHROME_FILTER) += vf_monochrome.o
> +OBJS-$(CONFIG_MORPHO_FILTER) += vf_morpho.o
> OBJS-$(CONFIG_MPDECIMATE_FILTER) += vf_mpdecimate.o
> OBJS-$(CONFIG_NEGATE_FILTER) += vf_lut.o
> OBJS-$(CONFIG_NLMEANS_FILTER) += vf_nlmeans.o
> diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c
> index 1283d124b8..10dfe72131 100644
> --- a/libavfilter/allfilters.c
> +++ b/libavfilter/allfilters.c
> @@ -335,6 +335,7 @@ extern const AVFilter ff_vf_midequalizer;
> extern const AVFilter ff_vf_minterpolate;
> extern const AVFilter ff_vf_mix;
> extern const AVFilter ff_vf_monochrome;
> +extern const AVFilter ff_vf_morpho;
> extern const AVFilter ff_vf_mpdecimate;
> extern const AVFilter ff_vf_msad;
> extern const AVFilter ff_vf_negate;
> diff --git a/libavfilter/vf_morpho.c b/libavfilter/vf_morpho.c
> new file mode 100644
> index 0000000000..46c641c4b9
> --- /dev/null
> +++ b/libavfilter/vf_morpho.c
> @@ -0,0 +1,865 @@
> +/*
> + * Copyright (c) 2016 ReneBrals
> + * Copyright (c) 2021 Paul B Mahol
> + *
> + * This file is part of FFmpeg.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in all
> + * copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> + * SOFTWARE.
> + */
> +
> +#include "avfilter.h"
> +#include "formats.h"
> +#include "internal.h"
> +#include "libavutil/intreadwrite.h"
> +#include "libavutil/imgutils.h"
> +#include "libavutil/opt.h"
> +#include "libavutil/pixdesc.h"
> +#include "video.h"
> +#include "framesync.h"
> +
> +typedef struct IPlane {
> + uint8_t **img;
> + size_t W;
> + size_t H;
> + size_t range;
> + int type_size;
> +
> + void (*max)(uint8_t *c, uint8_t *a, uint8_t *b, size_t x);
> + void (*min)(uint8_t *c, uint8_t *a, uint8_t *b, size_t x);
> + void (*max_in_place)(uint8_t *a, uint8_t *b, size_t x);
> + void (*min_in_place)(uint8_t *a, uint8_t *b, size_t x);
> +} IPlane;
> +
> +typedef struct LUT {
> + uint8_t ***arr;
> + int minR;
> + int maxR;
> + size_t I;
> + size_t X;
> + int padX;
> +} LUT;
> +
> +typedef struct chord {
> + int x;
> + int y;
> + int l;
> + int i;
> +} chord;
> +
> +typedef struct chordSet {
> + chord *C;
> + size_t size;
> + size_t cap;
> +
> + int *R;
> + size_t Lnum;
> +
> + int minX;
> + int maxX;
> + int minY;
> + int maxY;
> +} chordSet;
> +
> +typedef struct MorphoContext {
> + const AVClass *class;
> + FFFrameSync fs;
> +
> + chordSet SE[4];
> + IPlane SEimg[4];
> + IPlane g[4], f[4];
> + LUT Ty[4];
> +
> + int mode;
> + int planes;
> + int structures;
> +
> + int planewidth[4];
> + int planeheight[4];
> + int splanewidth[4];
> + int splaneheight[4];
> + int depth;
> + int type_size;
> + int nb_planes;
> +
> + int got_structure[4];
> +} MorphoContext;
> +
> +#define OFFSET(x) offsetof(MorphoContext, x)
> +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_RUNTIME_PARAM
> +
> +static const AVOption morpho_options[] = {
> + { "mode", "set morphological transform", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "mode" },
> + { "erode", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "mode" },
> + { "dilate", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "mode" },
> + { "planes", "set planes to filter", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=7}, 0, 15, FLAGS },
> + { "structure", "when to process structures", OFFSET(structures), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, "str" },
> + { "first", "process only first structure, ignore rest", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "str" },
> + { "all", "process all structure", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "str" },
> + { NULL }
> +};
> +
> +FRAMESYNC_DEFINE_CLASS(morpho, MorphoContext, fs);
> +
> +static int query_formats(AVFilterContext *ctx)
> +{
> + static const enum AVPixelFormat pix_fmts[] = {
> + AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV440P,
> + AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ440P,
> + AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUV420P,
> + AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ420P,
> + AV_PIX_FMT_YUVJ411P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P,
> + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY9,
> + AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9, AV_PIX_FMT_GBRP9,
> + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9,
> + AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10,
> + AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV440P12,
> + AV_PIX_FMT_YUV420P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV444P14,
> + AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16,
> + AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10,
> + AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA444P12,
> + AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16,
> + AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16,
> + AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16,
> + AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY12, AV_PIX_FMT_GRAY14, AV_PIX_FMT_GRAY16,
> + AV_PIX_FMT_NONE
> + };
> +
> + return ff_set_common_formats_from_list(ctx, pix_fmts);
> +}
> +
> +static void Min(uint8_t *c, uint8_t *a, uint8_t *b, size_t x)
> +{
> + for (size_t i = 0; i < x; i++)
> + c[i] = FFMIN(b[i], a[i]);
> +}
> +
> +static void MinInPlace(uint8_t *a, uint8_t *b, size_t x)
> +{
> + for (size_t i = 0; i < x; i++)
> + a[i] = FFMIN(a[i], b[i]);
> +}
> +
> +static void Max(uint8_t *c, uint8_t *a, uint8_t *b, size_t x)
> +{
> + for (size_t i = 0; i < x; i++)
> + c[i] = FFMAX(a[i], b[i]);
> +}
> +
> +static void MaxInPlace(uint8_t *a, uint8_t *b, size_t x)
> +{
> + for (size_t i = 0; i < x; i++)
> + a[i] = FFMAX(a[i], b[i]);
> +}
> +
> +static void Min16(uint8_t *cc, uint8_t *aa, uint8_t *bb, size_t x)
> +{
> + uint16_t *a = (uint16_t *)aa;
> + uint16_t *b = (uint16_t *)bb;
> + uint16_t *c = (uint16_t *)cc;
> +
> + for (size_t i = 0; i < x; i++)
> + c[i] = FFMIN(b[i], a[i]);
> +}
> +
> +static void MinInPlace16(uint8_t *aa, uint8_t *bb, size_t x)
> +{
> + uint16_t *a = (uint16_t *)aa;
> + uint16_t *b = (uint16_t *)bb;
> +
> + for (size_t i = 0; i < x; i++)
> + a[i] = FFMIN(a[i], b[i]);
> +}
> +
> +static void Max16(uint8_t *cc, uint8_t *aa, uint8_t *bb, size_t x)
> +{
> + uint16_t *a = (uint16_t *)aa;
> + uint16_t *b = (uint16_t *)bb;
> + uint16_t *c = (uint16_t *)cc;
> +
> + for (size_t i = 0; i < x; i++)
> + c[i] = FFMAX(a[i], b[i]);
> +}
> +
> +static void MaxInPlace16(uint8_t *aa, uint8_t *bb, size_t x)
> +{
> + uint16_t *a = (uint16_t *)aa;
> + uint16_t *b = (uint16_t *)bb;
> +
> + for (size_t i = 0; i < x; i++)
> + a[i] = FFMAX(a[i], b[i]);
> +}
>
Remove the pointless wrapper functions and remove the CamelCase
naming convention.
More information about the ffmpeg-devel
mailing list