Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:X0F:HSF
mpv
mpv_PR12802.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File mpv_PR12802.patch of Package mpv
From 01bf36c4864d8cd54e0be5ed3c6d3dfc3b5d3162 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= <kasper93@gmail.com> Date: Sat, 4 Nov 2023 03:55:38 +0100 Subject: [PATCH 1/5] csputils: replace mp_colorspace with pl_color_space --- demux/demux_mkv.c | 21 +- demux/stheader.h | 5 +- filters/f_decoder_wrapper.c | 3 +- player/command.c | 10 +- sub/draw_bmp.c | 4 +- sub/sd_ass.c | 66 +++--- test/img_format.c | 2 +- test/repack.c | 32 +-- test/scale_test.c | 4 +- video/csputils.c | 369 +++++++++++----------------------- video/csputils.h | 122 ++--------- video/filter/vf_d3d11vpp.c | 4 +- video/filter/vf_fingerprint.c | 2 +- video/filter/vf_format.c | 28 +-- video/filter/vf_vapoursynth.c | 7 +- video/filter/vf_vavpp.c | 2 +- video/image_writer.c | 31 +-- video/img_format.c | 10 +- video/img_format.h | 6 +- video/mp_image.c | 157 ++++++++------- video/mp_image.h | 4 +- video/out/d3d11/context.c | 2 +- video/out/gpu/context.h | 2 +- video/out/gpu/d3d11_helpers.c | 38 ++-- video/out/gpu/d3d11_helpers.h | 4 +- video/out/gpu/lcms.c | 40 ++-- video/out/gpu/lcms.h | 6 +- video/out/gpu/video.c | 132 ++++++------ video/out/gpu/video.h | 1 - video/out/gpu/video_shaders.c | 95 ++++----- video/out/gpu/video_shaders.h | 9 +- video/out/opengl/hwdec_rpi.c | 10 +- video/out/placebo/utils.c | 148 -------------- video/out/placebo/utils.h | 7 - video/out/vo_gpu_next.c | 34 ++-- video/out/vo_lavc.c | 8 +- video/out/vo_rpi.c | 10 +- video/out/vo_vaapi.c | 2 +- video/out/vo_xv.c | 6 +- video/repack.c | 16 +- video/sws_utils.c | 19 +- video/vaapi.c | 8 +- video/vaapi.h | 2 +- video/zimg.c | 102 +++++----- 44 files changed, 610 insertions(+), 980 deletions(-) diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c index 41226c56ba75..45719ede8922 100644 --- a/demux/demux_mkv.c +++ b/demux/demux_mkv.c @@ -36,6 +36,8 @@ #include <libavcodec/avcodec.h> #include <libavcodec/version.h> +#include <libplacebo/utils/libav.h> + #include "config.h" #if HAVE_ZLIB @@ -108,7 +110,8 @@ typedef struct mkv_track { double v_frate; uint32_t colorspace; int stereo_mode; - struct mp_colorspace color; + struct pl_color_repr repr; + struct pl_color_space color; uint32_t v_crop_top, v_crop_left, v_crop_right, v_crop_bottom; float v_projection_pose_roll; bool v_projection_pose_roll_set; @@ -573,24 +576,24 @@ static void parse_trackcolour(struct demuxer *demuxer, struct mkv_track *track, // 23001-8:2013/DCOR1, which is the same order used by libavutil/pixfmt.h, // so we can just re-use our avcol_ conversion functions. if (colour->n_matrix_coefficients) { - track->color.space = avcol_spc_to_mp_csp(colour->matrix_coefficients); + track->repr.sys = pl_system_from_av(colour->matrix_coefficients); MP_DBG(demuxer, "| + Matrix: %s\n", - m_opt_choice_str(mp_csp_names, track->color.space)); + m_opt_choice_str(pl_csp_names, track->repr.sys)); } if (colour->n_primaries) { - track->color.primaries = avcol_pri_to_mp_csp_prim(colour->primaries); + track->color.primaries = pl_primaries_from_av(colour->primaries); MP_DBG(demuxer, "| + Primaries: %s\n", - m_opt_choice_str(mp_csp_prim_names, track->color.primaries)); + m_opt_choice_str(pl_csp_prim_names, track->color.primaries)); } if (colour->n_transfer_characteristics) { - track->color.gamma = avcol_trc_to_mp_csp_trc(colour->transfer_characteristics); + track->color.transfer = pl_transfer_from_av(colour->transfer_characteristics); MP_DBG(demuxer, "| + Gamma: %s\n", - m_opt_choice_str(mp_csp_trc_names, track->color.gamma)); + m_opt_choice_str(pl_csp_trc_names, track->color.transfer)); } if (colour->n_range) { - track->color.levels = avcol_range_to_mp_csp_levels(colour->range); + track->repr.levels = pl_levels_from_av(colour->range); MP_DBG(demuxer, "| + Levels: %s\n", - m_opt_choice_str(mp_csp_levels_names, track->color.levels)); + m_opt_choice_str(pl_csp_levels_names, track->repr.levels)); } if (colour->n_max_cll) { track->color.hdr.max_cll = colour->max_cll; diff --git a/demux/stheader.h b/demux/stheader.h index 1bc036d648df..597c97843968 100644 --- a/demux/stheader.h +++ b/demux/stheader.h @@ -105,8 +105,9 @@ struct mp_codec_params { int disp_w, disp_h; // display size int rotate; // intended display rotation, in degrees, [0, 359] int stereo_mode; // mp_stereo3d_mode (0 if none/unknown) - struct mp_colorspace color; // colorspace info where available - struct mp_rect crop; // crop to be applied + struct pl_color_space color; // colorspace info where available + struct pl_color_repr repr; // color representaion info where available + struct mp_rect crop; // crop to be applied // STREAM_VIDEO + STREAM_AUDIO int bits_per_coded_sample; diff --git a/filters/f_decoder_wrapper.c b/filters/f_decoder_wrapper.c index 87489ccdf1bd..12535c926c96 100644 --- a/filters/f_decoder_wrapper.c +++ b/filters/f_decoder_wrapper.c @@ -616,7 +616,8 @@ static void fix_image_params(struct priv *p, m.rotate = (m.rotate + opts->video_rotate) % 360; } - mp_colorspace_merge(&m.color, &c->color); + pl_color_space_merge(&m.color, &c->color); + pl_color_repr_merge(&m.repr, &c->repr); // Guess missing colorspace fields from metadata. This guarantees all // fields are at least set to legal values afterwards. diff --git a/player/command.c b/player/command.c index 8d6ab07d03f6..33d30508e79f 100644 --- a/player/command.c +++ b/player/command.c @@ -2317,16 +2317,16 @@ static int property_imgparams(struct mp_image_params p, int action, void *arg) {"aspect-name", SUB_PROP_STR(aspect_name), .unavailable = !aspect_name}, {"par", SUB_PROP_FLOAT(p.p_w / (double)p.p_h)}, {"colormatrix", - SUB_PROP_STR(m_opt_choice_str(mp_csp_names, p.color.space))}, + SUB_PROP_STR(m_opt_choice_str(pl_csp_names, p.repr.sys))}, {"colorlevels", - SUB_PROP_STR(m_opt_choice_str(mp_csp_levels_names, p.color.levels))}, + SUB_PROP_STR(m_opt_choice_str(pl_csp_levels_names, p.repr.levels))}, {"primaries", - SUB_PROP_STR(m_opt_choice_str(mp_csp_prim_names, p.color.primaries))}, + SUB_PROP_STR(m_opt_choice_str(pl_csp_prim_names, p.color.primaries))}, {"gamma", - SUB_PROP_STR(m_opt_choice_str(mp_csp_trc_names, p.color.gamma))}, + SUB_PROP_STR(m_opt_choice_str(pl_csp_trc_names, p.color.transfer))}, {"sig-peak", SUB_PROP_FLOAT(p.color.hdr.max_luma / MP_REF_WHITE)}, {"light", - SUB_PROP_STR(m_opt_choice_str(mp_csp_light_names, p.color.light))}, + SUB_PROP_STR(m_opt_choice_str(mp_csp_light_names, p.light))}, {"chroma-location", SUB_PROP_STR(m_opt_choice_str(mp_chroma_names, p.chroma_location))}, {"stereo-in", diff --git a/sub/draw_bmp.c b/sub/draw_bmp.c index 58db162a56d3..cde8f503f334 100644 --- a/sub/draw_bmp.c +++ b/sub/draw_bmp.c @@ -546,7 +546,7 @@ static bool reinit_to_video(struct mp_draw_sub_cache *p) mp_get_regular_imgfmt(&vfdesc, mp_repack_get_format_dst(p->video_to_f32)); assert(vfdesc.num_planes); // must have succeeded - if (params->color.space == MP_CSP_RGB && vfdesc.num_planes >= 3) { + if (params->repr.sys == PL_COLOR_SYSTEM_RGB && vfdesc.num_planes >= 3) { use_shortcut = true; if (vfdesc.component_type == MP_COMPONENT_TYPE_UINT && @@ -724,7 +724,7 @@ static bool reinit_to_video(struct mp_draw_sub_cache *p) p->alpha_overlay->stride[0] = p->video_overlay->stride[aplane]; // Full range gray always has the same range as alpha. - p->alpha_overlay->params.color.levels = MP_CSP_LEVELS_PC; + p->alpha_overlay->params.repr.levels = PL_COLOR_LEVELS_FULL; mp_image_params_guess_csp(&p->alpha_overlay->params); p->calpha_overlay = diff --git a/sub/sd_ass.c b/sub/sd_ass.c index 6742f6f658fd..aa651375bec1 100644 --- a/sub/sd_ass.c +++ b/sub/sd_ass.c @@ -897,27 +897,27 @@ static void mangle_colors(struct sd *sd, struct sub_bitmaps *parts) { struct mp_subtitle_opts *opts = sd->opts; struct sd_ass_priv *ctx = sd->priv; - enum mp_csp csp = 0; - enum mp_csp_levels levels = 0; + enum pl_color_system csp = 0; + enum pl_color_levels levels = 0; if (opts->ass_vsfilter_color_compat == 0) // "no" return; bool force_601 = opts->ass_vsfilter_color_compat == 3; ASS_Track *track = ctx->ass_track; static const int ass_csp[] = { - [YCBCR_BT601_TV] = MP_CSP_BT_601, - [YCBCR_BT601_PC] = MP_CSP_BT_601, - [YCBCR_BT709_TV] = MP_CSP_BT_709, - [YCBCR_BT709_PC] = MP_CSP_BT_709, - [YCBCR_SMPTE240M_TV] = MP_CSP_SMPTE_240M, - [YCBCR_SMPTE240M_PC] = MP_CSP_SMPTE_240M, + [YCBCR_BT601_TV] = PL_COLOR_SYSTEM_BT_601, + [YCBCR_BT601_PC] = PL_COLOR_SYSTEM_BT_601, + [YCBCR_BT709_TV] = PL_COLOR_SYSTEM_BT_709, + [YCBCR_BT709_PC] = PL_COLOR_SYSTEM_BT_709, + [YCBCR_SMPTE240M_TV] = PL_COLOR_SYSTEM_SMPTE_240M, + [YCBCR_SMPTE240M_PC] = PL_COLOR_SYSTEM_SMPTE_240M, }; static const int ass_levels[] = { - [YCBCR_BT601_TV] = MP_CSP_LEVELS_TV, - [YCBCR_BT601_PC] = MP_CSP_LEVELS_PC, - [YCBCR_BT709_TV] = MP_CSP_LEVELS_TV, - [YCBCR_BT709_PC] = MP_CSP_LEVELS_PC, - [YCBCR_SMPTE240M_TV] = MP_CSP_LEVELS_TV, - [YCBCR_SMPTE240M_PC] = MP_CSP_LEVELS_PC, + [YCBCR_BT601_TV] = PL_COLOR_LEVELS_LIMITED, + [YCBCR_BT601_PC] = PL_COLOR_LEVELS_FULL, + [YCBCR_BT709_TV] = PL_COLOR_LEVELS_LIMITED, + [YCBCR_BT709_PC] = PL_COLOR_LEVELS_FULL, + [YCBCR_SMPTE240M_TV] = PL_COLOR_LEVELS_LIMITED, + [YCBCR_SMPTE240M_PC] = PL_COLOR_LEVELS_FULL, }; int trackcsp = track->YCbCrMatrix; if (force_601) @@ -930,8 +930,8 @@ static void mangle_colors(struct sd *sd, struct sub_bitmaps *parts) if (trackcsp < sizeof(ass_levels) / sizeof(ass_levels[0])) levels = ass_levels[trackcsp]; if (trackcsp == YCBCR_DEFAULT) { - csp = MP_CSP_BT_601; - levels = MP_CSP_LEVELS_TV; + csp = PL_COLOR_SYSTEM_BT_601; + levels = PL_COLOR_LEVELS_LIMITED; } // Unknown colorspace (either YCBCR_UNKNOWN, or a valid value unknown to us) if (!csp || !levels) @@ -940,42 +940,42 @@ static void mangle_colors(struct sd *sd, struct sub_bitmaps *parts) struct mp_image_params params = ctx->video_params; if (force_601) { - params.color = (struct mp_colorspace){ - .space = MP_CSP_BT_709, - .levels = MP_CSP_LEVELS_TV, + params.repr = (struct pl_color_repr){ + .sys = PL_COLOR_SYSTEM_BT_709, + .levels = PL_COLOR_LEVELS_LIMITED, }; } - if ((csp == params.color.space && levels == params.color.levels) || - params.color.space == MP_CSP_RGB) // Even VSFilter doesn't mangle on RGB video + if ((csp == params.repr.sys && levels == params.repr.levels) || + params.repr.sys == PL_COLOR_SYSTEM_RGB) // Even VSFilter doesn't mangle on RGB video return; - bool basic_conv = params.color.space == MP_CSP_BT_709 && - params.color.levels == MP_CSP_LEVELS_TV && - csp == MP_CSP_BT_601 && - levels == MP_CSP_LEVELS_TV; + bool basic_conv = params.repr.sys == PL_COLOR_SYSTEM_BT_709 && + params.repr.levels == PL_COLOR_LEVELS_LIMITED && + csp == PL_COLOR_SYSTEM_BT_601 && + levels == PL_COLOR_LEVELS_LIMITED; // With "basic", only do as much as needed for basic compatibility. if (opts->ass_vsfilter_color_compat == 1 && !basic_conv) return; - if (params.color.space != ctx->last_params.color.space || - params.color.levels != ctx->last_params.color.levels) + if (params.repr.sys != ctx->last_params.repr.sys || + params.repr.levels != ctx->last_params.repr.levels) { int msgl = basic_conv ? MSGL_V : MSGL_WARN; ctx->last_params = params; MP_MSG(sd, msgl, "mangling colors like vsfilter: " "RGB -> %s %s -> %s %s -> RGB\n", - m_opt_choice_str(mp_csp_names, csp), - m_opt_choice_str(mp_csp_levels_names, levels), - m_opt_choice_str(mp_csp_names, params.color.space), - m_opt_choice_str(mp_csp_names, params.color.levels)); + m_opt_choice_str(pl_csp_names, csp), + m_opt_choice_str(pl_csp_levels_names, levels), + m_opt_choice_str(pl_csp_names, params.repr.sys), + m_opt_choice_str(pl_csp_names, params.repr.levels)); } // Conversion that VSFilter would use struct mp_csp_params vs_params = MP_CSP_PARAMS_DEFAULTS; - vs_params.color.space = csp; - vs_params.color.levels = levels; + vs_params.repr.sys = csp; + vs_params.repr.levels = levels; struct mp_cmat vs_yuv2rgb, vs_rgb2yuv; mp_get_csp_matrix(&vs_params, &vs_yuv2rgb); mp_invert_cmat(&vs_rgb2yuv, &vs_yuv2rgb); diff --git a/test/img_format.c b/test/img_format.c index 3cc8ff5fe01d..3b553f6531aa 100644 --- a/test/img_format.c +++ b/test/img_format.c @@ -40,7 +40,7 @@ int main(int argc, char *argv[]) int fcsp = mp_imgfmt_get_forced_csp(mpfmt); if (fcsp) - fprintf(f, "fcsp=%s ", m_opt_choice_str(mp_csp_names, fcsp)); + fprintf(f, "fcsp=%s ", m_opt_choice_str(pl_csp_names, fcsp)); fprintf(f, "ctype=%s\n", comp_type(mp_imgfmt_get_component_type(mpfmt))); struct mp_imgfmt_desc d = mp_imgfmt_get_desc(mpfmt); diff --git a/test/repack.c b/test/repack.c index a37559b70545..c6ec506ecee5 100644 --- a/test/repack.c +++ b/test/repack.c @@ -326,8 +326,8 @@ static int try_repack(FILE *f, int imgfmt, int flags, int not_if_fmt) return b; } -static void check_float_repack(int imgfmt, enum mp_csp csp, - enum mp_csp_levels levels) +static void check_float_repack(int imgfmt, enum pl_color_system csp, + enum pl_color_levels levels) { imgfmt = UNFUCK(imgfmt); @@ -349,12 +349,12 @@ static void check_float_repack(int imgfmt, enum mp_csp csp, struct mp_image *src = mp_image_alloc(imgfmt, w, 1); assert(src); - src->params.color.space = csp; - src->params.color.levels = levels; + src->params.repr.sys = csp; + src->params.repr.levels = levels; mp_image_params_guess_csp(&src->params); // mpv may not allow all combinations - assert(src->params.color.space == csp); - assert(src->params.color.levels == levels); + assert(src->params.repr.sys == csp); + assert(src->params.repr.levels == levels); for (int p = 0; p < src->num_planes; p++) { int val = 0; @@ -384,6 +384,8 @@ static void check_float_repack(int imgfmt, enum mp_csp csp, z_f->params.color = r_f->params.color = z_i->params.color = r_i->params.color = src->params.color; + z_f->params.repr = r_f->params.repr = z_i->params.repr = + r_i->params.repr = src->params.repr; // The idea is to use zimg to cross-check conversion. struct mp_sws_context *s = mp_sws_alloc(NULL); @@ -503,15 +505,15 @@ int main(int argc, char *argv[]) assert_text_files_equal(refdir, outdir, "repack.txt", "This can fail if FFmpeg/libswscale adds or removes pixfmts."); - check_float_repack(-AV_PIX_FMT_GBRAP, MP_CSP_RGB, MP_CSP_LEVELS_PC); - check_float_repack(-AV_PIX_FMT_GBRAP10, MP_CSP_RGB, MP_CSP_LEVELS_PC); - check_float_repack(-AV_PIX_FMT_GBRAP16, MP_CSP_RGB, MP_CSP_LEVELS_PC); - check_float_repack(-AV_PIX_FMT_YUVA444P, MP_CSP_BT_709, MP_CSP_LEVELS_PC); - check_float_repack(-AV_PIX_FMT_YUVA444P, MP_CSP_BT_709, MP_CSP_LEVELS_TV); - check_float_repack(-AV_PIX_FMT_YUVA444P10, MP_CSP_BT_709, MP_CSP_LEVELS_PC); - check_float_repack(-AV_PIX_FMT_YUVA444P10, MP_CSP_BT_709, MP_CSP_LEVELS_TV); - check_float_repack(-AV_PIX_FMT_YUVA444P16, MP_CSP_BT_709, MP_CSP_LEVELS_PC); - check_float_repack(-AV_PIX_FMT_YUVA444P16, MP_CSP_BT_709, MP_CSP_LEVELS_TV); + check_float_repack(-AV_PIX_FMT_GBRAP, PL_COLOR_SYSTEM_RGB, PL_COLOR_LEVELS_FULL); + check_float_repack(-AV_PIX_FMT_GBRAP10, PL_COLOR_SYSTEM_RGB, PL_COLOR_LEVELS_FULL); + check_float_repack(-AV_PIX_FMT_GBRAP16, PL_COLOR_SYSTEM_RGB, PL_COLOR_LEVELS_FULL); + check_float_repack(-AV_PIX_FMT_YUVA444P, PL_COLOR_SYSTEM_BT_709, PL_COLOR_LEVELS_FULL); + check_float_repack(-AV_PIX_FMT_YUVA444P, PL_COLOR_SYSTEM_BT_709, PL_COLOR_LEVELS_LIMITED); + check_float_repack(-AV_PIX_FMT_YUVA444P10, PL_COLOR_SYSTEM_BT_709, PL_COLOR_LEVELS_FULL); + check_float_repack(-AV_PIX_FMT_YUVA444P10, PL_COLOR_SYSTEM_BT_709, PL_COLOR_LEVELS_LIMITED); + check_float_repack(-AV_PIX_FMT_YUVA444P16, PL_COLOR_SYSTEM_BT_709, PL_COLOR_LEVELS_FULL); + check_float_repack(-AV_PIX_FMT_YUVA444P16, PL_COLOR_SYSTEM_BT_709, PL_COLOR_LEVELS_LIMITED); // Determine the list of possible draw_bmp input formats. Do this here // because it mostly depends on repack and imgformat stuff. diff --git a/test/scale_test.c b/test/scale_test.c index f919dca1e241..fa7886de4823 100644 --- a/test/scale_test.c +++ b/test/scale_test.c @@ -10,7 +10,7 @@ static struct mp_image *gen_repack_test_img(int w, int h, int bytes, bool rgb, struct mp_regular_imgfmt planar_desc = { .component_type = MP_COMPONENT_TYPE_UINT, .component_size = bytes, - .forced_csp = rgb ? MP_CSP_RGB : 0, + .forced_csp = rgb ? PL_COLOR_SYSTEM_RGB : 0, .num_planes = alpha ? 4 : 3, .planes = { {1, {rgb ? 2 : 1}}, @@ -129,7 +129,7 @@ void repack_test_run(struct scale_test *stest) if (!mp_get_regular_imgfmt(&rdesc, ofmt)) continue; } - if (rdesc.num_planes > 1 || rdesc.forced_csp != MP_CSP_RGB) + if (rdesc.num_planes > 1 || rdesc.forced_csp != PL_COLOR_SYSTEM_RGB) continue; struct mp_image *test_img = NULL; diff --git a/video/csputils.c b/video/csputils.c index 59200c5669a9..3b43ba9f5b69 100644 --- a/video/csputils.c +++ b/video/csputils.c @@ -32,66 +32,66 @@ #include "options/m_config.h" #include "options/m_option.h" -const struct m_opt_choice_alternatives mp_csp_names[] = { - {"auto", MP_CSP_AUTO}, - {"bt.601", MP_CSP_BT_601}, - {"bt.709", MP_CSP_BT_709}, - {"smpte-240m", MP_CSP_SMPTE_240M}, - {"bt.2020-ncl", MP_CSP_BT_2020_NC}, - {"bt.2020-cl", MP_CSP_BT_2020_C}, - {"rgb", MP_CSP_RGB}, - {"xyz", MP_CSP_XYZ}, - {"ycgco", MP_CSP_YCGCO}, +const struct m_opt_choice_alternatives pl_csp_names[] = { + {"auto", PL_COLOR_SYSTEM_UNKNOWN}, + {"bt.601", PL_COLOR_SYSTEM_BT_601}, + {"bt.709", PL_COLOR_SYSTEM_BT_709}, + {"smpte-240m", PL_COLOR_SYSTEM_SMPTE_240M}, + {"bt.2020-ncl", PL_COLOR_SYSTEM_BT_2020_NC}, + {"bt.2020-cl", PL_COLOR_SYSTEM_BT_2020_C}, + {"rgb", PL_COLOR_SYSTEM_RGB}, + {"xyz", PL_COLOR_SYSTEM_XYZ}, + {"ycgco", PL_COLOR_SYSTEM_YCGCO}, {0} }; -const struct m_opt_choice_alternatives mp_csp_levels_names[] = { - {"auto", MP_CSP_LEVELS_AUTO}, - {"limited", MP_CSP_LEVELS_TV}, - {"full", MP_CSP_LEVELS_PC}, +const struct m_opt_choice_alternatives pl_csp_levels_names[] = { + {"auto", PL_COLOR_LEVELS_UNKNOWN}, + {"limited", PL_COLOR_LEVELS_LIMITED}, + {"full", PL_COLOR_LEVELS_FULL}, {0} }; -const struct m_opt_choice_alternatives mp_csp_prim_names[] = { - {"auto", MP_CSP_PRIM_AUTO}, - {"bt.601-525", MP_CSP_PRIM_BT_601_525}, - {"bt.601-625", MP_CSP_PRIM_BT_601_625}, - {"bt.709", MP_CSP_PRIM_BT_709}, - {"bt.2020", MP_CSP_PRIM_BT_2020}, - {"bt.470m", MP_CSP_PRIM_BT_470M}, - {"apple", MP_CSP_PRIM_APPLE}, - {"adobe", MP_CSP_PRIM_ADOBE}, - {"prophoto", MP_CSP_PRIM_PRO_PHOTO}, - {"cie1931", MP_CSP_PRIM_CIE_1931}, - {"dci-p3", MP_CSP_PRIM_DCI_P3}, - {"display-p3", MP_CSP_PRIM_DISPLAY_P3}, - {"v-gamut", MP_CSP_PRIM_V_GAMUT}, - {"s-gamut", MP_CSP_PRIM_S_GAMUT}, - {"ebu3213", MP_CSP_PRIM_EBU_3213}, - {"film-c", MP_CSP_PRIM_FILM_C}, - {"aces-ap0", MP_CSP_PRIM_ACES_AP0}, - {"aces-ap1", MP_CSP_PRIM_ACES_AP1}, +const struct m_opt_choice_alternatives pl_csp_prim_names[] = { + {"auto", PL_COLOR_PRIM_UNKNOWN}, + {"bt.601-525", PL_COLOR_PRIM_BT_601_525}, + {"bt.601-625", PL_COLOR_PRIM_BT_601_625}, + {"bt.709", PL_COLOR_PRIM_BT_709}, + {"bt.2020", PL_COLOR_PRIM_BT_2020}, + {"bt.470m", PL_COLOR_PRIM_BT_470M}, + {"apple", PL_COLOR_PRIM_APPLE}, + {"adobe", PL_COLOR_PRIM_ADOBE}, + {"prophoto", PL_COLOR_PRIM_PRO_PHOTO}, + {"cie1931", PL_COLOR_PRIM_CIE_1931}, + {"dci-p3", PL_COLOR_PRIM_DCI_P3}, + {"display-p3", PL_COLOR_PRIM_DISPLAY_P3}, + {"v-gamut", PL_COLOR_PRIM_V_GAMUT}, + {"s-gamut", PL_COLOR_PRIM_S_GAMUT}, + {"ebu3213", PL_COLOR_PRIM_EBU_3213}, + {"film-c", PL_COLOR_PRIM_FILM_C}, + {"aces-ap0", PL_COLOR_PRIM_ACES_AP0}, + {"aces-ap1", PL_COLOR_PRIM_ACES_AP1}, {0} }; -const struct m_opt_choice_alternatives mp_csp_trc_names[] = { - {"auto", MP_CSP_TRC_AUTO}, - {"bt.1886", MP_CSP_TRC_BT_1886}, - {"srgb", MP_CSP_TRC_SRGB}, - {"linear", MP_CSP_TRC_LINEAR}, - {"gamma1.8", MP_CSP_TRC_GAMMA18}, - {"gamma2.0", MP_CSP_TRC_GAMMA20}, - {"gamma2.2", MP_CSP_TRC_GAMMA22}, - {"gamma2.4", MP_CSP_TRC_GAMMA24}, - {"gamma2.6", MP_CSP_TRC_GAMMA26}, - {"gamma2.8", MP_CSP_TRC_GAMMA28}, - {"prophoto", MP_CSP_TRC_PRO_PHOTO}, - {"pq", MP_CSP_TRC_PQ}, - {"hlg", MP_CSP_TRC_HLG}, - {"v-log", MP_CSP_TRC_V_LOG}, - {"s-log1", MP_CSP_TRC_S_LOG1}, - {"s-log2", MP_CSP_TRC_S_LOG2}, - {"st428", MP_CSP_TRC_ST428}, +const struct m_opt_choice_alternatives pl_csp_trc_names[] = { + {"auto", PL_COLOR_TRC_UNKNOWN}, + {"bt.1886", PL_COLOR_TRC_BT_1886}, + {"srgb", PL_COLOR_TRC_SRGB}, + {"linear", PL_COLOR_TRC_LINEAR}, + {"gamma1.8", PL_COLOR_TRC_GAMMA18}, + {"gamma2.0", PL_COLOR_TRC_GAMMA20}, + {"gamma2.2", PL_COLOR_TRC_GAMMA22}, + {"gamma2.4", PL_COLOR_TRC_GAMMA24}, + {"gamma2.6", PL_COLOR_TRC_GAMMA26}, + {"gamma2.8", PL_COLOR_TRC_GAMMA28}, + {"prophoto", PL_COLOR_TRC_PRO_PHOTO}, + {"pq", PL_COLOR_TRC_PQ}, + {"hlg", PL_COLOR_TRC_HLG}, + {"v-log", PL_COLOR_TRC_V_LOG}, + {"s-log1", PL_COLOR_TRC_S_LOG1}, + {"s-log2", PL_COLOR_TRC_S_LOG2}, + {"st428", PL_COLOR_TRC_ST428}, {0} }; @@ -119,21 +119,6 @@ const struct m_opt_choice_alternatives mp_alpha_names[] = { {0} }; -void mp_colorspace_merge(struct mp_colorspace *orig, struct mp_colorspace *new) -{ - if (!orig->space) - orig->space = new->space; - if (!orig->levels) - orig->levels = new->levels; - if (!orig->primaries) - orig->primaries = new->primaries; - if (!orig->gamma) - orig->gamma = new->gamma; - if (!orig->light) - orig->light = new->light; - pl_hdr_metadata_merge(&orig->hdr, &new->hdr); -} - // The short name _must_ match with what vf_stereo3d accepts (if supported). // The long name in comments is closer to the Matroska spec (StereoMode element). // The numeric index matches the Matroska StereoMode value. If you add entries @@ -158,139 +143,27 @@ const struct m_opt_choice_alternatives mp_stereo3d_names[] = { {0} }; -enum mp_csp avcol_spc_to_mp_csp(int avcolorspace) -{ - switch (avcolorspace) { - case AVCOL_SPC_BT709: return MP_CSP_BT_709; - case AVCOL_SPC_BT470BG: return MP_CSP_BT_601; - case AVCOL_SPC_BT2020_NCL: return MP_CSP_BT_2020_NC; - case AVCOL_SPC_BT2020_CL: return MP_CSP_BT_2020_C; - case AVCOL_SPC_SMPTE170M: return MP_CSP_BT_601; - case AVCOL_SPC_SMPTE240M: return MP_CSP_SMPTE_240M; - case AVCOL_SPC_RGB: return MP_CSP_RGB; - case AVCOL_SPC_YCOCG: return MP_CSP_YCGCO; - default: return MP_CSP_AUTO; - } -} - -enum mp_csp_levels avcol_range_to_mp_csp_levels(int avrange) -{ - switch (avrange) { - case AVCOL_RANGE_MPEG: return MP_CSP_LEVELS_TV; - case AVCOL_RANGE_JPEG: return MP_CSP_LEVELS_PC; - default: return MP_CSP_LEVELS_AUTO; - } -} - -enum mp_csp_prim avcol_pri_to_mp_csp_prim(int avpri) -{ - switch (avpri) { - case AVCOL_PRI_SMPTE240M: // Same as below - case AVCOL_PRI_SMPTE170M: return MP_CSP_PRIM_BT_601_525; - case AVCOL_PRI_BT470BG: return MP_CSP_PRIM_BT_601_625; - case AVCOL_PRI_BT709: return MP_CSP_PRIM_BT_709; - case AVCOL_PRI_BT2020: return MP_CSP_PRIM_BT_2020; - case AVCOL_PRI_BT470M: return MP_CSP_PRIM_BT_470M; - case AVCOL_PRI_SMPTE431: return MP_CSP_PRIM_DCI_P3; - case AVCOL_PRI_SMPTE432: return MP_CSP_PRIM_DISPLAY_P3; - default: return MP_CSP_PRIM_AUTO; - } -} - -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; - case AVCOL_TRC_GAMMA22: return MP_CSP_TRC_GAMMA22; - case AVCOL_TRC_GAMMA28: return MP_CSP_TRC_GAMMA28; - case AVCOL_TRC_SMPTEST2084: return MP_CSP_TRC_PQ; - case AVCOL_TRC_ARIB_STD_B67: return MP_CSP_TRC_HLG; - case AVCOL_TRC_SMPTE428: return MP_CSP_TRC_ST428; - default: return MP_CSP_TRC_AUTO; - } -} - -int mp_csp_to_avcol_spc(enum mp_csp colorspace) -{ - switch (colorspace) { - case MP_CSP_BT_709: return AVCOL_SPC_BT709; - case MP_CSP_BT_601: return AVCOL_SPC_BT470BG; - case MP_CSP_BT_2020_NC: return AVCOL_SPC_BT2020_NCL; - case MP_CSP_BT_2020_C: return AVCOL_SPC_BT2020_CL; - case MP_CSP_SMPTE_240M: return AVCOL_SPC_SMPTE240M; - case MP_CSP_RGB: return AVCOL_SPC_RGB; - case MP_CSP_YCGCO: return AVCOL_SPC_YCOCG; - default: return AVCOL_SPC_UNSPECIFIED; - } -} - -int mp_csp_levels_to_avcol_range(enum mp_csp_levels range) -{ - switch (range) { - case MP_CSP_LEVELS_TV: return AVCOL_RANGE_MPEG; - case MP_CSP_LEVELS_PC: return AVCOL_RANGE_JPEG; - default: return AVCOL_RANGE_UNSPECIFIED; - } -} - -int mp_csp_prim_to_avcol_pri(enum mp_csp_prim prim) -{ - switch (prim) { - case MP_CSP_PRIM_BT_601_525: return AVCOL_PRI_SMPTE170M; - case MP_CSP_PRIM_BT_601_625: return AVCOL_PRI_BT470BG; - case MP_CSP_PRIM_BT_709: return AVCOL_PRI_BT709; - case MP_CSP_PRIM_BT_2020: return AVCOL_PRI_BT2020; - case MP_CSP_PRIM_BT_470M: return AVCOL_PRI_BT470M; - case MP_CSP_PRIM_DCI_P3: return AVCOL_PRI_SMPTE431; - case MP_CSP_PRIM_DISPLAY_P3: return AVCOL_PRI_SMPTE432; - default: return AVCOL_PRI_UNSPECIFIED; - } -} - -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; - case MP_CSP_TRC_GAMMA22: return AVCOL_TRC_GAMMA22; - case MP_CSP_TRC_GAMMA28: return AVCOL_TRC_GAMMA28; - case MP_CSP_TRC_PQ: return AVCOL_TRC_SMPTEST2084; - case MP_CSP_TRC_HLG: return AVCOL_TRC_ARIB_STD_B67; - case MP_CSP_TRC_ST428: return AVCOL_TRC_SMPTE428; - default: return AVCOL_TRC_UNSPECIFIED; - } -} - -enum mp_csp mp_csp_guess_colorspace(int width, int height) +enum pl_color_system mp_csp_guess_colorspace(int width, int height) { - return width >= 1280 || height > 576 ? MP_CSP_BT_709 : MP_CSP_BT_601; + return width >= 1280 || height > 576 ? PL_COLOR_SYSTEM_BT_709 : PL_COLOR_SYSTEM_BT_601; } -enum mp_csp_prim mp_csp_guess_primaries(int width, int height) +enum pl_color_primaries mp_csp_guess_primaries(int width, int height) { // HD content if (width >= 1280 || height > 576) - return MP_CSP_PRIM_BT_709; + return PL_COLOR_PRIM_BT_709; switch (height) { case 576: // Typical PAL content, including anamorphic/squared - return MP_CSP_PRIM_BT_601_625; + return PL_COLOR_PRIM_BT_601_625; case 480: // Typical NTSC content, including squared case 486: // NTSC Pro or anamorphic NTSC - return MP_CSP_PRIM_BT_601_525; + return PL_COLOR_PRIM_BT_601_525; default: // No good metric, just pick BT.709 to minimize damage - return MP_CSP_PRIM_BT_709; + return PL_COLOR_PRIM_BT_709; } } @@ -369,7 +242,7 @@ static void mp_mul_matrix3x3(float a[3][3], float b[3][3]) } // return the primaries associated with a certain mp_csp_primaries val -struct mp_csp_primaries mp_get_csp_primaries(enum mp_csp_prim spc) +struct mp_csp_primaries mp_get_csp_primaries(enum pl_color_primaries spc) { /* Values from: ITU-R Recommendations BT.470-6, BT.601-7, BT.709-5, BT.2020-0 @@ -391,21 +264,21 @@ struct mp_csp_primaries mp_get_csp_primaries(enum mp_csp_prim spc) e = {1.0/3.0, 1.0/3.0}; switch (spc) { - case MP_CSP_PRIM_BT_470M: + case PL_COLOR_PRIM_BT_470M: return (struct mp_csp_primaries) { .red = {0.670, 0.330}, .green = {0.210, 0.710}, .blue = {0.140, 0.080}, .white = c }; - case MP_CSP_PRIM_BT_601_525: + case PL_COLOR_PRIM_BT_601_525: return (struct mp_csp_primaries) { .red = {0.630, 0.340}, .green = {0.310, 0.595}, .blue = {0.155, 0.070}, .white = d65 }; - case MP_CSP_PRIM_BT_601_625: + case PL_COLOR_PRIM_BT_601_625: return (struct mp_csp_primaries) { .red = {0.640, 0.330}, .green = {0.290, 0.600}, @@ -414,43 +287,43 @@ struct mp_csp_primaries mp_get_csp_primaries(enum mp_csp_prim spc) }; // This is the default assumption if no colorspace information could // be determined, eg. for files which have no video channel. - case MP_CSP_PRIM_AUTO: - case MP_CSP_PRIM_BT_709: + case PL_COLOR_PRIM_UNKNOWN: + case PL_COLOR_PRIM_BT_709: return (struct mp_csp_primaries) { .red = {0.640, 0.330}, .green = {0.300, 0.600}, .blue = {0.150, 0.060}, .white = d65 }; - case MP_CSP_PRIM_BT_2020: + case PL_COLOR_PRIM_BT_2020: return (struct mp_csp_primaries) { .red = {0.708, 0.292}, .green = {0.170, 0.797}, .blue = {0.131, 0.046}, .white = d65 }; - case MP_CSP_PRIM_APPLE: + case PL_COLOR_PRIM_APPLE: return (struct mp_csp_primaries) { .red = {0.625, 0.340}, .green = {0.280, 0.595}, .blue = {0.115, 0.070}, .white = d65 }; - case MP_CSP_PRIM_ADOBE: + case PL_COLOR_PRIM_ADOBE: return (struct mp_csp_primaries) { .red = {0.640, 0.330}, .green = {0.210, 0.710}, .blue = {0.150, 0.060}, .white = d65 }; - case MP_CSP_PRIM_PRO_PHOTO: + case PL_COLOR_PRIM_PRO_PHOTO: return (struct mp_csp_primaries) { .red = {0.7347, 0.2653}, .green = {0.1596, 0.8404}, .blue = {0.0366, 0.0001}, .white = d50 }; - case MP_CSP_PRIM_CIE_1931: + case PL_COLOR_PRIM_CIE_1931: return (struct mp_csp_primaries) { .red = {0.7347, 0.2653}, .green = {0.2738, 0.7174}, @@ -458,16 +331,16 @@ struct mp_csp_primaries mp_get_csp_primaries(enum mp_csp_prim spc) .white = e }; // From SMPTE RP 431-2 and 432-1 - case MP_CSP_PRIM_DCI_P3: - case MP_CSP_PRIM_DISPLAY_P3: + case PL_COLOR_PRIM_DCI_P3: + case PL_COLOR_PRIM_DISPLAY_P3: return (struct mp_csp_primaries) { .red = {0.680, 0.320}, .green = {0.265, 0.690}, .blue = {0.150, 0.060}, - .white = spc == MP_CSP_PRIM_DCI_P3 ? dci : d65 + .white = spc == PL_COLOR_PRIM_DCI_P3 ? dci : d65 }; // From Panasonic VARICAM reference manual - case MP_CSP_PRIM_V_GAMUT: + case PL_COLOR_PRIM_V_GAMUT: return (struct mp_csp_primaries) { .red = {0.730, 0.280}, .green = {0.165, 0.840}, @@ -475,7 +348,7 @@ struct mp_csp_primaries mp_get_csp_primaries(enum mp_csp_prim spc) .white = d65 }; // From Sony S-Log reference manual - case MP_CSP_PRIM_S_GAMUT: + case PL_COLOR_PRIM_S_GAMUT: return (struct mp_csp_primaries) { .red = {0.730, 0.280}, .green = {0.140, 0.855}, @@ -483,7 +356,7 @@ struct mp_csp_primaries mp_get_csp_primaries(enum mp_csp_prim spc) .white = d65 }; // from EBU Tech. 3213-E - case MP_CSP_PRIM_EBU_3213: + case PL_COLOR_PRIM_EBU_3213: return (struct mp_csp_primaries) { .red = {0.630, 0.340}, .green = {0.295, 0.605}, @@ -491,7 +364,7 @@ struct mp_csp_primaries mp_get_csp_primaries(enum mp_csp_prim spc) .white = d65 }; // From H.273, traditional film with Illuminant C - case MP_CSP_PRIM_FILM_C: + case PL_COLOR_PRIM_FILM_C: return (struct mp_csp_primaries) { .red = {0.681, 0.319}, .green = {0.243, 0.692}, @@ -499,7 +372,7 @@ struct mp_csp_primaries mp_get_csp_primaries(enum mp_csp_prim spc) .white = c }; // From libplacebo source code - case MP_CSP_PRIM_ACES_AP0: + case PL_COLOR_PRIM_ACES_AP0: return (struct mp_csp_primaries) { .red = {0.7347, 0.2653}, .green = {0.0000, 1.0000}, @@ -507,7 +380,7 @@ struct mp_csp_primaries mp_get_csp_primaries(enum mp_csp_prim spc) .white = {0.32168, 0.33767}, }; // From libplacebo source code - case MP_CSP_PRIM_ACES_AP1: + case PL_COLOR_PRIM_ACES_AP1: return (struct mp_csp_primaries) { .red = {0.713, 0.293}, .green = {0.165, 0.830}, @@ -522,20 +395,20 @@ struct mp_csp_primaries mp_get_csp_primaries(enum mp_csp_prim spc) // Get the nominal peak for a given colorspace, relative to the reference white // level. In other words, this returns the brightest encodable value that can // be represented by a given transfer curve. -float mp_trc_nom_peak(enum mp_csp_trc trc) +float mp_trc_nom_peak(enum pl_color_transfer trc) { switch (trc) { - case MP_CSP_TRC_PQ: return 10000.0 / MP_REF_WHITE; - case MP_CSP_TRC_HLG: return 12.0 / MP_REF_WHITE_HLG; - case MP_CSP_TRC_V_LOG: return 46.0855; - case MP_CSP_TRC_S_LOG1: return 6.52; - case MP_CSP_TRC_S_LOG2: return 9.212; + case PL_COLOR_TRC_PQ: return 10000.0 / MP_REF_WHITE; + case PL_COLOR_TRC_HLG: return 12.0 / MP_REF_WHITE_HLG; + case PL_COLOR_TRC_V_LOG: return 46.0855; + case PL_COLOR_TRC_S_LOG1: return 6.52; + case PL_COLOR_TRC_S_LOG2: return 9.212; } return 1.0; } -bool mp_trc_is_hdr(enum mp_csp_trc trc) +bool mp_trc_is_hdr(enum pl_color_transfer trc) { return mp_trc_nom_peak(trc) > 1.0; } @@ -660,7 +533,7 @@ static void mp_get_xyz2rgb_coeffs(struct mp_csp_params *params, enum mp_render_intent intent, struct mp_cmat *m) { // Convert to DCI-P3 - struct mp_csp_primaries prim = mp_get_csp_primaries(MP_CSP_PRIM_DCI_P3); + struct mp_csp_primaries prim = mp_get_csp_primaries(PL_COLOR_PRIM_DCI_P3); float brightness = params->brightness; mp_get_rgb2xyz_matrix(prim, m->m); mp_invert_matrix3x3(m->m); @@ -685,7 +558,7 @@ static void mp_get_xyz2rgb_coeffs(struct mp_csp_params *params, // Get multiplication factor required if image data is fit within the LSBs of a // higher smaller bit depth fixed-point texture data. // This is broken. Use mp_get_csp_uint_mul(). -double mp_get_csp_mul(enum mp_csp csp, int input_bits, int texture_bits) +double mp_get_csp_mul(enum pl_color_system csp, int input_bits, int texture_bits) { assert(texture_bits >= input_bits); @@ -694,10 +567,10 @@ double mp_get_csp_mul(enum mp_csp csp, int input_bits, int texture_bits) return 1; // RGB always uses the full range available. - if (csp == MP_CSP_RGB) + if (csp == PL_COLOR_SYSTEM_RGB) return ((1LL << input_bits) - 1.) / ((1LL << texture_bits) - 1.); - if (csp == MP_CSP_XYZ) + if (csp == PL_COLOR_SYSTEM_XYZ) return 1; // High bit depth YUV uses a range shifted from 8 bit. @@ -716,24 +589,24 @@ double mp_get_csp_mul(enum mp_csp csp, int input_bits, int texture_bits) // bits: number of significant bits, e.g. 10 for yuv420p10, 16 for p010 // out_m: returns factor to multiply the uint number with // out_o: returns offset to add after multiplication -void mp_get_csp_uint_mul(enum mp_csp csp, enum mp_csp_levels levels, +void mp_get_csp_uint_mul(enum pl_color_system csp, enum pl_color_levels levels, int bits, int component, double *out_m, double *out_o) { uint16_t i_min = 0; uint16_t i_max = (1u << bits) - 1; double f_min = 0; // min. float value - if (csp != MP_CSP_RGB && component != 4) { + if (csp != PL_COLOR_SYSTEM_RGB && component != 4) { if (component == 2 || component == 3) { f_min = (1u << (bits - 1)) / -(double)i_max; // force center => 0 - if (levels != MP_CSP_LEVELS_PC && bits >= 8) { + if (levels != PL_COLOR_LEVELS_FULL && bits >= 8) { i_min = 16 << (bits - 8); // => -0.5 i_max = 240 << (bits - 8); // => 0.5 f_min = -0.5; } } else { - if (levels != MP_CSP_LEVELS_PC && bits >= 8) { + if (levels != PL_COLOR_LEVELS_FULL && bits >= 8) { i_min = 16 << (bits - 8); // => 0 i_max = 235 << (bits - 8); // => 1 } @@ -778,19 +651,19 @@ static void luma_coeffs(struct mp_cmat *mat, float lr, float lg, float lb) // get the coefficients of the yuv -> rgb conversion matrix void mp_get_csp_matrix(struct mp_csp_params *params, struct mp_cmat *m) { - enum mp_csp colorspace = params->color.space; - if (colorspace <= MP_CSP_AUTO || colorspace >= MP_CSP_COUNT) - colorspace = MP_CSP_BT_601; - enum mp_csp_levels levels_in = params->color.levels; - if (levels_in <= MP_CSP_LEVELS_AUTO || levels_in >= MP_CSP_LEVELS_COUNT) - levels_in = MP_CSP_LEVELS_TV; + enum pl_color_system colorspace = params->repr.sys; + if (colorspace <= PL_COLOR_SYSTEM_UNKNOWN || colorspace >= PL_COLOR_SYSTEM_COUNT) + colorspace = PL_COLOR_SYSTEM_BT_601; + enum pl_color_levels levels_in = params->repr.levels; + if (levels_in <= PL_COLOR_LEVELS_UNKNOWN || levels_in >= PL_COLOR_LEVELS_COUNT) + levels_in = PL_COLOR_LEVELS_LIMITED; switch (colorspace) { - case MP_CSP_BT_601: luma_coeffs(m, 0.299, 0.587, 0.114 ); break; - case MP_CSP_BT_709: luma_coeffs(m, 0.2126, 0.7152, 0.0722); break; - case MP_CSP_SMPTE_240M: luma_coeffs(m, 0.2122, 0.7013, 0.0865); break; - case MP_CSP_BT_2020_NC: luma_coeffs(m, 0.2627, 0.6780, 0.0593); break; - case MP_CSP_BT_2020_C: { + case PL_COLOR_SYSTEM_BT_601: luma_coeffs(m, 0.299, 0.587, 0.114 ); break; + case PL_COLOR_SYSTEM_BT_709: luma_coeffs(m, 0.2126, 0.7152, 0.0722); break; + case PL_COLOR_SYSTEM_SMPTE_240M: luma_coeffs(m, 0.2122, 0.7013, 0.0865); break; + case PL_COLOR_SYSTEM_BT_2020_NC: luma_coeffs(m, 0.2627, 0.6780, 0.0593); break; + case PL_COLOR_SYSTEM_BT_2020_C: { // Note: This outputs into the [-0.5,0.5] range for chroma information. // If this clips on any VO, a constant 0.5 coefficient can be added // to the chroma channels to normalize them into [0,1]. This is not @@ -798,12 +671,12 @@ void mp_get_csp_matrix(struct mp_csp_params *params, struct mp_cmat *m) *m = (struct mp_cmat){{{0, 0, 1}, {1, 0, 0}, {0, 1, 0}}}; break; } - case MP_CSP_RGB: { + case PL_COLOR_SYSTEM_RGB: { *m = (struct mp_cmat){{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}}; levels_in = -1; break; } - case MP_CSP_XYZ: { + case PL_COLOR_SYSTEM_XYZ: { // The vo should probably not be using a matrix generated by this // function for XYZ sources, but if it does, let's just convert it to // an equivalent RGB space based on the colorimetry metadata it @@ -813,7 +686,7 @@ void mp_get_csp_matrix(struct mp_csp_params *params, struct mp_cmat *m) levels_in = -1; break; } - case MP_CSP_YCGCO: { + case PL_COLOR_SYSTEM_YCGCO: { *m = (struct mp_cmat) { {{1, -1, 1}, {1, 1, 0}, @@ -828,8 +701,8 @@ void mp_get_csp_matrix(struct mp_csp_params *params, struct mp_cmat *m) if (params->is_float) levels_in = -1; - if ((colorspace == MP_CSP_BT_601 || colorspace == MP_CSP_BT_709 || - colorspace == MP_CSP_SMPTE_240M || colorspace == MP_CSP_BT_2020_NC)) + if ((colorspace == PL_COLOR_SYSTEM_BT_601 || colorspace == PL_COLOR_SYSTEM_BT_709 || + colorspace == PL_COLOR_SYSTEM_SMPTE_240M || colorspace == PL_COLOR_SYSTEM_BT_2020_NC)) { // Hue is equivalent to rotating input [U, V] subvector around the origin. // Saturation scales [U, V]. @@ -855,23 +728,23 @@ void mp_get_csp_matrix(struct mp_csp_params *params, struct mp_cmat *m) anyfull = { 0*s, 255*s, 255*s/2, 0 }, // cmax picked to make cmul=ymul yuvlev; switch (levels_in) { - case MP_CSP_LEVELS_TV: yuvlev = yuvlim; break; - case MP_CSP_LEVELS_PC: yuvlev = yuvfull; break; + case PL_COLOR_LEVELS_LIMITED: yuvlev = yuvlim; break; + case PL_COLOR_LEVELS_FULL: yuvlev = yuvfull; break; case -1: yuvlev = anyfull; break; default: MP_ASSERT_UNREACHABLE(); } int levels_out = params->levels_out; - if (levels_out <= MP_CSP_LEVELS_AUTO || levels_out >= MP_CSP_LEVELS_COUNT) - levels_out = MP_CSP_LEVELS_PC; + if (levels_out <= PL_COLOR_LEVELS_UNKNOWN || levels_out >= PL_COLOR_LEVELS_COUNT) + levels_out = PL_COLOR_LEVELS_FULL; struct rgblevels { double min, max; } rgblim = { 16/255., 235/255. }, rgbfull = { 0, 1 }, rgblev; switch (levels_out) { - case MP_CSP_LEVELS_TV: rgblev = rgblim; break; - case MP_CSP_LEVELS_PC: rgblev = rgbfull; break; + case PL_COLOR_LEVELS_LIMITED: rgblev = rgblim; break; + case PL_COLOR_LEVELS_FULL: rgblev = rgbfull; break; default: MP_ASSERT_UNREACHABLE(); } @@ -904,16 +777,6 @@ void mp_csp_set_image_params(struct mp_csp_params *params, params->color = p.color; } -bool mp_colorspace_equal(struct mp_colorspace c1, struct mp_colorspace c2) -{ - return c1.space == c2.space && - c1.levels == c2.levels && - c1.primaries == c2.primaries && - c1.gamma == c2.gamma && - c1.light == c2.light && - pl_hdr_metadata_equal(&c1.hdr, &c2.hdr); -} - enum mp_csp_equalizer_param { MP_CSP_EQ_BRIGHTNESS, MP_CSP_EQ_CONTRAST, @@ -946,7 +809,7 @@ const struct m_sub_options mp_csp_equalizer_conf = { {"gamma", OPT_FLOAT(values[MP_CSP_EQ_GAMMA]), M_RANGE(-100, 100)}, {"video-output-levels", - OPT_CHOICE_C(output_levels, mp_csp_levels_names)}, + OPT_CHOICE_C(output_levels, pl_csp_levels_names)}, {0} }, .size = sizeof(struct mp_csp_equalizer_opts), diff --git a/video/csputils.h b/video/csputils.h index 3a904cbf3861..80901659cf3c 100644 --- a/video/csputils.h +++ b/video/csputils.h @@ -30,76 +30,10 @@ * nonzero at vf/vo level. */ -enum mp_csp { - MP_CSP_AUTO, - MP_CSP_BT_601, - MP_CSP_BT_709, - MP_CSP_SMPTE_240M, - MP_CSP_BT_2020_NC, - MP_CSP_BT_2020_C, - MP_CSP_RGB, - MP_CSP_XYZ, - MP_CSP_YCGCO, - MP_CSP_COUNT -}; - -extern const struct m_opt_choice_alternatives mp_csp_names[]; - -enum mp_csp_levels { - MP_CSP_LEVELS_AUTO, - MP_CSP_LEVELS_TV, - MP_CSP_LEVELS_PC, - MP_CSP_LEVELS_COUNT, -}; - -extern const struct m_opt_choice_alternatives mp_csp_levels_names[]; - -enum mp_csp_prim { - MP_CSP_PRIM_AUTO, - MP_CSP_PRIM_BT_601_525, - MP_CSP_PRIM_BT_601_625, - MP_CSP_PRIM_BT_709, - MP_CSP_PRIM_BT_2020, - MP_CSP_PRIM_BT_470M, - MP_CSP_PRIM_APPLE, - MP_CSP_PRIM_ADOBE, - MP_CSP_PRIM_PRO_PHOTO, - MP_CSP_PRIM_CIE_1931, - MP_CSP_PRIM_DCI_P3, - MP_CSP_PRIM_DISPLAY_P3, - MP_CSP_PRIM_V_GAMUT, - MP_CSP_PRIM_S_GAMUT, - MP_CSP_PRIM_EBU_3213, - MP_CSP_PRIM_FILM_C, - MP_CSP_PRIM_ACES_AP0, - MP_CSP_PRIM_ACES_AP1, - MP_CSP_PRIM_COUNT -}; - -extern const struct m_opt_choice_alternatives mp_csp_prim_names[]; - -enum mp_csp_trc { - MP_CSP_TRC_AUTO, - MP_CSP_TRC_BT_1886, - MP_CSP_TRC_SRGB, - MP_CSP_TRC_LINEAR, - MP_CSP_TRC_GAMMA18, - MP_CSP_TRC_GAMMA20, - MP_CSP_TRC_GAMMA22, - MP_CSP_TRC_GAMMA24, - MP_CSP_TRC_GAMMA26, - MP_CSP_TRC_GAMMA28, - MP_CSP_TRC_PRO_PHOTO, - MP_CSP_TRC_PQ, - MP_CSP_TRC_HLG, - MP_CSP_TRC_V_LOG, - MP_CSP_TRC_S_LOG1, - MP_CSP_TRC_S_LOG2, - MP_CSP_TRC_ST428, - MP_CSP_TRC_COUNT -}; - -extern const struct m_opt_choice_alternatives mp_csp_trc_names[]; +extern const struct m_opt_choice_alternatives pl_csp_names[]; +extern const struct m_opt_choice_alternatives pl_csp_levels_names[]; +extern const struct m_opt_choice_alternatives pl_csp_prim_names[]; +extern const struct m_opt_choice_alternatives pl_csp_trc_names[]; enum mp_csp_light { MP_CSP_LIGHT_AUTO, @@ -141,15 +75,6 @@ extern const struct m_opt_choice_alternatives mp_stereo3d_names[]; #define MP_STEREO3D_NAME_DEF(x, def) \ (MP_STEREO3D_NAME(x) ? MP_STEREO3D_NAME(x) : (def)) -struct mp_colorspace { - enum mp_csp space; - enum mp_csp_levels levels; - enum mp_csp_prim primaries; - enum mp_csp_trc gamma; - enum mp_csp_light light; - struct pl_hdr_metadata hdr; -}; - // For many colorspace conversions, in particular those involving HDR, an // implicit reference white level is needed. Since this magic constant shows up // a lot, give it an explicit name. The value of 203 cd/m² comes from ITU-R @@ -158,12 +83,10 @@ struct mp_colorspace { #define MP_REF_WHITE 203.0 #define MP_REF_WHITE_HLG 3.17955 -// Replaces unknown values in the first struct by those of the second struct -void mp_colorspace_merge(struct mp_colorspace *orig, struct mp_colorspace *new); - struct mp_csp_params { - struct mp_colorspace color; // input colorspace - enum mp_csp_levels levels_out; // output device + struct pl_color_repr repr; + struct pl_color_space color; + enum pl_color_levels levels_out; // output device float brightness; float contrast; float hue; @@ -179,9 +102,8 @@ struct mp_csp_params { }; #define MP_CSP_PARAMS_DEFAULTS { \ - .color = { .space = MP_CSP_BT_601, \ - .levels = MP_CSP_LEVELS_TV }, \ - .levels_out = MP_CSP_LEVELS_PC, \ + .repr = pl_color_repr_sdtv, \ + .levels_out = PL_COLOR_LEVELS_FULL, \ .brightness = 0, .contrast = 1, .hue = 0, .saturation = 1, \ .gamma = 1, .texture_bits = 8, .input_bits = 8} @@ -189,8 +111,6 @@ struct mp_image_params; void mp_csp_set_image_params(struct mp_csp_params *params, const struct mp_image_params *imgparams); -bool mp_colorspace_equal(struct mp_colorspace c1, struct mp_colorspace c2); - enum mp_chroma_location { MP_CHROMA_AUTO, MP_CHROMA_TOPLEFT, // uhd @@ -234,26 +154,16 @@ struct mp_csp_primaries { struct mp_csp_col_xy red, green, blue, white; }; -enum mp_csp avcol_spc_to_mp_csp(int avcolorspace); -enum mp_csp_levels avcol_range_to_mp_csp_levels(int avrange); -enum mp_csp_prim avcol_pri_to_mp_csp_prim(int avpri); -enum mp_csp_trc avcol_trc_to_mp_csp_trc(int avtrc); - -int mp_csp_to_avcol_spc(enum mp_csp colorspace); -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); +enum pl_color_system mp_csp_guess_colorspace(int width, int height); +enum pl_color_primaries mp_csp_guess_primaries(int width, int height); enum mp_chroma_location avchroma_location_to_mp(int avloc); int mp_chroma_location_to_av(enum mp_chroma_location mploc); void mp_get_chroma_location(enum mp_chroma_location loc, int *x, int *y); -struct mp_csp_primaries mp_get_csp_primaries(enum mp_csp_prim csp); -float mp_trc_nom_peak(enum mp_csp_trc trc); -bool mp_trc_is_hdr(enum mp_csp_trc trc); +struct mp_csp_primaries mp_get_csp_primaries(enum pl_color_primaries csp); +float mp_trc_nom_peak(enum pl_color_transfer trc); +bool mp_trc_is_hdr(enum pl_color_transfer trc); /* Color conversion matrix: RGB = m * YUV + c * m is in row-major matrix, with m[row][col], e.g.: @@ -277,8 +187,8 @@ void mp_get_rgb2xyz_matrix(struct mp_csp_primaries space, float m[3][3]); void mp_get_cms_matrix(struct mp_csp_primaries src, struct mp_csp_primaries dest, enum mp_render_intent intent, float cms_matrix[3][3]); -double mp_get_csp_mul(enum mp_csp csp, int input_bits, int texture_bits); -void mp_get_csp_uint_mul(enum mp_csp csp, enum mp_csp_levels levels, +double mp_get_csp_mul(enum pl_color_system csp, int input_bits, int texture_bits); +void mp_get_csp_uint_mul(enum pl_color_system csp, enum pl_color_levels levels, int bits, int component, double *out_m, double *out_o); void mp_get_csp_matrix(struct mp_csp_params *params, struct mp_cmat *out); diff --git a/video/filter/vf_d3d11vpp.c b/video/filter/vf_d3d11vpp.c index 3f00c5aa4dca..d63acd11ce0a 100644 --- a/video/filter/vf_d3d11vpp.c +++ b/video/filter/vf_d3d11vpp.c @@ -210,8 +210,8 @@ static int recreate_video_proc(struct mp_filter *vf) FALSE, 0); D3D11_VIDEO_PROCESSOR_COLOR_SPACE csp = { - .YCbCr_Matrix = p->params.color.space != MP_CSP_BT_601, - .Nominal_Range = p->params.color.levels == MP_CSP_LEVELS_TV ? 1 : 2, + .YCbCr_Matrix = p->params.repr.sys != PL_COLOR_SYSTEM_BT_601, + .Nominal_Range = p->params.repr.levels == PL_COLOR_LEVELS_LIMITED ? 1 : 2, }; ID3D11VideoContext_VideoProcessorSetStreamColorSpace(p->video_ctx, p->video_proc, diff --git a/video/filter/vf_fingerprint.c b/video/filter/vf_fingerprint.c index 8714382ff360..87248193d621 100644 --- a/video/filter/vf_fingerprint.c +++ b/video/filter/vf_fingerprint.c @@ -104,7 +104,7 @@ static void f_process(struct mp_filter *f) // "portable" across source video. p->scaled->params.color = mpi->params.color; // Make output always full range; no reason to lose precision. - p->scaled->params.color.levels = MP_CSP_LEVELS_PC; + p->scaled->params.repr.levels = PL_COLOR_LEVELS_FULL; if (!mp_zimg_convert(p->zimg, p->scaled, mpi)) { if (!p->fallback_warning) { diff --git a/video/filter/vf_format.c b/video/filter/vf_format.c index 4997d6f17371..4a14fc91024d 100644 --- a/video/filter/vf_format.c +++ b/video/filter/vf_format.c @@ -65,26 +65,26 @@ static void set_params(struct vf_format_opts *p, struct mp_image_params *out, bool set_size) { if (p->colormatrix) - out->color.space = p->colormatrix; + out->repr.sys = p->colormatrix; if (p->colorlevels) - out->color.levels = p->colorlevels; + out->repr.levels = p->colorlevels; if (p->primaries) out->color.primaries = p->primaries; if (p->gamma) { - enum mp_csp_trc in_gamma = p->gamma; - out->color.gamma = p->gamma; - if (in_gamma != out->color.gamma) { + enum pl_color_transfer in_gamma = p->gamma; + out->color.transfer = p->gamma; + if (in_gamma != out->color.transfer) { // When changing the gamma function explicitly, also reset stuff // related to the gamma function since that information will almost // surely be false now and have to be re-inferred out->color.hdr = (struct pl_hdr_metadata){0}; - out->color.light = MP_CSP_LIGHT_AUTO; + out->light = MP_CSP_LIGHT_AUTO; } } if (p->sig_peak) out->color.hdr = (struct pl_hdr_metadata){ .max_luma = p->sig_peak * MP_REF_WHITE }; if (p->light) - out->color.light = p->light; + out->light = p->light; if (p->chroma_location) out->chroma_location = p->chroma_location; if (p->stereo_in) @@ -122,10 +122,10 @@ static void vf_format_process(struct mp_filter *f) int outfmt = priv->opts->fmt; // If we convert from RGB to YUV, default to limited range. - if (mp_imgfmt_get_forced_csp(img->imgfmt) == MP_CSP_RGB && - outfmt && mp_imgfmt_get_forced_csp(outfmt) == MP_CSP_AUTO) + if (mp_imgfmt_get_forced_csp(img->imgfmt) == PL_COLOR_SYSTEM_RGB && + outfmt && mp_imgfmt_get_forced_csp(outfmt) == PL_COLOR_SYSTEM_UNKNOWN) { - par.color.levels = MP_CSP_LEVELS_TV; + par.repr.levels = PL_COLOR_LEVELS_LIMITED; } set_params(priv->opts, &par, true); @@ -204,10 +204,10 @@ static struct mp_filter *vf_format_create(struct mp_filter *parent, void *option #define OPT_BASE_STRUCT struct vf_format_opts static const m_option_t vf_opts_fields[] = { {"fmt", OPT_IMAGEFORMAT(fmt)}, - {"colormatrix", OPT_CHOICE_C(colormatrix, mp_csp_names)}, - {"colorlevels", OPT_CHOICE_C(colorlevels, mp_csp_levels_names)}, - {"primaries", OPT_CHOICE_C(primaries, mp_csp_prim_names)}, - {"gamma", OPT_CHOICE_C(gamma, mp_csp_trc_names)}, + {"colormatrix", OPT_CHOICE_C(colormatrix, pl_csp_names)}, + {"colorlevels", OPT_CHOICE_C(colorlevels, pl_csp_levels_names)}, + {"primaries", OPT_CHOICE_C(primaries, pl_csp_prim_names)}, + {"gamma", OPT_CHOICE_C(gamma, pl_csp_trc_names)}, {"sig-peak", OPT_FLOAT(sig_peak)}, {"light", OPT_CHOICE_C(light, mp_csp_light_names)}, {"chroma-location", OPT_CHOICE_C(chroma_location, mp_chroma_names)}, diff --git a/video/filter/vf_vapoursynth.c b/video/filter/vf_vapoursynth.c index 583a196f3b42..5a3ce423d1d7 100644 --- a/video/filter/vf_vapoursynth.c +++ b/video/filter/vf_vapoursynth.c @@ -27,6 +27,7 @@ #include <libavutil/rational.h> #include <libavutil/cpu.h> +#include <libplacebo/utils/libav.h> #include "common/msg.h" #include "filters/f_autoconvert.h" @@ -184,13 +185,13 @@ static void copy_mp_to_vs_frame_props_map(struct priv *p, VSMap *map, struct mp_image_params *params = &img->params; p->vsapi->propSetInt(map, "_SARNum", params->p_w, 0); p->vsapi->propSetInt(map, "_SARDen", params->p_h, 0); - if (params->color.levels) { + if (params->repr.levels) { p->vsapi->propSetInt(map, "_ColorRange", - params->color.levels == MP_CSP_LEVELS_TV, 0); + params->repr.levels == PL_COLOR_LEVELS_LIMITED, 0); } // The docs explicitly say it uses libavcodec values. p->vsapi->propSetInt(map, "_ColorSpace", - mp_csp_to_avcol_spc(params->color.space), 0); + pl_system_to_av(params->repr.sys), 0); if (params->chroma_location) { p->vsapi->propSetInt(map, "_ChromaLocation", params->chroma_location == MP_CHROMA_CENTER, 0); diff --git a/video/filter/vf_vavpp.c b/video/filter/vf_vavpp.c index 52be14811174..f70fe1f4a6d3 100644 --- a/video/filter/vf_vavpp.c +++ b/video/filter/vf_vavpp.c @@ -208,7 +208,7 @@ static struct mp_image *render(struct mp_filter *vf) mp_image_copy_attributes(img, in); - unsigned int flags = va_get_colorspace_flag(p->params.color.space); + unsigned int flags = va_get_colorspace_flag(p->params.repr.sys); if (!mp_refqueue_should_deint(p->queue)) { flags |= VA_FRAME_PICTURE; } else if (mp_refqueue_is_top_field(p->queue)) { diff --git a/video/image_writer.c b/video/image_writer.c index 288d809be4c1..df43830d7900 100644 --- a/video/image_writer.c +++ b/video/image_writer.c @@ -25,6 +25,7 @@ #include <libavutil/mem.h> #include <libavutil/opt.h> #include <libavutil/pixdesc.h> +#include <libplacebo/utils/libav.h> #include "common/msg.h" #include "config.h" @@ -137,16 +138,16 @@ static void prepare_avframe(AVFrame *pic, AVCodecContext *avctx, pic->width = avctx->width; pic->height = avctx->height; avctx->color_range = pic->color_range = - mp_csp_levels_to_avcol_range(image->params.color.levels); + pl_levels_to_av(image->params.repr.levels); if (!tag_csp) return; avctx->color_primaries = pic->color_primaries = - mp_csp_prim_to_avcol_pri(image->params.color.primaries); + pl_primaries_to_av(image->params.color.primaries); avctx->color_trc = pic->color_trc = - mp_csp_trc_to_avcol_trc(image->params.color.gamma); + pl_transfer_to_av(image->params.color.transfer); avctx->colorspace = pic->colorspace = - mp_csp_to_avcol_spc(image->params.color.space); + pl_system_to_av(image->params.repr.sys); avctx->chroma_sample_location = pic->chroma_location = mp_chroma_location_to_av(image->params.chroma_location); mp_dbg(log, "mapped color params:\n" @@ -195,7 +196,7 @@ static bool write_lavc(struct image_writer_ctx *ctx, mp_image_t *image, const ch avctx->pix_fmt = imgfmt2pixfmt(image->imgfmt); if (codec->id == AV_CODEC_ID_MJPEG) { // Annoying deprecated garbage for the jpg encoder. - if (image->params.color.levels == MP_CSP_LEVELS_PC) + if (image->params.repr.levels == PL_COLOR_LEVELS_FULL) avctx->pix_fmt = replace_j_format(avctx->pix_fmt); } if (avctx->pix_fmt == AV_PIX_FMT_NONE) { @@ -616,7 +617,7 @@ int image_writer_format_from_ext(const char *ext) } static struct mp_image *convert_image(struct mp_image *image, int destfmt, - enum mp_csp_levels yuv_levels, + enum pl_color_levels yuv_levels, const struct image_writer_opts *opts, struct mpv_global *global, struct mp_log *log) @@ -636,13 +637,13 @@ static struct mp_image *convert_image(struct mp_image *image, int destfmt, if (!image_writer_flexible_csp(opts)) { // If our format can't tag csps, set something sane - p.color.primaries = MP_CSP_PRIM_BT_709; - p.color.gamma = MP_CSP_TRC_AUTO; - p.color.light = MP_CSP_LIGHT_DISPLAY; + p.color.primaries = PL_COLOR_PRIM_BT_709; + p.color.transfer = PL_COLOR_TRC_UNKNOWN; + p.light = MP_CSP_LIGHT_DISPLAY; p.color.hdr = (struct pl_hdr_metadata){0}; - if (p.color.space != MP_CSP_RGB) { - p.color.levels = yuv_levels; - p.color.space = MP_CSP_BT_601; + if (p.repr.sys != PL_COLOR_SYSTEM_RGB) { + p.repr.levels = yuv_levels; + p.repr.sys = PL_COLOR_SYSTEM_BT_601; p.chroma_location = MP_CHROMA_CENTER; } mp_image_params_guess_csp(&p); @@ -730,11 +731,11 @@ bool write_image(struct mp_image *image, const struct image_writer_opts *opts, if (!destfmt) destfmt = get_target_format(&ctx); - enum mp_csp_levels levels; // Ignored if destfmt is a RGB format + enum pl_color_levels levels; // Ignored if destfmt is a RGB format if (opts->format == AV_CODEC_ID_WEBP) { - levels = MP_CSP_LEVELS_TV; + levels = PL_COLOR_LEVELS_LIMITED; } else { - levels = MP_CSP_LEVELS_PC; + levels = PL_COLOR_LEVELS_FULL; } struct mp_image *dst = convert_image(image, destfmt, levels, opts, global, log); diff --git a/video/img_format.c b/video/img_format.c index 6b7857f0b4c1..c9e2a3c0e647 100644 --- a/video/img_format.c +++ b/video/img_format.c @@ -664,18 +664,18 @@ static bool validate_regular_imgfmt(const struct mp_regular_imgfmt *fmt) return true; } -static enum mp_csp get_forced_csp_from_flags(int flags) +static enum pl_color_system get_forced_csp_from_flags(int flags) { if (flags & MP_IMGFLAG_COLOR_XYZ) - return MP_CSP_XYZ; + return PL_COLOR_SYSTEM_XYZ; if (flags & MP_IMGFLAG_COLOR_RGB) - return MP_CSP_RGB; + return PL_COLOR_SYSTEM_RGB; - return MP_CSP_AUTO; + return PL_COLOR_SYSTEM_UNKNOWN; } -enum mp_csp mp_imgfmt_get_forced_csp(int imgfmt) +enum pl_color_system mp_imgfmt_get_forced_csp(int imgfmt) { return get_forced_csp_from_flags(mp_imgfmt_get_desc(imgfmt).flags); } diff --git a/video/img_format.h b/video/img_format.h index 075382936690..e342de65dad6 100644 --- a/video/img_format.h +++ b/video/img_format.h @@ -155,9 +155,9 @@ int mp_imgfmt_desc_get_num_comps(struct mp_imgfmt_desc *desc); // luma pixel. luma_offsets[0] == mp_imgfmt_desc.comps[0].offset. bool mp_imgfmt_get_packed_yuv_locations(int imgfmt, uint8_t *luma_offsets); -// MP_CSP_AUTO for YUV, MP_CSP_RGB or MP_CSP_XYZ otherwise. +// PL_COLOR_SYSTEM_UNKNOWN for YUV, PL_COLOR_SYSTEM_RGB or PL_COLOR_SYSTEM_XYZ otherwise. // (Because IMGFMT/AV_PIX_FMT conflate format and csp for RGB and XYZ.) -enum mp_csp mp_imgfmt_get_forced_csp(int imgfmt); +enum pl_color_system mp_imgfmt_get_forced_csp(int imgfmt); enum mp_component_type { MP_COMPONENT_TYPE_UNKNOWN = 0, @@ -184,7 +184,7 @@ struct mp_regular_imgfmt { // See mp_imgfmt_get_forced_csp(). Normally code should use // mp_image_params.colors. This field is only needed to map the format // unambiguously to FFmpeg formats. - enum mp_csp forced_csp; + enum pl_color_system forced_csp; // Size of each component in bytes. uint8_t component_size; diff --git a/video/mp_image.c b/video/mp_image.c index dff2051d392e..ed7543b8ff76 100644 --- a/video/mp_image.c +++ b/video/mp_image.c @@ -493,7 +493,7 @@ void mp_image_copy(struct mp_image *dst, struct mp_image *src) memcpy(dst->planes[1], src->planes[1], AVPALETTE_SIZE); } -static enum mp_csp mp_image_params_get_forced_csp(struct mp_image_params *params) +static enum pl_color_system mp_image_params_get_forced_csp(struct mp_image_params *params) { int imgfmt = params->hw_subfmt ? params->hw_subfmt : params->imgfmt; return mp_imgfmt_get_forced_csp(imgfmt); @@ -522,15 +522,17 @@ void mp_image_copy_attributes(struct mp_image *dst, struct mp_image *src) dst->params.p_w = src->params.p_w; dst->params.p_h = src->params.p_h; dst->params.color = src->params.color; + dst->params.repr = src->params.repr; + dst->params.light = src->params.light; dst->params.chroma_location = src->params.chroma_location; dst->params.alpha = src->params.alpha; dst->params.crop = src->params.crop; dst->nominal_fps = src->nominal_fps; // ensure colorspace consistency - enum mp_csp dst_forced_csp = mp_image_params_get_forced_csp(&dst->params); + enum pl_color_system dst_forced_csp = mp_image_params_get_forced_csp(&dst->params); if (mp_image_params_get_forced_csp(&src->params) != dst_forced_csp) { - dst->params.color.space = dst_forced_csp != MP_CSP_AUTO ? + dst->params.repr.sys = dst_forced_csp != PL_COLOR_SYSTEM_UNKNOWN ? dst_forced_csp : mp_csp_guess_colorspace(src->w, src->h); } @@ -670,8 +672,8 @@ void mp_image_clear(struct mp_image *img, int x0, int y0, int x1, int y1) plane_size[cd->plane] = plane_bits / 8u; int depth = cd->size + MPMIN(cd->pad, 0); double m, o; - mp_get_csp_uint_mul(area.params.color.space, - area.params.color.levels, + mp_get_csp_uint_mul(area.params.repr.sys, + area.params.repr.levels, depth, c + 1, &m, &o); uint64_t val = MPCLAMP(lrint((0 - o) / m), 0, 1ull << depth); plane_clear_i[cd->plane] |= val << cd->offset; @@ -773,11 +775,11 @@ char *mp_image_params_to_str_buf(char *b, size_t bs, if (p->hw_subfmt) mp_snprintf_cat(b, bs, "[%s]", mp_imgfmt_to_name(p->hw_subfmt)); mp_snprintf_cat(b, bs, " %s/%s/%s/%s/%s", - m_opt_choice_str(mp_csp_names, p->color.space), - m_opt_choice_str(mp_csp_prim_names, p->color.primaries), - m_opt_choice_str(mp_csp_trc_names, p->color.gamma), - m_opt_choice_str(mp_csp_levels_names, p->color.levels), - m_opt_choice_str(mp_csp_light_names, p->color.light)); + m_opt_choice_str(pl_csp_names, p->repr.sys), + m_opt_choice_str(pl_csp_prim_names, p->color.primaries), + m_opt_choice_str(pl_csp_trc_names, p->color.transfer), + m_opt_choice_str(pl_csp_levels_names, p->repr.levels), + m_opt_choice_str(mp_csp_light_names, p->light)); mp_snprintf_cat(b, bs, " CL=%s", m_opt_choice_str(mp_chroma_names, p->chroma_location)); if (mp_image_crop_valid(p)) { @@ -836,7 +838,9 @@ bool mp_image_params_equal(const struct mp_image_params *p1, p1->w == p2->w && p1->h == p2->h && p1->p_w == p2->p_w && p1->p_h == p2->p_h && p1->force_window == p2->force_window && - mp_colorspace_equal(p1->color, p2->color) && + pl_color_space_equal(&p1->color, &p2->color) && + pl_color_repr_equal(&p1->repr, &p2->repr) && + p1->light == p2->light && p1->chroma_location == p2->chroma_location && p1->rotate == p2->rotate && p1->stereo3d == p2->stereo3d && @@ -854,11 +858,11 @@ void mp_image_set_attributes(struct mp_image *image, nparams.w = image->w; nparams.h = image->h; if (nparams.imgfmt != params->imgfmt) - nparams.color = (struct mp_colorspace){0}; + nparams.color = (struct pl_color_space){0}; mp_image_set_params(image, &nparams); } -static enum mp_csp_levels infer_levels(enum mp_imgfmt imgfmt) +static enum pl_color_levels infer_levels(enum mp_imgfmt imgfmt) { switch (imgfmt2pixfmt(imgfmt)) { case AV_PIX_FMT_YUVJ420P: @@ -880,9 +884,9 @@ static enum mp_csp_levels infer_levels(enum mp_imgfmt imgfmt) case AV_PIX_FMT_GRAY16BE: case AV_PIX_FMT_YA16BE: case AV_PIX_FMT_YA16LE: - return MP_CSP_LEVELS_PC; + return PL_COLOR_LEVELS_FULL; default: - return MP_CSP_LEVELS_TV; + return PL_COLOR_LEVELS_LIMITED; } } @@ -891,100 +895,100 @@ static enum mp_csp_levels infer_levels(enum mp_imgfmt imgfmt) // the colorspace as implied by the pixel format. void mp_image_params_guess_csp(struct mp_image_params *params) { - enum mp_csp forced_csp = mp_image_params_get_forced_csp(params); - if (forced_csp == MP_CSP_AUTO) { // YUV/other - if (params->color.space != MP_CSP_BT_601 && - params->color.space != MP_CSP_BT_709 && - params->color.space != MP_CSP_BT_2020_NC && - params->color.space != MP_CSP_BT_2020_C && - params->color.space != MP_CSP_SMPTE_240M && - params->color.space != MP_CSP_YCGCO) + enum pl_color_system forced_csp = mp_image_params_get_forced_csp(params); + if (forced_csp == PL_COLOR_SYSTEM_UNKNOWN) { // YUV/other + if (params->repr.sys != PL_COLOR_SYSTEM_BT_601 && + params->repr.sys != PL_COLOR_SYSTEM_BT_709 && + params->repr.sys != PL_COLOR_SYSTEM_BT_2020_NC && + params->repr.sys != PL_COLOR_SYSTEM_BT_2020_C && + params->repr.sys != PL_COLOR_SYSTEM_SMPTE_240M && + params->repr.sys != PL_COLOR_SYSTEM_YCGCO) { // Makes no sense, so guess instead // YCGCO should be separate, but libavcodec disagrees - params->color.space = MP_CSP_AUTO; + params->repr.sys = PL_COLOR_SYSTEM_UNKNOWN; } - if (params->color.space == MP_CSP_AUTO) - params->color.space = mp_csp_guess_colorspace(params->w, params->h); - if (params->color.levels == MP_CSP_LEVELS_AUTO) { - if (params->color.gamma == MP_CSP_TRC_V_LOG) { - params->color.levels = MP_CSP_LEVELS_PC; + if (params->repr.sys == PL_COLOR_SYSTEM_UNKNOWN) + params->repr.sys = mp_csp_guess_colorspace(params->w, params->h); + if (params->repr.levels == PL_COLOR_LEVELS_UNKNOWN) { + if (params->color.transfer == PL_COLOR_TRC_V_LOG) { + params->repr.levels = PL_COLOR_LEVELS_FULL; } else { - params->color.levels = infer_levels(params->imgfmt); + params->repr.levels = infer_levels(params->imgfmt); } } - if (params->color.primaries == MP_CSP_PRIM_AUTO) { + if (params->color.primaries == PL_COLOR_PRIM_UNKNOWN) { // Guess based on the colormatrix as a first priority - if (params->color.space == MP_CSP_BT_2020_NC || - params->color.space == MP_CSP_BT_2020_C) { - params->color.primaries = MP_CSP_PRIM_BT_2020; - } else if (params->color.space == MP_CSP_BT_709) { - params->color.primaries = MP_CSP_PRIM_BT_709; + if (params->repr.sys == PL_COLOR_SYSTEM_BT_2020_NC || + params->repr.sys == PL_COLOR_SYSTEM_BT_2020_C) { + params->color.primaries = PL_COLOR_PRIM_BT_2020; + } else if (params->repr.sys == PL_COLOR_SYSTEM_BT_709) { + params->color.primaries = PL_COLOR_PRIM_BT_709; } else { // Ambiguous colormatrix for BT.601, guess based on res params->color.primaries = mp_csp_guess_primaries(params->w, params->h); } } - if (params->color.gamma == MP_CSP_TRC_AUTO) - params->color.gamma = MP_CSP_TRC_BT_1886; - } else if (forced_csp == MP_CSP_RGB) { - params->color.space = MP_CSP_RGB; - params->color.levels = MP_CSP_LEVELS_PC; + if (params->color.transfer == PL_COLOR_TRC_UNKNOWN) + params->color.transfer = PL_COLOR_TRC_BT_1886; + } else if (forced_csp == PL_COLOR_SYSTEM_RGB) { + params->repr.sys = PL_COLOR_SYSTEM_RGB; + params->repr.levels = PL_COLOR_LEVELS_FULL; // The majority of RGB content is either sRGB or (rarely) some other // color space which we don't even handle, like AdobeRGB or // ProPhotoRGB. The only reasonable thing we can do is assume it's // sRGB and hope for the best, which should usually just work out fine. // Note: sRGB primaries = BT.709 primaries - if (params->color.primaries == MP_CSP_PRIM_AUTO) - params->color.primaries = MP_CSP_PRIM_BT_709; - if (params->color.gamma == MP_CSP_TRC_AUTO) - params->color.gamma = MP_CSP_TRC_SRGB; - } else if (forced_csp == MP_CSP_XYZ) { - params->color.space = MP_CSP_XYZ; - params->color.levels = MP_CSP_LEVELS_PC; + if (params->color.primaries == PL_COLOR_PRIM_UNKNOWN) + params->color.primaries = PL_COLOR_PRIM_BT_709; + if (params->color.transfer == PL_COLOR_TRC_UNKNOWN) + params->color.transfer = PL_COLOR_TRC_SRGB; + } else if (forced_csp == PL_COLOR_SYSTEM_XYZ) { + params->repr.sys = PL_COLOR_SYSTEM_XYZ; + params->repr.levels = PL_COLOR_LEVELS_FULL; // Force gamma to ST428 as this is the only correct for DCDM X'Y'Z' - params->color.gamma = MP_CSP_TRC_ST428; + params->color.transfer = PL_COLOR_TRC_ST428; // Don't care about primaries, they shouldn't be used, or if anything // MP_CSP_PRIM_ST428 should be defined. } else { // We have no clue. - params->color.space = MP_CSP_AUTO; - params->color.levels = MP_CSP_LEVELS_AUTO; - params->color.primaries = MP_CSP_PRIM_AUTO; - params->color.gamma = MP_CSP_TRC_AUTO; + params->repr.sys = PL_COLOR_SYSTEM_UNKNOWN; + params->repr.levels = PL_COLOR_LEVELS_UNKNOWN; + params->color.primaries = PL_COLOR_PRIM_UNKNOWN; + params->color.transfer = PL_COLOR_TRC_UNKNOWN; } if (!params->color.hdr.max_luma) { - if (params->color.gamma == MP_CSP_TRC_HLG) { + if (params->color.transfer == PL_COLOR_TRC_HLG) { params->color.hdr.max_luma = 1000; // reference display } else { // If the signal peak is unknown, we're forced to pick the TRC's // nominal range as the signal peak to prevent clipping - params->color.hdr.max_luma = mp_trc_nom_peak(params->color.gamma) * MP_REF_WHITE; + params->color.hdr.max_luma = mp_trc_nom_peak(params->color.transfer) * MP_REF_WHITE; } } - if (!mp_trc_is_hdr(params->color.gamma)) { + if (!mp_trc_is_hdr(params->color.transfer)) { // Some clips have leftover HDR metadata after conversion to SDR, so to // avoid blowing up the tone mapping code, strip/sanitize it params->color.hdr = pl_hdr_metadata_empty; } if (params->chroma_location == MP_CHROMA_AUTO) { - if (params->color.levels == MP_CSP_LEVELS_TV) + if (params->repr.levels == PL_COLOR_LEVELS_LIMITED) params->chroma_location = MP_CHROMA_LEFT; - if (params->color.levels == MP_CSP_LEVELS_PC) + if (params->repr.levels == PL_COLOR_LEVELS_FULL) params->chroma_location = MP_CHROMA_CENTER; } - if (params->color.light == MP_CSP_LIGHT_AUTO) { + if (params->light == MP_CSP_LIGHT_AUTO) { // HLG is always scene-referred (using its own OOTF), everything else // we assume is display-referred by default. - if (params->color.gamma == MP_CSP_TRC_HLG) { - params->color.light = MP_CSP_LIGHT_SCENE_HLG; + if (params->color.transfer == PL_COLOR_TRC_HLG) { + params->light = MP_CSP_LIGHT_SCENE_HLG; } else { - params->color.light = MP_CSP_LIGHT_DISPLAY; + params->light = MP_CSP_LIGHT_DISPLAY; } } } @@ -1033,11 +1037,14 @@ struct mp_image *mp_image_from_av_frame(struct AVFrame *src) if (src->repeat_pict == 1) dst->fields |= MP_IMGFIELD_REPEAT_FIRST; - dst->params.color = (struct mp_colorspace){ - .space = avcol_spc_to_mp_csp(src->colorspace), - .levels = avcol_range_to_mp_csp_levels(src->color_range), - .primaries = avcol_pri_to_mp_csp_prim(src->color_primaries), - .gamma = avcol_trc_to_mp_csp_trc(src->color_trc), + dst->params.repr = (struct pl_color_repr){ + .sys = pl_system_from_av(src->colorspace), + .levels = pl_levels_from_av(src->color_range), + }; + + dst->params.color = (struct pl_color_space){ + .primaries = pl_primaries_from_av(src->color_primaries), + .transfer = pl_transfer_from_av(src->color_trc), }; dst->params.chroma_location = avchroma_location_to_mp(src->chroma_location); @@ -1046,7 +1053,7 @@ struct mp_image *mp_image_from_av_frame(struct AVFrame *src) struct mp_image_params *p = (void *)src->opaque_ref->data; dst->params.stereo3d = p->stereo3d; // Might be incorrect if colorspace changes. - dst->params.color.light = p->color.light; + dst->params.light = p->light; dst->params.alpha = p->alpha; } @@ -1163,11 +1170,11 @@ struct AVFrame *mp_image_to_av_frame(struct mp_image *src) if (src->fields & MP_IMGFIELD_REPEAT_FIRST) dst->repeat_pict = 1; - dst->colorspace = mp_csp_to_avcol_spc(src->params.color.space); - dst->color_range = mp_csp_levels_to_avcol_range(src->params.color.levels); + dst->colorspace = pl_system_to_av(src->params.repr.sys); + dst->color_range = pl_levels_to_av(src->params.repr.levels); dst->color_primaries = - mp_csp_prim_to_avcol_pri(src->params.color.primaries); - dst->color_trc = mp_csp_trc_to_avcol_trc(src->params.color.gamma); + pl_primaries_to_av(src->params.color.primaries); + dst->color_trc = pl_transfer_to_av(src->params.color.transfer); dst->chroma_location = mp_chroma_location_to_av(src->params.chroma_location); @@ -1183,11 +1190,7 @@ struct AVFrame *mp_image_to_av_frame(struct mp_image *src) new_ref->icc_profile = NULL; } - pl_avframe_set_color(dst, (struct pl_color_space){ - .primaries = mp_prim_to_pl(src->params.color.primaries), - .transfer = mp_trc_to_pl(src->params.color.gamma), - .hdr = src->params.color.hdr, - }); + pl_avframe_set_color(dst, src->params.color); { AVFrameSideData *sd = av_frame_new_side_data(dst, diff --git a/video/mp_image.h b/video/mp_image.h index 0408aab3df99..c1ba89ee0ac7 100644 --- a/video/mp_image.h +++ b/video/mp_image.h @@ -47,7 +47,9 @@ struct mp_image_params { int w, h; // image dimensions int p_w, p_h; // define pixel aspect ratio (undefined: 0/0) bool force_window; // fake image created by handle_force_window - struct mp_colorspace color; + struct pl_color_space color; + struct pl_color_repr repr; + enum mp_csp_light light; enum mp_chroma_location chroma_location; // The image should be rotated clockwise (0-359 degrees). int rotate; diff --git a/video/out/d3d11/context.c b/video/out/d3d11/context.c index 05f04fdb6b08..9f866e2e8042 100644 --- a/video/out/d3d11/context.c +++ b/video/out/d3d11/context.c @@ -100,7 +100,7 @@ struct priv { struct ra_tex *backbuffer; ID3D11Device *device; IDXGISwapChain *swapchain; - struct mp_colorspace swapchain_csp; + struct pl_color_space swapchain_csp; int64_t perf_freq; unsigned sync_refresh_count; diff --git a/video/out/gpu/context.h b/video/out/gpu/context.h index 6788e6fd89bb..447f40b07501 100644 --- a/video/out/gpu/context.h +++ b/video/out/gpu/context.h @@ -72,7 +72,7 @@ struct ra_fbo { // Host system's colorspace that it will be interpreting // the frame buffer as. - struct mp_colorspace color_space; + struct pl_color_space color_space; }; struct ra_swapchain_fns { diff --git a/video/out/gpu/d3d11_helpers.c b/video/out/gpu/d3d11_helpers.c index 30d9eae56f64..dce40b333485 100644 --- a/video/out/gpu/d3d11_helpers.c +++ b/video/out/gpu/d3d11_helpers.c @@ -228,9 +228,9 @@ static const char *d3d11_get_csp_name(DXGI_COLOR_SPACE_TYPE csp) } static bool d3d11_get_mp_csp(DXGI_COLOR_SPACE_TYPE csp, - struct mp_colorspace *mp_csp) + struct pl_color_space *pl_color_system) { - if (!mp_csp) + if (!pl_color_system) return false; // Colorspaces utilizing gamma 2.2 (G22) are set to @@ -243,27 +243,27 @@ static bool d3d11_get_mp_csp(DXGI_COLOR_SPACE_TYPE csp, // regarding not doing conversion from BT.601 to BT.709. switch (csp) { case DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709: - *mp_csp = (struct mp_colorspace){ - .gamma = MP_CSP_TRC_AUTO, - .primaries = MP_CSP_PRIM_AUTO, + *pl_color_system = (struct pl_color_space){ + .transfer = PL_COLOR_TRC_UNKNOWN, + .primaries = PL_COLOR_PRIM_UNKNOWN, }; break; case DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709: - *mp_csp = (struct mp_colorspace) { - .gamma = MP_CSP_TRC_LINEAR, - .primaries = MP_CSP_PRIM_AUTO, + *pl_color_system = (struct pl_color_space) { + .transfer = PL_COLOR_TRC_LINEAR, + .primaries = PL_COLOR_PRIM_UNKNOWN, }; break; case DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020: - *mp_csp = (struct mp_colorspace) { - .gamma = MP_CSP_TRC_PQ, - .primaries = MP_CSP_PRIM_BT_2020, + *pl_color_system = (struct pl_color_space) { + .transfer = PL_COLOR_TRC_PQ, + .primaries = PL_COLOR_PRIM_BT_2020, }; break; case DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P2020: - *mp_csp = (struct mp_colorspace) { - .gamma = MP_CSP_TRC_AUTO, - .primaries = MP_CSP_PRIM_BT_2020, + *pl_color_system = (struct pl_color_space) { + .transfer = PL_COLOR_TRC_UNKNOWN, + .primaries = PL_COLOR_PRIM_BT_2020, }; break; default: @@ -793,7 +793,7 @@ static bool configure_created_swapchain(struct mp_log *log, IDXGISwapChain *swapchain, DXGI_FORMAT requested_format, DXGI_COLOR_SPACE_TYPE requested_csp, - struct mp_colorspace *configured_csp) + struct pl_color_space *configured_csp) { DXGI_FORMAT probed_format = DXGI_FORMAT_UNKNOWN; DXGI_FORMAT selected_format = DXGI_FORMAT_UNKNOWN; @@ -801,7 +801,7 @@ static bool configure_created_swapchain(struct mp_log *log, DXGI_COLOR_SPACE_TYPE selected_colorspace; const char *format_name = NULL; const char *csp_name = NULL; - struct mp_colorspace mp_csp = { 0 }; + struct pl_color_space pl_color_system = { 0 }; bool mp_csp_mapped = false; query_output_format_and_colorspace(log, swapchain, @@ -817,7 +817,7 @@ static bool configure_created_swapchain(struct mp_log *log, requested_csp : probed_colorspace; format_name = d3d11_get_format_name(selected_format); csp_name = d3d11_get_csp_name(selected_colorspace); - mp_csp_mapped = d3d11_get_mp_csp(selected_colorspace, &mp_csp); + mp_csp_mapped = d3d11_get_mp_csp(selected_colorspace, &pl_color_system); mp_verbose(log, "Selected swapchain format %s (%d), attempting " "to utilize it.\n", @@ -848,7 +848,7 @@ static bool configure_created_swapchain(struct mp_log *log, "mapping! Overriding to standard sRGB!\n", csp_name, selected_colorspace); selected_colorspace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709; - d3d11_get_mp_csp(selected_colorspace, &mp_csp); + d3d11_get_mp_csp(selected_colorspace, &pl_color_system); } mp_verbose(log, "Selected swapchain color space %s (%d), attempting to " @@ -860,7 +860,7 @@ static bool configure_created_swapchain(struct mp_log *log, } if (configured_csp) { - *configured_csp = mp_csp; + *configured_csp = pl_color_system; } return true; diff --git a/video/out/gpu/d3d11_helpers.h b/video/out/gpu/d3d11_helpers.h index c115d330d5f3..c452823cdc04 100644 --- a/video/out/gpu/d3d11_helpers.h +++ b/video/out/gpu/d3d11_helpers.h @@ -80,10 +80,10 @@ struct d3d11_swapchain_opts { DXGI_FORMAT format; DXGI_COLOR_SPACE_TYPE color_space; - // mp_colorspace mapping of the configured swapchain colorspace + // pl_color_space mapping of the configured swapchain colorspace // shall be written into this memory location if configuration // succeeds. Will be ignored if NULL. - struct mp_colorspace *configured_csp; + struct pl_color_space *configured_csp; // Use DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL if possible bool flip; diff --git a/video/out/gpu/lcms.c b/video/out/gpu/lcms.c index 7006a96776d5..00d819d2f0e3 100644 --- a/video/out/gpu/lcms.c +++ b/video/out/gpu/lcms.c @@ -46,8 +46,8 @@ struct gl_lcms { char *current_profile; bool using_memory_profile; bool changed; - enum mp_csp_prim current_prim; - enum mp_csp_trc current_trc; + enum pl_color_primaries current_prim; + enum pl_color_transfer current_trc; struct mp_log *log; struct mpv_global *global; @@ -162,8 +162,8 @@ static bool vid_profile_eq(struct AVBufferRef *a, struct AVBufferRef *b) // Return whether the profile or config has changed since the last time it was // retrieved. If it has changed, gl_lcms_get_lut3d() should be called. -bool gl_lcms_has_changed(struct gl_lcms *p, enum mp_csp_prim prim, - enum mp_csp_trc trc, struct AVBufferRef *vid_profile) +bool gl_lcms_has_changed(struct gl_lcms *p, enum pl_color_primaries prim, + enum pl_color_transfer trc, struct AVBufferRef *vid_profile) { if (p->changed || p->current_prim != prim || p->current_trc != trc) return true; @@ -180,7 +180,7 @@ bool gl_lcms_has_profile(struct gl_lcms *p) static cmsHPROFILE get_vid_profile(struct gl_lcms *p, cmsContext cms, cmsHPROFILE disp_profile, - enum mp_csp_prim prim, enum mp_csp_trc trc) + enum pl_color_primaries prim, enum pl_color_transfer trc) { if (p->opts->use_embedded && p->vid_profile) { // Try using the embedded ICC profile @@ -207,26 +207,26 @@ static cmsHPROFILE get_vid_profile(struct gl_lcms *p, cmsContext cms, cmsToneCurve *tonecurve[3] = {0}; switch (trc) { - case MP_CSP_TRC_LINEAR: tonecurve[0] = cmsBuildGamma(cms, 1.0); break; - case MP_CSP_TRC_GAMMA18: tonecurve[0] = cmsBuildGamma(cms, 1.8); break; - case MP_CSP_TRC_GAMMA20: tonecurve[0] = cmsBuildGamma(cms, 2.0); break; - case MP_CSP_TRC_GAMMA22: tonecurve[0] = cmsBuildGamma(cms, 2.2); break; - case MP_CSP_TRC_GAMMA24: tonecurve[0] = cmsBuildGamma(cms, 2.4); break; - case MP_CSP_TRC_GAMMA26: tonecurve[0] = cmsBuildGamma(cms, 2.6); break; - case MP_CSP_TRC_GAMMA28: tonecurve[0] = cmsBuildGamma(cms, 2.8); break; - - case MP_CSP_TRC_SRGB: + case PL_COLOR_TRC_LINEAR: tonecurve[0] = cmsBuildGamma(cms, 1.0); break; + case PL_COLOR_TRC_GAMMA18: tonecurve[0] = cmsBuildGamma(cms, 1.8); break; + case PL_COLOR_TRC_GAMMA20: tonecurve[0] = cmsBuildGamma(cms, 2.0); break; + case PL_COLOR_TRC_GAMMA22: tonecurve[0] = cmsBuildGamma(cms, 2.2); break; + case PL_COLOR_TRC_GAMMA24: tonecurve[0] = cmsBuildGamma(cms, 2.4); break; + case PL_COLOR_TRC_GAMMA26: tonecurve[0] = cmsBuildGamma(cms, 2.6); break; + case PL_COLOR_TRC_GAMMA28: tonecurve[0] = cmsBuildGamma(cms, 2.8); break; + + case PL_COLOR_TRC_SRGB: // Values copied from Little-CMS tonecurve[0] = cmsBuildParametricToneCurve(cms, 4, (double[5]){2.40, 1/1.055, 0.055/1.055, 1/12.92, 0.04045}); break; - case MP_CSP_TRC_PRO_PHOTO: + case PL_COLOR_TRC_PRO_PHOTO: tonecurve[0] = cmsBuildParametricToneCurve(cms, 4, (double[5]){1.8, 1.0, 0.0, 1/16.0, 0.03125}); break; - case MP_CSP_TRC_BT_1886: { + case PL_COLOR_TRC_BT_1886: { double src_black[3]; if (p->opts->contrast < 0) { // User requested infinite contrast, return 2.4 profile @@ -300,7 +300,7 @@ static cmsHPROFILE get_vid_profile(struct gl_lcms *p, cmsContext cms, } bool gl_lcms_get_lut3d(struct gl_lcms *p, struct lut3d **result_lut3d, - enum mp_csp_prim prim, enum mp_csp_trc trc, + enum pl_color_primaries prim, enum pl_color_transfer trc, struct AVBufferRef *vid_profile) { int s_r, s_g, s_b; @@ -474,8 +474,8 @@ struct gl_lcms *gl_lcms_init(void *talloc_ctx, struct mp_log *log, void gl_lcms_update_options(struct gl_lcms *p) { } bool gl_lcms_set_memory_profile(struct gl_lcms *p, bstr profile) {return false;} -bool gl_lcms_has_changed(struct gl_lcms *p, enum mp_csp_prim prim, - enum mp_csp_trc trc, struct AVBufferRef *vid_profile) +bool gl_lcms_has_changed(struct gl_lcms *p, enum pl_color_primaries prim, + enum pl_color_transfer trc, struct AVBufferRef *vid_profile) { return false; } @@ -486,7 +486,7 @@ bool gl_lcms_has_profile(struct gl_lcms *p) } bool gl_lcms_get_lut3d(struct gl_lcms *p, struct lut3d **result_lut3d, - enum mp_csp_prim prim, enum mp_csp_trc trc, + enum pl_color_primaries prim, enum pl_color_transfer trc, struct AVBufferRef *vid_profile) { return false; diff --git a/video/out/gpu/lcms.h b/video/out/gpu/lcms.h index 607353a84ff3..d0b0fe5b8927 100644 --- a/video/out/gpu/lcms.h +++ b/video/out/gpu/lcms.h @@ -37,10 +37,10 @@ void gl_lcms_update_options(struct gl_lcms *p); bool gl_lcms_set_memory_profile(struct gl_lcms *p, bstr profile); bool gl_lcms_has_profile(struct gl_lcms *p); bool gl_lcms_get_lut3d(struct gl_lcms *p, struct lut3d **, - enum mp_csp_prim prim, enum mp_csp_trc trc, + enum pl_color_primaries prim, enum pl_color_transfer trc, struct AVBufferRef *vid_profile); -bool gl_lcms_has_changed(struct gl_lcms *p, enum mp_csp_prim prim, - enum mp_csp_trc trc, struct AVBufferRef *vid_profile); +bool gl_lcms_has_changed(struct gl_lcms *p, enum pl_color_primaries prim, + enum pl_color_transfer trc, struct AVBufferRef *vid_profile); static inline bool gl_parse_3dlut_size(const char *arg, int *p1, int *p2, int *p3) { diff --git a/video/out/gpu/video.c b/video/out/gpu/video.c index 0f4826138981..62388d65c32b 100644 --- a/video/out/gpu/video.c +++ b/video/out/gpu/video.c @@ -368,13 +368,13 @@ const struct m_sub_options gl_video_conf = { .deprecation_message = "no replacement"}, {"gamma-auto", OPT_BOOL(gamma_auto), .deprecation_message = "no replacement"}, - {"target-prim", OPT_CHOICE_C(target_prim, mp_csp_prim_names)}, - {"target-trc", OPT_CHOICE_C(target_trc, mp_csp_trc_names)}, + {"target-prim", OPT_CHOICE_C(target_prim, pl_csp_prim_names)}, + {"target-trc", OPT_CHOICE_C(target_trc, pl_csp_trc_names)}, {"target-peak", OPT_CHOICE(target_peak, {"auto", 0}), M_RANGE(10, 10000)}, {"target-contrast", OPT_CHOICE(target_contrast, {"auto", 0}, {"inf", -1}), M_RANGE(10, 1000000)}, - {"target-gamut", OPT_CHOICE_C(target_gamut, mp_csp_prim_names)}, + {"target-gamut", OPT_CHOICE_C(target_gamut, pl_csp_prim_names)}, {"tone-mapping", OPT_CHOICE(tone_map.curve, {"auto", TONE_MAPPING_AUTO}, {"clip", TONE_MAPPING_CLIP}, @@ -605,15 +605,6 @@ bool gl_video_gamma_auto_enabled(struct gl_video *p) return p->opts.gamma_auto; } -struct mp_colorspace gl_video_get_output_colorspace(struct gl_video *p) -{ - return (struct mp_colorspace) { - .primaries = p->opts.target_prim, - .gamma = p->opts.target_trc, - .hdr.max_luma = p->opts.target_peak, - }; -} - // Warning: profile.start must point to a ta allocation, and the function // takes over ownership. void gl_video_set_icc_profile(struct gl_video *p, bstr icc_data) @@ -627,8 +618,8 @@ bool gl_video_icc_auto_enabled(struct gl_video *p) return p->opts.icc_opts ? p->opts.icc_opts->profile_auto : false; } -static bool gl_video_get_lut3d(struct gl_video *p, enum mp_csp_prim prim, - enum mp_csp_trc trc) +static bool gl_video_get_lut3d(struct gl_video *p, enum pl_color_primaries prim, + enum pl_color_transfer trc) { if (!p->use_lut_3d) return false; @@ -796,9 +787,9 @@ static void pass_get_images(struct gl_video *p, struct video_image *vimg, ctype = PLANE_NONE; } else if (c == 4) { ctype = PLANE_ALPHA; - } else if (p->image_params.color.space == MP_CSP_RGB) { + } else if (p->image_params.repr.sys == PL_COLOR_SYSTEM_RGB) { ctype = PLANE_RGB; - } else if (p->image_params.color.space == MP_CSP_XYZ) { + } else if (p->image_params.repr.sys == PL_COLOR_SYSTEM_XYZ) { ctype = PLANE_XYZ; } else { ctype = c == 1 ? PLANE_LUMA : PLANE_CHROMA; @@ -810,7 +801,7 @@ static void pass_get_images(struct gl_video *p, struct video_image *vimg, int msb_valid_bits = p->ra_format.component_bits + MPMIN(p->ra_format.component_pad, 0); - int csp = type == PLANE_ALPHA ? MP_CSP_RGB : p->image_params.color.space; + int csp = type == PLANE_ALPHA ? PL_COLOR_SYSTEM_RGB : p->image_params.repr.sys; float tex_mul = 1.0 / mp_get_csp_mul(csp, msb_valid_bits, p->ra_format.component_bits); if (p->ra_format.component_type == RA_CTYPE_FLOAT) @@ -1954,7 +1945,7 @@ static void deband_hook(struct gl_video *p, struct image img, { pass_describe(p, "debanding (%s)", plane_names[img.type]); pass_sample_deband(p->sc, p->opts.deband_opts, &p->lfg, - p->image_params.color.gamma); + p->image_params.color.transfer); } static void unsharp_hook(struct gl_video *p, struct image img, @@ -2344,8 +2335,8 @@ static void pass_convert_yuv(struct gl_video *p) GLSLF("color = color.%s;\n", p->color_swizzle); // Pre-colormatrix input gamma correction - if (cparams.color.space == MP_CSP_XYZ) - pass_linearize(p->sc, p->image_params.color.gamma); + if (cparams.repr.sys == PL_COLOR_SYSTEM_XYZ) + pass_linearize(p->sc, p->image_params.color.transfer); // We always explicitly normalize the range in pass_read_video cparams.input_bits = cparams.texture_bits = 0; @@ -2359,14 +2350,14 @@ static void pass_convert_yuv(struct gl_video *p) GLSL(color.rgb = mat3(colormatrix) * color.rgb + colormatrix_c;) - if (cparams.color.space == MP_CSP_XYZ) { - pass_delinearize(p->sc, p->image_params.color.gamma); + if (cparams.repr.sys == PL_COLOR_SYSTEM_XYZ) { + pass_delinearize(p->sc, p->image_params.color.transfer); // mp_get_csp_matrix implicitly converts XYZ to DCI-P3 - p->image_params.color.space = MP_CSP_RGB; - p->image_params.color.primaries = MP_CSP_PRIM_DCI_P3; + p->image_params.repr.sys = PL_COLOR_SYSTEM_RGB; + p->image_params.color.primaries = PL_COLOR_PRIM_DCI_P3; } - if (p->image_params.color.space == MP_CSP_BT_2020_C) { + if (p->image_params.repr.sys == PL_COLOR_SYSTEM_BT_2020_C) { // Conversion for C'rcY'cC'bc via the BT.2020 CL system: // C'bc = (B'-Y'c) / 1.9404 | C'bc <= 0 // = (B'-Y'c) / 1.5816 | C'bc > 0 @@ -2490,7 +2481,7 @@ static void pass_scale_main(struct gl_video *p) // Linear light downscaling results in nasty artifacts for HDR curves // due to the potentially extreme brightness differences severely // compounding any ringing. So just scale in gamma light instead. - if (mp_trc_is_hdr(p->image_params.color.gamma)) + if (mp_trc_is_hdr(p->image_params.color.transfer)) use_linear = false; } else if (upscaling) { use_linear = p->opts.linear_upscaling || p->opts.sigmoid_upscaling; @@ -2498,7 +2489,7 @@ static void pass_scale_main(struct gl_video *p) if (use_linear) { p->use_linear = true; - pass_linearize(p->sc, p->image_params.color.gamma); + pass_linearize(p->sc, p->image_params.color.transfer); pass_opt_hook_point(p, "LINEAR", NULL); } @@ -2551,8 +2542,9 @@ static void pass_scale_main(struct gl_video *p) // rendering) // If OSD is true, ignore any changes that may have been made to the video // by previous passes (i.e. linear scaling) -static void pass_colormanage(struct gl_video *p, struct mp_colorspace src, - struct mp_colorspace fbo_csp, int flags, bool osd) +static void pass_colormanage(struct gl_video *p, struct pl_color_space src, + enum mp_csp_light src_light, + struct pl_color_space fbo_csp, int flags, bool osd) { struct ra *ra = p->ra; @@ -2560,18 +2552,17 @@ static void pass_colormanage(struct gl_video *p, struct mp_colorspace src, // unless specific transfer function, primaries or target peak // is set. If values are set to _AUTO, the most likely intended // values are guesstimated later in this function. - struct mp_colorspace dst = { - .gamma = p->opts.target_trc == MP_CSP_TRC_AUTO ? - fbo_csp.gamma : p->opts.target_trc, - .primaries = p->opts.target_prim == MP_CSP_PRIM_AUTO ? + struct pl_color_space dst = { + .transfer = p->opts.target_trc == PL_COLOR_TRC_UNKNOWN ? + fbo_csp.transfer : p->opts.target_trc, + .primaries = p->opts.target_prim == PL_COLOR_PRIM_UNKNOWN ? fbo_csp.primaries : p->opts.target_prim, - .light = MP_CSP_LIGHT_DISPLAY, .hdr.max_luma = !p->opts.target_peak ? fbo_csp.hdr.max_luma : p->opts.target_peak, }; if (!p->colorspace_override_warned && - ((fbo_csp.gamma && dst.gamma != fbo_csp.gamma) || + ((fbo_csp.transfer && dst.transfer != fbo_csp.transfer) || (fbo_csp.primaries && dst.primaries != fbo_csp.primaries))) { MP_WARN(p, "One or more colorspace value is being overridden " @@ -2579,44 +2570,44 @@ static void pass_colormanage(struct gl_video *p, struct mp_colorspace src, "transfer function: (dst: %s, fbo: %s), " "primaries: (dst: %s, fbo: %s). " "Rendering can lead to incorrect results!\n", - m_opt_choice_str(mp_csp_trc_names, dst.gamma), - m_opt_choice_str(mp_csp_trc_names, fbo_csp.gamma), - m_opt_choice_str(mp_csp_prim_names, dst.primaries), - m_opt_choice_str(mp_csp_prim_names, fbo_csp.primaries)); + m_opt_choice_str(pl_csp_trc_names, dst.transfer), + m_opt_choice_str(pl_csp_trc_names, fbo_csp.transfer), + m_opt_choice_str(pl_csp_prim_names, dst.primaries), + m_opt_choice_str(pl_csp_prim_names, fbo_csp.primaries)); p->colorspace_override_warned = true; } - if (dst.gamma == MP_CSP_TRC_HLG) - dst.light = MP_CSP_LIGHT_SCENE_HLG; + enum mp_csp_light dst_light = dst.transfer == PL_COLOR_TRC_HLG ? + MP_CSP_LIGHT_SCENE_HLG : MP_CSP_LIGHT_DISPLAY; if (p->use_lut_3d && (flags & RENDER_SCREEN_COLOR)) { // The 3DLUT is always generated against the video's original source // space, *not* the reference space. (To avoid having to regenerate // the 3DLUT for the OSD on every frame) - enum mp_csp_prim prim_orig = p->image_params.color.primaries; - enum mp_csp_trc trc_orig = p->image_params.color.gamma; + enum pl_color_primaries prim_orig = p->image_params.color.primaries; + enum pl_color_transfer trc_orig = p->image_params.color.transfer; // One exception: HDR is not implemented by LittleCMS for technical // limitation reasons, so we use a gamma 2.2 input curve here instead. // We could pick any value we want here, the difference is just coding // efficiency. if (mp_trc_is_hdr(trc_orig)) - trc_orig = MP_CSP_TRC_GAMMA22; + trc_orig = PL_COLOR_TRC_GAMMA22; if (gl_video_get_lut3d(p, prim_orig, trc_orig)) { dst.primaries = prim_orig; - dst.gamma = trc_orig; - assert(dst.primaries && dst.gamma); + dst.transfer = trc_orig; + assert(dst.primaries && dst.transfer); } } - if (dst.primaries == MP_CSP_PRIM_AUTO) { + if (dst.primaries == PL_COLOR_PRIM_UNKNOWN) { // The vast majority of people are on sRGB or BT.709 displays, so pick // this as the default output color space. - dst.primaries = MP_CSP_PRIM_BT_709; + dst.primaries = PL_COLOR_PRIM_BT_709; - if (src.primaries == MP_CSP_PRIM_BT_601_525 || - src.primaries == MP_CSP_PRIM_BT_601_625) + if (src.primaries == PL_COLOR_PRIM_BT_601_525 || + src.primaries == PL_COLOR_PRIM_BT_601_625) { // Since we auto-pick BT.601 and BT.709 based on the dimensions, // combined with the fact that they're very similar to begin with, @@ -2626,28 +2617,28 @@ static void pass_colormanage(struct gl_video *p, struct mp_colorspace src, } } - if (dst.gamma == MP_CSP_TRC_AUTO) { + if (dst.transfer == PL_COLOR_TRC_UNKNOWN) { // Most people seem to complain when the image is darker or brighter // than what they're "used to", so just avoid changing the gamma // altogether by default. The only exceptions to this rule apply to // very unusual TRCs, which even hardcode technoluddites would probably // not enjoy viewing unaltered. - dst.gamma = src.gamma; + dst.transfer = src.transfer; // Avoid outputting linear light or HDR content "by default". For these // just pick gamma 2.2 as a default, since it's a good estimate for // the response of typical displays - if (dst.gamma == MP_CSP_TRC_LINEAR || mp_trc_is_hdr(dst.gamma)) - dst.gamma = MP_CSP_TRC_GAMMA22; + if (dst.transfer == PL_COLOR_TRC_LINEAR || mp_trc_is_hdr(dst.transfer)) + dst.transfer = PL_COLOR_TRC_GAMMA22; } // If there's no specific signal peak known for the output display, infer // it from the chosen transfer function. Also normalize the src peak, in // case it was unknown if (!dst.hdr.max_luma) - dst.hdr.max_luma = mp_trc_nom_peak(dst.gamma) * MP_REF_WHITE; + dst.hdr.max_luma = mp_trc_nom_peak(dst.transfer) * MP_REF_WHITE; if (!src.hdr.max_luma) - src.hdr.max_luma = mp_trc_nom_peak(src.gamma) * MP_REF_WHITE; + src.hdr.max_luma = mp_trc_nom_peak(src.transfer) * MP_REF_WHITE; // Whitelist supported modes switch (p->opts.tone_map.curve) { @@ -2679,7 +2670,7 @@ static void pass_colormanage(struct gl_video *p, struct mp_colorspace src, } struct gl_tone_map_opts tone_map = p->opts.tone_map; - bool detect_peak = tone_map.compute_peak >= 0 && mp_trc_is_hdr(src.gamma) + bool detect_peak = tone_map.compute_peak >= 0 && mp_trc_is_hdr(src.transfer) && src.hdr.max_luma > dst.hdr.max_luma; if (detect_peak && !p->hdr_peak_ssbo) { @@ -2718,7 +2709,7 @@ static void pass_colormanage(struct gl_video *p, struct mp_colorspace src, } // Adapt from src to dst as necessary - pass_color_map(p->sc, p->use_linear && !osd, src, dst, &tone_map); + pass_color_map(p->sc, p->use_linear && !osd, src, dst, src_light, dst_light, &tone_map); if (p->use_lut_3d && (flags & RENDER_SCREEN_COLOR)) { gl_sc_uniform_texture(p->sc, "lut_3d", p->lut_3d_texture); @@ -2909,13 +2900,13 @@ static void pass_draw_osd(struct gl_video *p, int osd_flags, int frame_flags, // When subtitles need to be color managed, assume they're in sRGB // (for lack of anything saner to do) if (cms) { - static const struct mp_colorspace csp_srgb = { - .primaries = MP_CSP_PRIM_BT_709, - .gamma = MP_CSP_TRC_SRGB, - .light = MP_CSP_LIGHT_DISPLAY, + static const struct pl_color_space csp_srgb = { + .primaries = PL_COLOR_PRIM_BT_709, + .transfer = PL_COLOR_TRC_SRGB, }; - pass_colormanage(p, csp_srgb, fbo.color_space, frame_flags, true); + pass_colormanage(p, csp_srgb, MP_CSP_LIGHT_DISPLAY, fbo.color_space, + frame_flags, true); } mpgl_osd_draw_finish(p->osd, n, p->sc, fbo); } @@ -3039,7 +3030,7 @@ static bool pass_render_frame(struct gl_video *p, struct mp_image *mpi, rect.mt *= scale[1]; rect.mb *= scale[1]; // We should always blend subtitles in non-linear light if (p->use_linear) { - pass_delinearize(p->sc, p->image_params.color.gamma); + pass_delinearize(p->sc, p->image_params.color.transfer); p->use_linear = false; } finish_pass_tex(p, &p->blend_subs_tex, p->texture_w, p->texture_h); @@ -3066,7 +3057,8 @@ static void pass_draw_to_screen(struct gl_video *p, struct ra_fbo fbo, int flags GLSL(color.rgb = pow(color.rgb, vec3(user_gamma));) } - pass_colormanage(p, p->image_params.color, fbo.color_space, flags, false); + pass_colormanage(p, p->image_params.color, p->image_params.light, + fbo.color_space, flags, false); // Since finish_pass_fbo doesn't work with compute shaders, and neither // does the checkerboard/dither code, we may need an indirection via @@ -3121,7 +3113,7 @@ static bool update_surface(struct gl_video *p, struct mp_image *mpi, // because mixing in compressed light artificially darkens the results if (!p->use_linear) { p->use_linear = true; - pass_linearize(p->sc, p->image_params.color.gamma); + pass_linearize(p->sc, p->image_params.color.transfer); } finish_pass_tex(p, &surf->tex, vp_w, vp_h); @@ -3912,8 +3904,8 @@ static void check_gl_features(struct gl_video *p) } } - int use_cms = p->opts.target_prim != MP_CSP_PRIM_AUTO || - p->opts.target_trc != MP_CSP_TRC_AUTO || p->use_lut_3d; + int use_cms = p->opts.target_prim != PL_COLOR_PRIM_UNKNOWN || + p->opts.target_trc != PL_COLOR_TRC_UNKNOWN || p->use_lut_3d; // mix() is needed for some gamma functions if (!have_mglsl && (p->opts.linear_downscaling || @@ -3925,8 +3917,8 @@ static void check_gl_features(struct gl_video *p) MP_WARN(p, "Disabling linear/sigmoid scaling (GLSL version too old).\n"); } if (!have_mglsl && use_cms) { - p->opts.target_prim = MP_CSP_PRIM_AUTO; - p->opts.target_trc = MP_CSP_TRC_AUTO; + p->opts.target_prim = PL_COLOR_PRIM_UNKNOWN; + p->opts.target_trc = PL_COLOR_TRC_UNKNOWN; p->use_lut_3d = false; MP_WARN(p, "Disabling color management (GLSL version too old).\n"); } diff --git a/video/out/gpu/video.h b/video/out/gpu/video.h index 411d336a2191..d1b7b3fc519c 100644 --- a/video/out/gpu/video.h +++ b/video/out/gpu/video.h @@ -215,7 +215,6 @@ void gl_video_set_ambient_lux(struct gl_video *p, int lux); void gl_video_set_icc_profile(struct gl_video *p, bstr icc_data); bool gl_video_icc_auto_enabled(struct gl_video *p); bool gl_video_gamma_auto_enabled(struct gl_video *p); -struct mp_colorspace gl_video_get_output_colorspace(struct gl_video *p); void gl_video_reset(struct gl_video *p); bool gl_video_showing_interpolated_frame(struct gl_video *p); diff --git a/video/out/gpu/video_shaders.c b/video/out/gpu/video_shaders.c index 6c0e8a815e56..2201e12d4639 100644 --- a/video/out/gpu/video_shaders.c +++ b/video/out/gpu/video_shaders.c @@ -338,9 +338,9 @@ static const float SLOG_A = 0.432699, // These functions always output to a normalized scale of [0,1], for // convenience of the video.c code that calls it. To get the values in an // absolute scale, multiply the result by `mp_trc_nom_peak(trc)` -void pass_linearize(struct gl_shader_cache *sc, enum mp_csp_trc trc) +void pass_linearize(struct gl_shader_cache *sc, enum pl_color_transfer trc) { - if (trc == MP_CSP_TRC_LINEAR) + if (trc == PL_COLOR_TRC_LINEAR) return; GLSLF("// linearize\n"); @@ -353,40 +353,40 @@ void pass_linearize(struct gl_shader_cache *sc, enum mp_csp_trc trc) GLSL(color.rgb = clamp(color.rgb, 0.0, 1.0);) switch (trc) { - case MP_CSP_TRC_SRGB: + case PL_COLOR_TRC_SRGB: GLSLF("color.rgb = mix(color.rgb * vec3(1.0/12.92), \n" " pow((color.rgb + vec3(0.055))/vec3(1.055), vec3(2.4)), \n" " %s(lessThan(vec3(0.04045), color.rgb))); \n", gl_sc_bvec(sc, 3)); break; - case MP_CSP_TRC_BT_1886: + case PL_COLOR_TRC_BT_1886: GLSL(color.rgb = pow(color.rgb, vec3(2.4));) break; - case MP_CSP_TRC_GAMMA18: + case PL_COLOR_TRC_GAMMA18: GLSL(color.rgb = pow(color.rgb, vec3(1.8));) break; - case MP_CSP_TRC_GAMMA20: + case PL_COLOR_TRC_GAMMA20: GLSL(color.rgb = pow(color.rgb, vec3(2.0));) break; - case MP_CSP_TRC_GAMMA22: + case PL_COLOR_TRC_GAMMA22: GLSL(color.rgb = pow(color.rgb, vec3(2.2));) break; - case MP_CSP_TRC_GAMMA24: + case PL_COLOR_TRC_GAMMA24: GLSL(color.rgb = pow(color.rgb, vec3(2.4));) break; - case MP_CSP_TRC_GAMMA26: + case PL_COLOR_TRC_GAMMA26: GLSL(color.rgb = pow(color.rgb, vec3(2.6));) break; - case MP_CSP_TRC_GAMMA28: + case PL_COLOR_TRC_GAMMA28: GLSL(color.rgb = pow(color.rgb, vec3(2.8));) break; - case MP_CSP_TRC_PRO_PHOTO: + case PL_COLOR_TRC_PRO_PHOTO: GLSLF("color.rgb = mix(color.rgb * vec3(1.0/16.0), \n" " pow(color.rgb, vec3(1.8)), \n" " %s(lessThan(vec3(0.03125), color.rgb))); \n", gl_sc_bvec(sc, 3)); break; - case MP_CSP_TRC_PQ: + case PL_COLOR_TRC_PQ: GLSLF("color.rgb = pow(color.rgb, vec3(1.0/%f));\n", PQ_M2); GLSLF("color.rgb = max(color.rgb - vec3(%f), vec3(0.0)) \n" " / (vec3(%f) - vec3(%f) * color.rgb);\n", @@ -396,33 +396,33 @@ void pass_linearize(struct gl_shader_cache *sc, enum mp_csp_trc trc) // MP_REF_WHITE instead, so rescale GLSLF("color.rgb *= vec3(%f);\n", 10000 / MP_REF_WHITE); break; - case MP_CSP_TRC_HLG: + case PL_COLOR_TRC_HLG: GLSLF("color.rgb = mix(vec3(4.0) * color.rgb * color.rgb,\n" " exp((color.rgb - vec3(%f)) * vec3(1.0/%f)) + vec3(%f),\n" " %s(lessThan(vec3(0.5), color.rgb)));\n", HLG_C, HLG_A, HLG_B, gl_sc_bvec(sc, 3)); GLSLF("color.rgb *= vec3(1.0/%f);\n", MP_REF_WHITE_HLG); break; - case MP_CSP_TRC_V_LOG: + case PL_COLOR_TRC_V_LOG: GLSLF("color.rgb = mix((color.rgb - vec3(0.125)) * vec3(1.0/5.6), \n" " pow(vec3(10.0), (color.rgb - vec3(%f)) * vec3(1.0/%f)) \n" " - vec3(%f), \n" " %s(lessThanEqual(vec3(0.181), color.rgb))); \n", VLOG_D, VLOG_C, VLOG_B, gl_sc_bvec(sc, 3)); break; - case MP_CSP_TRC_S_LOG1: + case PL_COLOR_TRC_S_LOG1: GLSLF("color.rgb = pow(vec3(10.0), (color.rgb - vec3(%f)) * vec3(1.0/%f))\n" " - vec3(%f);\n", SLOG_C, SLOG_A, SLOG_B); break; - case MP_CSP_TRC_S_LOG2: + case PL_COLOR_TRC_S_LOG2: GLSLF("color.rgb = mix((color.rgb - vec3(%f)) * vec3(1.0/%f), \n" " (pow(vec3(10.0), (color.rgb - vec3(%f)) * vec3(1.0/%f)) \n" " - vec3(%f)) * vec3(1.0/%f), \n" " %s(lessThanEqual(vec3(%f), color.rgb))); \n", SLOG_Q, SLOG_P, SLOG_C, SLOG_A, SLOG_B, SLOG_K2, gl_sc_bvec(sc, 3), SLOG_Q); break; - case MP_CSP_TRC_ST428: + case PL_COLOR_TRC_ST428: GLSL(color.rgb = vec3(52.37/48.0) * pow(color.rgb, vec3(2.6));); break; default: @@ -438,9 +438,9 @@ void pass_linearize(struct gl_shader_cache *sc, enum mp_csp_trc trc) // reference monitor. // // Like pass_linearize, this functions ingests values on an normalized scale -void pass_delinearize(struct gl_shader_cache *sc, enum mp_csp_trc trc) +void pass_delinearize(struct gl_shader_cache *sc, enum pl_color_transfer trc) { - if (trc == MP_CSP_TRC_LINEAR) + if (trc == PL_COLOR_TRC_LINEAR) return; GLSLF("// delinearize\n"); @@ -448,41 +448,41 @@ void pass_delinearize(struct gl_shader_cache *sc, enum mp_csp_trc trc) GLSLF("color.rgb *= vec3(%f);\n", mp_trc_nom_peak(trc)); switch (trc) { - case MP_CSP_TRC_SRGB: + case PL_COLOR_TRC_SRGB: GLSLF("color.rgb = mix(color.rgb * vec3(12.92), \n" " vec3(1.055) * pow(color.rgb, vec3(1.0/2.4)) \n" " - vec3(0.055), \n" " %s(lessThanEqual(vec3(0.0031308), color.rgb))); \n", gl_sc_bvec(sc, 3)); break; - case MP_CSP_TRC_BT_1886: + case PL_COLOR_TRC_BT_1886: GLSL(color.rgb = pow(color.rgb, vec3(1.0/2.4));) break; - case MP_CSP_TRC_GAMMA18: + case PL_COLOR_TRC_GAMMA18: GLSL(color.rgb = pow(color.rgb, vec3(1.0/1.8));) break; - case MP_CSP_TRC_GAMMA20: + case PL_COLOR_TRC_GAMMA20: GLSL(color.rgb = pow(color.rgb, vec3(1.0/2.0));) break; - case MP_CSP_TRC_GAMMA22: + case PL_COLOR_TRC_GAMMA22: GLSL(color.rgb = pow(color.rgb, vec3(1.0/2.2));) break; - case MP_CSP_TRC_GAMMA24: + case PL_COLOR_TRC_GAMMA24: GLSL(color.rgb = pow(color.rgb, vec3(1.0/2.4));) break; - case MP_CSP_TRC_GAMMA26: + case PL_COLOR_TRC_GAMMA26: GLSL(color.rgb = pow(color.rgb, vec3(1.0/2.6));) break; - case MP_CSP_TRC_GAMMA28: + case PL_COLOR_TRC_GAMMA28: GLSL(color.rgb = pow(color.rgb, vec3(1.0/2.8));) break; - case MP_CSP_TRC_PRO_PHOTO: + case PL_COLOR_TRC_PRO_PHOTO: GLSLF("color.rgb = mix(color.rgb * vec3(16.0), \n" " pow(color.rgb, vec3(1.0/1.8)), \n" " %s(lessThanEqual(vec3(0.001953), color.rgb))); \n", gl_sc_bvec(sc, 3)); break; - case MP_CSP_TRC_PQ: + case PL_COLOR_TRC_PQ: GLSLF("color.rgb *= vec3(1.0/%f);\n", 10000 / MP_REF_WHITE); GLSLF("color.rgb = pow(color.rgb, vec3(%f));\n", PQ_M1); GLSLF("color.rgb = (vec3(%f) + vec3(%f) * color.rgb) \n" @@ -490,32 +490,32 @@ void pass_delinearize(struct gl_shader_cache *sc, enum mp_csp_trc trc) PQ_C1, PQ_C2, PQ_C3); GLSLF("color.rgb = pow(color.rgb, vec3(%f));\n", PQ_M2); break; - case MP_CSP_TRC_HLG: + case PL_COLOR_TRC_HLG: GLSLF("color.rgb *= vec3(%f);\n", MP_REF_WHITE_HLG); GLSLF("color.rgb = mix(vec3(0.5) * sqrt(color.rgb),\n" " vec3(%f) * log(color.rgb - vec3(%f)) + vec3(%f),\n" " %s(lessThan(vec3(1.0), color.rgb)));\n", HLG_A, HLG_B, HLG_C, gl_sc_bvec(sc, 3)); break; - case MP_CSP_TRC_V_LOG: + case PL_COLOR_TRC_V_LOG: GLSLF("color.rgb = mix(vec3(5.6) * color.rgb + vec3(0.125), \n" " vec3(%f) * log(color.rgb + vec3(%f)) \n" " + vec3(%f), \n" " %s(lessThanEqual(vec3(0.01), color.rgb))); \n", VLOG_C / M_LN10, VLOG_B, VLOG_D, gl_sc_bvec(sc, 3)); break; - case MP_CSP_TRC_S_LOG1: + case PL_COLOR_TRC_S_LOG1: GLSLF("color.rgb = vec3(%f) * log(color.rgb + vec3(%f)) + vec3(%f);\n", SLOG_A / M_LN10, SLOG_B, SLOG_C); break; - case MP_CSP_TRC_S_LOG2: + case PL_COLOR_TRC_S_LOG2: GLSLF("color.rgb = mix(vec3(%f) * color.rgb + vec3(%f), \n" " vec3(%f) * log(vec3(%f) * color.rgb + vec3(%f)) \n" " + vec3(%f), \n" " %s(lessThanEqual(vec3(0.0), color.rgb))); \n", SLOG_P, SLOG_Q, SLOG_A / M_LN10, SLOG_K2, SLOG_B, SLOG_C, gl_sc_bvec(sc, 3)); break; - case MP_CSP_TRC_ST428: + case PL_COLOR_TRC_ST428: GLSL(color.rgb = pow(color.rgb * vec3(48.0/52.37), vec3(1.0/2.6));); break; default: @@ -834,7 +834,8 @@ static void pass_tone_map(struct gl_shader_cache *sc, // the caller to have already bound the appropriate SSBO and set up the compute // shader metadata void pass_color_map(struct gl_shader_cache *sc, bool is_linear, - struct mp_colorspace src, struct mp_colorspace dst, + struct pl_color_space src, struct pl_color_space dst, + enum mp_csp_light src_light, enum mp_csp_light dst_light, const struct gl_tone_map_opts *opts) { GLSLF("// color mapping\n"); @@ -847,29 +848,29 @@ void pass_color_map(struct gl_shader_cache *sc, bool is_linear, mp_get_rgb2xyz_matrix(mp_get_csp_primaries(dst.primaries), rgb2xyz); gl_sc_uniform_vec3(sc, "dst_luma", rgb2xyz[1]); - bool need_ootf = src.light != dst.light; - if (src.light == MP_CSP_LIGHT_SCENE_HLG && src.hdr.max_luma != dst.hdr.max_luma) + bool need_ootf = src_light != dst_light; + if (src_light == MP_CSP_LIGHT_SCENE_HLG && src.hdr.max_luma != dst.hdr.max_luma) need_ootf = true; // All operations from here on require linear light as a starting point, - // so we linearize even if src.gamma == dst.gamma when one of the other + // so we linearize even if src.gamma == dst.transfer when one of the other // operations needs it - bool need_linear = src.gamma != dst.gamma || + bool need_linear = src.transfer != dst.transfer || src.primaries != dst.primaries || src.hdr.max_luma != dst.hdr.max_luma || need_ootf; if (need_linear && !is_linear) { // We also pull it up so that 1.0 is the reference white - pass_linearize(sc, src.gamma); + pass_linearize(sc, src.transfer); is_linear = true; } // Pre-scale the incoming values into an absolute scale - GLSLF("color.rgb *= vec3(%f);\n", mp_trc_nom_peak(src.gamma)); + GLSLF("color.rgb *= vec3(%f);\n", mp_trc_nom_peak(src.transfer)); if (need_ootf) - pass_ootf(sc, src.light, src.hdr.max_luma / MP_REF_WHITE); + pass_ootf(sc, src_light, src.hdr.max_luma / MP_REF_WHITE); // Tone map to prevent clipping due to excessive brightness if (src.hdr.max_luma > dst.hdr.max_luma) { @@ -900,14 +901,14 @@ void pass_color_map(struct gl_shader_cache *sc, bool is_linear, } if (need_ootf) - pass_inverse_ootf(sc, dst.light, dst.hdr.max_luma / MP_REF_WHITE); + pass_inverse_ootf(sc, dst_light, dst.hdr.max_luma / MP_REF_WHITE); // Post-scale the outgoing values from absolute scale to normalized. // For SDR, we normalize to the chosen signal peak. For HDR, we normalize // to the encoding range of the transfer function. float dst_range = dst.hdr.max_luma / MP_REF_WHITE; - if (mp_trc_is_hdr(dst.gamma)) - dst_range = mp_trc_nom_peak(dst.gamma); + if (mp_trc_is_hdr(dst.transfer)) + dst_range = mp_trc_nom_peak(dst.transfer); GLSLF("color.rgb *= vec3(%f);\n", 1.0 / dst_range); @@ -919,7 +920,7 @@ void pass_color_map(struct gl_shader_cache *sc, bool is_linear, } if (is_linear) - pass_delinearize(sc, dst.gamma); + pass_delinearize(sc, dst.transfer); } // Wide usage friendly PRNG, shamelessly stolen from a GLSL tricks forum post. @@ -964,7 +965,7 @@ const struct m_sub_options deband_conf = { // Stochastically sample a debanded result from a hooked texture. void pass_sample_deband(struct gl_shader_cache *sc, struct deband_opts *opts, - AVLFG *lfg, enum mp_csp_trc trc) + AVLFG *lfg, enum pl_color_transfer trc) { // Initialize the PRNG GLSLF("{\n"); diff --git a/video/out/gpu/video_shaders.h b/video/out/gpu/video_shaders.h index 27e7874c6d19..7547df6a02cb 100644 --- a/video/out/gpu/video_shaders.h +++ b/video/out/gpu/video_shaders.h @@ -44,15 +44,16 @@ void pass_sample_bicubic_fast(struct gl_shader_cache *sc); void pass_sample_oversample(struct gl_shader_cache *sc, struct scaler *scaler, int w, int h); -void pass_linearize(struct gl_shader_cache *sc, enum mp_csp_trc trc); -void pass_delinearize(struct gl_shader_cache *sc, enum mp_csp_trc trc); +void pass_linearize(struct gl_shader_cache *sc, enum pl_color_transfer trc); +void pass_delinearize(struct gl_shader_cache *sc, enum pl_color_transfer trc); void pass_color_map(struct gl_shader_cache *sc, bool is_linear, - struct mp_colorspace src, struct mp_colorspace dst, + struct pl_color_space src, struct pl_color_space dst, + enum mp_csp_light src_light, enum mp_csp_light dst_light, const struct gl_tone_map_opts *opts); void pass_sample_deband(struct gl_shader_cache *sc, struct deband_opts *opts, - AVLFG *lfg, enum mp_csp_trc trc); + AVLFG *lfg, enum pl_color_transfer trc); void pass_sample_unsharp(struct gl_shader_cache *sc, float param); diff --git a/video/out/opengl/hwdec_rpi.c b/video/out/opengl/hwdec_rpi.c index 5362832b0334..b90fae571d1e 100644 --- a/video/out/opengl/hwdec_rpi.c +++ b/video/out/opengl/hwdec_rpi.c @@ -82,12 +82,12 @@ static size_t layout_buffer(struct mp_image *mpi, MMAL_BUFFER_HEADER_T *buffer, return size; } -static MMAL_FOURCC_T map_csp(enum mp_csp csp) +static MMAL_FOURCC_T map_csp(enum pl_color_system csp) { switch (csp) { - case MP_CSP_BT_601: return MMAL_COLOR_SPACE_ITUR_BT601; - case MP_CSP_BT_709: return MMAL_COLOR_SPACE_ITUR_BT709; - case MP_CSP_SMPTE_240M: return MMAL_COLOR_SPACE_SMPTE240M; + case PL_COLOR_SYSTEM_BT_601: return MMAL_COLOR_SPACE_ITUR_BT601; + case PL_COLOR_SYSTEM_BT_709: return MMAL_COLOR_SPACE_ITUR_BT709; + case PL_COLOR_SYSTEM_SMPTE_240M: return MMAL_COLOR_SPACE_SMPTE240M; default: return MMAL_COLOR_SPACE_UNKNOWN; } } @@ -201,7 +201,7 @@ static int enable_renderer(struct ra_hwdec *hw) input->format->es->video.height = MP_ALIGN_UP(params->h, ALIGN_H); input->format->es->video.crop = (MMAL_RECT_T){0, 0, params->w, params->h}; input->format->es->video.par = (MMAL_RATIONAL_T){params->p_w, params->p_h}; - input->format->es->video.color_space = map_csp(params->color.space); + input->format->es->video.color_space = map_csp(params->repr.sys); if (mmal_port_format_commit(input)) return -1; diff --git a/video/out/placebo/utils.c b/video/out/placebo/utils.c index 1209b721217d..7bb96dd20af6 100644 --- a/video/out/placebo/utils.c +++ b/video/out/placebo/utils.c @@ -66,154 +66,6 @@ void mppl_log_set_probing(pl_log log, bool probing) pl_log_update(log, ¶ms); } -enum pl_color_primaries mp_prim_to_pl(enum mp_csp_prim prim) -{ - switch (prim) { - case MP_CSP_PRIM_AUTO: return PL_COLOR_PRIM_UNKNOWN; - case MP_CSP_PRIM_BT_601_525: return PL_COLOR_PRIM_BT_601_525; - case MP_CSP_PRIM_BT_601_625: return PL_COLOR_PRIM_BT_601_625; - case MP_CSP_PRIM_BT_709: return PL_COLOR_PRIM_BT_709; - case MP_CSP_PRIM_BT_2020: return PL_COLOR_PRIM_BT_2020; - case MP_CSP_PRIM_BT_470M: return PL_COLOR_PRIM_BT_470M; - case MP_CSP_PRIM_APPLE: return PL_COLOR_PRIM_APPLE; - case MP_CSP_PRIM_ADOBE: return PL_COLOR_PRIM_ADOBE; - case MP_CSP_PRIM_PRO_PHOTO: return PL_COLOR_PRIM_PRO_PHOTO; - case MP_CSP_PRIM_CIE_1931: return PL_COLOR_PRIM_CIE_1931; - case MP_CSP_PRIM_DCI_P3: return PL_COLOR_PRIM_DCI_P3; - case MP_CSP_PRIM_DISPLAY_P3: return PL_COLOR_PRIM_DISPLAY_P3; - case MP_CSP_PRIM_V_GAMUT: return PL_COLOR_PRIM_V_GAMUT; - case MP_CSP_PRIM_S_GAMUT: return PL_COLOR_PRIM_S_GAMUT; - case MP_CSP_PRIM_EBU_3213: return PL_COLOR_PRIM_EBU_3213; - case MP_CSP_PRIM_FILM_C: return PL_COLOR_PRIM_FILM_C; - case MP_CSP_PRIM_ACES_AP0: return PL_COLOR_PRIM_ACES_AP0; - case MP_CSP_PRIM_ACES_AP1: return PL_COLOR_PRIM_ACES_AP1; - case MP_CSP_PRIM_COUNT: return PL_COLOR_PRIM_COUNT; - } - - MP_ASSERT_UNREACHABLE(); -} - -enum mp_csp_prim mp_prim_from_pl(enum pl_color_primaries prim) -{ - switch (prim){ - case PL_COLOR_PRIM_UNKNOWN: return MP_CSP_PRIM_AUTO; - case PL_COLOR_PRIM_BT_601_525: return MP_CSP_PRIM_BT_601_525; - case PL_COLOR_PRIM_BT_601_625: return MP_CSP_PRIM_BT_601_625; - case PL_COLOR_PRIM_BT_709: return MP_CSP_PRIM_BT_709; - case PL_COLOR_PRIM_BT_2020: return MP_CSP_PRIM_BT_2020; - case PL_COLOR_PRIM_BT_470M: return MP_CSP_PRIM_BT_470M; - case PL_COLOR_PRIM_APPLE: return MP_CSP_PRIM_APPLE; - case PL_COLOR_PRIM_ADOBE: return MP_CSP_PRIM_ADOBE; - case PL_COLOR_PRIM_PRO_PHOTO: return MP_CSP_PRIM_PRO_PHOTO; - case PL_COLOR_PRIM_CIE_1931: return MP_CSP_PRIM_CIE_1931; - case PL_COLOR_PRIM_DCI_P3: return MP_CSP_PRIM_DCI_P3; - case PL_COLOR_PRIM_DISPLAY_P3: return MP_CSP_PRIM_DISPLAY_P3; - case PL_COLOR_PRIM_V_GAMUT: return MP_CSP_PRIM_V_GAMUT; - case PL_COLOR_PRIM_S_GAMUT: return MP_CSP_PRIM_S_GAMUT; - case PL_COLOR_PRIM_EBU_3213: return MP_CSP_PRIM_EBU_3213; - case PL_COLOR_PRIM_FILM_C: return MP_CSP_PRIM_FILM_C; - case PL_COLOR_PRIM_ACES_AP0: return MP_CSP_PRIM_ACES_AP0; - case PL_COLOR_PRIM_ACES_AP1: return MP_CSP_PRIM_ACES_AP1; - case PL_COLOR_PRIM_COUNT: return MP_CSP_PRIM_COUNT; - } - - MP_ASSERT_UNREACHABLE(); -} - -enum pl_color_transfer mp_trc_to_pl(enum mp_csp_trc trc) -{ - switch (trc) { - case MP_CSP_TRC_AUTO: return PL_COLOR_TRC_UNKNOWN; - case MP_CSP_TRC_BT_1886: return PL_COLOR_TRC_BT_1886; - case MP_CSP_TRC_SRGB: return PL_COLOR_TRC_SRGB; - case MP_CSP_TRC_LINEAR: return PL_COLOR_TRC_LINEAR; - case MP_CSP_TRC_GAMMA18: return PL_COLOR_TRC_GAMMA18; - case MP_CSP_TRC_GAMMA20: return PL_COLOR_TRC_GAMMA20; - case MP_CSP_TRC_GAMMA22: return PL_COLOR_TRC_GAMMA22; - case MP_CSP_TRC_GAMMA24: return PL_COLOR_TRC_GAMMA24; - case MP_CSP_TRC_GAMMA26: return PL_COLOR_TRC_GAMMA26; - case MP_CSP_TRC_GAMMA28: return PL_COLOR_TRC_GAMMA28; - case MP_CSP_TRC_PRO_PHOTO: return PL_COLOR_TRC_PRO_PHOTO; - case MP_CSP_TRC_PQ: return PL_COLOR_TRC_PQ; - case MP_CSP_TRC_HLG: return PL_COLOR_TRC_HLG; - case MP_CSP_TRC_V_LOG: return PL_COLOR_TRC_V_LOG; - case MP_CSP_TRC_S_LOG1: return PL_COLOR_TRC_S_LOG1; - case MP_CSP_TRC_S_LOG2: return PL_COLOR_TRC_S_LOG2; - case MP_CSP_TRC_ST428: return PL_COLOR_TRC_ST428; - case MP_CSP_TRC_COUNT: return PL_COLOR_TRC_COUNT; - } - - MP_ASSERT_UNREACHABLE(); -} - -enum mp_csp_trc mp_trc_from_pl(enum pl_color_transfer trc) -{ - switch (trc){ - case PL_COLOR_TRC_UNKNOWN: return MP_CSP_TRC_AUTO; - case PL_COLOR_TRC_BT_1886: return MP_CSP_TRC_BT_1886; - case PL_COLOR_TRC_SRGB: return MP_CSP_TRC_SRGB; - case PL_COLOR_TRC_LINEAR: return MP_CSP_TRC_LINEAR; - case PL_COLOR_TRC_GAMMA18: return MP_CSP_TRC_GAMMA18; - case PL_COLOR_TRC_GAMMA20: return MP_CSP_TRC_GAMMA20; - case PL_COLOR_TRC_GAMMA22: return MP_CSP_TRC_GAMMA22; - case PL_COLOR_TRC_GAMMA24: return MP_CSP_TRC_GAMMA24; - case PL_COLOR_TRC_GAMMA26: return MP_CSP_TRC_GAMMA26; - case PL_COLOR_TRC_GAMMA28: return MP_CSP_TRC_GAMMA28; - case PL_COLOR_TRC_PRO_PHOTO: return MP_CSP_TRC_PRO_PHOTO; - case PL_COLOR_TRC_PQ: return MP_CSP_TRC_PQ; - case PL_COLOR_TRC_HLG: return MP_CSP_TRC_HLG; - case PL_COLOR_TRC_V_LOG: return MP_CSP_TRC_V_LOG; - case PL_COLOR_TRC_S_LOG1: return MP_CSP_TRC_S_LOG1; - case PL_COLOR_TRC_S_LOG2: return MP_CSP_TRC_S_LOG2; - case PL_COLOR_TRC_ST428: return MP_CSP_TRC_ST428; - case PL_COLOR_TRC_COUNT: return MP_CSP_TRC_COUNT; - } - - MP_ASSERT_UNREACHABLE(); -} - -enum pl_color_system mp_csp_to_pl(enum mp_csp csp) -{ - switch (csp) { - case MP_CSP_AUTO: return PL_COLOR_SYSTEM_UNKNOWN; - case MP_CSP_BT_601: return PL_COLOR_SYSTEM_BT_601; - case MP_CSP_BT_709: return PL_COLOR_SYSTEM_BT_709; - case MP_CSP_SMPTE_240M: return PL_COLOR_SYSTEM_SMPTE_240M; - case MP_CSP_BT_2020_NC: return PL_COLOR_SYSTEM_BT_2020_NC; - case MP_CSP_BT_2020_C: return PL_COLOR_SYSTEM_BT_2020_C; - case MP_CSP_RGB: return PL_COLOR_SYSTEM_RGB; - case MP_CSP_XYZ: return PL_COLOR_SYSTEM_XYZ; - case MP_CSP_YCGCO: return PL_COLOR_SYSTEM_YCGCO; - case MP_CSP_COUNT: return PL_COLOR_SYSTEM_COUNT; - } - - MP_ASSERT_UNREACHABLE(); -} - -enum pl_color_levels mp_levels_to_pl(enum mp_csp_levels levels) -{ - switch (levels) { - case MP_CSP_LEVELS_AUTO: return PL_COLOR_LEVELS_UNKNOWN; - case MP_CSP_LEVELS_TV: return PL_COLOR_LEVELS_TV; - case MP_CSP_LEVELS_PC: return PL_COLOR_LEVELS_PC; - case MP_CSP_LEVELS_COUNT: return PL_COLOR_LEVELS_COUNT; - } - - MP_ASSERT_UNREACHABLE(); -} - -enum mp_csp_levels mp_levels_from_pl(enum pl_color_levels levels) -{ - switch (levels){ - case PL_COLOR_LEVELS_UNKNOWN: return MP_CSP_LEVELS_AUTO; - case PL_COLOR_LEVELS_TV: return MP_CSP_LEVELS_TV; - case PL_COLOR_LEVELS_PC: return MP_CSP_LEVELS_PC; - case PL_COLOR_LEVELS_COUNT: return MP_CSP_LEVELS_COUNT; - } - - MP_ASSERT_UNREACHABLE(); -} - enum pl_alpha_mode mp_alpha_to_pl(enum mp_alpha_type alpha) { switch (alpha) { diff --git a/video/out/placebo/utils.h b/video/out/placebo/utils.h index bf780a82b35b..103fa4ce2462 100644 --- a/video/out/placebo/utils.h +++ b/video/out/placebo/utils.h @@ -27,13 +27,6 @@ static inline struct pl_rect2d mp_rect2d_to_pl(struct mp_rect rc) }; } -enum pl_color_primaries mp_prim_to_pl(enum mp_csp_prim prim); -enum mp_csp_prim mp_prim_from_pl(enum pl_color_primaries prim); -enum pl_color_transfer mp_trc_to_pl(enum mp_csp_trc trc); -enum mp_csp_trc mp_trc_from_pl(enum pl_color_transfer trc); -enum pl_color_system mp_csp_to_pl(enum mp_csp csp); -enum pl_color_levels mp_levels_to_pl(enum mp_csp_levels levels); -enum mp_csp_levels mp_levels_from_pl(enum pl_color_levels levels); enum pl_alpha_mode mp_alpha_to_pl(enum mp_alpha_type alpha); enum pl_chroma_location mp_chroma_to_pl(enum mp_chroma_location chroma); diff --git a/video/out/vo_gpu_next.c b/video/out/vo_gpu_next.c index 60fcaedd4246..7b3b3891ba68 100644 --- a/video/out/vo_gpu_next.c +++ b/video/out/vo_gpu_next.c @@ -129,7 +129,7 @@ struct priv { struct mp_csp_equalizer_state *video_eq; struct scaler_params scalers[SCALER_COUNT]; const struct pl_hook **hooks; // storage for `params.hooks` - enum mp_csp_levels output_levels; + enum pl_color_levels output_levels; char **raw_opts; struct pl_icc_params icc_params; @@ -440,8 +440,8 @@ static int plane_data_from_imgfmt(struct pl_plane_data out_data[4], static struct pl_color_space get_mpi_csp(struct vo *vo, struct mp_image *mpi) { struct pl_color_space csp = { - .primaries = mp_prim_to_pl(mpi->params.color.primaries), - .transfer = mp_trc_to_pl(mpi->params.color.gamma), + .primaries = mpi->params.color.primaries, + .transfer = mpi->params.color.transfer, .hdr = mpi->params.color.hdr, }; return csp; @@ -569,8 +569,8 @@ static bool map_frame(pl_gpu gpu, pl_tex *tex, const struct pl_source_frame *src *frame = (struct pl_frame) { .color = get_mpi_csp(vo, mpi), .repr = { - .sys = mp_csp_to_pl(par->color.space), - .levels = mp_levels_to_pl(par->color.levels), + .sys = par->repr.sys, + .levels = par->repr.levels, .alpha = mp_alpha_to_pl(par->alpha), }, .profile = { @@ -584,14 +584,14 @@ static bool map_frame(pl_gpu gpu, pl_tex *tex, const struct pl_source_frame *src // mp_image, like AVFrame, likes communicating RGB/XYZ/YCbCr status // implicitly via the image format, rather than the actual tagging. switch (mp_imgfmt_get_forced_csp(par->imgfmt)) { - case MP_CSP_RGB: + case PL_COLOR_SYSTEM_RGB: frame->repr.sys = PL_COLOR_SYSTEM_RGB; frame->repr.levels = PL_COLOR_LEVELS_FULL; break; - case MP_CSP_XYZ: + case PL_COLOR_SYSTEM_XYZ: frame->repr.sys = PL_COLOR_SYSTEM_XYZ; break; - case MP_CSP_AUTO: + case PL_COLOR_SYSTEM_UNKNOWN: if (!frame->repr.sys) frame->repr.sys = pl_color_system_guess_ycbcr(par->w, par->h); break; @@ -779,11 +779,11 @@ static void apply_target_options(struct priv *p, struct pl_frame *target) // Colorspace overrides const struct gl_video_opts *opts = p->opts_cache->opts; if (p->output_levels) - target->repr.levels = mp_levels_to_pl(p->output_levels); + target->repr.levels = p->output_levels; if (opts->target_prim) - target->color.primaries = mp_prim_to_pl(opts->target_prim); + target->color.primaries = opts->target_prim; if (opts->target_trc) - target->color.transfer = mp_trc_to_pl(opts->target_trc); + target->color.transfer = opts->target_trc; // If swapchain returned a value use this, override is used in hint if (opts->target_peak && !target->color.hdr.max_luma) target->color.hdr.max_luma = opts->target_peak; @@ -792,7 +792,7 @@ static void apply_target_options(struct priv *p, struct pl_frame *target) if (opts->target_gamut) { // Ensure resulting gamut still fits inside container const struct pl_raw_primaries *gamut, *container; - gamut = pl_raw_primaries_get(mp_prim_to_pl(opts->target_gamut)); + gamut = pl_raw_primaries_get(opts->target_gamut); container = pl_raw_primaries_get(target->color.primaries); target->color.hdr.prim = pl_primaries_clip(gamut, container); } @@ -912,9 +912,9 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame) if (p->target_hint && frame->current) { struct pl_color_space hint = get_mpi_csp(vo, frame->current); if (opts->target_prim) - hint.primaries = mp_prim_to_pl(opts->target_prim); + hint.primaries = opts->target_prim; if (opts->target_trc) - hint.transfer = mp_trc_to_pl(opts->target_trc); + hint.transfer = opts->target_trc; if (opts->target_peak) hint.hdr.max_luma = opts->target_peak; apply_target_contrast(p, &hint); @@ -1327,9 +1327,9 @@ static void video_screenshot(struct vo *vo, struct voctrl_screenshot *args) if (!args->res) goto done; - args->res->params.color.primaries = mp_prim_from_pl(target.color.primaries); - args->res->params.color.gamma = mp_trc_from_pl(target.color.transfer); - args->res->params.color.levels = mp_levels_from_pl(target.repr.levels); + args->res->params.color.primaries = target.color.primaries; + args->res->params.color.transfer = target.color.transfer; + args->res->params.repr.levels = target.repr.levels; args->res->params.color.hdr = target.color.hdr; if (args->scaled) args->res->params.p_w = args->res->params.p_h = 1; diff --git a/video/out/vo_lavc.c b/video/out/vo_lavc.c index 7170c1d5e70b..9008e2269910 100644 --- a/video/out/vo_lavc.c +++ b/video/out/vo_lavc.c @@ -23,6 +23,10 @@ #include <stdio.h> #include <stdlib.h> +#include <pthread.h> + +#include <libplacebo/utils/libav.h> + #include "common/common.h" #include "options/options.h" #include "video/fmt-conversion.h" @@ -112,8 +116,8 @@ static int reconfig2(struct vo *vo, struct mp_image *img) encoder->width = width; encoder->height = height; encoder->pix_fmt = pix_fmt; - encoder->colorspace = mp_csp_to_avcol_spc(params->color.space); - encoder->color_range = mp_csp_levels_to_avcol_range(params->color.levels); + encoder->colorspace = pl_system_to_av(params->repr.sys); + encoder->color_range = pl_levels_to_av(params->repr.levels); AVRational tb; diff --git a/video/out/vo_rpi.c b/video/out/vo_rpi.c index 55f1a68edb49..c53d027019aa 100644 --- a/video/out/vo_rpi.c +++ b/video/out/vo_rpi.c @@ -587,12 +587,12 @@ static int query_format(struct vo *vo, int format) return format == IMGFMT_MMAL || format == IMGFMT_420P; } -static MMAL_FOURCC_T map_csp(enum mp_csp csp) +static MMAL_FOURCC_T map_csp(enum pl_color_system csp) { switch (csp) { - case MP_CSP_BT_601: return MMAL_COLOR_SPACE_ITUR_BT601; - case MP_CSP_BT_709: return MMAL_COLOR_SPACE_ITUR_BT709; - case MP_CSP_SMPTE_240M: return MMAL_COLOR_SPACE_SMPTE240M; + case PL_COLOR_SYSTEM_BT_601: return MMAL_COLOR_SPACE_ITUR_BT601; + case PL_COLOR_SYSTEM_BT_709: return MMAL_COLOR_SPACE_ITUR_BT709; + case PL_COLOR_SYSTEM_SMPTE_240M: return MMAL_COLOR_SPACE_SMPTE240M; default: return MMAL_COLOR_SPACE_UNKNOWN; } } @@ -642,7 +642,7 @@ static int reconfig(struct vo *vo, struct mp_image_params *params) input->format->es->video.height = MP_ALIGN_UP(params->h, ALIGN_H); input->format->es->video.crop = (MMAL_RECT_T){0, 0, params->w, params->h}; input->format->es->video.par = (MMAL_RATIONAL_T){params->p_w, params->p_h}; - input->format->es->video.color_space = map_csp(params->color.space); + input->format->es->video.color_space = map_csp(params->repr.sys); if (mmal_port_format_commit(input)) return -1; diff --git a/video/out/vo_vaapi.c b/video/out/vo_vaapi.c index 12888fefe974..2a241300f23b 100644 --- a/video/out/vo_vaapi.c +++ b/video/out/vo_vaapi.c @@ -519,7 +519,7 @@ static bool render_to_screen(struct priv *p, struct mp_image *mpi) CHECK_VA_STATUS(p, "vaAssociateSubpicture()"); } - int flags = va_get_colorspace_flag(p->image_params.color.space) | + int flags = va_get_colorspace_flag(p->image_params.repr.sys) | p->scaling | VA_FRAME_PICTURE; status = vaPutSurface(p->display, surface, diff --git a/video/out/vo_xv.c b/video/out/vo_xv.c index 6c776c507ba1..378602b6554c 100644 --- a/video/out/vo_xv.c +++ b/video/out/vo_xv.c @@ -401,7 +401,7 @@ static void read_xv_csp(struct vo *vo) ctx->cached_csp = 0; int bt709_enabled; if (xv_get_eq(vo, ctx->xv_port, "bt_709", &bt709_enabled)) - ctx->cached_csp = bt709_enabled == 100 ? MP_CSP_BT_709 : MP_CSP_BT_601; + ctx->cached_csp = bt709_enabled == 100 ? PL_COLOR_SYSTEM_BT_709 : PL_COLOR_SYSTEM_BT_601; } @@ -519,7 +519,7 @@ static int reconfig(struct vo *vo, struct mp_image_params *params) ctx->current_buf = 0; ctx->current_ip_buf = 0; - int is_709 = params->color.space == MP_CSP_BT_709; + int is_709 = params->repr.sys == PL_COLOR_SYSTEM_BT_709; xv_set_eq(vo, ctx->xv_port, "bt_709", is_709 * 200 - 100); read_xv_csp(vo); @@ -652,7 +652,7 @@ static struct mp_image get_xv_buffer(struct vo *vo, int buf_index) if (vo->params) { struct mp_image_params params = *vo->params; if (ctx->cached_csp) - params.color.space = ctx->cached_csp; + params.repr.sys = ctx->cached_csp; mp_image_set_attributes(&img, ¶ms); } diff --git a/video/repack.c b/video/repack.c index ce3703ac5c32..00587fbb6b76 100644 --- a/video/repack.c +++ b/video/repack.c @@ -76,8 +76,8 @@ struct mp_repack { int f32_comp_size; float f32_m[4], f32_o[4]; uint32_t f32_pmax[4]; - enum mp_csp f32_csp_space; - enum mp_csp_levels f32_csp_levels; + enum pl_color_system f32_csp_space; + enum pl_color_levels f32_csp_levels; // REPACK_STEP_REPACK: if true, need to copy this plane bool copy_buf[4]; @@ -95,7 +95,7 @@ static int find_gbrp_format(int depth, int num_planes) return 0; struct mp_regular_imgfmt desc = { .component_type = MP_COMPONENT_TYPE_UINT, - .forced_csp = MP_CSP_RGB, + .forced_csp = PL_COLOR_SYSTEM_RGB, .component_size = depth > 8 ? 2 : 1, .component_pad = depth - (depth > 8 ? 16 : 8), .num_planes = num_planes, @@ -467,7 +467,7 @@ static void setup_fringe_rgb_packer(struct mp_repack *rp) return; if (desc.bpp[0] > 16 || (desc.bpp[0] % 8u) || - mp_imgfmt_get_forced_csp(rp->imgfmt_a) != MP_CSP_RGB || + mp_imgfmt_get_forced_csp(rp->imgfmt_a) != PL_COLOR_SYSTEM_RGB || desc.num_planes != 1 || desc.comps[3].size) return; @@ -845,8 +845,8 @@ static void update_repack_float(struct mp_repack *rp) // Image in input format. struct mp_image *ui = rp->pack ? rp->steps[rp->num_steps - 1].buf[1] : rp->steps[0].buf[0]; - enum mp_csp csp = ui->params.color.space; - enum mp_csp_levels levels = ui->params.color.levels; + enum pl_color_system csp = ui->params.repr.sys; + enum pl_color_levels levels = ui->params.repr.levels; if (rp->f32_csp_space == csp && rp->f32_csp_levels == levels) return; @@ -989,8 +989,8 @@ static bool setup_format_ne(struct mp_repack *rp) (desc.component_size != 1 && desc.component_size != 2)) return false; rp->f32_comp_size = desc.component_size; - rp->f32_csp_space = MP_CSP_COUNT; - rp->f32_csp_levels = MP_CSP_LEVELS_COUNT; + rp->f32_csp_space = PL_COLOR_SYSTEM_COUNT; + rp->f32_csp_levels = PL_COLOR_LEVELS_COUNT; rp->steps[rp->num_steps++] = (struct repack_step) { .type = REPACK_STEP_FLOAT, .fmt = { diff --git a/video/sws_utils.c b/video/sws_utils.c index 5e9c35876ac8..9844dd62eb03 100644 --- a/video/sws_utils.c +++ b/video/sws_utils.c @@ -24,6 +24,7 @@ #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 37, 100) #include <libavutil/pixdesc.h> #endif +#include <libplacebo/utils/libav.h> #include "config.h" @@ -156,11 +157,11 @@ bool mp_sws_supports_formats(struct mp_sws_context *ctx, sws_isSupportedOutput(imgfmt2pixfmt(imgfmt_out)); } -static int mp_csp_to_sws_colorspace(enum mp_csp csp) +static int pl_csp_to_sws_colorspace(enum pl_color_system csp) { // The SWS_CS_* macros are just convenience redefinitions of the // AVCOL_SPC_* macros, inside swscale.h. - return mp_csp_to_avcol_spc(csp); + return pl_system_to_av(csp); } static bool cache_valid(struct mp_sws_context *ctx) @@ -289,11 +290,11 @@ int mp_sws_reinit(struct mp_sws_context *ctx) return -1; } - int s_csp = mp_csp_to_sws_colorspace(src.color.space); - int s_range = src.color.levels == MP_CSP_LEVELS_PC; + int s_csp = pl_csp_to_sws_colorspace(src.repr.sys); + int s_range = src.repr.levels == PL_COLOR_LEVELS_FULL; - int d_csp = mp_csp_to_sws_colorspace(dst.color.space); - int d_range = dst.color.levels == MP_CSP_LEVELS_PC; + int d_csp = pl_csp_to_sws_colorspace(src.repr.sys); + int d_range = dst.repr.levels == PL_COLOR_LEVELS_FULL; av_opt_set_int(ctx->sws, "sws_flags", ctx->flags, 0); @@ -407,11 +408,11 @@ int mp_sws_scale(struct mp_sws_context *ctx, struct mp_image *dst, return mp_zimg_convert(ctx->zimg, dst, src) ? 0 : -1; #endif - if (src->params.color.space == MP_CSP_XYZ && dst->params.color.space != MP_CSP_XYZ) { + if (src->params.repr.sys == PL_COLOR_SYSTEM_XYZ && dst->params.repr.sys != PL_COLOR_SYSTEM_XYZ) { // swsscale has hardcoded gamma 2.2 internally and 2.6 for XYZ - dst->params.color.gamma = MP_CSP_TRC_GAMMA22; + dst->params.color.transfer = PL_COLOR_TRC_GAMMA22; // and sRGB primaries... - dst->params.color.primaries = MP_CSP_PRIM_BT_709; + dst->params.color.primaries = PL_COLOR_PRIM_BT_709; // it doesn't adjust white point though, but it is not worth to support // this case. It would require custom prim with equal energy white point // and sRGB primaries. diff --git a/video/vaapi.c b/video/vaapi.c index 08248a73885a..942351ad19d4 100644 --- a/video/vaapi.c +++ b/video/vaapi.c @@ -47,12 +47,12 @@ const struct m_sub_options vaapi_conf = { .size = sizeof(struct vaapi_opts), }; -int va_get_colorspace_flag(enum mp_csp csp) +int va_get_colorspace_flag(enum pl_color_system csp) { switch (csp) { - case MP_CSP_BT_601: return VA_SRC_BT601; - case MP_CSP_BT_709: return VA_SRC_BT709; - case MP_CSP_SMPTE_240M: return VA_SRC_SMPTE_240; + case PL_COLOR_SYSTEM_BT_601: return VA_SRC_BT601; + case PL_COLOR_SYSTEM_BT_709: return VA_SRC_BT709; + case PL_COLOR_SYSTEM_SMPTE_240M: return VA_SRC_SMPTE_240; } return 0; } diff --git a/video/vaapi.h b/video/vaapi.h index 56235bc05be8..3fdf3c1bf0cb 100644 --- a/video/vaapi.h +++ b/video/vaapi.h @@ -42,7 +42,7 @@ struct mp_vaapi_ctx { #define CHECK_VA_STATUS(ctx, msg) \ CHECK_VA_STATUS_LEVEL(ctx, msg, MSGL_ERR) -int va_get_colorspace_flag(enum mp_csp csp); +int va_get_colorspace_flag(enum pl_color_system csp); struct mp_vaapi_ctx * va_initialize(VADisplay *display, struct mp_log *plog, bool probing); void va_destroy(struct mp_vaapi_ctx *ctx); diff --git a/video/zimg.c b/video/zimg.c index 5ff300caab18..f744fe2c4b4f 100644 --- a/video/zimg.c +++ b/video/zimg.c @@ -131,66 +131,66 @@ static zimg_chroma_location_e mp_to_z_chroma(enum mp_chroma_location cl) } } -static zimg_matrix_coefficients_e mp_to_z_matrix(enum mp_csp csp) +static zimg_matrix_coefficients_e pl_to_z_matrix(enum pl_color_system csp) { switch (csp) { - case MP_CSP_BT_601: return ZIMG_MATRIX_BT470_BG; - case MP_CSP_BT_709: return ZIMG_MATRIX_BT709; - case MP_CSP_SMPTE_240M: return ZIMG_MATRIX_ST240_M; - case MP_CSP_BT_2020_NC: return ZIMG_MATRIX_BT2020_NCL; - case MP_CSP_BT_2020_C: return ZIMG_MATRIX_BT2020_CL; - case MP_CSP_RGB: return ZIMG_MATRIX_RGB; - case MP_CSP_XYZ: return ZIMG_MATRIX_RGB; - case MP_CSP_YCGCO: return ZIMG_MATRIX_YCGCO; + case PL_COLOR_SYSTEM_BT_601: return ZIMG_MATRIX_BT470_BG; + case PL_COLOR_SYSTEM_BT_709: return ZIMG_MATRIX_BT709; + case PL_COLOR_SYSTEM_SMPTE_240M: return ZIMG_MATRIX_ST240_M; + case PL_COLOR_SYSTEM_BT_2020_NC: return ZIMG_MATRIX_BT2020_NCL; + case PL_COLOR_SYSTEM_BT_2020_C: return ZIMG_MATRIX_BT2020_CL; + case PL_COLOR_SYSTEM_RGB: return ZIMG_MATRIX_RGB; + case PL_COLOR_SYSTEM_XYZ: return ZIMG_MATRIX_RGB; + case PL_COLOR_SYSTEM_YCGCO: return ZIMG_MATRIX_YCGCO; default: return ZIMG_MATRIX_BT709; } } -static zimg_transfer_characteristics_e mp_to_z_trc(enum mp_csp_trc trc) +static zimg_transfer_characteristics_e pl_to_z_trc(enum pl_color_transfer trc) { switch (trc) { - case MP_CSP_TRC_BT_1886: return ZIMG_TRANSFER_BT709; - case MP_CSP_TRC_SRGB: return ZIMG_TRANSFER_IEC_61966_2_1; - case MP_CSP_TRC_LINEAR: return ZIMG_TRANSFER_LINEAR; - case MP_CSP_TRC_GAMMA22: return ZIMG_TRANSFER_BT470_M; - case MP_CSP_TRC_GAMMA28: return ZIMG_TRANSFER_BT470_BG; - case MP_CSP_TRC_PQ: return ZIMG_TRANSFER_ST2084; - case MP_CSP_TRC_HLG: return ZIMG_TRANSFER_ARIB_B67; + case PL_COLOR_TRC_BT_1886: return ZIMG_TRANSFER_BT709; + case PL_COLOR_TRC_SRGB: return ZIMG_TRANSFER_IEC_61966_2_1; + case PL_COLOR_TRC_LINEAR: return ZIMG_TRANSFER_LINEAR; + case PL_COLOR_TRC_GAMMA22: return ZIMG_TRANSFER_BT470_M; + case PL_COLOR_TRC_GAMMA28: return ZIMG_TRANSFER_BT470_BG; + case PL_COLOR_TRC_PQ: return ZIMG_TRANSFER_ST2084; + case PL_COLOR_TRC_HLG: return ZIMG_TRANSFER_ARIB_B67; #if HAVE_ZIMG_ST428 - case MP_CSP_TRC_ST428: return ZIMG_TRANSFER_ST428; + case PL_COLOR_TRC_ST428: return ZIMG_TRANSFER_ST428; #endif - case MP_CSP_TRC_GAMMA18: // ? - case MP_CSP_TRC_GAMMA20: - case MP_CSP_TRC_GAMMA24: - case MP_CSP_TRC_GAMMA26: - case MP_CSP_TRC_PRO_PHOTO: - case MP_CSP_TRC_V_LOG: - case MP_CSP_TRC_S_LOG1: - case MP_CSP_TRC_S_LOG2: // ? + case PL_COLOR_TRC_GAMMA18: // ? + case PL_COLOR_TRC_GAMMA20: + case PL_COLOR_TRC_GAMMA24: + case PL_COLOR_TRC_GAMMA26: + case PL_COLOR_TRC_PRO_PHOTO: + case PL_COLOR_TRC_V_LOG: + case PL_COLOR_TRC_S_LOG1: + case PL_COLOR_TRC_S_LOG2: // ? default: return ZIMG_TRANSFER_BT709; } } -static zimg_color_primaries_e mp_to_z_prim(enum mp_csp_prim prim) +static zimg_color_primaries_e mp_to_z_prim(enum pl_color_primaries prim) { switch (prim) { - case MP_CSP_PRIM_BT_601_525:return ZIMG_PRIMARIES_ST170_M; - case MP_CSP_PRIM_BT_601_625:return ZIMG_PRIMARIES_BT470_BG; - case MP_CSP_PRIM_BT_709: return ZIMG_PRIMARIES_BT709; - case MP_CSP_PRIM_BT_2020: return ZIMG_PRIMARIES_BT2020; - case MP_CSP_PRIM_BT_470M: return ZIMG_PRIMARIES_BT470_M; - case MP_CSP_PRIM_DCI_P3: return ZIMG_PRIMARIES_ST431_2; - case MP_CSP_PRIM_DISPLAY_P3:return ZIMG_PRIMARIES_ST432_1; - case MP_CSP_PRIM_EBU_3213: return ZIMG_PRIMARIES_EBU3213_E; - case MP_CSP_PRIM_FILM_C: return ZIMG_PRIMARIES_FILM; - case MP_CSP_PRIM_CIE_1931: - case MP_CSP_PRIM_APPLE: // ? - case MP_CSP_PRIM_ADOBE: - case MP_CSP_PRIM_PRO_PHOTO: - case MP_CSP_PRIM_V_GAMUT: - case MP_CSP_PRIM_S_GAMUT: // ? - case MP_CSP_PRIM_ACES_AP0: - case MP_CSP_PRIM_ACES_AP1: + case PL_COLOR_PRIM_BT_601_525:return ZIMG_PRIMARIES_ST170_M; + case PL_COLOR_PRIM_BT_601_625:return ZIMG_PRIMARIES_BT470_BG; + case PL_COLOR_PRIM_BT_709: return ZIMG_PRIMARIES_BT709; + case PL_COLOR_PRIM_BT_2020: return ZIMG_PRIMARIES_BT2020; + case PL_COLOR_PRIM_BT_470M: return ZIMG_PRIMARIES_BT470_M; + case PL_COLOR_PRIM_DCI_P3: return ZIMG_PRIMARIES_ST431_2; + case PL_COLOR_PRIM_DISPLAY_P3:return ZIMG_PRIMARIES_ST432_1; + case PL_COLOR_PRIM_EBU_3213: return ZIMG_PRIMARIES_EBU3213_E; + case PL_COLOR_PRIM_FILM_C: return ZIMG_PRIMARIES_FILM; + case PL_COLOR_PRIM_CIE_1931: + case PL_COLOR_PRIM_APPLE: // ? + case PL_COLOR_PRIM_ADOBE: + case PL_COLOR_PRIM_PRO_PHOTO: + case PL_COLOR_PRIM_V_GAMUT: + case PL_COLOR_PRIM_S_GAMUT: // ? + case PL_COLOR_PRIM_ACES_AP0: + case PL_COLOR_PRIM_ACES_AP1: default: return ZIMG_PRIMARIES_BT709; } } @@ -414,7 +414,7 @@ static bool setup_format(zimg_image_format *zfmt, struct mp_zimg_repack *r, zfmt->color_family = ZIMG_COLOR_YUV; if (desc.num_planes <= 2) { zfmt->color_family = ZIMG_COLOR_GREY; - } else if (fmt.color.space == MP_CSP_RGB || fmt.color.space == MP_CSP_XYZ) { + } else if (fmt.repr.sys == PL_COLOR_SYSTEM_RGB || fmt.repr.sys == PL_COLOR_SYSTEM_XYZ) { zfmt->color_family = ZIMG_COLOR_RGB; } @@ -441,13 +441,13 @@ static bool setup_format(zimg_image_format *zfmt, struct mp_zimg_repack *r, // (Formats like P010 are basically reported as P016.) zfmt->depth = desc.component_size * 8 + MPMIN(0, desc.component_pad); - zfmt->pixel_range = fmt.color.levels == MP_CSP_LEVELS_PC ? + zfmt->pixel_range = fmt.repr.levels == PL_COLOR_LEVELS_FULL ? ZIMG_RANGE_FULL : ZIMG_RANGE_LIMITED; - zfmt->matrix_coefficients = mp_to_z_matrix(fmt.color.space); - zfmt->transfer_characteristics = mp_to_z_trc(fmt.color.gamma); - // For MP_CSP_XYZ only valid primaries are defined in ST 428-1 - zfmt->color_primaries = fmt.color.space == MP_CSP_XYZ + zfmt->matrix_coefficients = pl_to_z_matrix(fmt.repr.sys); + zfmt->transfer_characteristics = pl_to_z_trc(fmt.color.transfer); + // For PL_COLOR_SYSTEM_XYZ only valid primaries are defined in ST 428-1 + zfmt->color_primaries = fmt.repr.sys == PL_COLOR_SYSTEM_XYZ ? ZIMG_PRIMARIES_ST428 : mp_to_z_prim(fmt.color.primaries); zfmt->chroma_location = mp_to_z_chroma(fmt.chroma_location); @@ -548,7 +548,7 @@ static bool mp_zimg_state_init(struct mp_zimg_context *ctx, params.allow_approximate_gamma = 1; // leave at default for SDR, which means 100 cd/m^2 for zimg - if (ctx->dst.color.hdr.max_luma > 0 && mp_trc_is_hdr(ctx->dst.color.gamma)) + if (ctx->dst.color.hdr.max_luma > 0 && mp_trc_is_hdr(ctx->dst.color.transfer)) params.nominal_peak_luminance = ctx->dst.color.hdr.max_luma; st->graph = zimg_filter_graph_build(&src_fmt, &dst_fmt, ¶ms); From 2e5f080f2f89f63a4a02f5fa87384cda1a3a6b24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= <kasper93@gmail.com> Date: Sat, 4 Nov 2023 04:54:51 +0100 Subject: [PATCH 2/5] csputils: replace mp_alpha_type with pl_alpha_mode --- player/command.c | 12 ++++++------ sub/draw_bmp.c | 12 ++++++------ sub/draw_bmp.h | 2 +- video/csputils.c | 8 ++++---- video/csputils.h | 9 +-------- video/filter/vf_format.c | 4 ++-- video/mp_image.c | 8 +++----- video/mp_image.h | 1 - video/out/gpu/video.c | 2 +- video/out/placebo/utils.c | 11 ----------- video/out/placebo/utils.h | 1 - video/out/vo_gpu_next.c | 2 +- video/zimg.c | 2 +- 13 files changed, 26 insertions(+), 48 deletions(-) diff --git a/player/command.c b/player/command.c index 33d30508e79f..396ae651159f 100644 --- a/player/command.c +++ b/player/command.c @@ -2285,11 +2285,11 @@ static int property_imgparams(struct mp_image_params p, int action, void *arg) for (int i = 0; i < desc.num_planes; i++) bpp += desc.bpp[i] >> (desc.xs[i] + desc.ys[i]); - // Alpha type is not supported by FFmpeg, so MP_ALPHA_AUTO may mean alpha + // Alpha type is not supported by FFmpeg, so PL_ALPHA_UNKNOWN may mean alpha // is of an unknown type, or simply not present. Normalize to AUTO=no alpha. - if (!!(desc.flags & MP_IMGFLAG_ALPHA) != (p.alpha != MP_ALPHA_AUTO)) { - p.alpha = - (desc.flags & MP_IMGFLAG_ALPHA) ? MP_ALPHA_STRAIGHT : MP_ALPHA_AUTO; + if (!!(desc.flags & MP_IMGFLAG_ALPHA) != (p.repr.alpha != PL_ALPHA_UNKNOWN)) { + p.repr.alpha = + (desc.flags & MP_IMGFLAG_ALPHA) ? PL_ALPHA_INDEPENDENT : PL_ALPHA_UNKNOWN; } const struct pl_hdr_metadata *hdr = &p.color.hdr; @@ -2333,9 +2333,9 @@ static int property_imgparams(struct mp_image_params p, int action, void *arg) SUB_PROP_STR(m_opt_choice_str(mp_stereo3d_names, p.stereo3d))}, {"rotate", SUB_PROP_INT(p.rotate)}, {"alpha", - SUB_PROP_STR(m_opt_choice_str(mp_alpha_names, p.alpha)), + SUB_PROP_STR(m_opt_choice_str(pl_alpha_names, p.repr.alpha)), // avoid using "auto" for "no", so just make it unavailable - .unavailable = p.alpha == MP_ALPHA_AUTO}, + .unavailable = p.repr.alpha == PL_ALPHA_UNKNOWN}, {"min-luma", SUB_PROP_FLOAT(hdr->min_luma), .unavailable = !has_hdr10}, {"max-luma", SUB_PROP_FLOAT(hdr->max_luma), .unavailable = !has_hdr10}, {"max-cll", SUB_PROP_FLOAT(hdr->max_cll), .unavailable = !has_hdr10}, diff --git a/sub/draw_bmp.c b/sub/draw_bmp.c index cde8f503f334..cf214401a81b 100644 --- a/sub/draw_bmp.c +++ b/sub/draw_bmp.c @@ -431,7 +431,7 @@ static bool render_rgba(struct mp_draw_sub_cache *p, struct part *part, mp_image_set_size(&src_img, sw, sh); src_img.planes[0] = s_ptr; src_img.stride[0] = s_stride; - src_img.params.alpha = MP_ALPHA_PREMUL; + src_img.params.repr.alpha = PL_ALPHA_PREMULTIPLIED; scaled = mp_image_alloc(IMGFMT_BGRA, dw, dh); if (!scaled) @@ -525,7 +525,7 @@ static bool reinit_to_video(struct mp_draw_sub_cache *p) struct mp_image_params *params = &p->params; mp_image_params_guess_csp(params); - bool need_premul = params->alpha != MP_ALPHA_PREMUL && + bool need_premul = params->repr.alpha != PL_ALPHA_PREMULTIPLIED && (mp_imgfmt_get_desc(params->imgfmt).flags & MP_IMGFLAG_ALPHA); // Intermediate format for video_overlay. Requirements: @@ -660,7 +660,7 @@ static bool reinit_to_video(struct mp_draw_sub_cache *p) return false; mp_image_params_guess_csp(&p->rgba_overlay->params); - p->rgba_overlay->params.alpha = MP_ALPHA_PREMUL; + p->rgba_overlay->params.repr.alpha = PL_ALPHA_PREMULTIPLIED; p->overlay_tmp->params.color = params->color; p->video_tmp->params.color = params->color; @@ -677,7 +677,7 @@ static bool reinit_to_video(struct mp_draw_sub_cache *p) p->video_overlay->params.color = params->color; p->video_overlay->params.chroma_location = params->chroma_location; - p->video_overlay->params.alpha = MP_ALPHA_PREMUL; + p->video_overlay->params.repr.alpha = PL_ALPHA_PREMULTIPLIED; if (p->scale_in_tiles) p->video_overlay->params.chroma_location = MP_CHROMA_CENTER; @@ -762,7 +762,7 @@ static bool reinit_to_video(struct mp_draw_sub_cache *p) if (!p->premul_tmp) return false; mp_image_set_params(p->premul_tmp, params); - p->premul_tmp->params.alpha = MP_ALPHA_PREMUL; + p->premul_tmp->params.repr.alpha = PL_ALPHA_PREMULTIPLIED; // Only zimg supports this. p->premul->force_scaler = MP_SWS_ZIMG; @@ -787,7 +787,7 @@ static bool reinit_to_overlay(struct mp_draw_sub_cache *p) return false; mp_image_params_guess_csp(&p->rgba_overlay->params); - p->rgba_overlay->params.alpha = MP_ALPHA_PREMUL; + p->rgba_overlay->params.repr.alpha = PL_ALPHA_PREMULTIPLIED; // Some non-sense with the intention to somewhat isolate the returned image. mp_image_setfmt(&p->res_overlay, p->rgba_overlay->imgfmt); diff --git a/sub/draw_bmp.h b/sub/draw_bmp.h index fda7797c9eab..b4c737829039 100644 --- a/sub/draw_bmp.h +++ b/sub/draw_bmp.h @@ -15,7 +15,7 @@ struct mp_draw_sub_cache *mp_draw_sub_alloc_test(struct mp_image *dst); // Render the sub-bitmaps in sbs_list to dst. sbs_list must have been rendered // for an OSD resolution equivalent to dst's size (UB if not). -// Warning: if dst is a format with alpha, and dst is not set to MP_ALPHA_PREMUL +// Warning: if dst is a format with alpha, and dst is not set to PL_ALPHA_PREMULTIPLIED // (not done by default), this will be extremely slow. // Warning: the caller is responsible for ensuring that dst is writable. // cache: allocated instance; caches non-changing OSD parts etc. diff --git a/video/csputils.c b/video/csputils.c index 3b43ba9f5b69..e1b7823b3387 100644 --- a/video/csputils.c +++ b/video/csputils.c @@ -112,10 +112,10 @@ const struct m_opt_choice_alternatives mp_chroma_names[] = { {0} }; -const struct m_opt_choice_alternatives mp_alpha_names[] = { - {"auto", MP_ALPHA_AUTO}, - {"straight", MP_ALPHA_STRAIGHT}, - {"premul", MP_ALPHA_PREMUL}, +const struct m_opt_choice_alternatives pl_alpha_names[] = { + {"auto", PL_ALPHA_UNKNOWN}, + {"straight", PL_ALPHA_INDEPENDENT}, + {"premul", PL_ALPHA_PREMULTIPLIED}, {0} }; diff --git a/video/csputils.h b/video/csputils.h index 80901659cf3c..ac37e205abf1 100644 --- a/video/csputils.h +++ b/video/csputils.h @@ -120,14 +120,7 @@ enum mp_chroma_location { }; extern const struct m_opt_choice_alternatives mp_chroma_names[]; - -enum mp_alpha_type { - MP_ALPHA_AUTO, - MP_ALPHA_STRAIGHT, - MP_ALPHA_PREMUL, -}; - -extern const struct m_opt_choice_alternatives mp_alpha_names[]; +extern const struct m_opt_choice_alternatives pl_alpha_names[]; extern const struct m_sub_options mp_csp_equalizer_conf; diff --git a/video/filter/vf_format.c b/video/filter/vf_format.c index 4a14fc91024d..6a3e9fd390b4 100644 --- a/video/filter/vf_format.c +++ b/video/filter/vf_format.c @@ -92,7 +92,7 @@ static void set_params(struct vf_format_opts *p, struct mp_image_params *out, if (p->rotate >= 0) out->rotate = p->rotate; if (p->alpha) - out->alpha = p->alpha; + out->repr.alpha = p->alpha; if (p->w > 0 && set_size) out->w = p->w; @@ -213,7 +213,7 @@ static const m_option_t vf_opts_fields[] = { {"chroma-location", OPT_CHOICE_C(chroma_location, mp_chroma_names)}, {"stereo-in", OPT_CHOICE_C(stereo_in, mp_stereo3d_names)}, {"rotate", OPT_INT(rotate), M_RANGE(-1, 359)}, - {"alpha", OPT_CHOICE_C(alpha, mp_alpha_names)}, + {"alpha", OPT_CHOICE_C(alpha, pl_alpha_names)}, {"w", OPT_INT(w)}, {"h", OPT_INT(h)}, {"dw", OPT_INT(dw)}, diff --git a/video/mp_image.c b/video/mp_image.c index ed7543b8ff76..62bcef7d7ed7 100644 --- a/video/mp_image.c +++ b/video/mp_image.c @@ -525,7 +525,6 @@ void mp_image_copy_attributes(struct mp_image *dst, struct mp_image *src) dst->params.repr = src->params.repr; dst->params.light = src->params.light; dst->params.chroma_location = src->params.chroma_location; - dst->params.alpha = src->params.alpha; dst->params.crop = src->params.crop; dst->nominal_fps = src->nominal_fps; @@ -792,9 +791,9 @@ char *mp_image_params_to_str_buf(char *b, size_t bs, mp_snprintf_cat(b, bs, " stereo=%s", MP_STEREO3D_NAME_DEF(p->stereo3d, "?")); } - if (p->alpha) { + if (p->repr.alpha) { mp_snprintf_cat(b, bs, " A=%s", - m_opt_choice_str(mp_alpha_names, p->alpha)); + m_opt_choice_str(pl_alpha_names, p->repr.alpha)); } } else { snprintf(b, bs, "???"); @@ -844,7 +843,6 @@ bool mp_image_params_equal(const struct mp_image_params *p1, p1->chroma_location == p2->chroma_location && p1->rotate == p2->rotate && p1->stereo3d == p2->stereo3d && - p1->alpha == p2->alpha && mp_rect_equals(&p1->crop, &p2->crop); } @@ -1054,7 +1052,7 @@ struct mp_image *mp_image_from_av_frame(struct AVFrame *src) dst->params.stereo3d = p->stereo3d; // Might be incorrect if colorspace changes. dst->params.light = p->light; - dst->params.alpha = p->alpha; + dst->params.repr.alpha = p->repr.alpha; } sd = av_frame_get_side_data(src, AV_FRAME_DATA_DISPLAYMATRIX); diff --git a/video/mp_image.h b/video/mp_image.h index c1ba89ee0ac7..443488c9e1a3 100644 --- a/video/mp_image.h +++ b/video/mp_image.h @@ -54,7 +54,6 @@ struct mp_image_params { // The image should be rotated clockwise (0-359 degrees). int rotate; enum mp_stereo3d_mode stereo3d; // image is encoded with this mode - enum mp_alpha_type alpha; // usually auto; only set if explicitly known struct mp_rect crop; // crop applied on image }; diff --git a/video/out/gpu/video.c b/video/out/gpu/video.c index 62388d65c32b..6683da688c89 100644 --- a/video/out/gpu/video.c +++ b/video/out/gpu/video.c @@ -2396,7 +2396,7 @@ static void pass_convert_yuv(struct gl_video *p) p->components = 3; if (!p->has_alpha || p->opts.alpha_mode == ALPHA_NO) { GLSL(color.a = 1.0;) - } else if (p->image_params.alpha == MP_ALPHA_PREMUL) { + } else if (p->image_params.repr.alpha == PL_ALPHA_PREMULTIPLIED) { p->components = 4; } else { p->components = 4; diff --git a/video/out/placebo/utils.c b/video/out/placebo/utils.c index 7bb96dd20af6..3d8c827d617f 100644 --- a/video/out/placebo/utils.c +++ b/video/out/placebo/utils.c @@ -66,17 +66,6 @@ void mppl_log_set_probing(pl_log log, bool probing) pl_log_update(log, ¶ms); } -enum pl_alpha_mode mp_alpha_to_pl(enum mp_alpha_type alpha) -{ - switch (alpha) { - case MP_ALPHA_AUTO: return PL_ALPHA_UNKNOWN; - case MP_ALPHA_STRAIGHT: return PL_ALPHA_INDEPENDENT; - case MP_ALPHA_PREMUL: return PL_ALPHA_PREMULTIPLIED; - } - - MP_ASSERT_UNREACHABLE(); -} - enum pl_chroma_location mp_chroma_to_pl(enum mp_chroma_location chroma) { switch (chroma) { diff --git a/video/out/placebo/utils.h b/video/out/placebo/utils.h index 103fa4ce2462..84b2e0468ecd 100644 --- a/video/out/placebo/utils.h +++ b/video/out/placebo/utils.h @@ -27,7 +27,6 @@ static inline struct pl_rect2d mp_rect2d_to_pl(struct mp_rect rc) }; } -enum pl_alpha_mode mp_alpha_to_pl(enum mp_alpha_type alpha); enum pl_chroma_location mp_chroma_to_pl(enum mp_chroma_location chroma); void mp_map_dovi_metadata_to_pl(struct mp_image *mpi, diff --git a/video/out/vo_gpu_next.c b/video/out/vo_gpu_next.c index 7b3b3891ba68..5488d85ee33a 100644 --- a/video/out/vo_gpu_next.c +++ b/video/out/vo_gpu_next.c @@ -571,7 +571,7 @@ static bool map_frame(pl_gpu gpu, pl_tex *tex, const struct pl_source_frame *src .repr = { .sys = par->repr.sys, .levels = par->repr.levels, - .alpha = mp_alpha_to_pl(par->alpha), + .alpha = par->repr.alpha, }, .profile = { .data = mpi->icc_profile ? mpi->icc_profile->data : NULL, diff --git a/video/zimg.c b/video/zimg.c index f744fe2c4b4f..4ea32af83a88 100644 --- a/video/zimg.c +++ b/video/zimg.c @@ -375,7 +375,7 @@ static bool setup_format(zimg_image_format *zfmt, struct mp_zimg_repack *r, r->z_planes[3] = n; // alpha, always plane 4 in zimg #if HAVE_ZIMG_ALPHA - zfmt->alpha = fmt.alpha == MP_ALPHA_PREMUL + zfmt->alpha = fmt.repr.alpha == PL_ALPHA_PREMULTIPLIED ? ZIMG_ALPHA_PREMULTIPLIED : ZIMG_ALPHA_STRAIGHT; #else return false; From 1797d74280eae7baaa1e6ec842932538aa93c893 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= <kasper93@gmail.com> Date: Sat, 4 Nov 2023 05:15:27 +0100 Subject: [PATCH 3/5] csputils: replace mp_chroma_location with pl_chroma_location --- player/command.c | 2 +- sub/draw_bmp.c | 2 +- video/csputils.c | 45 +++++++---------------------------- video/csputils.h | 14 +---------- video/filter/vf_format.c | 2 +- video/filter/vf_vapoursynth.c | 2 +- video/image_writer.c | 4 ++-- video/mp_image.c | 12 +++++----- video/mp_image.h | 2 +- video/out/gpu/video.c | 10 ++++---- video/out/placebo/utils.c | 13 ---------- video/out/placebo/utils.h | 2 -- video/out/vo_gpu_next.c | 2 +- video/sws_utils.c | 4 ++-- video/zimg.c | 15 +++++++----- 15 files changed, 39 insertions(+), 92 deletions(-) diff --git a/player/command.c b/player/command.c index 396ae651159f..722e0cb1675e 100644 --- a/player/command.c +++ b/player/command.c @@ -2328,7 +2328,7 @@ static int property_imgparams(struct mp_image_params p, int action, void *arg) {"light", SUB_PROP_STR(m_opt_choice_str(mp_csp_light_names, p.light))}, {"chroma-location", - SUB_PROP_STR(m_opt_choice_str(mp_chroma_names, p.chroma_location))}, + SUB_PROP_STR(m_opt_choice_str(pl_chroma_names, p.chroma_location))}, {"stereo-in", SUB_PROP_STR(m_opt_choice_str(mp_stereo3d_names, p.stereo3d))}, {"rotate", SUB_PROP_INT(p.rotate)}, diff --git a/sub/draw_bmp.c b/sub/draw_bmp.c index cf214401a81b..90529221157a 100644 --- a/sub/draw_bmp.c +++ b/sub/draw_bmp.c @@ -680,7 +680,7 @@ static bool reinit_to_video(struct mp_draw_sub_cache *p) p->video_overlay->params.repr.alpha = PL_ALPHA_PREMULTIPLIED; if (p->scale_in_tiles) - p->video_overlay->params.chroma_location = MP_CHROMA_CENTER; + p->video_overlay->params.chroma_location = PL_CHROMA_CENTER; p->rgba_to_overlay = alloc_scaler(p); p->rgba_to_overlay->allow_zimg = true; diff --git a/video/csputils.c b/video/csputils.c index e1b7823b3387..6b708f7525c9 100644 --- a/video/csputils.c +++ b/video/csputils.c @@ -104,11 +104,14 @@ const struct m_opt_choice_alternatives mp_csp_light_names[] = { {0} }; -const struct m_opt_choice_alternatives mp_chroma_names[] = { - {"unknown", MP_CHROMA_AUTO}, - {"uhd", MP_CHROMA_TOPLEFT}, - {"mpeg2/4/h264",MP_CHROMA_LEFT}, - {"mpeg1/jpeg", MP_CHROMA_CENTER}, +const struct m_opt_choice_alternatives pl_chroma_names[] = { + {"unknown", PL_CHROMA_UNKNOWN}, + {"uhd", PL_CHROMA_TOP_LEFT}, + {"mpeg2/4/h264",PL_CHROMA_LEFT}, + {"mpeg1/jpeg", PL_CHROMA_CENTER}, + {"top", PL_CHROMA_TOP_CENTER}, + {"bottom left", PL_CHROMA_BOTTOM_LEFT}, + {"bottom", PL_CHROMA_BOTTOM_CENTER}, {0} }; @@ -167,38 +170,6 @@ enum pl_color_primaries mp_csp_guess_primaries(int width, int height) } } -enum mp_chroma_location avchroma_location_to_mp(int avloc) -{ - switch (avloc) { - case AVCHROMA_LOC_TOPLEFT: return MP_CHROMA_TOPLEFT; - case AVCHROMA_LOC_LEFT: return MP_CHROMA_LEFT; - case AVCHROMA_LOC_CENTER: return MP_CHROMA_CENTER; - default: return MP_CHROMA_AUTO; - } -} - -int mp_chroma_location_to_av(enum mp_chroma_location mploc) -{ - switch (mploc) { - case MP_CHROMA_TOPLEFT: return AVCHROMA_LOC_TOPLEFT; - case MP_CHROMA_LEFT: return AVCHROMA_LOC_LEFT; - case MP_CHROMA_CENTER: return AVCHROMA_LOC_CENTER; - default: return AVCHROMA_LOC_UNSPECIFIED; - } -} - -// Return location of chroma samples relative to luma samples. 0/0 means -// centered. Other possible values are -1 (top/left) and +1 (right/bottom). -void mp_get_chroma_location(enum mp_chroma_location loc, int *x, int *y) -{ - *x = 0; - *y = 0; - if (loc == MP_CHROMA_LEFT || loc == MP_CHROMA_TOPLEFT) - *x = -1; - if (loc == MP_CHROMA_TOPLEFT) - *y = -1; -} - void mp_invert_matrix3x3(float m[3][3]) { float m00 = m[0][0], m01 = m[0][1], m02 = m[0][2], diff --git a/video/csputils.h b/video/csputils.h index ac37e205abf1..9b2d0378df96 100644 --- a/video/csputils.h +++ b/video/csputils.h @@ -111,15 +111,7 @@ struct mp_image_params; void mp_csp_set_image_params(struct mp_csp_params *params, const struct mp_image_params *imgparams); -enum mp_chroma_location { - MP_CHROMA_AUTO, - MP_CHROMA_TOPLEFT, // uhd - MP_CHROMA_LEFT, // mpeg2/4, h264 - MP_CHROMA_CENTER, // mpeg1, jpeg - MP_CHROMA_COUNT, -}; - -extern const struct m_opt_choice_alternatives mp_chroma_names[]; +extern const struct m_opt_choice_alternatives pl_chroma_names[]; extern const struct m_opt_choice_alternatives pl_alpha_names[]; extern const struct m_sub_options mp_csp_equalizer_conf; @@ -150,10 +142,6 @@ struct mp_csp_primaries { enum pl_color_system mp_csp_guess_colorspace(int width, int height); enum pl_color_primaries mp_csp_guess_primaries(int width, int height); -enum mp_chroma_location avchroma_location_to_mp(int avloc); -int mp_chroma_location_to_av(enum mp_chroma_location mploc); -void mp_get_chroma_location(enum mp_chroma_location loc, int *x, int *y); - struct mp_csp_primaries mp_get_csp_primaries(enum pl_color_primaries csp); float mp_trc_nom_peak(enum pl_color_transfer trc); bool mp_trc_is_hdr(enum pl_color_transfer trc); diff --git a/video/filter/vf_format.c b/video/filter/vf_format.c index 6a3e9fd390b4..206304586415 100644 --- a/video/filter/vf_format.c +++ b/video/filter/vf_format.c @@ -210,7 +210,7 @@ static const m_option_t vf_opts_fields[] = { {"gamma", OPT_CHOICE_C(gamma, pl_csp_trc_names)}, {"sig-peak", OPT_FLOAT(sig_peak)}, {"light", OPT_CHOICE_C(light, mp_csp_light_names)}, - {"chroma-location", OPT_CHOICE_C(chroma_location, mp_chroma_names)}, + {"chroma-location", OPT_CHOICE_C(chroma_location, pl_chroma_names)}, {"stereo-in", OPT_CHOICE_C(stereo_in, mp_stereo3d_names)}, {"rotate", OPT_INT(rotate), M_RANGE(-1, 359)}, {"alpha", OPT_CHOICE_C(alpha, pl_alpha_names)}, diff --git a/video/filter/vf_vapoursynth.c b/video/filter/vf_vapoursynth.c index 5a3ce423d1d7..0b798c8dafe6 100644 --- a/video/filter/vf_vapoursynth.c +++ b/video/filter/vf_vapoursynth.c @@ -194,7 +194,7 @@ static void copy_mp_to_vs_frame_props_map(struct priv *p, VSMap *map, pl_system_to_av(params->repr.sys), 0); if (params->chroma_location) { p->vsapi->propSetInt(map, "_ChromaLocation", - params->chroma_location == MP_CHROMA_CENTER, 0); + params->chroma_location == PL_CHROMA_CENTER, 0); } char pict_type = 0; switch (img->pict_type) { diff --git a/video/image_writer.c b/video/image_writer.c index df43830d7900..fc07302d64cf 100644 --- a/video/image_writer.c +++ b/video/image_writer.c @@ -149,7 +149,7 @@ static void prepare_avframe(AVFrame *pic, AVCodecContext *avctx, avctx->colorspace = pic->colorspace = pl_system_to_av(image->params.repr.sys); avctx->chroma_sample_location = pic->chroma_location = - mp_chroma_location_to_av(image->params.chroma_location); + pl_chroma_to_av(image->params.chroma_location); mp_dbg(log, "mapped color params:\n" " trc = %s\n" " primaries = %s\n" @@ -644,7 +644,7 @@ static struct mp_image *convert_image(struct mp_image *image, int destfmt, if (p.repr.sys != PL_COLOR_SYSTEM_RGB) { p.repr.levels = yuv_levels; p.repr.sys = PL_COLOR_SYSTEM_BT_601; - p.chroma_location = MP_CHROMA_CENTER; + p.chroma_location = PL_CHROMA_CENTER; } mp_image_params_guess_csp(&p); } diff --git a/video/mp_image.c b/video/mp_image.c index 62bcef7d7ed7..8fbcfea77da8 100644 --- a/video/mp_image.c +++ b/video/mp_image.c @@ -780,7 +780,7 @@ char *mp_image_params_to_str_buf(char *b, size_t bs, m_opt_choice_str(pl_csp_levels_names, p->repr.levels), m_opt_choice_str(mp_csp_light_names, p->light)); mp_snprintf_cat(b, bs, " CL=%s", - m_opt_choice_str(mp_chroma_names, p->chroma_location)); + m_opt_choice_str(pl_chroma_names, p->chroma_location)); if (mp_image_crop_valid(p)) { mp_snprintf_cat(b, bs, " crop=%dx%d+%d+%d", mp_rect_w(p->crop), mp_rect_h(p->crop), p->crop.x0, p->crop.y0); @@ -973,11 +973,11 @@ void mp_image_params_guess_csp(struct mp_image_params *params) params->color.hdr = pl_hdr_metadata_empty; } - if (params->chroma_location == MP_CHROMA_AUTO) { + if (params->chroma_location == PL_CHROMA_UNKNOWN) { if (params->repr.levels == PL_COLOR_LEVELS_LIMITED) - params->chroma_location = MP_CHROMA_LEFT; + params->chroma_location = PL_CHROMA_LEFT; if (params->repr.levels == PL_COLOR_LEVELS_FULL) - params->chroma_location = MP_CHROMA_CENTER; + params->chroma_location = PL_CHROMA_CENTER; } if (params->light == MP_CSP_LIGHT_AUTO) { @@ -1045,7 +1045,7 @@ struct mp_image *mp_image_from_av_frame(struct AVFrame *src) .transfer = pl_transfer_from_av(src->color_trc), }; - dst->params.chroma_location = avchroma_location_to_mp(src->chroma_location); + dst->params.chroma_location = pl_chroma_from_av(src->chroma_location); if (src->opaque_ref) { struct mp_image_params *p = (void *)src->opaque_ref->data; @@ -1174,7 +1174,7 @@ struct AVFrame *mp_image_to_av_frame(struct mp_image *src) pl_primaries_to_av(src->params.color.primaries); dst->color_trc = pl_transfer_to_av(src->params.color.transfer); - dst->chroma_location = mp_chroma_location_to_av(src->params.chroma_location); + dst->chroma_location = pl_chroma_to_av(src->params.chroma_location); dst->opaque_ref = av_buffer_alloc(sizeof(struct mp_image_params)); MP_HANDLE_OOM(dst->opaque_ref); diff --git a/video/mp_image.h b/video/mp_image.h index 443488c9e1a3..149b63ead14e 100644 --- a/video/mp_image.h +++ b/video/mp_image.h @@ -50,7 +50,7 @@ struct mp_image_params { struct pl_color_space color; struct pl_color_repr repr; enum mp_csp_light light; - enum mp_chroma_location chroma_location; + enum pl_chroma_location chroma_location; // The image should be rotated clockwise (0-359 degrees). int rotate; enum mp_stereo3d_mode stereo3d; // image is encoded with this mode diff --git a/video/out/gpu/video.c b/video/out/gpu/video.c index 6683da688c89..70aca4223866 100644 --- a/video/out/gpu/video.c +++ b/video/out/gpu/video.c @@ -762,16 +762,16 @@ static void pass_get_images(struct gl_video *p, struct video_image *vimg, struct gl_transform chroma = {{{ls_w, 0.0}, {0.0, ls_h}}}; - if (p->image_params.chroma_location != MP_CHROMA_CENTER) { - int cx, cy; - mp_get_chroma_location(p->image_params.chroma_location, &cx, &cy); + if (p->image_params.chroma_location != PL_CHROMA_CENTER) { + float cx, cy; + pl_chroma_location_offset(p->image_params.chroma_location, &cx, &cy); // By default texture coordinates are such that chroma is centered with // any chroma subsampling. If a specific direction is given, make it // so that the luma and chroma sample line up exactly. // For 4:4:4, setting chroma location should have no effect at all. // luma sample size (in chroma coord. space) - chroma.t[0] = ls_w < 1 ? ls_w * -cx / 2 : 0; - chroma.t[1] = ls_h < 1 ? ls_h * -cy / 2 : 0; + chroma.t[0] = ls_w < 1 ? ls_w * -cx : 0; + chroma.t[1] = ls_h < 1 ? ls_h * -cy : 0; } memset(img, 0, 4 * sizeof(img[0])); diff --git a/video/out/placebo/utils.c b/video/out/placebo/utils.c index 3d8c827d617f..2bf655ac3fc0 100644 --- a/video/out/placebo/utils.c +++ b/video/out/placebo/utils.c @@ -66,19 +66,6 @@ void mppl_log_set_probing(pl_log log, bool probing) pl_log_update(log, ¶ms); } -enum pl_chroma_location mp_chroma_to_pl(enum mp_chroma_location chroma) -{ - switch (chroma) { - case MP_CHROMA_AUTO: return PL_CHROMA_UNKNOWN; - case MP_CHROMA_TOPLEFT: return PL_CHROMA_TOP_LEFT; - case MP_CHROMA_LEFT: return PL_CHROMA_LEFT; - case MP_CHROMA_CENTER: return PL_CHROMA_CENTER; - case MP_CHROMA_COUNT: return PL_CHROMA_COUNT; - } - - MP_ASSERT_UNREACHABLE(); -} - void mp_map_dovi_metadata_to_pl(struct mp_image *mpi, struct pl_frame *frame) { diff --git a/video/out/placebo/utils.h b/video/out/placebo/utils.h index 84b2e0468ecd..d2fa619b4a91 100644 --- a/video/out/placebo/utils.h +++ b/video/out/placebo/utils.h @@ -27,7 +27,5 @@ static inline struct pl_rect2d mp_rect2d_to_pl(struct mp_rect rc) }; } -enum pl_chroma_location mp_chroma_to_pl(enum mp_chroma_location chroma); - void mp_map_dovi_metadata_to_pl(struct mp_image *mpi, struct pl_frame *frame); diff --git a/video/out/vo_gpu_next.c b/video/out/vo_gpu_next.c index 5488d85ee33a..2fa2a46c2eca 100644 --- a/video/out/vo_gpu_next.c +++ b/video/out/vo_gpu_next.c @@ -660,7 +660,7 @@ static bool map_frame(pl_gpu gpu, pl_tex *tex, const struct pl_source_frame *src } // Update chroma location, must be done after initializing planes - pl_frame_set_chroma_location(frame, mp_chroma_to_pl(par->chroma_location)); + pl_frame_set_chroma_location(frame, par->chroma_location); // Set the frame DOVI metadata mp_map_dovi_metadata_to_pl(mpi, frame); diff --git a/video/sws_utils.c b/video/sws_utils.c index 9844dd62eb03..a07bb5542428 100644 --- a/video/sws_utils.c +++ b/video/sws_utils.c @@ -309,8 +309,8 @@ int mp_sws_reinit(struct mp_sws_context *ctx) av_opt_set_double(ctx->sws, "param0", ctx->params[0], 0); av_opt_set_double(ctx->sws, "param1", ctx->params[1], 0); - int cr_src = mp_chroma_location_to_av(src.chroma_location); - int cr_dst = mp_chroma_location_to_av(dst.chroma_location); + int cr_src = pl_chroma_to_av(src.chroma_location); + int cr_dst = pl_chroma_to_av(dst.chroma_location); int cr_xpos, cr_ypos; #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 37, 100) if (av_chroma_location_enum_to_pos(&cr_xpos, &cr_ypos, cr_src) >= 0) { diff --git a/video/zimg.c b/video/zimg.c index 4ea32af83a88..35a987dfea7d 100644 --- a/video/zimg.c +++ b/video/zimg.c @@ -121,13 +121,16 @@ static void mp_zimg_update_from_cmdline(struct mp_zimg_context *ctx) ctx->opts = *opts; } -static zimg_chroma_location_e mp_to_z_chroma(enum mp_chroma_location cl) +static zimg_chroma_location_e pl_to_z_chroma(enum pl_chroma_location cl) { switch (cl) { - case MP_CHROMA_TOPLEFT: return ZIMG_CHROMA_TOP_LEFT; - case MP_CHROMA_LEFT: return ZIMG_CHROMA_LEFT; - case MP_CHROMA_CENTER: return ZIMG_CHROMA_CENTER; - default: return ZIMG_CHROMA_LEFT; + case PL_CHROMA_LEFT: return ZIMG_CHROMA_LEFT; + case PL_CHROMA_CENTER: return ZIMG_CHROMA_CENTER; + case PL_CHROMA_TOP_LEFT: return ZIMG_CHROMA_TOP_LEFT; + case PL_CHROMA_TOP_CENTER: return ZIMG_CHROMA_TOP; + case PL_CHROMA_BOTTOM_LEFT: return ZIMG_CHROMA_BOTTOM_LEFT; + case PL_CHROMA_BOTTOM_CENTER: return ZIMG_CHROMA_BOTTOM; + default: return ZIMG_CHROMA_LEFT; } } @@ -450,7 +453,7 @@ static bool setup_format(zimg_image_format *zfmt, struct mp_zimg_repack *r, zfmt->color_primaries = fmt.repr.sys == PL_COLOR_SYSTEM_XYZ ? ZIMG_PRIMARIES_ST428 : mp_to_z_prim(fmt.color.primaries); - zfmt->chroma_location = mp_to_z_chroma(fmt.chroma_location); + zfmt->chroma_location = pl_to_z_chroma(fmt.chroma_location); if (ctx && ctx->opts.fast) { // mpv's default for RGB output slows down zimg significantly. From df5da7fa525c4e6ce11a70651abbe9aef01a2f2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= <kasper93@gmail.com> Date: Sat, 4 Nov 2023 06:27:38 +0100 Subject: [PATCH 4/5] csputils: replace more primitives with pl_ We can go deeper, but need to stop somewhere to not reimplement vo_gpu using libplacebo... --- demux/demux_disc.c | 2 +- sub/sd_ass.c | 8 +- video/csputils.c | 430 +++++----------------------------- video/csputils.h | 57 +---- video/mp_image.c | 4 +- video/out/gpu/lcms.c | 14 +- video/out/gpu/video.c | 16 +- video/out/gpu/video_shaders.c | 35 +-- video/vdpau_mixer.c | 4 +- video/zimg.c | 2 +- 10 files changed, 98 insertions(+), 474 deletions(-) diff --git a/demux/demux_disc.c b/demux/demux_disc.c index 3dfff454038f..8cd4b7b5e9e6 100644 --- a/demux/demux_disc.c +++ b/demux/demux_disc.c @@ -94,7 +94,7 @@ static void add_dvd_streams(demuxer_t *demuxer) // emulate the extradata struct mp_csp_params csp = MP_CSP_PARAMS_DEFAULTS; - struct mp_cmat cmatrix; + struct pl_transform3x3 cmatrix; mp_get_csp_matrix(&csp, &cmatrix); char *s = talloc_strdup(sh, ""); diff --git a/sub/sd_ass.c b/sub/sd_ass.c index aa651375bec1..c50953147c41 100644 --- a/sub/sd_ass.c +++ b/sub/sd_ass.c @@ -976,14 +976,14 @@ static void mangle_colors(struct sd *sd, struct sub_bitmaps *parts) struct mp_csp_params vs_params = MP_CSP_PARAMS_DEFAULTS; vs_params.repr.sys = csp; vs_params.repr.levels = levels; - struct mp_cmat vs_yuv2rgb, vs_rgb2yuv; + struct pl_transform3x3 vs_yuv2rgb; mp_get_csp_matrix(&vs_params, &vs_yuv2rgb); - mp_invert_cmat(&vs_rgb2yuv, &vs_yuv2rgb); + pl_transform3x3_invert(&vs_yuv2rgb); // Proper conversion to RGB struct mp_csp_params rgb_params = MP_CSP_PARAMS_DEFAULTS; rgb_params.color = params.color; - struct mp_cmat vs2rgb; + struct pl_transform3x3 vs2rgb; mp_get_csp_matrix(&rgb_params, &vs2rgb); for (int n = 0; n < parts->num_parts; n++) { @@ -994,7 +994,7 @@ static void mangle_colors(struct sd *sd, struct sub_bitmaps *parts) int b = (color >> 8u) & 0xff; int a = 0xff - (color & 0xff); int rgb[3] = {r, g, b}, yuv[3]; - mp_map_fixp_color(&vs_rgb2yuv, 8, rgb, 8, yuv); + mp_map_fixp_color(&vs_yuv2rgb, 8, rgb, 8, yuv); mp_map_fixp_color(&vs2rgb, 8, yuv, 8, rgb); sb->libass.color = MP_ASS_RGBA(rgb[0], rgb[1], rgb[2], a); } diff --git a/video/csputils.c b/video/csputils.c index 6b708f7525c9..3a12fda9f020 100644 --- a/video/csputils.c +++ b/video/csputils.c @@ -3,8 +3,6 @@ * * Copyleft (C) 2009 Reimar Döffinger <Reimar.Doeffinger@gmx.de> * - * mp_invert_cmat based on DarkPlaces engine (relicensed from GPL to LGPL) - * * This file is part of mpv. * * mpv is free software; you can redistribute it and/or @@ -170,260 +168,17 @@ enum pl_color_primaries mp_csp_guess_primaries(int width, int height) } } -void mp_invert_matrix3x3(float m[3][3]) -{ - float m00 = m[0][0], m01 = m[0][1], m02 = m[0][2], - m10 = m[1][0], m11 = m[1][1], m12 = m[1][2], - m20 = m[2][0], m21 = m[2][1], m22 = m[2][2]; - - // calculate the adjoint - m[0][0] = (m11 * m22 - m21 * m12); - m[0][1] = -(m01 * m22 - m21 * m02); - m[0][2] = (m01 * m12 - m11 * m02); - m[1][0] = -(m10 * m22 - m20 * m12); - m[1][1] = (m00 * m22 - m20 * m02); - m[1][2] = -(m00 * m12 - m10 * m02); - m[2][0] = (m10 * m21 - m20 * m11); - m[2][1] = -(m00 * m21 - m20 * m01); - m[2][2] = (m00 * m11 - m10 * m01); - - // calculate the determinant (as inverse == 1/det * adjoint, - // adjoint * m == identity * det, so this calculates the det) - float det = m00 * m[0][0] + m10 * m[0][1] + m20 * m[0][2]; - det = 1.0f / det; - - for (int i = 0; i < 3; i++) { - for (int j = 0; j < 3; j++) - m[i][j] *= det; - } -} - -// A := A * B -static void mp_mul_matrix3x3(float a[3][3], float b[3][3]) -{ - float a00 = a[0][0], a01 = a[0][1], a02 = a[0][2], - a10 = a[1][0], a11 = a[1][1], a12 = a[1][2], - a20 = a[2][0], a21 = a[2][1], a22 = a[2][2]; - - for (int i = 0; i < 3; i++) { - a[0][i] = a00 * b[0][i] + a01 * b[1][i] + a02 * b[2][i]; - a[1][i] = a10 * b[0][i] + a11 * b[1][i] + a12 * b[2][i]; - a[2][i] = a20 * b[0][i] + a21 * b[1][i] + a22 * b[2][i]; - } -} - -// return the primaries associated with a certain mp_csp_primaries val -struct mp_csp_primaries mp_get_csp_primaries(enum pl_color_primaries spc) -{ - /* - Values from: ITU-R Recommendations BT.470-6, BT.601-7, BT.709-5, BT.2020-0 - - https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.470-6-199811-S!!PDF-E.pdf - https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.601-7-201103-I!!PDF-E.pdf - https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.709-5-200204-I!!PDF-E.pdf - https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.2020-0-201208-I!!PDF-E.pdf - - Other colorspaces from https://en.wikipedia.org/wiki/RGB_color_space#Specifications - */ - - // CIE standard illuminant series - static const struct mp_csp_col_xy - d50 = {0.34577, 0.35850}, - d65 = {0.31271, 0.32902}, - c = {0.31006, 0.31616}, - dci = {0.31400, 0.35100}, - e = {1.0/3.0, 1.0/3.0}; - - switch (spc) { - case PL_COLOR_PRIM_BT_470M: - return (struct mp_csp_primaries) { - .red = {0.670, 0.330}, - .green = {0.210, 0.710}, - .blue = {0.140, 0.080}, - .white = c - }; - case PL_COLOR_PRIM_BT_601_525: - return (struct mp_csp_primaries) { - .red = {0.630, 0.340}, - .green = {0.310, 0.595}, - .blue = {0.155, 0.070}, - .white = d65 - }; - case PL_COLOR_PRIM_BT_601_625: - return (struct mp_csp_primaries) { - .red = {0.640, 0.330}, - .green = {0.290, 0.600}, - .blue = {0.150, 0.060}, - .white = d65 - }; - // This is the default assumption if no colorspace information could - // be determined, eg. for files which have no video channel. - case PL_COLOR_PRIM_UNKNOWN: - case PL_COLOR_PRIM_BT_709: - return (struct mp_csp_primaries) { - .red = {0.640, 0.330}, - .green = {0.300, 0.600}, - .blue = {0.150, 0.060}, - .white = d65 - }; - case PL_COLOR_PRIM_BT_2020: - return (struct mp_csp_primaries) { - .red = {0.708, 0.292}, - .green = {0.170, 0.797}, - .blue = {0.131, 0.046}, - .white = d65 - }; - case PL_COLOR_PRIM_APPLE: - return (struct mp_csp_primaries) { - .red = {0.625, 0.340}, - .green = {0.280, 0.595}, - .blue = {0.115, 0.070}, - .white = d65 - }; - case PL_COLOR_PRIM_ADOBE: - return (struct mp_csp_primaries) { - .red = {0.640, 0.330}, - .green = {0.210, 0.710}, - .blue = {0.150, 0.060}, - .white = d65 - }; - case PL_COLOR_PRIM_PRO_PHOTO: - return (struct mp_csp_primaries) { - .red = {0.7347, 0.2653}, - .green = {0.1596, 0.8404}, - .blue = {0.0366, 0.0001}, - .white = d50 - }; - case PL_COLOR_PRIM_CIE_1931: - return (struct mp_csp_primaries) { - .red = {0.7347, 0.2653}, - .green = {0.2738, 0.7174}, - .blue = {0.1666, 0.0089}, - .white = e - }; - // From SMPTE RP 431-2 and 432-1 - case PL_COLOR_PRIM_DCI_P3: - case PL_COLOR_PRIM_DISPLAY_P3: - return (struct mp_csp_primaries) { - .red = {0.680, 0.320}, - .green = {0.265, 0.690}, - .blue = {0.150, 0.060}, - .white = spc == PL_COLOR_PRIM_DCI_P3 ? dci : d65 - }; - // From Panasonic VARICAM reference manual - case PL_COLOR_PRIM_V_GAMUT: - return (struct mp_csp_primaries) { - .red = {0.730, 0.280}, - .green = {0.165, 0.840}, - .blue = {0.100, -0.03}, - .white = d65 - }; - // From Sony S-Log reference manual - case PL_COLOR_PRIM_S_GAMUT: - return (struct mp_csp_primaries) { - .red = {0.730, 0.280}, - .green = {0.140, 0.855}, - .blue = {0.100, -0.05}, - .white = d65 - }; - // from EBU Tech. 3213-E - case PL_COLOR_PRIM_EBU_3213: - return (struct mp_csp_primaries) { - .red = {0.630, 0.340}, - .green = {0.295, 0.605}, - .blue = {0.155, 0.077}, - .white = d65 - }; - // From H.273, traditional film with Illuminant C - case PL_COLOR_PRIM_FILM_C: - return (struct mp_csp_primaries) { - .red = {0.681, 0.319}, - .green = {0.243, 0.692}, - .blue = {0.145, 0.049}, - .white = c - }; - // From libplacebo source code - case PL_COLOR_PRIM_ACES_AP0: - return (struct mp_csp_primaries) { - .red = {0.7347, 0.2653}, - .green = {0.0000, 1.0000}, - .blue = {0.0001, -0.0770}, - .white = {0.32168, 0.33767}, - }; - // From libplacebo source code - case PL_COLOR_PRIM_ACES_AP1: - return (struct mp_csp_primaries) { - .red = {0.713, 0.293}, - .green = {0.165, 0.830}, - .blue = {0.128, 0.044}, - .white = {0.32168, 0.33767}, - }; - default: - return (struct mp_csp_primaries) {{0}}; - } -} - -// Get the nominal peak for a given colorspace, relative to the reference white -// level. In other words, this returns the brightest encodable value that can -// be represented by a given transfer curve. -float mp_trc_nom_peak(enum pl_color_transfer trc) -{ - switch (trc) { - case PL_COLOR_TRC_PQ: return 10000.0 / MP_REF_WHITE; - case PL_COLOR_TRC_HLG: return 12.0 / MP_REF_WHITE_HLG; - case PL_COLOR_TRC_V_LOG: return 46.0855; - case PL_COLOR_TRC_S_LOG1: return 6.52; - case PL_COLOR_TRC_S_LOG2: return 9.212; - } - - return 1.0; -} - -bool mp_trc_is_hdr(enum pl_color_transfer trc) -{ - return mp_trc_nom_peak(trc) > 1.0; -} - -// Compute the RGB/XYZ matrix as described here: -// http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html -void mp_get_rgb2xyz_matrix(struct mp_csp_primaries space, float m[3][3]) -{ - float S[3], X[4], Z[4]; - - // Convert from CIE xyY to XYZ. Note that Y=1 holds true for all primaries - X[0] = space.red.x / space.red.y; - X[1] = space.green.x / space.green.y; - X[2] = space.blue.x / space.blue.y; - X[3] = space.white.x / space.white.y; - - Z[0] = (1 - space.red.x - space.red.y) / space.red.y; - Z[1] = (1 - space.green.x - space.green.y) / space.green.y; - Z[2] = (1 - space.blue.x - space.blue.y) / space.blue.y; - Z[3] = (1 - space.white.x - space.white.y) / space.white.y; - - // S = XYZ^-1 * W - for (int i = 0; i < 3; i++) { - m[0][i] = X[i]; - m[1][i] = 1; - m[2][i] = Z[i]; - } - - mp_invert_matrix3x3(m); - - for (int i = 0; i < 3; i++) - S[i] = m[i][0] * X[3] + m[i][1] * 1 + m[i][2] * Z[3]; - - // M = [Sc * XYZc] - for (int i = 0; i < 3; i++) { - m[0][i] = S[i] * X[i]; - m[1][i] = S[i] * 1; - m[2][i] = S[i] * Z[i]; - } -} +// LMS<-XYZ revised matrix from CIECAM97, based on a linear transform and +// normalized for equal energy on monochrome inputs +static const pl_matrix3x3 m_cat97 = {{ + { 0.8562, 0.3372, -0.1934 }, + { -0.8360, 1.8327, 0.0033 }, + { 0.0357, -0.0469, 1.0112 }, +}}; // M := M * XYZd<-XYZs -static void mp_apply_chromatic_adaptation(struct mp_csp_col_xy src, - struct mp_csp_col_xy dest, float m[3][3]) +static void apply_chromatic_adaptation(struct pl_cie_xy src, + struct pl_cie_xy dest, pl_matrix3x3 *mat) { // If the white points are nearly identical, this is a wasteful identity // operation. @@ -432,98 +187,33 @@ static void mp_apply_chromatic_adaptation(struct mp_csp_col_xy src, // XYZd<-XYZs = Ma^-1 * (I*[Cd/Cs]) * Ma // http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html - float C[3][2], tmp[3][3] = {{0}}; - - // Ma = Bradford matrix, arguably most popular method in use today. - // This is derived experimentally and thus hard-coded. - float bradford[3][3] = { - { 0.8951, 0.2664, -0.1614 }, - { -0.7502, 1.7135, 0.0367 }, - { 0.0389, -0.0685, 1.0296 }, - }; + // For Ma, we use the CIECAM97 revised (linear) matrix + float C[3][2]; for (int i = 0; i < 3; i++) { // source cone - C[i][0] = bradford[i][0] * mp_xy_X(src) - + bradford[i][1] * 1 - + bradford[i][2] * mp_xy_Z(src); + C[i][0] = m_cat97.m[i][0] * pl_cie_X(src) + + m_cat97.m[i][1] * 1 + + m_cat97.m[i][2] * pl_cie_Z(src); // dest cone - C[i][1] = bradford[i][0] * mp_xy_X(dest) - + bradford[i][1] * 1 - + bradford[i][2] * mp_xy_Z(dest); + C[i][1] = m_cat97.m[i][0] * pl_cie_X(dest) + + m_cat97.m[i][1] * 1 + + m_cat97.m[i][2] * pl_cie_Z(dest); } // tmp := I * [Cd/Cs] * Ma + pl_matrix3x3 tmp = {0}; for (int i = 0; i < 3; i++) - tmp[i][i] = C[i][1] / C[i][0]; + tmp.m[i][i] = C[i][1] / C[i][0]; - mp_mul_matrix3x3(tmp, bradford); + pl_matrix3x3_mul(&tmp, &m_cat97); // M := M * Ma^-1 * tmp - mp_invert_matrix3x3(bradford); - mp_mul_matrix3x3(m, bradford); - mp_mul_matrix3x3(m, tmp); -} - -// get the coefficients of the source -> dest cms matrix -void mp_get_cms_matrix(struct mp_csp_primaries src, struct mp_csp_primaries dest, - enum mp_render_intent intent, float m[3][3]) -{ - float tmp[3][3]; - - // In saturation mapping, we don't care about accuracy and just want - // primaries to map to primaries, making this an identity transformation. - if (intent == MP_INTENT_SATURATION) { - for (int i = 0; i < 3; i++) - m[i][i] = 1; - return; - } - - // RGBd<-RGBs = RGBd<-XYZd * XYZd<-XYZs * XYZs<-RGBs - // Equations from: http://www.brucelindbloom.com/index.html?Math.html - // Note: Perceptual is treated like relative colorimetric. There's no - // definition for perceptual other than "make it look good". - - // RGBd<-XYZd, inverted from XYZd<-RGBd - mp_get_rgb2xyz_matrix(dest, m); - mp_invert_matrix3x3(m); - - // Chromatic adaptation, except in absolute colorimetric intent - if (intent != MP_INTENT_ABSOLUTE_COLORIMETRIC) - mp_apply_chromatic_adaptation(src.white, dest.white, m); - - // XYZs<-RGBs - mp_get_rgb2xyz_matrix(src, tmp); - mp_mul_matrix3x3(m, tmp); -} - -// get the coefficients of an ST 428-1 xyz -> rgb conversion matrix -// intent = the rendering intent used to convert to the target primaries -static void mp_get_xyz2rgb_coeffs(struct mp_csp_params *params, - enum mp_render_intent intent, struct mp_cmat *m) -{ - // Convert to DCI-P3 - struct mp_csp_primaries prim = mp_get_csp_primaries(PL_COLOR_PRIM_DCI_P3); - float brightness = params->brightness; - mp_get_rgb2xyz_matrix(prim, m->m); - mp_invert_matrix3x3(m->m); - - // All non-absolute mappings want to map source white to target white - if (intent != MP_INTENT_ABSOLUTE_COLORIMETRIC) { - // SMPTE EG 432-1 Annex H defines the white point as equal energy - static const struct mp_csp_col_xy smpte432 = {1.0/3.0, 1.0/3.0}; - mp_apply_chromatic_adaptation(smpte432, prim.white, m->m); - } - - // 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. - brightness *= fabs(brightness); - - for (int i = 0; i < 3; i++) - m->c[i] = brightness; + pl_matrix3x3 ma_inv = m_cat97; + pl_matrix3x3_invert(&ma_inv); + pl_matrix3x3_mul(mat, &ma_inv); + pl_matrix3x3_mul(mat, &tmp); } // Get multiplication factor required if image data is fit within the LSBs of a @@ -608,19 +298,19 @@ void mp_get_csp_uint_mul(enum pl_color_system csp, enum pl_color_levels levels, * Under these conditions the given parameters lr, lg, lb uniquely * determine the mapping of Y, U, V to R, G, B. */ -static void luma_coeffs(struct mp_cmat *mat, float lr, float lg, float lb) +static void luma_coeffs(struct pl_transform3x3 *mat, float lr, float lg, float lb) { assert(fabs(lr+lg+lb - 1) < 1e-6); - *mat = (struct mp_cmat) { - { {1, 0, 2 * (1-lr) }, - {1, -2 * (1-lb) * lb/lg, -2 * (1-lr) * lr/lg }, - {1, 2 * (1-lb), 0 } }, + *mat = (struct pl_transform3x3) { + { {{1, 0, 2 * (1-lr) }, + {1, -2 * (1-lb) * lb/lg, -2 * (1-lr) * lr/lg }, + {1, 2 * (1-lb), 0 }} }, // Constant coefficients (mat->c) not set here }; } // get the coefficients of the yuv -> rgb conversion matrix -void mp_get_csp_matrix(struct mp_csp_params *params, struct mp_cmat *m) +void mp_get_csp_matrix(struct mp_csp_params *params, struct pl_transform3x3 *m) { enum pl_color_system colorspace = params->repr.sys; if (colorspace <= PL_COLOR_SYSTEM_UNKNOWN || colorspace >= PL_COLOR_SYSTEM_COUNT) @@ -639,29 +329,30 @@ void mp_get_csp_matrix(struct mp_csp_params *params, struct mp_cmat *m) // If this clips on any VO, a constant 0.5 coefficient can be added // to the chroma channels to normalize them into [0,1]. This is not // currently needed by anything, though. - *m = (struct mp_cmat){{{0, 0, 1}, {1, 0, 0}, {0, 1, 0}}}; + *m = (struct pl_transform3x3){{{{0, 0, 1}, {1, 0, 0}, {0, 1, 0}}}}; break; } case PL_COLOR_SYSTEM_RGB: { - *m = (struct mp_cmat){{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}}; + *m = (struct pl_transform3x3){{{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}}}; levels_in = -1; break; } case PL_COLOR_SYSTEM_XYZ: { - // The vo should probably not be using a matrix generated by this - // function for XYZ sources, but if it does, let's just convert it to - // an equivalent RGB space based on the colorimetry metadata it - // provided in mp_csp_params. (At the risk of clipping, if the - // chosen primaries are too small to fit the actual data) - mp_get_xyz2rgb_coeffs(params, MP_INTENT_RELATIVE_COLORIMETRIC, m); + // For lack of anything saner to do, just assume the caller wants + // DCI-P3 primaries, which is a reasonable assumption. + const struct pl_raw_primaries *dst = pl_raw_primaries_get(PL_COLOR_PRIM_DCI_P3); + pl_matrix3x3 mat = pl_get_xyz2rgb_matrix(dst); + // DCDM X'Y'Z' is expected to have equal energy white point (EG 432-1 Annex H) + apply_chromatic_adaptation((struct pl_cie_xy){1.0/3.0, 1.0/3.0}, dst->white, &mat); + *m = (struct pl_transform3x3) { .mat = mat }; levels_in = -1; break; } case PL_COLOR_SYSTEM_YCGCO: { - *m = (struct mp_cmat) { - {{1, -1, 1}, - {1, 1, 0}, - {1, -1, -1}}, + *m = (struct pl_transform3x3) { + {{{1, -1, 1}, + {1, 1, 0}, + {1, -1, -1}}}, }; break; } @@ -680,9 +371,9 @@ void mp_get_csp_matrix(struct mp_csp_params *params, struct mp_cmat *m) float huecos = params->gray ? 0 : params->saturation * cos(params->hue); float huesin = params->gray ? 0 : params->saturation * sin(params->hue); for (int i = 0; i < 3; i++) { - float u = m->m[i][1], v = m->m[i][2]; - m->m[i][1] = huecos * u - huesin * v; - m->m[i][2] = huesin * u + huecos * v; + float u = m->mat.m[i][1], v = m->mat.m[i][2]; + m->mat.m[i][1] = huecos * u - huesin * v; + m->mat.m[i][2] = huesin * u + huecos * v; } } @@ -728,13 +419,13 @@ void mp_get_csp_matrix(struct mp_csp_params *params, struct mp_cmat *m) cmul *= params->contrast; for (int i = 0; i < 3; i++) { - m->m[i][0] *= ymul; - m->m[i][1] *= cmul; - m->m[i][2] *= cmul; + m->mat.m[i][0] *= ymul; + m->mat.m[i][1] *= cmul; + m->mat.m[i][2] *= cmul; // Set c so that Y=umin,UV=cmid maps to RGB=min (black to black), // also add brightness offset (black lift) - m->c[i] = rgblev.min - m->m[i][0] * yuvlev.ymin - - (m->m[i][1] + m->m[i][2]) * yuvlev.cmid + m->c[i] = rgblev.min - m->mat.m[i][0] * yuvlev.ymin + - (m->mat.m[i][1] + m->mat.m[i][2]) * yuvlev.cmid + params->brightness; } } @@ -822,32 +513,17 @@ void mp_csp_equalizer_state_get(struct mp_csp_equalizer_state *state, mp_csp_copy_equalizer_values(params, opts); } -void mp_invert_cmat(struct mp_cmat *out, struct mp_cmat *in) -{ - *out = *in; - mp_invert_matrix3x3(out->m); - - // fix the constant coefficient - // rgb = M * yuv + C - // M^-1 * rgb = yuv + M^-1 * C - // yuv = M^-1 * rgb - M^-1 * C - // ^^^^^^^^^^ - out->c[0] = -(out->m[0][0] * in->c[0] + out->m[0][1] * in->c[1] + out->m[0][2] * in->c[2]); - out->c[1] = -(out->m[1][0] * in->c[0] + out->m[1][1] * in->c[1] + out->m[1][2] * in->c[2]); - out->c[2] = -(out->m[2][0] * in->c[0] + out->m[2][1] * in->c[1] + out->m[2][2] * in->c[2]); -} - // Multiply the color in c with the given matrix. // i/o is {R, G, B} or {Y, U, V} (depending on input/output and matrix), using // a fixed point representation with the given number of bits (so for bits==8, // [0,255] maps to [0,1]). The output is clipped to the range as needed. -void mp_map_fixp_color(struct mp_cmat *matrix, int ibits, int in[3], +void mp_map_fixp_color(struct pl_transform3x3 *matrix, int ibits, int in[3], int obits, int out[3]) { for (int i = 0; i < 3; i++) { double val = matrix->c[i]; for (int x = 0; x < 3; x++) - val += matrix->m[i][x] * in[x] / ((1 << ibits) - 1); + val += matrix->mat.m[i][x] * in[x] / ((1 << ibits) - 1); int ival = lrint(val * ((1 << obits) - 1)); out[i] = av_clip(ival, 0, (1 << obits) - 1); } diff --git a/video/csputils.h b/video/csputils.h index 9b2d0378df96..5ab1287d9c69 100644 --- a/video/csputils.h +++ b/video/csputils.h @@ -46,15 +46,6 @@ enum mp_csp_light { extern const struct m_opt_choice_alternatives mp_csp_light_names[]; -// 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 { - MP_INTENT_PERCEPTUAL = 0, - MP_INTENT_RELATIVE_COLORIMETRIC = 1, - MP_INTENT_SATURATION = 2, - MP_INTENT_ABSOLUTE_COLORIMETRIC = 3 -}; - // The numeric values (except -1) match the Matroska StereoMode element value. enum mp_stereo3d_mode { MP_STEREO3D_INVALID = -1, @@ -123,59 +114,15 @@ bool mp_csp_equalizer_state_changed(struct mp_csp_equalizer_state *state); void mp_csp_equalizer_state_get(struct mp_csp_equalizer_state *state, struct mp_csp_params *params); -struct mp_csp_col_xy { - float x, y; -}; - -static inline float mp_xy_X(struct mp_csp_col_xy xy) { - return xy.x / xy.y; -} - -static inline float mp_xy_Z(struct mp_csp_col_xy xy) { - return (1 - xy.x - xy.y) / xy.y; -} - -struct mp_csp_primaries { - struct mp_csp_col_xy red, green, blue, white; -}; - enum pl_color_system mp_csp_guess_colorspace(int width, int height); enum pl_color_primaries mp_csp_guess_primaries(int width, int height); -struct mp_csp_primaries mp_get_csp_primaries(enum pl_color_primaries csp); -float mp_trc_nom_peak(enum pl_color_transfer trc); -bool mp_trc_is_hdr(enum pl_color_transfer trc); - -/* Color conversion matrix: RGB = m * YUV + c - * m is in row-major matrix, with m[row][col], e.g.: - * [ a11 a12 a13 ] float m[3][3] = { { a11, a12, a13 }, - * [ a21 a22 a23 ] { a21, a22, a23 }, - * [ a31 a32 a33 ] { a31, a32, a33 } }; - * This is accessed as e.g.: m[2-1][1-1] = a21 - * In particular, each row contains all the coefficients for one of R, G, B, - * while each column contains all the coefficients for one of Y, U, V: - * m[r,g,b][y,u,v] = ... - * The matrix could also be viewed as group of 3 vectors, e.g. the 1st column - * is the Y vector (1, 1, 1), the 2nd is the U vector, the 3rd the V vector. - * The matrix might also be used for other conversions and colorspaces. - */ -struct mp_cmat { - float m[3][3]; - float c[3]; -}; - -void mp_get_rgb2xyz_matrix(struct mp_csp_primaries space, float m[3][3]); -void mp_get_cms_matrix(struct mp_csp_primaries src, struct mp_csp_primaries dest, - enum mp_render_intent intent, float cms_matrix[3][3]); - double mp_get_csp_mul(enum pl_color_system csp, int input_bits, int texture_bits); void mp_get_csp_uint_mul(enum pl_color_system csp, enum pl_color_levels levels, int bits, int component, double *out_m, double *out_o); -void mp_get_csp_matrix(struct mp_csp_params *params, struct mp_cmat *out); +void mp_get_csp_matrix(struct mp_csp_params *params, struct pl_transform3x3 *out); -void mp_invert_matrix3x3(float m[3][3]); -void mp_invert_cmat(struct mp_cmat *out, struct mp_cmat *in); -void mp_map_fixp_color(struct mp_cmat *matrix, int ibits, int in[3], +void mp_map_fixp_color(struct pl_transform3x3 *matrix, int ibits, int in[3], int obits, int out[3]); #endif /* MPLAYER_CSPUTILS_H */ diff --git a/video/mp_image.c b/video/mp_image.c index 8fbcfea77da8..512239c7bc42 100644 --- a/video/mp_image.c +++ b/video/mp_image.c @@ -963,11 +963,11 @@ void mp_image_params_guess_csp(struct mp_image_params *params) } else { // If the signal peak is unknown, we're forced to pick the TRC's // nominal range as the signal peak to prevent clipping - params->color.hdr.max_luma = mp_trc_nom_peak(params->color.transfer) * MP_REF_WHITE; + params->color.hdr.max_luma = pl_color_transfer_nominal_peak(params->color.transfer) * MP_REF_WHITE; } } - if (!mp_trc_is_hdr(params->color.transfer)) { + if (!pl_color_space_is_hdr(¶ms->color)) { // Some clips have leftover HDR metadata after conversion to SDR, so to // avoid blowing up the tone mapping code, strip/sanitize it params->color.hdr = pl_hdr_metadata_empty; diff --git a/video/out/gpu/lcms.c b/video/out/gpu/lcms.c index 00d819d2f0e3..1e451aa7a216 100644 --- a/video/out/gpu/lcms.c +++ b/video/out/gpu/lcms.c @@ -197,12 +197,12 @@ static cmsHPROFILE get_vid_profile(struct gl_lcms *p, cmsContext cms, // The input profile for the transformation is dependent on the video // primaries and transfer characteristics - struct mp_csp_primaries csp = mp_get_csp_primaries(prim); - cmsCIExyY wp_xyY = {csp.white.x, csp.white.y, 1.0}; + const struct pl_raw_primaries *csp = pl_raw_primaries_get(prim); + cmsCIExyY wp_xyY = {csp->white.x, csp->white.y, 1.0}; cmsCIExyYTRIPLE prim_xyY = { - .Red = {csp.red.x, csp.red.y, 1.0}, - .Green = {csp.green.x, csp.green.y, 1.0}, - .Blue = {csp.blue.x, csp.blue.y, 1.0}, + .Red = {csp->red.x, csp->red.y, 1.0}, + .Green = {csp->green.x, csp->green.y, 1.0}, + .Blue = {csp->blue.x, csp->blue.y, 1.0}, }; cmsToneCurve *tonecurve[3] = {0}; @@ -242,7 +242,7 @@ static cmsHPROFILE get_vid_profile(struct gl_lcms *p, cmsContext cms, // function. Relative colorimetric is used since we want to // approximate the BT.1886 to the target device's actual black // point even in e.g. perceptual mode - const int intent = MP_INTENT_RELATIVE_COLORIMETRIC; + const int intent = PL_INTENT_RELATIVE_COLORIMETRIC; cmsCIEXYZ bp_XYZ; if (!cmsDetectBlackPoint(&bp_XYZ, disp_profile, intent, 0)) return false; @@ -519,7 +519,7 @@ const struct m_sub_options mp_icc_conf = { .size = sizeof(struct mp_icc_opts), .defaults = &(const struct mp_icc_opts) { .size_str = "auto", - .intent = MP_INTENT_RELATIVE_COLORIMETRIC, + .intent = PL_INTENT_RELATIVE_COLORIMETRIC, .use_embedded = true, .cache = true, }, diff --git a/video/out/gpu/video.c b/video/out/gpu/video.c index 70aca4223866..5ae2816fed8a 100644 --- a/video/out/gpu/video.c +++ b/video/out/gpu/video.c @@ -2343,9 +2343,9 @@ static void pass_convert_yuv(struct gl_video *p) // Conversion to RGB. For RGB itself, this still applies e.g. brightness // and contrast controls, or expansion of e.g. LSB-packed 10 bit data. - struct mp_cmat m = {{{0}}}; + struct pl_transform3x3 m = {0}; mp_get_csp_matrix(&cparams, &m); - gl_sc_uniform_mat3(sc, "colormatrix", true, &m.m[0][0]); + gl_sc_uniform_mat3(sc, "colormatrix", true, &m.mat.m[0][0]); gl_sc_uniform_vec3(sc, "colormatrix_c", m.c); GLSL(color.rgb = mat3(colormatrix) * color.rgb + colormatrix_c;) @@ -2481,7 +2481,7 @@ static void pass_scale_main(struct gl_video *p) // Linear light downscaling results in nasty artifacts for HDR curves // due to the potentially extreme brightness differences severely // compounding any ringing. So just scale in gamma light instead. - if (mp_trc_is_hdr(p->image_params.color.transfer)) + if (pl_color_space_is_hdr(&p->image_params.color)) use_linear = false; } else if (upscaling) { use_linear = p->opts.linear_upscaling || p->opts.sigmoid_upscaling; @@ -2591,7 +2591,7 @@ static void pass_colormanage(struct gl_video *p, struct pl_color_space src, // limitation reasons, so we use a gamma 2.2 input curve here instead. // We could pick any value we want here, the difference is just coding // efficiency. - if (mp_trc_is_hdr(trc_orig)) + if (pl_color_space_is_hdr(&p->image_params.color)) trc_orig = PL_COLOR_TRC_GAMMA22; if (gl_video_get_lut3d(p, prim_orig, trc_orig)) { @@ -2628,7 +2628,7 @@ static void pass_colormanage(struct gl_video *p, struct pl_color_space src, // Avoid outputting linear light or HDR content "by default". For these // just pick gamma 2.2 as a default, since it's a good estimate for // the response of typical displays - if (dst.transfer == PL_COLOR_TRC_LINEAR || mp_trc_is_hdr(dst.transfer)) + if (dst.transfer == PL_COLOR_TRC_LINEAR || pl_color_space_is_hdr(&dst)) dst.transfer = PL_COLOR_TRC_GAMMA22; } @@ -2636,9 +2636,9 @@ static void pass_colormanage(struct gl_video *p, struct pl_color_space src, // it from the chosen transfer function. Also normalize the src peak, in // case it was unknown if (!dst.hdr.max_luma) - dst.hdr.max_luma = mp_trc_nom_peak(dst.transfer) * MP_REF_WHITE; + dst.hdr.max_luma = pl_color_transfer_nominal_peak(dst.transfer) * MP_REF_WHITE; if (!src.hdr.max_luma) - src.hdr.max_luma = mp_trc_nom_peak(src.transfer) * MP_REF_WHITE; + src.hdr.max_luma = pl_color_transfer_nominal_peak(src.transfer) * MP_REF_WHITE; // Whitelist supported modes switch (p->opts.tone_map.curve) { @@ -2670,7 +2670,7 @@ static void pass_colormanage(struct gl_video *p, struct pl_color_space src, } struct gl_tone_map_opts tone_map = p->opts.tone_map; - bool detect_peak = tone_map.compute_peak >= 0 && mp_trc_is_hdr(src.transfer) + bool detect_peak = tone_map.compute_peak >= 0 && pl_color_space_is_hdr(&src) && src.hdr.max_luma > dst.hdr.max_luma; if (detect_peak && !p->hdr_peak_ssbo) { diff --git a/video/out/gpu/video_shaders.c b/video/out/gpu/video_shaders.c index 2201e12d4639..62fe11caaea1 100644 --- a/video/out/gpu/video_shaders.c +++ b/video/out/gpu/video_shaders.c @@ -17,6 +17,8 @@ #include <math.h> +#include <libplacebo/colorspace.h> + #include "video_shaders.h" #include "video.h" @@ -337,7 +339,7 @@ static const float SLOG_A = 0.432699, // // These functions always output to a normalized scale of [0,1], for // convenience of the video.c code that calls it. To get the values in an -// absolute scale, multiply the result by `mp_trc_nom_peak(trc)` +// absolute scale, multiply the result by `pl_color_transfer_nominal_peak(trc)` void pass_linearize(struct gl_shader_cache *sc, enum pl_color_transfer trc) { if (trc == PL_COLOR_TRC_LINEAR) @@ -430,7 +432,7 @@ void pass_linearize(struct gl_shader_cache *sc, enum pl_color_transfer trc) } // Rescale to prevent clipping on non-float textures - GLSLF("color.rgb *= vec3(1.0/%f);\n", mp_trc_nom_peak(trc)); + GLSLF("color.rgb *= vec3(1.0/%f);\n", pl_color_transfer_nominal_peak(trc)); } // Delinearize (compress), given a TRC as output. This corresponds to the @@ -445,7 +447,7 @@ void pass_delinearize(struct gl_shader_cache *sc, enum pl_color_transfer trc) GLSLF("// delinearize\n"); GLSL(color.rgb = clamp(color.rgb, 0.0, 1.0);) - GLSLF("color.rgb *= vec3(%f);\n", mp_trc_nom_peak(trc)); + GLSLF("color.rgb *= vec3(%f);\n", pl_color_transfer_nominal_peak(trc)); switch (trc) { case PL_COLOR_TRC_SRGB: @@ -842,11 +844,10 @@ void pass_color_map(struct gl_shader_cache *sc, bool is_linear, // Some operations need access to the video's luma coefficients, so make // them available - float rgb2xyz[3][3]; - mp_get_rgb2xyz_matrix(mp_get_csp_primaries(src.primaries), rgb2xyz); - gl_sc_uniform_vec3(sc, "src_luma", rgb2xyz[1]); - mp_get_rgb2xyz_matrix(mp_get_csp_primaries(dst.primaries), rgb2xyz); - gl_sc_uniform_vec3(sc, "dst_luma", rgb2xyz[1]); + pl_matrix3x3 rgb2xyz = pl_get_rgb2xyz_matrix(pl_raw_primaries_get(src.primaries)); + gl_sc_uniform_vec3(sc, "src_luma", rgb2xyz.m[1]); + rgb2xyz = pl_get_rgb2xyz_matrix(pl_raw_primaries_get(dst.primaries)); + gl_sc_uniform_vec3(sc, "dst_luma", rgb2xyz.m[1]); bool need_ootf = src_light != dst_light; if (src_light == MP_CSP_LIGHT_SCENE_HLG && src.hdr.max_luma != dst.hdr.max_luma) @@ -867,7 +868,7 @@ void pass_color_map(struct gl_shader_cache *sc, bool is_linear, } // Pre-scale the incoming values into an absolute scale - GLSLF("color.rgb *= vec3(%f);\n", mp_trc_nom_peak(src.transfer)); + GLSLF("color.rgb *= vec3(%f);\n", pl_color_transfer_nominal_peak(src.transfer)); if (need_ootf) pass_ootf(sc, src_light, src.hdr.max_luma / MP_REF_WHITE); @@ -880,11 +881,11 @@ void pass_color_map(struct gl_shader_cache *sc, bool is_linear, // Adapt to the right colorspace if necessary if (src.primaries != dst.primaries) { - struct mp_csp_primaries csp_src = mp_get_csp_primaries(src.primaries), - csp_dst = mp_get_csp_primaries(dst.primaries); - float m[3][3] = {{0}}; - mp_get_cms_matrix(csp_src, csp_dst, MP_INTENT_RELATIVE_COLORIMETRIC, m); - gl_sc_uniform_mat3(sc, "cms_matrix", true, &m[0][0]); + const struct pl_raw_primaries *csp_src = pl_raw_primaries_get(src.primaries), + *csp_dst = pl_raw_primaries_get(dst.primaries); + pl_matrix3x3 m = pl_get_color_mapping_matrix(csp_src, csp_dst, + PL_INTENT_RELATIVE_COLORIMETRIC); + gl_sc_uniform_mat3(sc, "cms_matrix", true, &m.m[0][0]); GLSL(color.rgb = cms_matrix * color.rgb;) if (!opts->gamut_mode || opts->gamut_mode == GAMUT_DESATURATE) { @@ -907,8 +908,8 @@ void pass_color_map(struct gl_shader_cache *sc, bool is_linear, // For SDR, we normalize to the chosen signal peak. For HDR, we normalize // to the encoding range of the transfer function. float dst_range = dst.hdr.max_luma / MP_REF_WHITE; - if (mp_trc_is_hdr(dst.transfer)) - dst_range = mp_trc_nom_peak(dst.transfer); + if (pl_color_space_is_hdr(&dst)) + dst_range = pl_color_transfer_nominal_peak(dst.transfer); GLSLF("color.rgb *= vec3(%f);\n", 1.0 / dst_range); @@ -1009,7 +1010,7 @@ void pass_sample_deband(struct gl_shader_cache *sc, struct deband_opts *opts, GLSL(noise.z = rand(h); h = permute(h);) // Noise is scaled to the signal level to prevent extreme noise for HDR - float gain = opts->grain/8192.0 / mp_trc_nom_peak(trc); + float gain = opts->grain/8192.0 / pl_color_transfer_nominal_peak(trc); GLSLF("color.xyz += %f * (noise - vec3(0.5));\n", gain); GLSLF("}\n"); } diff --git a/video/vdpau_mixer.c b/video/vdpau_mixer.c index b1aed70e78fe..5adb3b4ec3c3 100644 --- a/video/vdpau_mixer.c +++ b/video/vdpau_mixer.c @@ -193,7 +193,7 @@ static int create_vdp_mixer(struct mp_vdpau_mixer *mixer, if (!opts->chroma_deint) SET_VIDEO_ATTR(SKIP_CHROMA_DEINTERLACE, uint8_t, 1); - struct mp_cmat yuv2rgb; + struct pl_transform3x3 yuv2rgb; VdpCSCMatrix matrix; struct mp_csp_params cparams = MP_CSP_PARAMS_DEFAULTS; @@ -204,7 +204,7 @@ static int create_vdp_mixer(struct mp_vdpau_mixer *mixer, for (int r = 0; r < 3; r++) { for (int c = 0; c < 3; c++) - matrix[r][c] = yuv2rgb.m[r][c]; + matrix[r][c] = yuv2rgb.mat.m[r][c]; matrix[r][3] = yuv2rgb.c[r]; } diff --git a/video/zimg.c b/video/zimg.c index 35a987dfea7d..907e81deb7fc 100644 --- a/video/zimg.c +++ b/video/zimg.c @@ -551,7 +551,7 @@ static bool mp_zimg_state_init(struct mp_zimg_context *ctx, params.allow_approximate_gamma = 1; // leave at default for SDR, which means 100 cd/m^2 for zimg - if (ctx->dst.color.hdr.max_luma > 0 && mp_trc_is_hdr(ctx->dst.color.transfer)) + if (ctx->dst.color.hdr.max_luma > 0 && pl_color_space_is_hdr(&ctx->dst.color)) params.nominal_peak_luminance = ctx->dst.color.hdr.max_luma; st->graph = zimg_filter_graph_build(&src_fmt, &dst_fmt, ¶ms); From ae4ec861a381d06c49ffcf83572d244cba862135 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= <kasper93@gmail.com> Date: Sat, 4 Nov 2023 07:10:31 +0100 Subject: [PATCH 5/5] vo_gpu_next: simplify after recent changes --- video/out/vo_gpu_next.c | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/video/out/vo_gpu_next.c b/video/out/vo_gpu_next.c index 2fa2a46c2eca..42ceb6e7a945 100644 --- a/video/out/vo_gpu_next.c +++ b/video/out/vo_gpu_next.c @@ -232,8 +232,6 @@ static struct mp_image *get_image(struct vo *vo, int imgfmt, int w, int h, return mpi; } -static struct pl_color_space get_mpi_csp(struct vo *vo, struct mp_image *mpi); - static void update_overlays(struct vo *vo, struct mp_osd_res res, int flags, enum pl_overlay_coords coords, struct osd_state *state, struct pl_frame *frame, @@ -318,7 +316,7 @@ static void update_overlays(struct vo *vo, struct mp_osd_res res, ol->repr.alpha = PL_ALPHA_PREMULTIPLIED; // Infer bitmap colorspace from source if (src) { - ol->color = get_mpi_csp(vo, src); + ol->color = src->params.color; // Seems like HDR subtitles are targeting SDR white if (pl_color_transfer_is_hdr(ol->color.transfer)) { ol->color.hdr = (struct pl_hdr_metadata) { @@ -437,16 +435,6 @@ static int plane_data_from_imgfmt(struct pl_plane_data out_data[4], return desc.num_planes; } -static struct pl_color_space get_mpi_csp(struct vo *vo, struct mp_image *mpi) -{ - struct pl_color_space csp = { - .primaries = mpi->params.color.primaries, - .transfer = mpi->params.color.transfer, - .hdr = mpi->params.color.hdr, - }; - return csp; -} - static bool hwdec_reconfig(struct priv *p, struct ra_hwdec *hwdec, const struct mp_image_params *par) { @@ -567,12 +555,8 @@ static bool map_frame(pl_gpu gpu, pl_tex *tex, const struct pl_source_frame *src } *frame = (struct pl_frame) { - .color = get_mpi_csp(vo, mpi), - .repr = { - .sys = par->repr.sys, - .levels = par->repr.levels, - .alpha = par->repr.alpha, - }, + .color = par->color, + .repr = par->repr, .profile = { .data = mpi->icc_profile ? mpi->icc_profile->data : NULL, .len = mpi->icc_profile ? mpi->icc_profile->size : 0, @@ -910,7 +894,7 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame) const struct gl_video_opts *opts = p->opts_cache->opts; if (p->target_hint && frame->current) { - struct pl_color_space hint = get_mpi_csp(vo, frame->current); + struct pl_color_space hint = frame->current->params.color; if (opts->target_prim) hint.primaries = opts->target_prim; if (opts->target_trc)
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor