diff options
author | Niklas Haas <git@nand.wakku.to> | 2015-03-25 04:40:28 +0100 |
---|---|---|
committer | Niklas Haas <git@nand.wakku.to> | 2015-04-04 15:36:13 +0200 |
commit | 586dc5574f519a336fda0e8c1d3c94e0c1df38b2 (patch) | |
tree | 8127e7cd89ebd4bb522c05333ae6bb4421913a8d /video/out/gl_video.c | |
parent | 00151e987d2a290eee27a107faa9a7050fc656c0 (diff) | |
download | mpv-586dc5574f519a336fda0e8c1d3c94e0c1df38b2.tar.bz2 mpv-586dc5574f519a336fda0e8c1d3c94e0c1df38b2.tar.xz |
vo_opengl: separate kernel and window
This makes the core much more elegant, reusable, reconfigurable and also
allows us to more easily add aliases for specific configurations.
Furthermore, this lets us apply a generic blur factor / window function
to arbitrary filters, so we can finally "mix and match" in order to
fine-tune windowing functions.
A few notes are in order:
1. The current system for configuring scalers is ugly and rapidly
getting unwieldy. I modified the man page to make it a bit more
bearable, but long-term we have to do something about it; especially
since..
2. There's currently no way to affect the blur factor or parameters of
the window functions themselves. For example, I can't actually
fine-tune the kaiser window's param1, since there's simply no way to
do so in the current API - even though filter_kernels.c supports it
just fine!
3. This removes some lesser used filters (especially those which are
purely window functions to begin with). If anybody asks, you can get
eg. the old behavior of scale=hanning by using
scale=box:scale-window=hanning:scale-radius=1 (and yes, the result is
just as terrible as that sounds - which is why nobody should have
been using them in the first place).
4. This changes the semantics of the "triangle" scaler slightly - it now
has an arbitrary radius. This can possibly produce weird results for
people who were previously using scale-down=triangle, especially if
in combination with scale-radius (for the usual upscaling). The
correct fix for this is to use scale-down=bilinear_slow instead,
which is an alias for triangle at radius 1.
In regards to the last point, in future I want to make it so that
filters have a filter-specific "preferred radius" (for the ones that
are arbitrarily tunable), once the configuration system for filters has
been redesigned (in particular in a way that will let us separate scale
and scale-down cleanly). That way, "triangle" can simply have the
preferred radius of 1 by default, while still being tunable. (Rather
than the default radius being hard-coded to 3 always)
Diffstat (limited to 'video/out/gl_video.c')
-rw-r--r-- | video/out/gl_video.c | 61 |
1 files changed, 52 insertions, 9 deletions
diff --git a/video/out/gl_video.c b/video/out/gl_video.c index 94b2e93564..7f426bfd1f 100644 --- a/video/out/gl_video.c +++ b/video/out/gl_video.c @@ -357,6 +357,9 @@ const struct gl_video_opts gl_video_opts_hq_def = { static int validate_scaler_opt(struct mp_log *log, const m_option_t *opt, struct bstr name, struct bstr param); +static int validate_window_opt(struct mp_log *log, const m_option_t *opt, + struct bstr name, struct bstr param); + #define OPT_BASE_STRUCT struct gl_video_opts const struct m_sub_options gl_video_conf = { .opts = (const m_option_t[]) { @@ -387,6 +390,12 @@ const struct m_sub_options gl_video_conf = { OPT_FLOAT("cscale-param2", scaler_params[1][1], 0), OPT_FLOAT("tscale-param1", scaler_params[2][0], 0), OPT_FLOAT("tscale-param2", scaler_params[2][1], 0), + OPT_FLOAT("scale-blur", scaler_blur[0], 0), + OPT_FLOAT("cscale-blur", scaler_blur[1], 0), + OPT_FLOAT("tscale-blur", scaler_blur[2], 0), + OPT_STRING_VALIDATE("scale-window", scaler_window[0], 0, validate_window_opt), + OPT_STRING_VALIDATE("cscale-window", scaler_window[1], 0, validate_window_opt), + OPT_STRING_VALIDATE("tscale-window", scaler_window[2], 0, validate_window_opt), OPT_FLOATRANGE("scale-radius", scaler_radius[0], 0, 1.0, 16.0), OPT_FLOATRANGE("cscale-radius", scaler_radius[1], 0, 1.0, 16.0), OPT_FLOATRANGE("tscale-radius", scaler_radius[2], 0, 1.0, 3.0), @@ -893,6 +902,7 @@ static void reinit_scaler(struct gl_video *p, int scaler_unit, const char *name, for (int n = 0; n < 2; n++) scaler->params[n] = p->opts.scaler_params[scaler->index][n]; + scaler->antiring = p->opts.scaler_antiring[scaler->index]; const struct filter_kernel *t_kernel = mp_find_filter_kernel(scaler->name); if (!t_kernel) @@ -901,15 +911,24 @@ static void reinit_scaler(struct gl_video *p, int scaler_unit, const char *name, scaler->kernel_storage = *t_kernel; scaler->kernel = &scaler->kernel_storage; + const char *win = p->opts.scaler_window[scaler->index]; + if (!win || !win[0]) + win = t_kernel->window; + const struct filter_window *t_window = mp_find_filter_window(win); + if (t_window) + scaler->kernel->w = *t_window; + for (int n = 0; n < 2; n++) { if (!isnan(scaler->params[n])) - scaler->kernel->params[n] = scaler->params[n]; + scaler->kernel->f.params[n] = scaler->params[n]; } - scaler->antiring = p->opts.scaler_antiring[scaler->index]; + float blur = p->opts.scaler_blur[scaler->index]; + if (blur > 0.0) + scaler->kernel->f.blur = blur; - if (scaler->kernel->radius < 0) - scaler->kernel->radius = p->opts.scaler_radius[scaler->index]; + if (scaler->kernel->f.radius < 0) + scaler->kernel->f.radius = p->opts.scaler_radius[scaler->index]; scaler->insufficient = !mp_init_filter(scaler->kernel, sizes, scale_factor); @@ -1064,7 +1083,7 @@ static void pass_sample_separated(struct gl_video *p, int src_tex, static void pass_sample_polar(struct gl_video *p, struct scaler *scaler) { - double radius = scaler->kernel->radius; + double radius = scaler->kernel->f.radius; int bound = (int)ceil(radius); bool use_ar = scaler->antiring > 0; GLSL(vec4 color = vec4(0.0);) @@ -2491,7 +2510,7 @@ static const char *handle_scaler_opt(const char *name, bool tscale) if (name && name[0]) { const struct filter_kernel *kernel = mp_find_filter_kernel(name); if (kernel && (!tscale || !kernel->polar)) - return kernel->name; + return kernel->f.name; for (const char *const *filter = tscale ? fixed_tscale_filters : fixed_scale_filters; @@ -2520,7 +2539,7 @@ void gl_video_set_options(struct gl_video *p, struct gl_video_opts *opts, if (queue_size && p->opts.interpolation && p->opts.scalers[2]) { const struct filter_kernel *kernel = mp_find_filter_kernel(p->opts.scalers[2]); if (kernel) { - double radius = kernel->radius; + double radius = kernel->f.radius; radius = radius > 0 ? radius : p->opts.scaler_radius[2]; *queue_size = 50e3 * ceil(radius); } @@ -2566,9 +2585,9 @@ static int validate_scaler_opt(struct mp_log *log, const m_option_t *opt, *filter; filter++) { mp_info(log, " %s\n", *filter); } - for (int n = 0; mp_filter_kernels[n].name; n++) { + for (int n = 0; mp_filter_kernels[n].f.name; n++) { if (!tscale || !mp_filter_kernels[n].polar) - mp_info(log, " %s\n", mp_filter_kernels[n].name); + mp_info(log, " %s\n", mp_filter_kernels[n].f.name); } if (s[0]) mp_fatal(log, "No scaler named '%s' found!\n", s); @@ -2576,6 +2595,30 @@ static int validate_scaler_opt(struct mp_log *log, const m_option_t *opt, return r; } +static int validate_window_opt(struct mp_log *log, const m_option_t *opt, + struct bstr name, struct bstr param) +{ + char s[20] = {0}; + int r = 1; + if (bstr_equals0(param, "help")) { + r = M_OPT_EXIT - 1; + } else { + snprintf(s, sizeof(s), "%.*s", BSTR_P(param)); + const struct filter_window *window = mp_find_filter_window(s); + if (!window) + r = M_OPT_INVALID; + } + if (r < 1) { + mp_info(log, "Available windows:\n"); + for (int n = 0; mp_filter_windows[n].name; n++) + mp_info(log, " %s\n", mp_filter_windows[n].name); + if (s[0]) + mp_fatal(log, "No window named '%s' found!\n", s); + } + return r; +} + + // Resize and redraw the contents of the window without further configuration. // Intended to be used in situations where the frontend can't really be // involved with reconfiguring the VO properly. |