mpv_event_property (for property observation) actually never sets an
error status. You cannot distinguish between unavailable properties and
properties which returned an error. Not sure if it ever did.
Another thing nobody will read. I'm attempting to document the rules by
which incompatible changes can be made. These rules have always been
present in this project, but I don't think they were written down. Or
maybe they were, but I forgot where.
I think due to the time of the day it became increasingly incoherent
(not necessarily near the end of the text). Hopefully no logical or
freudian lapses in there.
There's potential confusion about how long a process started with the
"subprocess" command is allowed to live. Add some more explanations
regarding "subprocess" specifics (such as the playback_only field), and
things that apply to asynchronous commands in general.
Partially for #7025.
This allows stream_cb backends to implement blocking
behavior inside read_fn, and still get notified when the user
wants to cancel and stop playback.
Signed-off-by: Aman Gupta <aman@tmm1.net>
I think a popular libmpv application did exactly this: enabling advanced
control, and then receiving deadlocks. I didn't confirm it, though. In
any case, the API docs should avoid tricking users into making this easy
mistake.
The render API (vo_libmpv) had potential deadlock problems with
MPV_RENDER_PARAM_ADVANCED_CONTROL. This required vd-lavc-dr to be
enabled (the default). I never observed these deadlocks in the wild
(doesn't mean they didn't happen), although I could specifically provoke
them with some code changes.
The problem was mostly about DR (direct rendering, letting the video
decoder write to OpenGL buffer memory). Allocating/freeing a DR image
needs to be done on the OpenGL thread, even though _lots_ of threads are
involved with handling images. Freeing a DR image is a special case that
can happen any time. dr_helper.c does most of the evil magic of
achieving this. Unfortunately, there was a (sort of) circular lock
dependency: freeing an image while certain internal locks are held would
trigger the user's context update callback, which in turn would call
mpv_render_context_update(), which processed all pending free requests,
and then acquire an internal lock - which the caller might not release
until a further DR image could be freed.
"Solve" this by making freeing DR images asynchronous. This is slightly
risky, but actually not much. The DR images will be free'd eventually.
The biggest disadvantage is probably that debugging might get trickier.
Any solution to this problem will probably add images to free to some
sort of queue, and then process it later. I considered making this more
explicit (so there'd be a point where the caller forcibly waits for all
queued items to be free'd), but discarded these ideas as this probably
would only increase complexity.
Another consequence is that freeing DR images on the GL thread is not
synchronous anymore. Instead, it mpv_render_context_update() will do it
with a delay. This seems roundabout, but doesn't actually change
anything, and avoids additional code.
This also fixes that the render API required the render API user to
remain on the same thread, even though this wasn't documented. As such,
it was a bug. OpenGL essentially forces you to do all GL usage on a
single thread, but in theory the API user could for example move the GL
context to another thread.
The API bump is because I think you can't make enough noise about this.
Since we don't backport fixes to old versions, I'm specifically stating
that old versions are broken, and I'm supplying workarounds.
Internally, dr_helper_create() does not use pthread_self() anymore, thus
the vo.c change. I think it's better to make binding to the current
thread as explicit as possible.
Of course it's not sure that this fixes all deadlocks (probably not).
This change adds a version of `mpv_command` that also returns a result.
The main rationale behind this is `mpv_command_node` requires defining
multiple structs before you can even use it, which results in a pretty
painful to use interface just to get the result from a command.
There isn't really a good name for this function, so I'm open to
suggestions on a better name for it.
This is because dr_helper.c calls pthread_self(). It's used to avoid
deadlocks. This was not a problem internal to mpv (dr_helper.c was first
created for vo_gpu.c), but it accidentally leaked as an unintended
consequence of an implementation detail to libmpv.
This problem existed for MPV_RENDER_PARAM_ADVANCED_CONTROL users, ever
since it was introduced.
Maybe this could be done differently, but it's certainly very tricky.
the pthread_t is used to avoid deadlocks when the caller is on the same
thread as the one which needs to handle the calls.
The critical code is in free_dr_buffer_on_dr_thread(). It's called when
a DR image is free'd. Freeing a DR image requires access to the GL
context, i.e. it just has to run on the "GL" thread. In libmpv's case,
this is done by calling the API user's wakeup call, and the user will
eventually call mpv_render_context_update() on the "GL" thread, which in
turn calls mp_dispatch_queue_process() on the dispatch queue that was
passed to dr_helper_create(), which then calls av_buffer_unref(), which
calls gl_video_dr_free_buffer(). (God who came up with this rube
goldberg shit.)
The above case will typically happen when e.g. vd_lavc.c (internal mpv
thread) frees images. Allocation works similarly; deallocation is just
trickier because calls to free images are everywhere.
Now consider if mpv_render_context_render() releases a DR image. This
function is always called on the "GL" thread. Going through the dispatch
queue would obviously deadlock, because according to the render API
rules, the user's wakeup callback must not mpv_render_context_update(),
instead it has to signal the "GL" thread, which must wait until
mpv_render_context_render() returns. To avoid this deadlock, dr_helper.c
checks whether the calling thread is the "GL" thread, and if so, allows
a reentrant call (basically gl_video_dr_free_buffer() is called
directly).
While with GL, you usually will stay on the same thread, API users were
in theory allowed to e.g. move the GL context to a different thread. But
this dr_helper issue means this is not possible. Moreover, other APIs
will not have the same thread-locality problems as GL.
FUCK THIS SHIT
In theory, libmpv could provide an API to "move" the context to a
separate thread, but let's not start with even more broken crap like
this. I'm not sure yet whether there is an easy solution. Maybe all
mpv_render() function could be guarded by entry/exit functions, which
set/unset a flag that dr_helper.c should use reentrant calls.
libmpv users which do not set MPV_RENDER_PARAM_ADVANCED_CONTROL were
never affected.
Extending the client-allocated mpv_opengl_drm_params struct
constituted a break of ABI that could cause UB.
Create a clean break by deprecating "drm_params" and related structs
and enum values, and replacing it with "drm_params_v2".
Also fix some comments and code that wrongly assumed that open could
return any other negative number than -1 for failure.
This commit updates the libmpv version to 1.104
This commit bumps the libmpv version to 1.102
drm-osd-plane -> drm-draw-plane
drm-video-plane -> drm-drmprime-video-plane
drm-osd-size -> drm-draw-surface-size
"draw plane", as in the plane that OpenGL draws to, whether it be
video + OSD or just OSD.
"drmprime video plane", as in the plane used for hwdec video imported
via drmprime.
"draw surface size", as in the size of the surface used for the draw plane
The new names are invariant whether or not hwdec_drmprime_drm is being
used or not. The original naming was very confusing, as when doing
regular rendering (swdec or vaapi) the video would be displayed on the
"OSD plane", and the "Video plane" would remain unused.
Add another parameter to mpv_opengl_drm_params to hold the FD to the
render node, so that the fd can be passed to hwdec_vaegl.
The render node is opened in context_drm_egl and inferred from the
primary device fd using drmGetRenderDeviceNameFromFd.
Before this change, only 1 command or so had named arguments. There is
no reason why other commands can't have them, except that it's a bit of
work to add them.
Commands with variable number of arguments are inherently incompatible
to named arguments, such as the "run" command. They still have dummy
names, but obviously you can't assign multiple values to a single named
argument (unless the argument has an array type, which would be
something different). For now, disallow using named argument APIs with
these commands. This might change later.
2 commands are adjusted to not need a separate default value by changing
flag constants. (The numeric values are C only and can't be set by
users.)
Make the command syntax in the manpage more consistent. Now none of the
allowed choice/flag names are in the command header, and all arguments
are shown with their proper name and quoted with <...>.
Some places in the manpage and the client.h doxygen are updated to
reflect that most commands support named arguments. In addition, try to
improve the documentation of the syntax and need for escaping etc. as
well.
(Or actually most uses of the word "argument" should be "parameter".)
Many asynchronous commands are potentially long running operations, such
as loading something from network or running a foreign process.
Obviously it shouldn't just be possible for them to freeze the player if
they don't terminate as expected. Also, there will be situations where
you want to explicitly stop some of those operations explicitly. So add
an infrastructure for this.
Commands have to support this explicitly. The next commit uses this to
actually add support to a command.
Named arguments should make it easier to have long time compatibility,
even if command arguments get added or removed. They're also much nicer
for commands with a large number of arguments, especially if many
arguments are optional.
As of this commit, this can not be used, because there is no command yet
which supports them. See the following commit.
Both asynchronous and synchronous calls used to be put into the core's
dispatch queue. Also, asynchronous calls were actually synchronous, just
without forcing a wait on the client's thread. This meant that both
kinds of calls were always strictly ordered.
A longer time ago, synchronous calls were changed to simply lock the
core. This could possibly lead to reordering. Recently, some commands
were changed to run on worker threads, which made the order even looser.
Also remove another now incorrect doxygen comment regarding async
commands.
This patch adds
- DRM connector object to atomic context.
- fd property to the drm atomic object as well as a method to read blob type properties.
This allows to ensure that the proper connector is picked up, especially when specifying it
from the commandline, and also allows to make sure we're using the right one when embedding
with interop into an application.
That new API was introduced and allows to have several native resources.
Thisuses that mechanisma for drm resources rather than the deprecated
opengl-cb structs.
This patch therefore add two structs that can be used with the drm atomic interop.
- mpv_opengl_drm_params : which will hold all the drm handles
- mpv_opengl_drm_osd_size : which will hold osd layer size
This commit adds a drm-osd-size=WxH parameter to commandline which
allows to define the OSD plane dimension. OSD can be upscaled to
screen resolution when having OSD at video resolution is too heavy.
This is especially useful for UHD modes on embedded devices where
the GPU cannot handle UHD modes at a decent framerate.
Strictly speaking redundant, but probably helpful.
In particular I want to push MPV_RENDER_PARAM_ADVANCED_CONTROL. Not
enabling this parameter is actually not very sane.
Attempts to enable the following things:
- let a render API user do "proper" audio-sync video timing itself
- make it possible to not re-render repeated frames if the API user has
better mechanisms available (e.g. waiting for a DisplayLink cycle
instead)
- allow the user to delay or skip redraws if it makes sense
Basically this information will be needed by API users who want to be
"clever" about optimizing timing and rendering.
DR (letting the decoder allocate texture memory) requires running the
allocation on the render thread. This is rather hard with the render
API, because the user controls this thread and when it's entered. It was
not possible until now.
This commit adds a bunch of infrastructure to make this possible. We add
a new optional mode (MPV_RENDER_PARAM_ADVANCED_CONTROL) which basically
lets the user's render thread and libmpv agree how this should be done.
Misuse would lead to deadlocks. To make this less likely, strictly
document thread safety/locking issues. In particular, document which
libmpv functions can be called without issues. (The rest has to be
assumed unsafe.)
The worst issue is destruction of the render context while video is
still active. To avoid certain unintended recursive locks (i.e.
deadlocks, unless we'd make the locks recursive), make the update
callback lock separate. Make "killing" the video chain asynchronous, so
we can do extra work while video is being destroyed.
Because losing wakeups is a big deal, setting the update callback now
triggers a wakeup. (It would have been better if the wakeup callback
were a parameter to mpv_render_context_create(), but too late.)
This commit does not add DR yet; the following commit does this.
Normally, MPV_RENDER_PARAM* arguments are copied, unless documented
otherwise. Of course we can't copy X11 Display or Wayland wl_display
types, but for arguments that are "summarized" in a struct (like
MPV_RENDER_PARAM_OPENGL_FBO), a copy is expected.
Also add some unused infrastructure to make this explicit, and to make
it easier to add parameter types that require a copy.
Untested.
As it turns out, there are multiple libmpv users who saw a need to
use the hook API. The API is kind of shitty and was never meant to be
actually public (it was mostly a hack for the ytdl script).
Introduce a proper API and deprecate the old one. The old one will
probably continue to work for a few releases, but will be removed
eventually.
There are some slight changes to the old API, but if a user followed
the manual properly, it won't break.
Mostly untested. Appears to work with ytdl_hook.
Hardware decoding things often need access to additional handles from
the windowing system, such as the X11 or Wayland display when using
vaapi. The opengl-cb had nothing dedicated for this, and used the weird
GL_MP_MPGetNativeDisplay GL extension (which was mpv specific and not
officially registered with OpenGL).
This was awkward, and a pain due to having to emulate GL context
behavior (like needing a TLS variable to store context for the pseudo GL
extension function). In addition (and not inherently due to this), we
could pass only one resource from mpv builtin context backends to
hwdecs. It was also all GL specific.
Replace this with a newer mechanism. It works for all RA backends, not
just GL. the API user can explicitly pass the objects at init time via
mpv_render_context_create(). Multiple resources are naturally possible.
The API uses MPV_RENDER_PARAM_* defines, but internally we use strings.
This is done for 2 reasons: 1. trying to leave libmpv and internal
mechanisms decoupled, 2. not having to add public API for some of the
internal resource types (especially D3D/GL interop stuff).
To remain sane, drop support for obscure half-working opengl-cb things,
like the DRM interop (was missing necessary things), the RPI window
thing (nobody used it), and obscure D3D interop things (not needed with
ANGLE, others were undocumented). In order not to break ABI and the C
API, we don't remove the associated structs from opengl_cb.h.
The parts which are still needed (in particular DRM interop) needs to be
ported to the render API.
It's a WTF that we have something as specific in the API. It could be
argued that we should provide helpers for other language and GUI toolkit
combinations. Obviously that's not going to scale, and it's somewhat
likely that it will bitrot. The rest is said in the API changelog.
Before this change, mpv_wait_event() could inconsistently return
multiple MPV_EVENT_SHUTDOWN events to a single mpv_handle, up to the
point of spamming the event queue under certain circumstances. Change
this and just send it exactly once to each mpv_handle.
Some client API users might have weird requirements about destroying
their state asynchronously (and not reacting immediately to the SHUTDOWN
event). This change will help a bit to make this less weird and
surprising.
This changes how mpv_terminate_destroy() and mpv_detach_destroy()
behave. The doxygen in client.h tries to point out the differences. The
goal is to make this more useful to the API user (making it behave like
refcounting).
This will be refined in follow up commits.
Initialization is unfortunately closely tied to termination, so that
changes as well. This also removes earlier hacks that make sure that
some parts of FFmpeg initialization are run in the playback thread
(instead of the user's thread). This does not matter with standard
FFmpeg, and I have no reason to care about this anymore.
The purpose of the new API is to make it useable with other APIs than
OpenGL, especially D3D11 and vulkan. In theory it's now possible to
support other vo_gpu backends, as well as backends that don't use the
vo_gpu code at all.
This also aims to get rid of the dumb mpv_get_sub_api() function. The
life cycle of the new mpv_render_context is a bit different from
mpv_opengl_cb_context, and you explicitly create/destroy the new
context, instead of calling init/uninit on an object returned by
mpv_get_sub_api().
In other to make the render API generic, it's annoyingly EGL style, and
requires you to pass in API-specific objects to generic functions. This
is to avoid explicit objects like the internal ra API has, because that
sounds more complicated and annoying for an API that's supposed to never
change.
The opengl_cb API will continue to exist for a bit longer, but
internally there are already a few tradeoffs, like reduced
thread-safety.
Mostly untested. Seems to work fine with mpc-qt.
This should be helpful for the new OSX Cocoa backend, which uses
opengl-cb internally. Since it comes with a behavior change that could
possibly interfere with libmpv/opengl_cb users, we mark it as explicit
API change.
ipc-unix.c does this out of convenience. Since signals are global
process state, this deserves a mention, since applications could in
theory rely on SIGPIPE being set to something else.
With the recent changes to the script it does not incur a startup delay
by default due to starting youtube-dl and waiting for it. This was the
main reason for making libmpv have a different default.
Starting sub processes from a library can still be a bit fishy, but I
think it's ok. Still mention it in the libmpv header. There were already
other cases where libmpv would start its own processes, such as the X11
backend calling xdg-screensaver. (The reason why this is fishy is
because UNIX process management sucks: SIGCHLD and the wait() syscall
make sub processes non-transparent and could potentially introduce
conflicts with code trying to use them.)
Make the VO<->decoder interface capable of supporting multiple hwdec
APIs at once. The main gain is that this simplifies autoprobing a lot.
Before this change, it could happen that the VO loaded the "wrong" hwdec
API, and the decoder was stuck with the choice (breaking hw decoding).
With the change applied, the VO simply loads all available APIs, so
autoprobing trickery is left entirely to the decoder.
In the past, we were quite careful about not accidentally loading the
wrong interop drivers. This was in part to make sure autoprobing works,
but also because libva had this obnoxious bug of dumping garbage to
stderr when using the API. libva was fixed, so this is not a problem
anymore.
The --opengl-hwdec-interop option is changed in various ways (again...),
and renamed to --gpu-hwdec-interop. It does not have much use anymore,
other than debugging. It's notable that the order in the hwdec interop
array ra_hwdec_drivers[] still matters if multiple drivers support the
same image formats, so the option can explicitly force one, if that
should ever be necessary, or more likely, for debugging. One example are
the ra_hwdec_d3d11egl and ra_hwdec_d3d11eglrgb drivers, which both
support d3d11 input.
vo_gpu now always loads the interop lazily by default, but when it does,
it loads them all. vo_opengl_cb now always loads them when the GL
context handle is initialized. I don't expect that this causes any
problems.
It's now possible to do things like changing between vdpau and nvdec
decoding at runtime.
This is also preparation for cleaning up vd_lavc.c hwdec autoprobing.
It's another reason why hwdec_devices_request_all() does not take a
hwdec type anymore.
This commit allows to use the AV_PIX_FMT_DRM_PRIME newly introduced
format in ffmpeg that allows decoders to provide an AVDRMFrameDescriptor
struct.
That struct holds dmabuf fds and information allowing zerocopy rendering
using KMS / DRM Atomic.
This has been tested on RockChip ROCK64 device.