2 * Copyright (C) 2019 Seungha Yang <seungha.yang@navercorp.com>
3 * Copyright (C) 2020 Seungha Yang <seungha@centricular.com>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
25 #include "gstd3d11device.h"
26 #include "gstd3d11utils.h"
27 #include "gstd3d11format.h"
28 #include "gstd3d11_private.h"
29 #include "gstd3d11memory.h"
34 #include <versionhelpers.h>
37 * SECTION:gstd3d11device
38 * @short_description: Direct3D11 device abstraction
39 * @title: GstD3D11Device
41 * #GstD3D11Device wraps ID3D11Device and ID3D11DeviceContext for GPU resources
42 * to be able to be shared among various elements. Caller can get native
43 * Direct3D11 handles via getter method.
44 * Basically Direct3D11 API doesn't require dedicated thread like that of
45 * OpenGL context, and ID3D11Device APIs are supposed to be thread-safe.
46 * But concurrent call for ID3D11DeviceContext and DXGI API are not allowed.
47 * To protect such object, callers need to make use of gst_d3d11_device_lock()
48 * and gst_d3d11_device_unlock()
52 using namespace Microsoft::WRL;
55 #if HAVE_D3D11SDKLAYERS_H
56 #include <d3d11sdklayers.h>
57 static GModule *d3d11_debug_module = NULL;
59 /* mingw header does not define D3D11_RLDO_IGNORE_INTERNAL
60 * D3D11_RLDO_SUMMARY = 0x1,
61 D3D11_RLDO_DETAIL = 0x2,
62 * D3D11_RLDO_IGNORE_INTERNAL = 0x4
64 #define GST_D3D11_RLDO_FLAGS (0x2 | 0x4)
68 #include <dxgidebug.h>
69 typedef HRESULT (WINAPI * DXGIGetDebugInterface_t) (REFIID riid,
71 static GModule *dxgi_debug_module = NULL;
72 static DXGIGetDebugInterface_t GstDXGIGetDebugInterface = NULL;
76 #if (HAVE_D3D11SDKLAYERS_H || HAVE_DXGIDEBUG_H)
77 GST_DEBUG_CATEGORY_STATIC (gst_d3d11_debug_layer_debug);
79 GST_DEBUG_CATEGORY_STATIC (gst_d3d11_device_debug);
80 #define GST_CAT_DEFAULT gst_d3d11_device_debug
94 #define DEFAULT_ADAPTER 0
95 #define DEFAULT_CREATE_FLAGS 0
97 #define GST_D3D11_N_FORMATS 25
99 struct _GstD3D11DevicePrivate
109 ID3D11Device *device;
110 ID3D11DeviceContext *device_context;
112 ID3D11VideoDevice *video_device;
113 ID3D11VideoContext *video_context;
115 IDXGIFactory1 *factory;
116 GstD3D11Format format_table[GST_D3D11_N_FORMATS];
118 GRecMutex extern_lock;
119 GMutex resource_lock;
121 #if HAVE_D3D11SDKLAYERS_H
122 ID3D11Debug *d3d11_debug;
123 ID3D11InfoQueue *d3d11_info_queue;
127 IDXGIDebug *dxgi_debug;
128 IDXGIInfoQueue *dxgi_info_queue;
133 debug_init_once (void)
135 static gsize init_once = 0;
137 if (g_once_init_enter (&init_once)) {
138 GST_DEBUG_CATEGORY_INIT (gst_d3d11_device_debug,
139 "d3d11device", 0, "d3d11 device object");
140 #if defined(HAVE_D3D11SDKLAYERS_H) || defined(HAVE_DXGIDEBUG_H)
141 GST_DEBUG_CATEGORY_INIT (gst_d3d11_debug_layer_debug,
142 "d3d11debuglayer", 0, "native d3d11 and dxgi debug");
144 g_once_init_leave (&init_once, 1);
148 #define gst_d3d11_device_parent_class parent_class
149 G_DEFINE_TYPE_WITH_CODE (GstD3D11Device, gst_d3d11_device, GST_TYPE_OBJECT,
150 G_ADD_PRIVATE (GstD3D11Device); debug_init_once ());
152 static void gst_d3d11_device_get_property (GObject * object, guint prop_id,
153 GValue * value, GParamSpec * pspec);
154 static void gst_d3d11_device_dispose (GObject * object);
155 static void gst_d3d11_device_finalize (GObject * object);
157 #if HAVE_D3D11SDKLAYERS_H
159 gst_d3d11_device_enable_d3d11_debug (void)
161 static gsize _init = 0;
163 /* If all below libraries are unavailable, d3d11 device would fail with
164 * D3D11_CREATE_DEVICE_DEBUG flag */
165 if (g_once_init_enter (&_init)) {
167 g_module_open ("d3d11sdklayers.dll", G_MODULE_BIND_LAZY);
169 if (!d3d11_debug_module)
171 g_module_open ("d3d11_1sdklayers.dll", G_MODULE_BIND_LAZY);
172 if (!d3d11_debug_module)
174 g_module_open ("d3d11_2sdklayers.dll", G_MODULE_BIND_LAZY);
175 if (!d3d11_debug_module)
177 g_module_open ("d3d11_3sdklayers.dll", G_MODULE_BIND_LAZY);
179 g_once_init_leave (&_init, 1);
182 if (d3d11_debug_module)
188 static inline GstDebugLevel
189 d3d11_message_severity_to_gst (D3D11_MESSAGE_SEVERITY level)
192 case D3D11_MESSAGE_SEVERITY_CORRUPTION:
193 case D3D11_MESSAGE_SEVERITY_ERROR:
194 return GST_LEVEL_ERROR;
195 case D3D11_MESSAGE_SEVERITY_WARNING:
196 return GST_LEVEL_WARNING;
197 case D3D11_MESSAGE_SEVERITY_INFO:
198 return GST_LEVEL_INFO;
199 case D3D11_MESSAGE_SEVERITY_MESSAGE:
200 return GST_LEVEL_DEBUG;
205 return GST_LEVEL_LOG;
209 gst_d3d11_device_d3d11_debug (GstD3D11Device * device,
210 const gchar * file, const gchar * function, gint line)
212 GstD3D11DevicePrivate *priv = device->priv;
217 ID3D11InfoQueue *info_queue = priv->d3d11_info_queue;
222 num_msg = info_queue->GetNumStoredMessages ();
224 for (i = 0; i < num_msg; i++) {
227 hr = info_queue->GetMessage (i, NULL, &msg_len);
229 if (FAILED (hr) || msg_len == 0) {
233 msg = (D3D11_MESSAGE *) g_alloca (msg_len);
234 hr = info_queue->GetMessage (i, msg, &msg_len);
236 level = d3d11_message_severity_to_gst (msg->Severity);
237 if (msg->Category == D3D11_MESSAGE_CATEGORY_STATE_CREATION &&
238 level > GST_LEVEL_ERROR) {
239 /* Do not warn for live object, since there would be live object
240 * when ReportLiveDeviceObjects was called */
241 level = GST_LEVEL_INFO;
244 gst_debug_log (gst_d3d11_debug_layer_debug, level, file, function, line,
245 G_OBJECT (device), "D3D11InfoQueue: %s", msg->pDescription);
248 info_queue->ClearStoredMessages ();
254 gst_d3d11_device_d3d11_debug (GstD3D11Device * device,
255 const gchar * file, const gchar * function, gint line)
264 gst_d3d11_device_enable_dxgi_debug (void)
266 static gsize _init = 0;
267 gboolean ret = FALSE;
269 /* If all below libraries are unavailable, d3d11 device would fail with
270 * D3D11_CREATE_DEVICE_DEBUG flag */
271 if (g_once_init_enter (&_init)) {
272 #if (!GST_D3D11_WINAPI_ONLY_APP)
273 dxgi_debug_module = g_module_open ("dxgidebug.dll", G_MODULE_BIND_LAZY);
275 if (dxgi_debug_module)
276 g_module_symbol (dxgi_debug_module,
277 "DXGIGetDebugInterface", (gpointer *) & GstDXGIGetDebugInterface);
278 if (GstDXGIGetDebugInterface)
280 #elif (GST_D3D11_DXGI_HEADER_VERSION >= 3)
283 g_once_init_leave (&_init, 1);
290 gst_d3d11_device_dxgi_get_device_interface (REFIID riid, void **debug)
292 #if (!GST_D3D11_WINAPI_ONLY_APP)
293 if (GstDXGIGetDebugInterface) {
294 return GstDXGIGetDebugInterface (riid, debug);
296 #elif (GST_D3D11_DXGI_HEADER_VERSION >= 3)
297 return DXGIGetDebugInterface1 (0, riid, debug);
300 return E_NOINTERFACE;
303 static inline GstDebugLevel
304 dxgi_info_queue_message_severity_to_gst (DXGI_INFO_QUEUE_MESSAGE_SEVERITY level)
307 case DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION:
308 case DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR:
309 return GST_LEVEL_ERROR;
310 case DXGI_INFO_QUEUE_MESSAGE_SEVERITY_WARNING:
311 return GST_LEVEL_WARNING;
312 case DXGI_INFO_QUEUE_MESSAGE_SEVERITY_INFO:
313 return GST_LEVEL_INFO;
314 case DXGI_INFO_QUEUE_MESSAGE_SEVERITY_MESSAGE:
315 return GST_LEVEL_DEBUG;
320 return GST_LEVEL_LOG;
324 gst_d3d11_device_dxgi_debug (GstD3D11Device * device,
325 const gchar * file, const gchar * function, gint line)
327 GstD3D11DevicePrivate *priv = device->priv;
328 DXGI_INFO_QUEUE_MESSAGE *msg;
332 IDXGIInfoQueue *info_queue = priv->dxgi_info_queue;
337 num_msg = info_queue->GetNumStoredMessages (DXGI_DEBUG_ALL);
339 for (i = 0; i < num_msg; i++) {
342 hr = info_queue->GetMessage (DXGI_DEBUG_ALL, i, NULL, &msg_len);
344 if (FAILED (hr) || msg_len == 0) {
348 msg = (DXGI_INFO_QUEUE_MESSAGE *) g_alloca (msg_len);
349 hr = info_queue->GetMessage (DXGI_DEBUG_ALL, i, msg, &msg_len);
351 level = dxgi_info_queue_message_severity_to_gst (msg->Severity);
352 gst_debug_log (gst_d3d11_debug_layer_debug, level, file, function, line,
353 G_OBJECT (device), "DXGIInfoQueue: %s", msg->pDescription);
356 info_queue->ClearStoredMessages (DXGI_DEBUG_ALL);
362 gst_d3d11_device_dxgi_debug (GstD3D11Device * device,
363 const gchar * file, const gchar * function, gint line)
371 gst_d3d11_device_class_init (GstD3D11DeviceClass * klass)
373 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
374 GParamFlags readable_flags =
375 (GParamFlags) (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
377 gobject_class->get_property = gst_d3d11_device_get_property;
378 gobject_class->dispose = gst_d3d11_device_dispose;
379 gobject_class->finalize = gst_d3d11_device_finalize;
381 g_object_class_install_property (gobject_class, PROP_ADAPTER,
382 g_param_spec_uint ("adapter", "Adapter",
383 "DXGI Adapter index for creating device",
384 0, G_MAXUINT32, DEFAULT_ADAPTER, readable_flags));
386 g_object_class_install_property (gobject_class, PROP_DEVICE_ID,
387 g_param_spec_uint ("device-id", "Device Id",
388 "DXGI Device ID", 0, G_MAXUINT32, 0, readable_flags));
390 g_object_class_install_property (gobject_class, PROP_VENDOR_ID,
391 g_param_spec_uint ("vendor-id", "Vendor Id",
392 "DXGI Vendor ID", 0, G_MAXUINT32, 0, readable_flags));
394 g_object_class_install_property (gobject_class, PROP_HARDWARE,
395 g_param_spec_boolean ("hardware", "Hardware",
396 "Whether hardware device or not", TRUE, readable_flags));
398 g_object_class_install_property (gobject_class, PROP_DESCRIPTION,
399 g_param_spec_string ("description", "Description",
400 "Human readable device description", NULL, readable_flags));
402 g_object_class_install_property (gobject_class, PROP_ADAPTER_LUID,
403 g_param_spec_int64 ("adapter-luid", "Adapter LUID",
404 "DXGI Adapter LUID (Locally Unique Identifier) of created device",
405 G_MININT64, G_MAXINT64, 0, readable_flags));
407 gst_d3d11_memory_init_once ();
411 gst_d3d11_device_init (GstD3D11Device * self)
413 GstD3D11DevicePrivate *priv;
415 priv = (GstD3D11DevicePrivate *)
416 gst_d3d11_device_get_instance_private (self);
417 priv->adapter = DEFAULT_ADAPTER;
419 g_rec_mutex_init (&priv->extern_lock);
420 g_mutex_init (&priv->resource_lock);
426 is_windows_8_or_greater (void)
428 static gsize version_once = 0;
429 static gboolean ret = FALSE;
431 if (g_once_init_enter (&version_once)) {
432 #if (!GST_D3D11_WINAPI_ONLY_APP)
433 if (IsWindows8OrGreater ())
439 g_once_init_leave (&version_once, 1);
445 inline D3D11_FORMAT_SUPPORT
446 operator | (D3D11_FORMAT_SUPPORT lhs, D3D11_FORMAT_SUPPORT rhs)
448 return static_cast < D3D11_FORMAT_SUPPORT > (static_cast < UINT >
449 (lhs) | static_cast < UINT > (rhs));
452 inline D3D11_FORMAT_SUPPORT
453 operator |= (D3D11_FORMAT_SUPPORT lhs, D3D11_FORMAT_SUPPORT rhs)
459 can_support_format (GstD3D11Device * self, DXGI_FORMAT format,
460 D3D11_FORMAT_SUPPORT extra_flags)
462 GstD3D11DevicePrivate *priv = self->priv;
463 ID3D11Device *handle = priv->device;
466 D3D11_FORMAT_SUPPORT flags = D3D11_FORMAT_SUPPORT_TEXTURE2D;
468 flags |= extra_flags;
470 if (!is_windows_8_or_greater ()) {
471 GST_INFO_OBJECT (self, "DXGI format %d needs Windows 8 or greater",
476 hr = handle->CheckFormatSupport (format, &supported);
478 GST_DEBUG_OBJECT (self, "DXGI format %d is not supported by device",
483 if ((supported & flags) != flags) {
484 GST_DEBUG_OBJECT (self,
485 "DXGI format %d doesn't support flag 0x%x (supported flag 0x%x)",
486 (guint) format, (guint) supported, (guint) flags);
490 GST_INFO_OBJECT (self, "Device supports DXGI format %d", (guint) format);
496 gst_d3d11_device_setup_format_table (GstD3D11Device * self)
498 GstD3D11DevicePrivate *priv = self->priv;
502 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_BGRA;
503 priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_B8G8R8A8_UNORM;
504 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_B8G8R8A8_UNORM;
507 /* Identical to BGRA, but alpha will be ignored */
508 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_BGRx;
509 priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_B8G8R8A8_UNORM;
510 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_B8G8R8A8_UNORM;
513 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_RGBA;
514 priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
515 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_R8G8B8A8_UNORM;
518 /* Identical to RGBA, but alpha will be ignored */
519 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_RGBx;
520 priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
521 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_R8G8B8A8_UNORM;
524 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_RGB10A2_LE;
525 priv->format_table[n_formats].resource_format[0] =
526 DXGI_FORMAT_R10G10B10A2_UNORM;
527 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_R10G10B10A2_UNORM;
531 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_VUYA;
532 priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
533 if (can_support_format (self, DXGI_FORMAT_AYUV,
534 D3D11_FORMAT_SUPPORT_RENDER_TARGET |
535 D3D11_FORMAT_SUPPORT_SHADER_SAMPLE))
536 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_AYUV;
538 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_UNKNOWN;
541 /* FIXME: d3d11 sampler doesn't support packed-and-subsampled formats
542 * very well (and it's really poorly documented).
543 * As per observation, d3d11 samplers seems to be dropping the second
544 * Y componet from "Y0-U0-Y1-V0" pair which results in bad visual quality
545 * than 4:2:0 subsampled formats. We should revisit this later */
547 /* TODO: The best would be using d3d11 compute shader to handle this kinds of
548 * samples but comute shader is not implemented yet by us.
550 * Another simple approach is using d3d11 video processor,
551 * but capability will be very device dependent because it depends on
552 * GPU vendor's driver implementation, moreover, software fallback does
553 * not support d3d11 video processor. So it's not reliable in this case */
555 /* NOTE: packted yuv 4:2:2 YUY2, UYVY, and VYUY formats are not natively
556 * supported render target view formats
557 * (i.e., cannot be output format of shader pipeline) */
558 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_YUY2;
559 if (can_support_format (self, DXGI_FORMAT_YUY2,
560 D3D11_FORMAT_SUPPORT_SHADER_SAMPLE)) {
561 priv->format_table[n_formats].resource_format[0] =
562 DXGI_FORMAT_R8G8B8A8_UNORM;
563 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_YUY2;
565 /* If DXGI_FORMAT_YUY2 format is not supported, use this format,
566 * it's analogous to YUY2 */
567 priv->format_table[n_formats].resource_format[0] =
568 DXGI_FORMAT_G8R8_G8B8_UNORM;
572 /* No native DXGI format available for UYVY */
573 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_UYVY;
574 priv->format_table[n_formats].resource_format[0] =
575 DXGI_FORMAT_R8G8_B8G8_UNORM;
578 /* No native DXGI format available for VYUY */
579 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_VYUY;
580 priv->format_table[n_formats].resource_format[0] =
581 DXGI_FORMAT_R8G8_B8G8_UNORM;
584 /* Y210 and Y410 formats cannot support rtv */
585 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_Y210;
586 priv->format_table[n_formats].resource_format[0] =
587 DXGI_FORMAT_R16G16B16A16_UNORM;
588 if (can_support_format (self, DXGI_FORMAT_Y210,
589 D3D11_FORMAT_SUPPORT_SHADER_SAMPLE))
590 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_Y210;
592 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_UNKNOWN;
596 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_Y410;
597 priv->format_table[n_formats].resource_format[0] =
598 DXGI_FORMAT_R10G10B10A2_UNORM;
599 if (can_support_format (self, DXGI_FORMAT_Y410,
600 D3D11_FORMAT_SUPPORT_SHADER_SAMPLE))
601 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_Y410;
603 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_UNKNOWN;
606 /* YUV semi-planar */
607 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_NV12;
608 priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R8_UNORM;
609 priv->format_table[n_formats].resource_format[1] = DXGI_FORMAT_R8G8_UNORM;
610 if (can_support_format (self, DXGI_FORMAT_NV12,
611 D3D11_FORMAT_SUPPORT_RENDER_TARGET |
612 D3D11_FORMAT_SUPPORT_SHADER_SAMPLE))
613 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_NV12;
615 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_UNKNOWN;
618 /* no native format for NV21 */
619 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_NV21;
620 priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R8_UNORM;
621 priv->format_table[n_formats].resource_format[1] = DXGI_FORMAT_R8G8_UNORM;
622 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_UNKNOWN;
625 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_P010_10LE;
626 priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R16_UNORM;
627 priv->format_table[n_formats].resource_format[1] = DXGI_FORMAT_R16G16_UNORM;
628 if (can_support_format (self, DXGI_FORMAT_P010,
629 D3D11_FORMAT_SUPPORT_RENDER_TARGET |
630 D3D11_FORMAT_SUPPORT_SHADER_SAMPLE))
631 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_P010;
633 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_UNKNOWN;
636 /* P012 is identical to P016 from runtime point of view */
637 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_P012_LE;
638 priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R16_UNORM;
639 priv->format_table[n_formats].resource_format[1] = DXGI_FORMAT_R16G16_UNORM;
640 if (can_support_format (self, DXGI_FORMAT_P016,
641 D3D11_FORMAT_SUPPORT_RENDER_TARGET |
642 D3D11_FORMAT_SUPPORT_SHADER_SAMPLE))
643 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_P016;
645 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_UNKNOWN;
648 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_P016_LE;
649 priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R16_UNORM;
650 priv->format_table[n_formats].resource_format[1] = DXGI_FORMAT_R16G16_UNORM;
651 if (can_support_format (self, DXGI_FORMAT_P016,
652 D3D11_FORMAT_SUPPORT_RENDER_TARGET |
653 D3D11_FORMAT_SUPPORT_SHADER_SAMPLE))
654 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_P016;
656 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_UNKNOWN;
660 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_I420;
661 priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R8_UNORM;
662 priv->format_table[n_formats].resource_format[1] = DXGI_FORMAT_R8_UNORM;
663 priv->format_table[n_formats].resource_format[2] = DXGI_FORMAT_R8_UNORM;
666 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_YV12;
667 priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R8_UNORM;
668 priv->format_table[n_formats].resource_format[1] = DXGI_FORMAT_R8_UNORM;
669 priv->format_table[n_formats].resource_format[2] = DXGI_FORMAT_R8_UNORM;
672 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_I420_10LE;
673 priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R16_UNORM;
674 priv->format_table[n_formats].resource_format[1] = DXGI_FORMAT_R16_UNORM;
675 priv->format_table[n_formats].resource_format[2] = DXGI_FORMAT_R16_UNORM;
678 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_I420_12LE;
679 priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R16_UNORM;
680 priv->format_table[n_formats].resource_format[1] = DXGI_FORMAT_R16_UNORM;
681 priv->format_table[n_formats].resource_format[2] = DXGI_FORMAT_R16_UNORM;
684 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_Y42B;
685 priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R8_UNORM;
686 priv->format_table[n_formats].resource_format[1] = DXGI_FORMAT_R8_UNORM;
687 priv->format_table[n_formats].resource_format[2] = DXGI_FORMAT_R8_UNORM;
690 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_I422_10LE;
691 priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R16_UNORM;
692 priv->format_table[n_formats].resource_format[1] = DXGI_FORMAT_R16_UNORM;
693 priv->format_table[n_formats].resource_format[2] = DXGI_FORMAT_R16_UNORM;
696 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_I422_12LE;
697 priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R16_UNORM;
698 priv->format_table[n_formats].resource_format[1] = DXGI_FORMAT_R16_UNORM;
699 priv->format_table[n_formats].resource_format[2] = DXGI_FORMAT_R16_UNORM;
702 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_Y444;
703 priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R8_UNORM;
704 priv->format_table[n_formats].resource_format[1] = DXGI_FORMAT_R8_UNORM;
705 priv->format_table[n_formats].resource_format[2] = DXGI_FORMAT_R8_UNORM;
708 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_Y444_10LE;
709 priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R16_UNORM;
710 priv->format_table[n_formats].resource_format[1] = DXGI_FORMAT_R16_UNORM;
711 priv->format_table[n_formats].resource_format[2] = DXGI_FORMAT_R16_UNORM;
714 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_Y444_12LE;
715 priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R16_UNORM;
716 priv->format_table[n_formats].resource_format[1] = DXGI_FORMAT_R16_UNORM;
717 priv->format_table[n_formats].resource_format[2] = DXGI_FORMAT_R16_UNORM;
720 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_Y444_16LE;
721 priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R16_UNORM;
722 priv->format_table[n_formats].resource_format[1] = DXGI_FORMAT_R16_UNORM;
723 priv->format_table[n_formats].resource_format[2] = DXGI_FORMAT_R16_UNORM;
727 /* NOTE: To support conversion by using video processor,
728 * mark DXGI_FORMAT_{R8,R16}_UNORM formats as known dxgi_format.
729 * Otherwise, d3d11 elements will not try to use video processor for
731 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_GRAY8;
732 priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R8_UNORM;
733 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_R8_UNORM;
736 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_GRAY16_LE;
737 priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R16_UNORM;
738 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_R16_UNORM;
741 g_assert (n_formats == GST_D3D11_N_FORMATS);
745 gst_d3d11_device_get_property (GObject * object, guint prop_id,
746 GValue * value, GParamSpec * pspec)
748 GstD3D11Device *self = GST_D3D11_DEVICE (object);
749 GstD3D11DevicePrivate *priv = self->priv;
753 g_value_set_uint (value, priv->adapter);
756 g_value_set_uint (value, priv->device_id);
759 g_value_set_uint (value, priv->vendor_id);
762 g_value_set_boolean (value, priv->hardware);
764 case PROP_DESCRIPTION:
765 g_value_set_string (value, priv->description);
767 case PROP_ADAPTER_LUID:
768 g_value_set_int64 (value, priv->adapter_luid);
771 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
777 gst_d3d11_device_dispose (GObject * object)
779 GstD3D11Device *self = GST_D3D11_DEVICE (object);
780 GstD3D11DevicePrivate *priv = self->priv;
782 GST_LOG_OBJECT (self, "dispose");
784 GST_D3D11_CLEAR_COM (priv->video_device);
785 GST_D3D11_CLEAR_COM (priv->video_context);
786 GST_D3D11_CLEAR_COM (priv->device);
787 GST_D3D11_CLEAR_COM (priv->device_context);
788 GST_D3D11_CLEAR_COM (priv->factory);
789 #if HAVE_D3D11SDKLAYERS_H
790 if (priv->d3d11_debug) {
791 priv->d3d11_debug->ReportLiveDeviceObjects ((D3D11_RLDO_FLAGS)
792 GST_D3D11_RLDO_FLAGS);
794 GST_D3D11_CLEAR_COM (priv->d3d11_debug);
796 if (priv->d3d11_info_queue)
797 gst_d3d11_device_d3d11_debug (self, __FILE__, GST_FUNCTION, __LINE__);
799 GST_D3D11_CLEAR_COM (priv->d3d11_info_queue);
803 if (priv->dxgi_debug) {
804 priv->dxgi_debug->ReportLiveObjects (DXGI_DEBUG_ALL,
805 (DXGI_DEBUG_RLO_FLAGS) GST_D3D11_RLDO_FLAGS);
807 GST_D3D11_CLEAR_COM (priv->dxgi_debug);
809 if (priv->dxgi_info_queue)
810 gst_d3d11_device_dxgi_debug (self, __FILE__, GST_FUNCTION, __LINE__);
812 GST_D3D11_CLEAR_COM (priv->dxgi_info_queue);
815 G_OBJECT_CLASS (parent_class)->dispose (object);
819 gst_d3d11_device_finalize (GObject * object)
821 GstD3D11Device *self = GST_D3D11_DEVICE (object);
822 GstD3D11DevicePrivate *priv = self->priv;
824 GST_LOG_OBJECT (self, "finalize");
826 g_rec_mutex_clear (&priv->extern_lock);
827 g_mutex_clear (&priv->resource_lock);
828 g_free (priv->description);
830 G_OBJECT_CLASS (parent_class)->finalize (object);
835 DEVICE_CONSTRUCT_FOR_ADAPTER_INDEX,
836 DEVICE_CONSTRUCT_FOR_ADAPTER_LUID,
837 DEVICE_CONSTRUCT_WRAPPED,
838 } GstD3D11DeviceConstructType;
840 typedef struct _GstD3D11DeviceConstructData
846 ID3D11Device *device;
848 GstD3D11DeviceConstructType type;
850 } GstD3D11DeviceConstructData;
853 _gst_d3d11_device_get_adapter (const GstD3D11DeviceConstructData * data,
854 IDXGIFactory1 * factory, guint * index, DXGI_ADAPTER_DESC * adapter_desc,
855 IDXGIAdapter1 ** dxgi_adapter)
858 ComPtr < IDXGIAdapter1 > adapter1;
859 DXGI_ADAPTER_DESC desc;
861 switch (data->type) {
862 case DEVICE_CONSTRUCT_FOR_ADAPTER_INDEX:
864 hr = factory->EnumAdapters1 (data->data.adapter_index, &adapter1);
868 hr = adapter1->GetDesc (&desc);
872 *index = data->data.adapter_index;
873 *adapter_desc = desc;
874 *dxgi_adapter = adapter1.Detach ();
878 case DEVICE_CONSTRUCT_FOR_ADAPTER_LUID:
880 for (guint i = 0;; i++) {
885 hr = factory->EnumAdapters1 (i, &adapter1);
889 hr = adapter1->GetDesc (&desc);
893 luid = gst_d3d11_luid_to_int64 (&desc.AdapterLuid);
894 if (luid != data->data.adapter_luid)
898 *adapter_desc = desc;
899 *dxgi_adapter = adapter1.Detach ();
906 case DEVICE_CONSTRUCT_WRAPPED:
908 ComPtr < IDXGIDevice > dxgi_device;
909 ComPtr < IDXGIAdapter > adapter;
910 ID3D11Device *device = data->data.device;
913 hr = device->QueryInterface (IID_PPV_ARGS (&dxgi_device));
917 hr = dxgi_device->GetAdapter (&adapter);
921 hr = adapter.As (&adapter1);
925 hr = adapter1->GetDesc (&desc);
929 luid = gst_d3d11_luid_to_int64 (&desc.AdapterLuid);
931 for (guint i = 0;; i++) {
932 DXGI_ADAPTER_DESC tmp_desc;
933 ComPtr < IDXGIAdapter1 > tmp;
935 hr = factory->EnumAdapters1 (i, &tmp);
939 hr = tmp->GetDesc (&tmp_desc);
943 if (luid != gst_d3d11_luid_to_int64 (&tmp_desc.AdapterLuid))
947 *adapter_desc = desc;
948 *dxgi_adapter = adapter1.Detach ();
956 g_assert_not_reached ();
964 gst_d3d11_device_setup_debug_layer (GstD3D11Device * self)
967 if (gst_debug_category_get_threshold (gst_d3d11_debug_layer_debug) >
969 GstD3D11DevicePrivate *priv = self->priv;
971 if (gst_d3d11_device_enable_dxgi_debug ()) {
972 IDXGIDebug *debug = nullptr;
973 IDXGIInfoQueue *info_queue = nullptr;
976 GST_CAT_INFO_OBJECT (gst_d3d11_debug_layer_debug, self,
977 "dxgi debug library was loaded");
978 hr = gst_d3d11_device_dxgi_get_device_interface (IID_PPV_ARGS (&debug));
980 if (SUCCEEDED (hr)) {
981 GST_CAT_INFO_OBJECT (gst_d3d11_debug_layer_debug, self,
982 "IDXGIDebug interface available");
983 priv->dxgi_debug = debug;
985 hr = gst_d3d11_device_dxgi_get_device_interface (IID_PPV_ARGS
987 if (SUCCEEDED (hr)) {
988 GST_CAT_INFO_OBJECT (gst_d3d11_debug_layer_debug, self,
989 "IDXGIInfoQueue interface available");
990 priv->dxgi_info_queue = info_queue;
994 GST_CAT_INFO_OBJECT (gst_d3d11_debug_layer_debug, self,
995 "couldn't load dxgi debug library");
1000 #if HAVE_D3D11SDKLAYERS_H
1001 if ((self->priv->create_flags & D3D11_CREATE_DEVICE_DEBUG) != 0) {
1002 GstD3D11DevicePrivate *priv = self->priv;
1004 ID3D11InfoQueue *info_queue;
1007 hr = priv->device->QueryInterface (IID_PPV_ARGS (&debug));
1009 if (SUCCEEDED (hr)) {
1010 GST_CAT_INFO_OBJECT (gst_d3d11_debug_layer_debug, self,
1011 "D3D11Debug interface available");
1012 priv->d3d11_debug = debug;
1014 hr = priv->device->QueryInterface (IID_PPV_ARGS (&info_queue));
1015 if (SUCCEEDED (hr)) {
1016 GST_CAT_INFO_OBJECT (gst_d3d11_debug_layer_debug, self,
1017 "ID3D11InfoQueue interface available");
1018 priv->d3d11_info_queue = info_queue;
1025 static GstD3D11Device *
1026 gst_d3d11_device_new_internal (const GstD3D11DeviceConstructData * data)
1028 ComPtr < IDXGIAdapter1 > adapter;
1029 ComPtr < IDXGIFactory1 > factory;
1030 ComPtr < ID3D11Device > device;
1031 ComPtr < ID3D11DeviceContext > device_context;
1034 guint adapter_index = 0;
1035 DXGI_ADAPTER_DESC adapter_desc;
1036 static const D3D_FEATURE_LEVEL feature_levels[] = {
1037 D3D_FEATURE_LEVEL_11_1,
1038 D3D_FEATURE_LEVEL_11_0,
1039 D3D_FEATURE_LEVEL_10_1,
1040 D3D_FEATURE_LEVEL_10_0,
1041 D3D_FEATURE_LEVEL_9_3,
1042 D3D_FEATURE_LEVEL_9_2,
1043 D3D_FEATURE_LEVEL_9_1
1045 D3D_FEATURE_LEVEL selected_level;
1049 hr = CreateDXGIFactory1 (IID_PPV_ARGS (&factory));
1050 if (!gst_d3d11_result (hr, NULL)) {
1051 GST_ERROR ("cannot create dxgi factory, hr: 0x%x", (guint) hr);
1056 if (data->type != DEVICE_CONSTRUCT_WRAPPED) {
1057 create_flags = data->create_flags;
1058 #if HAVE_D3D11SDKLAYERS_H
1059 if (gst_debug_category_get_threshold (gst_d3d11_debug_layer_debug) >
1061 /* DirectX SDK should be installed on system for this */
1062 if (gst_d3d11_device_enable_d3d11_debug ()) {
1063 GST_CAT_INFO (gst_d3d11_debug_layer_debug,
1064 "d3d11 debug library was loaded");
1065 create_flags |= D3D11_CREATE_DEVICE_DEBUG;
1067 GST_CAT_INFO (gst_d3d11_debug_layer_debug,
1068 "couldn't load d3d11 debug library");
1074 /* Ensure valid device handle */
1075 if (data->type == DEVICE_CONSTRUCT_WRAPPED) {
1076 ID3D11Device *external_device = data->data.device;
1078 hr = external_device->QueryInterface (IID_PPV_ARGS (&device));
1080 GST_ERROR ("Not a valid external ID3D11Device handle");
1084 device->GetImmediateContext (&device_context);
1087 hr = _gst_d3d11_device_get_adapter (data, factory.Get (), &adapter_index,
1088 &adapter_desc, &adapter);
1090 GST_INFO ("Failed to get DXGI adapter");
1094 if (data->type != DEVICE_CONSTRUCT_WRAPPED) {
1095 hr = D3D11CreateDevice (adapter.Get (), D3D_DRIVER_TYPE_UNKNOWN,
1096 NULL, create_flags, feature_levels, G_N_ELEMENTS (feature_levels),
1097 D3D11_SDK_VERSION, &device, &selected_level, &device_context);
1100 /* Retry if the system could not recognize D3D_FEATURE_LEVEL_11_1 */
1101 hr = D3D11CreateDevice (adapter.Get (), D3D_DRIVER_TYPE_UNKNOWN,
1102 NULL, create_flags, &feature_levels[1],
1103 G_N_ELEMENTS (feature_levels) - 1, D3D11_SDK_VERSION, &device,
1104 &selected_level, &device_context);
1107 /* if D3D11_CREATE_DEVICE_DEBUG was enabled but couldn't create device,
1108 * try it without the flag again */
1109 if (FAILED (hr) && (create_flags & D3D11_CREATE_DEVICE_DEBUG) != 0) {
1110 create_flags &= ~D3D11_CREATE_DEVICE_DEBUG;
1112 hr = D3D11CreateDevice (adapter.Get (), D3D_DRIVER_TYPE_UNKNOWN,
1113 NULL, create_flags, feature_levels, G_N_ELEMENTS (feature_levels),
1114 D3D11_SDK_VERSION, &device, &selected_level, &device_context);
1117 /* Retry if the system could not recognize D3D_FEATURE_LEVEL_11_1 */
1118 hr = D3D11CreateDevice (adapter.Get (), D3D_DRIVER_TYPE_UNKNOWN,
1119 NULL, create_flags, &feature_levels[1],
1120 G_N_ELEMENTS (feature_levels) - 1, D3D11_SDK_VERSION, &device,
1121 &selected_level, &device_context);
1127 switch (data->type) {
1128 case DEVICE_CONSTRUCT_FOR_ADAPTER_INDEX:
1130 GST_INFO ("Failed to create d3d11 device for adapter index %d"
1131 " with flags 0x%x, hr: 0x%x", data->data.adapter_index,
1132 create_flags, (guint) hr);
1135 case DEVICE_CONSTRUCT_FOR_ADAPTER_LUID:
1137 GST_ERROR ("Failed to create d3d11 device for adapter luid %"
1138 G_GINT64_FORMAT " with flags 0x%x, hr: 0x%x",
1139 data->data.adapter_luid, create_flags, (guint) hr);
1149 GstD3D11Device *self = nullptr;
1150 GstD3D11DevicePrivate *priv;
1152 self = (GstD3D11Device *) g_object_new (GST_TYPE_D3D11_DEVICE, nullptr);
1153 gst_object_ref_sink (self);
1157 priv->adapter = adapter_index;
1158 priv->device = device.Detach ();
1159 priv->device_context = device_context.Detach ();
1160 priv->factory = factory.Detach ();
1162 priv->vendor_id = adapter_desc.VendorId;
1163 priv->device_id = adapter_desc.DeviceId;
1164 priv->description = g_utf16_to_utf8 ((gunichar2 *) adapter_desc.Description,
1165 -1, nullptr, nullptr, nullptr);
1166 priv->adapter_luid = gst_d3d11_luid_to_int64 (&adapter_desc.AdapterLuid);
1168 DXGI_ADAPTER_DESC1 desc1;
1169 hr = adapter->GetDesc1 (&desc1);
1171 /* DXGI_ADAPTER_FLAG_SOFTWARE is missing in dxgi.h of mingw */
1172 if (SUCCEEDED (hr) && (desc1.Flags & 0x2) != 0x2)
1173 priv->hardware = TRUE;
1175 priv->create_flags = create_flags;
1176 gst_d3d11_device_setup_format_table (self);
1177 gst_d3d11_device_setup_debug_layer (self);
1183 * gst_d3d11_device_new:
1184 * @adapter_index: the index of adapter for creating d3d11 device
1185 * @flags: a D3D11_CREATE_DEVICE_FLAG value used for creating d3d11 device
1187 * Returns: (transfer full) (nullable): a new #GstD3D11Device for @adapter_index
1188 * or %NULL when failed to create D3D11 device with given adapter index.
1193 gst_d3d11_device_new (guint adapter_index, guint flags)
1195 GstD3D11DeviceConstructData data;
1197 data.data.adapter_index = adapter_index;
1198 data.type = DEVICE_CONSTRUCT_FOR_ADAPTER_INDEX;
1199 data.create_flags = flags;
1201 return gst_d3d11_device_new_internal (&data);
1205 * gst_d3d11_device_new_for_adapter_luid:
1206 * @adapter_luid: an int64 representation of the DXGI adapter LUID
1207 * @flags: a D3D11_CREATE_DEVICE_FLAG value used for creating d3d11 device
1209 * Returns: (transfer full) (nullable): a new #GstD3D11Device for @adapter_luid
1210 * or %NULL when failed to create D3D11 device with given adapter luid.
1215 gst_d3d11_device_new_for_adapter_luid (gint64 adapter_luid, guint flags)
1217 GstD3D11DeviceConstructData data;
1219 data.data.adapter_luid = adapter_luid;
1220 data.type = DEVICE_CONSTRUCT_FOR_ADAPTER_LUID;
1221 data.create_flags = flags;
1223 return gst_d3d11_device_new_internal (&data);
1227 * gst_d3d11_device_new_wrapped:
1228 * @device: (transfer none): an existing ID3D11Device handle
1230 * Returns: (transfer full) (nullable): a new #GstD3D11Device for @device
1231 * or %NULL if an error occurred
1236 gst_d3d11_device_new_wrapped (ID3D11Device * device)
1238 GstD3D11DeviceConstructData data;
1240 g_return_val_if_fail (device != nullptr, nullptr);
1242 data.data.device = device;
1243 data.type = DEVICE_CONSTRUCT_WRAPPED;
1244 data.create_flags = 0;
1246 return gst_d3d11_device_new_internal (&data);
1250 * gst_d3d11_device_get_device_handle:
1251 * @device: a #GstD3D11Device
1253 * Used for various D3D11 APIs directly. Caller must not destroy returned device
1256 * Returns: (transfer none): the ID3D11Device handle
1261 gst_d3d11_device_get_device_handle (GstD3D11Device * device)
1263 g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL);
1265 return device->priv->device;
1269 * gst_d3d11_device_get_device_context_handle:
1270 * @device: a #GstD3D11Device
1272 * Used for various D3D11 APIs directly. Caller must not destroy returned device
1273 * object. Any ID3D11DeviceContext call needs to be protected by
1274 * gst_d3d11_device_lock() and gst_d3d11_device_unlock() method.
1276 * Returns: (transfer none): the immeidate ID3D11DeviceContext handle
1280 ID3D11DeviceContext *
1281 gst_d3d11_device_get_device_context_handle (GstD3D11Device * device)
1283 g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL);
1285 return device->priv->device_context;
1289 * gst_d3d11_device_get_dxgi_factory_handle:
1290 * @device: a #GstD3D11Device
1292 * Used for various D3D11 APIs directly. Caller must not destroy returned device
1295 * Returns: (transfer none): the IDXGIFactory1 handle
1300 gst_d3d11_device_get_dxgi_factory_handle (GstD3D11Device * device)
1302 g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL);
1304 return device->priv->factory;
1308 * gst_d3d11_device_get_video_device_handle:
1309 * @device: a #GstD3D11Device
1311 * Used for various D3D11 APIs directly. Caller must not destroy returned device
1314 * Returns: (nullable) (transfer none) : the ID3D11VideoDevice handle or %NULL
1315 * if ID3D11VideoDevice is unavailable.
1320 gst_d3d11_device_get_video_device_handle (GstD3D11Device * device)
1322 GstD3D11DevicePrivate *priv;
1324 g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL);
1326 priv = device->priv;
1327 g_mutex_lock (&priv->resource_lock);
1328 if (!priv->video_device) {
1330 ID3D11VideoDevice *video_device = NULL;
1332 hr = priv->device->QueryInterface (IID_PPV_ARGS (&video_device));
1333 if (gst_d3d11_result (hr, device))
1334 priv->video_device = video_device;
1336 g_mutex_unlock (&priv->resource_lock);
1338 return priv->video_device;
1342 * gst_d3d11_device_get_video_context_handle:
1343 * @device: a #GstD3D11Device
1345 * Used for various D3D11 APIs directly. Caller must not destroy returned device
1348 * Returns: (nullable) (transfer none): the ID3D11VideoContext handle or %NULL
1349 * if ID3D11VideoContext is unavailable.
1353 ID3D11VideoContext *
1354 gst_d3d11_device_get_video_context_handle (GstD3D11Device * device)
1356 GstD3D11DevicePrivate *priv;
1358 g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL);
1360 priv = device->priv;
1361 g_mutex_lock (&priv->resource_lock);
1362 if (!priv->video_context) {
1364 ID3D11VideoContext *video_context = NULL;
1366 hr = priv->device_context->QueryInterface (IID_PPV_ARGS (&video_context));
1367 if (gst_d3d11_result (hr, device))
1368 priv->video_context = video_context;
1370 g_mutex_unlock (&priv->resource_lock);
1372 return priv->video_context;
1376 * gst_d3d11_device_lock:
1377 * @device: a #GstD3D11Device
1379 * Take lock for @device. Any thread-unsafe API call needs to be
1380 * protected by this method. This call must be paired with
1381 * gst_d3d11_device_unlock()
1386 gst_d3d11_device_lock (GstD3D11Device * device)
1388 GstD3D11DevicePrivate *priv;
1390 g_return_if_fail (GST_IS_D3D11_DEVICE (device));
1392 priv = device->priv;
1394 GST_TRACE_OBJECT (device, "device locking");
1395 g_rec_mutex_lock (&priv->extern_lock);
1396 GST_TRACE_OBJECT (device, "device locked");
1400 * gst_d3d11_device_unlock:
1401 * @device: a #GstD3D11Device
1403 * Release lock for @device. This call must be paired with
1404 * gst_d3d11_device_lock()
1409 gst_d3d11_device_unlock (GstD3D11Device * device)
1411 GstD3D11DevicePrivate *priv;
1413 g_return_if_fail (GST_IS_D3D11_DEVICE (device));
1415 priv = device->priv;
1417 g_rec_mutex_unlock (&priv->extern_lock);
1418 GST_TRACE_OBJECT (device, "device unlocked");
1422 * gst_d3d11_device_format_from_gst:
1423 * @device: a #GstD3D11Device
1424 * @format: a #GstVideoFormat
1426 * Returns: (transfer none) (nullable): a pointer to #GstD3D11Format
1427 * or %NULL if @format is not supported by @device
1431 const GstD3D11Format *
1432 gst_d3d11_device_format_from_gst (GstD3D11Device * device,
1433 GstVideoFormat format)
1435 GstD3D11DevicePrivate *priv;
1438 g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL);
1440 priv = device->priv;
1442 for (i = 0; i < G_N_ELEMENTS (priv->format_table); i++) {
1443 if (priv->format_table[i].format == format)
1444 return &priv->format_table[i];