summaryrefslogtreecommitdiffstats
path: root/libmpv
diff options
context:
space:
mode:
Diffstat (limited to 'libmpv')
-rw-r--r--libmpv/client.h23
-rw-r--r--libmpv/mpv.def1
-rw-r--r--libmpv/render.h105
3 files changed, 127 insertions, 2 deletions
diff --git a/libmpv/client.h b/libmpv/client.h
index 77c149e405..488ccb332c 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, 100)
+#define MPV_CLIENT_API_VERSION MPV_MAKE_VERSION(1, 101)
/**
* The API user is allowed to "#define MPV_ENABLE_DEPRECATED 0" before
@@ -614,6 +614,8 @@ void mpv_resume(mpv_handle *ctx);
*
* Unlike other libmpv APIs, this can be called at absolutely any time (even
* within wakeup callbacks), as long as the context is valid.
+ *
+ * Safe to be called from mpv render API threads.
*/
int64_t mpv_get_time_us(mpv_handle *ctx);
@@ -959,6 +961,8 @@ int mpv_command_string(mpv_handle *ctx, const char *args);
* be unified in the future. For now, calling this API means that the command
* will be synchronously executed on the core, without blocking the API user.
*
+ * * Safe to be called from mpv render API threads.
+ *
* @param reply_userdata the value mpv_event.reply_userdata of the reply will
* be set to (see section about asynchronous calls)
* @param args NULL-terminated list of strings (see mpv_command())
@@ -975,6 +979,8 @@ int mpv_command_async(mpv_handle *ctx, uint64_t reply_userdata,
* See mpv_command_async() for details. Retrieving the result is not
* supported yet.
*
+ * Safe to be called from mpv render API threads.
+ *
* @param reply_userdata the value mpv_event.reply_userdata of the reply will
* be set to (see section about asynchronous calls)
* @param args as in mpv_command_node()
@@ -1030,6 +1036,8 @@ int mpv_set_property_string(mpv_handle *ctx, const char *name, const char *data)
* the result status of the operation. Otherwise, this function is similar to
* mpv_set_property().
*
+ * Safe to be called from mpv render API threads.
+ *
* @param reply_userdata see section about asynchronous calls
* @param name The property name.
* @param format see enum mpv_format.
@@ -1090,6 +1098,8 @@ char *mpv_get_property_osd_string(mpv_handle *ctx, const char *name);
* as well as the property data with the MPV_EVENT_GET_PROPERTY_REPLY event.
* You should check the mpv_event.error field on the reply event.
*
+ * Safe to be called from mpv render API threads.
+ *
* @param reply_userdata see section about asynchronous calls
* @param name The property name.
* @param format see enum mpv_format.
@@ -1136,6 +1146,8 @@ int mpv_get_property_async(mpv_handle *ctx, uint64_t reply_userdata,
* Only the mpv_handle on which this was called will receive the property
* change events, or can unobserve them.
*
+ * Safe to be called from mpv render API threads.
+ *
* @param reply_userdata This will be used for the mpv_event.reply_userdata
* field for the received MPV_EVENT_PROPERTY_CHANGE
* events. (Also see section about asynchronous calls,
@@ -1155,6 +1167,8 @@ int mpv_observe_property(mpv_handle *mpv, uint64_t reply_userdata,
* Undo mpv_observe_property(). This will remove all observed properties for
* which the given number was passed as reply_userdata to mpv_observe_property.
*
+ * Safe to be called from mpv render API threads.
+ *
* @param registered_reply_userdata ID that was passed to mpv_observe_property
* @return negative value is an error code, >=0 is number of removed properties
* on success (includes the case when 0 were removed)
@@ -1586,6 +1600,8 @@ typedef struct mpv_event {
* (Informational note: currently, all events are enabled by default, except
* MPV_EVENT_TICK.)
*
+ * Safe to be called from mpv render API threads.
+ *
* @param event See enum mpv_event_id.
* @param enable 1 to enable receiving this event, 0 to disable it.
* @return error code
@@ -1625,6 +1641,9 @@ int mpv_request_log_messages(mpv_handle *ctx, const char *min_level);
* function internally calls mpv_wait_event(). Additionally, concurrent calls
* to different mpv_handles are always safe.
*
+ * As long as the timeout is 0, this is safe to be called from mpv render API
+ * threads.
+ *
* @param timeout Timeout in seconds, after which the function returns even if
* no event was received. A MPV_EVENT_NONE is returned on
* timeout. A value of 0 will disable waiting. Negative values
@@ -1648,6 +1667,8 @@ mpv_event *mpv_wait_event(mpv_handle *ctx, double timeout);
* this call. But note that this dummy event might be skipped if there are
* already other events queued. All what counts is that the waiting thread
* is woken up at all.
+ *
+ * Safe to be called from mpv render API threads.
*/
void mpv_wakeup(mpv_handle *ctx);
diff --git a/libmpv/mpv.def b/libmpv/mpv.def
index 1d828f4b2b..efbf713622 100644
--- a/libmpv/mpv.def
+++ b/libmpv/mpv.def
@@ -38,6 +38,7 @@ mpv_render_context_render
mpv_render_context_report_swap
mpv_render_context_set_parameter
mpv_render_context_set_update_callback
+mpv_render_context_update
mpv_request_event
mpv_request_log_messages
mpv_resume
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