gallium/vl: Add new function to get RGB YUV conversion matrix
This supports Identity, BT601, BT709, BT2020, SMPTE240M and color range conversions in both directions. Acked-by: Ruijing Dong <ruijing.dong@amd.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/37058>
This commit is contained in:
parent
39fa54bc6e
commit
228b2ac2a3
2 changed files with 149 additions and 0 deletions
|
|
@ -242,3 +242,144 @@ void vl_csc_get_matrix(enum VL_CSC_COLOR_STANDARD cs,
|
|||
(*cstd)[2][1] * (x * cbbias + y * crbias) +
|
||||
(*cstd)[2][2] * (x * crbias - y * cbbias);
|
||||
}
|
||||
|
||||
static unsigned format_bpc(enum pipe_format format)
|
||||
{
|
||||
const enum pipe_format plane_format = util_format_get_plane_format(format, 0);
|
||||
const struct util_format_description *desc = util_format_description(plane_format);
|
||||
|
||||
for (unsigned i = 0; i < desc->nr_channels; i++) {
|
||||
if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID)
|
||||
return desc->channel[i].size;
|
||||
}
|
||||
UNREACHABLE("invalid format description");
|
||||
}
|
||||
|
||||
void vl_csc_get_rgbyuv_matrix(enum pipe_video_vpp_matrix_coefficients coefficients,
|
||||
enum pipe_format in_format, enum pipe_format out_format,
|
||||
enum pipe_video_vpp_color_range in_color_range,
|
||||
enum pipe_video_vpp_color_range out_color_range,
|
||||
vl_csc_matrix *matrix)
|
||||
{
|
||||
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 r_min = 16.0 / 256.0 * scale;
|
||||
const float r_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 r_scale, g_scale, r_bias, g_bias;
|
||||
|
||||
memcpy(matrix, &identity, sizeof(vl_csc_matrix));
|
||||
|
||||
if (in_yuv != out_yuv && coefficients == PIPE_VIDEO_VPP_MCF_RGB)
|
||||
return;
|
||||
|
||||
/* Convert input to full range, chroma to [-0.5,0.5]. */
|
||||
if (in_color_range == PIPE_VIDEO_VPP_CHROMA_COLOR_RANGE_REDUCED) {
|
||||
r_scale = 1.0 / (r_max - r_min);
|
||||
g_scale = in_yuv ? 0.5 / (c_max - c_mid) : r_scale;
|
||||
r_bias = -r_min;
|
||||
g_bias = in_yuv ? -c_mid : r_bias;
|
||||
} else if (in_yuv) {
|
||||
r_scale = 1.0;
|
||||
g_scale = 0.5 / (1.0 - c_mid);
|
||||
r_bias = 0.0;
|
||||
g_bias = -c_mid;
|
||||
} else {
|
||||
r_scale = g_scale = 1.0;
|
||||
r_bias = g_bias = 0.0;
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < 3; i++) {
|
||||
(*matrix)[i][i] = i == 0 ? r_scale : g_scale;
|
||||
(*matrix)[i][3] = (i == 0 ? r_bias : g_bias) * (*matrix)[i][i];
|
||||
}
|
||||
|
||||
if (in_yuv != out_yuv) {
|
||||
float cr, cg, cb;
|
||||
|
||||
switch (coefficients) {
|
||||
case PIPE_VIDEO_VPP_MCF_BT470BG:
|
||||
case PIPE_VIDEO_VPP_MCF_SMPTE170M:
|
||||
cr = 0.299;
|
||||
cb = 0.114;
|
||||
break;
|
||||
case PIPE_VIDEO_VPP_MCF_SMPTE240M:
|
||||
cr = 0.212;
|
||||
cb = 0.087;
|
||||
break;
|
||||
case PIPE_VIDEO_VPP_MCF_BT2020_NCL:
|
||||
cr = 0.2627;
|
||||
cb = 0.0593;
|
||||
break;
|
||||
case PIPE_VIDEO_VPP_MCF_BT709:
|
||||
default:
|
||||
cr = 0.2126;
|
||||
cb = 0.0722;
|
||||
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;
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < 3; i++) {
|
||||
for (unsigned j = 0; j < 3; j++) {
|
||||
(*matrix)[i][j] *= j == 0 ? r_scale : g_scale;
|
||||
(*matrix)[i][3] += (*matrix)[i][j] * (j == 0 ? r_bias : g_bias);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert output to reduced range, chroma to [0.0,1.0]. */
|
||||
if (out_color_range == PIPE_VIDEO_VPP_CHROMA_COLOR_RANGE_REDUCED) {
|
||||
r_scale = (r_max - r_min) / 1.0;
|
||||
g_scale = in_yuv ? r_scale : (c_max - c_mid) / 0.5;
|
||||
r_bias = r_min;
|
||||
g_bias = in_yuv ? r_bias : c_mid;
|
||||
} else if (out_yuv) {
|
||||
r_scale = 1.0;
|
||||
g_scale = (1.0 - c_mid) / 0.5;
|
||||
r_bias = 0.0;
|
||||
g_bias = c_mid;
|
||||
} else {
|
||||
r_scale = g_scale = 1.0;
|
||||
r_bias = g_bias = 0.0;
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < 3; i++) {
|
||||
for (unsigned j = 0; j < 4; j++)
|
||||
(*matrix)[i][j] *= i == 0 ? r_scale : g_scale;
|
||||
(*matrix)[i][3] += i == 0 ? r_bias : g_bias;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@
|
|||
#define vl_csc_h
|
||||
|
||||
#include "util/compiler.h"
|
||||
#include "util/format/u_format.h"
|
||||
#include "pipe/p_video_enums.h"
|
||||
|
||||
typedef float vl_csc_matrix[3][4];
|
||||
|
||||
|
|
@ -57,4 +59,10 @@ void vl_csc_get_matrix(enum VL_CSC_COLOR_STANDARD cs,
|
|||
bool full_range,
|
||||
vl_csc_matrix *matrix);
|
||||
|
||||
void vl_csc_get_rgbyuv_matrix(enum pipe_video_vpp_matrix_coefficients coefficients,
|
||||
enum pipe_format in_format, enum pipe_format out_format,
|
||||
enum pipe_video_vpp_color_range in_color_range,
|
||||
enum pipe_video_vpp_color_range out_color_range,
|
||||
vl_csc_matrix *matrix);
|
||||
|
||||
#endif /* vl_csc_h */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue