mirror of https://github.com/mpv-player/mpv
vo_opengl: fix smoothmotion coefficient calculation, for real this time
I've reworked pretty much all the logic to correspond to what the theory actually describes. With this commit, playback is wonderfully smooth on my machine.
This commit is contained in:
parent
611f9ab0a8
commit
4356e893a1
|
@ -1739,21 +1739,24 @@ static void gl_video_interpolate_frame(struct gl_video *p,
|
||||||
GL *gl = p->gl;
|
GL *gl = p->gl;
|
||||||
double inter_coeff = 0.0;
|
double inter_coeff = 0.0;
|
||||||
int64_t prev_pts = p->surfaces[fbosurface_next(p)].pts;
|
int64_t prev_pts = p->surfaces[fbosurface_next(p)].pts;
|
||||||
p->is_interpolated = prev_pts < t->pts;
|
int64_t vsync_interval = t->next_vsync - t->prev_vsync;
|
||||||
|
|
||||||
if (p->is_interpolated) {
|
if (prev_pts < t->pts) {
|
||||||
MP_STATS(p, "new-pts");
|
MP_STATS(p, "new-pts");
|
||||||
// fbosurface 0 is already bound from the caller
|
|
||||||
p->surfaces[p->surface_idx].pts = t->pts;
|
p->surfaces[p->surface_idx].pts = t->pts;
|
||||||
p->surface_idx = fbosurface_next(p);
|
p->surface_idx = fbosurface_next(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fbosurface 0 is already bound from the caller
|
||||||
gl->ActiveTexture(GL_TEXTURE0 + 1);
|
gl->ActiveTexture(GL_TEXTURE0 + 1);
|
||||||
gl->BindTexture(p->gl_target, p->surfaces[p->surface_idx].fbotex.texture);
|
gl->BindTexture(p->gl_target, p->surfaces[p->surface_idx].fbotex.texture);
|
||||||
gl->ActiveTexture(GL_TEXTURE0);
|
gl->ActiveTexture(GL_TEXTURE0);
|
||||||
if (prev_pts < t->next_vsync && t->pts > t->next_vsync) {
|
|
||||||
double N = t->next_vsync - t->prev_vsync;
|
if (t->pts > t->next_vsync && t->pts < t->next_vsync + vsync_interval) {
|
||||||
double P = t->pts - t->prev_vsync;
|
// current frame overlaps PTS boundary, blend
|
||||||
|
double R = t->pts - t->next_vsync;
|
||||||
float ts = p->opts.smoothmotion_threshold;
|
float ts = p->opts.smoothmotion_threshold;
|
||||||
inter_coeff = 1 - (N / P);
|
inter_coeff = R / vsync_interval;
|
||||||
inter_coeff = inter_coeff < 0.0 + ts ? 0.0 : inter_coeff;
|
inter_coeff = inter_coeff < 0.0 + ts ? 0.0 : inter_coeff;
|
||||||
inter_coeff = inter_coeff > 1.0 - ts ? 1.0 : inter_coeff;
|
inter_coeff = inter_coeff > 1.0 - ts ? 1.0 : inter_coeff;
|
||||||
MP_DBG(p, "inter frame ppts: %lld, pts: %lld, "
|
MP_DBG(p, "inter frame ppts: %lld, pts: %lld, "
|
||||||
|
@ -1766,9 +1769,13 @@ static void gl_video_interpolate_frame(struct gl_video *p,
|
||||||
// unrelated "phase" value (which is stupid)
|
// unrelated "phase" value (which is stupid)
|
||||||
MP_STATS(p, "value-timed %lld %f mix-value",
|
MP_STATS(p, "value-timed %lld %f mix-value",
|
||||||
(long long)t->pts, inter_coeff * 10000);
|
(long long)t->pts, inter_coeff * 10000);
|
||||||
}
|
} else if (t->pts > t->next_vsync) {
|
||||||
|
// there's a new frame, but we haven't displayed or blended it yet,
|
||||||
|
// so we still draw the old frame
|
||||||
|
inter_coeff = 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p->is_interpolated = inter_coeff > 0.0;
|
||||||
gl->UseProgram(p->inter_program);
|
gl->UseProgram(p->inter_program);
|
||||||
GLint loc = gl->GetUniformLocation(p->inter_program, "inter_coeff");
|
GLint loc = gl->GetUniformLocation(p->inter_program, "inter_coeff");
|
||||||
gl->Uniform1f(loc, inter_coeff);
|
gl->Uniform1f(loc, inter_coeff);
|
||||||
|
|
Loading…
Reference in New Issue