Closed winneon closed 6 years ago
“Regular” screenshots and “window” screenshots go through very different code paths.
Regular screenshots take the frame, pass them through libswscale to convert to RGB, and then save this to disk. The data never touches the VO, or the GPU for that matter.
Window screenshots go through the VO's rendering path - as you said, they're basically hard screenshots of what's visible on-screen. Since the vo_gpu
rendering path is the only part of mpv that has HDR tone mapping implemented, this is the only way to get HDR->SDR conversion out of mpv, currently.
There are a couple of possible work-arounds and long-term solutions:
You can forcibly insert some of lavf's conversion filters (e.g. zimg + tonemap) which are designed to produce a better result on HDR content. (The quality won't be the same as mpv's built-in algorithm, but it also won't be as horribly washed out as your examples). You can even do this right now, perhaps even inserting the correct filters before taking a screenshot and removing them afterwards. (Hack)
Mpv could become smart enough to recognize HDR content when taking screenshots and apply the correct zimg/tonemap filters itself.
We could implement software tonemapping in mpv (perhaps using the same algorithm?), and apply this where needed to convert from HDR to SDR. This would require duplication of code, however, and it would surely also be very slow unless somebody sits down and writes SIMD for it or whatever.
We can perhaps add an optional dependency on libplacebo
and use this for the VO-agnostic screenshot path where available/supported. This library basically implements the same algorithms as mpv, including high quality tone mapping. As a bonus, we could even make an effort to apply e.g. the same --scale
when invoking libplacebo. This would have the benefit of being fairly orthogonal to the VO used (and even work when you have no VO at all).
We could redesign the VO to also allow taking window-agnostic screenshots (by basically re-rendering the image to an FBO and saving that) using the same rendering algorithms. This would, however, require potentially reinitializing a lot of state on every screenshot due to limitations of the current vo_gpu
design. It also wouldn't be trivial, and it wouldn't work on platforms without e.g. FBO support. It also wouldn't work if you were using another VO.
The fourth solution seems to be the one with the most benefits with the least disadvantages.
vo_gpu
related features added, they would also have to be added to the software algorithm, not to mention the duplication of code as you mentioned.libplacebo
, and as you mentioned, it would work even without a VO.Do you have any specific opinions as well?
The fourth would probably be the easiest for me to get going, it would also be a good test case for libplacebo
's APIs without having to write a full VO for it, so I'd have a personal interest in trying it out.
On the other hand, further downsides are the fact that libplacebo is still WIP/beta and therefore might not be the best fit for an on-by-default solution. It'd be more of an experimental branch for now, I think. libplacebo also only currently supports vulkan, so there would be little hope for getting this running on a system that doesn't, at least for the immediate foreseeable future. There is no CPU-emulation of the libplacebo algorithms planned. So with that in mind, especially on systems with older or weaker GPUs or where vulkan is not available, the zimg/tonemap approach might be more reasonable.
That said, we could also do both: I wouldn't be opposed to adding libplacebo as a strictly optional dependency that users who do meet all the prerequisites can use it for higher quality screenshots, but mpv will otherwise fall back to zimg/tonemap's CPU algorithms.
My main issue is that I don't really know my way around FFmpeg code at all, so I'd have trouble working on any sort of zimg/tonemap based approach.
tl;dr I could implement 3. 4. and with difficulty 5., but not 2.
You could always try out the fourth option for now and tag it under "experimental" features, and then when an alternative for lower-end users like the second option comes around, likely developed by someone else, then both features could move out of the "experimental" label. Whatever "experimental" ends up being, that is.
The easiest solution would be just adding it to the current renderer, which would be relatively trivial.
That would be the easiest solution, but would it be practical in the long run? It seems to fix the main issue here but it's incompatible with other GPU-related options.
I'd tend to agree that the current renderer should be used or be fixed so that it can be used, otherwise there are two code-paths that do the same thing and we'd have to fight to get the results consistent between them. If someone has spent 3 hours tweaking their mpv.conf vo options, those should be honoured in making the screenshot as applicable.
mpv version and platform
Running on Arch Linux with version 4.14.15-1 of the Linux kernel. The VO driver used is
gpu
, the default with the master branch as of this issue.Explanation
Currently, screenshots do not properly output and preserve GPU-accelerated feature(s) such as HDR. Instead, the screenshot that is outputted is an 8-bit version of the 10-bit HDR frame, resulting in a very washed-out image that is not representative of the image displayed in mpv in the slightest. This happens on both the
subtitles
andvideo
screenshot options. Thewindow
option is unaffected because it just literally takes a screenshot of the window, not the video file (at least, I'm assuming that's how it works). Thewindow
option also scales the image and isn't a proper screenshot of the current frame anyway, so it's not a viable workaround.I'm unsure if there are other features not present in the outputted image, as I've only tested HDR as of this time. Below are a few examples I tested with "Life of Pi" sample HDR footage, and a ripped UHD BD HDR copy of the animated film "Your Name". All comparison images have been downscaled to 1280x720 for smaller file sizes, and all tone-mapping & related HDR options have been kept to default. The
window
option comparison was not downscaled manually, but by mpv itself by keeping the window at 1280x720."Life of Pi" sample HDR footage
subtitles
&video
screenshot optionswindow
screenshot option"Your Name" UHD BD copy
subtitles
&video
screenshot optionswindow
screenshot optionReproduction steps
subtitle
option (default is thes
key).Expected behavior
The outputted screenshot looks like what you're viewing in mpv.
Actual behavior
The outputted screenshot is incredibly washed-out and entirely unrepresentative of what you are watching. It's even more unrepresentative of non-HDR copies of the same film.
Log file
http://0x0.st/scuL.txt
Sample files
"Life of Pi" sample HDR footage