diff options
-rw-r--r-- | DOCS/client-api-changes.rst | 13 | ||||
-rw-r--r-- | DOCS/interface-changes.rst | 2 | ||||
-rw-r--r-- | DOCS/man/options.rst | 3 | ||||
-rw-r--r-- | DOCS/man/vo.rst | 9 | ||||
-rw-r--r-- | libmpv/client.h | 13 | ||||
-rw-r--r-- | libmpv/mpv.def | 6 | ||||
-rw-r--r-- | libmpv/opengl_cb.h | 11 | ||||
-rw-r--r-- | libmpv/render.h | 309 | ||||
-rw-r--r-- | libmpv/render_gl.h | 155 | ||||
-rw-r--r-- | player/client.c | 164 | ||||
-rw-r--r-- | player/client.h | 19 | ||||
-rw-r--r-- | player/core.h | 2 | ||||
-rw-r--r-- | player/main.c | 3 | ||||
-rw-r--r-- | player/playloop.c | 1 | ||||
-rw-r--r-- | player/video.c | 1 | ||||
-rw-r--r-- | video/out/gpu/libmpv_gpu.c | 182 | ||||
-rw-r--r-- | video/out/gpu/libmpv_gpu.h | 38 | ||||
-rw-r--r-- | video/out/libmpv.h | 72 | ||||
-rw-r--r-- | video/out/opengl/libmpv_gl.c | 113 | ||||
-rw-r--r-- | video/out/vo.c | 9 | ||||
-rw-r--r-- | video/out/vo.h | 1 | ||||
-rw-r--r-- | video/out/vo_libmpv.c (renamed from video/out/vo_opengl_cb.c) | 425 | ||||
-rw-r--r-- | wscript_build.py | 4 |
23 files changed, 1267 insertions, 288 deletions
diff --git a/DOCS/client-api-changes.rst b/DOCS/client-api-changes.rst index df2b42aa70..845953580a 100644 --- a/DOCS/client-api-changes.rst +++ b/DOCS/client-api-changes.rst @@ -33,6 +33,19 @@ API changes :: --- mpv 0.29.0 --- + 1.28 - deprecate the render opengl_cb API, and replace it with render.h + and render_gl.h. The goal is allowing support for APIs other than + OpenGL. The old API is emulated with the new API. + Likewise, the "opengl-cb" VO is renamed to "libmpv". + mpv_get_sub_api() is deprecated along the opengl_cb API. + The new API is relatively similar, but not the same. The rough + equivalents are: + mpv_opengl_cb_init_gl => mpv_render_context_create + mpv_opengl_cb_set_update_callback => mpv_render_context_set_update_callback + mpv_opengl_cb_draw => mpv_render_context_render + mpv_opengl_cb_report_flip => mpv_render_context_report_swap + mpv_opengl_cb_uninit_gl => mpv_render_context_free + The VO opengl-cb is also renamed to "libmpv". 1.27 - make opengl-cb the default VO. This causes a subtle behavior change if the API user called mpv_opengl_cb_init_gl(), but does not set the "vo" option. Before, it would still have used another VO (like diff --git a/DOCS/interface-changes.rst b/DOCS/interface-changes.rst index e18fec4c1d..5830b413e0 100644 --- a/DOCS/interface-changes.rst +++ b/DOCS/interface-changes.rst @@ -72,6 +72,8 @@ Interface changes will probably stall. - deprecate the OpenGL cocoa backend, option choice --gpu-context=cocoa when used with --gpu-api=opengl (use --vo=opengl-cb) + - rename --vo=opengl-cb to --vo=libmpv (goes in hand with the opengl-cb + API deprecation, see client-api-changes.rst) - make --deinterlace=yes always deinterlace, instead of trying to check certain unreliable video metadata. Also flip the defaults of all builtin HW deinterlace filters to always deinterlace. diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index 8246dd0f49..2716302e72 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -5221,6 +5221,9 @@ The following video options are currently all specific to ``--vo=gpu`` and NOTE: On Windows, the default profile must be an ICC profile. WCS profiles are not supported. + Applications using libmpv with the render API need to provide the ICC + profile via ``MPV_RENDER_PARAM_ICC_PROFILE``. + ``--icc-cache-dir=<dirname>`` Store and load the 3D LUTs created from the ICC profile in this directory. This can be used to speed up loading, since LittleCMS 2 can take a while to diff --git a/DOCS/man/vo.rst b/DOCS/man/vo.rst index 8e8b9803be..672f3c68f6 100644 --- a/DOCS/man/vo.rst +++ b/DOCS/man/vo.rst @@ -428,13 +428,14 @@ Available video output drivers are: ``--vo-image-outdir=<dirname>`` Specify the directory to save the image files to (default: ``./``). -``opengl-cb`` - For use with libmpv direct OpenGL embedding. As a special case, on OS X it +``libmpv`` + For use with libmpv direct embedding. As a special case, on OS X it is used like a normal VO within mpv (cocoa-cb). Otherwise useless in any other contexts. - (See ``<mpv/opengl_cb.h>``.) + (See ``<mpv/render.h>``.) - This also supports many of the options the ``gpu`` VO has. + This also supports many of the options the ``gpu`` VO has, depending on the + backend. ``rpi`` (Raspberry Pi) Native video output on the Raspberry Pi using the MMAL API. diff --git a/libmpv/client.h b/libmpv/client.h index 424bf0613d..07237c9d4d 100644 --- a/libmpv/client.h +++ b/libmpv/client.h @@ -210,7 +210,7 @@ extern "C" { * relational operators (<, >, <=, >=). */ #define MPV_MAKE_VERSION(major, minor) (((major) << 16) | (minor) | 0UL) -#define MPV_CLIENT_API_VERSION MPV_MAKE_VERSION(1, 27) +#define MPV_CLIENT_API_VERSION MPV_MAKE_VERSION(1, 28) /** * The API user is allowed to "#define MPV_ENABLE_DEPRECATED 0" before @@ -1691,6 +1691,11 @@ int mpv_get_wakeup_pipe(mpv_handle *ctx); */ void mpv_wait_async_requests(mpv_handle *ctx); +#if MPV_ENABLE_DEPRECATED + +/** + * @deprecated use render.h + */ typedef enum mpv_sub_api { /** * For using mpv's OpenGL renderer on an external OpenGL context. @@ -1698,6 +1703,8 @@ typedef enum mpv_sub_api { * This context can be used with mpv_opengl_cb_* functions. * Will return NULL if unavailable (if OpenGL support was not compiled in). * See opengl_cb.h for details. + * + * @deprecated use render.h */ MPV_SUB_API_OPENGL_CB = 1 } mpv_sub_api; @@ -1705,9 +1712,13 @@ typedef enum mpv_sub_api { /** * This is used for additional APIs that are not strictly part of the core API. * See the individual mpv_sub_api member values. + * + * @deprecated use render.h */ void *mpv_get_sub_api(mpv_handle *ctx, mpv_sub_api sub_api); +#endif + #ifdef __cplusplus } #endif diff --git a/libmpv/mpv.def b/libmpv/mpv.def index 0384c7db9d..5299f69c9a 100644 --- a/libmpv/mpv.def +++ b/libmpv/mpv.def @@ -28,6 +28,12 @@ mpv_opengl_cb_report_flip mpv_opengl_cb_render mpv_opengl_cb_set_update_callback mpv_opengl_cb_uninit_gl +mpv_render_context_create +mpv_render_context_free +mpv_render_context_render +mpv_render_context_report_swap +mpv_render_context_set_parameter +mpv_render_context_set_update_callback mpv_request_event mpv_request_log_messages mpv_resume diff --git a/libmpv/opengl_cb.h b/libmpv/opengl_cb.h index 384372b617..ce88a8570a 100644 --- a/libmpv/opengl_cb.h +++ b/libmpv/opengl_cb.h @@ -18,6 +18,10 @@ #include "client.h" +#if !MPV_ENABLE_DEPRECATED +#error "This header and all API provided by it is deprecated. Use render.h instead." +#else + #ifdef __cplusplus extern "C" { #endif @@ -27,6 +31,9 @@ extern "C" { * Overview * -------- * + * Warning: this API is deprecated. A very similar API is provided by render.h + * and render_gl.h. The deprecated API is emulated with the new API. + * * This API can be used to make mpv render into a foreign OpenGL context. It * can be used to handle video display. * @@ -328,7 +335,6 @@ int mpv_opengl_cb_init_gl(mpv_opengl_cb_context *ctx, const char *exts, */ int mpv_opengl_cb_draw(mpv_opengl_cb_context *ctx, int fbo, int w, int h); -#if MPV_ENABLE_DEPRECATED /** * Deprecated. Use mpv_opengl_cb_draw(). This function is equivalent to: * @@ -341,7 +347,6 @@ int mpv_opengl_cb_draw(mpv_opengl_cb_context *ctx, int fbo, int w, int h); * was never marked as stable). */ int mpv_opengl_cb_render(mpv_opengl_cb_context *ctx, int fbo, int vp[4]); -#endif /** * Tell the renderer that a frame was flipped at the given time. This is @@ -375,4 +380,6 @@ int mpv_opengl_cb_uninit_gl(mpv_opengl_cb_context *ctx); } #endif +#endif /* else #if MPV_ENABLE_DEPRECATED */ + #endif diff --git a/libmpv/render.h b/libmpv/render.h new file mode 100644 index 0000000000..64a317d73c --- /dev/null +++ b/libmpv/render.h @@ -0,0 +1,309 @@ +/* Copyright (C) 2018 the mpv developers + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef MPV_CLIENT_API_RENDER_H_ +#define MPV_CLIENT_API_RENDER_H_ + +#include "client.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Overview + * -------- + * + * This API can be used to make mpv render using supported graphic APIs (such + * as OpenGL). It can be used to handle video display. + * + * The renderer needs to be created with mpv_render_context_create() before + * you start playback (or otherwise cause a VO to be created). Then (with most + * backends) mpv_render_context_render() can be used to explicitly render the + * current video frame. Use mpv_render_context_set_update_callback() to get + * notified when there is a new frame to draw. + * + * Preferably rendering should be done in a separate thread. If you call + * normal libmpv API functions on the renderer thread, deadlocks can result + * (these are made non-fatal with timeouts, but user experience will obviously + * suffer). + * + * You can output and embed video without this API by setting the mpv "wid" + * option to a native window handle (see "Embedding the video window" section + * in the client.h header). In general, using the render API is recommended, + * because window embedding can cause various issues, especially with GUI + * toolkits and certain platforms. + * + * Supported backends + * ------------------ + * + * OpenGL: via MPV_RENDER_API_TYPE_OPENGL, see render_gl.h header. + * + * Threading + * --------- + * + * The mpv_render_* functions can be called from any thread, under the + * following conditions: + * - only one of the mpv_render_* functions can be called at the same time + * (unless they belong to different mpv cores created by mpv_create()) + * - never can be called from within the callbacks set with + * mpv_set_wakeup_callback() or mpv_render_context_set_update_callback() + * - if the OpenGL backend is used, for all functions the OpenGL context + * must be "current" in the calling thread, and it must be the same OpenGL + * context as the mpv_render_context was created with. Otherwise, undefined + * behavior will occur. + * + * Context and handle lifecycle + * ---------------------------- + * + * Video initialization will fail if the render context was not initialized yet + * (with mpv_render_context_create()), or it will revert to a VO that creates + * its own window. + * + * Calling mpv_render_context_free() while a VO is using the render context is + * active will disable video. + * + * You must free the context with mpv_render_context_free() before the mpv core + * is destroyed. If this doesn't happen, undefined behavior will result. + */ + +/** + * Opaque context, returned by mpv_render_context_create(). + */ +typedef struct mpv_render_context mpv_render_context; + +/** + * Parameters for mpv_render_param (which is used in a few places such as + * mpv_render_context_create(). + * + * Also see mpv_render_param for conventions and how to use it. + */ +typedef enum mpv_render_param_type { + /** + * Not a valid value, but also used to terminate a params array. Its value + * is always guaranteed to be 0 (even if the ABI changes in the future). + */ + MPV_RENDER_PARAM_INVALID = 0, + /** + * The render API to use. Valid for mpv_render_context_create(). + * + * Type: char* + * + * Defined APIs: + * + * MPV_RENDER_API_TYPE_OPENGL: + * OpenGL desktop 2.1 or later (preferably core profile compatible to + * OpenGL 3.2), or OpenGLES 2.0 or later. + * Providing MPV_RENDER_PARAM_OPENGL_INIT_PARAMS is required. + * It is expected that an OpenGL context is valid and "current" when + * calling mpv_render_* functions (unless specified otherwise). It + * must be the same context for the same mpv_render_context. + */ + MPV_RENDER_PARAM_API_TYPE = 1, + /** + * Required parameters for initializing the OpenGL renderer. Valid for + * mpv_render_context_create(). + * Type: mpv_opengl_init_params* + */ + MPV_RENDER_PARAM_OPENGL_INIT_PARAMS = 2, + /** + * Describes a GL render target. Valid for mpv_render_context_render(). + * Type: mpv_opengl_fbo* + */ + MPV_RENDER_PARAM_OPENGL_FBO = 3, + /** + * Control flipped rendering. Valid for mpv_render_context_render(). + * Type: int* + * If the value is set to 0, render normally. Otherwise, render it flipped, + * which is needed e.g. when rendering to an OpenGL default framebuffer + * (which has a flipped coordinate system). + */ + MPV_RENDER_PARAM_FLIP_Y = 4, + /** + * Control surface depth. Valid for mpv_render_context_render(). + * Type: int* + * This implies the depth of the surface passed to the render function in + * bits per channel. If omitted or set to 0, the renderer will assume 8. + * Typically used to control dithering. + */ + MPV_RENDER_PARAM_DEPTH = 5, + /** + * ICC profile blob. Valid for mpv_render_context_set_parameter(). + * Type: mpv_byte_array* + * Set an ICC profile for use with the "icc-profile-auto" option. (If the + * option is not enabled, the ICC data will not be used.) + */ + MPV_RENDER_PARAM_ICC_PROFILE = 6, + /** + * Ambient light in lux. Valid for mpv_render_context_set_parameter(). + * Type: int* + * This can be used for automatic gamma correction. + */ + MPV_RENDER_PARAM_AMBIENT_LIGHT = 7, +} mpv_render_param_type; + +/** + * Predefined values for MPV_RENDER_PARAM_API_TYPE. + */ +#define MPV_RENDER_API_TYPE_OPENGL "opengl" + +/** + * Used to pass arbitrary parameters to some mpv_render_* functions. The + * meaning of the data parameter is determined by the type, and each + * MPV_RENDER_PARAM_* documents what type the value must point to. + * + * Each value documents the required data type as the pointer you cast to + * void* and set on mpv_render_param.data. For example, if MPV_RENDER_PARAM_FOO + * documents the type as Something* , then the code should look like this: + * + * Something foo = {...}; + * mpv_render_param param; + * param.type = MPV_RENDER_PARAM_FOO; + * param.data = & foo; + * + * Normally, the data field points to exactly 1 object. If the type is char*, + * it points to a 0-terminated string. + * + * In all cases (unless documented otherwise) the pointers need to remain + * valid during the call only. Unless otherwise documented, the API functions + * will not write to the params array or any data pointed to it. + * + * As a convention, parameter arrays are always terminated by type==0. There + * is no specific order of the parameters required. The order of fields is + * guaranteed (even after ABI changes). + */ +typedef struct mpv_render_param { + enum mpv_render_param_type type; + void *data; +} mpv_render_param; + +/** + * Initialize the renderer state. Depending on the backend used, this will + * access the underlying GPU API and initialize its own objects. + * + * You must free the context with mpv_render_context_free(). Not doing so before + * the mpv core is destroyed may result in memory leaks or crashes. + * + * Currently, only at most 1 context can exists per mpv core (it represents the + * main video output). + * + * @param res set to the context (on success) or NULL (on failure). The value + * is never read and always overwritten. + * @param mpv handle used to get the core (the mpv_render_context won't depend + * on this specific handle, only the core referenced by it) + * @param params an array of parameters, terminated by type==0. It's left + * unspecified what happens with unknown parameters. At least + * MPV_RENDER_PARAM_API_TYPE is required, and most backends will + * require another backend-specific parameter. + * @return error code, including but not limited to: + * MPV_ERROR_UNSUPPORTED: the OpenGL version is not supported + * (or required extensions are missing) + * MPV_ERROR_NOT_IMPLEMENTED: an unknown API type was provided, or + * support for the requested API was not + * built in the used libmpv binary. + * MPV_ERROR_INVALID_PARAMETER: at least one of the provided parameters was + * not valid. + */ +int mpv_render_context_create(mpv_render_context **res, mpv_handle *mpv, + mpv_render_param *params); + +/** + * Attempt to change a single parameter. Not all backends and parameter types + * support all kinds of changes. + * + * @param ctx a valid render context + * @param param the parameter type and data that should be set + * @return error code. If a parameter could actually be changed, this returns + * success, otherwise an error code depending on the parameter type + * and situation. + */ +int mpv_render_context_set_parameter(mpv_render_context *ctx, + mpv_render_param param); + +typedef void (*mpv_render_update_fn)(void *cb_ctx); + +/** + * Set the callback that notifies you when a new video frame is available, or + * if the video display configuration somehow changed and requires a redraw. + * Similar to mpv_set_wakeup_callback(), you must not call any mpv API from + * the callback, and all the other listed restrictions apply (such as not + * exiting the callback by throwing exceptions). + * + * This can be called from any thread, except from an update callback. In case + * of the OpenGL backend, no OpenGL state or API is accessed. + * + * @param callback callback(callback_ctx) is called if the frame should be + * redrawn + * @param callback_ctx opaque argument to the callback + */ +void mpv_render_context_set_update_callback(mpv_render_context *ctx, + mpv_render_update_fn callback, + void *callback_ctx); + +/** + * Render video. + * + * Typically renders the video to a target surface provided via mpv_render_param + * (the details depend on the backend in use). Options like "panscan" are + * applied to determine which part of the video should be visible and how the + * video should be scaled. You can change these options at runtime by using the + * mpv property API. + * + * The renderer will reconfigure itself every time the target surface + * configuration (such as size) is changed. + * + * This function implicitly pulls a video frame from the internal queue and + * renders it. If no new frame is available, the previous frame is redrawn. + * The update callback set with mpv_render_context_set_update_callback() + * notifies you when a new frame was added. The details potentially depend on + * the backends and the provided parameters. + * + * @param ctx a valid render context + * @param params an array of parameters, terminated by type==0. Which parameters + * are required depends on the backend. It's left unspecified what + * happens with unknown parameters. + * @return error code + */ +int mpv_render_context_render(mpv_render_context *ctx, mpv_render_param *params); + +/** + * Tell the renderer that a frame was flipped at the given time. This is + * optional, but can help the player to achieve better timing. + * + * Note that calling this at least once informs libmpv that you will use this + * function. If you use it inconsistently, expect bad video playback. + * + * If this is called while no video is initialized, it is ignored. + * + * @param ctx a valid render context + */ +void mpv_render_context_report_swap(mpv_render_context *ctx); + +/** + * Destroy the mpv renderer state. + * + * If video is still active (e.g. a file playing), video will be disabled + * forcefully. + * + * @param ctx a valid render context. After this function returns, this is not + * a valid pointer anymore. NULL is also allowed and does nothing. + */ +void mpv_render_context_free(mpv_render_context *ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libmpv/render_gl.h b/libmpv/render_gl.h new file mode 100644 index 0000000000..01c09e80df --- /dev/null +++ b/libmpv/render_gl.h @@ -0,0 +1,155 @@ +/* Copyright (C) 2018 the mpv developers + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef MPV_CLIENT_API_RENDER_GL_H_ +#define MPV_CLIENT_API_RENDER_GL_H_ + +#include "render.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * OpenGL backend + * -------------- + * + * This header contains definitions for using OpenGL with the render.h API. + * + * OpenGL interop + * -------------- + * + * The OpenGL backend has some special rules, because OpenGL itself uses + * implicit per-thread contexts, which causes additional API problems. + * + * This assumes the OpenGL context lives on a certain thread controlled by the + * API user. All mpv_render_* APIs have to be assumed to implicitly use the + * OpenGL context if you pass a mpv_render_context using the OpenGL backend, + * unless specified otherwise. + * + * The OpenGL context is indirectly accessed through the OpenGL function + * pointers returned by the get_proc_address callback in mpv_opengl_init_params. + * Generally, mpv will not load the system OpenGL library when using this API. + * + * OpenGL state + * ------------ + * + * OpenGL has a large amount of implicit state. All the mpv functions mentioned + * above expect that the OpenGL state is reasonably set to OpenGL standard + * defaults. Likewise, mpv will attempt to leave the OpenGL context with + * standard defaults. The following state is excluded from this: + * + * - the glViewport state + * - the glScissor state (but GL_SCISSOR_TEST is in its default value) + * - glBlendFuncSeparate() state (but GL_BLEND is in its default value) + * - glClearColor() state + * - mpv may overwrite the callback set with glDebugMessageCallback() + * - mpv always disables GL_DITHER at init + * + * Messing with the state could be avoided by creating shared OpenGL contexts, + * but this is avoided for the sake of compatibility and interoperability. + * + * On OpenGL 2.1, mpv will strictly call functions like glGenTextures() to + * create OpenGL objects. You will have to do the same. This ensures that + * objects created by mpv and the API users don't clash. Also, legacy state + * must be either in its defaults, or not interfere with core state. + * + * API use + * ------- + * + * The mpv_render_* API is used. That API supports multiple backends, and this + * section documents specifics for the OpenGL backend. + * + * Use mpv_render_context_create() with MPV_RENDER_PARAM_API_TYPE set to + * MPV_RENDER_API_TYPE_OPENGL, and MPV_RENDER_PARAM_OPENGL_INIT_PARAMS provided. + * + * Call mpv_render_context_render() with MPV_RENDER_PARAM_OPENGL_FBO to render + * the video frame to an FBO. + * + * Hardware decoding + * ----------------- + * + * Hardware decoding via this API is fully supported, but requires some + * additional setup. (At least if direct hardware decoding modes are wanted, + * instead of copying back surface data from GPU to CPU RAM.) + * + * There may be certain requirements on the OpenGL implementation: + * + * - Windows: ANGLE is required (although in theory GL/DX interop could be used) + * - Intel/Linux: EGL is required, and also a glMPGetNativeDisplay() callback + * must be provided (see sections below) + * - nVidia/Linux: Both GLX and EGL should work (GLX is required if vdpau is + * used, e.g. due to old drivers.) + * - OSX: CGL is required (CGLGetCurrentContext() returning non-NULL) + * - iOS: EAGL is required (EAGLContext.currentContext returning non-nil) + * + * Once these things are setup, hardware decoding can be enabled/disabled at + * any time by setting the "hwdec" property. + */ + +/** + * For initializing the mpv OpenGL state via MPV_RENDER_PARAM_OPENGL_INIT_PARAMS. + */ +typedef struct mpv_opengl_init_params { + /** + * This retrieves OpenGL function pointers, and will use them in subsequent + * operation. + * Usually, GL context APIs do this for you (e.g. with glXGetProcAddressARB + * or wglGetProcAddress), but some APIs do not always return pointers for + * all standard functions (even if present); in this case you have to + * compensate by looking up these functions yourself and returning them + * from this callback. + */ + void *(*get_proc_address)(void *ctx, const char *name); + /** + * Value passed as ctx parameter to get_proc_address(). + */ + void *get_proc_address_ctx; + /** + * This should not be used. The main purpose is signaling support for + * "GL_MP_MPGetNativeDisplay", which is needed for compatibility with the + * opengl_cb API only. Thus it's deprecated and will be removed or ignored + * when the opengl_cb API is removed. + */ + const char *extra_exts; +} mpv_opengl_init_params; + +/** + * For MPV_RENDER_PARAM_OPENGL_FBO. + */ +typedef struct mpv_opengl_fbo { + /** + * Framebuffer object name. This must be either a valid FBO generated by + * glGenFramebuffers() that is complete and color-renderable, or 0. If the + * value is 0, this refers to the OpenGL default framebuffer. + */ + int fbo; + /** + * Valid dimensions. This must refer to the size of the framebuffer. This + * must always be set. + */ + int w, h; + /** + * Underlying texture internal format (e.g. GL_RGBA8), or 0 if unknown. If + * this is the default framebuffer, this can be an equivalent. + */ + int internal_format; +} mpv_opengl_fbo; + +#ifdef __cplusplus +} +#endif + +#endif 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, |