mirror of https://github.com/mpv-player/mpv
vo_gpu{,_next}: convert scale options to type choice
This allows Tab completing them in the console and zsh, and using cycle scale. jinc is also added to --tscale=help's output, while before it was missing because validate_scaler_opt() skipped filter windows with the same name as a filter kernel, but the jinc kernel was skipped with --tscale because it is polar.
This commit is contained in:
parent
d84a7c5112
commit
dd77d0a7da
|
@ -32,23 +32,19 @@
|
|||
|
||||
// NOTE: all filters are designed for discrete convolution
|
||||
|
||||
const struct filter_window *mp_find_filter_window(const char *name)
|
||||
const struct filter_window *mp_find_filter_window(enum scaler_filter function)
|
||||
{
|
||||
if (!name)
|
||||
return NULL;
|
||||
for (const struct filter_window *w = mp_filter_windows; w->name; w++) {
|
||||
if (strcmp(w->name, name) == 0)
|
||||
for (const struct filter_window *w = mp_filter_windows; w->function; w++) {
|
||||
if (w->function == function)
|
||||
return w;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const struct filter_kernel *mp_find_filter_kernel(const char *name)
|
||||
const struct filter_kernel *mp_find_filter_kernel(enum scaler_filter function)
|
||||
{
|
||||
if (!name)
|
||||
return NULL;
|
||||
for (const struct filter_kernel *k = mp_filter_kernels; k->f.name; k++) {
|
||||
if (strcmp(k->f.name, name) == 0)
|
||||
for (const struct filter_kernel *k = mp_filter_kernels; k->f.function; k++) {
|
||||
if (k->f.function == function)
|
||||
return k;
|
||||
}
|
||||
return NULL;
|
||||
|
@ -335,21 +331,21 @@ static double sphinx(params *p, double x)
|
|||
}
|
||||
|
||||
const struct filter_window mp_filter_windows[] = {
|
||||
{"box", 1, box},
|
||||
{"triangle", 1, triangle},
|
||||
{"bartlett", 1, triangle},
|
||||
{"cosine", M_PI_2, cosine},
|
||||
{"hanning", 1, hanning},
|
||||
{"tukey", 1, hanning, .taper = 0.5},
|
||||
{"hamming", 1, hamming},
|
||||
{"quadric", 1.5, quadric},
|
||||
{"welch", 1, welch},
|
||||
{"kaiser", 1, kaiser, .params = {6.33, NAN} },
|
||||
{"blackman", 1, blackman, .params = {0.16, NAN} },
|
||||
{"gaussian", 2, gaussian, .params = {1.00, NAN} },
|
||||
{"sinc", 1, sinc},
|
||||
{"jinc", 1.2196698912665045, jinc},
|
||||
{"sphinx", 1.4302966531242027, sphinx},
|
||||
{WINDOW_BOX, 1, box},
|
||||
{WINDOW_TRIANGLE, 1, triangle},
|
||||
{WINDOW_BARTLETT, 1, triangle},
|
||||
{WINDOW_COSINE, M_PI_2, cosine},
|
||||
{WINDOW_HANNING, 1, hanning},
|
||||
{WINDOW_TUKEY, 1, hanning, .taper = 0.5},
|
||||
{WINDOW_HAMMING, 1, hamming},
|
||||
{WINDOW_QUADRIC, 1.5, quadric},
|
||||
{WINDOW_WELCH, 1, welch},
|
||||
{WINDOW_KAISER, 1, kaiser, .params = {6.33, NAN} },
|
||||
{WINDOW_BLACKMAN, 1, blackman, .params = {0.16, NAN} },
|
||||
{WINDOW_GAUSSIAN, 2, gaussian, .params = {1.00, NAN} },
|
||||
{WINDOW_SINC, 1, sinc},
|
||||
{WINDOW_JINC, 1.2196698912665045, jinc},
|
||||
{WINDOW_SPHINX, 1.4302966531242027, sphinx},
|
||||
{0}
|
||||
};
|
||||
|
||||
|
@ -358,54 +354,54 @@ const struct filter_window mp_filter_windows[] = {
|
|||
|
||||
const struct filter_kernel mp_filter_kernels[] = {
|
||||
// Spline filters
|
||||
{{"spline16", 2, spline16}},
|
||||
{{"spline36", 3, spline36}},
|
||||
{{"spline64", 4, spline64}},
|
||||
{{SCALER_SPLINE16, 2, spline16}},
|
||||
{{SCALER_SPLINE36, 3, spline36}},
|
||||
{{SCALER_SPLINE64, 4, spline64}},
|
||||
// Sinc filters
|
||||
{{"sinc", 2, sinc, .resizable = true}},
|
||||
{{"lanczos", 3, sinc, .resizable = true}, .window = "sinc"},
|
||||
{{"ginseng", 3, sinc, .resizable = true}, .window = "jinc"},
|
||||
{{SCALER_SINC, 2, sinc, .resizable = true}},
|
||||
{{SCALER_LANCZOS, 3, sinc, .resizable = true}, .window = WINDOW_SINC},
|
||||
{{SCALER_GINSENG, 3, sinc, .resizable = true}, .window = WINDOW_JINC},
|
||||
// Jinc filters
|
||||
{{"jinc", JINC_R3, jinc, .resizable = true}, .polar = true},
|
||||
{{"ewa_lanczos", JINC_R3, jinc, .resizable = true}, .polar = true, .window = "jinc"},
|
||||
{{"ewa_hanning", JINC_R3, jinc, .resizable = true}, .polar = true, .window = "hanning" },
|
||||
{{"ewa_ginseng", JINC_R3, jinc, .resizable = true}, .polar = true, .window = "sinc"},
|
||||
{{SCALER_JINC, JINC_R3, jinc, .resizable = true}, .polar = true},
|
||||
{{SCALER_EWA_LANCZOS, JINC_R3, jinc, .resizable = true}, .polar = true, .window = WINDOW_JINC},
|
||||
{{SCALER_EWA_HANNING, JINC_R3, jinc, .resizable = true}, .polar = true, .window = WINDOW_HANNING},
|
||||
{{SCALER_EWA_GINSENG, JINC_R3, jinc, .resizable = true}, .polar = true, .window = WINDOW_SINC},
|
||||
// Slightly sharpened to minimize the 1D step response error (to better
|
||||
// preserve horizontal/vertical lines)
|
||||
{{"ewa_lanczossharp", JINC_R3, jinc, .blur = 0.9812505837223707, .resizable = true},
|
||||
.polar = true, .window = "jinc"},
|
||||
{{SCALER_EWA_LANCZOSSHARP, JINC_R3, jinc, .blur = 0.9812505837223707, .resizable = true},
|
||||
.polar = true, .window = WINDOW_JINC},
|
||||
// Similar to the above, but sharpened substantially to the point of
|
||||
// minimizing the total impulse response error on an integer grid. Tends
|
||||
// to preserve hash patterns well. Very sharp but rings a lot.
|
||||
{{"ewa_lanczos4sharpest", JINC_R4, jinc, .blur = 0.8845120932605005, .resizable = true},
|
||||
.polar = true, .window = "jinc"},
|
||||
{{SCALER_EWA_LANCZOS4SHARPEST, JINC_R4, jinc, .blur = 0.8845120932605005, .resizable = true},
|
||||
.polar = true, .window = WINDOW_JINC},
|
||||
// Similar to the above, but softened instead, to make even/odd integer
|
||||
// contributions exactly symmetrical. Designed to smooth out hash patterns.
|
||||
{{"ewa_lanczossoft", JINC_R3, jinc, .blur = 1.0164667662867047, .resizable = true},
|
||||
.polar = true, .window = "jinc"},
|
||||
{{SCALER_EWA_LANCZOSSOFT, JINC_R3, jinc, .blur = 1.0164667662867047, .resizable = true},
|
||||
.polar = true, .window = WINDOW_JINC},
|
||||
// Very soft (blurred) hanning-windowed jinc; removes almost all aliasing.
|
||||
// Blur parameter picked to match orthogonal and diagonal contributions
|
||||
{{"haasnsoft", JINC_R3, jinc, .blur = 1.11, .resizable = true},
|
||||
.polar = true, .window = "hanning"},
|
||||
{{SCALER_HAASNSOFT, JINC_R3, jinc, .blur = 1.11, .resizable = true},
|
||||
.polar = true, .window = WINDOW_HANNING},
|
||||
// Cubic filters
|
||||
{{"bicubic", 2, cubic_bc, .params = {1.0, 0.0} }},
|
||||
{{"hermite", 1, cubic_bc, .params = {0.0, 0.0} }},
|
||||
{{"catmull_rom", 2, cubic_bc, .params = {0.0, 0.5} }},
|
||||
{{"mitchell", 2, cubic_bc, .params = {1.0/3.0, 1.0/3.0} }},
|
||||
{{"robidoux", 2, cubic_bc, .params = {12 / (19 + 9 * M_SQRT2),
|
||||
113 / (58 + 216 * M_SQRT2)} }},
|
||||
{{"robidouxsharp", 2, cubic_bc, .params = {6 / (13 + 7 * M_SQRT2),
|
||||
7 / (2 + 12 * M_SQRT2)} }},
|
||||
{{"ewa_robidoux", 2, cubic_bc, .params = {12 / (19 + 9 * M_SQRT2),
|
||||
113 / (58 + 216 * M_SQRT2)}},
|
||||
.polar = true},
|
||||
{{"ewa_robidouxsharp", 2,cubic_bc, .params = {6 / (13 + 7 * M_SQRT2),
|
||||
7 / (2 + 12 * M_SQRT2)}},
|
||||
.polar = true},
|
||||
{{SCALER_BICUBIC, 2, cubic_bc, .params = {1.0, 0.0} }},
|
||||
{{SCALER_HERMITE, 1, cubic_bc, .params = {0.0, 0.0} }},
|
||||
{{SCALER_CATMULL_ROM, 2, cubic_bc, .params = {0.0, 0.5} }},
|
||||
{{SCALER_MITCHELL, 2, cubic_bc, .params = {1.0/3.0, 1.0/3.0} }},
|
||||
{{SCALER_ROBIDOUX, 2, cubic_bc,
|
||||
.params = {12 / (19 + 9 * M_SQRT2), 113 / (58 + 216 * M_SQRT2)} }},
|
||||
{{SCALER_ROBIDOUXSHARP, 2, cubic_bc,
|
||||
.params = {6 / (13 + 7 * M_SQRT2), 7 / (2 + 12 * M_SQRT2)} }},
|
||||
{{SCALER_EWA_ROBIDOUX, 2, cubic_bc,
|
||||
.params = {12 / (19 + 9 * M_SQRT2), 113 / (58 + 216 * M_SQRT2)}},
|
||||
.polar = true},
|
||||
{{SCALER_EWA_ROBIDOUXSHARP, 2,cubic_bc,
|
||||
.params = {6 / (13 + 7 * M_SQRT2), 7 / (2 + 12 * M_SQRT2)}},
|
||||
.polar = true},
|
||||
// Miscellaneous filters
|
||||
{{"box", 1, box, .resizable = true}},
|
||||
{{"nearest", 0.5, box}},
|
||||
{{"triangle", 1, triangle, .resizable = true}},
|
||||
{{"gaussian", 2, gaussian, .params = {1.0, NAN}, .resizable = true}},
|
||||
{{SCALER_BOX, 1, box, .resizable = true}},
|
||||
{{SCALER_NEAREST, 0.5, box}},
|
||||
{{SCALER_TRIANGLE, 1, triangle, .resizable = true}},
|
||||
{{SCALER_GAUSSIAN, 2, gaussian, .params = {1.0, NAN}, .resizable = true}},
|
||||
{{0}}
|
||||
};
|
||||
|
|
|
@ -14,8 +14,58 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
|
||||
enum scaler_filter {
|
||||
SCALER_INHERIT,
|
||||
SCALER_BILINEAR,
|
||||
SCALER_BICUBIC_FAST,
|
||||
SCALER_OVERSAMPLE,
|
||||
SCALER_LINEAR,
|
||||
SCALER_SPLINE16,
|
||||
SCALER_SPLINE36,
|
||||
SCALER_SPLINE64,
|
||||
SCALER_SINC,
|
||||
SCALER_LANCZOS,
|
||||
SCALER_GINSENG,
|
||||
SCALER_JINC,
|
||||
SCALER_EWA_LANCZOS,
|
||||
SCALER_EWA_HANNING,
|
||||
SCALER_EWA_GINSENG,
|
||||
SCALER_EWA_LANCZOSSHARP,
|
||||
SCALER_EWA_LANCZOS4SHARPEST,
|
||||
SCALER_EWA_LANCZOSSOFT,
|
||||
SCALER_HAASNSOFT,
|
||||
SCALER_BICUBIC,
|
||||
SCALER_HERMITE,
|
||||
SCALER_CATMULL_ROM,
|
||||
SCALER_MITCHELL,
|
||||
SCALER_ROBIDOUX,
|
||||
SCALER_ROBIDOUXSHARP,
|
||||
SCALER_EWA_ROBIDOUX,
|
||||
SCALER_EWA_ROBIDOUXSHARP,
|
||||
SCALER_BOX,
|
||||
SCALER_NEAREST,
|
||||
SCALER_TRIANGLE,
|
||||
SCALER_GAUSSIAN,
|
||||
WINDOW_PREFERRED,
|
||||
WINDOW_BOX,
|
||||
WINDOW_TRIANGLE,
|
||||
WINDOW_BARTLETT,
|
||||
WINDOW_COSINE,
|
||||
WINDOW_HANNING,
|
||||
WINDOW_TUKEY,
|
||||
WINDOW_HAMMING,
|
||||
WINDOW_QUADRIC,
|
||||
WINDOW_WELCH,
|
||||
WINDOW_KAISER,
|
||||
WINDOW_BLACKMAN,
|
||||
WINDOW_GAUSSIAN,
|
||||
WINDOW_SINC,
|
||||
WINDOW_JINC,
|
||||
WINDOW_SPHINX,
|
||||
};
|
||||
|
||||
struct filter_window {
|
||||
const char *name;
|
||||
enum scaler_filter function;
|
||||
double radius; // Preferred radius, should only be changed if resizable
|
||||
double (*weight)(struct filter_window *k, double x);
|
||||
bool resizable; // Filter supports any given radius
|
||||
|
@ -30,7 +80,7 @@ struct filter_kernel {
|
|||
struct filter_window w; // window storage
|
||||
double clamp; // clamping factor, affects negative weights
|
||||
// Constant values
|
||||
const char *window; // default window
|
||||
enum scaler_filter window; // default window
|
||||
bool polar; // whether or not the filter uses polar coordinates
|
||||
// The following values are set by mp_init_filter() at runtime.
|
||||
int size; // number of coefficients (may depend on radius)
|
||||
|
@ -45,8 +95,8 @@ struct filter_kernel {
|
|||
extern const struct filter_window mp_filter_windows[];
|
||||
extern const struct filter_kernel mp_filter_kernels[];
|
||||
|
||||
const struct filter_window *mp_find_filter_window(const char *name);
|
||||
const struct filter_kernel *mp_find_filter_kernel(const char *name);
|
||||
const struct filter_window *mp_find_filter_window(enum scaler_filter function);
|
||||
const struct filter_kernel *mp_find_filter_kernel(enum scaler_filter function);
|
||||
|
||||
bool mp_init_filter(struct filter_kernel *filter, const int *sizes,
|
||||
double scale);
|
||||
|
|
|
@ -45,20 +45,6 @@
|
|||
#include "video/out/dither.h"
|
||||
#include "video/out/vo.h"
|
||||
|
||||
// scale/cscale arguments that map directly to shader filter routines.
|
||||
// Note that the convolution filters are not included in this list.
|
||||
static const char *const fixed_scale_filters[] = {
|
||||
"bilinear",
|
||||
"bicubic_fast",
|
||||
"oversample",
|
||||
NULL
|
||||
};
|
||||
static const char *const fixed_tscale_filters[] = {
|
||||
"oversample",
|
||||
"linear",
|
||||
NULL
|
||||
};
|
||||
|
||||
// must be sorted, and terminated with 0
|
||||
int filter_sizes[] =
|
||||
{2, 4, 6, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 0};
|
||||
|
@ -295,6 +281,86 @@ struct gl_video {
|
|||
bool correct_downscaling_warned;
|
||||
};
|
||||
|
||||
#define FIXED_SCALE_KERNELS \
|
||||
{"bilinear", SCALER_BILINEAR}, \
|
||||
{"bicubic_fast", SCALER_BICUBIC_FAST}, \
|
||||
{"oversample", SCALER_OVERSAMPLE}, \
|
||||
|
||||
#define NON_POLAR_FILTER_KERNELS \
|
||||
{"spline16", SCALER_SPLINE16}, \
|
||||
{"spline36", SCALER_SPLINE36}, \
|
||||
{"spline64", SCALER_SPLINE64}, \
|
||||
{"sinc", SCALER_SINC}, \
|
||||
{"lanczos", SCALER_LANCZOS}, \
|
||||
{"ginseng", SCALER_GINSENG}, \
|
||||
{"bicubic", SCALER_BICUBIC}, \
|
||||
{"hermite", SCALER_HERMITE}, \
|
||||
{"catmull_rom", SCALER_CATMULL_ROM}, \
|
||||
{"mitchell", SCALER_MITCHELL}, \
|
||||
{"robidoux", SCALER_ROBIDOUX}, \
|
||||
{"robidouxsharp", SCALER_ROBIDOUXSHARP}, \
|
||||
{"box", SCALER_BOX}, \
|
||||
{"nearest", SCALER_NEAREST}, \
|
||||
{"triangle", SCALER_TRIANGLE}, \
|
||||
{"gaussian", SCALER_GAUSSIAN}, \
|
||||
|
||||
#define POLAR_FILTER_KERNELS \
|
||||
{"jinc", SCALER_JINC}, \
|
||||
{"ewa_lanczos", SCALER_EWA_LANCZOS}, \
|
||||
{"ewa_hanning", SCALER_EWA_HANNING}, \
|
||||
{"ewa_ginseng", SCALER_EWA_GINSENG}, \
|
||||
{"ewa_lanczossharp", SCALER_EWA_LANCZOSSHARP}, \
|
||||
{"ewa_lanczos4sharpest", SCALER_EWA_LANCZOS4SHARPEST}, \
|
||||
{"ewa_lanczossoft", SCALER_EWA_LANCZOSSOFT}, \
|
||||
{"haasnsoft", SCALER_HAASNSOFT}, \
|
||||
{"ewa_robidoux", SCALER_EWA_ROBIDOUX}, \
|
||||
{"ewa_robidouxsharp", SCALER_EWA_ROBIDOUXSHARP}, \
|
||||
|
||||
#define FILTER_WINDOWS \
|
||||
{"bartlett", WINDOW_BARTLETT}, \
|
||||
{"cosine", WINDOW_COSINE}, \
|
||||
{"hanning", WINDOW_HANNING}, \
|
||||
{"tukey", WINDOW_TUKEY}, \
|
||||
{"hamming", WINDOW_HAMMING}, \
|
||||
{"quadric", WINDOW_QUADRIC}, \
|
||||
{"welch", WINDOW_WELCH}, \
|
||||
{"kaiser", WINDOW_KAISER}, \
|
||||
{"blackman", WINDOW_BLACKMAN}, \
|
||||
{"sphinx", WINDOW_SPHINX}, \
|
||||
|
||||
static const struct m_opt_choice_alternatives scale_filters[] = {
|
||||
FIXED_SCALE_KERNELS
|
||||
NON_POLAR_FILTER_KERNELS
|
||||
POLAR_FILTER_KERNELS
|
||||
FILTER_WINDOWS
|
||||
{0},
|
||||
};
|
||||
|
||||
static const struct m_opt_choice_alternatives cdscale_filters[] = {
|
||||
{"", SCALER_INHERIT},
|
||||
FIXED_SCALE_KERNELS
|
||||
NON_POLAR_FILTER_KERNELS
|
||||
POLAR_FILTER_KERNELS
|
||||
FILTER_WINDOWS
|
||||
{0},
|
||||
};
|
||||
|
||||
static const struct m_opt_choice_alternatives tscale_filters[] = {
|
||||
{"oversample", SCALER_OVERSAMPLE},
|
||||
{"linear", SCALER_LINEAR},
|
||||
NON_POLAR_FILTER_KERNELS
|
||||
FILTER_WINDOWS
|
||||
{"jinc", WINDOW_JINC},
|
||||
{0},
|
||||
};
|
||||
|
||||
static const struct m_opt_choice_alternatives filter_windows[] = {
|
||||
{"", WINDOW_PREFERRED},
|
||||
FILTER_WINDOWS
|
||||
{"jinc", WINDOW_JINC},
|
||||
{0},
|
||||
};
|
||||
|
||||
static const struct gl_video_opts gl_video_opts_def = {
|
||||
.dither_algo = DITHER_FRUIT,
|
||||
.dither_size = 6,
|
||||
|
@ -304,10 +370,22 @@ static const struct gl_video_opts gl_video_opts_def = {
|
|||
.sigmoid_center = 0.75,
|
||||
.sigmoid_slope = 6.5,
|
||||
.scaler = {
|
||||
{{"lanczos", .params={NAN, NAN}}, {.params = {NAN, NAN}}}, // scale
|
||||
{{"hermite", .params={NAN, NAN}}, {.params = {NAN, NAN}}}, // dscale
|
||||
{{NULL, .params={NAN, NAN}}, {.params = {NAN, NAN}}}, // cscale
|
||||
{{"oversample", .params={NAN, NAN}}, {.params = {NAN, NAN}}}, // tscale
|
||||
[SCALER_SCALE] = {
|
||||
{SCALER_LANCZOS, .params = {NAN, NAN}, .functions = scale_filters},
|
||||
{WINDOW_PREFERRED, .params = {NAN, NAN}, .functions = filter_windows},
|
||||
},
|
||||
[SCALER_DSCALE] = {
|
||||
{SCALER_HERMITE, .params = {NAN, NAN}, .functions = cdscale_filters},
|
||||
{WINDOW_PREFERRED, .params = {NAN, NAN}, .functions = filter_windows},
|
||||
},
|
||||
[SCALER_CSCALE] = {
|
||||
{SCALER_INHERIT, .params = {NAN, NAN}, .functions = cdscale_filters},
|
||||
{WINDOW_PREFERRED, .params = {NAN, NAN}, .functions = filter_windows},
|
||||
},
|
||||
[SCALER_TSCALE] = {
|
||||
{SCALER_OVERSAMPLE, .params = {NAN, NAN}, .functions = tscale_filters},
|
||||
{WINDOW_PREFERRED, .params = {NAN, NAN}, .functions = filter_windows},
|
||||
},
|
||||
},
|
||||
.scaler_resizes_only = true,
|
||||
.correct_downscaling = true,
|
||||
|
@ -331,8 +409,6 @@ static const struct gl_video_opts gl_video_opts_def = {
|
|||
.hwdec_interop = "auto",
|
||||
};
|
||||
|
||||
static OPT_STRING_VALIDATE_FUNC(validate_scaler_opt);
|
||||
static OPT_STRING_VALIDATE_FUNC(validate_window_opt);
|
||||
static OPT_STRING_VALIDATE_FUNC(validate_error_diffusion_opt);
|
||||
|
||||
#define OPT_BASE_STRUCT struct gl_video_opts
|
||||
|
@ -343,7 +419,6 @@ static OPT_STRING_VALIDATE_FUNC(validate_error_diffusion_opt);
|
|||
.flags = M_OPT_DEFAULT_NAN
|
||||
|
||||
#define SCALER_OPTS(n, i) \
|
||||
{n, OPT_STRING_VALIDATE(scaler[i].kernel.name, validate_scaler_opt)}, \
|
||||
{n"-param1", OPT_FLOATDEF(scaler[i].kernel.params[0])}, \
|
||||
{n"-param2", OPT_FLOATDEF(scaler[i].kernel.params[1])}, \
|
||||
{n"-blur", OPT_FLOAT(scaler[i].kernel.blur)}, \
|
||||
|
@ -353,7 +428,7 @@ static OPT_STRING_VALIDATE_FUNC(validate_error_diffusion_opt);
|
|||
{n"-clamp", OPT_FLOAT(scaler[i].clamp), M_RANGE(0.0, 1.0)}, \
|
||||
{n"-radius", OPT_FLOAT(scaler[i].radius), M_RANGE(0.5, 16.0)}, \
|
||||
{n"-antiring", OPT_FLOAT(scaler[i].antiring), M_RANGE(0.0, 1.0)}, \
|
||||
{n"-window", OPT_STRING_VALIDATE(scaler[i].window.name, validate_window_opt)}
|
||||
{n"-window", OPT_CHOICE_C(scaler[i].window.function, filter_windows)}
|
||||
|
||||
const struct m_sub_options gl_video_conf = {
|
||||
.opts = (const m_option_t[]) {
|
||||
|
@ -416,9 +491,13 @@ const struct m_sub_options gl_video_conf = {
|
|||
{"hdr-contrast-smoothness", OPT_FLOAT(tone_map.contrast_smoothness),
|
||||
M_RANGE(1.0, 100.0)},
|
||||
{"opengl-pbo", OPT_BOOL(pbo)},
|
||||
{"scale", OPT_CHOICE_C(scaler[SCALER_SCALE].kernel.function, scale_filters)},
|
||||
SCALER_OPTS("scale", SCALER_SCALE),
|
||||
{"dscale", OPT_CHOICE_C(scaler[SCALER_DSCALE].kernel.function, cdscale_filters)},
|
||||
SCALER_OPTS("dscale", SCALER_DSCALE),
|
||||
{"cscale", OPT_CHOICE_C(scaler[SCALER_CSCALE].kernel.function, cdscale_filters)},
|
||||
SCALER_OPTS("cscale", SCALER_CSCALE),
|
||||
{"tscale", OPT_CHOICE_C(scaler[SCALER_TSCALE].kernel.function, tscale_filters)},
|
||||
SCALER_OPTS("tscale", SCALER_TSCALE),
|
||||
{"scaler-resizes-only", OPT_BOOL(scaler_resizes_only)},
|
||||
{"correct-downscaling", OPT_BOOL(correct_downscaling)},
|
||||
|
@ -481,7 +560,6 @@ static void uninit_rendering(struct gl_video *p);
|
|||
static void uninit_scaler(struct gl_video *p, struct scaler *scaler);
|
||||
static void check_gl_features(struct gl_video *p);
|
||||
static bool pass_upload_image(struct gl_video *p, struct mp_image *mpi, uint64_t id);
|
||||
static const char *handle_scaler_opt(const char *name, bool tscale);
|
||||
static void reinit_from_options(struct gl_video *p);
|
||||
static void get_scale_factors(struct gl_video *p, bool transpose_rot, double xy[2]);
|
||||
static void gl_video_setup_hooks(struct gl_video *p);
|
||||
|
@ -1663,10 +1741,7 @@ static bool double_seq(double a, double b)
|
|||
|
||||
static bool scaler_fun_eq(struct scaler_fun a, struct scaler_fun b)
|
||||
{
|
||||
if ((a.name && !b.name) || (b.name && !a.name))
|
||||
return false;
|
||||
|
||||
return ((!a.name && !b.name) || strcmp(a.name, b.name) == 0) &&
|
||||
return a.function == b.function &&
|
||||
double_seq(a.params[0], b.params[0]) &&
|
||||
double_seq(a.params[1], b.params[1]) &&
|
||||
a.blur == b.blur &&
|
||||
|
@ -1696,24 +1771,14 @@ static void reinit_scaler(struct gl_video *p, struct scaler *scaler,
|
|||
|
||||
uninit_scaler(p, scaler);
|
||||
|
||||
if (scaler->index == SCALER_DSCALE && (!conf->kernel.name ||
|
||||
!conf->kernel.name[0]))
|
||||
{
|
||||
if (conf->kernel.function == SCALER_INHERIT)
|
||||
conf = &p->opts.scaler[SCALER_SCALE];
|
||||
}
|
||||
|
||||
if (scaler->index == SCALER_CSCALE && (!conf->kernel.name ||
|
||||
!conf->kernel.name[0]))
|
||||
{
|
||||
conf = &p->opts.scaler[SCALER_SCALE];
|
||||
}
|
||||
|
||||
struct filter_kernel bare_window;
|
||||
const struct filter_kernel *t_kernel = mp_find_filter_kernel(conf->kernel.name);
|
||||
const struct filter_window *t_window = mp_find_filter_window(conf->window.name);
|
||||
bool is_tscale = scaler->index == SCALER_TSCALE;
|
||||
const struct filter_kernel *t_kernel = mp_find_filter_kernel(conf->kernel.function);
|
||||
const struct filter_window *t_window = mp_find_filter_window(conf->window.function);
|
||||
if (!t_kernel) {
|
||||
const struct filter_window *window = mp_find_filter_window(conf->kernel.name);
|
||||
const struct filter_window *window = mp_find_filter_window(conf->kernel.function);
|
||||
if (window) {
|
||||
bare_window = (struct filter_kernel) { .f = *window };
|
||||
t_kernel = &bare_window;
|
||||
|
@ -1721,8 +1786,6 @@ static void reinit_scaler(struct gl_video *p, struct scaler *scaler,
|
|||
}
|
||||
|
||||
scaler->conf = *conf;
|
||||
scaler->conf.kernel.name = (char *)handle_scaler_opt(conf->kernel.name, is_tscale);
|
||||
scaler->conf.window.name = t_window ? (char *)t_window->name : NULL;
|
||||
scaler->scale_factor = scale_factor;
|
||||
scaler->insufficient = false;
|
||||
scaler->initialized = true;
|
||||
|
@ -1819,7 +1882,9 @@ static void pass_sample_separated(struct gl_video *p, struct image src,
|
|||
// Second pass (scale only in the x dir)
|
||||
src = image_wrap(scaler->sep_fbo, src.type, src.components);
|
||||
src.transform = t_x;
|
||||
pass_describe(p, "%s second pass", scaler->conf.kernel.name);
|
||||
pass_describe(p, "%s second pass",
|
||||
m_opt_choice_str(scaler->conf.kernel.functions,
|
||||
scaler->conf.kernel.function));
|
||||
sampler_prelude(p->sc, pass_bind(p, src));
|
||||
pass_sample_separated_gen(p->sc, scaler, 1, 0);
|
||||
}
|
||||
|
@ -1888,7 +1953,9 @@ static void pass_sample(struct gl_video *p, struct image img,
|
|||
};
|
||||
|
||||
pass_describe(p, "%s=%s (%s)", scaler_opt[scaler->index],
|
||||
scaler->conf.kernel.name, plane_names[img.type]);
|
||||
m_opt_choice_str(scaler->conf.kernel.functions,
|
||||
scaler->conf.kernel.function),
|
||||
plane_names[img.type]);
|
||||
|
||||
bool is_separated = scaler->kernel && !scaler->kernel->polar;
|
||||
|
||||
|
@ -1898,12 +1965,11 @@ static void pass_sample(struct gl_video *p, struct image img,
|
|||
sampler_prelude(p->sc, pass_bind(p, img));
|
||||
|
||||
// Dispatch the scaler. They're all wildly different.
|
||||
const char *name = scaler->conf.kernel.name;
|
||||
if (strcmp(name, "bilinear") == 0) {
|
||||
if (scaler->conf.kernel.function == SCALER_BILINEAR) {
|
||||
GLSL(color = texture(tex, pos);)
|
||||
} else if (strcmp(name, "bicubic_fast") == 0) {
|
||||
} else if (scaler->conf.kernel.function == SCALER_BICUBIC_FAST) {
|
||||
pass_sample_bicubic_fast(p->sc);
|
||||
} else if (strcmp(name, "oversample") == 0) {
|
||||
} else if (scaler->conf.kernel.function == SCALER_OVERSAMPLE) {
|
||||
pass_sample_oversample(p->sc, scaler, w, h);
|
||||
} else if (scaler->kernel && scaler->kernel->polar) {
|
||||
pass_dispatch_sample_polar(p, scaler, img, w, h);
|
||||
|
@ -2290,16 +2356,13 @@ static void pass_read_video(struct gl_video *p)
|
|||
|
||||
const struct scaler_config *conf = &p->opts.scaler[scaler_id];
|
||||
|
||||
if (scaler_id == SCALER_CSCALE && (!conf->kernel.name ||
|
||||
!conf->kernel.name[0]))
|
||||
{
|
||||
if (conf->kernel.function == SCALER_INHERIT)
|
||||
conf = &p->opts.scaler[SCALER_SCALE];
|
||||
}
|
||||
|
||||
struct scaler *scaler = &p->scaler[scaler_id];
|
||||
|
||||
// bilinear scaling is a free no-op thanks to GPU sampling
|
||||
if (strcmp(conf->kernel.name, "bilinear") != 0) {
|
||||
if (conf->kernel.function != SCALER_BILINEAR) {
|
||||
GLSLF("// upscaling plane %d\n", n);
|
||||
pass_sample(p, img[n], scaler, conf, 1.0, p->texture_w, p->texture_h);
|
||||
finish_pass_tex(p, &p->scale_tex[n], p->texture_w, p->texture_h);
|
||||
|
@ -2460,7 +2523,7 @@ static void pass_scale_main(struct gl_video *p)
|
|||
struct scaler *scaler = &p->scaler[SCALER_SCALE];
|
||||
struct scaler_config scaler_conf = p->opts.scaler[SCALER_SCALE];
|
||||
if (p->opts.scaler_resizes_only && !downscaling && !upscaling) {
|
||||
scaler_conf.kernel.name = "bilinear";
|
||||
scaler_conf.kernel.function = SCALER_BILINEAR;
|
||||
// For scaler-resizes-only, we round the texture offset to
|
||||
// the nearest round value in order to prevent ugly blurriness
|
||||
// (in exchange for slightly shifting the image by up to half a
|
||||
|
@ -2468,7 +2531,8 @@ static void pass_scale_main(struct gl_video *p)
|
|||
p->texture_offset.t[0] = roundf(p->texture_offset.t[0]);
|
||||
p->texture_offset.t[1] = roundf(p->texture_offset.t[1]);
|
||||
}
|
||||
if (downscaling && p->opts.scaler[SCALER_DSCALE].kernel.name) {
|
||||
if (downscaling &&
|
||||
p->opts.scaler[SCALER_DSCALE].kernel.function != SCALER_INHERIT) {
|
||||
scaler_conf = p->opts.scaler[SCALER_DSCALE];
|
||||
scaler = &p->scaler[SCALER_DSCALE];
|
||||
}
|
||||
|
@ -3194,8 +3258,8 @@ static void gl_video_interpolate_frame(struct gl_video *p, struct vo_frame *t,
|
|||
// surface_end.
|
||||
struct scaler *tscale = &p->scaler[SCALER_TSCALE];
|
||||
reinit_scaler(p, tscale, &p->opts.scaler[SCALER_TSCALE], 1, tscale_sizes);
|
||||
bool oversample = strcmp(tscale->conf.kernel.name, "oversample") == 0;
|
||||
bool linear = strcmp(tscale->conf.kernel.name, "linear") == 0;
|
||||
bool oversample = tscale->conf.kernel.function == SCALER_OVERSAMPLE;
|
||||
bool linear = tscale->conf.kernel.function == SCALER_LINEAR;
|
||||
int size;
|
||||
|
||||
if (oversample || linear) {
|
||||
|
@ -3753,7 +3817,7 @@ static bool test_fbo(struct gl_video *p, const struct ra_format *fmt)
|
|||
}
|
||||
|
||||
// Return whether dumb-mode can be used without disabling any features.
|
||||
// Essentially, vo_gpu with mostly default settings will return true.
|
||||
// Essentially, vo_gpu with --profile=fast will return true.
|
||||
static bool check_dumb_mode(struct gl_video *p)
|
||||
{
|
||||
struct gl_video_opts *o = &p->opts;
|
||||
|
@ -3772,8 +3836,8 @@ static bool check_dumb_mode(struct gl_video *p)
|
|||
// check remaining scalers (tscale is already implicitly excluded above)
|
||||
for (int i = 0; i < SCALER_COUNT; i++) {
|
||||
if (i != SCALER_TSCALE) {
|
||||
const char *name = o->scaler[i].kernel.name;
|
||||
if (name && strcmp(name, "bilinear") != 0)
|
||||
if (o->scaler[i].kernel.function != SCALER_BILINEAR &&
|
||||
o->scaler[i].kernel.function != SCALER_INHERIT)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -3872,17 +3936,25 @@ static void check_gl_features(struct gl_video *p)
|
|||
"Most extended features will be disabled.\n");
|
||||
}
|
||||
p->dumb_mode = true;
|
||||
static const struct scaler_config dumb_scaler_config = {
|
||||
{"bilinear", .params = {NAN, NAN}},
|
||||
{.params = {NAN, NAN}},
|
||||
};
|
||||
// Most things don't work, so whitelist all options that still work.
|
||||
p->opts = (struct gl_video_opts){
|
||||
.scaler = {
|
||||
[SCALER_SCALE] = dumb_scaler_config,
|
||||
[SCALER_DSCALE] = dumb_scaler_config,
|
||||
[SCALER_CSCALE] = dumb_scaler_config,
|
||||
[SCALER_TSCALE] = dumb_scaler_config,
|
||||
[SCALER_SCALE] = {
|
||||
{SCALER_BILINEAR, .params = {NAN, NAN}, .functions = scale_filters},
|
||||
{WINDOW_PREFERRED, .params = {NAN, NAN}, .functions = filter_windows},
|
||||
},
|
||||
[SCALER_DSCALE] = {
|
||||
{SCALER_BILINEAR, .params = {NAN, NAN}, .functions = cdscale_filters},
|
||||
{WINDOW_PREFERRED, .params = {NAN, NAN}, .functions = filter_windows},
|
||||
},
|
||||
[SCALER_CSCALE] = {
|
||||
{SCALER_BILINEAR, .params = {NAN, NAN}, .functions = cdscale_filters},
|
||||
{WINDOW_PREFERRED, .params = {NAN, NAN}, .functions = filter_windows},
|
||||
},
|
||||
[SCALER_TSCALE] = {
|
||||
{SCALER_BILINEAR, .params = {NAN, NAN}, .functions = tscale_filters},
|
||||
{WINDOW_PREFERRED, .params = {NAN, NAN}, .functions = filter_windows},
|
||||
},
|
||||
},
|
||||
.gamma = p->opts.gamma,
|
||||
.gamma_auto = p->opts.gamma_auto,
|
||||
|
@ -3919,7 +3991,7 @@ static void check_gl_features(struct gl_video *p)
|
|||
// I don't know if luminance alpha float textures exist, so disregard them.
|
||||
for (int n = 0; n < SCALER_COUNT; n++) {
|
||||
const struct filter_kernel *kernel =
|
||||
mp_find_filter_kernel(p->opts.scaler[n].kernel.name);
|
||||
mp_find_filter_kernel(p->opts.scaler[n].kernel.function);
|
||||
if (kernel) {
|
||||
char *reason = NULL;
|
||||
if (!have_float_tex)
|
||||
|
@ -3928,9 +4000,12 @@ static void check_gl_features(struct gl_video *p)
|
|||
reason = "(GLSL version too old)";
|
||||
if (reason) {
|
||||
MP_WARN(p, "Disabling scaler #%d %s %s.\n", n,
|
||||
p->opts.scaler[n].kernel.name, reason);
|
||||
m_opt_choice_str(p->opts.scaler[n].kernel.functions,
|
||||
p->opts.scaler[n].kernel.function),
|
||||
reason);
|
||||
|
||||
// p->opts is a copy => we can just mess with it.
|
||||
p->opts.scaler[n].kernel.name = "bilinear";
|
||||
p->opts.scaler[n].kernel.function = SCALER_BILINEAR;
|
||||
if (n == SCALER_TSCALE)
|
||||
p->opts.interpolation = false;
|
||||
}
|
||||
|
@ -4097,29 +4172,6 @@ struct gl_video *gl_video_init(struct ra *ra, struct mp_log *log,
|
|||
return p;
|
||||
}
|
||||
|
||||
// Get static string for scaler shader. If "tscale" is set to true, the
|
||||
// scaler must be a separable convolution filter.
|
||||
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->f.name;
|
||||
|
||||
const struct filter_window *window = mp_find_filter_window(name);
|
||||
if (window)
|
||||
return window->name;
|
||||
|
||||
for (const char *const *filter = tscale ? fixed_tscale_filters
|
||||
: fixed_scale_filters;
|
||||
*filter; filter++) {
|
||||
if (strcmp(*filter, name) == 0)
|
||||
return *filter;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void gl_video_update_options(struct gl_video *p)
|
||||
{
|
||||
if (m_config_cache_update(p->opts_cache)) {
|
||||
|
@ -4160,10 +4212,9 @@ static void reinit_from_options(struct gl_video *p)
|
|||
talloc_free(vo_opts);
|
||||
|
||||
if (p->opts.correct_downscaling && !p->correct_downscaling_warned) {
|
||||
const char *name = p->opts.scaler[SCALER_DSCALE].kernel.name;
|
||||
if (!name)
|
||||
name = p->opts.scaler[SCALER_SCALE].kernel.name;
|
||||
if (!name || !strcmp(name, "bilinear")) {
|
||||
if (p->opts.scaler[SCALER_DSCALE].kernel.function == SCALER_BILINEAR ||
|
||||
(p->opts.scaler[SCALER_DSCALE].kernel.function == SCALER_INHERIT &&
|
||||
p->opts.scaler[SCALER_SCALE].kernel.function == SCALER_BILINEAR)) {
|
||||
MP_WARN(p, "correct-downscaling requires non-bilinear scaler.\n");
|
||||
p->correct_downscaling_warned = true;
|
||||
}
|
||||
|
@ -4180,7 +4231,7 @@ void gl_video_configure_queue(struct gl_video *p, struct vo *vo)
|
|||
// the radius, the earlier we need to queue frames.
|
||||
if (p->opts.interpolation) {
|
||||
const struct filter_kernel *kernel =
|
||||
mp_find_filter_kernel(p->opts.scaler[SCALER_TSCALE].kernel.name);
|
||||
mp_find_filter_kernel(p->opts.scaler[SCALER_TSCALE].kernel.function);
|
||||
if (kernel) {
|
||||
// filter_scale wouldn't be correctly initialized were we to use it here.
|
||||
// This is fine since we're always upsampling, but beware if downsampling
|
||||
|
@ -4197,75 +4248,6 @@ void gl_video_configure_queue(struct gl_video *p, struct vo *vo)
|
|||
vo_set_queue_params(vo, 0, queue_size);
|
||||
}
|
||||
|
||||
static int validate_scaler_opt(struct mp_log *log, const m_option_t *opt,
|
||||
struct bstr name, const char **value)
|
||||
{
|
||||
struct bstr param = bstr0(*value);
|
||||
char s[32] = {0};
|
||||
int r = 1;
|
||||
bool tscale = bstr_equals0(name, "tscale");
|
||||
if (bstr_equals0(param, "help")) {
|
||||
r = M_OPT_EXIT;
|
||||
} else if (bstr_equals0(name, "dscale") && !param.len) {
|
||||
return r; // empty dscale means "use same as upscaler"
|
||||
} else if (bstr_equals0(name, "cscale") && !param.len) {
|
||||
return r; // empty cscale means "use same as upscaler"
|
||||
} else {
|
||||
snprintf(s, sizeof(s), "%.*s", BSTR_P(param));
|
||||
if (!handle_scaler_opt(s, tscale))
|
||||
r = M_OPT_INVALID;
|
||||
}
|
||||
if (r < 1) {
|
||||
mp_info(log, "Available scalers:\n");
|
||||
for (const char *const *filter = tscale ? fixed_tscale_filters
|
||||
: fixed_scale_filters;
|
||||
*filter; filter++) {
|
||||
mp_info(log, " %s\n", *filter);
|
||||
}
|
||||
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].f.name);
|
||||
}
|
||||
for (int n = 0; mp_filter_windows[n].name; n++) {
|
||||
for (int m = 0; mp_filter_kernels[m].f.name; m++) {
|
||||
if (!strcmp(mp_filter_windows[n].name, mp_filter_kernels[m].f.name))
|
||||
goto next_window; // don't log duplicates
|
||||
}
|
||||
mp_info(log, " %s\n", mp_filter_windows[n].name);
|
||||
next_window: ;
|
||||
}
|
||||
if (s[0])
|
||||
mp_fatal(log, "No scaler named '%s' found!\n", s);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static int validate_window_opt(struct mp_log *log, const m_option_t *opt,
|
||||
struct bstr name, const char **value)
|
||||
{
|
||||
struct bstr param = bstr0(*value);
|
||||
char s[32] = {0};
|
||||
int r = 1;
|
||||
if (bstr_equals0(param, "help")) {
|
||||
r = M_OPT_EXIT;
|
||||
} else if (!param.len) {
|
||||
return r; // empty string means "use preferred window"
|
||||
} 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;
|
||||
}
|
||||
|
||||
static int validate_error_diffusion_opt(struct mp_log *log, const m_option_t *opt,
|
||||
struct bstr name, const char **value)
|
||||
{
|
||||
|
|
|
@ -29,10 +29,11 @@
|
|||
#include "video/out/filter_kernels.h"
|
||||
|
||||
struct scaler_fun {
|
||||
char *name;
|
||||
int function;
|
||||
float params[2];
|
||||
float blur;
|
||||
float taper;
|
||||
const struct m_opt_choice_alternatives *functions;
|
||||
};
|
||||
|
||||
struct scaler_config {
|
||||
|
|
|
@ -1907,13 +1907,13 @@ static const struct pl_filter_config *map_scaler(struct priv *p,
|
|||
|
||||
const struct gl_video_opts *opts = p->opts_cache->opts;
|
||||
const struct scaler_config *cfg = &opts->scaler[unit];
|
||||
if (unit == SCALER_DSCALE && (!cfg->kernel.name || !cfg->kernel.name[0]))
|
||||
cfg = &opts->scaler[SCALER_SCALE];
|
||||
if (unit == SCALER_CSCALE && (!cfg->kernel.name || !cfg->kernel.name[0]))
|
||||
if (cfg->kernel.function == SCALER_INHERIT)
|
||||
cfg = &opts->scaler[SCALER_SCALE];
|
||||
const char *kernel_name = m_opt_choice_str(cfg->kernel.functions,
|
||||
cfg->kernel.function);
|
||||
|
||||
for (int i = 0; fixed_presets[i].name; i++) {
|
||||
if (strcmp(cfg->kernel.name, fixed_presets[i].name) == 0)
|
||||
if (strcmp(kernel_name, fixed_presets[i].name) == 0)
|
||||
return fixed_presets[i].filter;
|
||||
}
|
||||
|
||||
|
@ -1921,9 +1921,9 @@ static const struct pl_filter_config *map_scaler(struct priv *p,
|
|||
struct scaler_params *par = &p->scalers[unit];
|
||||
const struct pl_filter_preset *preset;
|
||||
const struct pl_filter_function_preset *fpreset;
|
||||
if ((preset = pl_find_filter_preset(cfg->kernel.name))) {
|
||||
if ((preset = pl_find_filter_preset(kernel_name))) {
|
||||
par->config = *preset->filter;
|
||||
} else if ((fpreset = pl_find_filter_function_preset(cfg->kernel.name))) {
|
||||
} else if ((fpreset = pl_find_filter_function_preset(kernel_name))) {
|
||||
par->config = (struct pl_filter_config) {
|
||||
.kernel = fpreset->function,
|
||||
.params[0] = fpreset->function->params[0],
|
||||
|
@ -1931,12 +1931,13 @@ static const struct pl_filter_config *map_scaler(struct priv *p,
|
|||
};
|
||||
} else {
|
||||
MP_ERR(p, "Failed mapping filter function '%s', no libplacebo analog?\n",
|
||||
cfg->kernel.name);
|
||||
kernel_name);
|
||||
return &pl_filter_bilinear;
|
||||
}
|
||||
|
||||
const struct pl_filter_function_preset *wpreset;
|
||||
if ((wpreset = pl_find_filter_function_preset(cfg->window.name))) {
|
||||
if ((wpreset = pl_find_filter_function_preset(
|
||||
m_opt_choice_str(cfg->window.functions, cfg->window.function)))) {
|
||||
par->config.window = wpreset->function;
|
||||
par->config.wparams[0] = wpreset->function->params[0];
|
||||
par->config.wparams[1] = wpreset->function->params[1];
|
||||
|
@ -1959,7 +1960,7 @@ static const struct pl_filter_config *map_scaler(struct priv *p,
|
|||
par->config.radius = cfg->radius;
|
||||
} else {
|
||||
MP_WARN(p, "Filter radius specified but filter '%s' is not "
|
||||
"resizable, ignoring\n", cfg->kernel.name);
|
||||
"resizable, ignoring\n", kernel_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue