From 443c9fab57fababd864dc13f7bdc16b330cbd481 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 4 Sep 2016 23:57:09 +0200 Subject: [PATCH] avfilter/vf_gblur: add sigmaV option, different vertical filtering Signed-off-by: Paul B Mahol --- doc/filters.texi | 6 +++++- libavfilter/vf_gblur.c | 37 ++++++++++++++++++++++++++----------- 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 14a67505a7..99f07a6337 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -8259,13 +8259,17 @@ The filter accepts the following options: @table @option @item sigma -Set sigma, standard deviation of Gaussian blur. Default is @code{0.5}. +Set horizontal sigma, standard deviation of Gaussian blur. Default is @code{0.5}. @item steps Set number of steps for Gaussian approximation. Defauls is @code{1}. @item planes Set which planes to filter. By default all planes are filtered. + +@item sigmaV +Set vertical sigma, if negative it will be same as @code{sigma}. +Default is @code{-1}. @end table @section geq diff --git a/libavfilter/vf_gblur.c b/libavfilter/vf_gblur.c index e289f6933f..27b702998e 100644 --- a/libavfilter/vf_gblur.c +++ b/libavfilter/vf_gblur.c @@ -37,6 +37,7 @@ typedef struct GBlurContext { const AVClass *class; float sigma; + float sigmaV; int steps; int planes; @@ -45,8 +46,11 @@ typedef struct GBlurContext { int planeheight[4]; float *buffer; float boundaryscale; + float boundaryscaleV; float postscale; + float postscaleV; float nu; + float nuV; int nb_planes; } GBlurContext; @@ -57,6 +61,7 @@ static const AVOption gblur_options[] = { { "sigma", "set sigma", OFFSET(sigma), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, 0.0, 1024, FLAGS }, { "steps", "set number of steps", OFFSET(steps), AV_OPT_TYPE_INT, {.i64=1}, 1, 6, FLAGS }, { "planes", "set planes to filter", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=0xF}, 0, 0xF, FLAGS }, + { "sigmaV", "set vertical sigma", OFFSET(sigmaV), AV_OPT_TYPE_FLOAT, {.dbl=-1}, -1, 1024, FLAGS }, { NULL } }; @@ -111,10 +116,10 @@ static int filter_vertically(AVFilterContext *ctx, void *arg, int jobnr, int nb_ const int width = td->width; const int slice_start = (width * jobnr ) / nb_jobs; const int slice_end = (width * (jobnr+1)) / nb_jobs; - const float boundaryscale = s->boundaryscale; + const float boundaryscale = s->boundaryscaleV; const int numpixels = width * height; const int steps = s->steps; - const float nu = s->nu; + const float nu = s->nuV; float *buffer = s->buffer; int i, x, step; float *ptr; @@ -150,7 +155,7 @@ static int filter_postscale(AVFilterContext *ctx, void *arg, int jobnr, int nb_j const int64_t numpixels = width * height; const int slice_start = (numpixels * jobnr ) / nb_jobs; const int slice_end = (numpixels * (jobnr+1)) / nb_jobs; - const float postscale = s->postscale; + const float postscale = s->postscale * s->postscaleV; float *buffer = s->buffer; int i; @@ -220,25 +225,35 @@ static int config_input(AVFilterLink *inlink) s->buffer = av_malloc_array(inlink->w, inlink->h * sizeof(*s->buffer)); if (!s->buffer) return AVERROR(ENOMEM); + + if (s->sigmaV < 0) { + s->sigmaV = s->sigma; + } + return 0; } +static void set_params(float sigma, int steps, float *postscale, float *boundaryscale, float *nu) +{ + double dnu, lambda; + + lambda = (sigma * sigma) / (2.0 * steps); + dnu = (1.0 + 2.0 * lambda - sqrt(1.0 + 4.0 * lambda)) / (2.0 * lambda); + *postscale = pow(dnu / lambda, steps); + *boundaryscale = 1.0 / (1.0 - dnu); + *nu = (float)dnu; +} + static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; GBlurContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; - double dnu, lambda; - float sigma = s->sigma; - int steps = s->steps; AVFrame *out; int plane; - lambda = (sigma * sigma) / (2.0 * steps); - dnu = (1.0 + 2.0 * lambda - sqrt(1.0 + 4.0 * lambda)) / (2.0 * lambda); - s->postscale = pow(dnu / lambda, 2 * steps); - s->boundaryscale = 1.0 / (1.0 - dnu); - s->nu = (float)dnu; + set_params(s->sigma, s->steps, &s->postscale, &s->boundaryscale, &s->nu); + set_params(s->sigmaV, s->steps, &s->postscaleV, &s->boundaryscaleV, &s->nuV); if (av_frame_is_writable(in)) { out = in;