diff --git a/src/gallium/auxiliary/vl/vl_csc.c b/src/gallium/auxiliary/vl/vl_csc.c index 374b4eee214..cfb6b4c0f5b 100644 --- a/src/gallium/auxiliary/vl/vl_csc.c +++ b/src/gallium/auxiliary/vl/vl_csc.c @@ -27,6 +27,7 @@ #include "util/u_math.h" #include "util/u_debug.h" +#include "util/u_ycbcr.h" #include "vl_csc.h" @@ -58,119 +59,59 @@ void vl_csc_get_rgbyuv_matrix(enum pipe_video_vpp_matrix_coefficients coefficien const bool in_yuv = util_format_is_yuv(in_format); const bool out_yuv = util_format_is_yuv(out_format); const unsigned bpc = format_bpc(in_format); - const float scale = (1 << bpc) / ((1 << bpc) - 1.0); - const float y_min = 16.0 / 256.0 * scale; - const float y_max = 235.0 / 256.0 * scale; - const float c_mid = 128.0 / 256.0 * scale; - const float c_max = 240.0 / 256.0 * scale; - float y_scale, c_scale, y_bias, c_bias; + const unsigned bpcs[3] = { bpc, bpc, bpc }; memcpy(matrix, &identity, sizeof(vl_csc_matrix)); if (in_yuv != out_yuv && coefficients == PIPE_VIDEO_VPP_MCF_RGB) return; + float in_range[3][2]; /* Convert input to full range, chroma to [-0.5,0.5]. */ - if (in_color_range == PIPE_VIDEO_VPP_CHROMA_COLOR_RANGE_REDUCED) { - y_scale = 1.0 / (y_max - y_min); - c_scale = in_yuv ? 0.5 / (c_max - c_mid) : y_scale; - y_bias = -y_min; - c_bias = in_yuv ? -c_mid : y_bias; - } else if (in_yuv) { - y_scale = 1.0; - c_scale = 0.5 / (1.0 - c_mid); - y_bias = 0.0; - c_bias = -c_mid; - } else { - y_scale = c_scale = 1.0; - y_bias = c_bias = 0.0; - } + if (in_color_range == PIPE_VIDEO_VPP_CHROMA_COLOR_RANGE_REDUCED) + util_get_narrow_range_coeffs(in_range, bpcs); + else if (in_yuv) + util_get_full_range_coeffs(in_range, bpcs); + else + util_get_identity_range_coeffs(in_range); if (in_yuv != out_yuv) { - float cr, cg, cb; + const float *ycbcr_coeffs; switch (coefficients) { case PIPE_VIDEO_VPP_MCF_BT470BG: case PIPE_VIDEO_VPP_MCF_SMPTE170M: - cr = 0.299; - cb = 0.114; + ycbcr_coeffs = util_ycbcr_bt601_coeffs; break; case PIPE_VIDEO_VPP_MCF_SMPTE240M: - cr = 0.212; - cb = 0.087; + ycbcr_coeffs = util_ycbcr_smpte240m_coeffs; break; case PIPE_VIDEO_VPP_MCF_BT2020_NCL: - cr = 0.2627; - cb = 0.0593; + ycbcr_coeffs = util_ycbcr_bt2020_coeffs; break; case PIPE_VIDEO_VPP_MCF_BT709: default: - cr = 0.2126; - cb = 0.0722; + ycbcr_coeffs = util_ycbcr_bt709_coeffs; break; } - cg = 1.0 - cb - cr; - - if (in_yuv) { - /* YUV to RGB */ - (*matrix)[0][0] = 1.0; - (*matrix)[0][1] = 0.0; - (*matrix)[0][2] = 2.0 - 2.0 * cr; - (*matrix)[0][3] = 0.0; - (*matrix)[1][0] = 1.0; - (*matrix)[1][1] = (-cb / cg) * (2.0 - 2.0 * cb); - (*matrix)[1][2] = (-cr / cg) * (2.0 - 2.0 * cr); - (*matrix)[1][3] = 0.0; - (*matrix)[2][0] = 1.0; - (*matrix)[2][1] = 2.0 - 2.0 * cb; - (*matrix)[2][2] = 0.0; - (*matrix)[2][3] = 0.0; - } else { - /* RGB to YUV */ - (*matrix)[0][0] = cr; - (*matrix)[0][1] = cg; - (*matrix)[0][2] = cb; - (*matrix)[0][3] = 0.0; - (*matrix)[1][0] = (0.5 / (cb - 1.0)) * cr; - (*matrix)[1][1] = (0.5 / (cb - 1.0)) * cg; - (*matrix)[1][2] = 0.5; - (*matrix)[1][3] = 0.0; - (*matrix)[2][0] = 0.5; - (*matrix)[2][1] = (0.5 / (cr - 1.0)) * cg; - (*matrix)[2][2] = (0.5 / (cr - 1.0)) * cb; - (*matrix)[2][3] = 0.0; - } + if (in_yuv) + util_get_ycbcr_to_rgb_matrix(*matrix, ycbcr_coeffs); + else + util_get_rgb_to_ycbcr_matrix(*matrix, ycbcr_coeffs); } - for (unsigned i = 0; i < 3; i++) { - for (unsigned j = 0; j < 3; j++) { - (*matrix)[i][j] *= j == 0 ? y_scale : c_scale; - (*matrix)[i][3] += (*matrix)[i][j] * (j == 0 ? y_bias : c_bias); - } - } + util_ycbcr_adjust_from_range(*matrix, in_range); - /* Convert output to reduced range, chroma to [0.0,1.0]. */ - if (out_color_range == PIPE_VIDEO_VPP_CHROMA_COLOR_RANGE_REDUCED) { - y_scale = (y_max - y_min) / 1.0; - c_scale = in_yuv ? y_scale : (c_max - c_mid) / 0.5; - y_bias = y_min; - c_bias = in_yuv ? y_bias : c_mid; - } else if (out_yuv) { - y_scale = 1.0; - c_scale = (1.0 - c_mid) / 0.5; - y_bias = 0.0; - c_bias = c_mid; - } else { - y_scale = c_scale = 1.0; - y_bias = c_bias = 0.0; - } + float out_range[3][2]; + if (out_color_range == PIPE_VIDEO_VPP_CHROMA_COLOR_RANGE_REDUCED) + util_get_narrow_range_coeffs(out_range, bpcs); + else if (out_yuv) + util_get_full_range_coeffs(out_range, bpcs); + else + util_get_identity_range_coeffs(out_range); - for (unsigned i = 0; i < 3; i++) { - for (unsigned j = 0; j < 4; j++) - (*matrix)[i][j] *= i == 0 ? y_scale : c_scale; - (*matrix)[i][3] += i == 0 ? y_bias : c_bias; - } + util_ycbcr_adjust_to_range(*matrix, out_range); } void vl_csc_get_primaries_matrix(enum pipe_video_vpp_color_primaries in_color_primaries,