0
0
mirror of https://github.com/obsproject/obs-studio.git synced 2024-09-19 20:32:15 +02:00

libobs: Add VIDEO_FORMAT_R10L

Support 10-bit packed format that DeckLink uses.
This commit is contained in:
jpark37 2023-04-02 17:49:35 -07:00 committed by Lain
parent 0934e73902
commit 7669da1ea8
10 changed files with 178 additions and 0 deletions

View File

@ -60,6 +60,8 @@ Video Handler
- VIDEO_FORMAT_V210
- VIDEO_FORMAT_R10L
---------------------
.. enum:: video_trc

View File

@ -827,6 +827,9 @@ Functions used by outputs
/* packed 4:2:2 format, 10 bpp */
VIDEO_FORMAT_V210,
/* packed uncompressed 10-bit format */
VIDEO_FORMAT_R10L,
};
enum video_colorspace {

View File

@ -1470,6 +1470,9 @@ Functions used by sources
/* packed 4:2:2 format, 10 bpp */
VIDEO_FORMAT_V210,
/* packed uncompressed 10-bit format */
VIDEO_FORMAT_R10L,
};
struct obs_source_frame {

View File

@ -1054,6 +1054,72 @@ float3 PSBGR3_Full(FragPos frag_in) : TARGET
return rgb;
}
float3 compute_r10l_reverse(float2 pos, bool limited)
{
float4 xyzw = image.Load(int3(pos, 0)).bgra;
uint4 xyzw255 = uint4(mad(xyzw, 255., 0.5));
uint r = ((xyzw255.z & 0xC0u) >> 6) | (xyzw255.w << 2);
uint g = ((xyzw255.y & 0xFu) >> 4) | ((xyzw255.z & 0x3Fu) << 4);
uint b = (xyzw255.x >> 2) | ((xyzw255.y & 0xFu) << 6);
float3 rgb = float3(uint3(r, g, b));
if (limited)
{
rgb = mad(rgb, 1. / 876., -16. / 219.);
}
else
{
rgb /= 1023.;
}
return rgb;
}
float4 PSR10L_SRGB_Full_Reverse(FragPos frag_in) : TARGET
{
float3 rgb = compute_r10l_reverse(frag_in.pos.xy, false);
rgb = srgb_nonlinear_to_linear(rgb);
return float4(rgb, 1.);
}
float4 PSR10L_PQ_2020_709_Full_Reverse(FragPos frag_in) : TARGET
{
float3 pq = compute_r10l_reverse(frag_in.pos.xy, false);
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 PSR10L_HLG_2020_709_Full_Reverse(FragPos frag_in) : TARGET
{
float3 hlg = compute_r10l_reverse(frag_in.pos.xy, false);
float3 hdr2020 = hlg_to_linear(hlg, hlg_exponent) * maximum_over_sdr_white_nits;
float3 rgb = rec2020_to_rec709(hdr2020);
return float4(rgb, 1.);
}
float4 PSR10L_SRGB_Limited_Reverse(FragPos frag_in) : TARGET
{
float3 rgb = compute_r10l_reverse(frag_in.pos.xy, true);
rgb = srgb_nonlinear_to_linear(rgb);
return float4(rgb, 1.);
}
float4 PSR10L_PQ_2020_709_Limited_Reverse(FragPos frag_in) : TARGET
{
float3 pq = compute_r10l_reverse(frag_in.pos.xy, true);
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 PSR10L_HLG_2020_709_Limited_Reverse(FragPos frag_in) : TARGET
{
float3 hlg = compute_r10l_reverse(frag_in.pos.xy, true);
float3 hdr2020 = hlg_to_linear(hlg, hlg_exponent) * maximum_over_sdr_white_nits;
float3 rgb = rec2020_to_rec709(hdr2020);
return float4(rgb, 1.);
}
technique Planar_Y
{
pass
@ -1701,3 +1767,57 @@ technique BGR3_Full
pixel_shader = PSBGR3_Full(frag_in);
}
}
technique R10L_SRGB_Full_Reverse
{
pass
{
vertex_shader = VSPos(id);
pixel_shader = PSR10L_SRGB_Full_Reverse(frag_in);
}
}
technique R10L_PQ_2020_709_Full_Reverse
{
pass
{
vertex_shader = VSPos(id);
pixel_shader = PSR10L_PQ_2020_709_Full_Reverse(frag_in);
}
}
technique R10L_HLG_2020_709_Full_Reverse
{
pass
{
vertex_shader = VSPos(id);
pixel_shader = PSR10L_HLG_2020_709_Full_Reverse(frag_in);
}
}
technique R10L_SRGB_Limited_Reverse
{
pass
{
vertex_shader = VSPos(id);
pixel_shader = PSR10L_SRGB_Limited_Reverse(frag_in);
}
}
technique R10L_PQ_2020_709_Limited_Reverse
{
pass
{
vertex_shader = VSPos(id);
pixel_shader = PSR10L_PQ_2020_709_Limited_Reverse(frag_in);
}
}
technique R10L_HLG_2020_709_Limited_Reverse
{
pass
{
vertex_shader = VSPos(id);
pixel_shader = PSR10L_HLG_2020_709_Limited_Reverse(frag_in);
}
}

View File

@ -339,6 +339,13 @@ void video_frame_init(struct video_frame *frame, enum video_format format,
frame->linesize[0] = adjusted_width;
break;
}
case VIDEO_FORMAT_R10L:
size = width * height * 4;
ALIGN_SIZE(size, alignment);
frame->data[0] = bmalloc(size);
frame->linesize[0] = width * 4;
break;
}
}
@ -372,6 +379,7 @@ void video_frame_copy(struct video_frame *dst, const struct video_frame *src,
case VIDEO_FORMAT_BGR3:
case VIDEO_FORMAT_AYUV:
case VIDEO_FORMAT_V210:
case VIDEO_FORMAT_R10L:
memcpy(dst->data[0], src->data[0], src->linesize[0] * cy);
break;

View File

@ -91,6 +91,9 @@ enum video_format {
/* packed 4:2:2 format, 10 bpp */
VIDEO_FORMAT_V210,
/* packed uncompressed 10-bit format */
VIDEO_FORMAT_R10L,
};
enum video_trc {
@ -164,6 +167,7 @@ static inline bool format_is_yuv(enum video_format format)
case VIDEO_FORMAT_BGRX:
case VIDEO_FORMAT_Y800:
case VIDEO_FORMAT_BGR3:
case VIDEO_FORMAT_R10L:
return false;
}
@ -221,6 +225,8 @@ static inline const char *get_video_format_name(enum video_format format)
return "P416";
case VIDEO_FORMAT_V210:
return "v210";
case VIDEO_FORMAT_R10L:
return "R10l";
case VIDEO_FORMAT_NONE:;
}

View File

@ -264,6 +264,7 @@ bool video_format_get_parameters_for_format(enum video_colorspace color_space,
case VIDEO_FORMAT_P010:
case VIDEO_FORMAT_I210:
case VIDEO_FORMAT_V210:
case VIDEO_FORMAT_R10L:
bpc = 10;
break;
case VIDEO_FORMAT_I412:

View File

@ -963,6 +963,7 @@ convert_video_format(enum video_format format, enum video_trc trc)
case VIDEO_FORMAT_P216:
case VIDEO_FORMAT_P416:
case VIDEO_FORMAT_V210:
case VIDEO_FORMAT_R10L:
return GS_RGBA16F;
default:
return GS_BGRX;

View File

@ -1592,6 +1592,7 @@ enum convert_type {
CONVERT_I010,
CONVERT_P010,
CONVERT_V210,
CONVERT_R10L,
};
static inline enum convert_type get_convert_type(enum video_format format,
@ -1652,6 +1653,9 @@ static inline enum convert_type get_convert_type(enum video_format format,
case VIDEO_FORMAT_V210:
return CONVERT_V210;
case VIDEO_FORMAT_R10L:
return CONVERT_R10L;
case VIDEO_FORMAT_P216:
case VIDEO_FORMAT_P416:
/* Unimplemented */
@ -1959,6 +1963,16 @@ static inline bool set_v210_sizes(struct obs_source *source,
return true;
}
static inline bool set_r10l_sizes(struct obs_source *source,
const struct obs_source_frame *frame)
{
source->async_convert_width[0] = frame->width;
source->async_convert_height[0] = frame->height;
source->async_texture_formats[0] = GS_BGRA_UNORM;
source->async_channel_count = 1;
return true;
}
static inline bool init_gpu_conversion(struct obs_source *source,
const struct obs_source_frame *frame)
{
@ -2019,6 +2033,9 @@ static inline bool init_gpu_conversion(struct obs_source *source,
case CONVERT_V210:
return set_v210_sizes(source, frame);
case CONVERT_R10L:
return set_r10l_sizes(source, frame);
case CONVERT_NONE:
assert(false && "No conversion requested");
break;
@ -2112,6 +2129,7 @@ static void upload_raw_frame(gs_texture_t *tex[MAX_AV_PLANES],
case CONVERT_I010:
case CONVERT_P010:
case CONVERT_V210:
case CONVERT_R10L:
for (size_t c = 0; c < MAX_AV_PLANES; c++) {
if (tex[c])
gs_texture_set_image(tex[c], frame->data[c],
@ -2245,6 +2263,20 @@ static const char *select_conversion_technique(enum video_format format,
}
}
case VIDEO_FORMAT_R10L: {
switch (trc) {
case VIDEO_TRC_PQ:
return full_range ? "R10L_PQ_2020_709_Full_Reverse"
: "R10L_PQ_2020_709_Limited_Reverse";
case VIDEO_TRC_HLG:
return full_range ? "R10L_HLG_2020_709_Full_Reverse"
: "R10L_HLG_2020_709_Limited_Reverse";
default:
return full_range ? "R10L_SRGB_Full_Reverse"
: "R10L_SRGB_Limited_Reverse";
}
}
case VIDEO_FORMAT_BGRA:
case VIDEO_FORMAT_BGRX:
case VIDEO_FORMAT_RGBA:
@ -3462,6 +3494,7 @@ static void copy_frame_data(struct obs_source_frame *dst,
case VIDEO_FORMAT_BGR3:
case VIDEO_FORMAT_AYUV:
case VIDEO_FORMAT_V210:
case VIDEO_FORMAT_R10L:
copy_frame_data_plane(dst, src, 0, dst->height);
break;

View File

@ -787,6 +787,7 @@ static void set_gpu_converted_data(struct video_frame *output,
case VIDEO_FORMAT_YA2L:
case VIDEO_FORMAT_AYUV:
case VIDEO_FORMAT_V210:
case VIDEO_FORMAT_R10L:
/* unimplemented */
;
}