From 0be3a94e0b81d553849f9520f7ee9f2b6e34c6b4 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 20 Apr 2018 22:12:29 +0200 Subject: vo_libmpv: support GPU rendered screenshots Like DR, this needed a lot of preparation, and here's the boring glue code that finally implements it. --- video/out/gpu/libmpv_gpu.c | 9 +++++++++ video/out/libmpv.h | 2 ++ video/out/vo_libmpv.c | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/video/out/gpu/libmpv_gpu.c b/video/out/gpu/libmpv_gpu.c index 3674d678c7..f687c97b51 100644 --- a/video/out/gpu/libmpv_gpu.c +++ b/video/out/gpu/libmpv_gpu.c @@ -190,6 +190,14 @@ static struct mp_image *get_image(struct render_backend *ctx, int imgfmt, return gl_video_get_image(p->renderer, imgfmt, w, h, stride_align); } +static void screenshot(struct render_backend *ctx, struct vo_frame *frame, + struct voctrl_screenshot *args) +{ + struct priv *p = ctx->priv; + + gl_video_screenshot(p->renderer, frame, args); +} + static void destroy(struct render_backend *ctx) { struct priv *p = ctx->priv; @@ -217,5 +225,6 @@ const struct render_backend_fns render_backend_gpu = { .get_target_size = get_target_size, .render = render, .get_image = get_image, + .screenshot = screenshot, .destroy = destroy, }; diff --git a/video/out/libmpv.h b/video/out/libmpv.h index 4544a278db..dc9d523b23 100644 --- a/video/out/libmpv.h +++ b/video/out/libmpv.h @@ -52,6 +52,8 @@ struct render_backend_fns { void (*reconfig)(struct render_backend *ctx, struct mp_image_params *params); // Like VOCTRL_RESET. void (*reset)(struct render_backend *ctx); + void (*screenshot)(struct render_backend *ctx, struct vo_frame *frame, + struct voctrl_screenshot *args); // Like vo_driver.get_image(). struct mp_image *(*get_image)(struct render_backend *ctx, int imgfmt, int w, int h, int stride_align); diff --git a/video/out/vo_libmpv.c b/video/out/vo_libmpv.c index ba8a19f947..ef5dc9809e 100644 --- a/video/out/vo_libmpv.c +++ b/video/out/vo_libmpv.c @@ -511,6 +511,29 @@ static int query_format(struct vo *vo, int format) return ok; } +static void run_control_on_render_thread(void *p) +{ + void **args = p; + struct mpv_render_context *ctx = args[0]; + int request = (intptr_t)args[1]; + void *data = args[2]; + int ret = VO_NOTIMPL; + + switch (request) { + case VOCTRL_SCREENSHOT: { + pthread_mutex_lock(&ctx->lock); + struct vo_frame *frame = vo_frame_ref(ctx->cur_frame); + pthread_mutex_unlock(&ctx->lock); + if (frame && ctx->renderer->fns->screenshot) + ctx->renderer->fns->screenshot(ctx->renderer, frame, data); + talloc_free(frame); + break; + } + } + + *(int *)args[3] = ret; +} + static int control(struct vo *vo, uint32_t request, void *data) { struct vo_priv *p = vo->priv; @@ -544,6 +567,17 @@ static int control(struct vo *vo, uint32_t request, void *data) return VO_TRUE; } + // VOCTRLs to be run on the renderer thread (if possible at all). + switch (request) { + case VOCTRL_SCREENSHOT: + if (ctx->dispatch) { + int ret; + void *args[] = {ctx, (void *)(intptr_t)request, data, &ret}; + mp_dispatch_run(ctx->dispatch, run_control_on_render_thread, args); + return ret; + } + } + int r = VO_NOTIMPL; pthread_mutex_lock(&ctx->control_lock); if (ctx->control_cb) { -- cgit v1.2.3