|
|
|
@ -25,6 +25,7 @@ |
|
|
|
|
* Ported from MPlayer libmpcodecs/vf_smartblur.c by Michael Niedermayer. |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
#include "libavutil/opt.h" |
|
|
|
|
#include "libavutil/pixdesc.h" |
|
|
|
|
#include "libswscale/swscale.h" |
|
|
|
|
|
|
|
|
@ -50,6 +51,7 @@ typedef struct { |
|
|
|
|
} FilterParam; |
|
|
|
|
|
|
|
|
|
typedef struct { |
|
|
|
|
const AVClass *class; |
|
|
|
|
FilterParam luma; |
|
|
|
|
FilterParam chroma; |
|
|
|
|
int hsub; |
|
|
|
@ -57,63 +59,63 @@ typedef struct { |
|
|
|
|
unsigned int sws_flags; |
|
|
|
|
} SmartblurContext; |
|
|
|
|
|
|
|
|
|
#define CHECK_PARAM(param, name, min, max, format, ret) \ |
|
|
|
|
if (param < min || param > max) { \
|
|
|
|
|
av_log(ctx, AV_LOG_ERROR, \
|
|
|
|
|
"Invalid " #name " value " #format ": " \
|
|
|
|
|
"must be included between range " #format " and " #format "\n",\
|
|
|
|
|
param, min, max); \
|
|
|
|
|
ret = AVERROR(EINVAL); \
|
|
|
|
|
} |
|
|
|
|
#define OFFSET(x) offsetof(SmartblurContext, x) |
|
|
|
|
#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM |
|
|
|
|
|
|
|
|
|
static const AVOption smartblur_options[] = { |
|
|
|
|
{ "luma_radius", "set luma radius", OFFSET(luma.radius), AV_OPT_TYPE_FLOAT, {.dbl=1.0}, RADIUS_MIN, RADIUS_MAX, .flags=FLAGS }, |
|
|
|
|
{ "lr" , "set luma radius", OFFSET(luma.radius), AV_OPT_TYPE_FLOAT, {.dbl=1.0}, RADIUS_MIN, RADIUS_MAX, .flags=FLAGS }, |
|
|
|
|
{ "luma_strength", "set luma strength", OFFSET(luma.strength), AV_OPT_TYPE_FLOAT, {.dbl=1.0}, STRENGTH_MIN, STRENGTH_MAX, .flags=FLAGS }, |
|
|
|
|
{ "ls", "set luma strength", OFFSET(luma.strength), AV_OPT_TYPE_FLOAT, {.dbl=1.0}, STRENGTH_MIN, STRENGTH_MAX, .flags=FLAGS }, |
|
|
|
|
{ "luma_threshold", "set luma threshold", OFFSET(luma.threshold), AV_OPT_TYPE_INT, {.i64=0}, THRESHOLD_MIN, THRESHOLD_MAX, .flags=FLAGS }, |
|
|
|
|
{ "lt", "set luma threshold", OFFSET(luma.threshold), AV_OPT_TYPE_INT, {.i64=0}, THRESHOLD_MIN, THRESHOLD_MAX, .flags=FLAGS }, |
|
|
|
|
|
|
|
|
|
{ "chroma_radius", "set chroma radius", OFFSET(chroma.radius), AV_OPT_TYPE_FLOAT, {.dbl=RADIUS_MIN-1}, RADIUS_MIN-1, RADIUS_MAX, .flags=FLAGS }, |
|
|
|
|
{ "cr", "set chroma radius", OFFSET(chroma.radius), AV_OPT_TYPE_FLOAT, {.dbl=RADIUS_MIN-1}, RADIUS_MIN-1, RADIUS_MAX, .flags=FLAGS }, |
|
|
|
|
{ "chroma_strength", "set chroma strength", OFFSET(chroma.strength), AV_OPT_TYPE_FLOAT, {.dbl=STRENGTH_MIN-1}, STRENGTH_MIN-1, STRENGTH_MAX, .flags=FLAGS }, |
|
|
|
|
{ "cs", "set chroma strength", OFFSET(chroma.strength), AV_OPT_TYPE_FLOAT, {.dbl=STRENGTH_MIN-1}, STRENGTH_MIN-1, STRENGTH_MAX, .flags=FLAGS }, |
|
|
|
|
{ "chroma_threshold", "set chroma threshold", OFFSET(chroma.threshold), AV_OPT_TYPE_INT, {.i64=THRESHOLD_MIN-1}, THRESHOLD_MIN-1, THRESHOLD_MAX, .flags=FLAGS }, |
|
|
|
|
{ "ct", "set chroma threshold", OFFSET(chroma.threshold), AV_OPT_TYPE_INT, {.i64=THRESHOLD_MIN-1}, THRESHOLD_MIN-1, THRESHOLD_MAX, .flags=FLAGS }, |
|
|
|
|
|
|
|
|
|
{ NULL } |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
AVFILTER_DEFINE_CLASS(smartblur); |
|
|
|
|
|
|
|
|
|
static av_cold int init(AVFilterContext *ctx, const char *args) |
|
|
|
|
{ |
|
|
|
|
SmartblurContext *sblur = ctx->priv; |
|
|
|
|
int n = 0, ret = 0; |
|
|
|
|
float lradius, lstrength, cradius, cstrength; |
|
|
|
|
int lthreshold, cthreshold; |
|
|
|
|
|
|
|
|
|
if (args) |
|
|
|
|
n = sscanf(args, "%f:%f:%d:%f:%f:%d", |
|
|
|
|
&lradius, &lstrength, <hreshold, |
|
|
|
|
&cradius, &cstrength, &cthreshold); |
|
|
|
|
|
|
|
|
|
if (n != 3 && n != 6) { |
|
|
|
|
av_log(ctx, AV_LOG_ERROR, |
|
|
|
|
"Incorrect number of parameters or invalid syntax: " |
|
|
|
|
"must be luma_radius:luma_strength:luma_threshold" |
|
|
|
|
"[:chroma_radius:chroma_strength:chroma_threshold]\n"); |
|
|
|
|
return AVERROR(EINVAL); |
|
|
|
|
} |
|
|
|
|
int ret; |
|
|
|
|
static const char *shorthand[] = { |
|
|
|
|
"luma_radius", "luma_strength", "luma_threshold", |
|
|
|
|
"chroma_radius", "chroma_strength", "chroma_threshold", |
|
|
|
|
NULL |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
sblur->luma.radius = lradius; |
|
|
|
|
sblur->luma.strength = lstrength; |
|
|
|
|
sblur->luma.threshold = lthreshold; |
|
|
|
|
sblur->class = &smartblur_class; |
|
|
|
|
av_opt_set_defaults(sblur); |
|
|
|
|
|
|
|
|
|
if (n == 3) { |
|
|
|
|
sblur->chroma.radius = sblur->luma.radius; |
|
|
|
|
if ((ret = av_opt_set_from_string(sblur, args, shorthand, "=", ":")) < 0) |
|
|
|
|
return ret; |
|
|
|
|
|
|
|
|
|
/* make chroma default to luma values, if not explicitly set */ |
|
|
|
|
if (sblur->chroma.radius < RADIUS_MIN) |
|
|
|
|
sblur->chroma.radius = sblur->luma.radius; |
|
|
|
|
if (sblur->chroma.strength < STRENGTH_MIN) |
|
|
|
|
sblur->chroma.strength = sblur->luma.strength; |
|
|
|
|
if (sblur->chroma.threshold < THRESHOLD_MIN) |
|
|
|
|
sblur->chroma.threshold = sblur->luma.threshold; |
|
|
|
|
} else { |
|
|
|
|
sblur->chroma.radius = cradius; |
|
|
|
|
sblur->chroma.strength = cstrength; |
|
|
|
|
sblur->chroma.threshold = cthreshold; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
sblur->luma.quality = sblur->chroma.quality = 3.0; |
|
|
|
|
sblur->sws_flags = SWS_BICUBIC; |
|
|
|
|
|
|
|
|
|
CHECK_PARAM(lradius, luma radius, RADIUS_MIN, RADIUS_MAX, %0.1f, ret) |
|
|
|
|
CHECK_PARAM(lstrength, luma strength, STRENGTH_MIN, STRENGTH_MAX, %0.1f, ret) |
|
|
|
|
CHECK_PARAM(lthreshold, luma threshold, THRESHOLD_MIN, THRESHOLD_MAX, %d, ret) |
|
|
|
|
av_log(ctx, AV_LOG_VERBOSE, |
|
|
|
|
"luma_radius:%f luma_strength:%f luma_threshold:%d " |
|
|
|
|
"chroma_radius:%f chroma_strength:%f chroma_threshold:%d ", |
|
|
|
|
sblur->luma.radius, sblur->luma.strength, sblur->luma.threshold, |
|
|
|
|
sblur->chroma.radius, sblur->chroma.strength, sblur->chroma.threshold); |
|
|
|
|
|
|
|
|
|
if (n != 3) { |
|
|
|
|
CHECK_PARAM(sblur->chroma.radius, chroma radius, RADIUS_MIN, RADIUS_MAX, %0.1f, ret) |
|
|
|
|
CHECK_PARAM(sblur->chroma.strength, chroma strength, STRENGTH_MIN, STRENGTH_MAX, %0.1f, ret) |
|
|
|
|
CHECK_PARAM(sblur->chroma.threshold, chroma threshold, THRESHOLD_MIN,THRESHOLD_MAX, %d, ret) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return ret; |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static av_cold void uninit(AVFilterContext *ctx) |
|
|
|
@ -122,6 +124,7 @@ static av_cold void uninit(AVFilterContext *ctx) |
|
|
|
|
|
|
|
|
|
sws_freeContext(sblur->luma.filter_context); |
|
|
|
|
sws_freeContext(sblur->chroma.filter_context); |
|
|
|
|
av_opt_free(sblur); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int query_formats(AVFilterContext *ctx) |
|
|
|
@ -310,4 +313,5 @@ AVFilter avfilter_vf_smartblur = { |
|
|
|
|
.query_formats = query_formats, |
|
|
|
|
.inputs = smartblur_inputs, |
|
|
|
|
.outputs = smartblur_outputs, |
|
|
|
|
.priv_class = &smartblur_class, |
|
|
|
|
}; |
|
|
|
|