Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/platform/linux/cuda.cu
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ namespace cuda {
}

void sws_t::apply_colorspace(const video::sunshine_colorspace_t &colorspace) {
auto color_p = video::color_vectors_from_colorspace(colorspace);
auto color_p = video::color_vectors_from_colorspace(colorspace, true);
CU_CHECK_IGNORE(cudaMemcpy(color_matrix.get(), color_p, sizeof(video::color_t), cudaMemcpyHostToDevice), "Couldn't copy color matrix to cuda");
}

Expand Down
4 changes: 2 additions & 2 deletions src/platform/linux/graphics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -698,7 +698,7 @@ namespace egl {
}

void sws_t::apply_colorspace(const video::sunshine_colorspace_t &colorspace) {
auto color_p = video::color_vectors_from_colorspace(colorspace);
auto color_p = video::color_vectors_from_colorspace(colorspace, true);

std::string_view members[] {
util::view(color_p->color_vec_y),
Expand Down Expand Up @@ -811,7 +811,7 @@ namespace egl {
gl::ctx.UseProgram(sws.program[1].handle());
gl::ctx.Uniform1fv(loc_width_i, 1, &width_i);

auto color_p = video::color_vectors_from_colorspace(video::colorspace_e::rec601, false);
auto color_p = video::color_vectors_from_colorspace({video::colorspace_e::rec601, false, 8}, true);
std::pair<const char *, std::string_view> members[] {
std::make_pair("color_vec_y", util::view(color_p->color_vec_y)),
std::make_pair("color_vec_u", util::view(color_p->color_vec_u)),
Expand Down
6 changes: 3 additions & 3 deletions src/platform/windows/display_vram.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -457,12 +457,12 @@ namespace platf::dxgi {
}

void apply_colorspace(const ::video::sunshine_colorspace_t &colorspace) {
auto color_vectors = ::video::color_vectors_from_colorspace(colorspace);
auto color_vectors = ::video::color_vectors_from_colorspace(colorspace, true);

if (format == DXGI_FORMAT_AYUV ||
format == DXGI_FORMAT_R16_UINT ||
format == DXGI_FORMAT_Y410) {
color_vectors = ::video::new_color_vectors_from_colorspace(colorspace);
color_vectors = ::video::color_vectors_from_colorspace(colorspace, false);
}

if (!color_vectors) {
Expand Down Expand Up @@ -775,7 +775,7 @@ namespace platf::dxgi {
BOOST_LOG(warning) << "Failed to increase encoding GPU thread priority. Please run application as administrator for optimal performance.";
}

auto default_color_vectors = ::video::color_vectors_from_colorspace(::video::colorspace_e::rec601, false);
auto default_color_vectors = ::video::color_vectors_from_colorspace({::video::colorspace_e::rec601, false, 8}, true);
if (!default_color_vectors) {
BOOST_LOG(error) << "Missing color vectors for Rec. 601"sv;
return -1;
Expand Down
119 changes: 43 additions & 76 deletions src/video_colorspace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -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;
Expand All @@ -282,6 +246,9 @@ namespace video {
if (colorspace.full_range) {
result += 1;
}
if (unorm_output) {
result += 12;
}

return result;
}
Expand Down
15 changes: 5 additions & 10 deletions src/video_colorspace.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,20 +48,15 @@ namespace video {
float range_uv[2];
};

const color_t *color_vectors_from_colorspace(const sunshine_colorspace_t &colorspace);

const color_t *color_vectors_from_colorspace(colorspace_e colorspace, bool full_range);

/**
* @brief New version of `color_vectors_from_colorspace()` function that better adheres to the standards.
* Returned vectors are used to perform RGB->YUV conversion.
* Unlike its predecessor, color vectors will produce output in `UINT` range, not `UNORM` range.
* Input is still in `UNORM` range. Returned vectors won't modify color primaries and color
* transfer function.
* @brief Get static RGB->YUV color conversion matrix.
* This matrix expects RGB input in UNORM (0.0 to 1.0) range and doesn't perform any
* gamut mapping or gamma correction.
* @param colorspace Targeted YUV colorspace.
* @param unorm_output Whether the matrix should produce output in UNORM or UINT range.
* @return `const color_t*` that contains RGB->YUV transformation vectors.
* Components `range_y` and `range_uv` are there for backwards compatibility
* and can be ignored in the computation.
*/
const color_t *new_color_vectors_from_colorspace(const sunshine_colorspace_t &colorspace);
const color_t *color_vectors_from_colorspace(const sunshine_colorspace_t &colorspace, bool unorm_output);
} // namespace video
Loading