Tonemapping HDR to SDR for the PS4
Following on from the
previous post, the PS4's Media Player can
not play
HDR video
files. In order to play HDR files, they must be
tone-mapped to SDR. Obviously, this will greatly reduce
the vibrancy and brightness of the original image, but it is better than nothing and sometimes barely noticeable.
Acceptable output of tone-mapping can be subjective, but I have used this helpful
blog-post to find
something I am happy with. That blog post explains well what is being done to the image so will not be touched on here.
FFMPEG
In the previous post, the general command for encoding a PS4 compatible file was:
ffmpeg -i "$input_file" \
-vf "zscale=w=1920:h=-2:f=lanczos" \
-pix_fmt yuv420p \
-c:v libx264 -profile:v High -level:v 4.2 -crf $crf_value -bf 2 \
-c:a ac3 -b:a $bitrate \
-movflags faststart output.mp4
With a slight modification of the above, HDR files that are otherwise unplayable on the PS4's Media Player can be made
playable:
ffmpeg -i "$input_file" \
-vf "zscale=w=1920:h=-2:f=lanczos:c=left,
zscale=t=linear:npl=100,format=gbrpf32le,
zscale=p=bt709,tonemap=tonemap=hable:desat=0,
zscale=t=bt709:m=bt709:r=tv,format=yuv420p" \
-pix_fmt yuv420p \
-c:v libx264 -profile:v High -level:v 4.2 -crf $crf_value -bf 2 \
-c:a ac3 -b:a $bitrate \
-movflags faststart output.mp4
Displaying the difference this can make in a screenshot on a HDR incompatible monitor is tricky,
but the image below
from a 90s classic has HDR on the left, SDR on the right.
It illustrates that extreme highlight detail will be lost and smooth dark sections tend to be posterised.
This can be somewhat alleviated with higher bit-depths, but the PS4 Media Player only supports 8bit :(
Caveats
-
So far, I have only tonemapped HDR10 and Dolby Vision (HDR10 compatible) BluRays. I do not know if the following
will work for HLG, HDR10+ and Dolby Vision with dynamic metadata.
-
This tonemapping is not possible in FreeBSD, easily. The zscale filter (z.lib) is not available.
For reasons unknown, the ffmpeg package was not built with the library. FFmpeg will need to be built from the ports tree (note the ZIMG flag).
Don't forget to lock the package afterwards! Lord knows I have.