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: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/2079>
This commit is contained in:
Seungha Yang 2021-03-13 22:47:55 +09:00
parent b08310f748
commit 615f52f2f7
5 changed files with 134 additions and 52 deletions

View file

@ -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

View file

@ -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);

View file

@ -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;
}

View file

@ -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<ID3D11VideoDevice> video_device;
ComPtr<ID3D11VideoContext> 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;
}

View file

@ -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;