mirror of https://github.com/mpv-player/mpv
video: Better support for XYZ input
With this change, XYZ input is directly converted to the output colorspace wherever possible, and to the colorspace specified by the tags and/or --primaries option, otherwise. This commit also restructures some of the CMS code in gl_video.c to hopefully make it clearer which decision is being done where and why.
This commit is contained in:
parent
17762a1919
commit
7f3ea12802
|
@ -435,6 +435,36 @@ static void luma_coeffs(float m[3][4], float lr, float lg, float lb)
|
|||
// Constant coefficients (m[x][3]) not set here
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief get the coefficients of an xyz -> rgb conversion matrix
|
||||
* \param params parameters for the conversion, only brightness is used
|
||||
* \param prim primaries of the RGB space to transform to
|
||||
* \param m array to store the coefficients into
|
||||
*/
|
||||
void mp_get_xyz2rgb_coeffs(struct mp_csp_params *params, struct mp_csp_primaries prim, float m[3][4])
|
||||
{
|
||||
float tmp[3][3], brightness = params->brightness;
|
||||
mp_get_rgb2xyz_matrix(prim, tmp);
|
||||
mp_invert_matrix3x3(tmp);
|
||||
|
||||
// Since this outputs linear RGB rather than companded RGB, we
|
||||
// want to linearize any brightness additions. 2 is a reasonable
|
||||
// approximation for any sort of gamma function that could be in use.
|
||||
// As this is an aesthetic setting only, any exact values do not matter.
|
||||
if (brightness < 0) {
|
||||
brightness *= -brightness;
|
||||
} else {
|
||||
brightness *= brightness;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (int j = 0; j < 3; j++)
|
||||
m[i][j] = tmp[i][j];
|
||||
|
||||
m[i][COL_C] = brightness;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief get the coefficients of the yuv -> rgb conversion matrix
|
||||
* \param params struct specifying the properties of the conversion like
|
||||
|
|
|
@ -127,6 +127,7 @@ enum mp_csp_equalizer_param {
|
|||
| (1 << MP_CSP_EQ_SATURATION) )
|
||||
|
||||
#define MP_CSP_EQ_CAPS_GAMMA (1 << MP_CSP_EQ_GAMMA)
|
||||
#define MP_CSP_EQ_CAPS_BRIGHTNESS (1 << MP_CSP_EQ_BRIGHTNESS)
|
||||
|
||||
extern const char *const mp_csp_equalizer_names[MP_CSP_EQ_COUNT];
|
||||
|
||||
|
@ -188,6 +189,8 @@ struct mp_csp_primaries mp_get_csp_primaries(enum mp_csp_prim csp);
|
|||
|
||||
void mp_get_cms_matrix(struct mp_csp_primaries src, struct mp_csp_primaries dest, float cms_matrix[3][3]);
|
||||
void mp_get_rgb2xyz_matrix(struct mp_csp_primaries space, float m[3][3]);
|
||||
|
||||
void mp_get_xyz2rgb_coeffs(struct mp_csp_params *params, struct mp_csp_primaries prim, float xyz2rgb[3][4]);
|
||||
void mp_get_yuv2rgb_coeffs(struct mp_csp_params *params, float yuv2rgb[3][4]);
|
||||
void mp_gen_yuv2rgb_map(struct mp_csp_params *params, uint8_t *map, int size);
|
||||
|
||||
|
|
|
@ -566,7 +566,10 @@ void mp_image_params_guess_csp(struct mp_image_params *params)
|
|||
// since that's the most likely scenario. Proper VOs should ignore
|
||||
// this field as well as the matrix and treat XYZ input as absolute,
|
||||
// but for VOs which use the matrix (and hence, consult this field)
|
||||
// this is the correct parameter.
|
||||
// this is the correct parameter. This doubles as a reasonable output
|
||||
// gamut for VOs which *do* use the specialized XYZ matrix but don't
|
||||
// know any better output gamut other than whatever the source is
|
||||
// tagged with.
|
||||
if (params->primaries == MP_CSP_PRIM_AUTO)
|
||||
params->primaries = MP_CSP_PRIM_BT_709;
|
||||
} else {
|
||||
|
|
|
@ -575,9 +575,13 @@ static void update_uniforms(struct gl_video *p, GLuint program)
|
|||
|
||||
loc = gl->GetUniformLocation(program, "colormatrix");
|
||||
if (loc >= 0) {
|
||||
float yuv2rgb[3][4] = {{0}};
|
||||
mp_get_yuv2rgb_coeffs(&cparams, yuv2rgb);
|
||||
gl->UniformMatrix4x3fv(loc, 1, GL_TRUE, &yuv2rgb[0][0]);
|
||||
float m[3][4] = {{0}};
|
||||
if (p->image_desc.flags & MP_IMGFLAG_XYZ) {
|
||||
mp_get_xyz2rgb_coeffs(&cparams, p->csp_src, m);
|
||||
} else {
|
||||
mp_get_yuv2rgb_coeffs(&cparams, m);
|
||||
}
|
||||
gl->UniformMatrix4x3fv(loc, 1, GL_TRUE, &m[0][0]);
|
||||
}
|
||||
|
||||
gl->Uniform1f(gl->GetUniformLocation(program, "input_gamma"),
|
||||
|
@ -880,15 +884,29 @@ static void compile_shaders(struct gl_video *p)
|
|||
bool convert_to_linear_gamma = !p->is_linear_rgb && use_cms || use_const_luma;
|
||||
|
||||
// Figure out the right color spaces we need to convert, if any
|
||||
enum mp_csp_prim dest = p->opts.srgb ? MP_CSP_PRIM_BT_709 : MP_CSP_PRIM_BT_2020;
|
||||
bool use_cms_matrix = false;
|
||||
|
||||
if (use_cms && p->image_params.primaries != dest) {
|
||||
p->csp_src = mp_get_csp_primaries(p->image_params.primaries);
|
||||
p->csp_dest = mp_get_csp_primaries(dest);
|
||||
use_cms_matrix = true;
|
||||
enum mp_csp_prim prim_src = p->image_params.primaries, prim_dest;
|
||||
if (use_cms) {
|
||||
// sRGB mode wants sRGB aka BT.709 primaries, but the 3DLUT is
|
||||
// always built against BT.2020.
|
||||
prim_dest = p->opts.srgb ? MP_CSP_PRIM_BT_709 : MP_CSP_PRIM_BT_2020;
|
||||
} else {
|
||||
// If no CMS is being done we just want to output stuff as-is,
|
||||
// in the native colorspace of the source.
|
||||
prim_dest = prim_src;
|
||||
}
|
||||
|
||||
// XYZ input has no defined input color space, so we can directly convert
|
||||
// it to whatever output space we actually need.
|
||||
if (p->image_desc.flags & MP_IMGFLAG_XYZ)
|
||||
prim_src = prim_dest;
|
||||
|
||||
// Set the colorspace primaries and figure out whether we need to perform
|
||||
// an extra conversion.
|
||||
p->csp_src = mp_get_csp_primaries(prim_src);
|
||||
p->csp_dest = mp_get_csp_primaries(prim_dest);
|
||||
|
||||
bool use_cms_matrix = prim_src != prim_dest;
|
||||
|
||||
if (p->gl_target == GL_TEXTURE_RECTANGLE) {
|
||||
shader_def(&header, "VIDEO_SAMPLER", "sampler2DRect");
|
||||
shader_def_opt(&header, "USE_RECTANGLE", true);
|
||||
|
@ -1368,6 +1386,8 @@ static void init_video(struct gl_video *p, const struct mp_image_params *params)
|
|||
int eq_caps = MP_CSP_EQ_CAPS_GAMMA;
|
||||
if (p->is_yuv && p->image_params.colorspace != MP_CSP_BT_2020_C)
|
||||
eq_caps |= MP_CSP_EQ_CAPS_COLORMATRIX;
|
||||
if (p->image_desc.flags & MP_IMGFLAG_XYZ)
|
||||
eq_caps |= MP_CSP_EQ_CAPS_BRIGHTNESS;
|
||||
p->video_eq.capabilities = eq_caps;
|
||||
|
||||
debug_check_gl(p, "before video texture creation");
|
||||
|
|
Loading…
Reference in New Issue