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:
parent
0934e73902
commit
7669da1ea8
@ -60,6 +60,8 @@ Video Handler
|
||||
|
||||
- VIDEO_FORMAT_V210
|
||||
|
||||
- VIDEO_FORMAT_R10L
|
||||
|
||||
---------------------
|
||||
|
||||
.. enum:: video_trc
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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:;
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 */
|
||||
;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user