vo_opengl: remove sharpen scalers, add sharpen sub-option

This turns the old scalers (inherited from MPlayer) into a pre-
processing step (after color conversion and before scaling). The code
for the "sharpen5" scaler is reused for this.

The main reason MPlayer implemented this as scalers was perhaps because
FBOs were too expensive, and making it a scaler allowed to implement
this in 1 pass. But unsharp masking is not really a scaler, and I would
guess the result is more like combining bilinear scaling and unsharp
masking.
This commit is contained in:
wm4 2015-09-23 22:43:27 +02:00
parent c17ff1703a
commit cb1c072534
7 changed files with 49 additions and 53 deletions

View File

@ -50,7 +50,7 @@ Item {
text: "Make video look like on a Smart TV"
onClicked: {
if (checkbox.checked) {
renderer.command(["vo_cmdline", "scale=sharpen3:scale-param1=5.0"])
renderer.command(["vo_cmdline", "sharpen=5.0"])
} else {
renderer.command(["vo_cmdline", ""])
}

View File

@ -19,6 +19,8 @@ Interface changes
::
--- mpv 0.12.0 ---
- vo_opengl: remove sharpen3/sharpen5 scale filters, add sharpen sub-option
--- mpv 0.11.0 ---
- add "af-metadata" property
--- mpv 0.10.0 ---

View File

@ -375,10 +375,6 @@ Available video output drivers are:
Scale parameter (``t``). Increasing this makes the result blurrier.
Defaults to 1.
sharpen3, sharpen5
Sharpening strength. Increasing this makes the image sharper but
adds more ringing and aliasing. Defaults to 0.5.
oversample
Minimum distance to an edge before interpolation is used. Setting
this to 0 will always interpolate edges, whereas setting it to 0.5
@ -408,8 +404,8 @@ Available video output drivers are:
between 0.0 and 1.0. The default value of 0.0 disables antiringing
entirely.
Note that this doesn't affect the special filters ``bilinear``,
``bicubic_fast`` or ``sharpen``.
Note that this doesn't affect the special filters ``bilinear`` and
``bicubic_fast``.
``scale-window=<window>``
(Advanced users only) Choose a custom windowing function for the kernel.
@ -645,6 +641,16 @@ Available video output drivers are:
The slope of the sigmoid curve used for ``sigmoid-upscaling``, must
be a float between 1.0 and 20.0. Defaults to 6.5 if not specified.
``sharpen=<value>``
If set to a value other than 0, enable an unsharp masking filter.
Positive values will sharpen the image (but add more ringing and
aliasing). Negative values will blur the image. If your GPU is powerful
enough, consider alternatives like the ``ewa_lanczossharp`` scale
filter, or the ``scale-blur`` sub-option.
(This feature is the replacement for the old ``sharpen3`` and
``sharpen5`` scalers.)
``glfinish``
Call ``glFinish()`` before and after swapping buffers (default: disabled).
Slower, but might help getting better results when doing framedropping.

View File

@ -53,8 +53,6 @@
static const char *const fixed_scale_filters[] = {
"bilinear",
"bicubic_fast",
"sharpen3",
"sharpen5",
"oversample",
"custom",
NULL
@ -167,6 +165,7 @@ struct gl_video {
struct fbotex chroma_deband_fbo;
struct fbotex indirect_fbo;
struct fbotex blend_subs_fbo;
struct fbotex unsharp_fbo;
struct fbosurface surfaces[FBOSURFACES_MAX];
// these are duplicated so we can keep rendering back and forth between
@ -427,6 +426,7 @@ const struct m_sub_options gl_video_conf = {
OPT_STRINGLIST("post-shaders", post_shaders, 0),
OPT_FLAG("deband", deband, 0),
OPT_SUBSTRUCT("deband", deband_opts, deband_conf, 0),
OPT_FLOAT("sharpen", unsharp, 0),
OPT_REMOVED("approx-gamma", "this is always enabled now"),
OPT_REMOVED("cscale-down", "chroma is never downscaled"),
@ -576,6 +576,7 @@ static void uninit_rendering(struct gl_video *p)
fbotex_uninit(&p->chroma_deband_fbo);
fbotex_uninit(&p->indirect_fbo);
fbotex_uninit(&p->blend_subs_fbo);
fbotex_uninit(&p->unsharp_fbo);
for (int n = 0; n < 2; n++) {
fbotex_uninit(&p->pre_fbo[n]);
@ -1098,10 +1099,6 @@ static void pass_sample(struct gl_video *p, int src_tex, struct scaler *scaler,
GLSL(vec4 color = texture(tex, pos);)
} else if (strcmp(name, "bicubic_fast") == 0) {
pass_sample_bicubic_fast(p->sc);
} else if (strcmp(name, "sharpen3") == 0) {
pass_sample_sharpen3(p->sc, scaler);
} else if (strcmp(name, "sharpen5") == 0) {
pass_sample_sharpen5(p->sc, scaler);
} else if (strcmp(name, "oversample") == 0) {
pass_sample_oversample(p->sc, scaler, w, h);
} else if (strcmp(name, "custom") == 0) {
@ -1666,6 +1663,11 @@ static void pass_render_frame(struct gl_video *p)
apply_shaders(p, p->opts.pre_shaders, &p->pre_fbo[0], 0,
p->image_w, p->image_h);
if (p->opts.unsharp != 0.0) {
finish_pass_fbo(p, &p->unsharp_fbo, p->image_w, p->image_h, 0, 0);
pass_sample_unsharp(p->sc, p->opts.unsharp);
}
pass_scale_main(p);
int vp_w = p->dst_rect.x1 - p->dst_rect.x0,

View File

@ -98,6 +98,7 @@ struct gl_video_opts {
char **post_shaders;
int deband;
struct deband_opts *deband_opts;
float unsharp;
};
extern const struct m_sub_options gl_video_conf;

View File

@ -200,44 +200,6 @@ void pass_sample_bicubic_fast(struct gl_shader_cache *sc)
GLSLF("}\n");
}
void pass_sample_sharpen3(struct gl_shader_cache *sc, struct scaler *scaler)
{
GLSL(vec4 color;)
GLSLF("{\n");
GLSL(vec2 st = pt * 0.5;)
GLSL(vec4 p = texture(tex, pos);)
GLSL(vec4 sum = texture(tex, pos + st * vec2(+1, +1))
+ texture(tex, pos + st * vec2(+1, -1))
+ texture(tex, pos + st * vec2(-1, +1))
+ texture(tex, pos + st * vec2(-1, -1));)
float param = scaler->conf.kernel.params[0];
param = isnan(param) ? 0.5 : param;
GLSLF("color = p + (p - 0.25 * sum) * %f;\n", param);
GLSLF("}\n");
}
void pass_sample_sharpen5(struct gl_shader_cache *sc, struct scaler *scaler)
{
GLSL(vec4 color;)
GLSLF("{\n");
GLSL(vec2 st1 = pt * 1.2;)
GLSL(vec4 p = texture(tex, pos);)
GLSL(vec4 sum1 = texture(tex, pos + st1 * vec2(+1, +1))
+ texture(tex, pos + st1 * vec2(+1, -1))
+ texture(tex, pos + st1 * vec2(-1, +1))
+ texture(tex, pos + st1 * vec2(-1, -1));)
GLSL(vec2 st2 = pt * 1.5;)
GLSL(vec4 sum2 = texture(tex, pos + st2 * vec2(+1, 0))
+ texture(tex, pos + st2 * vec2( 0, +1))
+ texture(tex, pos + st2 * vec2(-1, 0))
+ texture(tex, pos + st2 * vec2( 0, -1));)
GLSL(vec4 t = p * 0.859375 + sum2 * -0.1171875 + sum1 * -0.09765625;)
float param = scaler->conf.kernel.params[0];
param = isnan(param) ? 0.5 : param;
GLSLF("color = p + t * %f;\n", param);
GLSLF("}\n");
}
void pass_sample_oversample(struct gl_shader_cache *sc, struct scaler *scaler,
int w, int h)
{
@ -435,3 +397,26 @@ void pass_sample_deband(struct gl_shader_cache *sc, struct deband_opts *opts,
GLSL(noise.z = rand(h); h = permute(h);)
GLSLF("color.xyz += %f * (noise - vec3(0.5));\n", opts->grain/8192.0);
}
void pass_sample_unsharp(struct gl_shader_cache *sc, float param)
{
GLSLF("// unsharp\n");
sampler_prelude(sc, 0);
GLSL(vec4 color;)
GLSLF("{\n");
GLSL(vec2 st1 = pt * 1.2;)
GLSL(vec4 p = texture(tex, pos);)
GLSL(vec4 sum1 = texture(tex, pos + st1 * vec2(+1, +1))
+ texture(tex, pos + st1 * vec2(+1, -1))
+ texture(tex, pos + st1 * vec2(-1, +1))
+ texture(tex, pos + st1 * vec2(-1, -1));)
GLSL(vec2 st2 = pt * 1.5;)
GLSL(vec4 sum2 = texture(tex, pos + st2 * vec2(+1, 0))
+ texture(tex, pos + st2 * vec2( 0, +1))
+ texture(tex, pos + st2 * vec2(-1, 0))
+ texture(tex, pos + st2 * vec2( 0, -1));)
GLSL(vec4 t = p * 0.859375 + sum2 * -0.1171875 + sum1 * -0.09765625;)
GLSLF("color = p + t * %f;\n", param);
GLSLF("}\n");
}

View File

@ -37,8 +37,6 @@ void pass_sample_separated_gen(struct gl_shader_cache *sc, struct scaler *scaler
int d_x, int d_y);
void pass_sample_polar(struct gl_shader_cache *sc, struct scaler *scaler);
void pass_sample_bicubic_fast(struct gl_shader_cache *sc);
void pass_sample_sharpen3(struct gl_shader_cache *sc, struct scaler *scaler);
void pass_sample_sharpen5(struct gl_shader_cache *sc, struct scaler *scaler);
void pass_sample_oversample(struct gl_shader_cache *sc, struct scaler *scaler,
int w, int h);
@ -49,4 +47,6 @@ void pass_sample_deband(struct gl_shader_cache *sc, struct deband_opts *opts,
int tex_num, GLenum tex_target, float tex_mul,
float img_w, float img_h, AVLFG *lfg);
void pass_sample_unsharp(struct gl_shader_cache *sc, float param);
#endif