mirror of
https://github.com/obsproject/obs-studio.git
synced 2026-04-04 23:04:20 -04:00
libobs,UI: Add P216/P416 pixel formats
Will be useful for ProRes.
This commit is contained in:
@@ -1148,7 +1148,7 @@ Basic.Settings.Advanced.General.ProcessPriority.Normal="Normal"
|
||||
Basic.Settings.Advanced.General.ProcessPriority.BelowNormal="Below Normal"
|
||||
Basic.Settings.Advanced.General.ProcessPriority.Idle="Idle"
|
||||
Basic.Settings.Advanced.FormatWarning="Warning: Color formats other than NV12/P010 are primarily intended for recording, and are not recommended when streaming. Streaming may incur increased CPU usage due to color format conversion."
|
||||
Basic.Settings.Advanced.FormatWarning10BitSdr="Warning: 10-bit formats are more commonly used with HDR color spaces."
|
||||
Basic.Settings.Advanced.FormatWarningPreciseSdr="Warning: High-precision formats are more commonly used with HDR color spaces."
|
||||
Basic.Settings.Advanced.FormatWarning2100="Warning: Rec. 2100 should use a format with more precision."
|
||||
Basic.Settings.Advanced.Audio.BufferingTime="Audio Buffering Time"
|
||||
Basic.Settings.Advanced.Video.ColorFormat="Color Format"
|
||||
@@ -1157,6 +1157,8 @@ Basic.Settings.Advanced.Video.ColorFormat.I420="I420 (8-bit, 4:2:0, 3 planes)"
|
||||
Basic.Settings.Advanced.Video.ColorFormat.I444="I444 (8-bit, 4:4:4, 3 planes)"
|
||||
Basic.Settings.Advanced.Video.ColorFormat.P010="P010 (10-bit, 4:2:0, 2 planes)"
|
||||
Basic.Settings.Advanced.Video.ColorFormat.I010="I010 (10-bit, 4:2:0, 3 planes)"
|
||||
Basic.Settings.Advanced.Video.ColorFormat.P216="P216 (16-bit, 4:2:2, 2 planes)"
|
||||
Basic.Settings.Advanced.Video.ColorFormat.P416="P416 (16-bit, 4:4:4, 2 planes)"
|
||||
Basic.Settings.Advanced.Video.ColorFormat.BGRA="BGRA (8-bit)"
|
||||
Basic.Settings.Advanced.Video.ColorSpace="Color Space"
|
||||
Basic.Settings.Advanced.Video.ColorSpace.sRGB="sRGB"
|
||||
|
||||
@@ -4393,6 +4393,10 @@ static inline enum video_format GetVideoFormatFromName(const char *name)
|
||||
return VIDEO_FORMAT_I010;
|
||||
else if (astrcmpi(name, "P010") == 0)
|
||||
return VIDEO_FORMAT_P010;
|
||||
else if (astrcmpi(name, "P216") == 0)
|
||||
return VIDEO_FORMAT_P216;
|
||||
else if (astrcmpi(name, "P416") == 0)
|
||||
return VIDEO_FORMAT_P416;
|
||||
#if 0 //currently unsupported
|
||||
else if (astrcmpi(name, "YVYU") == 0)
|
||||
return VIDEO_FORMAT_YVYU;
|
||||
|
||||
@@ -1006,6 +1006,8 @@ void OBSBasicSettings::LoadColorSpaces()
|
||||
#define CF_I444_STR QTStr("Basic.Settings.Advanced.Video.ColorFormat.I444")
|
||||
#define CF_P010_STR QTStr("Basic.Settings.Advanced.Video.ColorFormat.P010")
|
||||
#define CF_I010_STR QTStr("Basic.Settings.Advanced.Video.ColorFormat.I010")
|
||||
#define CF_P216_STR QTStr("Basic.Settings.Advanced.Video.ColorFormat.P216")
|
||||
#define CF_P416_STR QTStr("Basic.Settings.Advanced.Video.ColorFormat.P416")
|
||||
#define CF_BGRA_STR QTStr("Basic.Settings.Advanced.Video.ColorFormat.BGRA")
|
||||
|
||||
void OBSBasicSettings::LoadColorFormats()
|
||||
@@ -1015,6 +1017,8 @@ void OBSBasicSettings::LoadColorFormats()
|
||||
ui->colorFormat->addItem(CF_I444_STR, "I444");
|
||||
ui->colorFormat->addItem(CF_P010_STR, "P010");
|
||||
ui->colorFormat->addItem(CF_I010_STR, "I010");
|
||||
ui->colorFormat->addItem(CF_P216_STR, "P216");
|
||||
ui->colorFormat->addItem(CF_P416_STR, "P416");
|
||||
ui->colorFormat->addItem(CF_BGRA_STR, "RGB"); // Avoid config break
|
||||
}
|
||||
|
||||
@@ -2599,7 +2603,8 @@ void OBSBasicSettings::UpdateColorFormatSpaceWarning()
|
||||
switch (ui->colorSpace->currentIndex()) {
|
||||
case 3: /* Rec.2100 (PQ) */
|
||||
case 4: /* Rec.2100 (HLG) */
|
||||
if (format == "P010") {
|
||||
if ((format == "P010") || (format == "P216") ||
|
||||
(format == "P416")) {
|
||||
ui->advancedMsg2->clear();
|
||||
} else if (format == "I010") {
|
||||
ui->advancedMsg2->setText(
|
||||
@@ -2612,9 +2617,10 @@ void OBSBasicSettings::UpdateColorFormatSpaceWarning()
|
||||
default:
|
||||
if (format == "NV12") {
|
||||
ui->advancedMsg2->clear();
|
||||
} else if ((format == "I010") || (format == "P010")) {
|
||||
} else if ((format == "I010") || (format == "P010") ||
|
||||
(format == "P216") || (format == "P416")) {
|
||||
ui->advancedMsg2->setText(QTStr(
|
||||
"Basic.Settings.Advanced.FormatWarning10BitSdr"));
|
||||
"Basic.Settings.Advanced.FormatWarningPreciseSdr"));
|
||||
} else {
|
||||
ui->advancedMsg2->setText(
|
||||
QTStr("Basic.Settings.Advanced.FormatWarning"));
|
||||
|
||||
@@ -48,6 +48,16 @@ Video Handler
|
||||
- VIDEO_FORMAT_I010
|
||||
- VIDEO_FORMAT_P010
|
||||
|
||||
- VIDEO_FORMAT_I210
|
||||
|
||||
- VIDEO_FORMAT_I412
|
||||
|
||||
- VIDEO_FORMAT_YA2L
|
||||
|
||||
- VIDEO_FORMAT_P216
|
||||
|
||||
- VIDEO_FORMAT_P416
|
||||
|
||||
---------------------
|
||||
|
||||
.. enum:: video_trc
|
||||
|
||||
@@ -747,6 +747,21 @@ Functions used by outputs
|
||||
/* planar 4:2:0 format, 10 bpp */
|
||||
VIDEO_FORMAT_I010, /* three-plane */
|
||||
VIDEO_FORMAT_P010, /* two-plane, luma and packed chroma */
|
||||
|
||||
/* planar 4:2:2 format, 10 bpp */
|
||||
VIDEO_FORMAT_I210,
|
||||
|
||||
/* planar 4:4:4 format, 12 bpp */
|
||||
VIDEO_FORMAT_I412,
|
||||
|
||||
/* planar 4:4:4:4 format, 12 bpp */
|
||||
VIDEO_FORMAT_YA2L,
|
||||
|
||||
/* planar 4:2:2 format, 16 bpp */
|
||||
VIDEO_FORMAT_P216, /* two-plane, luma and packed chroma */
|
||||
|
||||
/* planar 4:4:4 format, 16 bpp */
|
||||
VIDEO_FORMAT_P416, /* two-plane, luma and packed chroma */
|
||||
};
|
||||
|
||||
enum video_colorspace {
|
||||
|
||||
@@ -1425,6 +1425,21 @@ Functions used by sources
|
||||
/* planar 4:2:0 format, 10 bpp */
|
||||
VIDEO_FORMAT_I010, /* three-plane */
|
||||
VIDEO_FORMAT_P010, /* two-plane, luma and packed chroma */
|
||||
|
||||
/* planar 4:2:2 format, 10 bpp */
|
||||
VIDEO_FORMAT_I210,
|
||||
|
||||
/* planar 4:4:4 format, 12 bpp */
|
||||
VIDEO_FORMAT_I412,
|
||||
|
||||
/* planar 4:4:4:4 format, 12 bpp */
|
||||
VIDEO_FORMAT_YA2L,
|
||||
|
||||
/* planar 4:2:2 format, 16 bpp */
|
||||
VIDEO_FORMAT_P216, /* two-plane, luma and packed chroma */
|
||||
|
||||
/* planar 4:4:4 format, 16 bpp */
|
||||
VIDEO_FORMAT_P416, /* two-plane, luma and packed chroma */
|
||||
};
|
||||
|
||||
struct obs_source_frame {
|
||||
|
||||
@@ -252,6 +252,58 @@ float PS_P010_SRGB_Y(FragPos frag_in) : TARGET
|
||||
return y;
|
||||
}
|
||||
|
||||
float PS_P216_PQ_Y_709_2020(FragPos frag_in) : TARGET
|
||||
{
|
||||
float3 rgb = image.Load(int3(frag_in.pos.xy, 0)).rgb * sdr_white_nits_over_maximum;
|
||||
rgb = rec709_to_rec2020(rgb);
|
||||
rgb = linear_to_st2084(rgb);
|
||||
float y = dot(color_vec0.xyz, rgb) + color_vec0.w;
|
||||
return y;
|
||||
}
|
||||
|
||||
float PS_P216_HLG_Y_709_2020(FragPos frag_in) : TARGET
|
||||
{
|
||||
float3 rgb = image.Load(int3(frag_in.pos.xy, 0)).rgb * sdr_white_nits_over_maximum;
|
||||
rgb = rec709_to_rec2020(rgb);
|
||||
rgb = linear_to_hlg(rgb, hdr_lw);
|
||||
float y = dot(color_vec0.xyz, rgb) + color_vec0.w;
|
||||
return y;
|
||||
}
|
||||
|
||||
float PS_P216_SRGB_Y(FragPos frag_in) : TARGET
|
||||
{
|
||||
float3 rgb = image.Load(int3(frag_in.pos.xy, 0)).rgb;
|
||||
rgb = srgb_linear_to_nonlinear(rgb);
|
||||
float y = dot(color_vec0.xyz, rgb) + color_vec0.w;
|
||||
return y;
|
||||
}
|
||||
|
||||
float PS_P416_PQ_Y_709_2020(FragPos frag_in) : TARGET
|
||||
{
|
||||
float3 rgb = image.Load(int3(frag_in.pos.xy, 0)).rgb * sdr_white_nits_over_maximum;
|
||||
rgb = rec709_to_rec2020(rgb);
|
||||
rgb = linear_to_st2084(rgb);
|
||||
float y = dot(color_vec0.xyz, rgb) + color_vec0.w;
|
||||
return y;
|
||||
}
|
||||
|
||||
float PS_P416_HLG_Y_709_2020(FragPos frag_in) : TARGET
|
||||
{
|
||||
float3 rgb = image.Load(int3(frag_in.pos.xy, 0)).rgb * sdr_white_nits_over_maximum;
|
||||
rgb = rec709_to_rec2020(rgb);
|
||||
rgb = linear_to_hlg(rgb, hdr_lw);
|
||||
float y = dot(color_vec0.xyz, rgb) + color_vec0.w;
|
||||
return y;
|
||||
}
|
||||
|
||||
float PS_P416_SRGB_Y(FragPos frag_in) : TARGET
|
||||
{
|
||||
float3 rgb = image.Load(int3(frag_in.pos.xy, 0)).rgb;
|
||||
rgb = srgb_linear_to_nonlinear(rgb);
|
||||
float y = dot(color_vec0.xyz, rgb) + color_vec0.w;
|
||||
return y;
|
||||
}
|
||||
|
||||
float PS_I010_PQ_Y_709_2020(FragPos frag_in) : TARGET
|
||||
{
|
||||
float3 rgb = image.Load(int3(frag_in.pos.xy, 0)).rgb * sdr_white_nits_over_maximum;
|
||||
@@ -333,6 +385,76 @@ float2 PS_P010_SRGB_UV_Wide(FragTexWide frag_in) : TARGET
|
||||
return uv;
|
||||
}
|
||||
|
||||
float2 PS_P216_PQ_UV_709_2020_Wide(FragTexWide frag_in) : TARGET
|
||||
{
|
||||
float3 rgb_left = image.Sample(def_sampler, frag_in.uuv.xz).rgb;
|
||||
float3 rgb_right = image.Sample(def_sampler, frag_in.uuv.yz).rgb;
|
||||
float3 rgb = (rgb_left + rgb_right) * (0.5 * sdr_white_nits_over_maximum);
|
||||
rgb = rec709_to_rec2020(rgb);
|
||||
rgb = linear_to_st2084(rgb);
|
||||
float u = dot(color_vec1.xyz, rgb) + color_vec1.w;
|
||||
float v = dot(color_vec2.xyz, rgb) + color_vec2.w;
|
||||
float2 uv = float2(u, v);
|
||||
return uv;
|
||||
}
|
||||
|
||||
float2 PS_P216_HLG_UV_709_2020_Wide(FragTexWide frag_in) : TARGET
|
||||
{
|
||||
float3 rgb_left = image.Sample(def_sampler, frag_in.uuv.xz).rgb;
|
||||
float3 rgb_right = image.Sample(def_sampler, frag_in.uuv.yz).rgb;
|
||||
float3 rgb = (rgb_left + rgb_right) * (0.5 * sdr_white_nits_over_maximum);
|
||||
rgb = rec709_to_rec2020(rgb);
|
||||
rgb = linear_to_hlg(rgb, hdr_lw);
|
||||
float u = dot(color_vec1.xyz, rgb) + color_vec1.w;
|
||||
float v = dot(color_vec2.xyz, rgb) + color_vec2.w;
|
||||
float2 uv = float2(u, v);
|
||||
return uv;
|
||||
}
|
||||
|
||||
float2 PS_P216_SRGB_UV_Wide(FragTexWide frag_in) : TARGET
|
||||
{
|
||||
float3 rgb_left = image.Sample(def_sampler, frag_in.uuv.xz).rgb;
|
||||
float3 rgb_right = image.Sample(def_sampler, frag_in.uuv.yz).rgb;
|
||||
float3 rgb = (rgb_left + rgb_right) * 0.5;
|
||||
rgb = srgb_linear_to_nonlinear(rgb);
|
||||
float u = dot(color_vec1.xyz, rgb) + color_vec1.w;
|
||||
float v = dot(color_vec2.xyz, rgb) + color_vec2.w;
|
||||
float2 uv = float2(u, v);
|
||||
return uv;
|
||||
}
|
||||
|
||||
float2 PS_P416_PQ_UV_709_2020(FragPos frag_in) : TARGET
|
||||
{
|
||||
float3 rgb = image.Load(int3(frag_in.pos.xy, 0)).rgb;
|
||||
rgb = rec709_to_rec2020(rgb);
|
||||
rgb = linear_to_st2084(rgb);
|
||||
float u = dot(color_vec1.xyz, rgb) + color_vec1.w;
|
||||
float v = dot(color_vec2.xyz, rgb) + color_vec2.w;
|
||||
float2 uv = float2(u, v);
|
||||
return uv;
|
||||
}
|
||||
|
||||
float2 PS_P416_HLG_UV_709_2020(FragPos frag_in) : TARGET
|
||||
{
|
||||
float3 rgb = image.Load(int3(frag_in.pos.xy, 0)).rgb;
|
||||
rgb = rec709_to_rec2020(rgb);
|
||||
rgb = linear_to_hlg(rgb, hdr_lw);
|
||||
float u = dot(color_vec1.xyz, rgb) + color_vec1.w;
|
||||
float v = dot(color_vec2.xyz, rgb) + color_vec2.w;
|
||||
float2 uv = float2(u, v);
|
||||
return uv;
|
||||
}
|
||||
|
||||
float2 PS_P416_SRGB_UV(FragPos frag_in) : TARGET
|
||||
{
|
||||
float3 rgb = image.Load(int3(frag_in.pos.xy, 0)).rgb;
|
||||
rgb = srgb_linear_to_nonlinear(rgb);
|
||||
float u = dot(color_vec1.xyz, rgb) + color_vec1.w;
|
||||
float v = dot(color_vec2.xyz, rgb) + color_vec2.w;
|
||||
float2 uv = float2(u, v);
|
||||
return uv;
|
||||
}
|
||||
|
||||
float PS_U(FragPos frag_in) : TARGET
|
||||
{
|
||||
float3 rgb = image.Load(int3(frag_in.pos.xy, 0)).rgb;
|
||||
@@ -1044,6 +1166,114 @@ technique P010_SRGB_UV
|
||||
}
|
||||
}
|
||||
|
||||
technique P216_PQ_Y
|
||||
{
|
||||
pass
|
||||
{
|
||||
vertex_shader = VSPos(id);
|
||||
pixel_shader = PS_P216_PQ_Y_709_2020(frag_in);
|
||||
}
|
||||
}
|
||||
|
||||
technique P216_HLG_Y
|
||||
{
|
||||
pass
|
||||
{
|
||||
vertex_shader = VSPos(id);
|
||||
pixel_shader = PS_P216_HLG_Y_709_2020(frag_in);
|
||||
}
|
||||
}
|
||||
|
||||
technique P216_SRGB_Y
|
||||
{
|
||||
pass
|
||||
{
|
||||
vertex_shader = VSPos(id);
|
||||
pixel_shader = PS_P216_SRGB_Y(frag_in);
|
||||
}
|
||||
}
|
||||
|
||||
technique P216_PQ_UV
|
||||
{
|
||||
pass
|
||||
{
|
||||
vertex_shader = VSTexPos_Left(id);
|
||||
pixel_shader = PS_P216_PQ_UV_709_2020_Wide(frag_in);
|
||||
}
|
||||
}
|
||||
|
||||
technique P216_HLG_UV
|
||||
{
|
||||
pass
|
||||
{
|
||||
vertex_shader = VSTexPos_Left(id);
|
||||
pixel_shader = PS_P216_HLG_UV_709_2020_Wide(frag_in);
|
||||
}
|
||||
}
|
||||
|
||||
technique P216_SRGB_UV
|
||||
{
|
||||
pass
|
||||
{
|
||||
vertex_shader = VSTexPos_Left(id);
|
||||
pixel_shader = PS_P216_SRGB_UV_Wide(frag_in);
|
||||
}
|
||||
}
|
||||
|
||||
technique P416_PQ_Y
|
||||
{
|
||||
pass
|
||||
{
|
||||
vertex_shader = VSPos(id);
|
||||
pixel_shader = PS_P416_PQ_Y_709_2020(frag_in);
|
||||
}
|
||||
}
|
||||
|
||||
technique P416_HLG_Y
|
||||
{
|
||||
pass
|
||||
{
|
||||
vertex_shader = VSPos(id);
|
||||
pixel_shader = PS_P416_HLG_Y_709_2020(frag_in);
|
||||
}
|
||||
}
|
||||
|
||||
technique P416_SRGB_Y
|
||||
{
|
||||
pass
|
||||
{
|
||||
vertex_shader = VSPos(id);
|
||||
pixel_shader = PS_P416_SRGB_Y(frag_in);
|
||||
}
|
||||
}
|
||||
|
||||
technique P416_PQ_UV
|
||||
{
|
||||
pass
|
||||
{
|
||||
vertex_shader = VSPos(id);
|
||||
pixel_shader = PS_P416_PQ_UV_709_2020(frag_in);
|
||||
}
|
||||
}
|
||||
|
||||
technique P416_HLG_UV
|
||||
{
|
||||
pass
|
||||
{
|
||||
vertex_shader = VSPos(id);
|
||||
pixel_shader = PS_P416_HLG_UV_709_2020(frag_in);
|
||||
}
|
||||
}
|
||||
|
||||
technique P416_SRGB_UV
|
||||
{
|
||||
pass
|
||||
{
|
||||
vertex_shader = VSPos(id);
|
||||
pixel_shader = PS_P416_SRGB_UV(frag_in);
|
||||
}
|
||||
}
|
||||
|
||||
technique UYVY_Reverse
|
||||
{
|
||||
pass
|
||||
|
||||
@@ -303,6 +303,33 @@ void video_frame_init(struct video_frame *frame, enum video_format format,
|
||||
frame->linesize[1] = cbcr_width * 2;
|
||||
break;
|
||||
}
|
||||
|
||||
case VIDEO_FORMAT_P216: {
|
||||
size = width * height * 2;
|
||||
ALIGN_SIZE(size, alignment);
|
||||
offsets[0] = size;
|
||||
const uint32_t cbcr_width = (width + 1) & (UINT32_MAX - 1);
|
||||
size += cbcr_width * height * 2;
|
||||
ALIGN_SIZE(size, alignment);
|
||||
frame->data[0] = bmalloc(size);
|
||||
frame->data[1] = (uint8_t *)frame->data[0] + offsets[0];
|
||||
frame->linesize[0] = width * 2;
|
||||
frame->linesize[1] = cbcr_width * 2;
|
||||
break;
|
||||
}
|
||||
|
||||
case VIDEO_FORMAT_P416: {
|
||||
size = width * height * 2;
|
||||
ALIGN_SIZE(size, alignment);
|
||||
offsets[0] = size;
|
||||
size += width * height * 4;
|
||||
ALIGN_SIZE(size, alignment);
|
||||
frame->data[0] = bmalloc(size);
|
||||
frame->data[1] = (uint8_t *)frame->data[0] + offsets[0];
|
||||
frame->linesize[0] = width * 2;
|
||||
frame->linesize[1] = width * 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -362,5 +389,11 @@ void video_frame_copy(struct video_frame *dst, const struct video_frame *src,
|
||||
memcpy(dst->data[2], src->data[2], src->linesize[2] * cy);
|
||||
memcpy(dst->data[3], src->data[3], src->linesize[3] * cy);
|
||||
break;
|
||||
|
||||
case VIDEO_FORMAT_P216:
|
||||
case VIDEO_FORMAT_P416:
|
||||
memcpy(dst->data[0], src->data[0], src->linesize[0] * cy);
|
||||
memcpy(dst->data[1], src->data[1], src->linesize[1] * cy);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,14 +74,20 @@ enum video_format {
|
||||
VIDEO_FORMAT_I010, /* three-plane */
|
||||
VIDEO_FORMAT_P010, /* two-plane, luma and packed chroma */
|
||||
|
||||
/* planar 4:2:2 10 bits */
|
||||
VIDEO_FORMAT_I210, // Little Endian
|
||||
/* planar 4:2:2 format, 10 bpp */
|
||||
VIDEO_FORMAT_I210,
|
||||
|
||||
/* planar 4:4:4 12 bits */
|
||||
VIDEO_FORMAT_I412, // Little Endian
|
||||
/* planar 4:4:4 format, 12 bpp */
|
||||
VIDEO_FORMAT_I412,
|
||||
|
||||
/* planar 4:4:4 12 bits with alpha */
|
||||
VIDEO_FORMAT_YA2L, // Little Endian
|
||||
/* planar 4:4:4:4 format, 12 bpp */
|
||||
VIDEO_FORMAT_YA2L,
|
||||
|
||||
/* planar 4:2:2 format, 16 bpp */
|
||||
VIDEO_FORMAT_P216, /* two-plane, luma and packed chroma */
|
||||
|
||||
/* planar 4:4:4 format, 16 bpp */
|
||||
VIDEO_FORMAT_P416, /* two-plane, luma and packed chroma */
|
||||
};
|
||||
|
||||
enum video_trc {
|
||||
@@ -145,6 +151,8 @@ static inline bool format_is_yuv(enum video_format format)
|
||||
case VIDEO_FORMAT_AYUV:
|
||||
case VIDEO_FORMAT_I010:
|
||||
case VIDEO_FORMAT_P010:
|
||||
case VIDEO_FORMAT_P216:
|
||||
case VIDEO_FORMAT_P416:
|
||||
return true;
|
||||
case VIDEO_FORMAT_NONE:
|
||||
case VIDEO_FORMAT_RGBA:
|
||||
@@ -203,6 +211,10 @@ static inline const char *get_video_format_name(enum video_format format)
|
||||
return "I010";
|
||||
case VIDEO_FORMAT_P010:
|
||||
return "P010";
|
||||
case VIDEO_FORMAT_P216:
|
||||
return "P216";
|
||||
case VIDEO_FORMAT_P416:
|
||||
return "P416";
|
||||
case VIDEO_FORMAT_NONE:;
|
||||
}
|
||||
|
||||
|
||||
@@ -269,6 +269,10 @@ bool video_format_get_parameters_for_format(enum video_colorspace color_space,
|
||||
case VIDEO_FORMAT_YA2L:
|
||||
bpc = 12;
|
||||
break;
|
||||
case VIDEO_FORMAT_P216:
|
||||
case VIDEO_FORMAT_P416:
|
||||
bpc = 16;
|
||||
break;
|
||||
default:
|
||||
bpc = 8;
|
||||
break;
|
||||
|
||||
@@ -68,23 +68,25 @@ get_ffmpeg_video_format(enum video_format format)
|
||||
return AV_PIX_FMT_YUVA422P;
|
||||
case VIDEO_FORMAT_YUVA:
|
||||
return AV_PIX_FMT_YUVA444P;
|
||||
case VIDEO_FORMAT_YA2L:
|
||||
#if LIBAVUTIL_BUILD >= AV_VERSION_INT(56, 31, 100)
|
||||
case VIDEO_FORMAT_YA2L:
|
||||
return AV_PIX_FMT_YUVA444P12LE;
|
||||
#else
|
||||
return AV_PIX_FMT_NONE;
|
||||
#endif
|
||||
case VIDEO_FORMAT_I010:
|
||||
return AV_PIX_FMT_YUV420P10LE;
|
||||
case VIDEO_FORMAT_P010:
|
||||
return AV_PIX_FMT_P010LE;
|
||||
#if LIBAVUTIL_BUILD >= AV_VERSION_INT(57, 17, 100)
|
||||
case VIDEO_FORMAT_P216:
|
||||
return AV_PIX_FMT_P216LE;
|
||||
case VIDEO_FORMAT_P416:
|
||||
return AV_PIX_FMT_P416LE;
|
||||
#endif
|
||||
case VIDEO_FORMAT_NONE:
|
||||
case VIDEO_FORMAT_AYUV:
|
||||
/* not supported by FFmpeg */
|
||||
default:
|
||||
return AV_PIX_FMT_NONE;
|
||||
}
|
||||
|
||||
return AV_PIX_FMT_NONE;
|
||||
}
|
||||
|
||||
static inline int get_ffmpeg_scale_type(enum video_scale_type type)
|
||||
|
||||
@@ -909,6 +909,8 @@ convert_video_format(enum video_format format, enum video_trc trc)
|
||||
case VIDEO_FORMAT_I210:
|
||||
case VIDEO_FORMAT_I412:
|
||||
case VIDEO_FORMAT_YA2L:
|
||||
case VIDEO_FORMAT_P216:
|
||||
case VIDEO_FORMAT_P416:
|
||||
return GS_RGBA16F;
|
||||
default:
|
||||
return GS_BGRX;
|
||||
|
||||
@@ -729,6 +729,33 @@ static void set_gpu_converted_data(struct video_frame *output,
|
||||
|
||||
break;
|
||||
}
|
||||
case VIDEO_FORMAT_P216: {
|
||||
const uint32_t width_x2 = info->width * 2;
|
||||
const uint32_t height = info->height;
|
||||
|
||||
set_gpu_converted_plane(width_x2, height, input->linesize[0],
|
||||
output->linesize[0], input->data[0],
|
||||
output->data[0]);
|
||||
|
||||
set_gpu_converted_plane(width_x2, height, input->linesize[1],
|
||||
output->linesize[1], input->data[1],
|
||||
output->data[1]);
|
||||
|
||||
break;
|
||||
}
|
||||
case VIDEO_FORMAT_P416: {
|
||||
const uint32_t height = info->height;
|
||||
|
||||
set_gpu_converted_plane(info->width * 2, height,
|
||||
input->linesize[0], output->linesize[0],
|
||||
input->data[0], output->data[0]);
|
||||
|
||||
set_gpu_converted_plane(info->width * 4, height,
|
||||
input->linesize[1], output->linesize[1],
|
||||
input->data[1], output->data[1]);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case VIDEO_FORMAT_NONE:
|
||||
case VIDEO_FORMAT_YVYU:
|
||||
|
||||
84
libobs/obs.c
84
libobs/obs.c
@@ -109,6 +109,36 @@ static inline void calc_gpu_conversion_sizes(struct obs_core_video_mix *video)
|
||||
video->conversion_techs[1] = "P010_SRGB_UV";
|
||||
}
|
||||
break;
|
||||
case VIDEO_FORMAT_P216:
|
||||
video->conversion_needed = true;
|
||||
video->conversion_width_i = 1.f / (float)info->width;
|
||||
video->conversion_height_i = 1.f / (float)info->height;
|
||||
if (info->colorspace == VIDEO_CS_2100_PQ) {
|
||||
video->conversion_techs[0] = "P216_PQ_Y";
|
||||
video->conversion_techs[1] = "P216_PQ_UV";
|
||||
} else if (info->colorspace == VIDEO_CS_2100_HLG) {
|
||||
video->conversion_techs[0] = "P216_HLG_Y";
|
||||
video->conversion_techs[1] = "P216_HLG_UV";
|
||||
} else {
|
||||
video->conversion_techs[0] = "P216_SRGB_Y";
|
||||
video->conversion_techs[1] = "P216_SRGB_UV";
|
||||
}
|
||||
break;
|
||||
case VIDEO_FORMAT_P416:
|
||||
video->conversion_needed = true;
|
||||
video->conversion_width_i = 1.f / (float)info->width;
|
||||
video->conversion_height_i = 1.f / (float)info->height;
|
||||
if (info->colorspace == VIDEO_CS_2100_PQ) {
|
||||
video->conversion_techs[0] = "P416_PQ_Y";
|
||||
video->conversion_techs[1] = "P416_PQ_UV";
|
||||
} else if (info->colorspace == VIDEO_CS_2100_HLG) {
|
||||
video->conversion_techs[0] = "P416_HLG_Y";
|
||||
video->conversion_techs[1] = "P416_HLG_UV";
|
||||
} else {
|
||||
video->conversion_techs[0] = "P416_SRGB_Y";
|
||||
video->conversion_techs[1] = "P416_SRGB_UV";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -237,6 +267,26 @@ static bool obs_init_gpu_conversion(struct obs_core_video_mix *video)
|
||||
if (!video->convert_textures[0] || !video->convert_textures[1])
|
||||
success = false;
|
||||
break;
|
||||
case VIDEO_FORMAT_P216:
|
||||
video->convert_textures[0] =
|
||||
gs_texture_create(info->width, info->height, GS_R16, 1,
|
||||
NULL, GS_RENDER_TARGET);
|
||||
video->convert_textures[1] =
|
||||
gs_texture_create(info->width / 2, info->height,
|
||||
GS_RG16, 1, NULL, GS_RENDER_TARGET);
|
||||
if (!video->convert_textures[0] || !video->convert_textures[1])
|
||||
success = false;
|
||||
break;
|
||||
case VIDEO_FORMAT_P416:
|
||||
video->convert_textures[0] =
|
||||
gs_texture_create(info->width, info->height, GS_R16, 1,
|
||||
NULL, GS_RENDER_TARGET);
|
||||
video->convert_textures[1] =
|
||||
gs_texture_create(info->width, info->height, GS_RG16, 1,
|
||||
NULL, GS_RENDER_TARGET);
|
||||
if (!video->convert_textures[0] || !video->convert_textures[1])
|
||||
success = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -328,6 +378,26 @@ static bool obs_init_gpu_copy_surfaces(struct obs_core_video_mix *video,
|
||||
if (!video->copy_surfaces[i][1])
|
||||
return false;
|
||||
break;
|
||||
case VIDEO_FORMAT_P216:
|
||||
video->copy_surfaces[i][0] = gs_stagesurface_create(
|
||||
info->width, info->height, GS_R16);
|
||||
if (!video->copy_surfaces[i][0])
|
||||
return false;
|
||||
video->copy_surfaces[i][1] = gs_stagesurface_create(
|
||||
info->width / 2, info->height, GS_RG16);
|
||||
if (!video->copy_surfaces[i][1])
|
||||
return false;
|
||||
break;
|
||||
case VIDEO_FORMAT_P416:
|
||||
video->copy_surfaces[i][0] = gs_stagesurface_create(
|
||||
info->width, info->height, GS_R16);
|
||||
if (!video->copy_surfaces[i][0])
|
||||
return false;
|
||||
video->copy_surfaces[i][1] = gs_stagesurface_create(
|
||||
info->width, info->height, GS_RG16);
|
||||
if (!video->copy_surfaces[i][1])
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -349,6 +419,8 @@ static bool obs_init_textures(struct obs_core_video_mix *video)
|
||||
case VIDEO_FORMAT_I210:
|
||||
case VIDEO_FORMAT_I412:
|
||||
case VIDEO_FORMAT_YA2L:
|
||||
case VIDEO_FORMAT_P216:
|
||||
case VIDEO_FORMAT_P416:
|
||||
format = GS_RGBA16F;
|
||||
break;
|
||||
default:
|
||||
@@ -398,9 +470,17 @@ static bool obs_init_textures(struct obs_core_video_mix *video)
|
||||
space = GS_CS_709_EXTENDED;
|
||||
break;
|
||||
default:
|
||||
if (info->format == VIDEO_FORMAT_I010 ||
|
||||
info->format == VIDEO_FORMAT_P010)
|
||||
switch (info->format) {
|
||||
case VIDEO_FORMAT_I010:
|
||||
case VIDEO_FORMAT_P010:
|
||||
case VIDEO_FORMAT_P216:
|
||||
case VIDEO_FORMAT_P416:
|
||||
space = GS_CS_SRGB_16F;
|
||||
break;
|
||||
default:
|
||||
space = GS_CS_SRGB;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -56,6 +56,12 @@ obs_to_ffmpeg_video_format(enum video_format format)
|
||||
return AV_PIX_FMT_YUV420P10LE;
|
||||
case VIDEO_FORMAT_P010:
|
||||
return AV_PIX_FMT_P010LE;
|
||||
#if LIBAVUTIL_BUILD >= AV_VERSION_INT(57, 17, 100)
|
||||
case VIDEO_FORMAT_P216:
|
||||
return AV_PIX_FMT_P216LE;
|
||||
case VIDEO_FORMAT_P416:
|
||||
return AV_PIX_FMT_P416LE;
|
||||
#endif
|
||||
case VIDEO_FORMAT_NONE:
|
||||
case VIDEO_FORMAT_AYUV:
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user