From bb02620169ba2eef6903f56a18cd8ce26dd92500 Mon Sep 17 00:00:00 2001 From: jpark37 Date: Fri, 16 Sep 2022 20:27:41 -0700 Subject: [PATCH] libobs: Add support for reading NV12/YUY2 PQ/HLG 8-bit HDR shouldn't exist, but OBS looks broken, so just support it. --- libobs/data/format_conversion.effect | 86 ++++++++++++++++++++++++++++ libobs/obs-source.c | 18 +++++- 2 files changed, 102 insertions(+), 2 deletions(-) diff --git a/libobs/data/format_conversion.effect b/libobs/data/format_conversion.effect index 0d8a2f5d1..461c5913f 100644 --- a/libobs/data/format_conversion.effect +++ b/libobs/data/format_conversion.effect @@ -449,6 +449,34 @@ float3 PSYUY2_Reverse(FragTex frag_in) : TARGET return rgb; } +float4 PSYUY2_PQ_Reverse(FragTex frag_in) : TARGET +{ + float4 y2uv = image.Load(int3(frag_in.uv.xy, 0)); + float2 y01 = y2uv.zx; + float2 cbcr = y2uv.yw; + float leftover = frac(frag_in.uv.x); + float y = (leftover < 0.5) ? y01.x : y01.y; + float3 yuv = float3(y, cbcr); + float3 pq = YUV_to_RGB(yuv); + float3 hdr2020 = st2084_to_linear_eetf(pq, hdr_lw, hdr_lmax) * maximum_over_sdr_white_nits; + float3 rgb = rec2020_to_rec709(hdr2020); + return float4(rgb, 1.); +} + +float4 PSYUY2_HLG_Reverse(FragTex frag_in) : TARGET +{ + float4 y2uv = image.Load(int3(frag_in.uv.xy, 0)); + float2 y01 = y2uv.zx; + float2 cbcr = y2uv.yw; + float leftover = frac(frag_in.uv.x); + float y = (leftover < 0.5) ? y01.x : y01.y; + float3 yuv = float3(y, cbcr); + 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.); +} + float3 PSYVYU_Reverse(FragTex frag_in) : TARGET { float4 y2uv = image.Load(int3(frag_in.uv.xy, 0)); @@ -614,6 +642,28 @@ float3 PSNV12_Reverse(VertTexPos frag_in) : TARGET return rgb; } +float4 PSNV12_PQ_Reverse(VertTexPos frag_in) : TARGET +{ + float y = image.Load(int3(frag_in.pos.xy, 0)).x; + float2 cbcr = image1.Load(int3(frag_in.uv, 0)).xy; + float3 yuv = float3(y, cbcr); + float3 pq = YUV_to_RGB(yuv); + float3 hdr2020 = st2084_to_linear_eetf(pq, hdr_lw, hdr_lmax) * maximum_over_sdr_white_nits; + float3 rgb = rec2020_to_rec709(hdr2020); + return float4(rgb, 1.); +} + +float4 PSNV12_HLG_Reverse(VertTexPos frag_in) : TARGET +{ + float y = image.Load(int3(frag_in.pos.xy, 0)).x; + float2 cbcr = image1.Load(int3(frag_in.uv, 0)).xy; + float3 yuv = float3(y, cbcr); + 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.); +} + float4 PSI010_SRGB_Reverse(VertTexPos frag_in) : TARGET { float ratio = 65535. / 1023.; @@ -952,6 +1002,24 @@ technique YUY2_Reverse } } +technique YUY2_PQ_Reverse +{ + pass + { + vertex_shader = VSTexPosHalf_Reverse(id); + pixel_shader = PSYUY2_PQ_Reverse(frag_in); + } +} + +technique YUY2_HLG_Reverse +{ + pass + { + vertex_shader = VSTexPosHalf_Reverse(id); + pixel_shader = PSYUY2_HLG_Reverse(frag_in); + } +} + technique YVYU_Reverse { pass @@ -1078,6 +1146,24 @@ technique NV12_Reverse } } +technique NV12_PQ_Reverse +{ + pass + { + vertex_shader = VSTexPosHalfHalf_Reverse(id); + pixel_shader = PSNV12_PQ_Reverse(frag_in); + } +} + +technique NV12_HLG_Reverse +{ + pass + { + vertex_shader = VSTexPosHalfHalf_Reverse(id); + pixel_shader = PSNV12_HLG_Reverse(frag_in); + } +} + technique I010_SRGB_Reverse { pass diff --git a/libobs/obs-source.c b/libobs/obs-source.c index be1562052..05ac3483a 100644 --- a/libobs/obs-source.c +++ b/libobs/obs-source.c @@ -2078,7 +2078,14 @@ static const char *select_conversion_technique(enum video_format format, return "UYVY_Reverse"; case VIDEO_FORMAT_YUY2: - return "YUY2_Reverse"; + switch (trc) { + case VIDEO_TRC_PQ: + return "YUY2_PQ_Reverse"; + case VIDEO_TRC_HLG: + return "YUY2_HLG_Reverse"; + default: + return "YUY2_Reverse"; + } case VIDEO_FORMAT_YVYU: return "YVYU_Reverse"; @@ -2094,7 +2101,14 @@ static const char *select_conversion_technique(enum video_format format, } case VIDEO_FORMAT_NV12: - return "NV12_Reverse"; + switch (trc) { + case VIDEO_TRC_PQ: + return "NV12_PQ_Reverse"; + case VIDEO_TRC_HLG: + return "NV12_HLG_Reverse"; + default: + return "NV12_Reverse"; + } case VIDEO_FORMAT_I444: return "I444_Reverse";