From 615f52f2f7898925622ec30b581c83dd7a31920e Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Sat, 13 Mar 2021 22:47:55 +0900 Subject: [PATCH] d3d11device: Hold ID3D11VideoDevice and ID3D11VideoContext object ... instead of QueryInterface-ing per elements. Note that ID3D11VideoDevice and ID3D11VideoContext objects might not be available if device doesn't support video interface. So GstD3D11Device object will create those objects only when requested. Part-of: --- gst-libs/gst/d3d11/gstd3d11device.c | 82 ++++++++++++++++++++++++++++ gst-libs/gst/d3d11/gstd3d11device.h | 6 ++ sys/d3d11/gstd3d11decoder.cpp | 38 +++++-------- sys/d3d11/gstd3d11deinterlace.cpp | 31 +++++------ sys/d3d11/gstd3d11videoprocessor.cpp | 29 ++++++---- 5 files changed, 134 insertions(+), 52 deletions(-) diff --git a/gst-libs/gst/d3d11/gstd3d11device.c b/gst-libs/gst/d3d11/gstd3d11device.c index df075246b7..fd40ead5ef 100644 --- a/gst-libs/gst/d3d11/gstd3d11device.c +++ b/gst-libs/gst/d3d11/gstd3d11device.c @@ -103,10 +103,14 @@ struct _GstD3D11DevicePrivate ID3D11Device *device; ID3D11DeviceContext *device_context; + ID3D11VideoDevice *video_device; + ID3D11VideoContext *video_context; + IDXGIFactory1 *factory; GstD3D11Format format_table[GST_D3D11_N_FORMATS]; GRecMutex extern_lock; + GMutex resource_lock; #if HAVE_D3D11SDKLAYERS_H ID3D11Debug *d3d11_debug; @@ -409,6 +413,7 @@ gst_d3d11_device_init (GstD3D11Device * self) priv->adapter = DEFAULT_ADAPTER; g_rec_mutex_init (&priv->extern_lock); + g_mutex_init (&priv->resource_lock); self->priv = priv; } @@ -894,6 +899,16 @@ gst_d3d11_device_dispose (GObject * object) GST_LOG_OBJECT (self, "dispose"); + if (priv->video_device) { + ID3D11VideoDevice_Release (priv->video_device); + priv->video_device = NULL; + } + + if (priv->video_context) { + ID3D11VideoContext_Release (priv->video_context); + priv->video_context = NULL; + } + if (priv->device) { ID3D11Device_Release (priv->device); priv->device = NULL; @@ -952,6 +967,7 @@ gst_d3d11_device_finalize (GObject * object) GST_LOG_OBJECT (self, "finalize"); g_rec_mutex_clear (&priv->extern_lock); + g_mutex_clear (&priv->resource_lock); g_free (priv->description); G_OBJECT_CLASS (parent_class)->finalize (object); @@ -1046,6 +1062,72 @@ gst_d3d11_device_get_dxgi_factory_handle (GstD3D11Device * device) return device->priv->factory; } +/** + * gst_d3d11_device_get_video_device_handle: + * @device: a #GstD3D11Device + * + * Used for various D3D11 APIs directly. Caller must not destroy returned device + * object. + * + * Returns: (nullable) (transfer none) : the ID3D11VideoDevice handle or %NULL + * if ID3D11VideoDevice is unavailable. + * + * Since: 1.20 + */ +ID3D11VideoDevice * +gst_d3d11_device_get_video_device_handle (GstD3D11Device * device) +{ + GstD3D11DevicePrivate *priv; + + g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL); + + priv = device->priv; + g_mutex_lock (&priv->resource_lock); + if (!priv->video_device) { + HRESULT hr; + + hr = ID3D11Device_QueryInterface (priv->device, &IID_ID3D11VideoDevice, + (void **) &priv->video_device); + gst_d3d11_result (hr, device); + } + g_mutex_unlock (&priv->resource_lock); + + return priv->video_device; +} + +/** + * gst_d3d11_device_get_video_context_handle: + * @device: a #GstD3D11Device + * + * Used for various D3D11 APIs directly. Caller must not destroy returned device + * object. + * + * Returns: (nullable) (transfer none): the ID3D11VideoContext handle or %NULL + * if ID3D11VideoContext is unavailable. + * + * Since: 1.20 + */ +ID3D11VideoContext * +gst_d3d11_device_get_video_context_handle (GstD3D11Device * device) +{ + GstD3D11DevicePrivate *priv; + + g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL); + + priv = device->priv; + g_mutex_lock (&priv->resource_lock); + if (!priv->video_context) { + HRESULT hr; + + hr = ID3D11DeviceContext_QueryInterface (priv->device_context, + &IID_ID3D11VideoContext, (void **) &priv->video_context); + gst_d3d11_result (hr, device); + } + g_mutex_unlock (&priv->resource_lock); + + return priv->video_context; +} + /** * gst_d3d11_device_lock: * @device: a #GstD3D11Device diff --git a/gst-libs/gst/d3d11/gstd3d11device.h b/gst-libs/gst/d3d11/gstd3d11device.h index d63d4bfe3b..fd5d77d3ff 100644 --- a/gst-libs/gst/d3d11/gstd3d11device.h +++ b/gst-libs/gst/d3d11/gstd3d11device.h @@ -71,6 +71,12 @@ ID3D11DeviceContext * gst_d3d11_device_get_device_context_handle (GstD3D11Device GST_D3D11_API IDXGIFactory1 * gst_d3d11_device_get_dxgi_factory_handle (GstD3D11Device * device); +GST_D3D11_API +ID3D11VideoDevice * gst_d3d11_device_get_video_device_handle (GstD3D11Device * device); + +GST_D3D11_API +ID3D11VideoContext * gst_d3d11_device_get_video_context_handle (GstD3D11Device * device); + GST_D3D11_API void gst_d3d11_device_lock (GstD3D11Device * device); diff --git a/sys/d3d11/gstd3d11decoder.cpp b/sys/d3d11/gstd3d11decoder.cpp index 6cf25723d6..d78bebb2cd 100644 --- a/sys/d3d11/gstd3d11decoder.cpp +++ b/sys/d3d11/gstd3d11decoder.cpp @@ -150,43 +150,31 @@ gst_d3d11_decoder_constructed (GObject * object) { GstD3D11Decoder *self = GST_D3D11_DECODER (object); GstD3D11DecoderPrivate *priv = self->priv; - HRESULT hr; - ID3D11Device *device_handle; - ID3D11DeviceContext *device_context_handle; + ID3D11VideoDevice *video_device; + ID3D11VideoContext *video_context; if (!priv->device) { GST_ERROR_OBJECT (self, "No D3D11Device available"); return; } - device_handle = gst_d3d11_device_get_device_handle (priv->device); - device_context_handle = - gst_d3d11_device_get_device_context_handle (priv->device); - - hr = device_handle->QueryInterface (IID_PPV_ARGS (&priv->video_device)); - if (!gst_d3d11_result (hr, priv->device) || !priv->video_device) { - GST_WARNING_OBJECT (self, "Cannot create VideoDevice Object: 0x%x", - (guint) hr); - priv->video_device = NULL; - + video_device = gst_d3d11_device_get_video_device_handle (priv->device); + if (!video_device) { + GST_ERROR_OBJECT (self, "ID3D11VideoDevice is not available"); return; } - hr = device_context_handle-> - QueryInterface (IID_PPV_ARGS (&priv->video_context)); - if (!gst_d3d11_result (hr, priv->device) || !priv->video_context) { - GST_WARNING_OBJECT (self, "Cannot create VideoContext Object: 0x%x", - (guint) hr); - priv->video_context = NULL; - - goto fail; + video_context = gst_d3d11_device_get_video_context_handle (priv->device); + if (!video_context) { + GST_ERROR_OBJECT (self, "ID3D11VideoContext is not available"); + return; } - return; + priv->video_device = video_device; + video_device->AddRef (); -fail: - GST_D3D11_CLEAR_COM (priv->video_device); - GST_D3D11_CLEAR_COM (priv->video_context); + priv->video_context = video_context; + video_context->AddRef (); return; } diff --git a/sys/d3d11/gstd3d11deinterlace.cpp b/sys/d3d11/gstd3d11deinterlace.cpp index 59b09d6457..7c1ddd0e91 100644 --- a/sys/d3d11/gstd3d11deinterlace.cpp +++ b/sys/d3d11/gstd3d11deinterlace.cpp @@ -603,27 +603,26 @@ gst_d3d11_deinterlace_set_context (GstElement * element, GstContext * context) static gboolean gst_d3d11_deinterlace_open (GstD3D11Deinterlace * self) { - HRESULT hr; - ID3D11Device *device_handle; - ID3D11DeviceContext *context_handle; - /* *INDENT-OFF* */ - ComPtr video_device; - ComPtr video_context; - /* *INDENT-ON* */ + ID3D11VideoDevice *video_device; + ID3D11VideoContext *video_context; - device_handle = gst_d3d11_device_get_device_handle (self->device); - context_handle = gst_d3d11_device_get_device_context_handle (self->device); - - hr = device_handle->QueryInterface (IID_PPV_ARGS (&video_device)); - if (!gst_d3d11_result (hr, self->device)) + video_device = gst_d3d11_device_get_video_device_handle (self->device); + if (!video_device) { + GST_ERROR_OBJECT (self, "ID3D11VideoDevice is not availale"); return FALSE; + } - hr = context_handle->QueryInterface (IID_PPV_ARGS (&video_context)); - if (!gst_d3d11_result (hr, self->device)) + video_context = gst_d3d11_device_get_video_context_handle (self->device); + if (!video_context) { + GST_ERROR_OBJECT (self, "ID3D11VideoContext is not available"); return FALSE; + } - self->video_device = video_device.Detach (); - self->video_context = video_context.Detach (); + self->video_device = video_device; + video_device->AddRef (); + + self->video_context = video_context; + video_context->AddRef (); return TRUE; } diff --git a/sys/d3d11/gstd3d11videoprocessor.cpp b/sys/d3d11/gstd3d11videoprocessor.cpp index e9c770b322..e1b4b5cee2 100644 --- a/sys/d3d11/gstd3d11videoprocessor.cpp +++ b/sys/d3d11/gstd3d11videoprocessor.cpp @@ -68,28 +68,35 @@ gst_d3d11_video_processor_new (GstD3D11Device * device, guint in_width, guint in_height, guint out_width, guint out_height) { GstD3D11VideoProcessor *self; - ID3D11Device *device_handle; - ID3D11DeviceContext *context_handle; + ID3D11VideoDevice *video_device; + ID3D11VideoContext *video_context; HRESULT hr; D3D11_VIDEO_PROCESSOR_CONTENT_DESC desc; g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL); - memset (&desc, 0, sizeof (desc)); + video_device = gst_d3d11_device_get_video_device_handle (device); + if (!video_device) { + GST_WARNING_OBJECT (device, "ID3D11VideoDevice is not available"); + return NULL; + } - device_handle = gst_d3d11_device_get_device_handle (device); - context_handle = gst_d3d11_device_get_device_context_handle (device); + video_context = gst_d3d11_device_get_video_context_handle (device); + if (!video_context) { + GST_WARNING_OBJECT (device, "ID3D11VideoContext is not availale"); + return NULL; + } + + memset (&desc, 0, sizeof (desc)); self = g_new0 (GstD3D11VideoProcessor, 1); self->device = (GstD3D11Device *) gst_object_ref (device); - hr = device_handle->QueryInterface (IID_PPV_ARGS (&self->video_device)); - if (!gst_d3d11_result (hr, device)) - goto fail; + self->video_device = video_device; + video_device->AddRef (); - hr = context_handle->QueryInterface (IID_PPV_ARGS (&self->video_context)); - if (!gst_d3d11_result (hr, device)) - goto fail; + self->video_context = video_context; + video_context->AddRef (); /* FIXME: Add support intelace */ desc.InputFrameFormat = D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE;