summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/man/vo.rst6
-rw-r--r--video/out/filter_kernels.c3
-rw-r--r--video/out/filter_kernels.h1
-rw-r--r--video/out/gl_video.c6
-rw-r--r--video/out/gl_video.h1
5 files changed, 15 insertions, 2 deletions
diff --git a/DOCS/man/vo.rst b/DOCS/man/vo.rst
index da9bebe115..1865d848bb 100644
--- a/DOCS/man/vo.rst
+++ b/DOCS/man/vo.rst
@@ -506,6 +506,12 @@ Available video output drivers are:
limitations in the number of video textures that can be loaded
simultaneously.
+ ``tscale-clamp``
+ Clamp the ``tscale`` filter kernel's value range to [0-1]. This reduces
+ excessive ringing artifacts in the temporal domain (which typically
+ manifest themselves as short flashes or fringes of black, mostly
+ around moving edges) in exchange for potentially adding more blur.
+
``dscale-radius``, ``cscale-radius``, ``tscale-radius``, etc.
Set filter parameters for ``dscale``, ``cscale`` and ``tscale``,
respectively.
diff --git a/video/out/filter_kernels.c b/video/out/filter_kernels.c
index a748ac10ab..0f6d5a98bc 100644
--- a/video/out/filter_kernels.c
+++ b/video/out/filter_kernels.c
@@ -113,7 +113,8 @@ static double sample_filter(struct filter_kernel *filter,
double w = window->weight ? window->weight(window, x/bw * window->radius
/ filter->f.radius)
: 1.0;
- return c < filter->f.radius ? w * filter->f.weight(&filter->f, c) : 0.0;
+ double v = c < filter->f.radius ? w * filter->f.weight(&filter->f, c) : 0.0;
+ return filter->clamp ? fmax(0.0, fmin(1.0, v)) : v;
}
// Calculate the 1D filtering kernel for N sample points.
diff --git a/video/out/filter_kernels.h b/video/out/filter_kernels.h
index 9e6176293f..7b101cdd35 100644
--- a/video/out/filter_kernels.h
+++ b/video/out/filter_kernels.h
@@ -33,6 +33,7 @@ struct filter_window {
struct filter_kernel {
struct filter_window f; // the kernel itself
struct filter_window w; // window storage
+ bool clamp; // clamp to the range [0-1]
// Constant values
const char *window; // default window
bool polar; // whether or not the filter uses polar coordinates
diff --git a/video/out/gl_video.c b/video/out/gl_video.c
index a1d100f4dc..4eb4030244 100644
--- a/video/out/gl_video.c
+++ b/video/out/gl_video.c
@@ -415,6 +415,7 @@ const struct m_sub_options gl_video_conf = {
OPT_FLOATRANGE("dscale-antiring", scaler[1].antiring, 0, 0.0, 1.0),
OPT_FLOATRANGE("cscale-antiring", scaler[2].antiring, 0, 0.0, 1.0),
OPT_FLOATRANGE("tscale-antiring", scaler[3].antiring, 0, 0.0, 1.0),
+ OPT_FLAG("tscale-clamp", scaler[3].clamp, 0),
OPT_FLAG("scaler-resizes-only", scaler_resizes_only, 0),
OPT_FLAG("linear-scaling", linear_scaling, 0),
OPT_FLAG("fancy-downscaling", fancy_downscaling, 0),
@@ -950,7 +951,8 @@ static bool scaler_conf_eq(struct scaler_config a, struct scaler_config b)
// generation
return scaler_fun_eq(a.kernel, b.kernel) &&
scaler_fun_eq(a.window, b.window) &&
- a.radius == b.radius;
+ a.radius == b.radius &&
+ a.clamp == b.clamp;
}
static void reinit_scaler(struct gl_video *p, struct scaler *scaler,
@@ -1001,6 +1003,8 @@ static void reinit_scaler(struct gl_video *p, struct scaler *scaler,
if (scaler->kernel->f.resizable && conf->radius > 0.0)
scaler->kernel->f.radius = conf->radius;
+ scaler->kernel->clamp = conf->clamp;
+
scaler->insufficient = !mp_init_filter(scaler->kernel, sizes, scale_factor);
if (scaler->kernel->polar) {
diff --git a/video/out/gl_video.h b/video/out/gl_video.h
index 0881025a14..385477e051 100644
--- a/video/out/gl_video.h
+++ b/video/out/gl_video.h
@@ -39,6 +39,7 @@ struct scaler_config {
struct scaler_fun window;
float radius;
float antiring;
+ int clamp;
};
struct gl_video_opts {