diff --git a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11compositor.cpp b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11compositor.cpp index 3a5cb1a880..6fcf7ead52 100644 --- a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11compositor.cpp +++ b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11compositor.cpp @@ -1322,7 +1322,6 @@ gst_d3d11_compositor_pad_setup_converter (GstVideoAggregatorPad * pad, { GstD3D11CompositorPad *cpad = GST_D3D11_COMPOSITOR_PAD (pad); GstD3D11Compositor *self = GST_D3D11_COMPOSITOR (vagg); - RECT rect; gint width, height; GstVideoInfo *info = &vagg->info; GstVideoRectangle frame_rect; @@ -1333,36 +1332,20 @@ gst_d3d11_compositor_pad_setup_converter (GstVideoAggregatorPad * pad, #endif if (!cpad->convert || self->reconfigured) { - GstStructure *config; - - if (cpad->convert) - gst_d3d11_converter_free (cpad->convert); - - config = gst_structure_new_empty ("config"); - if (cpad->alpha <= 1.0) { - gst_structure_set (config, GST_D3D11_CONVERTER_OPT_ALPHA_VALUE, - G_TYPE_DOUBLE, cpad->alpha, nullptr); - } + gst_clear_object (&cpad->convert); cpad->convert = - gst_d3d11_converter_new (self->device, &pad->info, &vagg->info, config); - + gst_d3d11_converter_new (self->device, &pad->info, &vagg->info); if (!cpad->convert) { GST_ERROR_OBJECT (pad, "Couldn't create converter"); return FALSE; } + g_object_set (cpad->convert, "alpha", cpad->alpha, nullptr); + is_first = TRUE; } else if (cpad->alpha_updated) { - GstStructure *config; - - config = gst_structure_new_empty ("config"); - if (cpad->alpha <= 1.0) { - gst_structure_set (config, GST_D3D11_CONVERTER_OPT_ALPHA_VALUE, - G_TYPE_DOUBLE, cpad->alpha, nullptr); - } - - gst_d3d11_converter_update_config (cpad->convert, config); + g_object_set (cpad->convert, "alpha", cpad->alpha, nullptr); cpad->alpha_updated = FALSE; } @@ -1387,6 +1370,12 @@ gst_d3d11_compositor_pad_setup_converter (GstVideoAggregatorPad * pad, } cpad->blend = blend; + g_object_set (cpad->convert, "blend-state", blend, + "blend-factor-red", cpad->blend_factor[0], + "blend-factor-green", cpad->blend_factor[1], + "blend-factor-blue", cpad->blend_factor[2], + "blend-factor-alpha", cpad->blend_factor[3], + "blend-sample-mask", 0xffffffff, nullptr); } if (!is_first && !cpad->position_updated) @@ -1398,26 +1387,25 @@ gst_d3d11_compositor_pad_setup_converter (GstVideoAggregatorPad * pad, frame_rect = clamp_rectangle (cpad->xpos + x_offset, cpad->ypos + y_offset, width, height, GST_VIDEO_INFO_WIDTH (info), GST_VIDEO_INFO_HEIGHT (info)); - rect.left = frame_rect.x; - rect.top = frame_rect.y; - rect.right = frame_rect.x + frame_rect.w; - rect.bottom = frame_rect.y + frame_rect.h; - #ifndef GST_DISABLE_GST_DEBUG g_object_get (pad, "zorder", &zorder, NULL); GST_LOG_OBJECT (pad, "Update position, pad-xpos %d, pad-ypos %d, " "pad-zorder %d, pad-width %d, pad-height %d, in-resolution %dx%d, " - "out-resoution %dx%d, dst-{left,top,right,bottom} %d-%d-%d-%d", + "out-resoution %dx%d, dst-{x,y,width,height} %d-%d-%d-%d", cpad->xpos, cpad->ypos, zorder, cpad->width, cpad->height, GST_VIDEO_INFO_WIDTH (&pad->info), GST_VIDEO_INFO_HEIGHT (&pad->info), GST_VIDEO_INFO_WIDTH (info), GST_VIDEO_INFO_HEIGHT (info), - (gint) rect.left, (gint) rect.top, (gint) rect.right, (gint) rect.bottom); + frame_rect.x, frame_rect.y, frame_rect.w, frame_rect.h); #endif cpad->position_updated = FALSE; - return gst_d3d11_converter_update_dest_rect (cpad->convert, &rect); + g_object_set (cpad->convert, "dest-x", frame_rect.x, + "dest-y", frame_rect.y, "dest-width", frame_rect.w, + "dest-height", frame_rect.h, nullptr); + + return TRUE; } static GstStaticCaps pad_template_caps = @@ -1681,7 +1669,7 @@ gst_d3d11_compositor_pad_clear_resource (GstD3D11Compositor * self, gst_buffer_pool_set_active (cpad->fallback_pool, FALSE); gst_clear_object (&cpad->fallback_pool); } - g_clear_pointer (&cpad->convert, gst_d3d11_converter_free); + gst_clear_object (&cpad->convert); GST_D3D11_CLEAR_COM (cpad->blend); return TRUE; @@ -2420,8 +2408,7 @@ gst_d3d11_compositor_aggregate_frames (GstVideoAggregator * vagg, } } - if (!gst_d3d11_converter_convert_unlocked (cpad->convert, srv, rtv, - cpad->blend, cpad->blend_factor)) { + if (!gst_d3d11_converter_convert_unlocked (cpad->convert, srv, rtv)) { GST_ERROR_OBJECT (self, "Couldn't convert frame"); ret = GST_FLOW_ERROR; break; diff --git a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11convert.cpp b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11convert.cpp index 1ebc5a3efe..2037875a52 100644 --- a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11convert.cpp +++ b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11convert.cpp @@ -305,7 +305,7 @@ gst_d3d11_base_convert_clear_shader_resource (GstD3D11BaseConvert * self) GST_D3D11_CLEAR_COM (self->out_texture[i]); } - g_clear_pointer (&self->converter, gst_d3d11_converter_free); + gst_clear_object (&self->converter); g_clear_pointer (&self->processor, gst_d3d11_video_processor_free); self->processor_in_use = FALSE; @@ -1720,7 +1720,6 @@ gst_d3d11_base_convert_set_info (GstD3D11BaseFilter * filter, GstD3D11BaseConvert *self = GST_D3D11_BASE_CONVERT (filter); const GstVideoInfo *unknown_info; gint from_dar_n, from_dar_d, to_dar_n, to_dar_d; - D3D11_VIEWPORT view_port; gint border_offset_x = 0; gint border_offset_y = 0; @@ -1799,9 +1798,7 @@ gst_d3d11_base_convert_set_info (GstD3D11BaseFilter * filter, goto format_unknown; } - self->converter = - gst_d3d11_converter_new (filter->device, in_info, out_info, nullptr); - + self->converter = gst_d3d11_converter_new (filter->device, in_info, out_info); if (!self->converter) { GST_ERROR_OBJECT (self, "couldn't set converter"); return FALSE; @@ -1891,14 +1888,11 @@ gst_d3d11_base_convert_set_info (GstD3D11BaseFilter * filter, self->out_rect.bottom = GST_VIDEO_INFO_HEIGHT (out_info); } - view_port.TopLeftX = border_offset_x; - view_port.TopLeftY = border_offset_y; - view_port.Width = GST_VIDEO_INFO_WIDTH (out_info) - self->borders_w; - view_port.Height = GST_VIDEO_INFO_HEIGHT (out_info) - self->borders_h; - view_port.MinDepth = 0.0f; - view_port.MaxDepth = 1.0f; - - gst_d3d11_converter_update_viewport (self->converter, &view_port); + g_object_set (self->converter, "dest-x", (gint) self->out_rect.left, + "dest-y", (gint) self->out_rect.top, + "dest-width", (gint) (self->out_rect.right - self->out_rect.left), + "dest-height", (gint) (self->out_rect.bottom - self->out_rect.top), + nullptr); return TRUE; @@ -2137,7 +2131,7 @@ gst_d3d11_base_convert_transform (GstBaseTransform * trans, if (!gst_d3d11_converter_convert (self->converter, copy_input ? self->shader_resource_view : resource_view, - target_rtv, NULL, NULL)) { + target_rtv)) { goto conversion_failed; } diff --git a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11converter.cpp b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11converter.cpp index fc48f87467..151fc060b2 100644 --- a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11converter.cpp +++ b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11converter.cpp @@ -29,7 +29,7 @@ #include #include -GST_DEBUG_CATEGORY_EXTERN (gst_d3d11_converter_debug); +GST_DEBUG_CATEGORY_STATIC (gst_d3d11_converter_debug); #define GST_CAT_DEFAULT gst_d3d11_converter_debug /* *INDENT-OFF* */ @@ -56,7 +56,7 @@ typedef struct PSColorSpace to_rgb_buf; PSColorSpace to_yuv_buf; PSColorSpace XYZ_convert_buf; - FLOAT AlphaMul; + FLOAT alpha; FLOAT padding[3]; } PSConstBuffer; @@ -483,9 +483,28 @@ typedef struct const gchar *XYZ_convert_func; } ConvertInfo; -struct _GstD3D11Converter +enum +{ + PROP_0, + PROP_SRC_X, + PROP_SRC_Y, + PROP_SRC_WIDTH, + PROP_SRC_HEIGHT, + PROP_DEST_X, + PROP_DEST_Y, + PROP_DEST_WIDTH, + PROP_DEST_HEIGHT, + PROP_ALPHA, + PROP_BLEND_STATE, + PROP_BLEND_FACTOR_RED, + PROP_BLEND_FACTOR_GREEN, + PROP_BLEND_FACTOR_BLUE, + PROP_BLEND_FACTOR_ALPHA, + PROP_BLEND_SAMPLE_MASK, +}; + +struct _GstD3D11ConverterPrivate { - GstD3D11Device *device; GstVideoInfo in_info; GstVideoInfo out_info; @@ -506,36 +525,333 @@ struct _GstD3D11Converter ID3D11ShaderResourceView *gamma_dec_srv; ID3D11ShaderResourceView *gamma_enc_srv; + ID3D11BlendState *blend; + gboolean fast_path; gboolean do_primaries; - RECT src_rect; - RECT dest_rect; gint input_texture_width; gint input_texture_height; gboolean update_vertex; + gboolean update_viewport; gboolean update_alpha; ConvertInfo convert_info; PSConstBuffer const_data; - GstStructure *config; + GMutex prop_lock; + + /* properties */ + gint src_x; + gint src_y; + gint src_width; + gint src_height; + gint dest_x; + gint dest_y; + gint dest_width; + gint dest_height; + gdouble alpha; + gfloat blend_factor[4]; + guint blend_sample_mask; }; -static gdouble -get_opt_double (GstD3D11Converter * self, const gchar * opt, gdouble def) -{ - gdouble res; - if (!gst_structure_get_double (self->config, opt, &res)) - res = def; +static void gst_d3d11_converter_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +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); - return res; +#define gst_d3d11_converter_parent_class parent_class +G_DEFINE_TYPE_WITH_PRIVATE (GstD3D11Converter, gst_d3d11_converter, + GST_TYPE_OBJECT); + +static void +gst_d3d11_converter_class_init (GstD3D11ConverterClass * klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GParamFlags param_flags = + (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + object_class->set_property = gst_d3d11_converter_set_property; + object_class->get_property = gst_d3d11_converter_get_property; + object_class->dispose = gst_d3d11_converter_dispose; + object_class->finalize = gst_d3d11_converter_finalize; + + g_object_class_install_property (object_class, PROP_SRC_X, + g_param_spec_int ("src-x", "Src-X", + "Source x poisition to start conversion", G_MININT, G_MAXINT, 0, + param_flags)); + g_object_class_install_property (object_class, PROP_SRC_Y, + g_param_spec_int ("src-y", "Src-Y", + "Source y poisition to start conversion", G_MININT, G_MAXINT, 0, + param_flags)); + g_object_class_install_property (object_class, PROP_SRC_WIDTH, + g_param_spec_int ("src-width", "Src-Width", + "Source width to convert", 0, G_MAXINT, 0, param_flags)); + g_object_class_install_property (object_class, PROP_SRC_HEIGHT, + g_param_spec_int ("src-height", "Src-Height", + "Source height to convert", 0, G_MAXINT, 0, param_flags)); + g_object_class_install_property (object_class, PROP_DEST_X, + g_param_spec_int ("dest-x", "Dest-X", + "x poisition in the destination frame", G_MININT, G_MAXINT, 0, + param_flags)); + g_object_class_install_property (object_class, PROP_DEST_Y, + g_param_spec_int ("dest-y", "Dest-Y", + "y poisition in the destination frame", G_MININT, G_MAXINT, 0, + param_flags)); + g_object_class_install_property (object_class, PROP_DEST_WIDTH, + g_param_spec_int ("dest-width", "Dest-Width", + "Width in the destination frame", 0, G_MAXINT, 0, param_flags)); + g_object_class_install_property (object_class, PROP_DEST_HEIGHT, + g_param_spec_int ("dest-height", "Dest-Height", + "Height in the destination frame", 0, G_MAXINT, 0, param_flags)); + g_object_class_install_property (object_class, PROP_ALPHA, + g_param_spec_double ("alpha", "Alpha", + "The alpha color value to use", 0, 1.0, 1.0, param_flags)); + g_object_class_install_property (object_class, PROP_BLEND_STATE, + g_param_spec_pointer ("blend-state", "Blend State", + "ID3D11BlendState object to use", param_flags)); + g_object_class_install_property (object_class, PROP_BLEND_FACTOR_RED, + g_param_spec_float ("blend-factor-red", "Blend Factor Red", + "Blend factor for red component", 0, 1.0, 1.0, param_flags)); + g_object_class_install_property (object_class, PROP_BLEND_FACTOR_GREEN, + g_param_spec_float ("blend-factor-green", "Blend Factor Green", + "Blend factor for green component", 0, 1.0, 1.0, param_flags)); + g_object_class_install_property (object_class, PROP_BLEND_FACTOR_BLUE, + g_param_spec_float ("blend-factor-blue", "Blend Factor Blue", + "Blend factor for blue component", 0, 1.0, 1.0, param_flags)); + g_object_class_install_property (object_class, PROP_BLEND_FACTOR_ALPHA, + g_param_spec_float ("blend-factor-alpha", "Blend Factor Alpha", + "Blend factor for alpha component", 0, 1.0, 1.0, param_flags)); + 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)); + + GST_DEBUG_CATEGORY_INIT (gst_d3d11_converter_debug, + "d3d11converter", 0, "d3d11converter"); } -#define DEFAULT_OPT_ALPHA_VALUE 1.0 +static void +gst_d3d11_converter_init (GstD3D11Converter * self) +{ + self->priv = (GstD3D11ConverterPrivate *) + gst_d3d11_converter_get_instance_private (self); + g_mutex_init (&self->priv->prop_lock); +} -#define GET_OPT_ALPHA_VALUE(c) get_opt_double(c, \ - GST_D3D11_CONVERTER_OPT_ALPHA_VALUE, DEFAULT_OPT_ALPHA_VALUE); +static void +gst_d3d11_converter_dispose (GObject * object) +{ + GstD3D11Converter *self = GST_D3D11_CONVERTER (object); + GstD3D11ConverterPrivate *priv = self->priv; + + GST_D3D11_CLEAR_COM (priv->vertex_buffer); + GST_D3D11_CLEAR_COM (priv->index_buffer); + GST_D3D11_CLEAR_COM (priv->const_buffer); + GST_D3D11_CLEAR_COM (priv->vs); + GST_D3D11_CLEAR_COM (priv->layout); + GST_D3D11_CLEAR_COM (priv->linear_sampler); + GST_D3D11_CLEAR_COM (priv->gamma_dec_lut); + GST_D3D11_CLEAR_COM (priv->gamma_dec_srv); + GST_D3D11_CLEAR_COM (priv->gamma_enc_lut); + GST_D3D11_CLEAR_COM (priv->gamma_enc_srv); + GST_D3D11_CLEAR_COM (priv->blend); + + for (guint i = 0; i < CONVERTER_MAX_QUADS; i++) + GST_D3D11_CLEAR_COM (priv->ps[i]); + + gst_clear_object (&self->device); + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +gst_d3d11_converter_finalize (GObject * object) +{ + GstD3D11Converter *self = GST_D3D11_CONVERTER (object); + GstD3D11ConverterPrivate *priv = self->priv; + + for (guint i = 0; i < CONVERTER_MAX_QUADS; i++) { + g_free (priv->convert_info.sample_texture_func[i]); + g_free (priv->convert_info.build_output_func[i]); + } + + g_mutex_clear (&priv->prop_lock); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +update_src_rect (GstD3D11Converter * self, gint * old_val, + const GValue * new_val) +{ + GstD3D11ConverterPrivate *priv = self->priv; + gint tmp; + + tmp = g_value_get_int (new_val); + if (tmp != *old_val) { + priv->update_vertex = TRUE; + *old_val = tmp; + } +} + +static void +update_dest_rect (GstD3D11Converter * self, gint * old_val, + const GValue * new_val) +{ + GstD3D11ConverterPrivate *priv = self->priv; + gint tmp; + + tmp = g_value_get_int (new_val); + if (tmp != *old_val) { + priv->update_viewport = TRUE; + *old_val = tmp; + } +} + +static void +update_alpha (GstD3D11Converter * self, gdouble * old_val, + const GValue * new_val) +{ + GstD3D11ConverterPrivate *priv = self->priv; + gdouble tmp; + + tmp = g_value_get_double (new_val); + if (tmp != *old_val) { + priv->update_alpha = TRUE; + *old_val = tmp; + } +} + +static void +gst_d3d11_converter_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstD3D11Converter *self = GST_D3D11_CONVERTER (object); + GstD3D11ConverterPrivate *priv = self->priv; + + g_mutex_lock (&priv->prop_lock); + switch (prop_id) { + case PROP_SRC_X: + update_src_rect (self, &priv->src_x, value); + break; + case PROP_SRC_Y: + update_src_rect (self, &priv->src_y, value); + break; + case PROP_SRC_WIDTH: + update_src_rect (self, &priv->src_width, value); + break; + case PROP_SRC_HEIGHT: + update_src_rect (self, &priv->src_height, value); + break; + case PROP_DEST_X: + update_dest_rect (self, &priv->dest_x, value); + break; + case PROP_DEST_Y: + update_dest_rect (self, &priv->dest_y, value); + break; + case PROP_DEST_WIDTH: + update_dest_rect (self, &priv->dest_width, value); + break; + case PROP_DEST_HEIGHT: + update_dest_rect (self, &priv->dest_height, value); + break; + case PROP_ALPHA: + update_alpha (self, &priv->alpha, value); + priv->const_data.alpha = priv->alpha; + break; + case PROP_BLEND_STATE:{ + ID3D11BlendState *blend = + (ID3D11BlendState *) g_value_get_pointer (value); + GST_D3D11_CLEAR_COM (priv->blend); + priv->blend = blend; + if (priv->blend) + priv->blend->AddRef (); + break; + } + case PROP_BLEND_FACTOR_RED: + priv->blend_factor[0] = g_value_get_float (value); + break; + case PROP_BLEND_FACTOR_GREEN: + priv->blend_factor[1] = g_value_get_float (value); + break; + case PROP_BLEND_FACTOR_BLUE: + priv->blend_factor[2] = g_value_get_float (value); + break; + case PROP_BLEND_FACTOR_ALPHA: + priv->blend_factor[3] = g_value_get_float (value); + break; + case PROP_BLEND_SAMPLE_MASK: + priv->blend_sample_mask = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + g_mutex_unlock (&priv->prop_lock); +} + +static void +gst_d3d11_converter_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstD3D11Converter *self = GST_D3D11_CONVERTER (object); + GstD3D11ConverterPrivate *priv = self->priv; + + g_mutex_lock (&priv->prop_lock); + switch (prop_id) { + case PROP_SRC_X: + g_value_set_int (value, priv->src_x); + break; + case PROP_SRC_Y: + g_value_set_int (value, priv->src_y); + break; + case PROP_SRC_WIDTH: + g_value_set_int (value, priv->src_width); + break; + case PROP_SRC_HEIGHT: + g_value_set_int (value, priv->src_height); + break; + case PROP_DEST_X: + g_value_set_int (value, priv->dest_x); + break; + case PROP_DEST_Y: + g_value_set_int (value, priv->dest_y); + break; + case PROP_DEST_WIDTH: + g_value_set_int (value, priv->dest_width); + break; + case PROP_DEST_HEIGHT: + g_value_set_int (value, priv->dest_height); + break; + case PROP_ALPHA: + g_value_set_double (value, priv->alpha); + break; + case PROP_BLEND_STATE: + g_value_set_pointer (value, priv->blend); + break; + case PROP_BLEND_FACTOR_RED: + g_value_set_float (value, priv->blend_factor[0]); + break; + case PROP_BLEND_FACTOR_GREEN: + g_value_set_float (value, priv->blend_factor[1]); + break; + case PROP_BLEND_FACTOR_BLUE: + g_value_set_float (value, priv->blend_factor[2]); + break; + case PROP_BLEND_FACTOR_ALPHA: + g_value_set_float (value, priv->blend_factor[3]); + break; + case PROP_BLEND_SAMPLE_MASK: + g_value_set_uint (value, priv->blend_sample_mask); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + g_mutex_unlock (&priv->prop_lock); +} static gboolean get_packed_yuv_components (GstVideoFormat format, gchar * y, gchar * u, @@ -643,6 +959,7 @@ static gboolean gst_d3d11_color_convert_setup_shader (GstD3D11Converter * self, const GstVideoInfo * in_info, const GstVideoInfo * out_info) { + GstD3D11ConverterPrivate *priv = self->priv; GstD3D11Device *device = self->device; HRESULT hr; D3D11_SAMPLER_DESC sampler_desc; @@ -653,7 +970,7 @@ gst_d3d11_color_convert_setup_shader (GstD3D11Converter * self, WORD *indices; ID3D11Device *device_handle; ID3D11DeviceContext *context_handle; - ConvertInfo *cinfo = &self->convert_info; + ConvertInfo *cinfo = &priv->convert_info; ComPtr < ID3D11PixelShader > ps[CONVERTER_MAX_QUADS]; ComPtr < ID3D11VertexShader > vs; ComPtr < ID3D11InputLayout > layout; @@ -682,7 +999,8 @@ gst_d3d11_color_convert_setup_shader (GstD3D11Converter * self, hr = device_handle->CreateSamplerState (&sampler_desc, &linear_sampler); if (!gst_d3d11_result (hr, device)) { - GST_ERROR ("Couldn't create samplerState state, hr: 0x%x", (guint) hr); + GST_ERROR_OBJECT (self, + "Couldn't create samplerState state, hr: 0x%x", (guint) hr); return FALSE; } @@ -724,7 +1042,7 @@ gst_d3d11_color_convert_setup_shader (GstD3D11Converter * self, if (!gst_d3d11_create_vertex_shader (device, templ_vertex_shader, input_desc, G_N_ELEMENTS (input_desc), &vs, &layout)) { - GST_ERROR ("Couldn't vertex pixel shader"); + GST_ERROR_OBJECT (self, "Couldn't vertex pixel shader"); return FALSE; } @@ -737,7 +1055,8 @@ gst_d3d11_color_convert_setup_shader (GstD3D11Converter * self, hr = device_handle->CreateBuffer (&buffer_desc, nullptr, &const_buffer); if (!gst_d3d11_result (hr, device)) { - GST_ERROR ("Couldn't create constant buffer, hr: 0x%x", (guint) hr); + GST_ERROR_OBJECT (self, + "Couldn't create constant buffer, hr: 0x%x", (guint) hr); return FALSE; } @@ -749,7 +1068,8 @@ gst_d3d11_color_convert_setup_shader (GstD3D11Converter * self, hr = device_handle->CreateBuffer (&buffer_desc, nullptr, &vertex_buffer); if (!gst_d3d11_result (hr, device)) { - GST_ERROR ("Couldn't create vertex buffer, hr: 0x%x", (guint) hr); + GST_ERROR_OBJECT (self, + "Couldn't create vertex buffer, hr: 0x%x", (guint) hr); return FALSE; } @@ -768,18 +1088,19 @@ gst_d3d11_color_convert_setup_shader (GstD3D11Converter * self, hr = context_handle->Map (const_buffer.Get (), 0, D3D11_MAP_WRITE_DISCARD, 0, &map); if (!gst_d3d11_result (hr, device)) { - GST_ERROR ("Couldn't map constant buffer, hr: 0x%x", (guint) hr); + GST_ERROR_OBJECT (self, + "Couldn't map constant buffer, hr: 0x%x", (guint) hr); gst_d3d11_device_unlock (device); return FALSE; } - memcpy (map.pData, &self->const_data, sizeof (PSConstBuffer)); + memcpy (map.pData, &priv->const_data, sizeof (PSConstBuffer)); context_handle->Unmap (const_buffer.Get (), 0); hr = context_handle->Map (vertex_buffer.Get (), 0, D3D11_MAP_WRITE_DISCARD, 0, &map); if (!gst_d3d11_result (hr, device)) { - GST_ERROR ("Couldn't map vertex buffer, hr: 0x%x", (guint) hr); + GST_ERROR_OBJECT (self, "Couldn't map vertex buffer, hr: 0x%x", (guint) hr); gst_d3d11_device_unlock (device); return FALSE; } @@ -789,7 +1110,7 @@ gst_d3d11_color_convert_setup_shader (GstD3D11Converter * self, hr = context_handle->Map (index_buffer.Get (), 0, D3D11_MAP_WRITE_DISCARD, 0, &map); if (!gst_d3d11_result (hr, device)) { - GST_ERROR ("Couldn't map index buffer, hr: 0x%x", (guint) hr); + GST_ERROR_OBJECT (self, "Couldn't map index buffer, hr: 0x%x", (guint) hr); context_handle->Unmap (vertex_buffer.Get (), 0); gst_d3d11_device_unlock (device); return FALSE; @@ -839,39 +1160,29 @@ gst_d3d11_color_convert_setup_shader (GstD3D11Converter * self, gst_d3d11_device_unlock (device); /* holds vertex buffer for crop rect update */ - self->vertex_buffer = vertex_buffer.Detach (); - self->index_buffer = index_buffer.Detach (); - self->const_buffer = const_buffer.Detach (); - self->vs = vs.Detach (); - self->layout = layout.Detach (); - self->linear_sampler = linear_sampler.Detach (); - self->ps[0] = ps[0].Detach (); + priv->vertex_buffer = vertex_buffer.Detach (); + priv->index_buffer = index_buffer.Detach (); + priv->const_buffer = const_buffer.Detach (); + priv->vs = vs.Detach (); + priv->layout = layout.Detach (); + priv->linear_sampler = linear_sampler.Detach (); + priv->ps[0] = ps[0].Detach (); if (ps[1]) - self->ps[1] = ps[1].Detach (); + priv->ps[1] = ps[1].Detach (); - self->src_rect.left = 0; - self->src_rect.top = 0; - self->src_rect.right = GST_VIDEO_INFO_WIDTH (in_info); - self->src_rect.bottom = GST_VIDEO_INFO_HEIGHT (in_info); + priv->input_texture_width = GST_VIDEO_INFO_WIDTH (in_info); + priv->input_texture_height = GST_VIDEO_INFO_HEIGHT (in_info); - self->dest_rect.left = 0; - self->dest_rect.top = 0; - self->dest_rect.right = GST_VIDEO_INFO_WIDTH (out_info); - self->dest_rect.bottom = GST_VIDEO_INFO_HEIGHT (out_info); - - self->input_texture_width = GST_VIDEO_INFO_WIDTH (in_info); - self->input_texture_height = GST_VIDEO_INFO_HEIGHT (in_info); - - self->num_input_view = GST_VIDEO_INFO_N_PLANES (in_info); - self->num_output_view = GST_VIDEO_INFO_N_PLANES (out_info); + priv->num_input_view = GST_VIDEO_INFO_N_PLANES (in_info); + priv->num_output_view = GST_VIDEO_INFO_N_PLANES (out_info); for (guint i = 0; i < GST_VIDEO_INFO_N_PLANES (out_info); i++) { - self->viewport[i].TopLeftX = 0; - self->viewport[i].TopLeftY = 0; - self->viewport[i].Width = GST_VIDEO_INFO_COMP_WIDTH (out_info, i); - self->viewport[i].Height = GST_VIDEO_INFO_COMP_HEIGHT (out_info, i); - self->viewport[i].MinDepth = 0.0f; - self->viewport[i].MaxDepth = 1.0f; + priv->viewport[i].TopLeftX = 0; + priv->viewport[i].TopLeftY = 0; + priv->viewport[i].Width = GST_VIDEO_INFO_COMP_WIDTH (out_info, i); + priv->viewport[i].Height = GST_VIDEO_INFO_COMP_HEIGHT (out_info, i); + priv->viewport[i].MinDepth = 0.0f; + priv->viewport[i].MaxDepth = 1.0f; } return TRUE; @@ -880,63 +1191,28 @@ gst_d3d11_color_convert_setup_shader (GstD3D11Converter * self, static gboolean gst_d3d11_converter_update_vertex_buffer (GstD3D11Converter * self) { + GstD3D11ConverterPrivate *priv = self->priv; D3D11_MAPPED_SUBRESOURCE map; VertexData *vertex_data; ID3D11DeviceContext *context_handle; HRESULT hr; - FLOAT x0, y0, x1, y1; FLOAT u0, u1, v0, v1, off_u, off_v; - const RECT *src_rect = &self->src_rect; - const RECT *dest_rect = &self->dest_rect; - gint texture_width = self->input_texture_width; - gint texture_height = self->input_texture_height; - gdouble val; + gint texture_width = priv->input_texture_width; + gint texture_height = priv->input_texture_height; + + GST_DEBUG_OBJECT (self, "Updating vertex buffer"); context_handle = gst_d3d11_device_get_device_context_handle (self->device); - hr = context_handle->Map (self->vertex_buffer, 0, D3D11_MAP_WRITE_DISCARD, + hr = context_handle->Map (priv->vertex_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); if (!gst_d3d11_result (hr, self->device)) { - GST_ERROR ("Couldn't map vertex buffer, hr: 0x%x", (guint) hr); + GST_ERROR_OBJECT (self, "Couldn't map vertex buffer, hr: 0x%x", (guint) hr); return FALSE; } vertex_data = (VertexData *) map.pData; - /* bottom left */ - if (dest_rect->left > 0) { - gst_util_fraction_to_double (dest_rect->left, - GST_VIDEO_INFO_WIDTH (&self->out_info), &val); - x0 = (val * 2.0f) - 1.0f; - } else { - x0 = -1.0f; - } - - if (dest_rect->bottom != GST_VIDEO_INFO_HEIGHT (&self->out_info)) { - gst_util_fraction_to_double (dest_rect->bottom, - GST_VIDEO_INFO_HEIGHT (&self->out_info), &val); - y0 = (val * -2.0f) + 1.0f; - } else { - y0 = -1.0f; - } - - /* top right */ - if (dest_rect->right != GST_VIDEO_INFO_WIDTH (&self->out_info)) { - gst_util_fraction_to_double (dest_rect->right, - GST_VIDEO_INFO_WIDTH (&self->out_info), &val); - x1 = (val * 2.0f) - 1.0f; - } else { - x1 = 1.0f; - } - - if (dest_rect->top > 0) { - gst_util_fraction_to_double (dest_rect->top, - GST_VIDEO_INFO_HEIGHT (&self->out_info), &val); - y1 = (val * -2.0f) + 1.0f; - } else { - y1 = 1.0f; - } - /* * (u0, v0) -- (u1, v0) * | | @@ -945,72 +1221,122 @@ gst_d3d11_converter_update_vertex_buffer (GstD3D11Converter * self) off_u = 0.5f / texture_width; off_v = 0.5f / texture_height; - if (src_rect->left > 0) - u0 = (src_rect->left / (gfloat) texture_width) + off_u; + if (priv->src_x > 0) + u0 = (priv->src_x / (gfloat) texture_width) + off_u; else u0 = 0.0f; - if (src_rect->right != texture_width) - u1 = (src_rect->right / (gfloat) texture_width) - off_u; + if ((priv->src_x + priv->src_width) != texture_width) + u1 = ((priv->src_x + priv->src_width) / (gfloat) texture_width) - off_u; else u1 = 1.0f; - if (src_rect->top > 0) - v0 = (src_rect->top / (gfloat) texture_height) + off_v; + if (priv->src_y > 0) + v0 = (priv->src_y / (gfloat) texture_height) + off_v; else v0 = 0.0; - if (src_rect->bottom != texture_height) - v1 = (src_rect->bottom / (gfloat) texture_height) - off_v; + if ((priv->src_y + priv->src_height) != texture_height) + v1 = ((priv->src_y + priv->src_height) / (gfloat) texture_height) - off_v; else v1 = 1.0f; /* bottom left */ - vertex_data[0].position.x = x0; - vertex_data[0].position.y = y0; + vertex_data[0].position.x = -1.0f; + vertex_data[0].position.y = -1.0f; + vertex_data[0].position.z = 0.0f; vertex_data[0].texture.u = u0; vertex_data[0].texture.v = v1; /* top left */ - vertex_data[1].position.x = x0; - vertex_data[1].position.y = y1; + vertex_data[1].position.x = -1.0f; + vertex_data[1].position.y = 1.0f; + vertex_data[1].position.z = 0.0f; vertex_data[1].texture.u = u0; vertex_data[1].texture.v = v0; /* top right */ - vertex_data[2].position.x = x1; - vertex_data[2].position.y = y1; + vertex_data[2].position.x = 1.0f; + vertex_data[2].position.y = 1.0f; + vertex_data[2].position.z = 0.0f; vertex_data[2].texture.u = u1; vertex_data[2].texture.v = v0; /* bottom right */ - vertex_data[3].position.x = x1; - vertex_data[3].position.y = y0; + vertex_data[3].position.x = 1.0f; + vertex_data[3].position.y = -1.0f; + vertex_data[3].position.z = 0.0f; vertex_data[3].texture.u = u1; vertex_data[3].texture.v = v1; - context_handle->Unmap (self->vertex_buffer, 0); + context_handle->Unmap (priv->vertex_buffer, 0); - self->update_vertex = FALSE; + priv->update_vertex = FALSE; return TRUE; } static gboolean -copy_config (GQuark field_id, const GValue * value, GstD3D11Converter * self) +gst_d3d11_converter_update_viewport (GstD3D11Converter * self) { - gst_structure_id_set_value (self->config, field_id, value); + GstD3D11ConverterPrivate *priv = self->priv; - return TRUE; -} + priv->viewport[0].TopLeftX = priv->dest_x; + priv->viewport[0].TopLeftY = priv->dest_y; + priv->viewport[0].Width = priv->dest_width; + priv->viewport[0].Height = priv->dest_height; -static gboolean -gst_d3d11_converter_set_config (GstD3D11Converter * converter, - GstStructure * config) -{ - gst_structure_foreach (config, (GstStructureForeachFunc) copy_config, - converter); - gst_structure_free (config); + GST_DEBUG_OBJECT (self, + "Update viewport, TopLeftX: %f, TopLeftY: %f, Width: %f, Height %f", + priv->viewport[0].TopLeftX, priv->viewport[0].TopLeftY, + priv->viewport[0].Width, priv->viewport[0].Height); + + switch (GST_VIDEO_INFO_FORMAT (&priv->out_info)) { + 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: + case GST_VIDEO_FORMAT_I420: + case GST_VIDEO_FORMAT_YV12: + case GST_VIDEO_FORMAT_I420_10LE: + case GST_VIDEO_FORMAT_I420_12LE: + priv->viewport[1].TopLeftX = priv->viewport[0].TopLeftX / 2; + priv->viewport[1].TopLeftY = priv->viewport[0].TopLeftY / 2; + priv->viewport[1].Width = priv->viewport[0].Width / 2; + priv->viewport[1].Height = priv->viewport[0].Height / 2; + + for (guint i = 2; i < GST_VIDEO_INFO_N_PLANES (&priv->out_info); i++) + priv->viewport[i] = priv->viewport[1]; + + break; + case GST_VIDEO_FORMAT_Y42B: + case GST_VIDEO_FORMAT_I422_10LE: + case GST_VIDEO_FORMAT_I422_12LE: + priv->viewport[1].TopLeftX = priv->viewport[0].TopLeftX / 2; + priv->viewport[1].TopLeftY = priv->viewport[0].TopLeftY; + priv->viewport[1].Width = priv->viewport[0].Width / 2; + priv->viewport[1].Height = priv->viewport[0].Height; + + for (guint i = 2; i < GST_VIDEO_INFO_N_PLANES (&priv->out_info); i++) + priv->viewport[i] = priv->viewport[1]; + break; + case GST_VIDEO_FORMAT_Y444: + case GST_VIDEO_FORMAT_Y444_10LE: + case GST_VIDEO_FORMAT_Y444_12LE: + case GST_VIDEO_FORMAT_Y444_16LE: + for (guint i = 1; i < GST_VIDEO_INFO_N_PLANES (&priv->out_info); i++) + priv->viewport[i] = priv->viewport[0]; + break; + default: + if (priv->num_output_view > 1) { + g_assert_not_reached (); + return FALSE; + } + break; + } + + priv->update_viewport = FALSE; return TRUE; } @@ -1019,8 +1345,9 @@ static gboolean gst_d3d11_converter_prepare_output (GstD3D11Converter * self, const GstVideoInfo * info) { + GstD3D11ConverterPrivate *priv = self->priv; GstVideoFormat format = GST_VIDEO_INFO_FORMAT (info); - ConvertInfo *cinfo = &self->convert_info; + ConvertInfo *cinfo = &priv->convert_info; switch (format) { /* RGB */ @@ -1126,11 +1453,12 @@ static gboolean gst_d3d11_converter_prepare_sample_texture (GstD3D11Converter * self, const GstVideoInfo * in_info, const GstVideoInfo * out_info) { + GstD3D11ConverterPrivate *priv = self->priv; GstVideoFormat format = GST_VIDEO_INFO_FORMAT (in_info); gboolean out_rgb = GST_VIDEO_INFO_IS_RGB (out_info); gboolean out_yuv = GST_VIDEO_INFO_IS_YUV (out_info); gboolean out_gray = GST_VIDEO_INFO_IS_GRAY (out_info); - ConvertInfo *cinfo = &self->convert_info; + ConvertInfo *cinfo = &priv->convert_info; switch (format) { /* RGB */ @@ -1181,7 +1509,7 @@ gst_d3d11_converter_prepare_sample_texture (GstD3D11Converter * self, cinfo->sample_texture_func[0] = g_strdup_printf (templ_SAMPLE_SEMI_PLANAR, u, v); } else { - if (self->fast_path) { + if (priv->fast_path) { cinfo->sample_texture_func[0] = g_strdup (templ_SAMPLE_YUV_LUMA); cinfo->sample_texture_func[1] = g_strdup_printf (templ_SAMPLE_SEMI_PLANAR_CHROMA, u, v); @@ -1227,7 +1555,7 @@ gst_d3d11_converter_prepare_sample_texture (GstD3D11Converter * self, cinfo->sample_texture_func[0] = g_strdup_printf (templ_SAMPLE_PLANAR, u, v, scale); } else { - if (self->fast_path) { + if (priv->fast_path) { cinfo->sample_texture_func[0] = g_strdup_printf (templ_SAMPLE_YUV_LUMA_SCALED, scale); cinfo->sample_texture_func[1] = @@ -1361,12 +1689,12 @@ static gboolean gst_d3d11_converter_prepare_colorspace_fast (GstD3D11Converter * self, const GstVideoInfo * in_info, const GstVideoInfo * out_info) { - GstD3D11Device *device = self->device; + GstD3D11ConverterPrivate *priv = self->priv; const GstVideoColorimetry *in_color = &in_info->colorimetry; const GstVideoColorimetry *out_color = &out_info->colorimetry; - ConvertInfo *cinfo = &self->convert_info; - PSColorSpace *to_rgb_buf = &self->const_data.to_rgb_buf; - PSColorSpace *to_yuv_buf = &self->const_data.to_yuv_buf; + ConvertInfo *cinfo = &priv->convert_info; + PSColorSpace *to_rgb_buf = &priv->const_data.to_rgb_buf; + PSColorSpace *to_yuv_buf = &priv->const_data.to_yuv_buf; GstD3D11ColorMatrix to_rgb_matrix; GstD3D11ColorMatrix to_yuv_matrix; gchar *matrix_dump; @@ -1386,16 +1714,16 @@ gst_d3d11_converter_prepare_colorspace_fast (GstD3D11Converter * self, if (GST_VIDEO_INFO_IS_RGB (in_info)) { if (GST_VIDEO_INFO_IS_RGB (out_info)) { if (in_color->range == out_color->range) { - GST_DEBUG_OBJECT (device, "RGB -> RGB without colorspace conversion"); + GST_DEBUG_OBJECT (self, "RGB -> RGB without colorspace conversion"); } else { if (!gst_d3d11_color_range_adjust_matrix_unorm (in_info, out_info, &to_rgb_matrix)) { - GST_ERROR_OBJECT (device, "Failed to get RGB range adjust matrix"); + GST_ERROR_OBJECT (self, "Failed to get RGB range adjust matrix"); return FALSE; } matrix_dump = gst_d3d11_dump_color_matrix (&to_rgb_matrix); - GST_DEBUG_OBJECT (device, "RGB range adjust %s -> %s\n%s", + GST_DEBUG_OBJECT (self, "RGB range adjust %s -> %s\n%s", get_color_range_name (in_color->range), get_color_range_name (out_color->range), matrix_dump); g_free (matrix_dump); @@ -1409,18 +1737,18 @@ gst_d3d11_converter_prepare_colorspace_fast (GstD3D11Converter * self, if (yuv_info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_UNKNOWN || yuv_info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_RGB) { - GST_WARNING_OBJECT (device, "Invalid matrix is detected"); + GST_WARNING_OBJECT (self, "Invalid matrix is detected"); yuv_info.colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT709; } if (!gst_d3d11_rgb_to_yuv_matrix_unorm (in_info, &yuv_info, &to_yuv_matrix)) { - GST_ERROR_OBJECT (device, "Failed to get RGB -> YUV transform matrix"); + GST_ERROR_OBJECT (self, "Failed to get RGB -> YUV transform matrix"); return FALSE; } matrix_dump = gst_d3d11_dump_color_matrix (&to_yuv_matrix); - GST_DEBUG_OBJECT (device, "RGB -> YUV matrix:\n%s", matrix_dump); + GST_DEBUG_OBJECT (self, "RGB -> YUV matrix:\n%s", matrix_dump); g_free (matrix_dump); if (GST_VIDEO_INFO_IS_GRAY (out_info)) { @@ -1454,18 +1782,18 @@ gst_d3d11_converter_prepare_colorspace_fast (GstD3D11Converter * self, identity = FALSE; if (!gst_d3d11_color_range_adjust_matrix_unorm (&in_tmp, &out_tmp, &matrix)) { - GST_ERROR_OBJECT (device, "Failed to get GRAY range adjust matrix"); + GST_ERROR_OBJECT (self, "Failed to get GRAY range adjust matrix"); return FALSE; } matrix_dump = gst_d3d11_dump_color_matrix (&matrix); - GST_DEBUG_OBJECT (device, "GRAY range adjust matrix:\n%s", matrix_dump); + GST_DEBUG_OBJECT (self, "GRAY range adjust matrix:\n%s", matrix_dump); g_free (matrix_dump); } if (GST_VIDEO_INFO_IS_GRAY (out_info)) { if (identity) { - GST_DEBUG_OBJECT (device, "GRAY to GRAY without range adjust"); + GST_DEBUG_OBJECT (self, "GRAY to GRAY without range adjust"); } else { cinfo->to_yuv_func[0] = templ_COLOR_SPACE_CONVERT_LUMA; } @@ -1473,7 +1801,7 @@ gst_d3d11_converter_prepare_colorspace_fast (GstD3D11Converter * self, to_yuv_matrix = matrix; } else if (GST_VIDEO_INFO_IS_RGB (out_info)) { if (identity) { - GST_DEBUG_OBJECT (device, "GRAY to RGB without range adjust"); + GST_DEBUG_OBJECT (self, "GRAY to RGB without range adjust"); cinfo->to_rgb_func[0] = templ_COLOR_SPACE_GRAY_TO_RGB; } else { cinfo->to_rgb_func[0] = templ_COLOR_SPACE_GRAY_TO_RGB_RANGE_ADJUST; @@ -1482,7 +1810,7 @@ gst_d3d11_converter_prepare_colorspace_fast (GstD3D11Converter * self, to_rgb_matrix = matrix; } else if (GST_VIDEO_INFO_IS_YUV (out_info)) { if (identity) { - GST_DEBUG_OBJECT (device, "GRAY to YUV without range adjust"); + GST_DEBUG_OBJECT (self, "GRAY to YUV without range adjust"); } else { cinfo->to_yuv_func[0] = templ_COLOR_SPACE_CONVERT_LUMA; cinfo->to_yuv_func[1] = templ_COLOR_SPACE_CONVERT_LUMA; @@ -1499,30 +1827,30 @@ gst_d3d11_converter_prepare_colorspace_fast (GstD3D11Converter * self, if (yuv_info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_UNKNOWN || yuv_info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_RGB) { - GST_WARNING_OBJECT (device, "Invalid matrix is detected"); + GST_WARNING_OBJECT (self, "Invalid matrix is detected"); yuv_info.colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT709; } if (!gst_d3d11_yuv_to_rgb_matrix_unorm (&yuv_info, out_info, &to_rgb_matrix)) { - GST_ERROR_OBJECT (device, "Failed to get YUV -> RGB transform matrix"); + GST_ERROR_OBJECT (self, "Failed to get YUV -> RGB transform matrix"); return FALSE; } matrix_dump = gst_d3d11_dump_color_matrix (&to_rgb_matrix); - GST_DEBUG_OBJECT (device, "YUV -> RGB matrix:\n%s", matrix_dump); + GST_DEBUG_OBJECT (self, "YUV -> RGB matrix:\n%s", matrix_dump); g_free (matrix_dump); cinfo->to_rgb_func[0] = templ_COLOR_SPACE_CONVERT; } else if (in_color->range != out_color->range) { if (!gst_d3d11_color_range_adjust_matrix_unorm (in_info, out_info, &to_yuv_matrix)) { - GST_ERROR_OBJECT (device, "Failed to get GRAY range adjust matrix"); + GST_ERROR_OBJECT (self, "Failed to get GRAY range adjust matrix"); return FALSE; } matrix_dump = gst_d3d11_dump_color_matrix (&to_yuv_matrix); - GST_DEBUG_OBJECT (device, "YUV range adjust matrix:\n%s", matrix_dump); + GST_DEBUG_OBJECT (self, "YUV range adjust matrix:\n%s", matrix_dump); g_free (matrix_dump); if (GST_VIDEO_INFO_IS_GRAY (out_info)) { @@ -1564,13 +1892,13 @@ static gboolean gst_d3d11_converter_prepare_colorspace (GstD3D11Converter * self, const GstVideoInfo * in_info, const GstVideoInfo * out_info) { - GstD3D11Device *device = self->device; + GstD3D11ConverterPrivate *priv = self->priv; const GstVideoColorimetry *in_color = &in_info->colorimetry; const GstVideoColorimetry *out_color = &out_info->colorimetry; - ConvertInfo *cinfo = &self->convert_info; - PSColorSpace *to_rgb_buf = &self->const_data.to_rgb_buf; - PSColorSpace *to_yuv_buf = &self->const_data.to_yuv_buf; - PSColorSpace *XYZ_convert_buf = &self->const_data.XYZ_convert_buf; + ConvertInfo *cinfo = &priv->convert_info; + PSColorSpace *to_rgb_buf = &priv->const_data.to_rgb_buf; + PSColorSpace *to_yuv_buf = &priv->const_data.to_yuv_buf; + PSColorSpace *XYZ_convert_buf = &priv->const_data.XYZ_convert_buf; GstD3D11ColorMatrix to_rgb_matrix; GstD3D11ColorMatrix to_yuv_matrix; GstD3D11ColorMatrix XYZ_convert_matrix; @@ -1602,12 +1930,12 @@ gst_d3d11_converter_prepare_colorspace (GstD3D11Converter * self, if (!gst_d3d11_color_range_adjust_matrix_unorm (in_info, &in_rgb_info, &to_rgb_matrix)) { - GST_ERROR_OBJECT (device, "Failed to get RGB range adjust matrix"); + GST_ERROR_OBJECT (self, "Failed to get RGB range adjust matrix"); return FALSE; } matrix_dump = gst_d3d11_dump_color_matrix (&to_rgb_matrix); - GST_DEBUG_OBJECT (device, "Input RGB range adjust matrix\n%s", matrix_dump); + GST_DEBUG_OBJECT (self, "Input RGB range adjust matrix\n%s", matrix_dump); g_free (matrix_dump); cinfo->to_rgb_func[0] = cinfo->to_rgb_func[1] = templ_COLOR_SPACE_CONVERT; @@ -1618,7 +1946,7 @@ gst_d3d11_converter_prepare_colorspace (GstD3D11Converter * self, yuv_info = *in_info; if (yuv_info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_UNKNOWN || yuv_info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_RGB) { - GST_WARNING_OBJECT (device, "Invalid matrix is detected"); + GST_WARNING_OBJECT (self, "Invalid matrix is detected"); yuv_info.colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT709; } @@ -1636,12 +1964,12 @@ gst_d3d11_converter_prepare_colorspace (GstD3D11Converter * self, if (!gst_d3d11_yuv_to_rgb_matrix_unorm (&yuv_info, &in_rgb_info, &to_rgb_matrix)) { - GST_ERROR_OBJECT (device, "Failed to get YUV -> RGB transform matrix"); + GST_ERROR_OBJECT (self, "Failed to get YUV -> RGB transform matrix"); return FALSE; } matrix_dump = gst_d3d11_dump_color_matrix (&to_rgb_matrix); - GST_DEBUG_OBJECT (device, "YUV -> RGB matrix:\n%s", matrix_dump); + GST_DEBUG_OBJECT (self, "YUV -> RGB matrix:\n%s", matrix_dump); g_free (matrix_dump); cinfo->to_rgb_func[0] = cinfo->to_rgb_func[1] = templ_COLOR_SPACE_CONVERT; @@ -1654,13 +1982,12 @@ gst_d3d11_converter_prepare_colorspace (GstD3D11Converter * self, if (!gst_d3d11_color_range_adjust_matrix_unorm (&out_rgb_info, out_info, &to_yuv_matrix)) { - GST_ERROR_OBJECT (device, "Failed to get RGB range adjust matrix"); + GST_ERROR_OBJECT (self, "Failed to get RGB range adjust matrix"); return FALSE; } matrix_dump = gst_d3d11_dump_color_matrix (&to_yuv_matrix); - GST_DEBUG_OBJECT (device, - "Output RGB range adjust matrix\n%s", matrix_dump); + GST_DEBUG_OBJECT (self, "Output RGB range adjust matrix\n%s", matrix_dump); g_free (matrix_dump); cinfo->to_yuv_func[0] = cinfo->to_yuv_func[1] = templ_COLOR_SPACE_CONVERT; @@ -1670,7 +1997,7 @@ gst_d3d11_converter_prepare_colorspace (GstD3D11Converter * self, yuv_info = *out_info; if (yuv_info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_UNKNOWN || yuv_info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_RGB) { - GST_WARNING_OBJECT (device, "Invalid matrix is detected"); + GST_WARNING_OBJECT (self, "Invalid matrix is detected"); yuv_info.colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT709; } @@ -1683,12 +2010,12 @@ gst_d3d11_converter_prepare_colorspace (GstD3D11Converter * self, if (!gst_d3d11_rgb_to_yuv_matrix_unorm (&out_rgb_info, &yuv_info, &to_yuv_matrix)) { - GST_ERROR_OBJECT (device, "Failed to get RGB -> YUV transform matrix"); + GST_ERROR_OBJECT (self, "Failed to get RGB -> YUV transform matrix"); return FALSE; } matrix_dump = gst_d3d11_dump_color_matrix (&to_yuv_matrix); - GST_DEBUG_OBJECT (device, "RGB -> YUV matrix:\n%s", matrix_dump); + GST_DEBUG_OBJECT (self, "RGB -> YUV matrix:\n%s", matrix_dump); g_free (matrix_dump); if (GST_VIDEO_INFO_N_PLANES (out_info) == 1 || @@ -1702,7 +2029,7 @@ gst_d3d11_converter_prepare_colorspace (GstD3D11Converter * self, } /* TODO: handle HDR mastring display info */ - if (self->do_primaries) { + if (priv->do_primaries) { const GstVideoColorPrimariesInfo *in_pinfo; const GstVideoColorPrimariesInfo *out_pinfo; @@ -1711,12 +2038,12 @@ gst_d3d11_converter_prepare_colorspace (GstD3D11Converter * self, if (!gst_d3d11_color_primaries_matrix_unorm (in_pinfo, out_pinfo, &XYZ_convert_matrix)) { - GST_ERROR_OBJECT (device, "Failed to get primaries conversion matrix"); + GST_ERROR_OBJECT (self, "Failed to get primaries conversion matrix"); return FALSE; } matrix_dump = gst_d3d11_dump_color_matrix (&XYZ_convert_matrix); - GST_DEBUG_OBJECT (device, "Primaries conversion matrix:\n%s", matrix_dump); + GST_DEBUG_OBJECT (self, "Primaries conversion matrix:\n%s", matrix_dump); g_free (matrix_dump); cinfo->XYZ_convert_func = templ_XYZ_CONVERT; @@ -1752,6 +2079,7 @@ static gboolean gst_d3d11_converter_setup_lut (GstD3D11Converter * self, const GstVideoInfo * in_info, const GstVideoInfo * out_info) { + GstD3D11ConverterPrivate *priv = self->priv; GstD3D11Device *device = self->device; ID3D11Device *device_handle = gst_d3d11_device_get_device_handle (device); D3D11_TEXTURE1D_DESC desc; @@ -1800,21 +2128,21 @@ gst_d3d11_converter_setup_lut (GstD3D11Converter * self, hr = device_handle->CreateTexture1D (&desc, &subresource, &gamma_dec_lut); if (!gst_d3d11_result (hr, device)) { - GST_ERROR_OBJECT (device, "Failed to create gamma decode LUT"); + GST_ERROR_OBJECT (self, "Failed to create gamma decode LUT"); return FALSE; } hr = device_handle->CreateShaderResourceView (gamma_dec_lut.Get (), &srv_desc, &gamma_dec_srv); if (!gst_d3d11_result (hr, device)) { - GST_ERROR_OBJECT (device, "Failed to create gamma decode LUT SRV"); + GST_ERROR_OBJECT (self, "Failed to create gamma decode LUT SRV"); return FALSE; } subresource.pSysMem = gamma_enc_table; hr = device_handle->CreateTexture1D (&desc, &subresource, &gamma_enc_lut); if (!gst_d3d11_result (hr, device)) { - GST_ERROR_OBJECT (device, "Failed to create gamma encode LUT"); + GST_ERROR_OBJECT (self, "Failed to create gamma encode LUT"); return FALSE; } @@ -1825,65 +2153,80 @@ gst_d3d11_converter_setup_lut (GstD3D11Converter * self, return FALSE; } - self->gamma_dec_lut = gamma_dec_lut.Detach (); - self->gamma_enc_lut = gamma_enc_lut.Detach (); - self->gamma_dec_srv = gamma_dec_srv.Detach (); - self->gamma_enc_srv = gamma_enc_srv.Detach (); + priv->gamma_dec_lut = gamma_dec_lut.Detach (); + priv->gamma_enc_lut = gamma_enc_lut.Detach (); + priv->gamma_dec_srv = gamma_dec_srv.Detach (); + priv->gamma_enc_srv = gamma_enc_srv.Detach (); return TRUE; } GstD3D11Converter * gst_d3d11_converter_new (GstD3D11Device * device, const GstVideoInfo * in_info, - const GstVideoInfo * out_info, GstStructure * config) + const GstVideoInfo * out_info) { - const GstVideoInfo *unknown_info; + GstD3D11Converter *self; + GstD3D11ConverterPrivate *priv; GstD3D11Format in_d3d11_format; GstD3D11Format out_d3d11_format; - GstD3D11Converter *self = nullptr; gboolean ret; - GST_DEBUG_OBJECT (device, "Setup convert with format %s -> %s", + self = (GstD3D11Converter *) g_object_new (GST_TYPE_D3D11_CONVERTER, nullptr); + gst_object_ref_sink (self); + priv = self->priv; + + GST_DEBUG_OBJECT (self, "Setup convert with format %s -> %s", gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (in_info)), gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (out_info))); if (!gst_d3d11_device_get_format (device, GST_VIDEO_INFO_FORMAT (in_info), &in_d3d11_format)) { - unknown_info = in_info; - goto format_unknown; + GST_ERROR_OBJECT (self, "%s couldn't be converted to d3d11 format", + gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (in_info))); + gst_object_unref (self); + + return nullptr; } if (!gst_d3d11_device_get_format (device, GST_VIDEO_INFO_FORMAT (out_info), &out_d3d11_format)) { - unknown_info = out_info; - goto format_unknown; + GST_ERROR_OBJECT (self, "%s couldn't be converted to d3d11 format", + gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (in_info))); + gst_object_unref (self); + + return nullptr; } - self = g_new0 (GstD3D11Converter, 1); self->device = (GstD3D11Device *) gst_object_ref (device); - self->config = gst_structure_new_empty ("GstD3D11Converter-Config"); - self->fast_path = TRUE; - if (config) - gst_d3d11_converter_set_config (self, config); + priv->fast_path = TRUE; + priv->const_data.alpha = 1.0; - self->const_data.AlphaMul = GET_OPT_ALPHA_VALUE (self); + /* Init properties */ + priv->src_width = GST_VIDEO_INFO_WIDTH (in_info); + priv->src_height = GST_VIDEO_INFO_HEIGHT (in_info); + priv->dest_width = GST_VIDEO_INFO_WIDTH (out_info); + priv->dest_height = GST_VIDEO_INFO_HEIGHT (out_info); + priv->alpha = 1.0; + for (guint i = 0; i < G_N_ELEMENTS (priv->blend_factor); i++) + priv->blend_factor[i] = 1.0; + priv->blend_sample_mask = 0xffffffff; if (!GST_VIDEO_INFO_IS_GRAY (in_info) && !GST_VIDEO_INFO_IS_GRAY (out_info)) { if (in_info->colorimetry.transfer != GST_VIDEO_TRANSFER_UNKNOWN && out_info->colorimetry.transfer != GST_VIDEO_TRANSFER_UNKNOWN && in_info->colorimetry.transfer != out_info->colorimetry.transfer) { - GST_DEBUG_OBJECT (device, "Different transfer function %d -> %d", + GST_DEBUG_OBJECT (self, "Different transfer function %d -> %d", in_info->colorimetry.transfer, out_info->colorimetry.transfer); - self->fast_path = FALSE; + priv->fast_path = FALSE; } if (in_info->colorimetry.primaries != GST_VIDEO_COLOR_PRIMARIES_UNKNOWN && out_info->colorimetry.primaries != GST_VIDEO_COLOR_PRIMARIES_UNKNOWN && in_info->colorimetry.primaries != out_info->colorimetry.primaries) { - GST_DEBUG_OBJECT (device, "Different primaries %d -> %d", + GST_DEBUG_OBJECT (self, "Different primaries %d -> %d", in_info->colorimetry.primaries, out_info->colorimetry.primaries); - self->fast_path = FALSE; - self->do_primaries = TRUE; + priv->fast_path = FALSE; + priv->do_primaries = TRUE; } } @@ -1893,7 +2236,7 @@ gst_d3d11_converter_new (GstD3D11Device * device, const GstVideoInfo * in_info, if (!gst_d3d11_converter_prepare_sample_texture (self, in_info, out_info)) goto conversion_not_supported; - if (self->fast_path) { + if (priv->fast_path) { if (!gst_d3d11_converter_prepare_colorspace_fast (self, in_info, out_info)) goto conversion_not_supported; } else { @@ -1906,82 +2249,40 @@ gst_d3d11_converter_new (GstD3D11Device * device, const GstVideoInfo * in_info, ret = gst_d3d11_color_convert_setup_shader (self, in_info, out_info); if (!ret) { - GST_ERROR_OBJECT (device, "Couldn't setup shader"); - gst_d3d11_converter_free (self); + GST_ERROR_OBJECT (self, "Couldn't setup shader"); + gst_object_unref (self); return nullptr; } - self->in_info = *in_info; - self->out_info = *out_info; + priv->in_info = *in_info; + priv->out_info = *out_info; return self; /* ERRORS */ -format_unknown: - { - GST_ERROR_OBJECT (device, "%s couldn't be converted to d3d11 format", - gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (unknown_info))); - if (config) - gst_structure_free (config); - - return nullptr; - } conversion_not_supported: { - GST_ERROR_OBJECT (device, "Conversion %s to %s not supported", + GST_ERROR_OBJECT (self, "Conversion %s to %s not supported", gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (in_info)), gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (out_info))); - gst_d3d11_converter_free (self); + gst_object_unref (self); return nullptr; } } -void -gst_d3d11_converter_free (GstD3D11Converter * converter) -{ - g_return_if_fail (converter != nullptr); - - GST_D3D11_CLEAR_COM (converter->vertex_buffer); - GST_D3D11_CLEAR_COM (converter->index_buffer); - GST_D3D11_CLEAR_COM (converter->const_buffer); - GST_D3D11_CLEAR_COM (converter->vs); - GST_D3D11_CLEAR_COM (converter->layout); - GST_D3D11_CLEAR_COM (converter->linear_sampler); - GST_D3D11_CLEAR_COM (converter->gamma_dec_lut); - GST_D3D11_CLEAR_COM (converter->gamma_dec_srv); - GST_D3D11_CLEAR_COM (converter->gamma_enc_lut); - GST_D3D11_CLEAR_COM (converter->gamma_enc_srv); - - for (guint i = 0; i < CONVERTER_MAX_QUADS; i++) { - GST_D3D11_CLEAR_COM (converter->ps[i]); - - g_free (converter->convert_info.sample_texture_func[i]); - g_free (converter->convert_info.build_output_func[i]); - } - - gst_clear_object (&converter->device); - - if (converter->config) - gst_structure_free (converter->config); - - g_free (converter); -} - gboolean gst_d3d11_converter_convert (GstD3D11Converter * converter, ID3D11ShaderResourceView * srv[GST_VIDEO_MAX_PLANES], - ID3D11RenderTargetView * rtv[GST_VIDEO_MAX_PLANES], - ID3D11BlendState * blend, gfloat blend_factor[4]) + ID3D11RenderTargetView * rtv[GST_VIDEO_MAX_PLANES]) { gboolean ret; - g_return_val_if_fail (converter != nullptr, FALSE); + g_return_val_if_fail (GST_IS_D3D11_CONVERTER (converter), FALSE); g_return_val_if_fail (srv != nullptr, FALSE); g_return_val_if_fail (rtv != nullptr, FALSE); gst_d3d11_device_lock (converter->device); - ret = gst_d3d11_converter_convert_unlocked (converter, - srv, rtv, blend, blend_factor); + ret = gst_d3d11_converter_convert_unlocked (converter, srv, rtv); gst_d3d11_device_unlock (converter->device); return ret; @@ -1990,9 +2291,9 @@ gst_d3d11_converter_convert (GstD3D11Converter * converter, gboolean gst_d3d11_converter_convert_unlocked (GstD3D11Converter * converter, ID3D11ShaderResourceView * srv[GST_VIDEO_MAX_PLANES], - ID3D11RenderTargetView * rtv[GST_VIDEO_MAX_PLANES], - ID3D11BlendState * blend, gfloat blend_factor[4]) + ID3D11RenderTargetView * rtv[GST_VIDEO_MAX_PLANES]) { + GstD3D11ConverterPrivate *priv; ComPtr < ID3D11Resource > resource; ComPtr < ID3D11Texture2D > texture; D3D11_TEXTURE2D_DESC desc; @@ -2001,12 +2302,14 @@ gst_d3d11_converter_convert_unlocked (GstD3D11Converter * converter, UINT offsets = 0; UINT vertex_stride = sizeof (VertexData); ID3D11ShaderResourceView *clear_view[GST_VIDEO_MAX_PLANES] = { nullptr, }; + gboolean ret = TRUE; - g_return_val_if_fail (converter != nullptr, FALSE); + g_return_val_if_fail (GST_IS_D3D11_CONVERTER (converter), FALSE); g_return_val_if_fail (srv != nullptr, FALSE); g_return_val_if_fail (rtv != nullptr, FALSE); - cinfo = &converter->convert_info; + priv = converter->priv; + cinfo = &priv->convert_info; context = gst_d3d11_device_get_device_context_handle (converter->device); /* check texture resolution and update crop area */ @@ -2014,69 +2317,84 @@ gst_d3d11_converter_convert_unlocked (GstD3D11Converter * converter, resource.As (&texture); texture->GetDesc (&desc); - if (converter->update_vertex || - desc.Width != (guint) converter->input_texture_width || - desc.Height != (guint) converter->input_texture_height) { - GST_DEBUG ("Update vertext buffer, texture resolution: %dx%d", + g_mutex_lock (&priv->prop_lock); + if (priv->update_viewport && !gst_d3d11_converter_update_viewport (converter)) { + GST_ERROR_OBJECT (converter, "Failed to update viewport"); + ret = FALSE; + goto out; + } + + if (priv->update_vertex || + desc.Width != (guint) priv->input_texture_width || + desc.Height != (guint) priv->input_texture_height) { + GST_DEBUG_OBJECT (converter, + "Update vertext buffer, texture resolution: %dx%d", desc.Width, desc.Height); - converter->input_texture_width = desc.Width; - converter->input_texture_height = desc.Height; + priv->input_texture_width = desc.Width; + priv->input_texture_height = desc.Height; if (!gst_d3d11_converter_update_vertex_buffer (converter)) { - GST_ERROR ("Cannot update vertex buffer"); - return FALSE; + GST_ERROR_OBJECT (converter, "Cannot update vertex buffer"); + ret = FALSE; + goto out; } } - if (converter->update_alpha) { + if (priv->update_alpha) { D3D11_MAPPED_SUBRESOURCE map; PSConstBuffer *const_buffer; HRESULT hr; - hr = context->Map (converter->const_buffer, - 0, D3D11_MAP_WRITE_DISCARD, 0, &map); + hr = context->Map (priv->const_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); if (!gst_d3d11_result (hr, converter->device)) { - GST_ERROR ("Couldn't map constant buffer, hr: 0x%x", (guint) hr); - return FALSE; + GST_ERROR_OBJECT (converter, + "Couldn't map constant buffer, hr: 0x%x", (guint) hr); + ret = FALSE; + goto out; } const_buffer = (PSConstBuffer *) map.pData; - const_buffer->AlphaMul = converter->const_data.AlphaMul; + const_buffer->alpha = priv->const_data.alpha; - context->Unmap (converter->const_buffer, 0); - converter->update_alpha = FALSE; + context->Unmap (priv->const_buffer, 0); + priv->update_alpha = FALSE; } context->IASetPrimitiveTopology (D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - context->IASetInputLayout (converter->layout); - context->IASetVertexBuffers (0, 1, &converter->vertex_buffer, &vertex_stride, + context->IASetInputLayout (priv->layout); + context->IASetVertexBuffers (0, 1, &priv->vertex_buffer, &vertex_stride, &offsets); - context->IASetIndexBuffer (converter->index_buffer, DXGI_FORMAT_R16_UINT, 0); - context->PSSetSamplers (0, 1, &converter->linear_sampler); - context->VSSetShader (converter->vs, nullptr, 0); - context->PSSetConstantBuffers (0, 1, &converter->const_buffer); - context->PSSetShaderResources (0, converter->num_input_view, srv); - if (!converter->fast_path) { + context->IASetIndexBuffer (priv->index_buffer, DXGI_FORMAT_R16_UINT, 0); + context->PSSetSamplers (0, 1, &priv->linear_sampler); + context->VSSetShader (priv->vs, nullptr, 0); + context->PSSetConstantBuffers (0, 1, &priv->const_buffer); + context->PSSetShaderResources (0, priv->num_input_view, srv); + if (!priv->fast_path) { ID3D11ShaderResourceView *gamma_srv[2]; - gamma_srv[0] = converter->gamma_dec_srv; - gamma_srv[1] = converter->gamma_enc_srv; + gamma_srv[0] = priv->gamma_dec_srv; + gamma_srv[1] = priv->gamma_enc_srv; context->PSSetShaderResources (4, 2, gamma_srv); } - context->PSSetShader (converter->ps[0], nullptr, 0); - context->RSSetViewports (cinfo->ps_output[0]->num_rtv, converter->viewport); + context->PSSetShader (priv->ps[0], nullptr, 0); + context->RSSetViewports (cinfo->ps_output[0]->num_rtv, priv->viewport); context->OMSetRenderTargets (cinfo->ps_output[0]->num_rtv, rtv, nullptr); - context->OMSetBlendState (blend, blend_factor, 0xffffffff); + if (priv->blend) { + context->OMSetBlendState (priv->blend, + priv->blend_factor, priv->blend_sample_mask); + } else { + context->OMSetBlendState (nullptr, nullptr, 0xffffffff); + } context->DrawIndexed (6, 0, 0); - if (converter->ps[1]) { + if (priv->ps[1]) { guint view_offset = cinfo->ps_output[0]->num_rtv; - context->PSSetShader (converter->ps[1], nullptr, 0); + context->PSSetShader (priv->ps[1], nullptr, 0); context->RSSetViewports (cinfo->ps_output[1]->num_rtv, - &converter->viewport[view_offset]); + &priv->viewport[view_offset]); context->OMSetRenderTargets (cinfo->ps_output[1]->num_rtv, &rtv[view_offset], nullptr); context->DrawIndexed (6, 0, 0); @@ -2085,130 +2403,8 @@ gst_d3d11_converter_convert_unlocked (GstD3D11Converter * converter, context->PSSetShaderResources (0, 4, clear_view); context->OMSetRenderTargets (0, nullptr, nullptr); - return TRUE; -} - -gboolean -gst_d3d11_converter_update_viewport (GstD3D11Converter * converter, - const D3D11_VIEWPORT * viewport) -{ - g_return_val_if_fail (converter != nullptr, FALSE); - g_return_val_if_fail (viewport != nullptr, FALSE); - - converter->viewport[0] = *viewport; - - switch (GST_VIDEO_INFO_FORMAT (&converter->out_info)) { - 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: - case GST_VIDEO_FORMAT_I420: - case GST_VIDEO_FORMAT_YV12: - case GST_VIDEO_FORMAT_I420_10LE: - case GST_VIDEO_FORMAT_I420_12LE: - converter->viewport[1].TopLeftX = converter->viewport[0].TopLeftX / 2; - converter->viewport[1].TopLeftY = converter->viewport[0].TopLeftY / 2; - converter->viewport[1].Width = converter->viewport[0].Width / 2; - converter->viewport[1].Height = converter->viewport[0].Height / 2; - - for (guint i = 2; i < GST_VIDEO_INFO_N_PLANES (&converter->out_info); i++) - converter->viewport[i] = converter->viewport[1]; - - break; - case GST_VIDEO_FORMAT_Y42B: - case GST_VIDEO_FORMAT_I422_10LE: - case GST_VIDEO_FORMAT_I422_12LE: - converter->viewport[1].TopLeftX = converter->viewport[0].TopLeftX / 2; - converter->viewport[1].TopLeftY = converter->viewport[0].TopLeftY; - converter->viewport[1].Width = converter->viewport[0].Width / 2; - converter->viewport[1].Height = converter->viewport[0].Height; - - for (guint i = 2; i < GST_VIDEO_INFO_N_PLANES (&converter->out_info); i++) - converter->viewport[i] = converter->viewport[1]; - break; - case GST_VIDEO_FORMAT_Y444: - case GST_VIDEO_FORMAT_Y444_10LE: - case GST_VIDEO_FORMAT_Y444_12LE: - case GST_VIDEO_FORMAT_Y444_16LE: - for (guint i = 1; i < GST_VIDEO_INFO_N_PLANES (&converter->out_info); i++) - converter->viewport[i] = converter->viewport[0]; - break; - default: - if (converter->num_output_view > 1) - g_assert_not_reached (); - break; - } - - return TRUE; -} - -gboolean -gst_d3d11_converter_update_src_rect (GstD3D11Converter * converter, - const RECT * src_rect) -{ - g_return_val_if_fail (converter != nullptr, FALSE); - g_return_val_if_fail (src_rect != nullptr, FALSE); - - gst_d3d11_device_lock (converter->device); - if (converter->src_rect.left != src_rect->left || - converter->src_rect.top != src_rect->top || - converter->src_rect.right != src_rect->right || - converter->src_rect.bottom != src_rect->bottom) { - converter->src_rect = *src_rect; - - /* vertex buffer will be updated on next convert() call */ - converter->update_vertex = TRUE; - } - gst_d3d11_device_unlock (converter->device); - - return TRUE; -} - -gboolean -gst_d3d11_converter_update_dest_rect (GstD3D11Converter * converter, - const RECT * dest_rect) -{ - g_return_val_if_fail (converter != nullptr, FALSE); - g_return_val_if_fail (dest_rect != nullptr, FALSE); - - gst_d3d11_device_lock (converter->device); - if (converter->dest_rect.left != dest_rect->left || - converter->dest_rect.top != dest_rect->top || - converter->dest_rect.right != dest_rect->right || - converter->dest_rect.bottom != dest_rect->bottom) { - converter->dest_rect = *dest_rect; - - /* vertex buffer will be updated on next convert() call */ - converter->update_vertex = TRUE; - } - gst_d3d11_device_unlock (converter->device); - - return TRUE; -} - -gboolean -gst_d3d11_converter_update_config (GstD3D11Converter * converter, - GstStructure * config) -{ - gdouble alpha; - - g_return_val_if_fail (converter != nullptr, FALSE); - g_return_val_if_fail (config != nullptr, FALSE); - - gst_d3d11_device_lock (converter->device); - gst_d3d11_converter_set_config (converter, config); - - /* Check whether options are updated or not */ - alpha = GET_OPT_ALPHA_VALUE (converter); - - if (alpha != converter->const_data.AlphaMul) { - GST_DEBUG ("Updating alpha %lf -> %lf", - converter->const_data.AlphaMul, alpha); - converter->const_data.AlphaMul = alpha; - converter->update_alpha = TRUE; - } - gst_d3d11_device_unlock (converter->device); - - return TRUE; +out: + g_mutex_unlock (&priv->prop_lock); + + return ret; } diff --git a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11converter.h b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11converter.h index b4c21601b2..9285b31522 100644 --- a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11converter.h +++ b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11converter.h @@ -26,46 +26,50 @@ G_BEGIN_DECLS -typedef struct _GstD3D11Converter GstD3D11Converter; +#define GST_TYPE_D3D11_CONVERTER (gst_d3d11_converter_get_type()) +#define GST_D3D11_CONVERTER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_D3D11_CONVERTER,GstD3D11Converter)) +#define GST_D3D11_CONVERTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_D3D11_CONVERTER,GstD3D11ConverterClass)) +#define GST_D3D11_CONVERTER_GET_CLASS(obj) (GST_D3D11_CONVERTER_CLASS(G_OBJECT_GET_CLASS(obj))) +#define GST_IS_D3D11_CONVERTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_D3D11_CONVERTER)) +#define GST_IS_D3D11_CONVERTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_D3D11_CONVERTER)) +#define GST_D3D11_CONVERTER_CAST(obj) ((GstD3D11Converter*)(obj)) -/** - * GST_D3D11_CONVERTER_OPT_ALPHA_VALUE - * - * #G_TYPE_FLOAT, the alpha value color value to use. - * Default is 1.0 - */ -#define GST_D3D11_CONVERTER_OPT_ALPHA_VALUE "GstD3D11Converter.alpha-value" +typedef struct _GstD3D11Converter GstD3D11Converter; +typedef struct _GstD3D11ConverterClass GstD3D11ConverterClass; +typedef struct _GstD3D11ConverterPrivate GstD3D11ConverterPrivate; + +struct _GstD3D11Converter +{ + GstObject parent; + + GstD3D11Device *device; + + /*< private >*/ + GstD3D11ConverterPrivate *priv; + gpointer _gst_reserved[GST_PADDING]; +}; + +struct _GstD3D11ConverterClass +{ + GstObjectClass parent_class; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GType gst_d3d11_converter_get_type (void); GstD3D11Converter * gst_d3d11_converter_new (GstD3D11Device * device, const GstVideoInfo * in_info, - const GstVideoInfo * out_info, - GstStructure * config); - -void gst_d3d11_converter_free (GstD3D11Converter * converter); + const GstVideoInfo * out_info); gboolean gst_d3d11_converter_convert (GstD3D11Converter * converter, ID3D11ShaderResourceView *srv[GST_VIDEO_MAX_PLANES], - ID3D11RenderTargetView *rtv[GST_VIDEO_MAX_PLANES], - ID3D11BlendState *blend, - gfloat blend_factor[4]); + ID3D11RenderTargetView *rtv[GST_VIDEO_MAX_PLANES]); gboolean gst_d3d11_converter_convert_unlocked (GstD3D11Converter * converter, ID3D11ShaderResourceView *srv[GST_VIDEO_MAX_PLANES], - ID3D11RenderTargetView *rtv[GST_VIDEO_MAX_PLANES], - ID3D11BlendState *blend, - gfloat blend_factor[4]); - -gboolean gst_d3d11_converter_update_viewport (GstD3D11Converter * converter, - const D3D11_VIEWPORT * viewport); - -gboolean gst_d3d11_converter_update_src_rect (GstD3D11Converter * converter, - const RECT * src_rect); - -gboolean gst_d3d11_converter_update_dest_rect (GstD3D11Converter * converter, - const RECT * dest_rect); - -gboolean gst_d3d11_converter_update_config (GstD3D11Converter * converter, - GstStructure * config); + ID3D11RenderTargetView *rtv[GST_VIDEO_MAX_PLANES]); G_END_DECLS diff --git a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11testsrc.cpp b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11testsrc.cpp index 9facb535bc..d915ce1e82 100644 --- a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11testsrc.cpp +++ b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11testsrc.cpp @@ -1283,7 +1283,7 @@ gst_d3d11_test_src_clear_resource (GstD3D11TestSrc * self) } g_clear_pointer (&self->render, gst_d3d11_test_src_render_free); - g_clear_pointer (&self->converter, gst_d3d11_converter_free); + gst_clear_object (&self->converter); } static gboolean @@ -1297,7 +1297,7 @@ gst_d3d11_test_src_setup_resource (GstD3D11TestSrc * self, GstCaps * caps) gst_video_info_set_format (&draw_info, GST_VIDEO_FORMAT_RGBA, self->info.width, self->info.height); self->converter = gst_d3d11_converter_new (self->device, - &draw_info, &self->info, nullptr); + &draw_info, &self->info); if (!self->converter) { GST_ERROR_OBJECT (self, "Failed to create converter"); @@ -1775,7 +1775,7 @@ gst_d3d11_test_src_create (GstBaseSrc * bsrc, guint64 offset, gst_d3d11_device_lock (self->device); gst_d3d11_test_src_draw_pattern (self, context_handle, pattern_rtv); gst_d3d11_converter_convert_unlocked (self->converter, pattern_srv, - convert_rtv, nullptr, nullptr); + convert_rtv); gst_d3d11_device_unlock (self->device); gst_memory_unmap (mem, &render_info); diff --git a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11window.cpp b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11window.cpp index d0cba93586..b09c62f35a 100644 --- a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11window.cpp +++ b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11window.cpp @@ -265,13 +265,12 @@ gst_d3d11_window_dispose (GObject * object) { GstD3D11Window *self = GST_D3D11_WINDOW (object); - if (self->device) { + if (self->device) gst_d3d11_window_release_resources (self->device, self); - } g_clear_pointer (&self->processor, gst_d3d11_video_processor_free); - g_clear_pointer (&self->converter, gst_d3d11_converter_free); g_clear_pointer (&self->compositor, gst_d3d11_overlay_compositor_free); + gst_clear_object (&self->converter); gst_clear_buffer (&self->cached_buffer); gst_clear_object (&self->device); @@ -460,8 +459,8 @@ gst_d3d11_window_prepare_default (GstD3D11Window * window, guint display_width, /* Step 1: Clear old resources and objects */ gst_clear_buffer (&window->cached_buffer); g_clear_pointer (&window->processor, gst_d3d11_video_processor_free); - g_clear_pointer (&window->converter, gst_d3d11_converter_free); g_clear_pointer (&window->compositor, gst_d3d11_overlay_compositor_free); + gst_clear_object (&window->converter); window->processor_in_use = FALSE; @@ -576,6 +575,8 @@ gst_d3d11_window_prepare_default (GstD3D11Window * window, guint display_width, window->input_rect.right = GST_VIDEO_INFO_WIDTH (&window->info); window->input_rect.bottom = GST_VIDEO_INFO_HEIGHT (&window->info); + window->prev_input_rect = window->input_rect; + /* Step 4: Decide render color space and set it on converter/processor */ { GstVideoMasteringDisplayInfo minfo; @@ -721,7 +722,7 @@ gst_d3d11_window_prepare_default (GstD3D11Window * window, guint display_width, /* configure shader even if video processor is available for fallback */ window->converter = gst_d3d11_converter_new (window->device, &window->info, - &window->render_info, nullptr); + &window->render_info); if (!window->converter) { GST_ERROR_OBJECT (window, "Cannot create converter"); @@ -846,13 +847,19 @@ gst_d3d11_window_do_convert (GstD3D11Window * self, ID3D11ShaderResourceView * srv[GST_VIDEO_MAX_PLANES], ID3D11RenderTargetView * rtv, RECT * input_rect) { - if (!gst_d3d11_converter_update_src_rect (self->converter, input_rect)) { - GST_ERROR_OBJECT (self, "Failed to update src rect"); - return FALSE; + RECT *prev = &self->prev_input_rect; + + if (input_rect->left != prev->left || input_rect->top != prev->top || + input_rect->right != prev->right || input_rect->bottom != prev->bottom) { + g_object_set (self->converter, "src-x", (gint) input_rect->left, + "src-y", (gint) input_rect->top, + "src-width", (gint) (input_rect->right - input_rect->left), + "src-height", (gint) (input_rect->bottom - input_rect->top), nullptr); + + *prev = *input_rect; } - if (!gst_d3d11_converter_convert_unlocked (self->converter, - srv, &rtv, NULL, NULL)) { + if (!gst_d3d11_converter_convert_unlocked (self->converter, srv, &rtv)) { GST_ERROR_OBJECT (self, "Couldn't render to backbuffer using converter"); return FALSE; } else { @@ -934,7 +941,13 @@ gst_d3d111_window_present (GstD3D11Window * self, GstBuffer * buffer, viewport.Height = self->render_rect.bottom - self->render_rect.top; viewport.MinDepth = 0.0f; viewport.MaxDepth = 1.0f; - gst_d3d11_converter_update_viewport (self->converter, &viewport); + + g_object_set (self->converter, "dest-x", (gint) self->render_rect.left, + "dest-y", (gint) self->render_rect.top, + "dest-width", + (gint) (self->render_rect.right - self->render_rect.left), + "dest-height", + (gint) (self->render_rect.bottom - self->render_rect.top), nullptr); gst_d3d11_overlay_compositor_update_viewport (self->compositor, &viewport); } diff --git a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11window.h b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11window.h index 8d35b4ef8c..585157f032 100644 --- a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11window.h +++ b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11window.h @@ -108,6 +108,7 @@ struct _GstD3D11Window /* input resolution */ RECT input_rect; + RECT prev_input_rect; /* requested rect via gst_d3d11_window_render */ GstVideoRectangle rect; diff --git a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11window_dummy.cpp b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11window_dummy.cpp index 7cffb5bdbb..6b0e8968f3 100644 --- a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11window_dummy.cpp +++ b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11window_dummy.cpp @@ -86,8 +86,8 @@ gst_d3d11_window_dummy_prepare (GstD3D11Window * window, gboolean * video_processor_available, GError ** error) { g_clear_pointer (&window->processor, gst_d3d11_video_processor_free); - g_clear_pointer (&window->converter, gst_d3d11_converter_free); g_clear_pointer (&window->compositor, gst_d3d11_overlay_compositor_free); + gst_clear_object (&window->converter); /* We are supporting only RGBA, BGRA or RGB10A2_LE formats but we don't know * which format texture will be used at this moment */ @@ -172,7 +172,7 @@ gst_d3d11_window_dummy_prepare (GstD3D11Window * window, window->converter = gst_d3d11_converter_new (window->device, &window->info, - &window->render_info, nullptr); + &window->render_info); if (!window->converter) { GST_ERROR_OBJECT (window, "Cannot create converter"); diff --git a/subprojects/gst-plugins-bad/sys/d3d11/plugin.cpp b/subprojects/gst-plugins-bad/sys/d3d11/plugin.cpp index 987fe4ae38..6a19f120f3 100644 --- a/subprojects/gst-plugins-bad/sys/d3d11/plugin.cpp +++ b/subprojects/gst-plugins-bad/sys/d3d11/plugin.cpp @@ -85,7 +85,6 @@ GST_DEBUG_CATEGORY (gst_d3d11_debug); GST_DEBUG_CATEGORY (gst_d3d11_shader_debug); -GST_DEBUG_CATEGORY (gst_d3d11_converter_debug); GST_DEBUG_CATEGORY (gst_d3d11_plugin_utils_debug); GST_DEBUG_CATEGORY (gst_d3d11_format_debug); GST_DEBUG_CATEGORY (gst_d3d11_device_debug); @@ -119,8 +118,6 @@ plugin_init (GstPlugin * plugin) GST_DEBUG_CATEGORY_INIT (gst_d3d11_debug, "d3d11", 0, "direct3d 11 plugin"); GST_DEBUG_CATEGORY_INIT (gst_d3d11_shader_debug, "d3d11shader", 0, "d3d11shader"); - GST_DEBUG_CATEGORY_INIT (gst_d3d11_converter_debug, - "d3d11converter", 0, "d3d11converter"); GST_DEBUG_CATEGORY_INIT (gst_d3d11_plugin_utils_debug, "d3d11pluginutils", 0, "d3d11 plugin utility functions"); GST_DEBUG_CATEGORY_INIT (gst_d3d11_overlay_compositor_debug,