Commit Graph

4372 Commits

Author SHA1 Message Date
wm4 b9d351f02a Implement backwards playback
See manpage additions. This is a huge hack. You can bet there are shit
tons of bugs. It's literally forcing square pegs into round holes.
Hopefully, the manpage wall of text makes it clear enough that the whole
shit can easily crash and burn. (Although it shouldn't literally crash.
That would be a bug. It possibly _could_ start a fire by entering some
sort of endless loop, not a literal one, just something where it tries
to do work without making progress.)

(Some obvious bugs I simply ignored for this initial version, but
there's a number of potential bugs I can't even imagine. Normal playback
should remain completely unaffected, though.)

How this works is also described in the manpage. Basically, we demux in
reverse, then we decode in reverse, then we render in reverse.

The decoding part is the simplest: just reorder the decoder output. This
weirdly integrates with the timeline/ordered chapter code, which also
has special requirements on feeding the packets to the decoder in a
non-straightforward way (it doesn't conflict, although a bugmessmass
breaks correct slicing of segments, so EDL/ordered chapter playback is
broken in backward direction).

Backward demuxing is pretty involved. In theory, it could be much
easier: simply iterating the usual demuxer output backward. But this
just doesn't fit into our code, so there's a cthulhu nightmare of shit.
To be specific, each stream (audio, video) is reversed separately. At
least this means we can do backward playback within cached content (for
example, you could play backwards in a live stream; on that note, it
disables prefetching, which would lead to losing new live video, but
this could be avoided).

The fuckmess also meant that I didn't bother trying to support
subtitles. Subtitles are a problem because they're "sparse" streams.
They need to be "passively" demuxed: you don't try to read a subtitle
packet, you demux audio and video, and then look whether there was a
subtitle packet. This means to get subtitles for a time range, you need
to know that you demuxed video and audio over this range, which becomes
pretty messy when you demux audio and video backwards separately.

Backward display is the most weird (and potentially buggy) part. To
avoid that we need to touch a LOT of timing code, we negate all
timestamps. The basic idea is that due to the navigation, all
comparisons and subtractions of timestamps keep working, and you don't
need to touch every single of them to "reverse" them.

E.g.:

    bool before = pts_a < pts_b;

would need to be:

    bool before = forward
        ? pts_a < pts_b
        : pts_a > pts_b;

or:

    bool before = pts_a * dir < pts_b * dir;

or if you, as it's implemented now, just do this after decoding:

    pts_a *= dir;
    pts_b *= dir;

and then in the normal timing/renderer code:

    bool before = pts_a < pts_b;

Consequently, we don't need many changes in the latter code. But some
assumptions inhererently true for forward playback may have been broken
anyway. What is mainly needed is fixing places where values are passed
between positive and negative "domains". For example, seeking and
timestamp user display always uses positive timestamps. The main mess is
that it's not obvious which domain a given variable should or does use.

Well, in my tests with a single file, it suddenly started to work when I
did this. I'm honestly surprised that it did, and that I didn't have to
change a single line in the timing code past decoder (just something
minor to make external/cached text subtitles display). I committed it
immediately while avoiding thinking about it. But there really likely
are subtle problems of all sorts.

As far as I'm aware, gstreamer also supports backward playback. When I
looked at this years ago, I couldn't find a way to actually try this,
and I didn't revisit it now. Back then I also read talk slides from the
person who implemented it, and I'm not sure if and which ideas I might
have taken from it. It's possible that the timestamp reversal is
inspired by it, but I didn't check. (I think it claimed that it could
avoid large changes by changing a sign?)

VapourSynth has some sort of reverse function, which provides a backward
view on a video. The function itself is trivial to implement, as
VapourSynth aims to provide random access to video by frame numbers (so
you just request decreasing frame numbers). From what I remember, it
wasn't exactly fluid, but it worked. It's implemented by creating an
index, and seeking to the target on demand, and a bunch of caching. mpv
could use it, but it would either require using VapourSynth as demuxer
and decoder for everything, or replacing the current file every time
something is supposed to be played backwards.

FFmpeg's libavfilter has reversal filters for audio and video. These
require buffering the entire media data of the file, and don't really
fit into mpv's architecture. It could be used by playing a libavfilter
graph that also demuxes, but that's like VapourSynth but worse.
2019-09-19 20:37:04 +02:00
dudemanguy 80c4aaa2a4 wayland: fix wl_proxy leak
This one is probably not terribly obvious from just the valgrind log,
but a wayland dev explained it to me just a second ago. Whenever mpv
sends events to the screen with wl_display_dispatch, wayland internally
allocates memory to a struct wl_proxy object if a new id is found. Quite
a few more things happen to that proxy object, but eventually mpv stores
the data on the client-side in a wrapper type of struct (struct
wl_data_offer). mpv's data_device_listener keeps track of those proxies
and frees the memory when appropriate. Of course, mpv is constantly
sending events to the screen and does so until the user quits the
player. What happens here is that one final wl_display_dispatch is called
right before the user quits the player and before mpv's
data_device_listener can handle that object. So the result is that you
always have one extra dangling proxy that doesn't get properly freed.
The solution is to just simply call wl_data_offer_destroy before closing
the wl_display to free that final dangling wl_proxy.
2019-09-19 00:00:19 +03:00
Anton Kindestam e08f235578 drm: fix libmpv ABI breakage introduced in 351c083487
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
2019-09-18 23:59:32 +03:00
Philip Langdale fa0a905ea0 vo_gpu: hwdec_vaapi: Refactor Vulkan and OpenGL interops for VAAPI
Like hwdec_cuda, you get a big #ifdef mess if you try and keep the
OpenGL and Vulkan interops in the same file. So, I've refactored
them into separate files in a similar way.
2019-09-15 17:51:47 -07:00
Philip Langdale 237f5fa1b7 vo_gpu: hwdec_cuda: Improve interop selection mechanism
This change updates the interop selection to match what I did for
VAAPI, by iterating through an array of init functions until one
of them works.
2019-09-15 17:51:47 -07:00
wm4 0abe34ed21 vo_gpu: x11: remove special vdpau probing, use EGL by default
Originally, vo_gpu/vo_opengl considered the case of Nvidia proprietary
drivers, which required vdpau/GLX, and Intel open source drivers, which
require vaapi/EGL. Since window creation and GPU context creation are
inseparable in mpv's internal API, it had to pick the correct API very
early, or hardware decoding wouldn't work. "x11probe" was introduced for
this reason. It created a GLX context (without showing the window yet),
and checked whether vdpau was available. If yes, it used GLX, if not, it
continued probing x11/EGL. (Obviously it couldn't always fail on GLX
without vdpau, which is why it was a separate "probe" backend.)

Years passed, and now the situation is different. Vdpau is dead. Nvidia
drivers and libavcodec now provide CUDA interop, which requires EGL, and
fixes some of the vdpau problems. AMD drivers now provide vaapi, which
generally works better than vdpau. Intel didn't change.

In particular, vaapi provides working HEVC Main10 support. In theory, it
should work on vdpau too, with quality reduction (no 10 bit surfaces),
but I couldn't get it to work.

So always prefer EGL. And suddenly hardware decoding works. This is
actually rather important, because HEVC is unfortunately on the rise,
despite shitty encoders and unoptimized decoders. The latter may mean
that hardware decoding works better than libavcodec.

This should have been done a long, long time ago.
2019-09-15 20:00:52 +03:00
wm4 6385a5fd1b vf_vavpp: disable this filter
Might be unreasonable, but I'm angry at the shit driver freezing my
machine.
2019-09-15 17:59:25 +02:00
Niklas Haas a416b3f084 vo_gpu: correctly normalize src.sig_peak
In some cases, src.sig_peak remains undefined as 0, which was definitely
the case when using the OSD, since it never got passed through the usual
color space normalization process. Most robust work-around is to simply
force the normalization at the site where it's needed. This ensures this
value is always valid and defined, to make the peak-dependent logic in
these two functions always work.

Fixes 4b25ec3a9d
Fixes #6917
Fixes #6918
2019-09-15 01:33:27 +02:00
sfan5 ee0f4444f9 image_writer: add webp-compression option 2019-09-14 23:02:39 +02:00
sfan5 0f79444c6d image_writer: add WebP support (lossy or lossless) 2019-09-14 23:02:39 +02:00
sfan5 8925f10962 image_writer: move convert_image() to player/screenshot.c 2019-09-14 23:02:39 +02:00
sfan5 5c313f1f59 vo: add warning message to vo_vaapi and vo_vdpau
These are a common source of bug reports, due to misconceptions that
they are required to make use of hardware decoding.
2019-09-14 13:50:10 +02:00
Hui Jin fda45f4537 vo_d3d11/context: fix crash due to ctx->ra is null pointer access
'ctx->ra' is null pointer when d3d11 init failed before call 'ra_d3d11_create' in 'd3d11_init'.
2019-09-14 21:35:49 +10:00
Hui Jin 191737b9c9 vo_d3d11/hwdec_dxva2dxgi: fix memory leak that 'ctx11' be not release
'ctx11' be not release when d3d11 hwdec be uninit with 'mapper_uninit' method.
2019-09-14 21:35:49 +10:00
wm4 10a1b98082 vo_gpu: x11egl: support Mesa OML sync extension
Mesa supports the EGL_CHROMIUM_sync_control extension, and it's
available out of the box with AMD drivers. In practice, this is exactly
the same as GLX_OML_sync_control, but for EGL. The extension
specification is separate from the GLX one though, and buried somewhere
in the Chromium code.

This appears to work, although I don't know if it really works.

In theory, this could be useful for other EGL targets. Support code for
it could have been added to egl_helpers.c to avoid some minor duplicated
glue code if another EGL target were to provide this extension. I didn't
bother with that. ANGLE on Windows can't support it, because the
extension spec. explicitly requires POSIX timers. ANGLE on Linux/OSX is
actively harmful for mpv and hopefully won't ever use it. Wayland uses
EGL, but has its own fancy presentation feedback stuff (and besides, I
don't think basic video player functionality works on Wayland at all).
context_drm_egl maybe? But I think DRM has its own stuff.
2019-09-08 23:23:43 +10:00
wm4 8d7960f6ef vo_gpu: glx: move OML sync code to an independent file
So the next commit can make EGL use it. EGL has a quite similar
function, that practically works the same. Although it's relatively
trivial, it's still tricky, and probably shouldn't end up as duplicated
code.

There are no functional changes, except initialization, and how failure
of the glXGetSyncValues call is handled. Also, some comments mention the
EGL extension.

Note that there's no intention for this code to handle anything else
than the very specific OML sync extension (and its EGL equivalent). This
is just too weirdly specific to the weird idiosyncrasies of the
extension, and it makes no sense to extend it to handle anything else.
(Such as Wayland or DXGI presentation feedback.)
2019-09-08 23:23:43 +10:00
Niklas Haas 4b25ec3a9d vo/gpu: fix check on src/dst peak mismatch
In the past, src peak was always equal to or higher than dst peak. But
since `--target-peak` got introduced, this could no longer be the case.
This leads to an incorrect result (scaling for peak mismatch in gamma
light) unless some other option (CMS, --linear-scaling, etc.) forces the
linearization.

Fixes #6533
2019-09-05 19:13:44 +03:00
der richter c8a911f35f cocoa-cb: remove an unused variable 2019-09-02 00:39:36 +03:00
Philip Langdale b539eb222b vo/gpu: vulkan: Pass the device name option through to libplacebo
We collect a 'vulkan-device' option today but then don't actually
pass it on, so it's useless. Once that's fixed, it can be used
to select a specific vulkan device by name.

Tested with the new nvidia offload feature to select between the
nvidia and intel GPUs.
2019-08-24 18:38:27 +02:00
James Ross-Gowan 80552ab28e vo_gpu: d3d11: fix storage lifetime of compound literals
Somehow I got the idea that compound literals had function-scoped
lifetime. Instead, like all other objects with automatic storage
duration, compound literals are block-scoped, so they become invalid
after exiting the block they were declared in. It seems like a recent
change to GCC actually reuses the memory that the compound literals
used to occupy, which was causing a few bugs.

The pattern of conditionally assigning a pointer to a compound literal
was used in a few places in ra_d3d11 where the Direct3D API expects
either a pointer to an initialised struct or NULL. Change these to
ensure the lifetime of the struct includes the API call.

Should fix #6775.
2019-08-20 18:12:21 +10:00
wnoun ae8cb39ab2 vo_gpu: fix taking screenshots of rotated videos 2019-08-14 21:54:14 +02:00
Philip Langdale 639ee55df7 vo_gpu: hwdec_vaapi: Synchronise after exporting VA surface
This is documented as required (although we did not do it in
the old GL codepath, with no visible problems) and I have seen
transient artifacts after seeking which _appear_ to have gone
away after introducing this.
2019-08-07 10:51:43 +02:00
der richter a8c2e29868 cocoa-cb: migrate to swift 5 with swift 4 fallback
this migrates our current swift code to version 5 and 4. building is
support from 10.12.6 and xcode 9.1 onwards.

dynamic linking is the new default, since Apple removed static libs
from their new toolchains and it's the recommended way.

additionally the found macOS SDK version is printed since it's an
important information for finding possible errors now.

Fixes #6470
2019-07-21 18:13:07 +03:00
der richter 0602f082cb cocoa-cb: fix optional cases on macOS 10.12 2019-07-21 18:13:07 +03:00
der richter c540ac8485 cocoa-cb: conditional compilation for Dark Mode and Material features
Fixes #6621
2019-07-21 18:13:07 +03:00
Philip Langdale b5b0350371 vo_gpu: hwdec_vaapi: Count planes rather than layers in Vulkan interop
We saw a segfault when trying to use the intel-media-driver (iHD)
rather than the normal intel va driver. This happened because the
iHD driver reports P010 (and maybe other formats) with multiple
layers to represent the interleaved UV plane. The normal va driver
reports one UV layer to match the plane.

This threw off my logic which assumed that the number of layers
could not exceed the number of planes.

There's a way one could fix this in a fully generalised form, but
I'm just going to do what the EGL path does and assume that:
 * Layer 'n' is on Plane 'n' for n < total number of planes
 * These layers always start at offset 0 on the plane

You can imagine ways that these assumptions are violated, but at
least the failure will look the same for both EGL and Vulkan
paths.
2019-07-08 01:57:02 +02:00
Philip Langdale b33ced193e vo_gpu: hwdec_vaapi: Suppress format errors when probing
Today, we normally see a format error when probing because yuyv422
cannot be used, but it's in the normal set of probed formats.

This error is distracting and confusing, so only log probing errors
at the VERBOSE level.

Fixes #6411
2019-07-08 01:57:02 +02:00
Philip Langdale b70ed35ba4 vo_gpu: hwdec_vaapi: Add Vulkan interop
This change introduces a vulkan interop path for the vaapi hwdec.
The basic principles are mostly the same as for EGL, with the
exported dma_buf being imported by Vukan. The biggest difference
is that we cannot reuse the texture as we do with OpenGL - there's
no way to rebind a VkImage to a different piece of memory, as far
as I can see. So, a new texture is created on each map call.

I did not bother implementing a code path for the old libva API as
I think it's safe to assume any system with a working vulkan driver
will have access to a newer libva.

Note that we are using separate layers for the vaapi surface, just
as is done for EGL. This is because libplacebo doesn't support
multiplane images.

This change does not include format negotiation because no driver
implements the vk_ext_image_drm_format_modifier extension that
would be required to do that. In practice, the two formats we care
about (nv12, p010) work correctly, so we are not blocked. A separate
change had to be made in libplacebo to filter out non-fatal validation
errors related to surface sizes due to the lack of format negotiation.
2019-07-08 01:57:02 +02:00
Philip Langdale 6842755feb vo_gpu: hwdec_vaegl: Rename and move to hwdec_vaapi
In preparation for adding Vulkan interop support, let's rename
to remove the egl reference and move to an api neutral location.
2019-07-08 01:57:02 +02:00
Chainik 7f0f1a1b72 vf_vapoursynth: allow multithreaded writing of source frames 2019-07-08 01:53:22 +02:00
Chainik 5907bc023c vf_vapoursynth: allow multithreaded reading of returned frames 2019-07-08 01:53:22 +02:00
Philip Langdale 1638fa7b46 vo/gpu: hwdec_vdpau: Support direct mode for 4:4:4 content
New releases of VDPAU support decoding 4:4:4 content, and that comes
back as NV24 when using 'direct mode' in OpenGL Interop. That means we
need to be a little bit smarter about how we set up the OpenGL
textures.
2019-07-08 01:11:27 +02:00
Michael Forney 13e14d95e1 opengl/context_wayland: Fix crash on configure before initial reconfig
If the compositor sends a configure event before the surface is initially
mapped, resize gets called before the egl_window gets created, resulting
in a crash in wl_egl_window_resize.

This was fixed back in 618361c697, but was reintroduced when the wayland
code was rewritten in 68f9ee7e0b.
2019-07-08 01:00:01 +02:00
Philip Langdale e2976e662d video/out/gpu: Add a `storable` flag to ra_format
While `ra` supports the concept of a texture as a storage
destination, it does not support the concept of a texture format
being usable for a storage texture. This can lead to us attempting
to create a texture from an incompatible format, with undefined
results.

So, let's introduce an explicit format flag for storage and use
it. In `ra_pl` we can simply reflect the `storable` flag. For
GL and D3D, we'll need to write some new code to do the compatibility
checks. I'm not going to do it here because it's not a regression;
we were already implicitly assuming all formats were storable.

Fixes #6657
2019-07-08 00:59:28 +02:00
Bin Jin c9e7473d67 vo_gpu: process three component together in error diffusion
This started as a desperate attempt to lower the memory requirement
of error diffusion, but later it turns out that this change also
improved the rendering performance a lot (by 40% as I tested).

Errors was stored in three uint before this change, each with 24bit
precision. This change encoded them into a single uint, each with 8bit
precision. This reduced the shared memory usage, as well as number of
atomic operations, all by three times.

Before this change, with the minimum required 32kb shared memory, only
the `simple` kernel can be used to render 1080p video, which is mostly
useless compare to `--dither=fruit`. After this change, 32kb can
handle `burkes` kernel for 1080p, or `sierra-lite` for 4K resolution.
2019-06-16 11:19:44 +02:00
Bin Jin f6fd127fe8 vo_gpu: fix use of existing textures in error diffusion
error diffusion requires two texture rendering pass. The existing code
reuses `screen_tex` and creates another for such purpose. This works
generally well for opengl, but could potentially be problematic for
vulkan, due to its async natural.
2019-06-16 11:19:44 +02:00
Bin Jin ca2f193671 vo_gpu: implement error diffusion for dithering
This is a straightforward parallel implementation of error diffusion
algorithms in compute shader. Basically we use single work group with
maximal possible size to process the whole image. After a shift
mapping we are able to process all pixels column by column.

A large ring buffer are allocated in shared memory to speed things up.
However the size of required shared memory depends linearly on the
height of video window (or screen height in fullscreen mode). In case
there is no enough shared memory, it will fallback to `--dither=fruit`.

The maximal allowed work group size is hardcoded as 1024. Ideally we
could query `GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS`. But for whatever
reason, it seems most high end card from nvidia and amd support only
the minimal required value, so I guess we can stick to it for now.
2019-06-16 11:19:44 +02:00
James Ross-Gowan cc38035841 vo_gpu: d3d11: use the SPIRV-Cross C API directly
When the D3D11 backend was first written, SPIRV-Cross only had a C++ API
and no guarantee of API or ABI stability, so instead of using
SPIRV-Cross directly, mpv used an unofficial C wrapper called crossc.

Now that KhronosGroup/SPIRV-Cross#611 is resolved, SPIRV-Cross has an
official C API that can be used instead, so remove crossc and use
SPIRV-Cross directly.
2019-06-12 23:03:55 +03:00
Bin Jin fbe267150d vo_gpu: fix --scaler-resizes-only for fractional ratio scaling
The calculation of scale factor involves 32-bit float, and a strict
equality test will effectively ignore `--scaler-resizes-only` option
for some non-integer scale factor.

Fix this by using non-strict equality check.
2019-06-06 20:01:56 +02:00
Bin Jin f2119d9d88 vo_gpu: expose texture_off to user shader
It will provide low level access to coordinate mapping other than
texmap().
2019-06-06 20:01:56 +02:00
Bin Jin ae1c489b31 vo_gpu: allow user shader to fix texture offset
This commit essentially makes user shader able to fix offset (produced
by other prescaler, for example) like builtin `--scale`.
2019-06-06 20:01:56 +02:00
Niklas Haas 4d001bb30d wayland: fix segfault on uninit
Probably the same issue as #6732
2019-05-26 11:09:16 +02:00
dudemanguy 6e4971f697 wayland: fix various memory leaks 2019-05-21 22:41:22 +02:00
der richter 64cdc3694e cocoa-cb: fix quit in fs with none native fs
since the none native fs is a special legacy case it needs a special
quit routine. it indefinitely waited for an exit fs screen event to
shutdown properly, though that event only fires for the native fs.
now we check if we really are using a native fullscreen and if not
shutdown immediately.

Fixes #6704
2019-05-11 12:54:44 +02:00
James Ross-Gowan c754c31d6f w32_common: avoid unnecessary sprintfs
These were unnecessary for a couple of reasons, but it seems like the
old code went through a lot of effort to avoid duplicating the code to
print a RECT, even though the windowrc gets printed anyway at the end of
the function.

Avoid printing the same windowrc twice by only printing it when it gets
changed (in the w32->current_fs branch.)
2019-05-10 20:47:05 +10:00
Anton Kindestam dcb7838bb7 drm_common: Support --drm-mode=<preferred|highest|N|WxH[@R]>
This allows to select the drm mode using a string specification. You
can either select the the preferred mode, the mode with the highest
resolution, by specifying WxH[@R] or by its index in the list of modes
as before.
2019-05-04 14:17:11 +02:00
Anton Kindestam d155b7541f drm_common: Don't export functions only being used internally
As far as I know none of these functions were being used outside of
drm_common, nor should there really be a need to use them.
2019-05-04 14:17:11 +02:00
Anton Kindestam 8261924db9 drm_common: Add proper help option to drm-mode
This was implemented by using OPT_STRING_VALIDATE for drm-mode,
instead of OPT_INT. Using a string here also prepares for future
additions to drm-mode that aim to allow specifying a mode by its
resolution.
2019-05-04 14:17:11 +02:00
Anton Kindestam a776628d88 drm_common: Add option to toggle use of atomic modesetting
It is useful when debugging to be able to force atomic off, or as a
workaround if atomic breaks for some user. Legacy modesetting is less
likely to break by virtue of being a less complex API.
2019-05-04 14:17:11 +02:00
Philip Langdale 23a324215b vo/gpu: hwdec_cuda: Refactor gpu api specific code into separate files
The amount of code now present that's specific to Vulkan or OpenGL
has reached the point where we really want to split it out to
avoid a mess of #ifdefs.

At the same time, I'm moving the code to an api neutral location.
2019-05-03 18:02:18 +02:00