libobs: Add Rec. 2020 video_colorspace enum values

One for PQ, and one for HLG. Including transfer function as part of the
color space simplifies logic by avoid invalid combinations.
master
jpark37 2022-03-16 01:01:47 -07:00 committed by Jim
parent ba68eda590
commit 692ca7efce
5 changed files with 87 additions and 23 deletions

View File

@ -39,10 +39,12 @@ Video Handler
YUV color space. Can be one of the following values:
- VIDEO_CS_DEFAULT - Equivalent to VIDEO_CS_709
- VIDEO_CS_601 - 601 color space
- VIDEO_CS_709 - 709 color space
- VIDEO_CS_SRGB - sRGB color space
- VIDEO_CS_DEFAULT - Equivalent to VIDEO_CS_709
- VIDEO_CS_601 - Rec. 601 color space
- VIDEO_CS_709 - Rec. 709 color space
- VIDEO_CS_SRGB - sRGB color space
- VIDEO_CS_2020_PQ - Rec. 2020 color space, PQ transfer
- VIDEO_CS_2020_HLG - Rec. 2020 color space, HLG transfer
---------------------

View File

@ -695,6 +695,24 @@ Functions used by outputs
/* planar 4:4:4 */
VIDEO_FORMAT_I444,
/* more packed uncompressed formats */
VIDEO_FORMAT_BGR3,
/* planar 4:2:2 */
VIDEO_FORMAT_I422,
/* planar 4:2:0 with alpha */
VIDEO_FORMAT_I40A,
/* planar 4:2:2 with alpha */
VIDEO_FORMAT_I42A,
/* planar 4:4:4 with alpha */
VIDEO_FORMAT_YUVA,
/* packed 4:4:4 with alpha */
VIDEO_FORMAT_AYUV,
};
enum video_colorspace {
@ -702,6 +720,8 @@ Functions used by outputs
VIDEO_CS_601,
VIDEO_CS_709,
VIDEO_CS_SRGB,
VIDEO_CS_2020_PQ,
VIDEO_CS_2020_HLG,
};
enum video_range_type {

View File

@ -75,12 +75,14 @@ enum video_colorspace {
VIDEO_CS_601,
VIDEO_CS_709,
VIDEO_CS_SRGB,
VIDEO_CS_2020_PQ,
VIDEO_CS_2020_HLG,
};
enum video_range_type {
VIDEO_RANGE_DEFAULT,
VIDEO_RANGE_PARTIAL,
VIDEO_RANGE_FULL
VIDEO_RANGE_FULL,
};
struct video_data {
@ -176,13 +178,18 @@ static inline const char *get_video_colorspace_name(enum video_colorspace cs)
switch (cs) {
case VIDEO_CS_DEFAULT:
case VIDEO_CS_709:
return "709";
return "Rec. 709";
case VIDEO_CS_SRGB:
return "sRGB";
case VIDEO_CS_601:;
case VIDEO_CS_601:
return "Rec. 601";
case VIDEO_CS_2020_PQ:
return "Rec. 2020 (PQ)";
case VIDEO_CS_2020_HLG:
return "Rec. 2020 (HLG)";
}
return "601";
return "Unknown";
}
static inline enum video_range_type

View File

@ -68,6 +68,23 @@ static struct {
{1.000000f, 0.000000f, 1.581000f, -0.793600f, 1.000000f, -0.188062f,
-0.469967f, 0.330305f, 1.000000f, 1.862906f, 0.000000f, -0.935106f,
0.000000f, 0.000000f, 0.000000f, 1.000000f}}
#endif
},
{VIDEO_CS_2020_PQ,
0.0593f,
0.2627f,
{64, 64, 64},
{940, 960, 960},
{{64, 512, 512}, {0, 512, 512}},
#ifndef COMPUTE_MATRICES
{64.0f / 1023.0f, 64.0f / 1023.0f, 64.0f / 1023.0f},
{940.0f / 1023.0f, 960.0f / 1023.0f, 960.0f / 1023.0f},
{{1.167808f, 0.000000f, 1.683611f, -0.915688f, 1.167808f, -0.187877f,
-0.652337f, 0.347459f, 1.167808f, 2.148072f, 0.000000f, -1.148145f,
0.000000f, 0.000000f, 0.000000f, 1.000000f},
{1.000000f, 0.000000f, 1.476043f, -0.738743f, 1.000000f, -0.164714f,
-0.571912f, 0.368673f, 1.000000f, 1.883241f, 0.000000f, -0.942541f,
0.000000f, 0.000000f, 0.000000f, 1.000000f}}
#endif
},
};
@ -88,8 +105,9 @@ static void log_matrix(float const matrix[16])
}
static void initialize_matrix(float const Kb, float const Kr,
int const range_min[3], int const range_max[3],
int const black_levels[3], float matrix[16])
float bit_range_max, int const range_min[3],
int const range_max[3], int const black_levels[3],
float matrix[16])
{
struct matrix3 color_matrix;
@ -97,15 +115,18 @@ static void initialize_matrix(float const Kb, float const Kr,
int uvals = (range_max[1] - range_min[1]) / 2;
int vvals = (range_max[2] - range_min[2]) / 2;
vec3_set(&color_matrix.x, 255. / yvals, 0., 255. / vvals * (1. - Kr));
vec3_set(&color_matrix.y, 255. / yvals,
255. / uvals * (Kb - 1.) * Kb / (1. - Kb - Kr),
255. / vvals * (Kr - 1.) * Kr / (1. - Kb - Kr));
vec3_set(&color_matrix.z, 255. / yvals, 255. / uvals * (1. - Kb), 0.);
vec3_set(&color_matrix.x, bit_range_max / yvals, 0.,
bit_range_max / vvals * (1.f - Kr));
vec3_set(&color_matrix.y, bit_range_max / yvals,
bit_range_max / uvals * (Kb - 1.f) * Kb / (1.f - Kb - Kr),
bit_range_max / vvals * (Kr - 1.f) * Kr / (1.f - Kb - Kr));
vec3_set(&color_matrix.z, bit_range_max / yvals,
bit_range_max / uvals * (1.f - Kb), 0.);
struct vec3 offsets, multiplied;
vec3_set(&offsets, -black_levels[0] / 255., -black_levels[1] / 255.,
-black_levels[2] / 255.);
vec3_set(&offsets, -black_levels[0] / bit_range_max,
-black_levels[1] / bit_range_max,
-black_levels[2] / bit_range_max);
vec3_rotate(&multiplied, &offsets, &color_matrix);
matrix[0] = color_matrix.x.x;
@ -131,16 +152,22 @@ static void initialize_matrix(float const Kb, float const Kr,
static void initialize_matrices()
{
static int range_min[] = {0, 0, 0};
static int range_max[] = {255, 255, 255};
static const int range_min[] = {0, 0, 0};
static const int range_max_8bit[] = {255, 255, 255};
static const int range_max_10bit[] = {1023, 1023, 1023};
for (size_t i = 0; i < NUM_FORMATS; i++) {
initialize_matrix(format_info[i].Kb, format_info[i].Kr,
const int *range_max =
(format_info[i].color_space == VIDEO_CS_2020_PQ)
? range_max_10bit
: range_max_8bit;
float f_r_max = (float)range_max[0];
initialize_matrix(format_info[i].Kb, format_info[i].Kr, f_r_max,
range_min, range_max,
format_info[i].black_levels[1],
format_info[i].matrix[1]);
initialize_matrix(format_info[i].Kb, format_info[i].Kr,
initialize_matrix(format_info[i].Kb, format_info[i].Kr, f_r_max,
format_info[i].range_min,
format_info[i].range_max,
format_info[i].black_levels[0],
@ -148,9 +175,9 @@ static void initialize_matrices()
for (int j = 0; j < 3; j++) {
format_info[i].float_range_min[j] =
format_info[i].range_min[j] / 255.;
format_info[i].range_min[j] / f_r_max;
format_info[i].float_range_max[j] =
format_info[i].range_max[j] / 255.;
format_info[i].range_max[j] / f_r_max;
}
}
}
@ -173,6 +200,8 @@ bool video_format_get_parameters(enum video_colorspace color_space,
#endif
if ((color_space == VIDEO_CS_DEFAULT) || (color_space == VIDEO_CS_SRGB))
color_space = VIDEO_CS_709;
else if (color_space == VIDEO_CS_2020_HLG)
color_space = VIDEO_CS_2020_PQ;
for (size_t i = 0; i < NUM_FORMATS; i++) {
if (format_info[i].color_space != color_space)

View File

@ -270,6 +270,12 @@ static bool obs_init_textures(struct obs_video_info *ovi)
enum gs_color_format format = GS_RGBA;
enum gs_color_space space = GS_CS_SRGB;
switch (ovi->colorspace) {
case VIDEO_CS_2020_PQ:
case VIDEO_CS_2020_HLG:
format = GS_RGBA16F;
space = GS_CS_709_EXTENDED;
}
video->render_texture = gs_texture_create(ovi->base_width,
ovi->base_height, format, 1,