mp_image: handle XYZ, and forward to libplacebo properly#18124
Conversation
| // decode, and tag post-decode primaries as DCI-P3 to match what its XYZ | ||
| // handler bakes in. Don't override the TRC: linear-light XYZ keeps | ||
| // TRC=LINEAR, DCDM-encoded XYZ keeps TRC=ST428. | ||
| if (src->color_primaries == AVCOL_PRI_SMPTE428) { |
There was a problem hiding this comment.
XYZ is almost never tagged, as such.
There was a problem hiding this comment.
XYZ is typically «fake» tagged as Identity (Identity matrix means either BGR or YZX) and primaries of white point 1/3, 1/3, unity, and gamma 2.6. Primaries is what signals that Identity here means YZX and not BGR. DCI-P3 would be what encoding to linear RGB from XYZ NPM matrix is, I believe. FFmpeg does not preserve WCG here encoding using BT.709 NPM. New patch apparently adds support for new NPMs. So you decode YZX using 2.6 gamma and then convert to linear RGB (e.g. of P3 with DCI white NPM) and then encode with PQ or whatever. Tag it all in the end with PQ/DCI-P3.
There was a problem hiding this comment.
I know, there is big gaps in DCDM support in ffmpeg. I made it work somehow good in mpv/libplacebo to get satisfactory rendering.
| if (params->color.transfer == PL_COLOR_TRC_UNKNOWN) | ||
| params->color.transfer = PL_COLOR_TRC_SRGB; | ||
| // Respect an explicit XYZ system tagging | ||
| if (params->repr.sys != PL_COLOR_SYSTEM_XYZ) { |
There was a problem hiding this comment.
This is dead code, no?
mp_image_params_get_forced_csp already does:
if (csp == PL_COLOR_SYSTEM_RGB && params->repr.sys == PL_COLOR_SYSTEM_XYZ)
csp = PL_COLOR_SYSTEM_XYZ;
The current behaviour overrode colorspace props which caused XYZ to get incorrectly decoded. Route SMPTE 428-1 / CIE XYZ inputs through the XYZ color system and preserve an explicit transfer tag, so scene-linear camera XYZ keeps TRC=LINEAR while DCDM keeps TRC=ST428. For DCDM the primaries are left unset: libplacebo tags it DCI-P3 itself, which keeps the DCI white point chromatically adapted to the display. Scene-linear XYZ is instead defaulted to BT.2020 (a wide D65 gamut) before pl_color_space_infer's generic BT.709 fallback runs, so that wide-gamut camera data is not clipped to BT.709 on decode.
The current behaviour overrode colorspace props which caused XYZ to get incorrectly decoded.
Requires recent ffmpeg (https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23475) and libplacebo improvements (https://code.videolan.org/videolan/libplacebo/-/merge_requests/865).