summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2015-11-25 22:11:58 +0100
committerwm4 <wm4@nowhere>2015-11-25 23:30:52 +0100
commit12eb8b2de8b0ce5a9c45dbcdf3befc5075a35c98 (patch)
tree360ee143330ae256df5c170ec570a0ab75fc4396 /video
parent44376d2d9bc36ca7d057e414243fb7de9d4a01cd (diff)
downloadmpv-12eb8b2de8b0ce5a9c45dbcdf3befc5075a35c98.tar.bz2
mpv-12eb8b2de8b0ce5a9c45dbcdf3befc5075a35c98.tar.xz
vo: smooth out reported vsync time
Return the estimated/ideal flip time to the timing logic (meaning vo_get_delay() returns a smoothed out time). In addition to this add some lame but working drift compensation. (Useful especially if the display FPS is wrong by a factor such as 1.001.) Also remove some older leftovers. The vsync_interval_approx and last_flip fields are redundant or unneeded.
Diffstat (limited to 'video')
-rw-r--r--video/out/vo.c41
1 files changed, 23 insertions, 18 deletions
diff --git a/video/out/vo.c b/video/out/vo.c
index 3d12e7f3b3..be0e2c6933 100644
--- a/video/out/vo.c
+++ b/video/out/vo.c
@@ -144,6 +144,7 @@ struct vo_internal {
int num_vsync_samples;
int64_t prev_vsync;
int64_t base_vsync;
+ int drop_point;
double estimated_vsync_interval;
double estimated_vsync_jitter;
bool expecting_vsync;
@@ -165,8 +166,6 @@ struct vo_internal {
double display_fps;
// --- The following fields can be accessed from the VO thread only
- int64_t vsync_interval_approx;
- int64_t last_flip;
char *window_title;
};
@@ -324,6 +323,7 @@ static void reset_vsync_timings(struct vo *vo)
{
struct vo_internal *in = vo->in;
in->num_vsync_samples = 0;
+ in->drop_point = 0;
in->prev_vsync = 0;
in->estimated_vsync_interval = 0;
in->estimated_vsync_jitter = -1;
@@ -342,12 +342,17 @@ static void update_vsync_timing_after_swap(struct vo *vo)
}
int64_t now = mp_time_us();
- if (in->num_vsync_samples >= 200)
+ int max_samples = 200;
+ if (in->num_vsync_samples >= max_samples)
in->num_vsync_samples -= 1;
MP_TARRAY_INSERT_AT(in, in->vsync_samples, in->num_vsync_samples, 0,
now - in->prev_vsync);
- if (!in->base_vsync)
+ in->drop_point = MPMIN(in->drop_point + 1, in->num_vsync_samples);
+ if (in->base_vsync) {
+ in->base_vsync += in->vsync_interval;
+ } else {
in->base_vsync = now;
+ }
in->prev_vsync = now;
double avg = 0, jitter = 0;
@@ -361,6 +366,7 @@ static void update_vsync_timing_after_swap(struct vo *vo)
in->estimated_vsync_jitter = sqrt(jitter / in->num_vsync_samples);
MP_STATS(vo, "value %f jitter", in->estimated_vsync_jitter);
+ MP_STATS(vo, "value %f vsync-diff", in->vsync_samples[0] / 1e6);
if (llabs(in->base_vsync - now) > in->vsync_interval * 2 / 3) {
// Assume a drop. An underflow can technically speaking not be a drop
@@ -368,10 +374,19 @@ static void update_vsync_timing_after_swap(struct vo *vo)
// to treat it differently.
in->base_vsync = now;
in->delayed_count += 1;
+ in->drop_point = 0;
MP_STATS(vo, "vo-delayed");
}
- in->base_vsync += in->vsync_interval;
+ // Smooth out drift.
+ int64_t t_r = now, t_e = in->base_vsync, diff = 0;
+ for (int n = 0; n < in->drop_point - 1; n++) {
+ diff += t_r - t_e;
+ t_r -= in->vsync_samples[n];
+ t_e -= in->vsync_interval;
+ }
+ if (in->drop_point > 10)
+ in->base_vsync += diff * 0.1 / in->num_vsync_samples;
}
// to be called from VO thread only
@@ -700,7 +715,7 @@ static bool render_frame(struct vo *vo)
in->dropped_frame &= (vo->global->opts->frame_dropping & 1);
// Even if we're hopelessly behind, rather degrade to 10 FPS playback,
// instead of just freezing the display forever.
- in->dropped_frame &= mp_time_us() - in->last_flip < 100 * 1000;
+ in->dropped_frame &= mp_time_us() - in->prev_vsync < 100 * 1000;
in->dropped_frame &= in->hasframe_rendered;
// Setup parameters for the next time this frame is drawn. ("frame" is the
@@ -738,10 +753,6 @@ static bool render_frame(struct vo *vo)
vo->driver->flip_page(vo);
- int64_t prev_flip = in->last_flip;
- in->last_flip = mp_time_us();
- in->vsync_interval_approx = in->last_flip - prev_flip;
-
MP_STATS(vo, "end video");
MP_STATS(vo, "video_end");
@@ -749,10 +760,6 @@ static bool render_frame(struct vo *vo)
in->dropped_frame = prev_drop_count < vo->in->drop_count;
in->rendering = false;
- double diff = (in->vsync_interval - in->vsync_interval_approx) / 1e6;
- if (fabs(diff) < 0.150)
- MP_STATS(vo, "value %f vsync-diff", diff);
-
update_vsync_timing_after_swap(vo);
}
@@ -877,7 +884,6 @@ void vo_set_paused(struct vo *vo, bool paused)
in->paused = paused;
if (in->paused && in->dropped_frame)
in->request_redraw = true;
- in->last_flip = 0;
reset_vsync_timings(vo);
}
pthread_mutex_unlock(&in->lock);
@@ -925,7 +931,6 @@ void vo_seek_reset(struct vo *vo)
struct vo_internal *in = vo->in;
pthread_mutex_lock(&in->lock);
forget_frames(vo);
- in->last_flip = 0;
reset_vsync_timings(vo);
in->send_reset = true;
wakeup_locked(vo);
@@ -1066,8 +1071,8 @@ double vo_get_delay(struct vo *vo)
pthread_mutex_lock(&in->lock);
assert (!in->frame_queued);
int64_t res = 0;
- if (in->last_flip && in->vsync_interval > 1 && in->current_frame) {
- res = in->last_flip;
+ if (in->base_vsync && in->vsync_interval > 1 && in->current_frame) {
+ res = in->base_vsync;
int extra = !!in->rendering;
res += (in->current_frame->num_vsyncs + extra) * in->vsync_interval;
if (!in->current_frame->display_synced)