2 * Copyright (C) 2019 Seungha Yang <seungha.yang@navercorp.com>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
24 #include "gstd3d11device.h"
27 #ifdef HAVE_D3D11SDKLAYER_H
28 #include <d3d11sdklayers.h>
31 GST_DEBUG_CATEGORY_STATIC (GST_CAT_CONTEXT);
32 GST_DEBUG_CATEGORY_STATIC (gst_d3d11_device_debug);
33 #define GST_CAT_DEFAULT gst_d3d11_device_debug
35 #ifdef HAVE_D3D11SDKLAYER_H
36 static GModule *sdk_layer = NULL;
45 #define DEFAULT_ADAPTER -1
47 struct _GstD3D11DevicePrivate
52 ID3D11DeviceContext *device_context;
54 IDXGIFactory1 *factory;
55 GstD3D11DXGIFactoryVersion factory_ver;
57 ID3D11VideoDevice *video_device;
58 ID3D11VideoContext *video_context;
63 GThread *active_thread;
65 GMainContext *main_context;
67 #ifdef HAVE_D3D11SDKLAYER_H
69 ID3D11InfoQueue *info_queue;
73 #define gst_d3d11_device_parent_class parent_class
74 G_DEFINE_TYPE_WITH_PRIVATE (GstD3D11Device, gst_d3d11_device, GST_TYPE_OBJECT);
76 static void gst_d3d11_device_set_property (GObject * object, guint prop_id,
77 const GValue * value, GParamSpec * pspec);
78 static void gst_d3d11_device_get_property (GObject * object, guint prop_id,
79 GValue * value, GParamSpec * pspec);
80 static void gst_d3d11_device_constructed (GObject * object);
81 static void gst_d3d11_device_dispose (GObject * object);
82 static void gst_d3d11_device_finalize (GObject * object);
84 static gpointer gst_d3d11_device_thread_func (gpointer data);
86 #ifdef HAVE_D3D11SDKLAYER_H
88 gst_d3d11_device_enable_debug_layer (void)
90 static volatile gsize _init = 0;
92 if (g_once_init_enter (&_init)) {
93 sdk_layer = g_module_open ("d3d11sdklayers.dll", G_MODULE_BIND_LAZY);
96 sdk_layer = g_module_open ("d3d11_1sdklayers.dll", G_MODULE_BIND_LAZY);
98 g_once_init_leave (&_init, 1);
105 gst_d3d11_device_get_message (GstD3D11Device * self)
107 GstD3D11DevicePrivate *priv = self->priv;
113 num_msg = ID3D11InfoQueue_GetNumStoredMessages (priv->info_queue);
115 for (i = 0; i < num_msg; i++) {
116 hr = ID3D11InfoQueue_GetMessage (priv->info_queue, i, NULL, &msg_len);
118 if (FAILED (hr) || msg_len == 0) {
119 return G_SOURCE_CONTINUE;
122 msg = (D3D11_MESSAGE *) g_malloc0 (msg_len);
123 hr = ID3D11InfoQueue_GetMessage (priv->info_queue, i, msg, &msg_len);
125 GST_TRACE_OBJECT (self, "D3D11 Message - %s", msg->pDescription);
129 ID3D11InfoQueue_ClearStoredMessages (priv->info_queue);
131 return G_SOURCE_CONTINUE;
136 gst_d3d11_device_class_init (GstD3D11DeviceClass * klass)
138 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
140 gobject_class->set_property = gst_d3d11_device_set_property;
141 gobject_class->get_property = gst_d3d11_device_get_property;
142 gobject_class->constructed = gst_d3d11_device_constructed;
143 gobject_class->dispose = gst_d3d11_device_dispose;
144 gobject_class->finalize = gst_d3d11_device_finalize;
146 g_object_class_install_property (gobject_class, PROP_ADAPTER,
147 g_param_spec_int ("adapter", "Adapter",
148 "Adapter index for creating device (-1 for default)",
149 -1, G_MAXINT32, DEFAULT_ADAPTER,
150 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
152 GST_DEBUG_CATEGORY_INIT (gst_d3d11_device_debug,
153 "d3d11device", 0, "d3d11 device");
154 GST_DEBUG_CATEGORY_GET (GST_CAT_CONTEXT, "GST_CONTEXT");
158 gst_d3d11_device_init (GstD3D11Device * self)
160 GstD3D11DevicePrivate *priv;
162 priv = gst_d3d11_device_get_instance_private (self);
163 priv->adapter = DEFAULT_ADAPTER;
165 g_mutex_init (&priv->lock);
166 g_cond_init (&priv->cond);
168 priv->main_context = g_main_context_new ();
169 priv->loop = g_main_loop_new (priv->main_context, FALSE);
175 _relase_adapter (IDXGIAdapter1 * adapter)
177 IDXGIAdapter1_Release (adapter);
181 gst_d3d11_device_constructed (GObject * object)
183 GstD3D11Device *self = GST_D3D11_DEVICE (object);
184 GstD3D11DevicePrivate *priv = self->priv;
185 IDXGIAdapter1 *adapter = NULL;
186 GList *adapter_list = NULL;
187 GList *hw_adapter_list = NULL;
188 IDXGIFactory1 *factory = NULL;
191 guint num_adapter = 0;
192 UINT d3d11_flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
194 static const D3D_DRIVER_TYPE driver_types[] = {
195 D3D_DRIVER_TYPE_HARDWARE,
196 D3D_DRIVER_TYPE_WARP,
197 D3D_DRIVER_TYPE_UNKNOWN
199 static const D3D_FEATURE_LEVEL feature_levels[] = {
200 D3D_FEATURE_LEVEL_11_1,
201 D3D_FEATURE_LEVEL_11_0,
202 D3D_FEATURE_LEVEL_10_1,
203 D3D_FEATURE_LEVEL_10_0,
204 D3D_FEATURE_LEVEL_9_3,
205 D3D_FEATURE_LEVEL_9_2,
206 D3D_FEATURE_LEVEL_9_1
208 D3D_FEATURE_LEVEL selected_level;
210 #ifdef HAVE_DXGI_1_5_H
211 hr = CreateDXGIFactory1 (&IID_IDXGIFactory5, (void **) &factory);
213 GST_INFO_OBJECT (self, "IDXGIFactory5 was unavailable");
217 priv->factory_ver = GST_D3D11_DXGI_FACTORY_5;
221 priv->factory_ver = GST_D3D11_DXGI_FACTORY_1;
222 hr = CreateDXGIFactory1 (&IID_IDXGIFactory1, (void **) &factory);
226 GST_ERROR_OBJECT (self, "cannot create dxgi factory, hr: 0x%x", (guint) hr);
230 while (IDXGIFactory1_EnumAdapters1 (factory, num_adapter,
231 &adapter) != DXGI_ERROR_NOT_FOUND) {
232 DXGI_ADAPTER_DESC1 desc;
234 hr = IDXGIAdapter1_GetDesc1 (adapter, &desc);
235 if (SUCCEEDED (hr)) {
236 gchar *vender = NULL;
238 vender = g_utf16_to_utf8 (desc.Description, -1, NULL, NULL, NULL);
239 GST_DEBUG_OBJECT (self,
240 "adapter index %d: D3D11 device vendor-id: 0x%04x, device-id: 0x%04x, "
242 num_adapter, desc.VendorId, desc.DeviceId, desc.Flags, vender);
245 /* DXGI_ADAPTER_FLAG_SOFTWARE is missing in dxgi.h of mingw */
246 if ((desc.Flags & 0x2) != 0x2) {
247 hw_adapter_list = g_list_append (hw_adapter_list, adapter);
248 IDXGIAdapter1_AddRef (adapter);
252 adapter_list = g_list_append (adapter_list, adapter);
256 if (priv->adapter >= 0 && priv->adapter < num_adapter)
261 if (priv->adapter >= 0) {
262 if (priv->adapter >= num_adapter) {
263 GST_WARNING_OBJECT (self,
264 "Requested index %d is out of scope for adapter", priv->adapter);
266 adapter = (IDXGIAdapter1 *) g_list_nth_data (adapter_list, priv->adapter);
268 } else if (hw_adapter_list) {
269 adapter = (IDXGIAdapter1 *) g_list_nth_data (hw_adapter_list, 0);
270 } else if (adapter_list) {
271 adapter = (IDXGIAdapter1 *) g_list_nth_data (adapter_list, 0);
275 IDXGIAdapter1_AddRef (adapter);
277 #ifdef HAVE_D3D11SDKLAYER_H
278 if (gst_debug_category_get_threshold (GST_CAT_DEFAULT) >= GST_LEVEL_TRACE) {
279 /* DirectX SDK should be installed on system for this */
280 if (gst_d3d11_device_enable_debug_layer ()) {
281 GST_INFO_OBJECT (self, "sdk layer library was loaded");
282 d3d11_flags |= D3D11_CREATE_DEVICE_DEBUG;
288 hr = D3D11CreateDevice ((IDXGIAdapter *) adapter, D3D_DRIVER_TYPE_UNKNOWN,
289 NULL, d3d11_flags, feature_levels, G_N_ELEMENTS (feature_levels),
290 D3D11_SDK_VERSION, &priv->device, &selected_level,
291 &priv->device_context);
294 /* Retry if the system could not recognize D3D_FEATURE_LEVEL_11_1 */
295 hr = D3D11CreateDevice ((IDXGIAdapter *) adapter, D3D_DRIVER_TYPE_UNKNOWN,
296 NULL, d3d11_flags, &feature_levels[1],
297 G_N_ELEMENTS (feature_levels) - 1, D3D11_SDK_VERSION, &priv->device,
298 &selected_level, &priv->device_context);
301 if (SUCCEEDED (hr)) {
302 GST_DEBUG_OBJECT (self, "Selected feature level 0x%x", selected_level);
305 for (i = 0; i < G_N_ELEMENTS (driver_types); i++) {
306 hr = D3D11CreateDevice (NULL, driver_types[i], NULL,
308 feature_levels, G_N_ELEMENTS (feature_levels),
309 D3D11_SDK_VERSION, &priv->device, &selected_level,
310 &priv->device_context);
313 /* Retry if the system could not recognize D3D_FEATURE_LEVEL_11_1 */
314 hr = D3D11CreateDevice (NULL, driver_types[i], NULL,
316 &feature_levels[1], G_N_ELEMENTS (feature_levels) - 1,
317 D3D11_SDK_VERSION, &priv->device, &selected_level,
318 &priv->device_context);
321 if (SUCCEEDED (hr)) {
322 GST_DEBUG_OBJECT (self, "Selected driver type 0x%x, feature level 0x%x",
323 driver_types[i], selected_level);
330 GST_ERROR_OBJECT (self, "cannot create d3d11 device, hr: 0x%x", (guint) hr);
334 priv->factory = factory;
337 IDXGIAdapter1_Release (adapter);
340 g_list_free_full (adapter_list, (GDestroyNotify) _relase_adapter);
343 g_list_free_full (hw_adapter_list, (GDestroyNotify) _relase_adapter);
345 #ifdef HAVE_D3D11SDKLAYER_H
346 if ((d3d11_flags & D3D11_CREATE_DEVICE_DEBUG) == D3D11_CREATE_DEVICE_DEBUG) {
348 ID3D11InfoQueue *info_queue;
350 hr = ID3D11Device_QueryInterface (priv->device,
351 &IID_ID3D11Debug, (void **) &debug);
353 if (SUCCEEDED (hr)) {
354 GST_DEBUG_OBJECT (self, "D3D11Debug interface available");
355 ID3D11Debug_ReportLiveDeviceObjects (debug, D3D11_RLDO_DETAIL);
359 hr = ID3D11Device_QueryInterface (priv->device,
360 &IID_ID3D11InfoQueue, (void **) &info_queue);
361 if (SUCCEEDED (hr)) {
364 GST_DEBUG_OBJECT (self, "D3D11InfoQueue interface available");
365 priv->info_queue = info_queue;
367 source = g_idle_source_new ();
368 g_source_set_callback (source, (GSourceFunc) gst_d3d11_device_get_message,
371 g_source_attach (source, priv->main_context);
372 g_source_unref (source);
377 g_mutex_lock (&priv->lock);
378 priv->thread = g_thread_new ("GstD3D11Device",
379 (GThreadFunc) gst_d3d11_device_thread_func, self);
380 while (!g_main_loop_is_running (priv->loop))
381 g_cond_wait (&priv->cond, &priv->lock);
382 g_mutex_unlock (&priv->lock);
384 G_OBJECT_CLASS (parent_class)->constructed (object);
390 IDXGIFactory1_Release (factory);
393 IDXGIAdapter1_Release (adapter);
396 g_list_free_full (adapter_list, (GDestroyNotify) _relase_adapter);
399 g_list_free_full (hw_adapter_list, (GDestroyNotify) _relase_adapter);
401 G_OBJECT_CLASS (parent_class)->constructed (object);
407 gst_d3d11_device_set_property (GObject * object, guint prop_id,
408 const GValue * value, GParamSpec * pspec)
410 GstD3D11Device *self = GST_D3D11_DEVICE (object);
411 GstD3D11DevicePrivate *priv = self->priv;
415 priv->adapter = g_value_get_int (value);
418 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
424 gst_d3d11_device_get_property (GObject * object, guint prop_id,
425 GValue * value, GParamSpec * pspec)
427 GstD3D11Device *self = GST_D3D11_DEVICE (object);
428 GstD3D11DevicePrivate *priv = self->priv;
432 g_value_set_int (value, priv->adapter);
435 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
441 gst_d3d11_device_dispose (GObject * object)
443 GstD3D11Device *self = GST_D3D11_DEVICE (object);
444 GstD3D11DevicePrivate *priv = self->priv;
446 GST_LOG_OBJECT (self, "dispose");
449 g_main_loop_quit (priv->loop);
453 g_thread_join (priv->thread);
458 g_main_loop_unref (priv->loop);
462 if (priv->main_context) {
463 g_main_context_unref (priv->main_context);
464 priv->main_context = NULL;
466 #ifdef HAVE_D3D11SDKLAYER_H
468 ID3D11Debug_Release (priv->debug);
472 if (priv->info_queue) {
473 ID3D11InfoQueue_ClearStoredMessages (priv->info_queue);
474 ID3D11InfoQueue_Release (priv->info_queue);
475 priv->info_queue = NULL;
480 ID3D11Device_Release (priv->device);
484 if (priv->device_context) {
485 ID3D11DeviceContext_Release (priv->device_context);
486 priv->device_context = NULL;
489 if (priv->video_device) {
490 ID3D11VideoDevice_Release (priv->video_device);
491 priv->video_device = NULL;
494 if (priv->video_context) {
495 ID3D11VideoContext_Release (priv->video_context);
496 priv->video_context = NULL;
500 IDXGIFactory1_Release (priv->factory);
501 priv->factory = NULL;
504 G_OBJECT_CLASS (parent_class)->dispose (object);
508 gst_d3d11_device_finalize (GObject * object)
510 GstD3D11Device *self = GST_D3D11_DEVICE (object);
511 GstD3D11DevicePrivate *priv = self->priv;
513 GST_LOG_OBJECT (self, "finalize");
515 g_mutex_clear (&priv->lock);
516 g_cond_clear (&priv->cond);
518 G_OBJECT_CLASS (parent_class)->finalize (object);
522 running_cb (gpointer user_data)
524 GstD3D11Device *self = GST_D3D11_DEVICE (user_data);
525 GstD3D11DevicePrivate *priv = self->priv;
527 GST_TRACE_OBJECT (self, "Main loop running now");
529 g_mutex_lock (&priv->lock);
530 g_cond_signal (&priv->cond);
531 g_mutex_unlock (&priv->lock);
533 return G_SOURCE_REMOVE;
537 gst_d3d11_device_thread_func (gpointer data)
539 GstD3D11Device *self = GST_D3D11_DEVICE (data);
540 GstD3D11DevicePrivate *priv = self->priv;
543 GST_DEBUG_OBJECT (self, "Enter loop");
544 g_main_context_push_thread_default (priv->main_context);
546 source = g_idle_source_new ();
547 g_source_set_callback (source, (GSourceFunc) running_cb, self, NULL);
548 g_source_attach (source, priv->main_context);
549 g_source_unref (source);
551 priv->active_thread = g_thread_self ();
552 g_main_loop_run (priv->loop);
554 g_main_context_pop_thread_default (priv->main_context);
556 GST_DEBUG_OBJECT (self, "Exit loop");
562 * gst_d3d11_device_new:
563 * @adapter: the index of adapter for creating d3d11 device (-1 for default)
565 * Returns: (transfer full) (nullable): a new #GstD3D11Device for @adapter or %NULL
566 * when failed to create D3D11 device with given adapter index.
569 gst_d3d11_device_new (gint adapter)
571 GstD3D11Device *device = NULL;
572 GstD3D11DevicePrivate *priv;
573 static volatile gsize _init = 0;
575 if (g_once_init_enter (&_init)) {
576 GST_DEBUG_CATEGORY_INIT (gst_d3d11_device_debug, "d3d11device", 0,
578 g_once_init_leave (&_init, 1);
581 device = g_object_new (GST_TYPE_D3D11_DEVICE, "adapter", adapter, NULL);
585 if (!priv->device || !priv->device_context) {
586 GST_ERROR ("Cannot create d3d11 device");
587 g_object_unref (device);
595 * gst_d3d11_device_get_device:
596 * @device: a #GstD3D11Device
598 * Used for various D3D11 APIs directly.
599 * Caller must not destroy returned device object.
601 * Returns: (transfer none): the ID3D11Device
604 gst_d3d11_device_get_device (GstD3D11Device * device)
606 g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL);
608 return device->priv->device;
612 * gst_d3d11_device_get_device_context:
613 * @device: a #GstD3D11Device
615 * Used for various D3D11 APIs directly.
616 * Caller must not destroy returned device object.
618 * Returns: (transfer none): the ID3D11DeviceContext
620 ID3D11DeviceContext *
621 gst_d3d11_device_get_device_context (GstD3D11Device * device)
623 g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL);
625 return device->priv->device_context;
628 GstD3D11DXGIFactoryVersion
629 gst_d3d11_device_get_chosen_dxgi_factory_version (GstD3D11Device * device)
631 g_return_val_if_fail (GST_IS_D3D11_DEVICE (device),
632 GST_D3D11_DXGI_FACTORY_UNKNOWN);
634 return device->priv->factory_ver;
639 GstD3D11Device *device;
640 GstD3D11DeviceThreadFunc func;
647 gst_d3d11_device_message_callback (MessageData * msg)
649 GstD3D11Device *self = msg->device;
650 GstD3D11DevicePrivate *priv = self->priv;
652 msg->func (self, msg->data);
654 g_mutex_lock (&priv->lock);
656 g_cond_broadcast (&priv->cond);
657 g_mutex_unlock (&priv->lock);
659 return G_SOURCE_REMOVE;
663 * gst_d3d11_device_thread_add:
664 * @device: a #GstD3D11Device
665 * @func: (scope call): a #GstD3D11DeviceThreadFunc
666 * @data: (closure): user data to call @func with
668 * Execute @func in the D3DDevice thread of @device with @data
673 gst_d3d11_device_thread_add (GstD3D11Device * device,
674 GstD3D11DeviceThreadFunc func, gpointer data)
676 GstD3D11DevicePrivate *priv;
677 MessageData msg = { 0, };
679 g_return_if_fail (GST_IS_D3D11_DEVICE (device));
680 g_return_if_fail (func != NULL);
684 if (priv->active_thread == g_thread_self ()) {
689 msg.device = gst_object_ref (device);
694 g_main_context_invoke (priv->main_context,
695 (GSourceFunc) gst_d3d11_device_message_callback, &msg);
697 g_mutex_lock (&priv->lock);
699 g_cond_wait (&priv->cond, &priv->lock);
700 g_mutex_unlock (&priv->lock);
702 gst_object_unref (device);
707 IDXGISwapChain *swap_chain;
708 const DXGI_SWAP_CHAIN_DESC *desc;
709 } CreateSwapChainData;
712 gst_d3d11_device_create_swap_chain_internal (GstD3D11Device * device,
713 CreateSwapChainData * data)
715 GstD3D11DevicePrivate *priv = device->priv;
718 hr = IDXGIFactory1_CreateSwapChain (priv->factory, (IUnknown *) priv->device,
719 (DXGI_SWAP_CHAIN_DESC *) data->desc, &data->swap_chain);
722 GST_ERROR_OBJECT (device, "Cannot create SwapChain Object: 0x%x",
724 data->swap_chain = NULL;
729 * gst_d3d11_device_create_swap_chain:
730 * @device: a #GstD3D11Device
731 * @desc: a DXGI_SWAP_CHAIN_DESC structure for swapchain
733 * Create a IDXGISwapChain object. Caller must release returned swap chain object
734 * via IDXGISwapChain_Release()
736 * Returns: (transfer full) (nullable): a new IDXGISwapChain or %NULL
737 * when failed to create swap chain with given @desc
740 gst_d3d11_device_create_swap_chain (GstD3D11Device * device,
741 const DXGI_SWAP_CHAIN_DESC * desc)
743 CreateSwapChainData data = { 0, };
745 g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL);
747 data.swap_chain = NULL;
750 gst_d3d11_device_thread_add (device, (GstD3D11DeviceThreadFunc)
751 gst_d3d11_device_create_swap_chain_internal, &data);
753 return data.swap_chain;
757 gst_d3d11_device_release_swap_chain_internal (GstD3D11Device * device,
758 IDXGISwapChain * swap_chain)
760 IDXGISwapChain_Release (swap_chain);
764 * gst_d3d11_device_release_swap_chain:
765 * @device: a #GstD3D11Device
766 * @swap_chain: a IDXGISwapChain
768 * Release a @swap_chain from device thread
772 gst_d3d11_device_release_swap_chain (GstD3D11Device * device,
773 IDXGISwapChain * swap_chain)
775 g_return_if_fail (GST_IS_D3D11_DEVICE (device));
777 gst_d3d11_device_thread_add (device,
778 (GstD3D11DeviceThreadFunc) gst_d3d11_device_release_swap_chain_internal,
784 ID3D11Texture2D *texture;
785 const D3D11_TEXTURE2D_DESC *desc;
786 const D3D11_SUBRESOURCE_DATA *inital_data;
790 gst_d3d11_device_create_texture_internal (GstD3D11Device * device,
791 CreateTextureData * data)
793 GstD3D11DevicePrivate *priv = device->priv;
796 hr = ID3D11Device_CreateTexture2D (priv->device, data->desc,
797 data->inital_data, &data->texture);
799 GST_ERROR ("Failed to create staging texture (0x%x)", (guint) hr);
800 data->texture = NULL;
805 gst_d3d11_device_create_texture (GstD3D11Device * device,
806 const D3D11_TEXTURE2D_DESC * desc,
807 const D3D11_SUBRESOURCE_DATA * inital_data)
809 CreateTextureData data;
811 g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL);
812 g_return_val_if_fail (desc != NULL, NULL);
816 data.inital_data = inital_data;
818 gst_d3d11_device_thread_add (device, (GstD3D11DeviceThreadFunc)
819 gst_d3d11_device_create_texture_internal, &data);
825 gst_d3d11_device_release_texture_internal (GstD3D11Device * device,
826 ID3D11Texture2D * texture)
828 ID3D11Texture2D_Release (texture);
832 gst_d3d11_device_release_texture (GstD3D11Device * device,
833 ID3D11Texture2D * texture)
835 g_return_if_fail (GST_IS_D3D11_DEVICE (device));
836 g_return_if_fail (texture != NULL);
838 gst_d3d11_device_thread_add (device, (GstD3D11DeviceThreadFunc)
839 gst_d3d11_device_release_texture_internal, texture);
843 * gst_context_set_d3d11_device:
844 * @context: a #GstContext
845 * @device: (transfer none): resulting #GstD3D11Device
847 * Sets @device on @context
850 gst_context_set_d3d11_device (GstContext * context, GstD3D11Device * device)
853 const gchar *context_type;
855 g_return_if_fail (GST_IS_CONTEXT (context));
856 g_return_if_fail (GST_IS_D3D11_DEVICE (device));
858 context_type = gst_context_get_context_type (context);
859 if (g_strcmp0 (context_type, GST_D3D11_DEVICE_HANDLE_CONTEXT_TYPE) != 0)
862 GST_CAT_LOG (GST_CAT_CONTEXT,
863 "setting GstD3DDevice(%" GST_PTR_FORMAT ") on context(%" GST_PTR_FORMAT
864 ")", device, context);
866 s = gst_context_writable_structure (context);
867 gst_structure_set (s, "device", GST_TYPE_D3D11_DEVICE, device, NULL);
871 * gst_context_get_d3d11_device:
872 * @context: a #GstContext
873 * @device: (out) (transfer full): resulting #GstD3D11Device
875 * Returns: Whether @device was in @context
878 gst_context_get_d3d11_device (GstContext * context, GstD3D11Device ** device)
880 const GstStructure *s;
881 const gchar *context_type;
884 g_return_val_if_fail (GST_IS_CONTEXT (context), FALSE);
885 g_return_val_if_fail (device != NULL, FALSE);
887 context_type = gst_context_get_context_type (context);
888 if (g_strcmp0 (context_type, GST_D3D11_DEVICE_HANDLE_CONTEXT_TYPE) != 0)
891 s = gst_context_get_structure (context);
892 ret = gst_structure_get (s, "device", GST_TYPE_D3D11_DEVICE, device, NULL);
894 GST_CAT_LOG (GST_CAT_CONTEXT, "got GstD3DDevice(%p) from context(%p)",