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.)
This commit is contained in:
wm4
2015-05-12 22:16:38 +02:00
parent ee3de1a063
commit 6b7155c05b

View File

@@ -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),