avfilter/vf_gblur: add sigmaV option, different vertical filtering
Signed-off-by: Paul B Mahol <onemda@gmail.com>
This commit is contained in:
parent
445522c01b
commit
443c9fab57
@ -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 {
|
|||||||
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 {
|
|||||||
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[] = {
|
|||||||
{ "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_
|
|||||||
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
|
|||||||
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)
|
|||||||
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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user