summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNiklas Haas <git@nand.wakku.to>2015-01-18 18:57:12 +0100
committerNiklas Haas <git@nand.wakku.to>2015-01-22 19:39:58 +0100
commit2d182fdea0a068cbbbe88b575963cbb480444f31 (patch)
tree407176b7db120a82106ccb05dbdce06917c635f8
parent6c250505fedc54a3918788f70445f5fff9d2569a (diff)
downloadmpv-2d182fdea0a068cbbbe88b575963cbb480444f31.tar.bz2
mpv-2d182fdea0a068cbbbe88b575963cbb480444f31.tar.xz
vo_opengl: implement naive anti-ringing
This is not quite the same thing as madVR's antiringing algorithm, but it essentially does something similar. Porting madVR's approach to elliptic coordinates will take some amount of thought.
-rw-r--r--DOCS/man/vo.rst17
-rw-r--r--video/out/gl_video.c18
-rw-r--r--video/out/gl_video.h1
-rw-r--r--video/out/gl_video_shaders.glsl23
4 files changed, 45 insertions, 14 deletions
diff --git a/DOCS/man/vo.rst b/DOCS/man/vo.rst
index ae7e377771..5e03361bf9 100644
--- a/DOCS/man/vo.rst
+++ b/DOCS/man/vo.rst
@@ -306,9 +306,10 @@ Available video output drivers are:
``ewa_lanczos``
Elliptic weighted average Lanczos scaling. Also known as Jinc.
Relatively slow, but very good quality. The number of taps can
- be controlled with ``lradius``.
+ be controlled with ``lradius``. Adding extra taps makes the filter
+ sharper but adds more ringing.
- Adding extra taps makes the filter sharper but adds more ringing.
+ This filter supports antiringing (see ``lantiring``).
``mitchell``
Mitchell-Netravali. The ``b`` and ``c`` parameters can be set with
@@ -337,6 +338,14 @@ Available video output drivers are:
ratio, the radius that actually being used might be different
(most likely being increased a bit).
+ ``lantiring=<value>``
+ Set the antiringing strength. This tries to eliminate ringing, but can
+ introduce other artifacts in the process. Must be a float number
+ between 0.0 and 1.0. The default value of 0.0 disables antiringing
+ entirely.
+
+ Note that this currently only affects ``ewa_lanczos``.
+
``scaler-resizes-only``
Disable the scaler if the video image is not resized. In that case,
``bilinear`` is used instead whatever is set with ``lscale``. Bilinear
@@ -434,10 +443,10 @@ Available video output drivers are:
down by more than twice (or other factors, depending on image formats),
and ``lscale`` did not use a separable scaler.
- ``cparam1``, ``cparam2``, ``cradius``
+ ``cparam1``, ``cparam2``, ``cradius``, ``cantiring``
Set filter parameters and radius for ``cscale``.
- See ``lparam1``, ``lparam2`` and ``lradius``.
+ See ``lparam1``, ``lparam2``, ``lradius`` and ``lantiring``.
``fancy-downscaling``
When using convolution based filters, extend the filter size
diff --git a/video/out/gl_video.c b/video/out/gl_video.c
index 7400ffba0f..ddccd3a3e5 100644
--- a/video/out/gl_video.c
+++ b/video/out/gl_video.c
@@ -105,6 +105,7 @@ struct scaler {
int index;
const char *name;
float params[2];
+ float antiring;
struct filter_kernel *kernel;
GLuint gl_lut;
const char *lut_name;
@@ -367,6 +368,8 @@ const struct m_sub_options gl_video_conf = {
OPT_FLOAT("cparam2", scaler_params[1][1], 0),
OPT_FLOATRANGE("lradius", scaler_radius[0], 0, 1.0, 16.0),
OPT_FLOATRANGE("cradius", scaler_radius[1], 0, 1.0, 16.0),
+ OPT_FLOATRANGE("lantiring", scaler_antiring[0], 0, 0.0, 1.0),
+ OPT_FLOATRANGE("cantiring", scaler_antiring[1], 0, 0.0, 1.0),
OPT_FLAG("scaler-resizes-only", scaler_resizes_only, 0),
OPT_FLAG("fancy-downscaling", fancy_downscaling, 0),
OPT_FLAG("sigmoid-upscaling", sigmoid_upscaling, 0),
@@ -955,9 +958,9 @@ static void shader_setup_scaler(char **shader, struct scaler *scaler, int pass)
char lut_fn[40];
if (scaler->kernel->polar) {
int radius = (int)scaler->kernel->radius;
- // SAMPLE_CONVOLUTION_POLAR_R(NAME, R, LUT)
- APPENDF(shader, "SAMPLE_CONVOLUTION_POLAR_R(%s, %d, %s, WEIGHTS%d)\n",
- name, radius, lut_tex, unit);
+ // SAMPLE_CONVOLUTION_POLAR_R(NAME, R, LUT, WEIGHTS_FN, ANTIRING)
+ APPENDF(shader, "SAMPLE_CONVOLUTION_POLAR_R(%s, %d, %s, WEIGHTS%d, %f)\n",
+ name, radius, lut_tex, unit, scaler->antiring);
// Pre-compute unrolled weights matrix
APPENDF(shader, "#define WEIGHTS%d(LUT) \\\n ", unit);
@@ -971,7 +974,12 @@ static void shader_setup_scaler(char **shader, struct scaler *scaler, int pass)
// Samples outside the radius are unnecessary
if (d < radius) {
- APPENDF(shader, "SAMPLE_POLAR(LUT, %f, %d, %d) \\\n ",
+ APPENDF(shader, "SAMPLE_POLAR_%s(LUT, %f, %d, %d) \\\n ",
+ // The center 4 coefficients are the primary
+ // contributors, used to clamp the result for
+ // anti-ringing
+ (x >= 0 && y >= 0 && x <= 1 && y <= 1)
+ ? "PRIMARY" : "HELPER",
(double)radius, x, y);
}
}
@@ -1316,6 +1324,8 @@ static void init_scaler(struct gl_video *p, struct scaler *scaler)
scaler->kernel->params[n] = p->opts.scaler_params[scaler->index][n];
}
+ scaler->antiring = p->opts.scaler_antiring[scaler->index];
+
if (scaler->kernel->radius < 0) {
float radius = p->opts.scaler_radius[scaler->index];
if (!isnan(radius))
diff --git a/video/out/gl_video.h b/video/out/gl_video.h
index b3c5d5abe5..980f237a15 100644
--- a/video/out/gl_video.h
+++ b/video/out/gl_video.h
@@ -33,6 +33,7 @@ struct gl_video_opts {
char *dscaler;
float scaler_params[2][2];
float scaler_radius[2];
+ float scaler_antiring[2];
int indirect;
float gamma;
int srgb;
diff --git a/video/out/gl_video_shaders.glsl b/video/out/gl_video_shaders.glsl
index fa9bfa2e95..d3cbbb7c41 100644
--- a/video/out/gl_video_shaders.glsl
+++ b/video/out/gl_video_shaders.glsl
@@ -188,6 +188,7 @@ uniform float dither_quantization;
uniform float dither_center;
uniform float filter_param1_l;
uniform float filter_param1_c;
+uniform float antiring_factor;
uniform vec2 dither_size;
in vec2 texcoord;
@@ -298,21 +299,31 @@ float[6] weights6(sampler2D lookup, float f) {
return res; \
}
-#define SAMPLE_POLAR(LUT, R, X, Y) \
+#define SAMPLE_POLAR_HELPER(LUT, R, X, Y) \
w = texture1D(LUT, length(vec2(X, Y) - fcoord)/R).r; \
+ c = texture(tex, base + pt * vec2(X, Y)); \
wsum += w; \
- res += w * texture(tex, base + pt * vec2(X, Y)); \
+ res += w * c; \
-#define SAMPLE_CONVOLUTION_POLAR_R(NAME, R, LUT, WEIGHTS_FN) \
+#define SAMPLE_POLAR_PRIMARY(LUT, R, X, Y) \
+ SAMPLE_POLAR_HELPER(LUT, R, X, Y) \
+ lo = min(lo, c); \
+ hi = max(hi, c); \
+
+#define SAMPLE_CONVOLUTION_POLAR_R(NAME, R, LUT, WEIGHTS_FN, ANTIRING) \
vec4 NAME(VIDEO_SAMPLER tex, vec2 texsize, vec2 texcoord) { \
vec2 pt = vec2(1.0) / texsize; \
vec2 fcoord = fract(texcoord * texsize - vec2(0.5)); \
vec2 base = texcoord - fcoord * pt; \
- vec4 res = vec4(0); \
- float wsum = 0; \
+ vec4 res = vec4(0.0); \
+ vec4 lo = vec4(1.0); \
+ vec4 hi = vec4(0.0); \
+ float wsum = 0.0; \
float w; \
+ vec4 c; \
WEIGHTS_FN(LUT); \
- return res / wsum; \
+ res /= wsum; \
+ return mix(res, clamp(res, lo, hi), ANTIRING); \
}
#ifdef DEF_SCALER0