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);
173 g_once_init_leave (&_init, 1);
176 if (d3d11_debug_module)
182 static inline GstDebugLevel
183 d3d11_message_severity_to_gst (D3D11_MESSAGE_SEVERITY level)
186 case D3D11_MESSAGE_SEVERITY_CORRUPTION:
187 case D3D11_MESSAGE_SEVERITY_ERROR:
188 return GST_LEVEL_ERROR;
189 case D3D11_MESSAGE_SEVERITY_WARNING:
190 return GST_LEVEL_WARNING;
191 case D3D11_MESSAGE_SEVERITY_INFO:
192 return GST_LEVEL_INFO;
193 case D3D11_MESSAGE_SEVERITY_MESSAGE:
194 return GST_LEVEL_DEBUG;
199 return GST_LEVEL_LOG;
203 gst_d3d11_device_d3d11_debug (GstD3D11Device * device,
204 const gchar * file, const gchar * function, gint line)
206 GstD3D11DevicePrivate *priv = device->priv;
211 ID3D11InfoQueue *info_queue = priv->d3d11_info_queue;
216 num_msg = info_queue->GetNumStoredMessages ();
218 for (i = 0; i < num_msg; i++) {
221 hr = info_queue->GetMessage (i, NULL, &msg_len);
223 if (FAILED (hr) || msg_len == 0) {
227 msg = (D3D11_MESSAGE *) g_alloca (msg_len);
228 hr = info_queue->GetMessage (i, msg, &msg_len);
230 level = d3d11_message_severity_to_gst (msg->Severity);
231 if (msg->Category == D3D11_MESSAGE_CATEGORY_STATE_CREATION &&
232 level > GST_LEVEL_ERROR) {
233 /* Do not warn for live object, since there would be live object
234 * when ReportLiveDeviceObjects was called */
235 level = GST_LEVEL_INFO;
238 gst_debug_log (gst_d3d11_debug_layer_debug, level, file, function, line,
239 G_OBJECT (device), "D3D11InfoQueue: %s", msg->pDescription);
242 info_queue->ClearStoredMessages ();
248 gst_d3d11_device_d3d11_debug (GstD3D11Device * device,
249 const gchar * file, const gchar * function, gint line)
258 gst_d3d11_device_enable_dxgi_debug (void)
260 static gsize _init = 0;
261 gboolean ret = FALSE;
263 /* If all below libraries are unavailable, d3d11 device would fail with
264 * D3D11_CREATE_DEVICE_DEBUG flag */
265 if (g_once_init_enter (&_init)) {
266 #if (!GST_D3D11_WINAPI_ONLY_APP)
267 dxgi_debug_module = g_module_open ("dxgidebug.dll", G_MODULE_BIND_LAZY);
269 if (dxgi_debug_module)
270 g_module_symbol (dxgi_debug_module,
271 "DXGIGetDebugInterface", (gpointer *) & GstDXGIGetDebugInterface);
272 if (GstDXGIGetDebugInterface)
274 #elif (GST_D3D11_DXGI_HEADER_VERSION >= 3)
277 g_once_init_leave (&_init, 1);
284 gst_d3d11_device_dxgi_get_device_interface (REFIID riid, void **debug)
286 #if (!GST_D3D11_WINAPI_ONLY_APP)
287 if (GstDXGIGetDebugInterface) {
288 return GstDXGIGetDebugInterface (riid, debug);
290 #elif (GST_D3D11_DXGI_HEADER_VERSION >= 3)
291 return DXGIGetDebugInterface1 (0, riid, debug);
294 return E_NOINTERFACE;
297 static inline GstDebugLevel
298 dxgi_info_queue_message_severity_to_gst (DXGI_INFO_QUEUE_MESSAGE_SEVERITY level)
301 case DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION:
302 case DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR:
303 return GST_LEVEL_ERROR;
304 case DXGI_INFO_QUEUE_MESSAGE_SEVERITY_WARNING:
305 return GST_LEVEL_WARNING;
306 case DXGI_INFO_QUEUE_MESSAGE_SEVERITY_INFO:
307 return GST_LEVEL_INFO;
308 case DXGI_INFO_QUEUE_MESSAGE_SEVERITY_MESSAGE:
309 return GST_LEVEL_DEBUG;
314 return GST_LEVEL_LOG;
318 gst_d3d11_device_dxgi_debug (GstD3D11Device * device,
319 const gchar * file, const gchar * function, gint line)
321 GstD3D11DevicePrivate *priv = device->priv;
322 DXGI_INFO_QUEUE_MESSAGE *msg;
326 IDXGIInfoQueue *info_queue = priv->dxgi_info_queue;
331 num_msg = info_queue->GetNumStoredMessages (DXGI_DEBUG_ALL);
333 for (i = 0; i < num_msg; i++) {
336 hr = info_queue->GetMessage (DXGI_DEBUG_ALL, i, NULL, &msg_len);
338 if (FAILED (hr) || msg_len == 0) {
342 msg = (DXGI_INFO_QUEUE_MESSAGE *) g_alloca (msg_len);
343 hr = info_queue->GetMessage (DXGI_DEBUG_ALL, i, msg, &msg_len);
345 level = dxgi_info_queue_message_severity_to_gst (msg->Severity);
346 gst_debug_log (gst_d3d11_debug_layer_debug, level, file, function, line,
347 G_OBJECT (device), "DXGIInfoQueue: %s", msg->pDescription);
350 info_queue->ClearStoredMessages (DXGI_DEBUG_ALL);
356 gst_d3d11_device_dxgi_debug (GstD3D11Device * device,
357 const gchar * file, const gchar * function, gint line)
365 gst_d3d11_device_class_init (GstD3D11DeviceClass * klass)
367 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
368 GParamFlags readable_flags =
369 (GParamFlags) (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
371 gobject_class->get_property = gst_d3d11_device_get_property;
372 gobject_class->dispose = gst_d3d11_device_dispose;
373 gobject_class->finalize = gst_d3d11_device_finalize;
375 g_object_class_install_property (gobject_class, PROP_ADAPTER,
376 g_param_spec_uint ("adapter", "Adapter",
377 "DXGI Adapter index for creating device",
378 0, G_MAXUINT32, DEFAULT_ADAPTER, readable_flags));
380 g_object_class_install_property (gobject_class, PROP_DEVICE_ID,
381 g_param_spec_uint ("device-id", "Device Id",
382 "DXGI Device ID", 0, G_MAXUINT32, 0, readable_flags));
384 g_object_class_install_property (gobject_class, PROP_VENDOR_ID,
385 g_param_spec_uint ("vendor-id", "Vendor Id",
386 "DXGI Vendor ID", 0, G_MAXUINT32, 0, readable_flags));
388 g_object_class_install_property (gobject_class, PROP_HARDWARE,
389 g_param_spec_boolean ("hardware", "Hardware",
390 "Whether hardware device or not", TRUE, readable_flags));
392 g_object_class_install_property (gobject_class, PROP_DESCRIPTION,
393 g_param_spec_string ("description", "Description",
394 "Human readable device description", NULL, readable_flags));
396 g_object_class_install_property (gobject_class, PROP_ADAPTER_LUID,
397 g_param_spec_int64 ("adapter-luid", "Adapter LUID",
398 "DXGI Adapter LUID (Locally Unique Identifier) of created device",
399 G_MININT64, G_MAXINT64, 0, readable_flags));
401 gst_d3d11_memory_init_once ();
405 gst_d3d11_device_init (GstD3D11Device * self)
407 GstD3D11DevicePrivate *priv;
409 priv = (GstD3D11DevicePrivate *)
410 gst_d3d11_device_get_instance_private (self);
411 priv->adapter = DEFAULT_ADAPTER;
413 g_rec_mutex_init (&priv->extern_lock);
414 g_mutex_init (&priv->resource_lock);
420 is_windows_8_or_greater (void)
422 static gsize version_once = 0;
423 static gboolean ret = FALSE;
425 if (g_once_init_enter (&version_once)) {
426 #if (!GST_D3D11_WINAPI_ONLY_APP)
427 if (IsWindows8OrGreater ())
433 g_once_init_leave (&version_once, 1);
439 inline D3D11_FORMAT_SUPPORT
440 operator | (D3D11_FORMAT_SUPPORT lhs, D3D11_FORMAT_SUPPORT rhs)
442 return static_cast < D3D11_FORMAT_SUPPORT > (static_cast < UINT >
443 (lhs) | static_cast < UINT > (rhs));
446 inline D3D11_FORMAT_SUPPORT
447 operator |= (D3D11_FORMAT_SUPPORT lhs, D3D11_FORMAT_SUPPORT rhs)
453 can_support_format (GstD3D11Device * self, DXGI_FORMAT format,
454 D3D11_FORMAT_SUPPORT extra_flags)
456 GstD3D11DevicePrivate *priv = self->priv;
457 ID3D11Device *handle = priv->device;
460 D3D11_FORMAT_SUPPORT flags = D3D11_FORMAT_SUPPORT_TEXTURE2D;
462 flags |= extra_flags;
464 if (!is_windows_8_or_greater ()) {
465 GST_INFO_OBJECT (self, "DXGI format %d needs Windows 8 or greater",
470 hr = handle->CheckFormatSupport (format, &supported);
472 GST_DEBUG_OBJECT (self, "DXGI format %d is not supported by device",
477 if ((supported & flags) != flags) {
478 GST_DEBUG_OBJECT (self,
479 "DXGI format %d doesn't support flag 0x%x (supported flag 0x%x)",
480 (guint) format, (guint) supported, (guint) flags);
484 GST_INFO_OBJECT (self, "Device supports DXGI format %d", (guint) format);
490 gst_d3d11_device_setup_format_table (GstD3D11Device * self)
492 GstD3D11DevicePrivate *priv = self->priv;
496 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_BGRA;
497 priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_B8G8R8A8_UNORM;
498 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_B8G8R8A8_UNORM;
501 /* Identical to BGRA, but alpha will be ignored */
502 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_BGRx;
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 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_RGBA;
508 priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
509 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_R8G8B8A8_UNORM;
512 /* Identical to RGBA, but alpha will be ignored */
513 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_RGBx;
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 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_RGB10A2_LE;
519 priv->format_table[n_formats].resource_format[0] =
520 DXGI_FORMAT_R10G10B10A2_UNORM;
521 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_R10G10B10A2_UNORM;
525 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_VUYA;
526 priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
527 if (can_support_format (self, DXGI_FORMAT_AYUV,
528 D3D11_FORMAT_SUPPORT_RENDER_TARGET |
529 D3D11_FORMAT_SUPPORT_SHADER_SAMPLE))
530 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_AYUV;
532 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_UNKNOWN;
535 /* FIXME: d3d11 sampler doesn't support packed-and-subsampled formats
536 * very well (and it's really poorly documented).
537 * As per observation, d3d11 samplers seems to be dropping the second
538 * Y componet from "Y0-U0-Y1-V0" pair which results in bad visual quality
539 * than 4:2:0 subsampled formats. We should revisit this later */
541 /* TODO: The best would be using d3d11 compute shader to handle this kinds of
542 * samples but comute shader is not implemented yet by us.
544 * Another simple approach is using d3d11 video processor,
545 * but capability will be very device dependent because it depends on
546 * GPU vendor's driver implementation, moreover, software fallback does
547 * not support d3d11 video processor. So it's not reliable in this case */
549 /* NOTE: packted yuv 4:2:2 YUY2, UYVY, and VYUY formats are not natively
550 * supported render target view formats
551 * (i.e., cannot be output format of shader pipeline) */
552 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_YUY2;
553 if (can_support_format (self, DXGI_FORMAT_YUY2,
554 D3D11_FORMAT_SUPPORT_SHADER_SAMPLE)) {
555 priv->format_table[n_formats].resource_format[0] =
556 DXGI_FORMAT_R8G8B8A8_UNORM;
557 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_YUY2;
559 /* If DXGI_FORMAT_YUY2 format is not supported, use this format,
560 * it's analogous to YUY2 */
561 priv->format_table[n_formats].resource_format[0] =
562 DXGI_FORMAT_G8R8_G8B8_UNORM;
566 /* No native DXGI format available for UYVY */
567 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_UYVY;
568 priv->format_table[n_formats].resource_format[0] =
569 DXGI_FORMAT_R8G8_B8G8_UNORM;
572 /* No native DXGI format available for VYUY */
573 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_VYUY;
574 priv->format_table[n_formats].resource_format[0] =
575 DXGI_FORMAT_R8G8_B8G8_UNORM;
578 /* Y210 and Y410 formats cannot support rtv */
579 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_Y210;
580 priv->format_table[n_formats].resource_format[0] =
581 DXGI_FORMAT_R16G16B16A16_UNORM;
582 if (can_support_format (self, DXGI_FORMAT_Y210,
583 D3D11_FORMAT_SUPPORT_SHADER_SAMPLE))
584 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_Y210;
586 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_UNKNOWN;
590 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_Y410;
591 priv->format_table[n_formats].resource_format[0] =
592 DXGI_FORMAT_R10G10B10A2_UNORM;
593 if (can_support_format (self, DXGI_FORMAT_Y410,
594 D3D11_FORMAT_SUPPORT_SHADER_SAMPLE))
595 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_Y410;
597 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_UNKNOWN;
600 /* YUV semi-planar */
601 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_NV12;
602 priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R8_UNORM;
603 priv->format_table[n_formats].resource_format[1] = DXGI_FORMAT_R8G8_UNORM;
604 if (can_support_format (self, DXGI_FORMAT_NV12,
605 D3D11_FORMAT_SUPPORT_RENDER_TARGET |
606 D3D11_FORMAT_SUPPORT_SHADER_SAMPLE))
607 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_NV12;
609 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_UNKNOWN;
612 /* no native format for NV21 */
613 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_NV21;
614 priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R8_UNORM;
615 priv->format_table[n_formats].resource_format[1] = DXGI_FORMAT_R8G8_UNORM;
616 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_UNKNOWN;
619 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_P010_10LE;
620 priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R16_UNORM;
621 priv->format_table[n_formats].resource_format[1] = DXGI_FORMAT_R16G16_UNORM;
622 if (can_support_format (self, DXGI_FORMAT_P010,
623 D3D11_FORMAT_SUPPORT_RENDER_TARGET |
624 D3D11_FORMAT_SUPPORT_SHADER_SAMPLE))
625 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_P010;
627 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_UNKNOWN;
630 /* P012 is identical to P016 from runtime point of view */
631 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_P012_LE;
632 priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R16_UNORM;
633 priv->format_table[n_formats].resource_format[1] = DXGI_FORMAT_R16G16_UNORM;
634 if (can_support_format (self, DXGI_FORMAT_P016,
635 D3D11_FORMAT_SUPPORT_RENDER_TARGET |
636 D3D11_FORMAT_SUPPORT_SHADER_SAMPLE))
637 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_P016;
639 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_UNKNOWN;
642 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_P016_LE;
643 priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R16_UNORM;
644 priv->format_table[n_formats].resource_format[1] = DXGI_FORMAT_R16G16_UNORM;
645 if (can_support_format (self, DXGI_FORMAT_P016,
646 D3D11_FORMAT_SUPPORT_RENDER_TARGET |
647 D3D11_FORMAT_SUPPORT_SHADER_SAMPLE))
648 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_P016;
650 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_UNKNOWN;
654 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_I420;
655 priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R8_UNORM;
656 priv->format_table[n_formats].resource_format[1] = DXGI_FORMAT_R8_UNORM;
657 priv->format_table[n_formats].resource_format[2] = DXGI_FORMAT_R8_UNORM;
660 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_YV12;
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_I420_10LE;
667 priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R16_UNORM;
668 priv->format_table[n_formats].resource_format[1] = DXGI_FORMAT_R16_UNORM;
669 priv->format_table[n_formats].resource_format[2] = DXGI_FORMAT_R16_UNORM;
672 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_I420_12LE;
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_Y42B;
679 priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R8_UNORM;
680 priv->format_table[n_formats].resource_format[1] = DXGI_FORMAT_R8_UNORM;
681 priv->format_table[n_formats].resource_format[2] = DXGI_FORMAT_R8_UNORM;
684 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_I422_10LE;
685 priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R16_UNORM;
686 priv->format_table[n_formats].resource_format[1] = DXGI_FORMAT_R16_UNORM;
687 priv->format_table[n_formats].resource_format[2] = DXGI_FORMAT_R16_UNORM;
690 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_I422_12LE;
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_Y444;
697 priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R8_UNORM;
698 priv->format_table[n_formats].resource_format[1] = DXGI_FORMAT_R8_UNORM;
699 priv->format_table[n_formats].resource_format[2] = DXGI_FORMAT_R8_UNORM;
702 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_Y444_10LE;
703 priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R16_UNORM;
704 priv->format_table[n_formats].resource_format[1] = DXGI_FORMAT_R16_UNORM;
705 priv->format_table[n_formats].resource_format[2] = DXGI_FORMAT_R16_UNORM;
708 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_Y444_12LE;
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_16LE;
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;
721 /* NOTE: To support conversion by using video processor,
722 * mark DXGI_FORMAT_{R8,R16}_UNORM formats as known dxgi_format.
723 * Otherwise, d3d11 elements will not try to use video processor for
725 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_GRAY8;
726 priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R8_UNORM;
727 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_R8_UNORM;
730 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_GRAY16_LE;
731 priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R16_UNORM;
732 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_R16_UNORM;
735 g_assert (n_formats == GST_D3D11_N_FORMATS);
739 gst_d3d11_device_get_property (GObject * object, guint prop_id,
740 GValue * value, GParamSpec * pspec)
742 GstD3D11Device *self = GST_D3D11_DEVICE (object);
743 GstD3D11DevicePrivate *priv = self->priv;
747 g_value_set_uint (value, priv->adapter);
750 g_value_set_uint (value, priv->device_id);
753 g_value_set_uint (value, priv->vendor_id);
756 g_value_set_boolean (value, priv->hardware);
758 case PROP_DESCRIPTION:
759 g_value_set_string (value, priv->description);
761 case PROP_ADAPTER_LUID:
762 g_value_set_int64 (value, priv->adapter_luid);
765 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
771 gst_d3d11_device_dispose (GObject * object)
773 GstD3D11Device *self = GST_D3D11_DEVICE (object);
774 GstD3D11DevicePrivate *priv = self->priv;
776 GST_LOG_OBJECT (self, "dispose");
778 GST_D3D11_CLEAR_COM (priv->video_device);
779 GST_D3D11_CLEAR_COM (priv->video_context);
780 GST_D3D11_CLEAR_COM (priv->device);
781 GST_D3D11_CLEAR_COM (priv->device_context);
782 GST_D3D11_CLEAR_COM (priv->factory);
783 #if HAVE_D3D11SDKLAYERS_H
784 if (priv->d3d11_debug) {
785 priv->d3d11_debug->ReportLiveDeviceObjects ((D3D11_RLDO_FLAGS)
786 GST_D3D11_RLDO_FLAGS);
788 GST_D3D11_CLEAR_COM (priv->d3d11_debug);
790 if (priv->d3d11_info_queue)
791 gst_d3d11_device_d3d11_debug (self, __FILE__, GST_FUNCTION, __LINE__);
793 GST_D3D11_CLEAR_COM (priv->d3d11_info_queue);
797 if (priv->dxgi_debug) {
798 priv->dxgi_debug->ReportLiveObjects (DXGI_DEBUG_ALL,
799 (DXGI_DEBUG_RLO_FLAGS) GST_D3D11_RLDO_FLAGS);
801 GST_D3D11_CLEAR_COM (priv->dxgi_debug);
803 if (priv->dxgi_info_queue)
804 gst_d3d11_device_dxgi_debug (self, __FILE__, GST_FUNCTION, __LINE__);
806 GST_D3D11_CLEAR_COM (priv->dxgi_info_queue);
809 G_OBJECT_CLASS (parent_class)->dispose (object);
813 gst_d3d11_device_finalize (GObject * object)
815 GstD3D11Device *self = GST_D3D11_DEVICE (object);
816 GstD3D11DevicePrivate *priv = self->priv;
818 GST_LOG_OBJECT (self, "finalize");
820 g_rec_mutex_clear (&priv->extern_lock);
821 g_mutex_clear (&priv->resource_lock);
822 g_free (priv->description);
824 G_OBJECT_CLASS (parent_class)->finalize (object);
829 DEVICE_CONSTRUCT_FOR_ADAPTER_INDEX,
830 DEVICE_CONSTRUCT_FOR_ADAPTER_LUID,
831 DEVICE_CONSTRUCT_WRAPPED,
832 } GstD3D11DeviceConstructType;
834 typedef struct _GstD3D11DeviceConstructData
840 ID3D11Device *device;
842 GstD3D11DeviceConstructType type;
844 } GstD3D11DeviceConstructData;
847 _gst_d3d11_device_get_adapter (const GstD3D11DeviceConstructData * data,
848 IDXGIFactory1 * factory, guint * index, DXGI_ADAPTER_DESC * adapter_desc,
849 IDXGIAdapter1 ** dxgi_adapter)
852 ComPtr < IDXGIAdapter1 > adapter1;
853 DXGI_ADAPTER_DESC desc;
855 switch (data->type) {
856 case DEVICE_CONSTRUCT_FOR_ADAPTER_INDEX:
858 hr = factory->EnumAdapters1 (data->data.adapter_index, &adapter1);
862 hr = adapter1->GetDesc (&desc);
866 *index = data->data.adapter_index;
867 *adapter_desc = desc;
868 *dxgi_adapter = adapter1.Detach ();
872 case DEVICE_CONSTRUCT_FOR_ADAPTER_LUID:
874 for (guint i = 0;; i++) {
879 hr = factory->EnumAdapters1 (i, &adapter1);
883 hr = adapter1->GetDesc (&desc);
887 luid = gst_d3d11_luid_to_int64 (&desc.AdapterLuid);
888 if (luid != data->data.adapter_luid)
892 *adapter_desc = desc;
893 *dxgi_adapter = adapter1.Detach ();
900 case DEVICE_CONSTRUCT_WRAPPED:
902 ComPtr < IDXGIDevice > dxgi_device;
903 ComPtr < IDXGIAdapter > adapter;
904 ID3D11Device *device = data->data.device;
907 hr = device->QueryInterface (IID_PPV_ARGS (&dxgi_device));
911 hr = dxgi_device->GetAdapter (&adapter);
915 hr = adapter.As (&adapter1);
919 hr = adapter1->GetDesc (&desc);
923 luid = gst_d3d11_luid_to_int64 (&desc.AdapterLuid);
925 for (guint i = 0;; i++) {
926 DXGI_ADAPTER_DESC tmp_desc;
927 ComPtr < IDXGIAdapter1 > tmp;
929 hr = factory->EnumAdapters1 (i, &tmp);
933 hr = tmp->GetDesc (&tmp_desc);
937 if (luid != gst_d3d11_luid_to_int64 (&tmp_desc.AdapterLuid))
941 *adapter_desc = desc;
942 *dxgi_adapter = adapter1.Detach ();
950 g_assert_not_reached ();
958 gst_d3d11_device_setup_debug_layer (GstD3D11Device * self)
961 if (gst_debug_category_get_threshold (gst_d3d11_debug_layer_debug) >
963 GstD3D11DevicePrivate *priv = self->priv;
965 if (gst_d3d11_device_enable_dxgi_debug ()) {
966 IDXGIDebug *debug = nullptr;
967 IDXGIInfoQueue *info_queue = nullptr;
970 GST_CAT_INFO_OBJECT (gst_d3d11_debug_layer_debug, self,
971 "dxgi debug library was loaded");
972 hr = gst_d3d11_device_dxgi_get_device_interface (IID_PPV_ARGS (&debug));
974 if (SUCCEEDED (hr)) {
975 GST_CAT_INFO_OBJECT (gst_d3d11_debug_layer_debug, self,
976 "IDXGIDebug interface available");
977 priv->dxgi_debug = debug;
979 hr = gst_d3d11_device_dxgi_get_device_interface (IID_PPV_ARGS
981 if (SUCCEEDED (hr)) {
982 GST_CAT_INFO_OBJECT (gst_d3d11_debug_layer_debug, self,
983 "IDXGIInfoQueue interface available");
984 priv->dxgi_info_queue = info_queue;
988 GST_CAT_INFO_OBJECT (gst_d3d11_debug_layer_debug, self,
989 "couldn't load dxgi debug library");
994 #if HAVE_D3D11SDKLAYERS_H
995 if ((self->priv->create_flags & D3D11_CREATE_DEVICE_DEBUG) != 0) {
996 GstD3D11DevicePrivate *priv = self->priv;
998 ID3D11InfoQueue *info_queue;
1001 hr = priv->device->QueryInterface (IID_PPV_ARGS (&debug));
1003 if (SUCCEEDED (hr)) {
1004 GST_CAT_INFO_OBJECT (gst_d3d11_debug_layer_debug, self,
1005 "D3D11Debug interface available");
1006 priv->d3d11_debug = debug;
1008 hr = priv->device->QueryInterface (IID_PPV_ARGS (&info_queue));
1009 if (SUCCEEDED (hr)) {
1010 GST_CAT_INFO_OBJECT (gst_d3d11_debug_layer_debug, self,
1011 "ID3D11InfoQueue interface available");
1012 priv->d3d11_info_queue = info_queue;
1019 static GstD3D11Device *
1020 gst_d3d11_device_new_internal (const GstD3D11DeviceConstructData * data)
1022 ComPtr < IDXGIAdapter1 > adapter;
1023 ComPtr < IDXGIFactory1 > factory;
1024 ComPtr < ID3D11Device > device;
1025 ComPtr < ID3D11DeviceContext > device_context;
1028 guint adapter_index = 0;
1029 DXGI_ADAPTER_DESC adapter_desc;
1030 static const D3D_FEATURE_LEVEL feature_levels[] = {
1031 D3D_FEATURE_LEVEL_11_1,
1032 D3D_FEATURE_LEVEL_11_0,
1033 D3D_FEATURE_LEVEL_10_1,
1034 D3D_FEATURE_LEVEL_10_0,
1035 D3D_FEATURE_LEVEL_9_3,
1036 D3D_FEATURE_LEVEL_9_2,
1037 D3D_FEATURE_LEVEL_9_1
1039 D3D_FEATURE_LEVEL selected_level;
1043 hr = CreateDXGIFactory1 (IID_PPV_ARGS (&factory));
1044 if (!gst_d3d11_result (hr, NULL)) {
1045 GST_ERROR ("cannot create dxgi factory, hr: 0x%x", (guint) hr);
1050 if (data->type != DEVICE_CONSTRUCT_WRAPPED) {
1051 create_flags = data->create_flags;
1052 #if HAVE_D3D11SDKLAYERS_H
1053 if (gst_debug_category_get_threshold (gst_d3d11_debug_layer_debug) >
1055 /* DirectX SDK should be installed on system for this */
1056 if (gst_d3d11_device_enable_d3d11_debug ()) {
1057 GST_CAT_INFO (gst_d3d11_debug_layer_debug,
1058 "d3d11 debug library was loaded");
1059 create_flags |= D3D11_CREATE_DEVICE_DEBUG;
1061 GST_CAT_INFO (gst_d3d11_debug_layer_debug,
1062 "couldn't load d3d11 debug library");
1068 /* Ensure valid device handle */
1069 if (data->type == DEVICE_CONSTRUCT_WRAPPED) {
1070 ID3D11Device *external_device = data->data.device;
1072 hr = external_device->QueryInterface (IID_PPV_ARGS (&device));
1074 GST_ERROR ("Not a valid external ID3D11Device handle");
1078 device->GetImmediateContext (&device_context);
1081 hr = _gst_d3d11_device_get_adapter (data, factory.Get (), &adapter_index,
1082 &adapter_desc, &adapter);
1084 GST_INFO ("Failed to get DXGI adapter");
1088 if (data->type != DEVICE_CONSTRUCT_WRAPPED) {
1089 hr = D3D11CreateDevice (adapter.Get (), D3D_DRIVER_TYPE_UNKNOWN,
1090 NULL, create_flags, feature_levels, G_N_ELEMENTS (feature_levels),
1091 D3D11_SDK_VERSION, &device, &selected_level, &device_context);
1094 /* Retry if the system could not recognize D3D_FEATURE_LEVEL_11_1 */
1095 hr = D3D11CreateDevice (adapter.Get (), D3D_DRIVER_TYPE_UNKNOWN,
1096 NULL, create_flags, &feature_levels[1],
1097 G_N_ELEMENTS (feature_levels) - 1, D3D11_SDK_VERSION, &device,
1098 &selected_level, &device_context);
1101 /* if D3D11_CREATE_DEVICE_DEBUG was enabled but couldn't create device,
1102 * try it without the flag again */
1103 if (FAILED (hr) && (create_flags & D3D11_CREATE_DEVICE_DEBUG) != 0) {
1104 create_flags &= ~D3D11_CREATE_DEVICE_DEBUG;
1106 hr = D3D11CreateDevice (adapter.Get (), D3D_DRIVER_TYPE_UNKNOWN,
1107 NULL, create_flags, feature_levels, G_N_ELEMENTS (feature_levels),
1108 D3D11_SDK_VERSION, &device, &selected_level, &device_context);
1111 /* Retry if the system could not recognize D3D_FEATURE_LEVEL_11_1 */
1112 hr = D3D11CreateDevice (adapter.Get (), D3D_DRIVER_TYPE_UNKNOWN,
1113 NULL, create_flags, &feature_levels[1],
1114 G_N_ELEMENTS (feature_levels) - 1, D3D11_SDK_VERSION, &device,
1115 &selected_level, &device_context);
1121 switch (data->type) {
1122 case DEVICE_CONSTRUCT_FOR_ADAPTER_INDEX:
1124 GST_INFO ("Failed to create d3d11 device for adapter index %d"
1125 " with flags 0x%x, hr: 0x%x", data->data.adapter_index,
1126 create_flags, (guint) hr);
1129 case DEVICE_CONSTRUCT_FOR_ADAPTER_LUID:
1131 GST_ERROR ("Failed to create d3d11 device for adapter luid %"
1132 G_GINT64_FORMAT " with flags 0x%x, hr: 0x%x",
1133 data->data.adapter_luid, create_flags, (guint) hr);
1143 GstD3D11Device *self = nullptr;
1144 GstD3D11DevicePrivate *priv;
1146 self = (GstD3D11Device *) g_object_new (GST_TYPE_D3D11_DEVICE, nullptr);
1147 gst_object_ref_sink (self);
1151 priv->adapter = adapter_index;
1152 priv->device = device.Detach ();
1153 priv->device_context = device_context.Detach ();
1154 priv->factory = factory.Detach ();
1156 priv->vendor_id = adapter_desc.VendorId;
1157 priv->device_id = adapter_desc.DeviceId;
1158 priv->description = g_utf16_to_utf8 ((gunichar2 *) adapter_desc.Description,
1159 -1, nullptr, nullptr, nullptr);
1160 priv->adapter_luid = gst_d3d11_luid_to_int64 (&adapter_desc.AdapterLuid);
1162 DXGI_ADAPTER_DESC1 desc1;
1163 hr = adapter->GetDesc1 (&desc1);
1165 /* DXGI_ADAPTER_FLAG_SOFTWARE is missing in dxgi.h of mingw */
1166 if (SUCCEEDED (hr) && (desc1.Flags & 0x2) != 0x2)
1167 priv->hardware = TRUE;
1169 priv->create_flags = create_flags;
1170 gst_d3d11_device_setup_format_table (self);
1171 gst_d3d11_device_setup_debug_layer (self);
1177 * gst_d3d11_device_new:
1178 * @adapter_index: the index of adapter for creating d3d11 device
1179 * @flags: a D3D11_CREATE_DEVICE_FLAG value used for creating d3d11 device
1181 * Returns: (transfer full) (nullable): a new #GstD3D11Device for @adapter_index
1182 * or %NULL when failed to create D3D11 device with given adapter index.
1187 gst_d3d11_device_new (guint adapter_index, guint flags)
1189 GstD3D11DeviceConstructData data;
1191 data.data.adapter_index = adapter_index;
1192 data.type = DEVICE_CONSTRUCT_FOR_ADAPTER_INDEX;
1193 data.create_flags = flags;
1195 return gst_d3d11_device_new_internal (&data);
1199 * gst_d3d11_device_new_for_adapter_luid:
1200 * @adapter_luid: an int64 representation of the DXGI adapter LUID
1201 * @flags: a D3D11_CREATE_DEVICE_FLAG value used for creating d3d11 device
1203 * Returns: (transfer full) (nullable): a new #GstD3D11Device for @adapter_luid
1204 * or %NULL when failed to create D3D11 device with given adapter luid.
1209 gst_d3d11_device_new_for_adapter_luid (gint64 adapter_luid, guint flags)
1211 GstD3D11DeviceConstructData data;
1213 data.data.adapter_luid = adapter_luid;
1214 data.type = DEVICE_CONSTRUCT_FOR_ADAPTER_LUID;
1215 data.create_flags = flags;
1217 return gst_d3d11_device_new_internal (&data);
1221 * gst_d3d11_device_new_wrapped:
1222 * @device: (transfer none): an existing ID3D11Device handle
1224 * Returns: (transfer full) (nullable): a new #GstD3D11Device for @device
1225 * or %NULL if an error occurred
1230 gst_d3d11_device_new_wrapped (ID3D11Device * device)
1232 GstD3D11DeviceConstructData data;
1234 g_return_val_if_fail (device != nullptr, nullptr);
1236 data.data.device = device;
1237 data.type = DEVICE_CONSTRUCT_WRAPPED;
1238 data.create_flags = 0;
1240 return gst_d3d11_device_new_internal (&data);
1244 * gst_d3d11_device_get_device_handle:
1245 * @device: a #GstD3D11Device
1247 * Used for various D3D11 APIs directly. Caller must not destroy returned device
1250 * Returns: (transfer none): the ID3D11Device handle
1255 gst_d3d11_device_get_device_handle (GstD3D11Device * device)
1257 g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL);
1259 return device->priv->device;
1263 * gst_d3d11_device_get_device_context_handle:
1264 * @device: a #GstD3D11Device
1266 * Used for various D3D11 APIs directly. Caller must not destroy returned device
1267 * object. Any ID3D11DeviceContext call needs to be protected by
1268 * gst_d3d11_device_lock() and gst_d3d11_device_unlock() method.
1270 * Returns: (transfer none): the immeidate ID3D11DeviceContext handle
1274 ID3D11DeviceContext *
1275 gst_d3d11_device_get_device_context_handle (GstD3D11Device * device)
1277 g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL);
1279 return device->priv->device_context;
1283 * gst_d3d11_device_get_dxgi_factory_handle:
1284 * @device: a #GstD3D11Device
1286 * Used for various D3D11 APIs directly. Caller must not destroy returned device
1289 * Returns: (transfer none): the IDXGIFactory1 handle
1294 gst_d3d11_device_get_dxgi_factory_handle (GstD3D11Device * device)
1296 g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL);
1298 return device->priv->factory;
1302 * gst_d3d11_device_get_video_device_handle:
1303 * @device: a #GstD3D11Device
1305 * Used for various D3D11 APIs directly. Caller must not destroy returned device
1308 * Returns: (nullable) (transfer none) : the ID3D11VideoDevice handle or %NULL
1309 * if ID3D11VideoDevice is unavailable.
1314 gst_d3d11_device_get_video_device_handle (GstD3D11Device * device)
1316 GstD3D11DevicePrivate *priv;
1318 g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL);
1320 priv = device->priv;
1321 g_mutex_lock (&priv->resource_lock);
1322 if (!priv->video_device) {
1324 ID3D11VideoDevice *video_device = NULL;
1326 hr = priv->device->QueryInterface (IID_PPV_ARGS (&video_device));
1327 if (gst_d3d11_result (hr, device))
1328 priv->video_device = video_device;
1330 g_mutex_unlock (&priv->resource_lock);
1332 return priv->video_device;
1336 * gst_d3d11_device_get_video_context_handle:
1337 * @device: a #GstD3D11Device
1339 * Used for various D3D11 APIs directly. Caller must not destroy returned device
1342 * Returns: (nullable) (transfer none): the ID3D11VideoContext handle or %NULL
1343 * if ID3D11VideoContext is unavailable.
1347 ID3D11VideoContext *
1348 gst_d3d11_device_get_video_context_handle (GstD3D11Device * device)
1350 GstD3D11DevicePrivate *priv;
1352 g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL);
1354 priv = device->priv;
1355 g_mutex_lock (&priv->resource_lock);
1356 if (!priv->video_context) {
1358 ID3D11VideoContext *video_context = NULL;
1360 hr = priv->device_context->QueryInterface (IID_PPV_ARGS (&video_context));
1361 if (gst_d3d11_result (hr, device))
1362 priv->video_context = video_context;
1364 g_mutex_unlock (&priv->resource_lock);
1366 return priv->video_context;
1370 * gst_d3d11_device_lock:
1371 * @device: a #GstD3D11Device
1373 * Take lock for @device. Any thread-unsafe API call needs to be
1374 * protected by this method. This call must be paired with
1375 * gst_d3d11_device_unlock()
1380 gst_d3d11_device_lock (GstD3D11Device * device)
1382 GstD3D11DevicePrivate *priv;
1384 g_return_if_fail (GST_IS_D3D11_DEVICE (device));
1386 priv = device->priv;
1388 GST_TRACE_OBJECT (device, "device locking");
1389 g_rec_mutex_lock (&priv->extern_lock);
1390 GST_TRACE_OBJECT (device, "device locked");
1394 * gst_d3d11_device_unlock:
1395 * @device: a #GstD3D11Device
1397 * Release lock for @device. This call must be paired with
1398 * gst_d3d11_device_lock()
1403 gst_d3d11_device_unlock (GstD3D11Device * device)
1405 GstD3D11DevicePrivate *priv;
1407 g_return_if_fail (GST_IS_D3D11_DEVICE (device));
1409 priv = device->priv;
1411 g_rec_mutex_unlock (&priv->extern_lock);
1412 GST_TRACE_OBJECT (device, "device unlocked");
1416 * gst_d3d11_device_format_from_gst:
1417 * @device: a #GstD3D11Device
1418 * @format: a #GstVideoFormat
1420 * Returns: (transfer none) (nullable): a pointer to #GstD3D11Format
1421 * or %NULL if @format is not supported by @device
1425 const GstD3D11Format *
1426 gst_d3d11_device_format_from_gst (GstD3D11Device * device,
1427 GstVideoFormat format)
1429 GstD3D11DevicePrivate *priv;
1432 g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL);
1434 priv = device->priv;
1436 for (i = 0; i < G_N_ELEMENTS (priv->format_table); i++) {
1437 if (priv->format_table[i].format == format)
1438 return &priv->format_table[i];