summaryrefslogtreecommitdiffstats
path: root/video/out
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2018-08-31 20:08:08 +0200
committerAnton Kindestam <antonki@kth.se>2018-12-06 10:30:25 +0100
commitb1ba7de34dd5685a082454817f23509d1c28e4aa (patch)
treedc7c077d64742cb728c88fc582f952718a61155d /video/out
parent83884fdf03fc991679bea53d3d5bddf97ed16a9b (diff)
downloadmpv-b1ba7de34dd5685a082454817f23509d1c28e4aa.tar.bz2
mpv-b1ba7de34dd5685a082454817f23509d1c28e4aa.tar.xz
vo: use a struct for vsync feedback stuff
So new useless stuff can be easily added.
Diffstat (limited to 'video/out')
-rw-r--r--video/out/gpu/context.h10
-rw-r--r--video/out/opengl/context.c8
-rw-r--r--video/out/opengl/context.h4
-rw-r--r--video/out/opengl/context_glx.c6
-rw-r--r--video/out/vo.c32
-rw-r--r--video/out/vo.h21
-rw-r--r--video/out/vo_gpu.c7
7 files changed, 52 insertions, 36 deletions
diff --git a/video/out/gpu/context.h b/video/out/gpu/context.h
index b6b6ffcf43..ef48e6053f 100644
--- a/video/out/gpu/context.h
+++ b/video/out/gpu/context.h
@@ -84,14 +84,8 @@ struct ra_swapchain_fns {
// params.swapchain_depth, or until the next vblank (for vsynced contexts)
void (*swap_buffers)(struct ra_swapchain *sw);
- // Return the latency at which swap_buffers() is performed. This is in
- // seconds and always >= 0. Essentially, it's the predicted time the last
- // shown frame will take until it is actually displayed on the physical
- // screen. (A reasonable implementation is returning the duration the
- // last actually displayed frame took after its swap_buffers() was called.)
- // Should return -1 on error (e.g. discontinuities).
- // Can be NULL 0 or always return -1 if unsupported.
- double (*get_latency)(struct ra_swapchain *sw);
+ // See vo. Usually called after swap_buffers().
+ void (*get_vsync)(struct ra_swapchain *sw, struct vo_vsync_info *info);
};
// Create and destroy a ra_ctx. This also takes care of creating and destroying
diff --git a/video/out/opengl/context.c b/video/out/opengl/context.c
index 44e64b7d9a..9b3dd6a827 100644
--- a/video/out/opengl/context.c
+++ b/video/out/opengl/context.c
@@ -313,10 +313,12 @@ void ra_gl_ctx_swap_buffers(struct ra_swapchain *sw)
}
}
-static double ra_gl_ctx_get_latency(struct ra_swapchain *sw)
+static void ra_gl_ctx_get_vsync(struct ra_swapchain *sw,
+ struct vo_vsync_info *info)
{
struct priv *p = sw->priv;
- return p->params.get_latency ? p->params.get_latency(sw->ctx) : -1;
+ if (p->params.get_vsync)
+ p->params.get_vsync(sw->ctx, info);
}
static const struct ra_swapchain_fns ra_gl_swapchain_fns = {
@@ -324,5 +326,5 @@ static const struct ra_swapchain_fns ra_gl_swapchain_fns = {
.start_frame = ra_gl_ctx_start_frame,
.submit_frame = ra_gl_ctx_submit_frame,
.swap_buffers = ra_gl_ctx_swap_buffers,
- .get_latency = ra_gl_ctx_get_latency,
+ .get_vsync = ra_gl_ctx_get_vsync,
};
diff --git a/video/out/opengl/context.h b/video/out/opengl/context.h
index feaf8e1ab6..2dd2517ef5 100644
--- a/video/out/opengl/context.h
+++ b/video/out/opengl/context.h
@@ -23,8 +23,8 @@ struct ra_gl_ctx_params {
// function or if you override it yourself.
void (*swap_buffers)(struct ra_ctx *ctx);
- // See ra_swapchain_fns.get_latency.
- double (*get_latency)(struct ra_ctx *ctx);
+ // See ra_swapchain_fns.get_vsync.
+ void (*get_vsync)(struct ra_ctx *ctx, struct vo_vsync_info *info);
// Set to false if the implementation follows normal GL semantics, which is
// upside down. Set to true if it does *not*, i.e. if rendering is right
diff --git a/video/out/opengl/context_glx.c b/video/out/opengl/context_glx.c
index fe210c5f7d..2a6a2a4cf1 100644
--- a/video/out/opengl/context_glx.c
+++ b/video/out/opengl/context_glx.c
@@ -305,10 +305,10 @@ static void glx_swap_buffers(struct ra_ctx *ctx)
p->latency = update_latency_oml(ctx);
}
-static double glx_get_latency(struct ra_ctx *ctx)
+static void glx_get_vsync(struct ra_ctx *ctx, struct vo_vsync_info *info)
{
struct priv *p = ctx->priv;
- return p->latency;
+ info->latency = p->latency;
}
static bool glx_init(struct ra_ctx *ctx)
@@ -394,7 +394,7 @@ static bool glx_init(struct ra_ctx *ctx)
struct ra_gl_ctx_params params = {
.swap_buffers = glx_swap_buffers,
- .get_latency = glx_get_latency,
+ .get_vsync = glx_get_vsync,
};
if (!ra_gl_ctx_init(ctx, gl, params))
diff --git a/video/out/vo.c b/video/out/vo.c
index 466759f595..4110e1f353 100644
--- a/video/out/vo.c
+++ b/video/out/vo.c
@@ -141,7 +141,6 @@ struct vo_internal {
double estimated_vsync_jitter;
bool expecting_vsync;
int64_t num_successive_vsyncs;
- double last_vo_latency;
int64_t flip_queue_offset; // queue flip events at most this much in advance
int64_t timing_offset; // same (but from options; not VO configured)
@@ -475,18 +474,14 @@ static void vsync_skip_detection(struct vo *vo)
}
// Always called locked.
-static void update_vsync_timing_after_swap(struct vo *vo)
+static void update_vsync_timing_after_swap(struct vo *vo,
+ struct vo_vsync_info *vsync)
{
struct vo_internal *in = vo->in;
- int64_t now = mp_time_us();
+ int64_t vsync_time = vsync->last_queue_time;
int64_t prev_vsync = in->prev_vsync;
-
- // If we can, use a "made up" expected display time.
- if (in->last_vo_latency >= 0)
- now += in->last_vo_latency * (1000.0 * 1000.0);
-
- in->prev_vsync = now;
+ in->prev_vsync = vsync_time;
if (!in->expecting_vsync) {
reset_vsync_timings(vo);
@@ -500,13 +495,13 @@ static void update_vsync_timing_after_swap(struct vo *vo)
if (in->num_vsync_samples >= MAX_VSYNC_SAMPLES)
in->num_vsync_samples -= 1;
MP_TARRAY_INSERT_AT(in, in->vsync_samples, in->num_vsync_samples, 0,
- now - prev_vsync);
+ vsync_time - prev_vsync);
in->drop_point = MPMIN(in->drop_point + 1, in->num_vsync_samples);
in->num_total_vsync_samples += 1;
if (in->base_vsync) {
in->base_vsync += in->vsync_interval;
} else {
- in->base_vsync = now;
+ in->base_vsync = vsync_time;
}
double avg = 0;
@@ -915,17 +910,24 @@ bool vo_render_frame_external(struct vo *vo)
vo->driver->flip_page(vo);
- double latency =
- vo->driver->get_latency ? vo->driver->get_latency(vo) : -1;
+ struct vo_vsync_info vsync = {
+ .last_queue_time = mp_time_us(),
+ .latency = -1,
+ };
+ if (vo->driver->get_vsync)
+ vo->driver->get_vsync(vo, &vsync);
+
+ // If we can, use a "made up" expected display time.
+ if (vsync.latency >= 0)
+ vsync.last_queue_time += vsync.latency * (1000.0 * 1000.0);
MP_STATS(vo, "end video-flip");
pthread_mutex_lock(&in->lock);
in->dropped_frame = prev_drop_count < vo->in->drop_count;
in->rendering = false;
- in->last_vo_latency = latency;
- update_vsync_timing_after_swap(vo);
+ update_vsync_timing_after_swap(vo, &vsync);
}
if (vo->driver->caps & VO_CAP_NORETAIN) {
diff --git a/video/out/vo.h b/video/out/vo.h
index 848f71e472..f64d94a5ba 100644
--- a/video/out/vo.h
+++ b/video/out/vo.h
@@ -263,6 +263,21 @@ struct vo_frame {
uint64_t frame_id;
};
+// Presentation feedback.
+struct vo_vsync_info {
+ // Last mp_time_us() timestamp at which a frame was queued.
+ int64_t last_queue_time;
+
+ // The latency at which swap_buffers() is performed. This is in seconds, and
+ // valid values are always >= 0. Essentially, it's the predicted time the
+ // last shown frame will take until it is actually displayed on the physical
+ // screen. (A reasonable implementation is returning the actual measured
+ // value for the last frame which was actually displayed. The assumption is
+ // that the latency usually doesn't change.)
+ // -1 if unset or unsupported.
+ double latency;
+};
+
struct vo_driver {
// Encoding functionality, which can be invoked via --o only.
bool encode;
@@ -375,9 +390,11 @@ struct vo_driver {
void (*flip_page)(struct vo *vo);
/*
- * See struct ra_swapchain. Optional.
+ * Return presentation feedback. The implementation should not touch fields
+ * it doesn't support; the info fields are preinitialized to neutral values.
+ * Usually called once after flip_page(), but can be called any time.
*/
- double (*get_latency)(struct vo *vo);
+ void (*get_vsync)(struct vo *vo, struct vo_vsync_info *info);
/* These optional callbacks can be provided if the GUI framework used by
* the VO requires entering a message loop for receiving events and does
diff --git a/video/out/vo_gpu.c b/video/out/vo_gpu.c
index 3535ae3e7e..0162e420e8 100644
--- a/video/out/vo_gpu.c
+++ b/video/out/vo_gpu.c
@@ -98,11 +98,12 @@ static void flip_page(struct vo *vo)
sw->fns->swap_buffers(sw);
}
-static double get_latency(struct vo *vo)
+static void get_vsync(struct vo *vo, struct vo_vsync_info *info)
{
struct gpu_priv *p = vo->priv;
struct ra_swapchain *sw = p->ctx->swapchain;
- return sw->fns->get_latency ? sw->fns->get_latency(sw) : -1;
+ if (sw->fns->get_vsync)
+ sw->fns->get_vsync(sw, info);
}
static int query_format(struct vo *vo, int format)
@@ -333,7 +334,7 @@ const struct vo_driver video_out_gpu = {
.get_image = get_image,
.draw_frame = draw_frame,
.flip_page = flip_page,
- .get_latency = get_latency,
+ .get_vsync = get_vsync,
.wait_events = wait_events,
.wakeup = wakeup,
.uninit = uninit,