Commit 443c9fab authored by Paul B Mahol's avatar Paul B Mahol

avfilter/vf_gblur: add sigmaV option, different vertical filtering

Signed-off-by: 's avatarPaul B Mahol <onemda@gmail.com>
parent 445522c0
...@@ -8259,13 +8259,17 @@ The filter accepts the following options: ...@@ -8259,13 +8259,17 @@ The filter accepts the following options:
@table @option @table @option
@item sigma @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 @item steps
Set number of steps for Gaussian approximation. Defauls is @code{1}. Set number of steps for Gaussian approximation. Defauls is @code{1}.
@item planes @item planes
Set which planes to filter. By default all planes are filtered. 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 @end table
@section geq @section geq
......
...@@ -37,6 +37,7 @@ typedef struct GBlurContext { ...@@ -37,6 +37,7 @@ typedef struct GBlurContext {
const AVClass *class; const AVClass *class;
float sigma; float sigma;
float sigmaV;
int steps; int steps;
int planes; int planes;
...@@ -45,8 +46,11 @@ typedef struct GBlurContext { ...@@ -45,8 +46,11 @@ typedef struct GBlurContext {
int planeheight[4]; int planeheight[4];
float *buffer; float *buffer;
float boundaryscale; float boundaryscale;
float boundaryscaleV;
float postscale; float postscale;
float postscaleV;
float nu; float nu;
float nuV;
int nb_planes; int nb_planes;
} GBlurContext; } GBlurContext;
...@@ -57,6 +61,7 @@ static const AVOption gblur_options[] = { ...@@ -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 }, { "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 }, { "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 }, { "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 } { NULL }
}; };
...@@ -111,10 +116,10 @@ static int filter_vertically(AVFilterContext *ctx, void *arg, int jobnr, int nb_ ...@@ -111,10 +116,10 @@ static int filter_vertically(AVFilterContext *ctx, void *arg, int jobnr, int nb_
const int width = td->width; const int width = td->width;
const int slice_start = (width * jobnr ) / nb_jobs; const int slice_start = (width * jobnr ) / nb_jobs;
const int slice_end = (width * (jobnr+1)) / 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 numpixels = width * height;
const int steps = s->steps; const int steps = s->steps;
const float nu = s->nu; const float nu = s->nuV;
float *buffer = s->buffer; float *buffer = s->buffer;
int i, x, step; int i, x, step;
float *ptr; float *ptr;
...@@ -150,7 +155,7 @@ static int filter_postscale(AVFilterContext *ctx, void *arg, int jobnr, int nb_j ...@@ -150,7 +155,7 @@ static int filter_postscale(AVFilterContext *ctx, void *arg, int jobnr, int nb_j
const int64_t numpixels = width * height; const int64_t numpixels = width * height;
const int slice_start = (numpixels * jobnr ) / nb_jobs; const int slice_start = (numpixels * jobnr ) / nb_jobs;
const int slice_end = (numpixels * (jobnr+1)) / 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; float *buffer = s->buffer;
int i; int i;
...@@ -220,25 +225,35 @@ static int config_input(AVFilterLink *inlink) ...@@ -220,25 +225,35 @@ static int config_input(AVFilterLink *inlink)
s->buffer = av_malloc_array(inlink->w, inlink->h * sizeof(*s->buffer)); s->buffer = av_malloc_array(inlink->w, inlink->h * sizeof(*s->buffer));
if (!s->buffer) if (!s->buffer)
return AVERROR(ENOMEM); return AVERROR(ENOMEM);
if (s->sigmaV < 0) {
s->sigmaV = s->sigma;
}
return 0; 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) static int filter_frame(AVFilterLink *inlink, AVFrame *in)
{ {
AVFilterContext *ctx = inlink->dst; AVFilterContext *ctx = inlink->dst;
GBlurContext *s = ctx->priv; GBlurContext *s = ctx->priv;
AVFilterLink *outlink = ctx->outputs[0]; AVFilterLink *outlink = ctx->outputs[0];
double dnu, lambda;
float sigma = s->sigma;
int steps = s->steps;
AVFrame *out; AVFrame *out;
int plane; int plane;
lambda = (sigma * sigma) / (2.0 * steps); set_params(s->sigma, s->steps, &s->postscale, &s->boundaryscale, &s->nu);
dnu = (1.0 + 2.0 * lambda - sqrt(1.0 + 4.0 * lambda)) / (2.0 * lambda); set_params(s->sigmaV, s->steps, &s->postscaleV, &s->boundaryscaleV, &s->nuV);
s->postscale = pow(dnu / lambda, 2 * steps);
s->boundaryscale = 1.0 / (1.0 - dnu);
s->nu = (float)dnu;
if (av_frame_is_writable(in)) { if (av_frame_is_writable(in)) {
out = in; out = in;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment