diff options
Diffstat (limited to 'player/client.c')
-rw-r--r-- | player/client.c | 164 |
1 files changed, 143 insertions, 21 deletions
diff --git a/player/client.c b/player/client.c index 1df7e659d8..45af55bee9 100644 --- a/player/client.c +++ b/player/client.c @@ -20,6 +20,7 @@ #include <fcntl.h> #include <errno.h> #include <locale.h> +#include <math.h> #include <assert.h> #include "common/common.h" @@ -46,8 +47,6 @@ #include "core.h" #include "client.h" -#include "config.h" - /* * Locking hierarchy: * @@ -74,6 +73,9 @@ struct mp_client_api { struct mp_custom_protocol *custom_protocols; int num_custom_protocols; + + struct mpv_render_context *render_context; + struct mpv_opengl_cb_context *gl_cb_ctx; }; struct observe_property { @@ -156,6 +158,16 @@ void mp_clients_destroy(struct MPContext *mpctx) if (!mpctx->clients) return; assert(mpctx->clients->num_clients == 0); + + TA_FREEP(&mpctx->clients->gl_cb_ctx); + + // The API user is supposed to call mpv_render_context_free(). It's simply + // not allowed not to do this. + if (mpctx->clients->render_context) { + MP_FATAL(mpctx, "Broken API use: mpv_render_context_free() not called.\n"); + abort(); + } + pthread_mutex_destroy(&mpctx->clients->lock); talloc_free(mpctx->clients); mpctx->clients = NULL; @@ -279,6 +291,11 @@ struct mp_log *mp_client_get_log(struct mpv_handle *ctx) return ctx->log; } +struct mpv_global *mp_client_get_global(struct mpv_handle *ctx) +{ + return ctx->mpctx->global; +} + struct MPContext *mp_client_get_core(struct mpv_handle *ctx) { return ctx->mpctx; @@ -1672,7 +1689,9 @@ int64_t mpv_get_time_us(mpv_handle *ctx) return mp_time_us(); } -// Used by vo_opengl_cb to synchronously uninitialize video. +#include "video/out/libmpv.h" + +// Used by vo_libmpv to synchronously uninitialize video. void kill_video(struct mp_client_api *client_api) { struct MPContext *mpctx = client_api->mpctx; @@ -1686,58 +1705,163 @@ void kill_video(struct mp_client_api *client_api) mp_dispatch_unlock(mpctx->dispatch); } +// Used by vo_libmpv to set the current render context. +bool mp_set_main_render_context(struct mp_client_api *client_api, + struct mpv_render_context *ctx, bool active) +{ + assert(ctx); + + pthread_mutex_lock(&client_api->lock); + bool is_set = !!client_api->render_context; + bool is_same = client_api->render_context == ctx; + // Can set if it doesn't remove another existing ctx. + bool res = is_same || !is_set; + if (res) + client_api->render_context = active ? ctx : NULL; + pthread_mutex_unlock(&client_api->lock); + return res; +} + +// Used by vo_libmpv. Relies on guarantees by mp_render_context_acquire(). +struct mpv_render_context * +mp_client_api_acquire_render_context(struct mp_client_api *ca) +{ + struct mpv_render_context *res = NULL; + pthread_mutex_lock(&ca->lock); + if (ca->render_context && mp_render_context_acquire(ca->render_context)) + res = ca->render_context; + pthread_mutex_unlock(&ca->lock); + return res; +} + +// Emulation of old opengl_cb API. + #include "libmpv/opengl_cb.h" +#include "libmpv/render_gl.h" + +struct mpv_opengl_cb_context { + struct mp_client_api *client_api; + mpv_opengl_cb_update_fn callback; + void *callback_ctx; +}; -#if HAVE_GL static mpv_opengl_cb_context *opengl_cb_get_context(mpv_handle *ctx) { - mpv_opengl_cb_context *cb = ctx->mpctx->gl_cb_ctx; + pthread_mutex_lock(&ctx->clients->lock); + mpv_opengl_cb_context *cb = ctx->clients->gl_cb_ctx; if (!cb) { - cb = mp_opengl_create(ctx->mpctx->global, ctx->clients); - ctx->mpctx->gl_cb_ctx = cb; + cb = talloc_zero(NULL, struct mpv_opengl_cb_context); + cb->client_api = ctx->clients; + cb->client_api->gl_cb_ctx = cb; } + pthread_mutex_unlock(&ctx->clients->lock); return cb; } -#else -static mpv_opengl_cb_context *opengl_cb_get_context(mpv_handle *ctx) -{ - return NULL; -} + void mpv_opengl_cb_set_update_callback(mpv_opengl_cb_context *ctx, mpv_opengl_cb_update_fn callback, void *callback_ctx) { + // This was probably supposed to be thread-safe, but we don't care. It's + // compatibility code, and if you have problems, use the new API. + if (ctx->client_api->render_context) { + mpv_render_context_set_update_callback(ctx->client_api->render_context, + callback, callback_ctx); + } + // Nasty thing: could set this even while not initialized, so we need to + // preserve it. + ctx->callback = callback; + ctx->callback_ctx = callback_ctx; } + int mpv_opengl_cb_init_gl(mpv_opengl_cb_context *ctx, const char *exts, mpv_opengl_cb_get_proc_address_fn get_proc_address, void *get_proc_address_ctx) { - return MPV_ERROR_NOT_IMPLEMENTED; + if (ctx->client_api->render_context) + return MPV_ERROR_INVALID_PARAMETER; + + // mpv_render_context_create() only calls mp_client_get_global() on it. + mpv_handle dummy = {.mpctx = ctx->client_api->mpctx}; + + mpv_render_param params[] = { + {MPV_RENDER_PARAM_API_TYPE, MPV_RENDER_API_TYPE_OPENGL}, + {MPV_RENDER_PARAM_OPENGL_INIT_PARAMS, &(mpv_opengl_init_params){ + .get_proc_address = get_proc_address, + .get_proc_address_ctx = get_proc_address_ctx, + .extra_exts = exts, + }}, + {0} + }; + int err = mpv_render_context_create(&ctx->client_api->render_context, + &dummy, params); + if (err >= 0) { + mpv_render_context_set_update_callback(ctx->client_api->render_context, + ctx->callback, ctx->callback_ctx); + } + return err; } + int mpv_opengl_cb_draw(mpv_opengl_cb_context *ctx, int fbo, int w, int h) { - return MPV_ERROR_NOT_IMPLEMENTED; + if (!ctx->client_api->render_context) + return MPV_ERROR_INVALID_PARAMETER; + + mpv_render_param params[] = { + {MPV_RENDER_PARAM_OPENGL_FBO, &(mpv_opengl_fbo){ + .fbo = fbo, + .w = w, + .h = abs(h), + }}, + {MPV_RENDER_PARAM_FLIP_Y, &(int){h < 0}}, + {0} + }; + return mpv_render_context_render(ctx->client_api->render_context, params); } + int mpv_opengl_cb_report_flip(mpv_opengl_cb_context *ctx, int64_t time) { - return MPV_ERROR_NOT_IMPLEMENTED; + if (!ctx->client_api->render_context) + return MPV_ERROR_INVALID_PARAMETER; + + mpv_render_context_report_swap(ctx->client_api->render_context); + return 0; } + int mpv_opengl_cb_uninit_gl(mpv_opengl_cb_context *ctx) { - return MPV_ERROR_NOT_IMPLEMENTED; + if (ctx->client_api->render_context) + mpv_render_context_free(ctx->client_api->render_context); + ctx->client_api->render_context = NULL; + return 0; } + void mp_client_set_control_callback(struct mpv_opengl_cb_context *ctx, mpv_opengl_cb_control_fn callback, void *callback_ctx) { + if (ctx->client_api->render_context) { + mp_render_context_set_control_callback(ctx->client_api->render_context, + callback, callback_ctx); + } } + void mp_client_set_icc_profile(struct mpv_opengl_cb_context *ctx, bstr icc_data) { + if (!ctx->client_api->render_context) + return; + mpv_render_param param = {MPV_RENDER_PARAM_ICC_PROFILE, + &(mpv_byte_array){icc_data.start, icc_data.len}}; + mpv_render_context_set_parameter(ctx->client_api->render_context, param); } + void mp_client_set_ambient_lux(struct mpv_opengl_cb_context *ctx, int lux) { + if (!ctx->client_api->render_context) + return; + mpv_render_param param = {MPV_RENDER_PARAM_AMBIENT_LIGHT, &(int){lux}}; + mpv_render_context_set_parameter(ctx->client_api->render_context, param); } -#endif int mpv_opengl_cb_render(mpv_opengl_cb_context *ctx, int fbo, int vp[4]) { @@ -1749,16 +1873,12 @@ void *mp_get_sub_api2(mpv_handle *ctx, mpv_sub_api sub_api, bool lock) if (!ctx->mpctx->initialized) return NULL; void *res = NULL; - if (lock) - lock_core(ctx); switch (sub_api) { case MPV_SUB_API_OPENGL_CB: res = opengl_cb_get_context(ctx); break; default:; } - if (lock) - unlock_core(ctx); return res; } @@ -1767,6 +1887,8 @@ void *mpv_get_sub_api(mpv_handle *ctx, mpv_sub_api sub_api) return mp_get_sub_api2(ctx, sub_api, true); } +// stream_cb + struct mp_custom_protocol { char *protocol; void *user_data; |