summaryrefslogtreecommitdiffstats
path: root/libmpv/render.h
diff options
context:
space:
mode:
Diffstat (limited to 'libmpv/render.h')
-rw-r--r--libmpv/render.h105
1 files changed, 104 insertions, 1 deletions
diff --git a/libmpv/render.h b/libmpv/render.h
index 34adb39646..af434b04e2 100644
--- a/libmpv/render.h
+++ b/libmpv/render.h
@@ -38,7 +38,7 @@ extern "C" {
* 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).
+ * 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
@@ -54,6 +54,9 @@ extern "C" {
* Threading
* ---------
*
+ * 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:
* - only one of the mpv_render_* functions can be called at the same time
@@ -64,6 +67,32 @@ extern "C" {
* 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.
+ * - the thread does not call libmpv API functions other than the mpv_render_*
+ * functions, except APIs which are declared as safe (see below). Likewise,
+ * there must be no lock or wait dependency from the render thread to a
+ * thread using other libmpv functions. Basically, the situation that your
+ * render thread waits for a "not safe" libmpv API function to return must
+ * not happen. If you ignore this requirement, deadlocks can happen, which
+ * are made non-fatal with timeouts; then playback quality will be degraded,
+ * and the message
+ * mpv_render_context_render() not being called or stuck.
+ * is logged. If you set MPV_RENDER_PARAM_ADVANCED_CONTROL, you promise that
+ * this won't happen, and must absolutely guarantee it, or a real deadlock
+ * will freeze the mpv core thread forever.
+ *
+ * libmpv functions which are safe to call from a render thread are:
+ * - functions marked with "Safe to be called from mpv render API threads."
+ * - client.h functions which don't have an explicit or implicit mpv_handle
+ * parameter
+ * - mpv_render_* functions; but only for the same mpv_render_context pointer.
+ * If the pointer is different, mpv_render_context_free() is not safe. (The
+ * reason is that if MPV_RENDER_PARAM_ADVANCED_CONTROL is set, it may have
+ * to process still queued requests from the core, which it can do only for
+ * the current context, while requests for other contexts would deadlock.
+ * Also, it may have to wait and block for the core to terminate the video
+ * chain to make sure no resources are used after context destruction.)
+ * - if the mpv_handle parameter refers to a different mpv core than the one
+ * you're rendering for (very obscure, but allowed)
*
* Context and handle lifecycle
* ----------------------------
@@ -72,6 +101,8 @@ extern "C" {
* (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.
*
@@ -166,6 +197,39 @@ typedef enum mpv_render_param_type {
* Type: struct wl_display*
*/
MPV_RENDER_PARAM_WL_DISPLAY = 9,
+ /**
+ * 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:
+ *
+ * - The API user's render thread, which is calling the mpv_render_*()
+ * functions, never waits for the core. Otherwise deadlocks can happen.
+ * See "Threading" section.
+ * - The callback set with mpv_render_context_set_update_callback() can now
+ * be called even if there is no new frame. The API user should call the
+ * mpv_render_context_update() function, and interpret the return value
+ * for whether a new frame should be rendered.
+ * - Correct functionality is impossible if the update callback is not set,
+ * or not set soon enough after mpv_render_context_create() (the core can
+ * block while waiting for you to call mpv_render_context_update(), and
+ * if the update callback is not correctly set, it will deadlock, or
+ * block for too long).
+ *
+ * In general, setting this option will enable the following features (and
+ * possibly more):
+ *
+ * - "Direct rendering", which means the player decodes directly to a
+ * texture, which saves a copy per video frame ("vd-lavc-dr" option
+ * needs to be enabled, and the rendering backend as well as the
+ * underlying GPU API/driver needs to have support for it).
+ * - Rendering screenshots with the GPU API if supported by the backend
+ * (instead of using a suboptimal software fallback via libswscale).
+ *
+ * Type: int*: 0 for disable (default), 1 for enable
+ */
+ MPV_RENDER_PARAM_ADVANCED_CONTROL = 10,
} mpv_render_param_type;
/**
@@ -258,6 +322,8 @@ typedef void (*mpv_render_update_fn)(void *cb_ctx);
* 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.
+ *
* @param callback callback(callback_ctx) is called if the frame should be
* redrawn
* @param callback_ctx opaque argument to the callback
@@ -267,6 +333,43 @@ void mpv_render_context_set_update_callback(mpv_render_context *ctx,
void *callback_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.
+ *
+ * @return a bitset of mpv_render_update_flag values (i.e. multiple flags are
+ * combined with bitwise or). Typically, this will tell the API user
+ * what should happen next. E.g. if the MPV_RENDER_UPDATE_FRAME flag is
+ * set, mpv_render_context_render() should be called. If flags unknown
+ * to the API user are set, or if the return value is 0, nothing needs
+ * to be done.
+ */
+uint64_t mpv_render_context_update(mpv_render_context *ctx);
+
+/**
+ * Flags returned by mpv_render_context_update(). Each value represents a bit
+ * in the function's return value.
+ */
+typedef enum mpv_render_update_flag {
+ /**
+ * A new video frame must be rendered. mpv_render_context_render() must be
+ * called.
+ */
+ MPV_RENDER_UPDATE_FRAME = 1 << 0,
+} mpv_render_context_flag;
+
+/**
* Render video.
*
* Typically renders the video to a target surface provided via mpv_render_param