aboutsummaryrefslogtreecommitdiffhomepage
path: root/video
diff options
context:
space:
mode:
authorGravatar wm4 <wm4@nowhere>2018-04-21 00:26:58 +0200
committerGravatar Jan Ekström <jeebjp@gmail.com>2018-04-29 02:21:32 +0300
commitce4d227986cf394a80fc687290bc732bbd8dbf22 (patch)
treec2f11a05e8961d613a244db5c2dfc7d67b1d0ccf /video
parent0be3a94e0b81d553849f9520f7ee9f2b6e34c6b4 (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.c92
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;