summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2015-05-12 22:16:38 +0200
committerwm4 <wm4@nowhere>2015-05-12 22:16:38 +0200
commit6b7155c05bafa2e3bdf4c4aa0f6372745dc59a1d (patch)
tree7d4d76e93649a2cb892c4dfd0dfc4a914d3b00cb /video
parentee3de1a063c281c1c915f204756d518966afdd54 (diff)
downloadmpv-6b7155c05bafa2e3bdf4c4aa0f6372745dc59a1d.tar.bz2
mpv-6b7155c05bafa2e3bdf4c4aa0f6372745dc59a1d.tar.xz
vo_opengl_cb: add support for interpolation
This uses the OpenGL frame interpolation code, which before could be used by vo_opengl only. Some effort was made to make it behave like vo_opengl, for the better or the worse. As a consequence, there is a minor duplication of code and mechanism. Hopefully this can all be wiped as soon as the VO frame queue/timing mechanism is cleaned up. This also attempts to use mpv_opengl_cb_report_flip() (as called by the API user) to determine the vsync interval. This might need refinement as well. (In general, we simply expect the API user to work in vsync-blocking manner.)
Diffstat (limited to 'video')
-rw-r--r--video/out/vo_opengl_cb.c56
1 files changed, 51 insertions, 5 deletions
diff --git a/video/out/vo_opengl_cb.c b/video/out/vo_opengl_cb.c
index 77bf5ed025..fc4dc950fb 100644
--- a/video/out/vo_opengl_cb.c
+++ b/video/out/vo_opengl_cb.c
@@ -80,6 +80,9 @@ struct mpv_opengl_cb_context {
bool eq_changed;
struct mp_csp_equalizer eq;
int64_t recent_flip;
+ int64_t approx_vsync;
+ int64_t cur_pts;
+ bool vsync_timed;
// --- All of these can only be accessed from the thread where the host
// application's OpenGL context is current - i.e. only while the
@@ -280,6 +283,16 @@ int mpv_opengl_cb_uninit_gl(struct mpv_opengl_cb_context *ctx)
return 0;
}
+// needs lock
+static int64_t prev_sync(mpv_opengl_cb_context *ctx, int64_t ts)
+{
+ int64_t diff = (int64_t)(ts - ctx->recent_flip);
+ int64_t offset = diff % ctx->approx_vsync;
+ if (offset < 0)
+ offset += ctx->approx_vsync;
+ return ts - offset;
+}
+
int mpv_opengl_cb_draw(mpv_opengl_cb_context *ctx, int fbo, int vp_w, int vp_h)
{
assert(ctx->renderer);
@@ -317,7 +330,12 @@ int mpv_opengl_cb_draw(mpv_opengl_cb_context *ctx, int fbo, int vp_w, int vp_h)
struct vo_priv *p = vo ? vo->priv : NULL;
struct vo_priv *opts = ctx->new_opts ? ctx->new_opts : p;
if (opts) {
- gl_video_set_options(ctx->renderer, opts->renderer_opts, NULL);
+ int queue = 0;
+ gl_video_set_options(ctx->renderer, opts->renderer_opts, &queue);
+ ctx->vsync_timed = opts->renderer_opts->interpolation;
+ if (ctx->vsync_timed)
+ queue += 0.050 * 1e6; // disable video timing
+ vo_set_flip_queue_params(vo, queue, false);
ctx->gl->debug_context = opts->use_gl_debug;
gl_video_set_debug(ctx->renderer, opts->use_gl_debug);
frame_queue_shrink(ctx, opts->frame_queue_size);
@@ -335,19 +353,32 @@ int mpv_opengl_cb_draw(mpv_opengl_cb_context *ctx, int fbo, int vp_w, int vp_h)
ctx->eq = *eq;
struct mp_image *mpi = frame_queue_pop(ctx);
+ if (mpi) {
+ struct frame_timing *t = mpi->priv; // set by draw_image_timed
+ if (t)
+ ctx->cur_pts = t->pts;
+ }
+
+ struct frame_timing timing = {
+ .pts = ctx->cur_pts,
+ };
+ if (ctx->approx_vsync > 0) {
+ timing.prev_vsync = prev_sync(ctx, mp_time_us());
+ timing.next_vsync = timing.prev_vsync + ctx->approx_vsync;
+ }
pthread_mutex_unlock(&ctx->lock);
if (mpi)
gl_video_set_image(ctx->renderer, mpi);
- gl_video_render_frame(ctx->renderer, fbo, NULL);
+ gl_video_render_frame(ctx->renderer, fbo, timing.pts ? &timing : NULL);
gl_video_unset_gl_state(ctx->renderer);
pthread_mutex_lock(&ctx->lock);
const int left = ctx->queued_frames;
- if (vo && left > 0)
+ if (vo && (left > 0 || ctx->vsync_timed))
update(vo->priv);
pthread_mutex_unlock(&ctx->lock);
@@ -357,22 +388,36 @@ int mpv_opengl_cb_draw(mpv_opengl_cb_context *ctx, int fbo, int vp_w, int vp_h)
int mpv_opengl_cb_report_flip(mpv_opengl_cb_context *ctx, int64_t time)
{
pthread_mutex_lock(&ctx->lock);
- ctx->recent_flip = time > 0 ? time : mp_time_us();
+ int64_t next = time > 0 ? time : mp_time_us();
+ if (ctx->recent_flip)
+ ctx->approx_vsync = next - ctx->recent_flip;
+ ctx->recent_flip = next;
pthread_mutex_unlock(&ctx->lock);
return 0;
}
-static void draw_image(struct vo *vo, mp_image_t *mpi)
+static void draw_image_timed(struct vo *vo, mp_image_t *mpi,
+ struct frame_timing *t)
{
struct vo_priv *p = vo->priv;
pthread_mutex_lock(&p->ctx->lock);
mp_image_setrefp(&p->ctx->waiting_frame, mpi);
+ if (p->ctx->waiting_frame) {
+ p->ctx->waiting_frame->priv =
+ t ? talloc_memdup(p->ctx->waiting_frame, t, sizeof(*t))
+ : NULL;
+ }
talloc_free(mpi);
pthread_mutex_unlock(&p->ctx->lock);
}
+static void draw_image(struct vo *vo, mp_image_t *mpi)
+{
+ draw_image_timed(vo, mpi, NULL);
+}
+
// Called locked.
static void update(struct vo_priv *p)
{
@@ -591,6 +636,7 @@ const struct vo_driver video_out_opengl_cb = {
.reconfig = reconfig,
.control = control,
.draw_image = draw_image,
+ .draw_image_timed = draw_image_timed,
.flip_page = flip_page,
.uninit = uninit,
.priv_size = sizeof(struct vo_priv),