This commit adds support for automatic selection of color profiles based on
the display where mpv is initialized, and automatically changes the color
profile when display is changed or the profile itself is changed from
System Preferences.
@UliZappe was responsible with the testing and implementation of a lot of this
commit, including the original implementation of `cocoa_get_icc_profile_path`
(See #594).
Fixes#594
Reduce most dependencies on struct mp_csp_details, which was a bad first
attempt at dealing with colorspace stuff. Instead, consistently use
mp_image_params.
Code which retrieves colorspace matrices from csputils.c still uses this
type, though.
This is pretty obscure, so it didn't matter much. It still breaks
switching output levels at runtime, because the video output is not
reinitialized with the new params.
There were some bad interactions with the OSC.
For one, dragging the OSC bar, and then moving the mouse outside of the
OSC (while mouse button still held) would suddenly initiate window
dragging. This was because win_drag_button1_down was not reset when
sending a normal mouse event, which means the window dragging code can
become active even after we've basically decided that the preceding
click didn't initiate window dragging.
Second, dragging the window and clicking on the OSC bar after that did
nothing. This was because no mouse button up event was sent to the core,
even though a mouse down event was sent. So make sure the key state is
erased with MP_INPUT_RELEASE_ALL.
We don't check whether the WM supports _NET_WM_MOVERESIZE_MOVE, but
if it doesn't, nothing bad happens. There might be a race condition
when pressing a button, and then moving the mouse and releasing the
button at the same time; then the WM might get the message to initiate
moving the window after the mouse button has been released, in which
case the result will probably be annoying. This could possibly be fixed
by sending _NET_WM_MOVERESIZE_CANCEL on button release, but on the
other hand, we probably won't receive a button release event in this
situation, so ignore this problem.
The dragging is initiated only when moving the mouse pointer after a
click in order to reduce annoying behavior when the user is e.g.
doubleclicking.
Closes#608.
VAAPI has some ambiguous image formats, like VA_FOURCC_I420,
VA_FOURCC_IYUV, VA_FOURCC_YV12 (the latter exactly the same as the first
two, just with swapped planes). There is potentially a problem when one
specific VAAPI format was picked, and converting it to a mpv format and
back to a VAAPI FourCC would result in a numerically different format
(even if it's actually the same). Then it could e.g. happen that
functions like va_surface_upload() reallocate the underlying VAImage,
which would be inefficient. Change the code so that this can't happen.
(Probably not a problem in practice with the current VAAPI usage.)
It's not really needed to be public. Other code can just use mp_image.
The only disadvantage is that the other code needs to call an accessor
to get the VASurfaceID.
Although I at first thought it would be better to have a separate
implementation for hwaccels because the difference to software images
are too large, it turns out you can actually save some code with it.
Note that the old implementation had a small memory management bug. This
got painted over in commit 269c1e1, but is hereby solved properly.
Also note that I couldn't test vf_vavpp.c (due to lack of hardware), and
I hope I didn't accidentally break it.
The plan is to get rid of the custom VAAPI and possibly VDPAU surface
allocators.
Add custom surface allocation, because hwaccel surfaces are allocated
completely differently from software surfaces.
Add optional LRU allocation, which is (probably) helpful for hwaccel,
but (probably) less optimal for software surfaces.
mp_image_pool_get_no_alloc() is specifically for VAAPI, which can't
allocate new decoder surfaces after decoder init.
They were used by ancient libavcodec versions. This also removes the
need to distinguish vdpau image formats at all (since there is only
one), and some code can be simplified.
Image formats used to be FourCCs, so unsigned int was better. But now
it's annoying and the only difference is that unsigned int is more to
type than int.
Instead of doing it on every seek (libavcodec calls get_format on every
seek), reinitialize the decoder only if the video resolution changes.
Note that this may be relatively naive, since we e.g. (or: in
particular) don't check for profile changes. But it's not worse than the
state before the get_format change, and at least it paints over the
current vaapi breakage (issue #646).
This follows the (only slowly progressing) plan to replace all internal
video filters with libavfilter.
All what's left in vf_gradfun.c is the weird wrapper around vf_lavfi.c.
This "sometimes" crashed when seeking. The fault apparently lies in
libavcodec: the decoder returns an unreferenced frame! This is
completely insane, but somehow I'm apparently still expected to
work this around. As a reaction, I will drop Libav 9 support in the
next commit. (While this commit will go into release/0.3.)
The window doesn't recieve a WM_LBUTTONUP message after it's dragged,
probably because it's swallowed by the modal loop. To stop the button
from sticking, release it manually when the drag is complete.
Mouse buttons can get stuck down if the button is pressed inside the
video window and released outside. Avoid this by capturing mouse input
when a button is pressed.
Apparently the "right" place to initialize the hardware decoder is in
the libavcodec get_format callback.
This doesn't change vda.c and vdpau_old.c, because I don't have OSX, and
vdpau_old.c is probably going to be removed soon (if Libav ever manages
to release Libav 10). So for now the init_decoder callback added with
this commit is optional.
This also means vdpau.c and vaapi.c don't have to manage and check the
image parameters anymore.
This change is probably needed for when libavcodec VDA supports gets a
new iteration of its API.
This updates the logic for the new, somewhat unified behavior of SRGB
and 3DLUT since 34bf9be (not that it was particularly correct even that
change) and checks for the presence of corresponding extensions only in
the cases in which they're needed.
This commit:
- Changes some of the #define and variable names for clarification and
adds comments where appropriate.
- Unifies :srgb and :icc-profile, making them fit into the same step of
the decoding process and removing the weird interactions between both
of them.
- Makes :icc-profile take precedence over :srgb (to significantly reduce
the number of confusing and useless special cases)
- Moves BT709 decompanding (approximate or actual) to the shader in all
cases, making it happen before upscaling (instead of the old 0.45
gamma function). This is the simpler and more proper way to do it.
- Enables the approx gamma function to work with :srgb as well due to
this (since they now share the gamma expansion code).
- Renames :icc-approx-gamma to :approx-gamma since it is no longer tied
to the ICC options or LittleCMS.
- Uses gamma 2.4 as input space for the actual 3DLUT, this is now a
pretty arbitrary factor but I picked 2.4 mainly because a higher pure
power value here seems to produce visually better results with wide
gamut profiles, rather then the previous 1.95 or BT.709.
- Adds the input gamma space to the 3dlut cache header in case we change
it more in the future, or even make it user customizable (though I
don't see why the latter would really be necessary).
- Fixes the OSD's gamma when using :srgb, which was previously still
using the old (0.45) approximation in all cases.
- Updates documentation on :srgb, it was still mentioning the old
behavior from circa a year ago.
This commit should serve to both open up and make the CMS/shader code much
more accessible and less confusing/error-prone and simultaneously also
improve the performance of 3DLUTs with wide gamut color spaces.
I would liked to have made it more modular but almost all of these
changes are interdependent, save for the documentation updates.
Note: Right now, the "3DLUT takes precedence over SRGB" logic is just
coded into gl_lcms.c's compile_shaders function. Ideally, this should be
done earlier, when parsing the options (by overriding the actual
opts.srgb flag) and output a warning to the user.
Note: I'm not sure how well this works together with real-world
subtitles that may need to be color corrected as well. I'm not sure
whether :approx-gamma needs to apply to subtitles as well. I'll need to
test this on proper files later.
Note: As of now, linear light scaling is still intrinsically tied to
either :srgb or :icc-profile. It would be thinkable to have this as an
extra option, :linear-scaling or similar, that could be used with or
without the two color management options.
Since the AO will run in a thread, and there's lots of shared state with
encoding, we have to add locking.
One case this doesn't handle correctly are the encode_lavc_available()
calls in ao_lavc.c and vo_lavc.c. They don't do much (and usually only
to protect against doing --ao=lavc with normal playback), and changing
it would be a bit messy. So just leave them.
The previous version of the gamma suboption was pretty useless. It could
be used to disable delayed gamma enabling, which is a mechanism to avoid
having to adjust gamma in the shader by default.
Repurpose the suboption and allow setting an exact gamma value with it.
You can already override gamma with the --gamma option as well as the
gamma input property, but these use a weird curve to create the
impression of a linear perceived brightness change when changing the
value. This suboption now allows setting an exact gamma value.
This used to be absolute colorimetric, but relative colorimetric is a
saner default due to the arguments presented in issue #595.
A short summary: In general it doesn't affect much because our eyes
adapt to the white point either way, but if running in windowed mode it
would make the whites seem inconsistent/tinted. For fullscreen
projection it's also undesirable since it reduces the dynamic range
without much benefit (again, since our eyes adapt either way) and it
also breaks calibration against ambient lighting.
This shouldn't change much, since most profile types that aren't 3DLUTs
aren't capable of either of those transforms, and most displays are
calibrated against D65 (same as BT.709 source) either way.