mirror of
https://github.com/mpv-player/mpv
synced 2025-01-29 19:22:48 +00:00
csputils: add missing gamma support
We have MP_CSP_TRC defined, but it wasn't being used by practically anything. This commit adds missing conversion logic, adds it to mp_image, and moves the auto-guessing logic to where it should be, in mp_image_params_guess_csp (and out of vo_opengl). Note that this also fixes a minor bug: csp_prim was not being copied between mp_image structs if the format was not YUV in both cases, but this is wrong - the primaries are always relevant.
This commit is contained in:
parent
076b3d1385
commit
fbacd5de31
@ -65,6 +65,13 @@ const char *const mp_csp_prim_names[MP_CSP_PRIM_COUNT] = {
|
||||
"BT.470 M",
|
||||
};
|
||||
|
||||
const char *const mp_csp_trc_names[MP_CSP_TRC_COUNT] = {
|
||||
"Autoselect",
|
||||
"BT.1886 (SD, HD, UHD)",
|
||||
"sRGB (IEC 61966-2-1)",
|
||||
"Linear light",
|
||||
};
|
||||
|
||||
const char *const mp_csp_equalizer_names[MP_CSP_EQ_COUNT] = {
|
||||
"brightness",
|
||||
"contrast",
|
||||
@ -142,6 +149,21 @@ enum mp_csp_prim avcol_pri_to_mp_csp_prim(int avpri)
|
||||
}
|
||||
}
|
||||
|
||||
enum mp_csp_trc avcol_trc_to_mp_csp_trc(int avtrc)
|
||||
{
|
||||
switch (avtrc) {
|
||||
case AVCOL_TRC_BT709:
|
||||
case AVCOL_TRC_SMPTE170M:
|
||||
case AVCOL_TRC_SMPTE240M:
|
||||
case AVCOL_TRC_BT1361_ECG:
|
||||
case AVCOL_TRC_BT2020_10:
|
||||
case AVCOL_TRC_BT2020_12: return MP_CSP_TRC_BT_1886;
|
||||
case AVCOL_TRC_IEC61966_2_1: return MP_CSP_TRC_SRGB;
|
||||
case AVCOL_TRC_LINEAR: return MP_CSP_TRC_LINEAR;
|
||||
default: return MP_CSP_TRC_AUTO;
|
||||
}
|
||||
}
|
||||
|
||||
int mp_csp_to_avcol_spc(enum mp_csp colorspace)
|
||||
{
|
||||
switch (colorspace) {
|
||||
@ -181,6 +203,17 @@ int mp_csp_prim_to_avcol_pri(enum mp_csp_prim prim)
|
||||
}
|
||||
}
|
||||
|
||||
int mp_csp_trc_to_avcol_trc(enum mp_csp_trc trc)
|
||||
{
|
||||
switch (trc) {
|
||||
// We just call it BT.1886 since we're decoding, but it's still BT.709
|
||||
case MP_CSP_TRC_BT_1886: return AVCOL_TRC_BT709;
|
||||
case MP_CSP_TRC_SRGB: return AVCOL_TRC_IEC61966_2_1;
|
||||
case MP_CSP_TRC_LINEAR: return AVCOL_TRC_LINEAR;
|
||||
default: return AVCOL_TRC_UNSPECIFIED;
|
||||
}
|
||||
}
|
||||
|
||||
enum mp_csp mp_csp_guess_colorspace(int width, int height)
|
||||
{
|
||||
return width >= 1280 || height > 576 ? MP_CSP_BT_709 : MP_CSP_BT_601;
|
||||
|
@ -68,16 +68,20 @@ enum mp_csp_prim {
|
||||
MP_CSP_PRIM_COUNT
|
||||
};
|
||||
|
||||
enum mp_csp_trc {
|
||||
MP_CSP_TRC_NONE,
|
||||
MP_CSP_TRC_BT_1886,
|
||||
MP_CSP_TRC_SRGB,
|
||||
MP_CSP_TRC_LINEAR
|
||||
};
|
||||
|
||||
// Any enum mp_csp_prim value is a valid index (except MP_CSP_PRIM_COUNT)
|
||||
extern const char *const mp_csp_prim_names[MP_CSP_PRIM_COUNT];
|
||||
|
||||
enum mp_csp_trc {
|
||||
MP_CSP_TRC_AUTO,
|
||||
MP_CSP_TRC_BT_1886,
|
||||
MP_CSP_TRC_SRGB,
|
||||
MP_CSP_TRC_LINEAR,
|
||||
MP_CSP_TRC_COUNT
|
||||
};
|
||||
|
||||
// Any enum mp_csp_trc value is a valid index (except MP_CSP_TRC_COUNT)
|
||||
extern const char *const mp_csp_trc_names[MP_CSP_TRC_COUNT];
|
||||
|
||||
// These constants are based on the ICC specification (Table 23) and match
|
||||
// up with the API of LittleCMS, which treats them as integers.
|
||||
enum mp_render_intent {
|
||||
@ -205,6 +209,8 @@ int mp_csp_levels_to_avcol_range(enum mp_csp_levels range);
|
||||
|
||||
int mp_csp_prim_to_avcol_pri(enum mp_csp_prim prim);
|
||||
|
||||
int mp_csp_trc_to_avcol_trc(enum mp_csp_trc trc);
|
||||
|
||||
enum mp_csp mp_csp_guess_colorspace(int width, int height);
|
||||
enum mp_csp_prim mp_csp_guess_primaries(int width, int height);
|
||||
|
||||
|
@ -368,10 +368,11 @@ void mp_image_copy_attributes(struct mp_image *dst, struct mp_image *src)
|
||||
dst->params.d_w = src->params.d_w;
|
||||
dst->params.d_h = src->params.d_h;
|
||||
}
|
||||
dst->params.primaries = src->params.primaries;
|
||||
dst->params.gamma = src->params.gamma;
|
||||
if ((dst->flags & MP_IMGFLAG_YUV) == (src->flags & MP_IMGFLAG_YUV)) {
|
||||
dst->params.colorspace = src->params.colorspace;
|
||||
dst->params.colorlevels = src->params.colorlevels;
|
||||
dst->params.primaries = src->params.primaries;
|
||||
dst->params.chroma_location = src->params.chroma_location;
|
||||
dst->params.outputlevels = src->params.outputlevels;
|
||||
}
|
||||
@ -516,6 +517,7 @@ bool mp_image_params_equal(const struct mp_image_params *p1,
|
||||
p1->colorlevels == p2->colorlevels &&
|
||||
p1->outputlevels == p2->outputlevels &&
|
||||
p1->primaries == p2->primaries &&
|
||||
p1->gamma == p2->gamma &&
|
||||
p1->chroma_location == p2->chroma_location &&
|
||||
p1->rotate == p2->rotate &&
|
||||
p1->stereo_in == p2->stereo_in &&
|
||||
@ -578,6 +580,8 @@ void mp_image_params_guess_csp(struct mp_image_params *params)
|
||||
params->primaries = mp_csp_guess_primaries(params->w, params->h);
|
||||
}
|
||||
}
|
||||
if (params->gamma == MP_CSP_TRC_AUTO)
|
||||
params->gamma = MP_CSP_TRC_BT_1886;
|
||||
} else if (fmt.flags & MP_IMGFLAG_RGB) {
|
||||
params->colorspace = MP_CSP_RGB;
|
||||
params->colorlevels = MP_CSP_LEVELS_PC;
|
||||
@ -589,6 +593,8 @@ void mp_image_params_guess_csp(struct mp_image_params *params)
|
||||
// Note: sRGB primaries = BT.709 primaries
|
||||
if (params->primaries == MP_CSP_PRIM_AUTO)
|
||||
params->primaries = MP_CSP_PRIM_BT_709;
|
||||
if (params->gamma == MP_CSP_TRC_AUTO)
|
||||
params->gamma = MP_CSP_TRC_SRGB;
|
||||
} else if (fmt.flags & MP_IMGFLAG_XYZ) {
|
||||
params->colorspace = MP_CSP_XYZ;
|
||||
params->colorlevels = MP_CSP_LEVELS_PC;
|
||||
@ -603,11 +609,14 @@ void mp_image_params_guess_csp(struct mp_image_params *params)
|
||||
// tagged with.
|
||||
if (params->primaries == MP_CSP_PRIM_AUTO)
|
||||
params->primaries = MP_CSP_PRIM_BT_709;
|
||||
if (params->gamma = MP_CSP_TRC_AUTO)
|
||||
params->gamma = MP_CSP_TRC_LINEAR;
|
||||
} else {
|
||||
// We have no clue.
|
||||
params->colorspace = MP_CSP_AUTO;
|
||||
params->colorlevels = MP_CSP_LEVELS_AUTO;
|
||||
params->primaries = MP_CSP_PRIM_AUTO;
|
||||
params->gamma = MP_CSP_TRC_AUTO;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,6 +48,7 @@ struct mp_image_params {
|
||||
enum mp_csp colorspace;
|
||||
enum mp_csp_levels colorlevels;
|
||||
enum mp_csp_prim primaries;
|
||||
enum mp_csp_trc gamma;
|
||||
enum mp_chroma_location chroma_location;
|
||||
// The image should be converted to these levels. Unlike colorlevels, it
|
||||
// does not describe the current state of the image. (Somewhat similar to
|
||||
|
@ -937,8 +937,7 @@ static void compile_shaders(struct gl_video *p)
|
||||
bool use_input_gamma = p->input_gamma != 1.0;
|
||||
bool use_conv_gamma = p->conv_gamma != 1.0;
|
||||
bool use_const_luma = p->image_params.colorspace == MP_CSP_BT_2020_C;
|
||||
|
||||
enum mp_csp_trc gamma_fun = MP_CSP_TRC_NONE;
|
||||
enum mp_csp_trc gamma_fun = p->image_params.gamma;
|
||||
|
||||
// If either color correction option (3dlut or srgb) is enabled, or if
|
||||
// sigmoidal upscaling is requested, or if the source is linear XYZ, we
|
||||
@ -946,20 +945,6 @@ static void compile_shaders(struct gl_video *p)
|
||||
bool use_linear_light = p->opts.linear_scaling || p->opts.sigmoid_upscaling
|
||||
|| use_cms || is_xyz;
|
||||
|
||||
if (use_linear_light) {
|
||||
// We use the color level range to distinguish between PC
|
||||
// content like images, which are most likely sRGB, and TV content
|
||||
// like movies, which are most likely BT.1886. XYZ input is always
|
||||
// treated as linear.
|
||||
if (is_xyz) {
|
||||
gamma_fun = MP_CSP_TRC_LINEAR;
|
||||
} else if (p->image_params.colorlevels == MP_CSP_LEVELS_PC) {
|
||||
gamma_fun = MP_CSP_TRC_SRGB;
|
||||
} else {
|
||||
gamma_fun = MP_CSP_TRC_BT_1886;
|
||||
}
|
||||
}
|
||||
|
||||
// The inverse of the above transformation is normally handled by
|
||||
// the CMS cases, but if CMS is disabled we need to go back manually
|
||||
bool use_inv_bt1886 = false;
|
||||
|
Loading…
Reference in New Issue
Block a user