Skip to content

Commit 69fd1f2

Browse files
committed
feat(video): use unified color conversion matrix generator
1 parent eb72930 commit 69fd1f2

5 files changed

Lines changed: 54 additions & 92 deletions

File tree

src/platform/linux/cuda.cu

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,7 @@ namespace cuda {
330330
}
331331

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

src/platform/linux/graphics.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -698,7 +698,7 @@ namespace egl {
698698
}
699699

700700
void sws_t::apply_colorspace(const video::sunshine_colorspace_t &colorspace) {
701-
auto color_p = video::color_vectors_from_colorspace(colorspace);
701+
auto color_p = video::color_vectors_from_colorspace(colorspace, true);
702702

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

814-
auto color_p = video::color_vectors_from_colorspace(video::colorspace_e::rec601, false);
814+
auto color_p = video::color_vectors_from_colorspace({colorspace_e::rec601, false, 8}, true);
815815
std::pair<const char *, std::string_view> members[] {
816816
std::make_pair("color_vec_y", util::view(color_p->color_vec_y)),
817817
std::make_pair("color_vec_u", util::view(color_p->color_vec_u)),

src/platform/windows/display_vram.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -457,12 +457,12 @@ namespace platf::dxgi {
457457
}
458458

459459
void apply_colorspace(const ::video::sunshine_colorspace_t &colorspace) {
460-
auto color_vectors = ::video::color_vectors_from_colorspace(colorspace);
460+
auto color_vectors = ::video::color_vectors_from_colorspace(colorspace, true);
461461

462462
if (format == DXGI_FORMAT_AYUV ||
463463
format == DXGI_FORMAT_R16_UINT ||
464464
format == DXGI_FORMAT_Y410) {
465-
color_vectors = ::video::new_color_vectors_from_colorspace(colorspace);
465+
color_vectors = ::video::color_vectors_from_colorspace(colorspace, false);
466466
}
467467

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

778-
auto default_color_vectors = ::video::color_vectors_from_colorspace(::video::colorspace_e::rec601, false);
778+
auto default_color_vectors = ::video::color_vectors_from_colorspace({::video::colorspace_e::rec601, false, 8}, true);
779779
if (!default_color_vectors) {
780780
BOOST_LOG(error) << "Missing color vectors for Rec. 601"sv;
781781
return -1;

src/video_colorspace.cpp

Lines changed: 43 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -120,66 +120,9 @@ namespace video {
120120
return avcodec_colorspace;
121121
}
122122

123-
const color_t *color_vectors_from_colorspace(const sunshine_colorspace_t &colorspace) {
124-
return color_vectors_from_colorspace(colorspace.colorspace, colorspace.full_range);
125-
}
126-
127-
const color_t *color_vectors_from_colorspace(colorspace_e colorspace, bool full_range) {
128-
using float2 = float[2];
129-
auto make_color_matrix = [](float Cr, float Cb, const float2 &range_Y, const float2 &range_UV) -> color_t {
130-
float Cg = 1.0f - Cr - Cb;
131-
132-
float Cr_i = 1.0f - Cr;
133-
float Cb_i = 1.0f - Cb;
134-
135-
float shift_y = range_Y[0] / 255.0f;
136-
float shift_uv = range_UV[0] / 255.0f;
137-
138-
float scale_y = (range_Y[1] - range_Y[0]) / 255.0f;
139-
float scale_uv = (range_UV[1] - range_UV[0]) / 255.0f;
140-
return {
141-
{Cr, Cg, Cb, 0.0f},
142-
{-(Cr * 0.5f / Cb_i), -(Cg * 0.5f / Cb_i), 0.5f, 0.5f},
143-
{0.5f, -(Cg * 0.5f / Cr_i), -(Cb * 0.5f / Cr_i), 0.5f},
144-
{scale_y, shift_y},
145-
{scale_uv, shift_uv},
146-
};
147-
};
148-
149-
static const color_t colors[] {
150-
make_color_matrix(0.299f, 0.114f, {16.0f, 235.0f}, {16.0f, 240.0f}), // BT601 MPEG
151-
make_color_matrix(0.299f, 0.114f, {0.0f, 255.0f}, {0.0f, 255.0f}), // BT601 JPEG
152-
make_color_matrix(0.2126f, 0.0722f, {16.0f, 235.0f}, {16.0f, 240.0f}), // BT709 MPEG
153-
make_color_matrix(0.2126f, 0.0722f, {0.0f, 255.0f}, {0.0f, 255.0f}), // BT709 JPEG
154-
make_color_matrix(0.2627f, 0.0593f, {16.0f, 235.0f}, {16.0f, 240.0f}), // BT2020 MPEG
155-
make_color_matrix(0.2627f, 0.0593f, {0.0f, 255.0f}, {0.0f, 255.0f}), // BT2020 JPEG
156-
};
157-
158-
const color_t *result = nullptr;
159-
160-
switch (colorspace) {
161-
case colorspace_e::rec601:
162-
default:
163-
result = &colors[0];
164-
break;
165-
case colorspace_e::rec709:
166-
result = &colors[2];
167-
break;
168-
case colorspace_e::bt2020:
169-
case colorspace_e::bt2020sdr:
170-
result = &colors[4];
171-
break;
172-
};
173-
174-
if (full_range) {
175-
result++;
176-
}
177-
178-
return result;
179-
}
180-
181-
const color_t *new_color_vectors_from_colorspace(const sunshine_colorspace_t &colorspace) {
182-
constexpr auto generate_color_vectors = [](const sunshine_colorspace_t &colorspace) -> color_t {
123+
const color_t *color_vectors_from_colorspace(const sunshine_colorspace_t &colorspace, bool unorm_output) {
124+
constexpr auto generate_color_vectors = [](const sunshine_colorspace_t &colorspace, bool unorm_output) -> color_t {
125+
// "Table 4 – Interpretation of matrix coefficients (MatrixCoefficients) value" section of ITU-T H.273
183126
double Kr, Kb;
184127
switch (colorspace.colorspace) {
185128
case colorspace_e::rec601:
@@ -202,7 +145,7 @@ namespace video {
202145
double y_mult, y_add;
203146
double uv_mult, uv_add;
204147

205-
// "Matrix coefficients" section of ITU-T H.273
148+
// "8.3 Matrix coefficients" section of ITU-T H.273
206149
if (colorspace.full_range) {
207150
y_mult = (1 << colorspace.bit_depth) - 1;
208151
y_add = 0;
@@ -215,9 +158,17 @@ namespace video {
215158
uv_add = (1 << (colorspace.bit_depth - 8)) * 128;
216159
}
217160

218-
// For rounding
219-
y_add += 0.5;
220-
uv_add += 0.5;
161+
if (unorm_output) {
162+
const double unorm_range = (1 << colorspace.bit_depth) - 1;
163+
y_mult /= unorm_range;
164+
y_add /= unorm_range;
165+
uv_mult /= unorm_range;
166+
uv_add /= unorm_range;
167+
} else {
168+
// For rounding
169+
y_add += 0.5f;
170+
uv_add += 0.5f;
171+
}
221172

222173
color_t color_vectors;
223174

@@ -246,18 +197,31 @@ namespace video {
246197
};
247198

248199
static constexpr color_t colors[] = {
249-
generate_color_vectors({colorspace_e::rec601, false, 8}),
250-
generate_color_vectors({colorspace_e::rec601, true, 8}),
251-
generate_color_vectors({colorspace_e::rec601, false, 10}),
252-
generate_color_vectors({colorspace_e::rec601, true, 10}),
253-
generate_color_vectors({colorspace_e::rec709, false, 8}),
254-
generate_color_vectors({colorspace_e::rec709, true, 8}),
255-
generate_color_vectors({colorspace_e::rec709, false, 10}),
256-
generate_color_vectors({colorspace_e::rec709, true, 10}),
257-
generate_color_vectors({colorspace_e::bt2020, false, 8}),
258-
generate_color_vectors({colorspace_e::bt2020, true, 8}),
259-
generate_color_vectors({colorspace_e::bt2020, false, 10}),
260-
generate_color_vectors({colorspace_e::bt2020, true, 10}),
200+
generate_color_vectors({colorspace_e::rec601, false, 8}, false),
201+
generate_color_vectors({colorspace_e::rec601, true, 8}, false),
202+
generate_color_vectors({colorspace_e::rec601, false, 10}, false),
203+
generate_color_vectors({colorspace_e::rec601, true, 10}, false),
204+
generate_color_vectors({colorspace_e::rec709, false, 8}, false),
205+
generate_color_vectors({colorspace_e::rec709, true, 8}, false),
206+
generate_color_vectors({colorspace_e::rec709, false, 10}, false),
207+
generate_color_vectors({colorspace_e::rec709, true, 10}, false),
208+
generate_color_vectors({colorspace_e::bt2020, false, 8}, false),
209+
generate_color_vectors({colorspace_e::bt2020, true, 8}, false),
210+
generate_color_vectors({colorspace_e::bt2020, false, 10}, false),
211+
generate_color_vectors({colorspace_e::bt2020, true, 10}, false),
212+
213+
generate_color_vectors({colorspace_e::rec601, false, 8}, true),
214+
generate_color_vectors({colorspace_e::rec601, true, 8}, true),
215+
generate_color_vectors({colorspace_e::rec601, false, 10}, true),
216+
generate_color_vectors({colorspace_e::rec601, true, 10}, true),
217+
generate_color_vectors({colorspace_e::rec709, false, 8}, true),
218+
generate_color_vectors({colorspace_e::rec709, true, 8}, true),
219+
generate_color_vectors({colorspace_e::rec709, false, 10}, true),
220+
generate_color_vectors({colorspace_e::rec709, true, 10}, true),
221+
generate_color_vectors({colorspace_e::bt2020, false, 8}, true),
222+
generate_color_vectors({colorspace_e::bt2020, true, 8}, true),
223+
generate_color_vectors({colorspace_e::bt2020, false, 10}, true),
224+
generate_color_vectors({colorspace_e::bt2020, true, 10}, true),
261225
};
262226

263227
const color_t *result = nullptr;
@@ -282,6 +246,9 @@ namespace video {
282246
if (colorspace.full_range) {
283247
result += 1;
284248
}
249+
if (unorm_output) {
250+
result += 12;
251+
}
285252

286253
return result;
287254
}

src/video_colorspace.h

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,20 +48,15 @@ namespace video {
4848
float range_uv[2];
4949
};
5050

51-
const color_t *color_vectors_from_colorspace(const sunshine_colorspace_t &colorspace);
52-
53-
const color_t *color_vectors_from_colorspace(colorspace_e colorspace, bool full_range);
54-
5551
/**
56-
* @brief New version of `color_vectors_from_colorspace()` function that better adheres to the standards.
57-
* Returned vectors are used to perform RGB->YUV conversion.
58-
* Unlike its predecessor, color vectors will produce output in `UINT` range, not `UNORM` range.
59-
* Input is still in `UNORM` range. Returned vectors won't modify color primaries and color
60-
* transfer function.
52+
* @brief Get static RGB->YUV color conversion matrix.
53+
* Expects RGB input in UNORM (0.0 to 1.0) range.
54+
* Returned vectors don't perform gamut matching.
6155
* @param colorspace Targeted YUV colorspace.
56+
* @param unorm_output Whether the output should be in UNORM or UINT range.
6257
* @return `const color_t*` that contains RGB->YUV transformation vectors.
6358
* Components `range_y` and `range_uv` are there for backwards compatibility
6459
* and can be ignored in the computation.
6560
*/
66-
const color_t *new_color_vectors_from_colorspace(const sunshine_colorspace_t &colorspace);
61+
const color_t *color_vectors_from_colorspace(const sunshine_colorspace_t &colorspace, bool unorm_output);
6762
} // namespace video

0 commit comments

Comments
 (0)