summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNiklas Haas <git@nand.wakku.to>2015-02-19 14:03:18 +0100
committerDiogo Franco (Kovensky) <diogomfranco@gmail.com>2015-02-21 20:48:24 +0900
commitf67dfcbec60e6456059f0ff748b3e84bae18c13f (patch)
tree16220510ae491d60ec7097bef3281b1f44387308
parent6b9f7923af52fc7c13e772ab7b23c115c7919062 (diff)
downloadmpv-f67dfcbec60e6456059f0ff748b3e84bae18c13f.tar.bz2
mpv-f67dfcbec60e6456059f0ff748b3e84bae18c13f.tar.xz
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. (cherry picked from commit 4356e893a138e24f2d54dee2b96d2720e69d4c18)
-rw-r--r--video/out/gl_video.c55
1 files changed, 31 insertions, 24 deletions
diff --git a/video/out/gl_video.c b/video/out/gl_video.c
index 1c70d56674..f43ad71858 100644
--- a/video/out/gl_video.c
+++ b/video/out/gl_video.c
@@ -1739,36 +1739,43 @@ static void gl_video_interpolate_frame(struct gl_video *p,
GL *gl = p->gl;
double inter_coeff = 0.0;
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");
- // fbosurface 0 is already bound from the caller
p->surfaces[p->surface_idx].pts = t->pts;
p->surface_idx = fbosurface_next(p);
- gl->ActiveTexture(GL_TEXTURE0 + 1);
- gl->BindTexture(p->gl_target, p->surfaces[p->surface_idx].fbotex.texture);
- gl->ActiveTexture(GL_TEXTURE0);
- if (prev_pts < t->next_vsync && t->pts > t->next_vsync) {
- double N = t->next_vsync - t->prev_vsync;
- double P = t->pts - t->prev_vsync;
- float ts = p->opts.smoothmotion_threshold;
- inter_coeff = 1 - (N / P);
- inter_coeff = inter_coeff < 0.0 + ts ? 0.0 : inter_coeff;
- inter_coeff = inter_coeff > 1.0 - ts ? 1.0 : inter_coeff;
- MP_DBG(p, "inter frame ppts: %lld, pts: %lld, "
- "vsync: %lld, mix: %f\n",
- (long long)prev_pts, (long long)t->pts,
- (long long)t->next_vsync, inter_coeff);
- MP_STATS(p, "frame-mix");
-
- // the value is scaled to fit in the graph with the completely
- // unrelated "phase" value (which is stupid)
- MP_STATS(p, "value-timed %lld %f mix-value",
- (long long)t->pts, inter_coeff * 10000);
- }
}
+ // fbosurface 0 is already bound from the caller
+ gl->ActiveTexture(GL_TEXTURE0 + 1);
+ gl->BindTexture(p->gl_target, p->surfaces[p->surface_idx].fbotex.texture);
+ gl->ActiveTexture(GL_TEXTURE0);
+
+ if (t->pts > t->next_vsync && t->pts < t->next_vsync + vsync_interval) {
+ // current frame overlaps PTS boundary, blend
+ double R = t->pts - t->next_vsync;
+ float ts = p->opts.smoothmotion_threshold;
+ inter_coeff = R / vsync_interval;
+ inter_coeff = inter_coeff < 0.0 + ts ? 0.0 : inter_coeff;
+ inter_coeff = inter_coeff > 1.0 - ts ? 1.0 : inter_coeff;
+ MP_DBG(p, "inter frame ppts: %lld, pts: %lld, "
+ "vsync: %lld, mix: %f\n",
+ (long long)prev_pts, (long long)t->pts,
+ (long long)t->next_vsync, inter_coeff);
+ MP_STATS(p, "frame-mix");
+
+ // the value is scaled to fit in the graph with the completely
+ // unrelated "phase" value (which is stupid)
+ MP_STATS(p, "value-timed %lld %f mix-value",
+ (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);
GLint loc = gl->GetUniformLocation(p->inter_program, "inter_coeff");
gl->Uniform1f(loc, inter_coeff);