1
0
mirror of https://github.com/mpv-player/mpv synced 2024-12-19 05:15:12 +00:00

vo_opengl: reimplement tscale=oversample

Closes #2102.
This commit is contained in:
Niklas Haas 2015-07-11 13:55:45 +02:00
parent 4b0b9b515b
commit 3007250824
No known key found for this signature in database
GPG Key ID: 3BA77D4BFDB10BCE
2 changed files with 33 additions and 10 deletions

View File

@ -495,7 +495,7 @@ Available video output drivers are:
The filter used for interpolating the temporal axis (frames). This is The filter used for interpolating the temporal axis (frames). This is
only used if ``interpolation`` is enabled. The only valid choices only used if ``interpolation`` is enabled. The only valid choices
for ``tscale`` are separable convolution filters (use ``tscale=help`` for ``tscale`` are separable convolution filters (use ``tscale=help``
to get a list). The default is ``robidoux``. to get a list). The default is ``oversample``.
Note that the maximum supported filter radius is currently 3, due to Note that the maximum supported filter radius is currently 3, due to
limitations in the number of video textures that can be loaded limitations in the number of video textures that can be loaded

View File

@ -64,7 +64,7 @@ static const char *const fixed_scale_filters[] = {
NULL NULL
}; };
static const char *const fixed_tscale_filters[] = { static const char *const fixed_tscale_filters[] = {
//"oversample", "oversample",
NULL NULL
}; };
@ -340,7 +340,7 @@ const struct gl_video_opts gl_video_opts_def = {
{{"bilinear", .params={NAN, NAN}}, {.params = {NAN, NAN}}}, // scale {{"bilinear", .params={NAN, NAN}}, {.params = {NAN, NAN}}}, // scale
{{NULL, .params={NAN, NAN}}, {.params = {NAN, NAN}}}, // dscale {{NULL, .params={NAN, NAN}}, {.params = {NAN, NAN}}}, // dscale
{{"bilinear", .params={NAN, NAN}}, {.params = {NAN, NAN}}}, // cscale {{"bilinear", .params={NAN, NAN}}, {.params = {NAN, NAN}}}, // cscale
{{"robidoux", .params={NAN, NAN}}, {.params = {NAN, NAN}}}, // tscale {{"oversample", .params={NAN, NAN}}, {.params = {NAN, NAN}}}, // tscale
}, },
.alpha_mode = 2, .alpha_mode = 2,
.background = {0, 0, 0, 255}, .background = {0, 0, 0, 255},
@ -2106,11 +2106,16 @@ static void gl_video_interpolate_frame(struct gl_video *p, struct vo_frame *t,
// surface_end. // surface_end.
struct scaler *tscale = &p->scaler[3]; struct scaler *tscale = &p->scaler[3];
reinit_scaler(p, tscale, &p->opts.scaler[3], 1, tscale_sizes); reinit_scaler(p, tscale, &p->opts.scaler[3], 1, tscale_sizes);
bool oversample = strcmp(tscale->conf.kernel.name, "oversample") == 0;
int size; int size;
if (oversample) {
size = 2;
} else {
assert(tscale->kernel && !tscale->kernel->polar); assert(tscale->kernel && !tscale->kernel->polar);
size = ceil(tscale->kernel->size); size = ceil(tscale->kernel->size);
assert(size <= TEXUNIT_VIDEO_NUM); assert(size <= TEXUNIT_VIDEO_NUM);
}
int radius = size/2; int radius = size/2;
int surface_now = p->surface_now; int surface_now = p->surface_now;
@ -2192,9 +2197,24 @@ static void gl_video_interpolate_frame(struct gl_video *p, struct vo_frame *t,
} }
} }
// Non-oversample case // Blend the frames together
if (oversample) {
double vsync_dist = (t->next_vsync - t->prev_vsync)/1e6
/ (pts_nxt - pts_now),
threshold = tscale->conf.kernel.params[0];
threshold = isnan(threshold) ? 0.0 : threshold;
mix = (1 - mix) / vsync_dist;
mix = mix <= 0 + threshold ? 0 : mix;
mix = mix >= 1 - threshold ? 1 : mix;
mix = 1 - mix;
gl_sc_uniform_f(p->sc, "inter_coeff", mix);
GLSL(vec4 color = mix(texture(texture0, texcoord0),
texture(texture1, texcoord1),
inter_coeff);)
} else {
gl_sc_uniform_f(p->sc, "fcoord", mix); gl_sc_uniform_f(p->sc, "fcoord", mix);
pass_sample_separated_gen(p, tscale, 0, 0); pass_sample_separated_gen(p, tscale, 0, 0);
}
// Load all the required frames // Load all the required frames
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
@ -2820,6 +2840,9 @@ void gl_video_set_options(struct gl_video *p, struct gl_video_opts *opts,
double radius = kernel->f.radius; double radius = kernel->f.radius;
radius = radius > 0 ? radius : p->opts.scaler[3].radius; radius = radius > 0 ? radius : p->opts.scaler[3].radius;
*queue_size = 1 + ceil(radius); *queue_size = 1 + ceil(radius);
} else {
// Oversample case
*queue_size = 2;
} }
} }