0
0
mirror of https://github.com/obsproject/obs-studio.git synced 2024-09-20 04:42:18 +02:00

libobs: Add support for reading I420 PQ

Not normally a valid combination, but Xbox writes 8-bit HDR videos.
This commit is contained in:
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; 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 float4 PSPlanar420A_Reverse(VertTexPos frag_in) : TARGET
{ {
int3 xy0_luma = int3(frag_in.pos.xy, 0); int3 xy0_luma = int3(frag_in.pos.xy, 0);
@ -511,7 +524,7 @@ float4 PSPlanar422_10LE_Reverse(FragPosWide frag_in) : TARGET
yuv *= 65535. / 1023.; yuv *= 65535. / 1023.;
float3 rgb = YUV_to_RGB(yuv); float3 rgb = YUV_to_RGB(yuv);
rgb = srgb_nonlinear_to_linear(rgb); rgb = srgb_nonlinear_to_linear(rgb);
return float4(rgb, 1.0); return float4(rgb, 1.);
} }
float4 PSPlanar422A_Reverse(FragPosWide frag_in) : TARGET float4 PSPlanar422A_Reverse(FragPosWide frag_in) : TARGET
@ -548,7 +561,7 @@ float4 PSPlanar444_12LE_Reverse(FragPos frag_in) : TARGET
yuv *= 65535. / 4095.; yuv *= 65535. / 4095.;
float3 rgb = YUV_to_RGB(yuv); float3 rgb = YUV_to_RGB(yuv);
rgb = srgb_nonlinear_to_linear(rgb); rgb = srgb_nonlinear_to_linear(rgb);
return float4(rgb, 1.0); return float4(rgb, 1.);
} }
float4 PSPlanar444A_Reverse(FragPos frag_in) : TARGET 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 yuv = float3(y, cb, cr);
float3 rgb = YUV_to_RGB(yuv); float3 rgb = YUV_to_RGB(yuv);
rgb = srgb_nonlinear_to_linear(rgb); 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 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 pq = YUV_to_RGB(yuv);
float3 hdr2020 = st2084_to_linear(pq) * maximum_over_sdr_white_nits; float3 hdr2020 = st2084_to_linear(pq) * maximum_over_sdr_white_nits;
float3 rgb = rec2020_to_rec709(hdr2020); 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 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 hlg = YUV_to_RGB(yuv);
float3 hdr2020 = hlg_to_linear(hlg, hlg_exponent) * maximum_over_sdr_white_nits; float3 hdr2020 = hlg_to_linear(hlg, hlg_exponent) * maximum_over_sdr_white_nits;
float3 rgb = rec2020_to_rec709(hdr2020); float3 rgb = rec2020_to_rec709(hdr2020);
return float4(rgb, 1.0); return float4(rgb, 1.);
} }
float4 PSP010_SRGB_Reverse(VertTexPos frag_in) : TARGET 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 yuv = float3(y, cbcr);
float3 rgb = YUV_to_RGB(yuv); float3 rgb = YUV_to_RGB(yuv);
rgb = srgb_nonlinear_to_linear(rgb); 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 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 pq = YUV_to_RGB(yuv);
float3 hdr2020 = st2084_to_linear(pq) * maximum_over_sdr_white_nits; float3 hdr2020 = st2084_to_linear(pq) * maximum_over_sdr_white_nits;
float3 rgb = rec2020_to_rec709(hdr2020); 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 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 hlg = YUV_to_RGB(yuv);
float3 hdr2020 = hlg_to_linear(hlg, hlg_exponent) * maximum_over_sdr_white_nits; float3 hdr2020 = hlg_to_linear(hlg, hlg_exponent) * maximum_over_sdr_white_nits;
float3 rgb = rec2020_to_rec709(hdr2020); float3 rgb = rec2020_to_rec709(hdr2020);
return float4(rgb, 1.0); return float4(rgb, 1.);
} }
float3 PSY800_Limited(FragPos frag_in) : TARGET 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 technique I40A_Reverse
{ {
pass 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 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) { switch (trc) {
case VIDEO_FORMAT_RGBA: case VIDEO_TRC_PQ:
return GS_RGBA; case VIDEO_TRC_HLG:
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; return GS_RGBA16F;
default: 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 video_trc trc)
{ {
enum gs_color_space space = GS_CS_SRGB; 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 space = (trc == VIDEO_TRC_SRGB) ? GS_CS_SRGB_16F
: GS_CS_709_EXTENDED; : 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) void set_deinterlace_texture_size(obs_source_t *source)
{ {
const enum gs_color_format format = 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) { if (source->async_gpu_conversion) {
source->async_prev_texrender = source->async_prev_texrender =

View File

@ -1546,6 +1546,7 @@ enum convert_type {
CONVERT_NONE, CONVERT_NONE,
CONVERT_NV12, CONVERT_NV12,
CONVERT_420, CONVERT_420,
CONVERT_420_PQ,
CONVERT_420_A, CONVERT_420_A,
CONVERT_422, CONVERT_422,
CONVERT_422P10LE, CONVERT_422P10LE,
@ -1572,7 +1573,7 @@ static inline enum convert_type get_convert_type(enum video_format format,
{ {
switch (format) { switch (format) {
case VIDEO_FORMAT_I420: case VIDEO_FORMAT_I420:
return CONVERT_420; return (trc == VIDEO_TRC_PQ) ? CONVERT_420_PQ : CONVERT_420;
case VIDEO_FORMAT_NV12: case VIDEO_FORMAT_NV12:
return CONVERT_NV12; return CONVERT_NV12;
case VIDEO_FORMAT_I444: 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_width[0] = frame->width;
source->async_convert_height[0] = frame->height; 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; source->async_channel_count = 1;
return true; return true;
} }
@ -1935,6 +1937,7 @@ static inline bool init_gpu_conversion(struct obs_source *source,
return set_packed422_sizes(source, frame); return set_packed422_sizes(source, frame);
case CONVERT_420: case CONVERT_420:
case CONVERT_420_PQ:
return set_planar420_sizes(source, frame); return set_planar420_sizes(source, frame);
case CONVERT_422: case CONVERT_422:
@ -2026,7 +2029,8 @@ bool set_async_texture_size(struct obs_source *source,
source->async_texrender = NULL; source->async_texrender = NULL;
source->async_prev_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) && const bool async_gpu_conversion = (cur != CONVERT_NONE) &&
init_gpu_conversion(source, frame); init_gpu_conversion(source, frame);
source->async_gpu_conversion = async_gpu_conversion; 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_RGB_LIMITED:
case CONVERT_BGR3: case CONVERT_BGR3:
case CONVERT_420: case CONVERT_420:
case CONVERT_420_PQ:
case CONVERT_422: case CONVERT_422:
case CONVERT_422P10LE: case CONVERT_422P10LE:
case CONVERT_NV12: case CONVERT_NV12:
@ -2107,7 +2112,8 @@ static const char *select_conversion_technique(enum video_format format,
return "YVYU_Reverse"; return "YVYU_Reverse";
case VIDEO_FORMAT_I420: case VIDEO_FORMAT_I420:
return "I420_Reverse"; return (trc == VIDEO_TRC_PQ) ? "I420_PQ_Reverse"
: "I420_Reverse";
case VIDEO_FORMAT_NV12: case VIDEO_FORMAT_NV12:
return "NV12_Reverse"; return "NV12_Reverse";