feat(video): use unified color conversion matrix generator (#4387)

This commit is contained in:
ns6089 2025-11-05 16:49:56 +03:00 committed by GitHub
commit cdb7e2b813
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 54 additions and 92 deletions

View file

@ -120,66 +120,9 @@ namespace video {
return avcodec_colorspace;
}
const color_t *color_vectors_from_colorspace(const sunshine_colorspace_t &colorspace) {
return color_vectors_from_colorspace(colorspace.colorspace, colorspace.full_range);
}
const color_t *color_vectors_from_colorspace(colorspace_e colorspace, bool full_range) {
using float2 = float[2];
auto make_color_matrix = [](float Cr, float Cb, const float2 &range_Y, const float2 &range_UV) -> color_t {
float Cg = 1.0f - Cr - Cb;
float Cr_i = 1.0f - Cr;
float Cb_i = 1.0f - Cb;
float shift_y = range_Y[0] / 255.0f;
float shift_uv = range_UV[0] / 255.0f;
float scale_y = (range_Y[1] - range_Y[0]) / 255.0f;
float scale_uv = (range_UV[1] - range_UV[0]) / 255.0f;
return {
{Cr, Cg, Cb, 0.0f},
{-(Cr * 0.5f / Cb_i), -(Cg * 0.5f / Cb_i), 0.5f, 0.5f},
{0.5f, -(Cg * 0.5f / Cr_i), -(Cb * 0.5f / Cr_i), 0.5f},
{scale_y, shift_y},
{scale_uv, shift_uv},
};
};
static const color_t colors[] {
make_color_matrix(0.299f, 0.114f, {16.0f, 235.0f}, {16.0f, 240.0f}), // BT601 MPEG
make_color_matrix(0.299f, 0.114f, {0.0f, 255.0f}, {0.0f, 255.0f}), // BT601 JPEG
make_color_matrix(0.2126f, 0.0722f, {16.0f, 235.0f}, {16.0f, 240.0f}), // BT709 MPEG
make_color_matrix(0.2126f, 0.0722f, {0.0f, 255.0f}, {0.0f, 255.0f}), // BT709 JPEG
make_color_matrix(0.2627f, 0.0593f, {16.0f, 235.0f}, {16.0f, 240.0f}), // BT2020 MPEG
make_color_matrix(0.2627f, 0.0593f, {0.0f, 255.0f}, {0.0f, 255.0f}), // BT2020 JPEG
};
const color_t *result = nullptr;
switch (colorspace) {
case colorspace_e::rec601:
default:
result = &colors[0];
break;
case colorspace_e::rec709:
result = &colors[2];
break;
case colorspace_e::bt2020:
case colorspace_e::bt2020sdr:
result = &colors[4];
break;
};
if (full_range) {
result++;
}
return result;
}
const color_t *new_color_vectors_from_colorspace(const sunshine_colorspace_t &colorspace) {
constexpr auto generate_color_vectors = [](const sunshine_colorspace_t &colorspace) -> color_t {
const color_t *color_vectors_from_colorspace(const sunshine_colorspace_t &colorspace, bool unorm_output) {
constexpr auto generate_color_vectors = [](const sunshine_colorspace_t &colorspace, bool unorm_output) -> color_t {
// "Table 4 Interpretation of matrix coefficients (MatrixCoefficients) value" section of ITU-T H.273
double Kr, Kb;
switch (colorspace.colorspace) {
case colorspace_e::rec601:
@ -202,7 +145,7 @@ namespace video {
double y_mult, y_add;
double uv_mult, uv_add;
// "Matrix coefficients" section of ITU-T H.273
// "8.3 Matrix coefficients" section of ITU-T H.273
if (colorspace.full_range) {
y_mult = (1 << colorspace.bit_depth) - 1;
y_add = 0;
@ -215,9 +158,17 @@ namespace video {
uv_add = (1 << (colorspace.bit_depth - 8)) * 128;
}
// For rounding
y_add += 0.5;
uv_add += 0.5;
if (unorm_output) {
const double unorm_range = (1 << colorspace.bit_depth) - 1;
y_mult /= unorm_range;
y_add /= unorm_range;
uv_mult /= unorm_range;
uv_add /= unorm_range;
} else {
// For rounding
y_add += 0.5f;
uv_add += 0.5f;
}
color_t color_vectors;
@ -246,18 +197,31 @@ namespace video {
};
static constexpr color_t colors[] = {
generate_color_vectors({colorspace_e::rec601, false, 8}),
generate_color_vectors({colorspace_e::rec601, true, 8}),
generate_color_vectors({colorspace_e::rec601, false, 10}),
generate_color_vectors({colorspace_e::rec601, true, 10}),
generate_color_vectors({colorspace_e::rec709, false, 8}),
generate_color_vectors({colorspace_e::rec709, true, 8}),
generate_color_vectors({colorspace_e::rec709, false, 10}),
generate_color_vectors({colorspace_e::rec709, true, 10}),
generate_color_vectors({colorspace_e::bt2020, false, 8}),
generate_color_vectors({colorspace_e::bt2020, true, 8}),
generate_color_vectors({colorspace_e::bt2020, false, 10}),
generate_color_vectors({colorspace_e::bt2020, true, 10}),
generate_color_vectors({colorspace_e::rec601, false, 8}, false),
generate_color_vectors({colorspace_e::rec601, true, 8}, false),
generate_color_vectors({colorspace_e::rec601, false, 10}, false),
generate_color_vectors({colorspace_e::rec601, true, 10}, false),
generate_color_vectors({colorspace_e::rec709, false, 8}, false),
generate_color_vectors({colorspace_e::rec709, true, 8}, false),
generate_color_vectors({colorspace_e::rec709, false, 10}, false),
generate_color_vectors({colorspace_e::rec709, true, 10}, false),
generate_color_vectors({colorspace_e::bt2020, false, 8}, false),
generate_color_vectors({colorspace_e::bt2020, true, 8}, false),
generate_color_vectors({colorspace_e::bt2020, false, 10}, false),
generate_color_vectors({colorspace_e::bt2020, true, 10}, false),
generate_color_vectors({colorspace_e::rec601, false, 8}, true),
generate_color_vectors({colorspace_e::rec601, true, 8}, true),
generate_color_vectors({colorspace_e::rec601, false, 10}, true),
generate_color_vectors({colorspace_e::rec601, true, 10}, true),
generate_color_vectors({colorspace_e::rec709, false, 8}, true),
generate_color_vectors({colorspace_e::rec709, true, 8}, true),
generate_color_vectors({colorspace_e::rec709, false, 10}, true),
generate_color_vectors({colorspace_e::rec709, true, 10}, true),
generate_color_vectors({colorspace_e::bt2020, false, 8}, true),
generate_color_vectors({colorspace_e::bt2020, true, 8}, true),
generate_color_vectors({colorspace_e::bt2020, false, 10}, true),
generate_color_vectors({colorspace_e::bt2020, true, 10}, true),
};
const color_t *result = nullptr;
@ -282,6 +246,9 @@ namespace video {
if (colorspace.full_range) {
result += 1;
}
if (unorm_output) {
result += 12;
}
return result;
}