libobs: Add support for reading I420 PQ

Not normally a valid combination, but Xbox writes 8-bit HDR videos.
master
jpark37 2022-05-08 13:23:08 -07:00 committed by Jim
parent ed835810b4
commit 2a0d8d1c9c
4 changed files with 64 additions and 30 deletions

View File

@ -477,6 +477,19 @@ float3 PSPlanar420_Reverse(VertTexPos frag_in) : TARGET
return rgb;
}
float4 PSPlanar420_PQ_Reverse(VertTexPos frag_in) : TARGET
{
float y = image.Load(int3(frag_in.pos.xy, 0)).x;
int3 xy0_chroma = int3(frag_in.uv, 0);
float cb = image1.Load(xy0_chroma).x;
float cr = image2.Load(xy0_chroma).x;
float3 yuv = float3(y, cb, cr);
float3 pq = YUV_to_RGB(yuv);
float3 hdr2020 = st2084_to_linear(pq) * maximum_over_sdr_white_nits;
float3 rgb = rec2020_to_rec709(hdr2020);
return float4(rgb, 1.);
}
float4 PSPlanar420A_Reverse(VertTexPos frag_in) : TARGET
{
int3 xy0_luma = int3(frag_in.pos.xy, 0);
@ -511,7 +524,7 @@ float4 PSPlanar422_10LE_Reverse(FragPosWide frag_in) : TARGET
yuv *= 65535. / 1023.;
float3 rgb = YUV_to_RGB(yuv);
rgb = srgb_nonlinear_to_linear(rgb);
return float4(rgb, 1.0);
return float4(rgb, 1.);
}
float4 PSPlanar422A_Reverse(FragPosWide frag_in) : TARGET
@ -548,7 +561,7 @@ float4 PSPlanar444_12LE_Reverse(FragPos frag_in) : TARGET
yuv *= 65535. / 4095.;
float3 rgb = YUV_to_RGB(yuv);
rgb = srgb_nonlinear_to_linear(rgb);
return float4(rgb, 1.0);
return float4(rgb, 1.);
}
float4 PSPlanar444A_Reverse(FragPos frag_in) : TARGET
@ -603,7 +616,7 @@ float4 PSI010_SRGB_Reverse(VertTexPos frag_in) : TARGET
float3 yuv = float3(y, cb, cr);
float3 rgb = YUV_to_RGB(yuv);
rgb = srgb_nonlinear_to_linear(rgb);
return float4(rgb, 1.0);
return float4(rgb, 1.);
}
float4 PSI010_PQ_2020_709_Reverse(VertTexPos frag_in) : TARGET
@ -617,7 +630,7 @@ float4 PSI010_PQ_2020_709_Reverse(VertTexPos frag_in) : TARGET
float3 pq = YUV_to_RGB(yuv);
float3 hdr2020 = st2084_to_linear(pq) * maximum_over_sdr_white_nits;
float3 rgb = rec2020_to_rec709(hdr2020);
return float4(rgb, 1.0);
return float4(rgb, 1.);
}
float4 PSI010_HLG_2020_709_Reverse(VertTexPos frag_in) : TARGET
@ -631,7 +644,7 @@ float4 PSI010_HLG_2020_709_Reverse(VertTexPos frag_in) : TARGET
float3 hlg = YUV_to_RGB(yuv);
float3 hdr2020 = hlg_to_linear(hlg, hlg_exponent) * maximum_over_sdr_white_nits;
float3 rgb = rec2020_to_rec709(hdr2020);
return float4(rgb, 1.0);
return float4(rgb, 1.);
}
float4 PSP010_SRGB_Reverse(VertTexPos frag_in) : TARGET
@ -641,7 +654,7 @@ float4 PSP010_SRGB_Reverse(VertTexPos frag_in) : TARGET
float3 yuv = float3(y, cbcr);
float3 rgb = YUV_to_RGB(yuv);
rgb = srgb_nonlinear_to_linear(rgb);
return float4(rgb, 1.0);
return float4(rgb, 1.);
}
float4 PSP010_PQ_2020_709_Reverse(VertTexPos frag_in) : TARGET
@ -652,7 +665,7 @@ float4 PSP010_PQ_2020_709_Reverse(VertTexPos frag_in) : TARGET
float3 pq = YUV_to_RGB(yuv);
float3 hdr2020 = st2084_to_linear(pq) * maximum_over_sdr_white_nits;
float3 rgb = rec2020_to_rec709(hdr2020);
return float4(rgb, 1.0);
return float4(rgb, 1.);
}
float4 PSP010_HLG_2020_709_Reverse(VertTexPos frag_in) : TARGET
@ -663,7 +676,7 @@ float4 PSP010_HLG_2020_709_Reverse(VertTexPos frag_in) : TARGET
float3 hlg = YUV_to_RGB(yuv);
float3 hdr2020 = hlg_to_linear(hlg, hlg_exponent) * maximum_over_sdr_white_nits;
float3 rgb = rec2020_to_rec709(hdr2020);
return float4(rgb, 1.0);
return float4(rgb, 1.);
}
float3 PSY800_Limited(FragPos frag_in) : TARGET
@ -943,6 +956,15 @@ technique I420_Reverse
}
}
technique I420_PQ_Reverse
{
pass
{
vertex_shader = VSTexPosHalfHalf_Reverse(id);
pixel_shader = PSPlanar420_PQ_Reverse(frag_in);
}
}
technique I40A_Reverse
{
pass

View File

@ -879,25 +879,31 @@ static inline bool frame_out_of_bounds(const obs_source_t *source, uint64_t ts)
}
static inline enum gs_color_format
convert_video_format(enum video_format format)
convert_video_format(enum video_format format, enum video_trc trc)
{
switch (format) {
case VIDEO_FORMAT_RGBA:
return GS_RGBA;
case VIDEO_FORMAT_BGRA:
case VIDEO_FORMAT_I40A:
case VIDEO_FORMAT_I42A:
case VIDEO_FORMAT_YUVA:
case VIDEO_FORMAT_AYUV:
return GS_BGRA;
case VIDEO_FORMAT_I010:
case VIDEO_FORMAT_P010:
case VIDEO_FORMAT_I210:
case VIDEO_FORMAT_I412:
case VIDEO_FORMAT_YA2L:
switch (trc) {
case VIDEO_TRC_PQ:
case VIDEO_TRC_HLG:
return GS_RGBA16F;
default:
return GS_BGRX;
switch (format) {
case VIDEO_FORMAT_RGBA:
return GS_RGBA;
case VIDEO_FORMAT_BGRA:
case VIDEO_FORMAT_I40A:
case VIDEO_FORMAT_I42A:
case VIDEO_FORMAT_YUVA:
case VIDEO_FORMAT_AYUV:
return GS_BGRA;
case VIDEO_FORMAT_I010:
case VIDEO_FORMAT_P010:
case VIDEO_FORMAT_I210:
case VIDEO_FORMAT_I412:
case VIDEO_FORMAT_YA2L:
return GS_RGBA16F;
default:
return GS_BGRX;
}
}
}
@ -905,7 +911,7 @@ static inline enum gs_color_space convert_video_space(enum video_format format,
enum video_trc trc)
{
enum gs_color_space space = GS_CS_SRGB;
if (convert_video_format(format) == GS_RGBA16F) {
if (convert_video_format(format, trc) == GS_RGBA16F) {
space = (trc == VIDEO_TRC_SRGB) ? GS_CS_SRGB_16F
: GS_CS_709_EXTENDED;
}

View File

@ -234,7 +234,7 @@ void deinterlace_process_last_frame(obs_source_t *s, uint64_t sys_time)
void set_deinterlace_texture_size(obs_source_t *source)
{
const enum gs_color_format format =
convert_video_format(source->async_format);
convert_video_format(source->async_format, source->async_trc);
if (source->async_gpu_conversion) {
source->async_prev_texrender =

View File

@ -1546,6 +1546,7 @@ enum convert_type {
CONVERT_NONE,
CONVERT_NV12,
CONVERT_420,
CONVERT_420_PQ,
CONVERT_420_A,
CONVERT_422,
CONVERT_422P10LE,
@ -1572,7 +1573,7 @@ static inline enum convert_type get_convert_type(enum video_format format,
{
switch (format) {
case VIDEO_FORMAT_I420:
return CONVERT_420;
return (trc == VIDEO_TRC_PQ) ? CONVERT_420_PQ : CONVERT_420;
case VIDEO_FORMAT_NV12:
return CONVERT_NV12;
case VIDEO_FORMAT_I444:
@ -1874,7 +1875,8 @@ static inline bool set_rgb_limited_sizes(struct obs_source *source,
{
source->async_convert_width[0] = frame->width;
source->async_convert_height[0] = frame->height;
source->async_texture_formats[0] = convert_video_format(frame->format);
source->async_texture_formats[0] =
convert_video_format(frame->format, frame->trc);
source->async_channel_count = 1;
return true;
}
@ -1935,6 +1937,7 @@ static inline bool init_gpu_conversion(struct obs_source *source,
return set_packed422_sizes(source, frame);
case CONVERT_420:
case CONVERT_420_PQ:
return set_planar420_sizes(source, frame);
case CONVERT_422:
@ -2026,7 +2029,8 @@ bool set_async_texture_size(struct obs_source *source,
source->async_texrender = NULL;
source->async_prev_texrender = NULL;
const enum gs_color_format format = convert_video_format(frame->format);
const enum gs_color_format format =
convert_video_format(frame->format, frame->trc);
const bool async_gpu_conversion = (cur != CONVERT_NONE) &&
init_gpu_conversion(source, frame);
source->async_gpu_conversion = async_gpu_conversion;
@ -2064,6 +2068,7 @@ static void upload_raw_frame(gs_texture_t *tex[MAX_AV_PLANES],
case CONVERT_RGB_LIMITED:
case CONVERT_BGR3:
case CONVERT_420:
case CONVERT_420_PQ:
case CONVERT_422:
case CONVERT_422P10LE:
case CONVERT_NV12:
@ -2107,7 +2112,8 @@ static const char *select_conversion_technique(enum video_format format,
return "YVYU_Reverse";
case VIDEO_FORMAT_I420:
return "I420_Reverse";
return (trc == VIDEO_TRC_PQ) ? "I420_PQ_Reverse"
: "I420_Reverse";
case VIDEO_FORMAT_NV12:
return "NV12_Reverse";