summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
Diffstat (limited to 'video')
-rw-r--r--video/out/vo.c77
-rw-r--r--video/out/vo.h2
2 files changed, 79 insertions, 0 deletions
diff --git a/video/out/vo.c b/video/out/vo.c
index 6606cf82f7..883d0e9818 100644
--- a/video/out/vo.c
+++ b/video/out/vo.c
@@ -142,6 +142,13 @@ struct vo_internal {
int64_t vsync_interval;
+ int64_t *vsync_samples;
+ int num_vsync_samples;
+ int64_t prev_vsync;
+ double estimated_vsync_interval;
+ double estimated_vsync_jitter;
+ bool expecting_vsync;
+
int64_t flip_queue_offset; // queue flip events at most this much in advance
int64_t delayed_count;
@@ -312,6 +319,48 @@ void vo_destroy(struct vo *vo)
dealloc_vo(vo);
}
+// Drop timing information on discontinuities like seeking.
+// Always called locked.
+static void reset_vsync_timings(struct vo *vo)
+{
+ struct vo_internal *in = vo->in;
+ in->num_vsync_samples = 0;
+ in->prev_vsync = 0;
+ in->estimated_vsync_interval = 0;
+ in->estimated_vsync_jitter = -1;
+ in->expecting_vsync = false;
+}
+
+// Always called locked.
+static void update_vsync_timing_after_swap(struct vo *vo)
+{
+ struct vo_internal *in = vo->in;
+
+ if (!in->expecting_vsync || !in->prev_vsync) {
+ reset_vsync_timings(vo);
+ return;
+ }
+
+ int64_t now = mp_time_us();
+ if (in->num_vsync_samples >= 200)
+ in->num_vsync_samples -= 1;
+ MP_TARRAY_INSERT_AT(in, in->vsync_samples, in->num_vsync_samples, 0,
+ now - in->prev_vsync);
+ in->prev_vsync = now;
+
+ double avg = 0, jitter = 0;
+ for (int n = 0; n < in->num_vsync_samples; n++) {
+ avg += in->vsync_samples[n] / 1e6;
+ double diff = in->vsync_samples[n] / (double)in->vsync_interval - 1.0;
+ jitter += diff * diff;
+ }
+ avg /= in->num_vsync_samples;
+ in->estimated_vsync_interval = avg;
+ in->estimated_vsync_jitter = sqrt(jitter / in->num_vsync_samples);
+
+ MP_STATS(vo, "value %f jitter", in->estimated_vsync_jitter);
+}
+
// to be called from VO thread only
static void update_display_fps(struct vo *vo)
{
@@ -383,6 +432,7 @@ static void run_reconfig(void *p)
talloc_free(in->current_frame);
in->current_frame = NULL;
forget_frames(vo);
+ reset_vsync_timings(vo);
pthread_mutex_unlock(&in->lock);
update_display_fps(vo);
@@ -705,6 +755,10 @@ static bool render_frame(struct vo *vo)
if (in->current_frame->num_vsyncs > 0)
in->current_frame->num_vsyncs -= 1;
+ in->expecting_vsync = in->current_frame->display_synced && !in->paused;
+ if (in->expecting_vsync && !in->prev_vsync)
+ in->prev_vsync = mp_time_us();
+
if (in->dropped_frame) {
in->drop_count += 1;
} else {
@@ -740,6 +794,8 @@ static bool render_frame(struct vo *vo)
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);
}
if (!in->dropped_frame) {
@@ -864,6 +920,7 @@ void vo_set_paused(struct vo *vo, bool paused)
if (in->paused && in->dropped_frame)
in->request_redraw = true;
in->last_flip = 0;
+ reset_vsync_timings(vo);
}
pthread_mutex_unlock(&in->lock);
vo_control(vo, paused ? VOCTRL_PAUSE : VOCTRL_RESUME, NULL);
@@ -911,6 +968,7 @@ void vo_seek_reset(struct vo *vo)
pthread_mutex_lock(&in->lock);
forget_frames(vo);
in->last_flip = 0;
+ reset_vsync_timings(vo);
in->send_reset = true;
wakeup_locked(vo);
pthread_mutex_unlock(&in->lock);
@@ -1022,6 +1080,25 @@ int64_t vo_get_vsync_interval(struct vo *vo)
return res;
}
+// Returns duration of a display refresh in seconds.
+double vo_get_estimated_vsync_interval(struct vo *vo)
+{
+ struct vo_internal *in = vo->in;
+ pthread_mutex_lock(&in->lock);
+ double res = in->estimated_vsync_interval;
+ pthread_mutex_unlock(&in->lock);
+ return res;
+}
+
+double vo_get_estimated_vsync_jitter(struct vo *vo)
+{
+ struct vo_internal *in = vo->in;
+ pthread_mutex_lock(&in->lock);
+ double res = in->estimated_vsync_jitter;
+ pthread_mutex_unlock(&in->lock);
+ return res;
+}
+
// Get the time in seconds at after which the currently rendering frame will
// end. Returns positive values if the frame is yet to be finished, negative
// values if it already finished.
diff --git a/video/out/vo.h b/video/out/vo.h
index bd68858b43..0f934ebdc4 100644
--- a/video/out/vo.h
+++ b/video/out/vo.h
@@ -348,6 +348,8 @@ void vo_set_queue_params(struct vo *vo, int64_t offset_us, bool vsync_timed,
int num_req_frames);
int vo_get_num_req_frames(struct vo *vo);
int64_t vo_get_vsync_interval(struct vo *vo);
+double vo_get_estimated_vsync_interval(struct vo *vo);
+double vo_get_estimated_vsync_jitter(struct vo *vo);
double vo_get_display_fps(struct vo *vo);
double vo_get_delay(struct vo *vo);