mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-11 02:24:13 +00:00
d3d11converter: Implement filling border color
Equivalent to GST_VIDEO_CONVERTER_OPT_BORDER_ARGB and GST_VIDEO_CONVERTER_OPT_FILL_BORDER options of GstVideoConverter Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2622>
This commit is contained in:
parent
59f39724b7
commit
461416b5f1
2 changed files with 181 additions and 12 deletions
|
@ -1894,6 +1894,9 @@ gst_d3d11_base_convert_set_info (GstD3D11BaseFilter * filter,
|
|||
"dest-height", (gint) (self->out_rect.bottom - self->out_rect.top),
|
||||
nullptr);
|
||||
|
||||
if (self->borders_w > 0 || self->borders_h > 0)
|
||||
g_object_set (self->converter, "fill-border", TRUE, nullptr);
|
||||
|
||||
return TRUE;
|
||||
|
||||
/* ERRORS */
|
||||
|
@ -2120,15 +2123,6 @@ gst_d3d11_base_convert_transform (GstBaseTransform * trans,
|
|||
target_rtv = render_view;
|
||||
}
|
||||
|
||||
/* We need to clear background color as our shader wouldn't touch border
|
||||
* area. Likely output texture was initialized with zeros which is fine for
|
||||
* RGB, but it's not black color in case of YUV */
|
||||
if (self->borders_w || self->borders_h) {
|
||||
gst_d3d11_device_lock (device);
|
||||
clear_rtv_color_all (self, &filter->out_info, context_handle, target_rtv);
|
||||
gst_d3d11_device_unlock (device);
|
||||
}
|
||||
|
||||
if (!gst_d3d11_converter_convert (self->converter,
|
||||
copy_input ? self->shader_resource_view : resource_view,
|
||||
target_rtv)) {
|
||||
|
|
|
@ -501,6 +501,8 @@ enum
|
|||
PROP_BLEND_FACTOR_BLUE,
|
||||
PROP_BLEND_FACTOR_ALPHA,
|
||||
PROP_BLEND_SAMPLE_MASK,
|
||||
PROP_FILL_BORDER,
|
||||
PROP_BORDER_COLOR,
|
||||
};
|
||||
|
||||
struct _GstD3D11ConverterPrivate
|
||||
|
@ -539,6 +541,10 @@ struct _GstD3D11ConverterPrivate
|
|||
ConvertInfo convert_info;
|
||||
PSConstBuffer const_data;
|
||||
|
||||
gboolean clear_background;
|
||||
FLOAT clear_color[4][4];
|
||||
GstD3D11ColorMatrix clear_color_matrix;
|
||||
|
||||
GMutex prop_lock;
|
||||
|
||||
/* properties */
|
||||
|
@ -553,6 +559,8 @@ struct _GstD3D11ConverterPrivate
|
|||
gdouble alpha;
|
||||
gfloat blend_factor[4];
|
||||
guint blend_sample_mask;
|
||||
gboolean fill_border;
|
||||
guint64 border_color;
|
||||
};
|
||||
|
||||
static void gst_d3d11_converter_set_property (GObject * object, guint prop_id,
|
||||
|
@ -561,6 +569,8 @@ static void gst_d3d11_converter_get_property (GObject * object, guint prop_id,
|
|||
GValue * value, GParamSpec * pspec);
|
||||
static void gst_d3d11_converter_dispose (GObject * object);
|
||||
static void gst_d3d11_converter_finalize (GObject * object);
|
||||
static void
|
||||
gst_d3d11_converter_calculate_border_color (GstD3D11Converter * self);
|
||||
|
||||
#define gst_d3d11_converter_parent_class parent_class
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GstD3D11Converter, gst_d3d11_converter,
|
||||
|
@ -627,6 +637,14 @@ gst_d3d11_converter_class_init (GstD3D11ConverterClass * klass)
|
|||
g_object_class_install_property (object_class, PROP_BLEND_SAMPLE_MASK,
|
||||
g_param_spec_uint ("blend-sample-mask", "Blend Sample Mask",
|
||||
"Blend sample mask", 0, 0xffffffff, 0xffffffff, param_flags));
|
||||
g_object_class_install_property (object_class, PROP_FILL_BORDER,
|
||||
g_param_spec_boolean ("fill-border", "Fill border",
|
||||
"Fill border with \"border-argb\" if destination rectangle does not "
|
||||
"fill the complete destination image", FALSE, param_flags));
|
||||
g_object_class_install_property (object_class, PROP_BORDER_COLOR,
|
||||
g_param_spec_uint64 ("border-color", "Border Color",
|
||||
"ARGB representation of the border color to use",
|
||||
0, G_MAXUINT64, 0xffff000000000000, param_flags));
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (gst_d3d11_converter_debug,
|
||||
"d3d11converter", 0, "d3d11converter");
|
||||
|
@ -785,6 +803,12 @@ gst_d3d11_converter_set_property (GObject * object, guint prop_id,
|
|||
case PROP_BLEND_SAMPLE_MASK:
|
||||
priv->blend_sample_mask = g_value_get_uint (value);
|
||||
break;
|
||||
case PROP_FILL_BORDER:
|
||||
priv->fill_border = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_BORDER_COLOR:
|
||||
priv->border_color = g_value_get_uint64 (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -846,6 +870,12 @@ gst_d3d11_converter_get_property (GObject * object, guint prop_id,
|
|||
case PROP_BLEND_SAMPLE_MASK:
|
||||
g_value_set_uint (value, priv->blend_sample_mask);
|
||||
break;
|
||||
case PROP_FILL_BORDER:
|
||||
g_value_set_boolean (value, priv->fill_border);
|
||||
break;
|
||||
case PROP_BORDER_COLOR:
|
||||
g_value_set_uint64 (value, priv->border_color);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -1280,6 +1310,7 @@ static gboolean
|
|||
gst_d3d11_converter_update_viewport (GstD3D11Converter * self)
|
||||
{
|
||||
GstD3D11ConverterPrivate *priv = self->priv;
|
||||
const GstVideoInfo *out_info = &priv->out_info;
|
||||
|
||||
priv->viewport[0].TopLeftX = priv->dest_x;
|
||||
priv->viewport[0].TopLeftY = priv->dest_y;
|
||||
|
@ -1291,6 +1322,16 @@ gst_d3d11_converter_update_viewport (GstD3D11Converter * self)
|
|||
priv->viewport[0].TopLeftX, priv->viewport[0].TopLeftY,
|
||||
priv->viewport[0].Width, priv->viewport[0].Height);
|
||||
|
||||
if (priv->fill_border && (priv->dest_x != 0 || priv->dest_y != 0 ||
|
||||
priv->dest_width != out_info->width ||
|
||||
priv->dest_height != out_info->height)) {
|
||||
GST_DEBUG_OBJECT (self, "Enable background color");
|
||||
priv->clear_background = TRUE;
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (self, "Disable background color");
|
||||
priv->clear_background = FALSE;
|
||||
}
|
||||
|
||||
switch (GST_VIDEO_INFO_FORMAT (&priv->out_info)) {
|
||||
case GST_VIDEO_FORMAT_NV12:
|
||||
case GST_VIDEO_FORMAT_NV21:
|
||||
|
@ -2161,6 +2202,110 @@ gst_d3d11_converter_setup_lut (GstD3D11Converter * self,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_d3d11_converter_calculate_border_color (GstD3D11Converter * self)
|
||||
{
|
||||
GstD3D11ConverterPrivate *priv = self->priv;
|
||||
GstD3D11ColorMatrix *m = &priv->clear_color_matrix;
|
||||
const GstVideoInfo *out_info = &priv->out_info;
|
||||
gdouble a;
|
||||
gdouble rgb[3];
|
||||
gdouble converted[3];
|
||||
GstVideoFormat format = GST_VIDEO_INFO_FORMAT (out_info);
|
||||
|
||||
a = ((priv->border_color & 0xffff000000000000) >> 48) / (gdouble) G_MAXUINT16;
|
||||
rgb[0] =
|
||||
((priv->border_color & 0x0000ffff00000000) >> 32) / (gdouble) G_MAXUINT16;
|
||||
rgb[1] =
|
||||
((priv->border_color & 0x00000000ffff0000) >> 16) / (gdouble) G_MAXUINT16;
|
||||
rgb[2] = (priv->border_color & 0x000000000000ffff) / (gdouble) G_MAXUINT16;
|
||||
|
||||
for (guint i = 0; i < 3; i++) {
|
||||
converted[i] = 0;
|
||||
for (guint j = 0; j < 3; j++) {
|
||||
converted[i] += m->matrix[i][j] * rgb[j];
|
||||
}
|
||||
converted[i] += m->offset[i];
|
||||
converted[i] = CLAMP (converted[i], m->min[i], m->max[i]);
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Calculated background color ARGB: %f, %f, %f, %f",
|
||||
a, converted[0], converted[1], converted[2]);
|
||||
|
||||
if (GST_VIDEO_INFO_IS_RGB (out_info) || GST_VIDEO_INFO_IS_GRAY (out_info)) {
|
||||
for (guint i = 0; i < 3; i++)
|
||||
priv->clear_color[0][i] = converted[i];
|
||||
priv->clear_color[0][3] = a;
|
||||
} else {
|
||||
switch (format) {
|
||||
case GST_VIDEO_FORMAT_VUYA:
|
||||
priv->clear_color[0][0] = converted[2];
|
||||
priv->clear_color[0][1] = converted[1];
|
||||
priv->clear_color[0][2] = converted[0];
|
||||
priv->clear_color[0][3] = a;
|
||||
break;
|
||||
case GST_VIDEO_FORMAT_AYUV:
|
||||
case GST_VIDEO_FORMAT_AYUV64:
|
||||
priv->clear_color[0][0] = a;
|
||||
priv->clear_color[0][1] = converted[0];
|
||||
priv->clear_color[0][2] = converted[1];
|
||||
priv->clear_color[0][3] = converted[2];
|
||||
break;
|
||||
case GST_VIDEO_FORMAT_NV12:
|
||||
case GST_VIDEO_FORMAT_NV21:
|
||||
case GST_VIDEO_FORMAT_P010_10LE:
|
||||
case GST_VIDEO_FORMAT_P012_LE:
|
||||
case GST_VIDEO_FORMAT_P016_LE:
|
||||
priv->clear_color[0][0] = converted[0];
|
||||
priv->clear_color[0][1] = 0;
|
||||
priv->clear_color[0][2] = 0;
|
||||
priv->clear_color[0][3] = 1.0;
|
||||
if (format == GST_VIDEO_FORMAT_NV21) {
|
||||
priv->clear_color[1][0] = converted[2];
|
||||
priv->clear_color[1][1] = converted[1];
|
||||
} else {
|
||||
priv->clear_color[1][0] = converted[1];
|
||||
priv->clear_color[1][1] = converted[2];
|
||||
}
|
||||
priv->clear_color[1][2] = 0;
|
||||
priv->clear_color[1][3] = 1.0;
|
||||
break;
|
||||
case GST_VIDEO_FORMAT_I420:
|
||||
case GST_VIDEO_FORMAT_YV12:
|
||||
case GST_VIDEO_FORMAT_I420_10LE:
|
||||
case GST_VIDEO_FORMAT_I420_12LE:
|
||||
case GST_VIDEO_FORMAT_Y42B:
|
||||
case GST_VIDEO_FORMAT_I422_10LE:
|
||||
case GST_VIDEO_FORMAT_I422_12LE:
|
||||
case GST_VIDEO_FORMAT_Y444:
|
||||
case GST_VIDEO_FORMAT_Y444_10LE:
|
||||
case GST_VIDEO_FORMAT_Y444_12LE:
|
||||
case GST_VIDEO_FORMAT_Y444_16LE:
|
||||
priv->clear_color[0][0] = converted[0];
|
||||
priv->clear_color[0][1] = 0;
|
||||
priv->clear_color[0][2] = 0;
|
||||
priv->clear_color[0][3] = 1.0;
|
||||
if (format == GST_VIDEO_FORMAT_YV12) {
|
||||
priv->clear_color[1][0] = converted[2];
|
||||
priv->clear_color[2][0] = converted[1];
|
||||
} else {
|
||||
priv->clear_color[1][0] = converted[1];
|
||||
priv->clear_color[2][0] = converted[2];
|
||||
}
|
||||
priv->clear_color[1][1] = 0;
|
||||
priv->clear_color[1][2] = 0;
|
||||
priv->clear_color[1][3] = 1.0;
|
||||
priv->clear_color[2][1] = 0;
|
||||
priv->clear_color[2][2] = 0;
|
||||
priv->clear_color[2][3] = 1.0;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GstD3D11Converter *
|
||||
gst_d3d11_converter_new (GstD3D11Device * device, const GstVideoInfo * in_info,
|
||||
const GstVideoInfo * out_info)
|
||||
|
@ -2200,6 +2345,8 @@ gst_d3d11_converter_new (GstD3D11Device * device, const GstVideoInfo * in_info,
|
|||
self->device = (GstD3D11Device *) gst_object_ref (device);
|
||||
priv->fast_path = TRUE;
|
||||
priv->const_data.alpha = 1.0;
|
||||
priv->in_info = *in_info;
|
||||
priv->out_info = *out_info;
|
||||
|
||||
/* Init properties */
|
||||
priv->src_width = GST_VIDEO_INFO_WIDTH (in_info);
|
||||
|
@ -2210,6 +2357,7 @@ gst_d3d11_converter_new (GstD3D11Device * device, const GstVideoInfo * in_info,
|
|||
for (guint i = 0; i < G_N_ELEMENTS (priv->blend_factor); i++)
|
||||
priv->blend_factor[i] = 1.0;
|
||||
priv->blend_sample_mask = 0xffffffff;
|
||||
priv->border_color = 0xffff000000000000;
|
||||
|
||||
if (!GST_VIDEO_INFO_IS_GRAY (in_info) && !GST_VIDEO_INFO_IS_GRAY (out_info)) {
|
||||
if (in_info->colorimetry.transfer != GST_VIDEO_TRANSFER_UNKNOWN &&
|
||||
|
@ -2247,6 +2395,31 @@ gst_d3d11_converter_new (GstD3D11Device * device, const GstVideoInfo * in_info,
|
|||
goto conversion_not_supported;
|
||||
}
|
||||
|
||||
if (GST_VIDEO_INFO_IS_RGB (out_info)) {
|
||||
GstVideoInfo rgb_info = *out_info;
|
||||
rgb_info.colorimetry.range = GST_VIDEO_COLOR_RANGE_0_255;
|
||||
gst_d3d11_color_range_adjust_matrix_unorm (&rgb_info, out_info,
|
||||
&priv->clear_color_matrix);
|
||||
} else {
|
||||
GstVideoInfo rgb_info;
|
||||
GstVideoInfo yuv_info;
|
||||
|
||||
gst_video_info_set_format (&rgb_info, GST_VIDEO_FORMAT_RGBA64_LE,
|
||||
out_info->width, out_info->height);
|
||||
convert_info_gray_to_yuv (out_info, &yuv_info);
|
||||
|
||||
if (yuv_info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_UNKNOWN ||
|
||||
yuv_info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_RGB) {
|
||||
GST_WARNING_OBJECT (self, "Invalid matrix is detected");
|
||||
yuv_info.colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT709;
|
||||
}
|
||||
|
||||
gst_d3d11_rgb_to_yuv_matrix_unorm (&rgb_info,
|
||||
&yuv_info, &priv->clear_color_matrix);
|
||||
}
|
||||
|
||||
gst_d3d11_converter_calculate_border_color (self);
|
||||
|
||||
ret = gst_d3d11_color_convert_setup_shader (self, in_info, out_info);
|
||||
if (!ret) {
|
||||
GST_ERROR_OBJECT (self, "Couldn't setup shader");
|
||||
|
@ -2254,9 +2427,6 @@ gst_d3d11_converter_new (GstD3D11Device * device, const GstVideoInfo * in_info,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
priv->in_info = *in_info;
|
||||
priv->out_info = *out_info;
|
||||
|
||||
return self;
|
||||
|
||||
/* ERRORS */
|
||||
|
@ -2362,6 +2532,11 @@ gst_d3d11_converter_convert_unlocked (GstD3D11Converter * converter,
|
|||
priv->update_alpha = FALSE;
|
||||
}
|
||||
|
||||
if (priv->clear_background) {
|
||||
for (guint i = 0; i < priv->num_output_view; i++)
|
||||
context->ClearRenderTargetView (rtv[i], priv->clear_color[i]);
|
||||
}
|
||||
|
||||
context->IASetPrimitiveTopology (D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
context->IASetInputLayout (priv->layout);
|
||||
context->IASetVertexBuffers (0, 1, &priv->vertex_buffer, &vertex_stride,
|
||||
|
|
Loading…
Reference in a new issue