libobs: Add support for YUV422P10LE, YUV444P12LE, YUVA444P12LE

master
mvji 2022-04-19 19:37:07 +02:00
parent 4c96feafab
commit d3a8ef7128
9 changed files with 261 additions and 1 deletions

View File

@ -501,6 +501,19 @@ float3 PSPlanar422_Reverse(FragPosWide frag_in) : TARGET
return rgb;
}
float4 PSPlanar422_10LE_Reverse(FragPosWide frag_in) : TARGET
{
float y = image.Load(int3(frag_in.pos_wide.xz, 0)).x;
int3 xy0_chroma = int3(frag_in.pos_wide.yz, 0);
float cb = image1.Load(xy0_chroma).x;
float cr = image2.Load(xy0_chroma).x;
float3 yuv = float3(y, cb, cr);
yuv *= 65535. / 1023.;
float3 rgb = YUV_to_RGB(yuv);
rgb = srgb_nonlinear_to_linear(rgb);
return float4(rgb, 1.0);
}
float4 PSPlanar422A_Reverse(FragPosWide frag_in) : TARGET
{
int3 xy0_luma = int3(frag_in.pos_wide.xz, 0);
@ -525,6 +538,19 @@ float3 PSPlanar444_Reverse(FragPos frag_in) : TARGET
return rgb;
}
float4 PSPlanar444_12LE_Reverse(FragPos frag_in) : TARGET
{
int3 xy0 = int3(frag_in.pos.xy, 0);
float y = image.Load(xy0).x;
float cb = image1.Load(xy0).x;
float cr = image2.Load(xy0).x;
float3 yuv = float3(y, cb, cr);
yuv *= 65535. / 4095.;
float3 rgb = YUV_to_RGB(yuv);
rgb = srgb_nonlinear_to_linear(rgb);
return float4(rgb, 1.0);
}
float4 PSPlanar444A_Reverse(FragPos frag_in) : TARGET
{
int3 xy0 = int3(frag_in.pos.xy, 0);
@ -537,6 +563,20 @@ float4 PSPlanar444A_Reverse(FragPos frag_in) : TARGET
return rgba;
}
float4 PSPlanar444A_12LE_Reverse(FragPos frag_in) : TARGET
{
int3 xy0 = int3(frag_in.pos.xy, 0);
float y = image.Load(xy0).x;
float cb = image1.Load(xy0).x;
float cr = image2.Load(xy0).x;
float alpha = image3.Load(xy0).x * 16.;
float3 yuv = float3(y, cb, cr);
yuv *= 65535. / 4095.;
float3 rgb = YUV_to_RGB(yuv);
rgb = srgb_nonlinear_to_linear(rgb);
return float4(rgb, alpha);
}
float4 PSAYUV_Reverse(FragPos frag_in) : TARGET
{
float4 yuva = image.Load(int3(frag_in.pos.xy, 0));
@ -921,6 +961,15 @@ technique I422_Reverse
}
}
technique I210_Reverse
{
pass
{
vertex_shader = VSPosWide_Reverse(id);
pixel_shader = PSPlanar422_10LE_Reverse(frag_in);
}
}
technique I42A_Reverse
{
pass
@ -939,6 +988,15 @@ technique I444_Reverse
}
}
technique I412_Reverse
{
pass
{
vertex_shader = VSPos(id);
pixel_shader = PSPlanar444_12LE_Reverse(frag_in);
}
}
technique YUVA_Reverse
{
pass
@ -948,6 +1006,15 @@ technique YUVA_Reverse
}
}
technique YA2L_Reverse
{
pass
{
vertex_shader = VSPos(id);
pixel_shader = PSPlanar444A_12LE_Reverse(frag_in);
}
}
technique AYUV_Reverse
{
pass

View File

@ -112,6 +112,17 @@ void video_frame_init(struct video_frame *frame, enum video_format format,
frame->linesize[2] = width;
break;
case VIDEO_FORMAT_I412:
size = width * height * 2;
ALIGN_SIZE(size, alignment);
frame->data[0] = bmalloc(size * 3);
frame->data[1] = (uint8_t *)frame->data[0] + size;
frame->data[2] = (uint8_t *)frame->data[1] + size;
frame->linesize[0] = width * 2;
frame->linesize[1] = width * 2;
frame->linesize[2] = width * 2;
break;
case VIDEO_FORMAT_BGR3:
size = width * height * 3;
ALIGN_SIZE(size, alignment);
@ -139,6 +150,27 @@ void video_frame_init(struct video_frame *frame, enum video_format format,
break;
}
case VIDEO_FORMAT_I210: {
size = width * height * 2;
ALIGN_SIZE(size, alignment);
offsets[0] = size;
const uint32_t half_width = (width + 1) / 2;
const uint32_t half_area = half_width * height;
const uint32_t half_area_size = 2 * half_area;
size += half_area_size;
ALIGN_SIZE(size, alignment);
offsets[1] = size;
size += half_area_size;
ALIGN_SIZE(size, alignment);
frame->data[0] = bmalloc(size);
frame->data[1] = (uint8_t *)frame->data[0] + offsets[0];
frame->data[2] = (uint8_t *)frame->data[0] + offsets[1];
frame->linesize[0] = width * 2;
frame->linesize[1] = half_width * 2;
frame->linesize[2] = half_width * 2;
break;
}
case VIDEO_FORMAT_I40A: {
size = width * height;
ALIGN_SIZE(size, alignment);
@ -212,6 +244,31 @@ void video_frame_init(struct video_frame *frame, enum video_format format,
frame->linesize[3] = width;
break;
case VIDEO_FORMAT_YA2L: {
const uint32_t linesize = width * 2;
const uint32_t plane_size = linesize * height;
size = plane_size;
ALIGN_SIZE(size, alignment);
offsets[0] = size;
size += plane_size;
ALIGN_SIZE(size, alignment);
offsets[1] = size;
size += plane_size;
ALIGN_SIZE(size, alignment);
offsets[2] = size;
size += plane_size;
ALIGN_SIZE(size, alignment);
frame->data[0] = bmalloc(size);
frame->data[1] = (uint8_t *)frame->data[0] + offsets[0];
frame->data[2] = (uint8_t *)frame->data[0] + offsets[1];
frame->data[3] = (uint8_t *)frame->data[0] + offsets[2];
frame->linesize[0] = linesize;
frame->linesize[1] = linesize;
frame->linesize[2] = linesize;
frame->linesize[3] = linesize;
break;
}
case VIDEO_FORMAT_I010: {
size = width * height * 2;
ALIGN_SIZE(size, alignment);
@ -283,6 +340,8 @@ void video_frame_copy(struct video_frame *dst, const struct video_frame *src,
case VIDEO_FORMAT_I444:
case VIDEO_FORMAT_I422:
case VIDEO_FORMAT_I210:
case VIDEO_FORMAT_I412:
memcpy(dst->data[0], src->data[0], src->linesize[0] * cy);
memcpy(dst->data[1], src->data[1], src->linesize[1] * cy);
memcpy(dst->data[2], src->data[2], src->linesize[2] * cy);
@ -297,6 +356,7 @@ void video_frame_copy(struct video_frame *dst, const struct video_frame *src,
case VIDEO_FORMAT_I42A:
case VIDEO_FORMAT_YUVA:
case VIDEO_FORMAT_YA2L:
memcpy(dst->data[0], src->data[0], src->linesize[0] * cy);
memcpy(dst->data[1], src->data[1], src->linesize[1] * cy);
memcpy(dst->data[2], src->data[2], src->linesize[2] * cy);

View File

@ -73,6 +73,15 @@ enum video_format {
/* 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 10 bits */
VIDEO_FORMAT_I210, // Little Endian
/* planar 4:4:4 12 bits */
VIDEO_FORMAT_I412, // Little Endian
/* planar 4:4:4 12 bits with alpha */
VIDEO_FORMAT_YA2L, // Little Endian
};
enum video_trc {
@ -123,13 +132,16 @@ static inline bool format_is_yuv(enum video_format format)
case VIDEO_FORMAT_I420:
case VIDEO_FORMAT_NV12:
case VIDEO_FORMAT_I422:
case VIDEO_FORMAT_I210:
case VIDEO_FORMAT_YVYU:
case VIDEO_FORMAT_YUY2:
case VIDEO_FORMAT_UYVY:
case VIDEO_FORMAT_I444:
case VIDEO_FORMAT_I412:
case VIDEO_FORMAT_I40A:
case VIDEO_FORMAT_I42A:
case VIDEO_FORMAT_YUVA:
case VIDEO_FORMAT_YA2L:
case VIDEO_FORMAT_AYUV:
case VIDEO_FORMAT_I010:
case VIDEO_FORMAT_P010:
@ -155,6 +167,8 @@ static inline const char *get_video_format_name(enum video_format format)
return "NV12";
case VIDEO_FORMAT_I422:
return "I422";
case VIDEO_FORMAT_I210:
return "I210";
case VIDEO_FORMAT_YVYU:
return "YVYU";
case VIDEO_FORMAT_YUY2:
@ -169,6 +183,8 @@ static inline const char *get_video_format_name(enum video_format format)
return "BGRX";
case VIDEO_FORMAT_I444:
return "I444";
case VIDEO_FORMAT_I412:
return "I412";
case VIDEO_FORMAT_Y800:
return "Y800";
case VIDEO_FORMAT_BGR3:
@ -179,6 +195,8 @@ static inline const char *get_video_format_name(enum video_format format)
return "I42A";
case VIDEO_FORMAT_YUVA:
return "YUVA";
case VIDEO_FORMAT_YA2L:
return "YA2L";
case VIDEO_FORMAT_AYUV:
return "AYUV";
case VIDEO_FORMAT_I010:

View File

@ -264,7 +264,13 @@ bool video_format_get_parameters_for_format(enum video_colorspace color_space,
switch (format) {
case VIDEO_FORMAT_I010:
case VIDEO_FORMAT_P010:
case VIDEO_FORMAT_I210:
bpc = 10;
break;
case VIDEO_FORMAT_I412:
case VIDEO_FORMAT_YA2L:
bpc = 12;
break;
}
return video_format_get_parameters_for_bpc(color_space, range, matrix,

View File

@ -51,16 +51,26 @@ get_ffmpeg_video_format(enum video_format format)
return AV_PIX_FMT_GRAY8;
case VIDEO_FORMAT_I444:
return AV_PIX_FMT_YUV444P;
case VIDEO_FORMAT_I412:
return AV_PIX_FMT_YUV444P12LE;
case VIDEO_FORMAT_BGR3:
return AV_PIX_FMT_BGR24;
case VIDEO_FORMAT_I422:
return AV_PIX_FMT_YUV422P;
case VIDEO_FORMAT_I210:
return AV_PIX_FMT_YUV422P10LE;
case VIDEO_FORMAT_I40A:
return AV_PIX_FMT_YUVA420P;
case VIDEO_FORMAT_I42A:
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)
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:

View File

@ -890,6 +890,9 @@ convert_video_format(enum video_format format)
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;

View File

@ -1548,10 +1548,13 @@ enum convert_type {
CONVERT_420,
CONVERT_420_A,
CONVERT_422,
CONVERT_422P10LE,
CONVERT_422_A,
CONVERT_422_PACK,
CONVERT_444,
CONVERT_444P12LE,
CONVERT_444_A,
CONVERT_444P12LE_A,
CONVERT_444_A_PACK,
CONVERT_800,
CONVERT_RGB_LIMITED,
@ -1574,8 +1577,12 @@ static inline enum convert_type get_convert_type(enum video_format format,
return CONVERT_NV12;
case VIDEO_FORMAT_I444:
return CONVERT_444;
case VIDEO_FORMAT_I412:
return CONVERT_444P12LE;
case VIDEO_FORMAT_I422:
return CONVERT_422;
case VIDEO_FORMAT_I210:
return CONVERT_422P10LE;
case VIDEO_FORMAT_YVYU:
case VIDEO_FORMAT_YUY2:
@ -1603,6 +1610,9 @@ static inline enum convert_type get_convert_type(enum video_format format,
case VIDEO_FORMAT_YUVA:
return CONVERT_444_A;
case VIDEO_FORMAT_YA2L:
return CONVERT_444P12LE_A;
case VIDEO_FORMAT_AYUV:
return CONVERT_444_A_PACK;
@ -1672,6 +1682,22 @@ static inline bool set_planar444_sizes(struct obs_source *source,
return true;
}
static inline bool set_planar444_16_sizes(struct obs_source *source,
const struct obs_source_frame *frame)
{
source->async_convert_width[0] = frame->width;
source->async_convert_width[1] = frame->width;
source->async_convert_width[2] = frame->width;
source->async_convert_height[0] = frame->height;
source->async_convert_height[1] = frame->height;
source->async_convert_height[2] = frame->height;
source->async_texture_formats[0] = GS_R16;
source->async_texture_formats[1] = GS_R16;
source->async_texture_formats[2] = GS_R16;
source->async_channel_count = 3;
return true;
}
static inline bool
set_planar444_alpha_sizes(struct obs_source *source,
const struct obs_source_frame *frame)
@ -1692,6 +1718,26 @@ set_planar444_alpha_sizes(struct obs_source *source,
return true;
}
static inline bool
set_planar444_16_alpha_sizes(struct obs_source *source,
const struct obs_source_frame *frame)
{
source->async_convert_width[0] = frame->width;
source->async_convert_width[1] = frame->width;
source->async_convert_width[2] = frame->width;
source->async_convert_width[3] = frame->width;
source->async_convert_height[0] = frame->height;
source->async_convert_height[1] = frame->height;
source->async_convert_height[2] = frame->height;
source->async_convert_height[3] = frame->height;
source->async_texture_formats[0] = GS_R16;
source->async_texture_formats[1] = GS_R16;
source->async_texture_formats[2] = GS_R16;
source->async_texture_formats[3] = GS_R16;
source->async_channel_count = 4;
return true;
}
static inline bool set_planar420_sizes(struct obs_source *source,
const struct obs_source_frame *frame)
{
@ -1754,6 +1800,24 @@ static inline bool set_planar422_sizes(struct obs_source *source,
source->async_channel_count = 3;
return true;
}
static inline bool set_planar422_16_sizes(struct obs_source *source,
const struct obs_source_frame *frame)
{
const uint32_t width = frame->width;
const uint32_t height = frame->height;
const uint32_t half_width = (width + 1) / 2;
source->async_convert_width[0] = width;
source->async_convert_width[1] = half_width;
source->async_convert_width[2] = half_width;
source->async_convert_height[0] = height;
source->async_convert_height[1] = height;
source->async_convert_height[2] = height;
source->async_texture_formats[0] = GS_R16;
source->async_texture_formats[1] = GS_R16;
source->async_texture_formats[2] = GS_R16;
source->async_channel_count = 3;
return true;
}
static inline bool
set_planar422_alpha_sizes(struct obs_source *source,
@ -1876,12 +1940,18 @@ static inline bool init_gpu_conversion(struct obs_source *source,
case CONVERT_422:
return set_planar422_sizes(source, frame);
case CONVERT_422P10LE:
return set_planar422_16_sizes(source, frame);
case CONVERT_NV12:
return set_nv12_sizes(source, frame);
case CONVERT_444:
return set_planar444_sizes(source, frame);
case CONVERT_444P12LE:
return set_planar444_16_sizes(source, frame);
case CONVERT_800:
return set_y800_sizes(source, frame);
@ -1900,6 +1970,9 @@ static inline bool init_gpu_conversion(struct obs_source *source,
case CONVERT_444_A:
return set_planar444_alpha_sizes(source, frame);
case CONVERT_444P12LE_A:
return set_planar444_16_alpha_sizes(source, frame);
case CONVERT_444_A_PACK:
return set_packed444_alpha_sizes(source, frame);
@ -1992,11 +2065,14 @@ static void upload_raw_frame(gs_texture_t *tex[MAX_AV_PLANES],
case CONVERT_BGR3:
case CONVERT_420:
case CONVERT_422:
case CONVERT_422P10LE:
case CONVERT_NV12:
case CONVERT_444:
case CONVERT_444P12LE:
case CONVERT_420_A:
case CONVERT_422_A:
case CONVERT_444_A:
case CONVERT_444P12LE_A:
case CONVERT_444_A_PACK:
case CONVERT_I010_SRGB:
case CONVERT_I010_PQ_2020_709:
@ -2039,6 +2115,9 @@ static const char *select_conversion_technique(enum video_format format,
case VIDEO_FORMAT_I444:
return "I444_Reverse";
case VIDEO_FORMAT_I412:
return "I412_Reverse";
case VIDEO_FORMAT_Y800:
return full_range ? "Y800_Full" : "Y800_Limited";
@ -2048,6 +2127,9 @@ static const char *select_conversion_technique(enum video_format format,
case VIDEO_FORMAT_I422:
return "I422_Reverse";
case VIDEO_FORMAT_I210:
return "I210_Reverse";
case VIDEO_FORMAT_I40A:
return "I40A_Reverse";
@ -2057,6 +2139,9 @@ static const char *select_conversion_technique(enum video_format format,
case VIDEO_FORMAT_YUVA:
return "YUVA_Reverse";
case VIDEO_FORMAT_YA2L:
return "YA2L_Reverse";
case VIDEO_FORMAT_AYUV:
return "AYUV_Reverse";
@ -2097,7 +2182,9 @@ static const char *select_conversion_technique(enum video_format format,
static bool need_linear_output(enum video_format format)
{
return (format == VIDEO_FORMAT_I010) || (format == VIDEO_FORMAT_P010);
return (format == VIDEO_FORMAT_I010) || (format == VIDEO_FORMAT_P010) ||
(format == VIDEO_FORMAT_I210) || (format == VIDEO_FORMAT_I412) ||
(format == VIDEO_FORMAT_YA2L);
}
static inline void set_eparam(gs_effect_t *effect, const char *name, float val)
@ -3192,6 +3279,8 @@ static void copy_frame_data(struct obs_source_frame *dst,
case VIDEO_FORMAT_I444:
case VIDEO_FORMAT_I422:
case VIDEO_FORMAT_I210:
case VIDEO_FORMAT_I412:
copy_frame_data_plane(dst, src, 0, dst->height);
copy_frame_data_plane(dst, src, 1, dst->height);
copy_frame_data_plane(dst, src, 2, dst->height);
@ -3222,6 +3311,7 @@ static void copy_frame_data(struct obs_source_frame *dst,
case VIDEO_FORMAT_I42A:
case VIDEO_FORMAT_YUVA:
case VIDEO_FORMAT_YA2L:
copy_frame_data_plane(dst, src, 0, dst->height);
copy_frame_data_plane(dst, src, 1, dst->height);
copy_frame_data_plane(dst, src, 2, dst->height);

View File

@ -727,10 +727,13 @@ static void set_gpu_converted_data(struct obs_core_video *video,
case VIDEO_FORMAT_BGRX:
case VIDEO_FORMAT_Y800:
case VIDEO_FORMAT_BGR3:
case VIDEO_FORMAT_I412:
case VIDEO_FORMAT_I422:
case VIDEO_FORMAT_I210:
case VIDEO_FORMAT_I40A:
case VIDEO_FORMAT_I42A:
case VIDEO_FORMAT_YUVA:
case VIDEO_FORMAT_YA2L:
case VIDEO_FORMAT_AYUV:
/* unimplemented */
;

View File

@ -379,6 +379,9 @@ static bool obs_init_textures(struct obs_video_info *ovi)
switch (ovi->output_format) {
case VIDEO_FORMAT_I010:
case VIDEO_FORMAT_P010:
case VIDEO_FORMAT_I210:
case VIDEO_FORMAT_I412:
case VIDEO_FORMAT_YA2L:
format = GS_RGBA16F;
}