d3d11converter: Add support for premultiplied alpha

Adding "src-alpha-mode" and "dest-alpha-mode" properties
and performs premultiplied alpha conversion if needed

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4825>
This commit is contained in:
Seungha Yang 2023-06-10 02:52:09 +09:00 committed by GStreamer Marge Bot
parent 04bcff4dce
commit 15735a4ef3
2 changed files with 130 additions and 1 deletions

View file

@ -91,6 +91,27 @@ gst_d3d11_converter_sampler_filter_get_type (void)
return filter_type;
}
GType
gst_d3d11_converter_alpha_mode_get_type (void)
{
static GType type = 0;
static const GEnumValue alpha_mode[] = {
{GST_D3D11_CONVERTER_ALPHA_MODE_UNSPECIFIED,
"GST_D3D11_CONVERTER_ALPHA_MODE_UNSPECIFIED", "unspecified"},
{GST_D3D11_CONVERTER_ALPHA_MODE_PREMULTIPLIED,
"GST_D3D11_CONVERTER_ALPHA_MODE_PREMULTIPLIED", "premultiplied"},
{GST_D3D11_CONVERTER_ALPHA_MODE_STRAIGHT,
"GST_D3D11_CONVERTER_ALPHA_MODE_STRAIGHT", "straight"},
{0, nullptr, nullptr},
};
GST_D3D11_CALL_ONCE_BEGIN {
type = g_enum_register_static ("GstD3D11ConverterAlphaMode", alpha_mode);
} GST_D3D11_CALL_ONCE_END;
return type;
}
/* *INDENT-OFF* */
using namespace Microsoft::WRL;
/* *INDENT-ON* */
@ -124,7 +145,9 @@ typedef struct
PSColorSpace to_yuv_buf;
PSColorSpace XYZ_convert_buf;
FLOAT alpha;
FLOAT padding[3];
DWORD in_premul_alpha;
DWORD out_premul_alpha;
FLOAT padding;
} PSConstBuffer;
typedef struct
@ -525,6 +548,8 @@ static const gchar templ_pixel_shader[] =
" PSColorSpace toYUVCoeff;\n"
" PSColorSpace primariesCoeff;\n"
" float AlphaMul;\n"
" dword InPremulAlpha;\n"
" dword OutPremulAlpha;\n"
"};\n"
"Texture2D shaderTexture[4] : register(t0);\n"
"Texture1D<float> gammaDecLUT: register(t4);\n"
@ -551,16 +576,40 @@ static const gchar templ_pixel_shader[] =
"%s\n"
/* XYZ_convert() function */
"%s\n"
"float4 alpha_premul (float4 sample)\n"
"{\n"
" float4 premul_tex;\n"
" premul_tex.r = sample.r * sample.a;\n"
" premul_tex.g = sample.g * sample.a;\n"
" premul_tex.b = sample.b * sample.a;\n"
" premul_tex.a = sample.a;\n"
" return premul_tex;\n"
"}\n"
"float4 alpha_unpremul (float4 sample)\n"
"{\n"
" float4 unpremul_tex;\n"
" if (sample.a == 0 || sample.a == 1)\n"
" return sample;\n"
" unpremul_tex.r = saturate (sample.r / sample.a);\n"
" unpremul_tex.g = saturate (sample.g / sample.a);\n"
" unpremul_tex.b = saturate (sample.b / sample.a);\n"
" unpremul_tex.a = sample.a;\n"
" return unpremul_tex;\n"
"}\n"
"PS_OUTPUT main(PS_INPUT input)\n"
"{\n"
" float4 sample;\n"
" sample = sample_texture (input.Texture);\n"
" if (InPremulAlpha)\n"
" sample = alpha_unpremul (sample);\n"
" sample.a = saturate (sample.a * AlphaMul);\n"
" sample.xyz = to_rgb (sample.xyz, toRGBCoeff);\n"
" sample.xyz = gamma_decode (sample.xyz);\n"
" sample.xyz = XYZ_convert (sample.xyz);\n"
" sample.xyz = gamma_encode (sample.xyz);\n"
" sample.xyz = to_yuv (sample.xyz, toYUVCoeff);\n"
" if (OutPremulAlpha)\n"
" sample = alpha_premul (sample);\n"
" return build_output (sample);\n"
"}\n";
@ -620,6 +669,8 @@ enum
PROP_DEST_MASTERING_DISPLAY_INFO,
PROP_DEST_CONTENT_LIGHT_LEVEL,
PROP_VIDEO_DIRECTION,
PROP_SRC_ALPHA_MODE,
PROP_DEST_ALPHA_MODE,
};
struct _GstD3D11ConverterPrivate
@ -727,6 +778,8 @@ struct _GstD3D11ConverterPrivate
guint blend_sample_mask;
gboolean fill_border;
guint64 border_color;
GstD3D11ConverterAlphaMode src_alpha_mode;
GstD3D11ConverterAlphaMode dst_alpha_mode;
};
static void gst_d3d11_converter_set_property (GObject * object, guint prop_id,
@ -837,6 +890,14 @@ gst_d3d11_converter_class_init (GstD3D11ConverterClass * klass)
g_param_spec_enum ("video-direction", "Video Direction",
"Video direction", GST_TYPE_VIDEO_ORIENTATION_METHOD,
GST_VIDEO_ORIENTATION_IDENTITY, param_flags));
g_object_class_install_property (object_class, PROP_SRC_ALPHA_MODE,
g_param_spec_enum ("src-alpha-mode", "Src Alpha Mode",
"Src alpha mode to use", GST_TYPE_D3D11_CONVERTER_ALPHA_MODE,
GST_D3D11_CONVERTER_ALPHA_MODE_UNSPECIFIED, param_flags));
g_object_class_install_property (object_class, PROP_DEST_ALPHA_MODE,
g_param_spec_enum ("dest-alpha-mode", "Dest Alpha Mode",
"Dest alpha mode to use", GST_TYPE_D3D11_CONVERTER_ALPHA_MODE,
GST_D3D11_CONVERTER_ALPHA_MODE_UNSPECIFIED, param_flags));
GST_DEBUG_CATEGORY_INIT (gst_d3d11_converter_debug,
"d3d11converter", 0, "d3d11converter");
@ -847,6 +908,8 @@ gst_d3d11_converter_init (GstD3D11Converter * self)
{
self->priv = (GstD3D11ConverterPrivate *)
gst_d3d11_converter_get_instance_private (self);
self->priv->src_alpha_mode = self->priv->dst_alpha_mode =
GST_D3D11_CONVERTER_ALPHA_MODE_UNSPECIFIED;
}
static void
@ -1056,6 +1119,38 @@ gst_d3d11_converter_set_property (GObject * object, guint prop_id,
}
break;
}
case PROP_SRC_ALPHA_MODE:
{
DWORD prev_premul = priv->const_data.in_premul_alpha;
priv->src_alpha_mode = (GstD3D11ConverterAlphaMode)
g_value_get_enum (value);
if (priv->src_alpha_mode == GST_D3D11_CONVERTER_ALPHA_MODE_PREMULTIPLIED) {
priv->const_data.in_premul_alpha = TRUE;
} else {
priv->const_data.in_premul_alpha = FALSE;
}
if (prev_premul != priv->const_data.in_premul_alpha) {
priv->update_alpha = TRUE;
}
break;
}
case PROP_DEST_ALPHA_MODE:
{
DWORD prev_premul = priv->const_data.out_premul_alpha;
priv->dst_alpha_mode = (GstD3D11ConverterAlphaMode)
g_value_get_enum (value);
if (priv->dst_alpha_mode == GST_D3D11_CONVERTER_ALPHA_MODE_PREMULTIPLIED) {
priv->const_data.out_premul_alpha = TRUE;
} else {
priv->const_data.out_premul_alpha = FALSE;
}
if (prev_premul != priv->const_data.out_premul_alpha) {
priv->update_alpha = TRUE;
}
break;
}
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -1137,6 +1232,12 @@ gst_d3d11_converter_get_property (GObject * object, guint prop_id,
case PROP_VIDEO_DIRECTION:
g_value_set_enum (value, priv->video_direction);
break;
case PROP_SRC_ALPHA_MODE:
g_value_set_enum (value, priv->src_alpha_mode);
break;
case PROP_DEST_ALPHA_MODE:
g_value_set_enum (value, priv->dst_alpha_mode);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -4176,6 +4277,13 @@ gst_d3d11_converter_convert_buffer_internal (GstD3D11Converter * self,
if ((priv->supported_backend & GST_D3D11_CONVERTER_BACKEND_SHADER) == 0) {
/* processor only */
use_processor = TRUE;
} else if ((priv->src_alpha_mode ==
GST_D3D11_CONVERTER_ALPHA_MODE_PREMULTIPLIED ||
priv->dst_alpha_mode ==
GST_D3D11_CONVERTER_ALPHA_MODE_PREMULTIPLIED)
&& GST_VIDEO_INFO_HAS_ALPHA (&priv->in_info)) {
/* Needs alpha conversion */
use_processor = FALSE;
} else if (piv_available) {
in_dmem = (GstD3D11Memory *) gst_buffer_peek_memory (in_buf, 0);

View file

@ -101,6 +101,27 @@ GST_D3D11_API
GType gst_d3d11_converter_sampler_filter_get_type (void);
#define GST_TYPE_D3D11_CONVERTER_SAMPLER_FILTER (gst_d3d11_converter_sampler_filter_get_type())
/**
* GstD3D11ConverterAlphaMode:
* @GST_D3D11_CONVERTER_ALPHA_MODE_UNSPECIFIED: Unspecified alpha mode
* @GST_D3D11_CONVERTER_ALPHA_MODE_PREMULTIPLIED: Premultiplied alpha
* @GST_D3D11_CONVERTER_ALPHA_MODE_STRAIGHT: Straight alpha
*
* Alpha mode. Enum values are idnetical to DXGI_ALPHA_MODE
*
* Since: 1.24
*/
typedef enum
{
GST_D3D11_CONVERTER_ALPHA_MODE_UNSPECIFIED = 0,
GST_D3D11_CONVERTER_ALPHA_MODE_PREMULTIPLIED = 1,
GST_D3D11_CONVERTER_ALPHA_MODE_STRAIGHT = 2,
} GstD3D11ConverterAlphaMode;
GST_D3D11_API
GType gst_d3d11_converter_alpha_mode_get_type (void);
#define GST_TYPE_D3D11_CONVERTER_ALPHA_MODE (gst_d3d11_converter_alpha_mode_get_type())
/**
* GstD3D11Converter:
*