diff options
author | wm4 <wm4@nowhere> | 2018-04-21 00:26:58 +0200 |
---|---|---|
committer | Jan Ekström <jeebjp@gmail.com> | 2018-04-29 02:21:32 +0300 |
commit | ce4d227986cf394a80fc687290bc732bbd8dbf22 (patch) | |
tree | c2f11a05e8961d613a244db5c2dfc7d67b1d0ccf /video | |
parent | 0be3a94e0b81d553849f9520f7ee9f2b6e34c6b4 (diff) |
client API: add some render API extensions for timing
Attempts to enable the following things:
- let a render API user do "proper" audio-sync video timing itself
- make it possible to not re-render repeated frames if the API user has
better mechanisms available (e.g. waiting for a DisplayLink cycle
instead)
- allow the user to delay or skip redraws if it makes sense
Basically this information will be needed by API users who want to be
"clever" about optimizing timing and rendering.
Diffstat (limited to 'video')
-rw-r--r-- | video/out/vo_libmpv.c | 92 |
1 files changed, 68 insertions, 24 deletions
diff --git a/video/out/vo_libmpv.c b/video/out/vo_libmpv.c index ef5dc9809e..59d3b6883c 100644 --- a/video/out/vo_libmpv.c +++ b/video/out/vo_libmpv.c @@ -323,38 +323,45 @@ bool mp_render_context_acquire(mpv_render_context *ctx) int mpv_render_context_render(mpv_render_context *ctx, mpv_render_param *params) { - int vp_w, vp_h; - int err = ctx->renderer->fns->get_target_size(ctx->renderer, params, - &vp_w, &vp_h); - if (err < 0) - return err; - pthread_mutex_lock(&ctx->lock); - struct vo *vo = ctx->vo; + int do_render = + !GET_MPV_RENDER_PARAM(params, MPV_RENDER_PARAM_SKIP_RENDERING, int, 0); - if (vo && (ctx->vp_w != vp_w || ctx->vp_h != vp_h || ctx->need_resize)) { - ctx->vp_w = vp_w; - ctx->vp_h = vp_h; + if (do_render) { + int vp_w, vp_h; + int err = ctx->renderer->fns->get_target_size(ctx->renderer, params, + &vp_w, &vp_h); + if (err < 0) { + pthread_mutex_unlock(&ctx->lock); + return err; + } + + if (ctx->vo && (ctx->vp_w != vp_w || ctx->vp_h != vp_h || + ctx->need_resize)) + { + ctx->vp_w = vp_w; + ctx->vp_h = vp_h; - m_config_cache_update(ctx->vo_opts_cache); + m_config_cache_update(ctx->vo_opts_cache); - struct mp_rect src, dst; - struct mp_osd_res osd; - mp_get_src_dst_rects(ctx->log, ctx->vo_opts, vo->driver->caps, - &ctx->img_params, vp_w, abs(vp_h), - 1.0, &src, &dst, &osd); + struct mp_rect src, dst; + struct mp_osd_res osd; + mp_get_src_dst_rects(ctx->log, ctx->vo_opts, ctx->vo->driver->caps, + &ctx->img_params, vp_w, abs(vp_h), + 1.0, &src, &dst, &osd); - ctx->renderer->fns->resize(ctx->renderer, &src, &dst, &osd); + ctx->renderer->fns->resize(ctx->renderer, &src, &dst, &osd); + } + ctx->need_resize = false; } - ctx->need_resize = false; if (ctx->need_reconfig) ctx->renderer->fns->reconfig(ctx->renderer, &ctx->img_params); ctx->need_reconfig = false; if (ctx->need_update_external) - ctx->renderer->fns->update_external(ctx->renderer, vo); + ctx->renderer->fns->update_external(ctx->renderer, ctx->vo); ctx->need_update_external = false; if (ctx->need_reset) { @@ -387,15 +394,22 @@ int mpv_render_context_render(mpv_render_context *ctx, mpv_render_param *params) MP_STATS(ctx, "glcb-render"); - err = ctx->renderer->fns->render(ctx->renderer, params, frame); + int err = 0; + + if (do_render) + err = ctx->renderer->fns->render(ctx->renderer, params, frame); if (frame != &dummy) talloc_free(frame); - pthread_mutex_lock(&ctx->lock); - while (wait_present_count > ctx->present_count) - pthread_cond_wait(&ctx->video_wait, &ctx->lock); - pthread_mutex_unlock(&ctx->lock); + if (GET_MPV_RENDER_PARAM(params, MPV_RENDER_PARAM_BLOCK_FOR_TARGET_TIME, + int, 1)) + { + pthread_mutex_lock(&ctx->lock); + while (wait_present_count > ctx->present_count) + pthread_cond_wait(&ctx->video_wait, &ctx->lock); + pthread_mutex_unlock(&ctx->lock); + } return err; } @@ -430,6 +444,36 @@ int mpv_render_context_set_parameter(mpv_render_context *ctx, return ctx->renderer->fns->set_parameter(ctx->renderer, param); } +int mpv_render_context_get_info(mpv_render_context *ctx, + mpv_render_param param) +{ + int res = MPV_ERROR_NOT_IMPLEMENTED; + pthread_mutex_lock(&ctx->lock); + + switch (param.type) { + case MPV_RENDER_PARAM_NEXT_FRAME_INFO: { + mpv_render_frame_info *info = param.data; + *info = (mpv_render_frame_info){0}; + struct vo_frame *frame = ctx->next_frame; + if (frame) { + info->flags = + MPV_RENDER_FRAME_INFO_PRESENT | + (frame->redraw ? MPV_RENDER_FRAME_INFO_REDRAW : 0) | + (frame->repeat ? MPV_RENDER_FRAME_INFO_REPEAT : 0) | + (frame->display_synced && !frame->redraw ? + MPV_RENDER_FRAME_INFO_BLOCK_VSYNC : 0); + info->target_time = frame->pts; + } + res = 0; + break; + } + default:; + } + + pthread_mutex_unlock(&ctx->lock); + return res; +} + static void draw_frame(struct vo *vo, struct vo_frame *frame) { struct vo_priv *p = vo->priv; |