#include "client.h"
Go to the source code of this file.
Classes | |
struct | mpv_render_param |
Used to pass arbitrary parameters to some mpv_render_* functions. More... | |
struct | mpv_render_frame_info |
Information about the next video frame that will be rendered. More... | |
Macros | |
#define | MPV_RENDER_PARAM_DRM_OSD_SIZE MPV_RENDER_PARAM_DRM_DRAW_SURFACE_SIZE |
For backwards compatibility with the old naming of MPV_RENDER_PARAM_DRM_DRAW_SURFACE_SIZE. More... | |
#define | MPV_RENDER_API_TYPE_OPENGL "opengl" |
Predefined values for MPV_RENDER_PARAM_API_TYPE. More... | |
#define | MPV_RENDER_API_TYPE_SW "sw" |
Typedefs | |
typedef struct mpv_render_context | mpv_render_context |
Opaque context, returned by mpv_render_context_create(). More... | |
typedef enum mpv_render_param_type | mpv_render_param_type |
Parameters for mpv_render_param (which is used in a few places such as mpv_render_context_create(). More... | |
typedef struct mpv_render_param | mpv_render_param |
Used to pass arbitrary parameters to some mpv_render_* functions. More... | |
typedef enum mpv_render_frame_info_flag | mpv_render_frame_info_flag |
Flags used in mpv_render_frame_info.flags. More... | |
typedef struct mpv_render_frame_info | mpv_render_frame_info |
Information about the next video frame that will be rendered. More... | |
typedef void(* | mpv_render_update_fn) (void *cb_ctx) |
typedef enum mpv_render_update_flag | mpv_render_context_flag |
Flags returned by mpv_render_context_update(). More... | |
Functions | |
int | mpv_render_context_create (mpv_render_context **res, mpv_handle *mpv, mpv_render_param *params) |
Initialize the renderer state. More... | |
int | mpv_render_context_set_parameter (mpv_render_context *ctx, mpv_render_param param) |
Attempt to change a single parameter. More... | |
int | mpv_render_context_get_info (mpv_render_context *ctx, mpv_render_param param) |
Retrieve information from the render context. More... | |
void | mpv_render_context_set_update_callback (mpv_render_context *ctx, mpv_render_update_fn callback, void *callback_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. More... | |
uint64_t | mpv_render_context_update (mpv_render_context *ctx) |
The API user is supposed to call this when the update callback was invoked (like all mpv_render_* functions, this has to happen on the render thread, and not from the update callback itself). More... | |
int | mpv_render_context_render (mpv_render_context *ctx, mpv_render_param *params) |
Render video. More... | |
void | mpv_render_context_report_swap (mpv_render_context *ctx) |
Tell the renderer that a frame was flipped at the given time. More... | |
void | mpv_render_context_free (mpv_render_context *ctx) |
Destroy the mpv renderer state. More... | |
#define MPV_RENDER_API_TYPE_OPENGL "opengl" |
#define MPV_RENDER_PARAM_DRM_OSD_SIZE MPV_RENDER_PARAM_DRM_DRAW_SURFACE_SIZE |
typedef struct mpv_render_context mpv_render_context |
Opaque context, returned by mpv_render_context_create().
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). See "Threading" section below.
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.
OpenGL: via MPV_RENDER_API_TYPE_OPENGL, see render_gl.h header. Software: via MPV_RENDER_API_TYPE_SW, see section "Software renderer"
You are recommended to do rendering on a separate thread than normal libmpv use.
The mpv_render_* functions can be called from any thread, under the following conditions:
libmpv functions which are safe to call from a render thread are:
Note about old libmpv version:
Before API version 1.105 (basically in mpv 0.29.x), simply enabling MPV_RENDER_PARAM_ADVANCED_CONTROL could cause deadlock issues. This can be worked around by setting the "vd-lavc-dr" option to "no". In addition, you were required to call all mpv_render*() API functions from the same thread on which mpv_render_context_create() was originally run (for the same the mpv_render_context). Not honoring it led to UB (deadlocks, use of invalid pthread_t handles), even if you moved your GL context to a different thread correctly. These problems were addressed in API version 1.105 (mpv 0.30.0).
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.
Currently, there can be only 1 mpv_render_context at a time per mpv core.
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.
MPV_RENDER_API_TYPE_SW provides an extremely simple (but slow) renderer to memory surfaces. You probably don't want to use this. Use other render API types, or other methods of video embedding.
Use mpv_render_context_create() with MPV_RENDER_PARAM_API_TYPE set to MPV_RENDER_API_TYPE_SW.
Call mpv_render_context_render() with various MPV_RENDER_PARAM_SW_* fields to render the video frame to an in-memory surface. The following fields are required: MPV_RENDER_PARAM_SW_SIZE, MPV_RENDER_PARAM_SW_FORMAT, MPV_RENDER_PARAM_SW_STRIDE, MPV_RENDER_PARAM_SW_POINTER.
This method of rendering is very slow, because everything, including color conversion, scaling, and OSD rendering, is done on the CPU, single-threaded. In particular, large video or display sizes, as well as presence of OSD or subtitles can make it too slow for realtime. As with other software rendering VOs, setting "sw-fast" may help. Enabling or disabling zimg may help, depending on the platform.
In addition, certain multimedia job creation measures like HDR may not work properly, and will have to be manually handled by for example inserting filters.
This API is not really suitable to extract individual frames from video etc. (basically non-playback uses) - there are better libraries for this. It can be used this way, but it may be clunky and tricky.
Further notes:
typedef enum mpv_render_update_flag mpv_render_context_flag |
Flags returned by mpv_render_context_update().
Each value represents a bit in the function's return value.
typedef struct mpv_render_frame_info mpv_render_frame_info |
Information about the next video frame that will be rendered.
Can be retrieved with MPV_RENDER_PARAM_NEXT_FRAME_INFO.
typedef enum mpv_render_frame_info_flag mpv_render_frame_info_flag |
Flags used in mpv_render_frame_info.flags.
Each value represents a bit in it.
typedef struct mpv_render_param mpv_render_param |
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 the 2 fields in this struct is guaranteed (even after ABI changes).
typedef enum mpv_render_param_type mpv_render_param_type |
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.
Flags used in mpv_render_frame_info.flags.
Each value represents a bit in it.
Enumerator | |
---|---|
MPV_RENDER_FRAME_INFO_PRESENT | Set if there is actually a next frame. If unset, there is no next frame yet, and other flags and fields that require a frame to be queued will be unset. This is set for any kind of frame, even for redraw requests. Note that when this is unset, it simply means no new frame was decoded/queued yet, not necessarily that the end of the video was reached. A new frame can be queued after some time. If the return value of mpv_render_context_render() had the MPV_RENDER_UPDATE_FRAME flag set, this flag will usually be set as well, unless the frame is rendered, or discarded by other asynchronous events. |
MPV_RENDER_FRAME_INFO_REDRAW | If set, the frame is not an actual new video frame, but a redraw request. For example if the video is paused, and an option that affects video rendering was changed (or any other reason), an update request can be issued and this flag will be set. Typically, redraw frames will not be subject to video timing. Implies MPV_RENDER_FRAME_INFO_PRESENT. |
MPV_RENDER_FRAME_INFO_REPEAT | If set, this is supposed to reproduce the previous frame perfectly. This is usually used for certain "video-sync" options ("display-..." modes). Typically the renderer will blit the video from a FBO. Unset otherwise. Implies MPV_RENDER_FRAME_INFO_PRESENT. |
MPV_RENDER_FRAME_INFO_BLOCK_VSYNC | If set, the player timing code expects that the user thread blocks on vsync (by either delaying the render call, or by making a call to mpv_render_context_report_swap() at vsync time). Implies MPV_RENDER_FRAME_INFO_PRESENT. |
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.
Enumerator | |
---|---|
MPV_RENDER_PARAM_INVALID | 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_API_TYPE | 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_OPENGL_INIT_PARAMS | Required parameters for initializing the OpenGL renderer. Valid for mpv_render_context_create(). Type: mpv_opengl_init_params* |
MPV_RENDER_PARAM_OPENGL_FBO | Describes a GL render target. Valid for mpv_render_context_render(). Type: mpv_opengl_fbo* |
MPV_RENDER_PARAM_FLIP_Y | 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_DEPTH | 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_ICC_PROFILE | 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_AMBIENT_LIGHT | Ambient light in lux. Valid for mpv_render_context_set_parameter(). Type: int* This can be used for automatic gamma correction. |
MPV_RENDER_PARAM_X11_DISPLAY | X11 Display, sometimes used for hwdec. Valid for mpv_render_context_create(). The Display must stay valid for the lifetime of the mpv_render_context. Type: Display* |
MPV_RENDER_PARAM_WL_DISPLAY | Wayland display, sometimes used for hwdec. Valid for mpv_render_context_create(). The wl_display must stay valid for the lifetime of the mpv_render_context. Type: struct wl_display* |
MPV_RENDER_PARAM_ADVANCED_CONTROL | Better control about rendering and enabling some advanced features. Valid for mpv_render_context_create(). This conflates multiple requirements the API user promises to abide if this option is enabled:
In general, setting this option will enable the following features (and possibly more):
Warning: do not just add this without reading the "Threading" section above, and then wondering that deadlocks happen. The requirements are tricky. But also note that even if advanced control is disabled, not adhering to the rules will lead to playback problems. Enabling advanced controls simply makes violating these rules fatal. Type: int*: 0 for disable (default), 1 for enable |
MPV_RENDER_PARAM_NEXT_FRAME_INFO | Return information about the next frame to render. Valid for mpv_render_context_get_info(). Type: mpv_render_frame_info* It strictly returns information about the next frame. The implication is that e.g. mpv_render_context_update()'s return value will have MPV_RENDER_UPDATE_FRAME set, and the user is supposed to call mpv_render_context_render(). If there is no next frame, then the return value will have is_valid set to 0. |
MPV_RENDER_PARAM_BLOCK_FOR_TARGET_TIME | Enable or disable video timing. Valid for mpv_render_context_render(). Type: int*: 0 for disable, 1 for enable (default) When video is timed to audio, the player attempts to render video a bit ahead, and then do a blocking wait until the target display time is reached. This blocks mpv_render_context_render() for up to the amount specified with the "video-timing-offset" global option. You can set this parameter to 0 to disable this kind of waiting. If you do, it's recommended to use the target time value in mpv_render_frame_info to wait yourself, or to set the "video-timing-offset" to 0 instead. Disabling this without doing anything in addition will result in A/V sync being slightly off. |
MPV_RENDER_PARAM_SKIP_RENDERING | Use to skip rendering in mpv_render_context_render(). Type: int*: 0 for rendering (default), 1 for skipping If this is set, you don't need to pass a target surface to the render function (and if you do, it's completely ignored). This can still call into the lower level APIs (i.e. if you use OpenGL, the OpenGL context must be set). Be aware that the render API will consider this frame as having been rendered. All other normal rules also apply, for example about whether you have to call mpv_render_context_report_swap(). It also does timing in the same way. |
MPV_RENDER_PARAM_DRM_DISPLAY | Deprecated. Not supported. Use MPV_RENDER_PARAM_DRM_DISPLAY_V2 instead. Type : struct mpv_opengl_drm_params* |
MPV_RENDER_PARAM_DRM_DRAW_SURFACE_SIZE | DRM draw surface size, contains draw surface dimensions. Valid for mpv_render_context_create(). Type : struct mpv_opengl_drm_draw_surface_size* |
MPV_RENDER_PARAM_DRM_DISPLAY_V2 | DRM display, contains drm display handles. Valid for mpv_render_context_create(). Type : struct mpv_opengl_drm_params_v2* |
MPV_RENDER_PARAM_SW_SIZE | MPV_RENDER_API_TYPE_SW only: rendering target surface size, mandatory. Valid for MPV_RENDER_API_TYPE_SW & mpv_render_context_create(). Type: int2 The video frame is transformed as with other VOs. Typically, this means the video gets scaled and black bars are added if the video size or aspect ratio mismatches with the target size. |
MPV_RENDER_PARAM_SW_FORMAT | MPV_RENDER_API_TYPE_SW only: rendering target surface pixel format, mandatory. Valid for MPV_RENDER_API_TYPE_SW & mpv_render_context_create(). Type: char* (e.g.: char *f = "rgb0"; param.data = f;) Valid values are: "rgb0", "bgr0", "0bgr", "0rgb" 4 bytes per pixel RGB, 1 byte (8 bit) per component, component bytes with increasing address from left to right (e.g. "rgb0" has r at address 0), the "0" component contains uninitialized garbage (often the value 0, but not necessarily; the bad naming is inherited from FFmpeg) "rgb24" 3 bytes per pixel RGB. This is strongly discouraged because it is very slow. other The API may accept other pixel formats, using mpv internal format names, as long as it's internally marked as RGB, has exactly 1 plane, and is supported as conversion output. It is not a good idea to rely on any of these. Their semantics and handling could change. |
MPV_RENDER_PARAM_SW_STRIDE | MPV_RENDER_API_TYPE_SW only: rendering target surface bytes per line, mandatory. Valid for MPV_RENDER_API_TYPE_SW & mpv_render_context_create(). Type: size_t* This is the number of bytes between a pixel (x, y) and (x, y + 1) on the target surface. It must be a multiple of the pixel size, and have space for the surface width as specified by MPV_RENDER_PARAM_SW_SIZE. It should be a multiple of 64 to facilitate fast SIMD operation. |
MPV_RENDER_PARAM_SW_POINTER |
Flags returned by mpv_render_context_update().
Each value represents a bit in the function's return value.
Enumerator | |
---|---|
MPV_RENDER_UPDATE_FRAME | A new video frame must be rendered. mpv_render_context_render() must be called. |
int mpv_render_context_create | ( | mpv_render_context ** | res, |
mpv_handle * | mpv, | ||
mpv_render_param * | params | ||
) |
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).
You should pass the following parameters:
res | set to the context (on success) or NULL (on failure). The value is never read and always overwritten. |
mpv | handle used to get the core (the mpv_render_context won't depend on this specific handle, only the core referenced by it) |
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. |
void mpv_render_context_free | ( | mpv_render_context * | ctx | ) |
Destroy the mpv renderer state.
If video is still active (e.g. a file playing), video will be disabled forcefully.
ctx | a valid render context. After this function returns, this is not a valid pointer anymore. NULL is also allowed and does nothing. |
int mpv_render_context_get_info | ( | mpv_render_context * | ctx, |
mpv_render_param | param | ||
) |
Retrieve information from the render context.
This is NOT a counterpart to mpv_render_context_set_parameter(), because you generally can't read parameters set with it, and this function is not meant for this purpose. Instead, this is for communicating information from the renderer back to the user. See mpv_render_param_type; entries which support this function explicitly mention it, and for other entries you can assume it will fail.
You pass param with param.type set and param.data pointing to a variable of the required data type. The function will then overwrite that variable with the returned value (at least on success).
ctx | a valid render context |
param | the parameter type and data that should be retrieved |
int mpv_render_context_render | ( | mpv_render_context * | ctx, |
mpv_render_param * | params | ||
) |
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.
Generally, libmpv will invoke your update callback some time before the video frame should be shown, and then lets this function block until the supposed display time. This will limit your rendering to video FPS. You can prevent this by setting the "video-timing-offset" global option to 0. (This applies only to "audio" video sync mode.)
You should pass the following parameters:
ctx | a valid render context |
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. |
void mpv_render_context_report_swap | ( | mpv_render_context * | ctx | ) |
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.
ctx | a valid render context |
int mpv_render_context_set_parameter | ( | mpv_render_context * | ctx, |
mpv_render_param | param | ||
) |
Attempt to change a single parameter.
Not all backends and parameter types support all kinds of changes.
ctx | a valid render context |
param | the parameter type and data that should be set |
void mpv_render_context_set_update_callback | ( | mpv_render_context * | ctx, |
mpv_render_update_fn | callback, | ||
void * | callback_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.
Calling this will raise an update callback immediately.
callback | callback(callback_ctx) is called if the frame should be redrawn |
callback_ctx | opaque argument to the callback |
uint64_t mpv_render_context_update | ( | mpv_render_context * | ctx | ) |
The API user is supposed to call this when the update callback was invoked (like all mpv_render_* functions, this has to happen on the render thread, and not from the update callback itself).
This is optional if MPV_RENDER_PARAM_ADVANCED_CONTROL was not set (default). Otherwise, it's a hard requirement that this is called after each update callback. If multiple update callback happened, and the function could not be called sooner, it's OK to call it once after the last callback.
If an update callback happens during or after this function, the function must be called again at the soonest possible time.
If MPV_RENDER_PARAM_ADVANCED_CONTROL was set, this will do additional work such as allocating textures for the video decoder.