#include <va/va_drm.h>
#include <gudev/gudev.h>
#include <gst/va/gstvadisplay_drm.h>
+#else
+#include <gst/d3d11/gstd3d11.h>
#endif
GST_DEBUG_CATEGORY_STATIC (gst_debug_msdkcontext);
GstMsdkContext *parent_context;
#ifndef _WIN32
GstVaDisplay *display;
+#else
+ GstD3D11Device *device;
#endif
};
return FALSE;
}
+#else
+static GstD3D11Device *
+get_device_by_index (IDXGIFactory1 * factory, guint idx)
+{
+ HRESULT hr;
+ IDXGIAdapter1 *adapter;
+ ID3D11Device *device_handle;
+ ID3D10Multithread *multi_thread;
+ DXGI_ADAPTER_DESC desc;
+ GstD3D11Device *device = NULL;
+ gint64 luid;
+
+ hr = IDXGIFactory1_EnumAdapters1 (factory, idx, &adapter);
+ if (FAILED (hr)) {
+ return NULL;
+ }
+
+ hr = IDXGIAdapter1_GetDesc (adapter, &desc);
+ if (FAILED (hr)) {
+ IDXGIAdapter1_Release (adapter);
+ return NULL;
+ }
+
+ if (desc.VendorId != 0x8086) {
+ IDXGIAdapter1_Release (adapter);
+ return NULL;
+ }
+
+ luid = gst_d3d11_luid_to_int64 (&desc.AdapterLuid);
+ device = gst_d3d11_device_new_for_adapter_luid (luid,
+ D3D11_CREATE_DEVICE_BGRA_SUPPORT);
+ IDXGIAdapter1_Release (adapter);
+
+ device_handle = gst_d3d11_device_get_device_handle (device);
+ hr = ID3D11Device_QueryInterface (device_handle,
+ &IID_ID3D10Multithread, (void **) &multi_thread);
+ if (FAILED (hr)) {
+ gst_object_unref (device);
+ return NULL;
+ }
+
+ hr = ID3D10Multithread_SetMultithreadProtected (multi_thread, TRUE);
+ ID3D10Multithread_Release (multi_thread);
+
+ return device;
+}
+
+static gboolean
+gst_msdk_context_use_d3d11 (GstMsdkContext * context)
+{
+ HRESULT hr;
+ IDXGIFactory1 *factory = NULL;
+ GstD3D11Device *device = NULL;
+ ID3D11Device *device_handle;
+ GstMsdkContextPrivate *priv = context->priv;
+ mfxStatus status;
+ guint idx = 0;
+ gint user_idx = -1;
+ const gchar *user_choice = g_getenv ("GST_MSDK_DEVICE");
+
+ hr = CreateDXGIFactory1 (&IID_IDXGIFactory1, (void **) &factory);
+ if (FAILED (hr)) {
+ GST_ERROR ("Couldn't create DXGI factory");
+ return FALSE;
+ }
+
+ if (user_choice) {
+ user_idx = atoi (user_choice);
+ if (!(device = get_device_by_index (factory, user_idx)))
+ GST_WARNING
+ ("Failed to get device by user index, try to pick the first available device");
+ }
+
+ /* Pick the first available device */
+ while (!device) {
+ device = get_device_by_index (factory, idx++);
+ }
+
+ IDXGIFactory1_Release (factory);
+ device_handle = gst_d3d11_device_get_device_handle (device);
+
+ status =
+ MFXVideoCORE_SetHandle (priv->session.session, MFX_HANDLE_D3D11_DEVICE,
+ gst_d3d11_device_get_device_handle (device));
+ if (status != MFX_ERR_NONE) {
+ GST_ERROR ("Setting D3D11VA handle failed (%s)",
+ msdk_status_to_string (status));
+ gst_object_unref (device);
+ return FALSE;
+ }
+
+ priv->device = device;
+
+ return TRUE;
+}
#endif
static gboolean
mfxU16 codename;
GstMsdkContextPrivate *priv = context->priv;
MsdkSession msdk_session;
+ mfxIMPL impl;
priv->job_type = job_type;
priv->hardware = hardware;
- msdk_session =
- msdk_open_session (hardware ? MFX_IMPL_HARDWARE_ANY : MFX_IMPL_SOFTWARE);
+ impl = hardware ? MFX_IMPL_HARDWARE_ANY : MFX_IMPL_SOFTWARE;
+
+#ifdef _WIN32
+ impl |= MFX_IMPL_VIA_D3D11;
+#endif
+
+ msdk_session = msdk_open_session (impl);
priv->session = msdk_session;
if (!priv->session.session)
goto failed;
if (!gst_msdk_context_use_vaapi (context))
goto failed;
}
+#else
+ if (hardware) {
+ if (!gst_msdk_context_use_d3d11 (context))
+ goto failed;
+ }
#endif
codename = msdk_get_platform_codename (priv->session.session);
#ifndef _WIN32
if (priv->display)
gst_object_unref (priv->display);
+#else
+ if (priv->device)
+ gst_object_unref (priv->device);
#endif
done:
if (MFX_IMPL_VIA_VAAPI == (0x0f00 & (impl)))
handle_type = MFX_HANDLE_VA_DISPLAY;
+ else if (MFX_IMPL_VIA_D3D11 == (0x0f00 & (impl)))
+ handle_type = MFX_HANDLE_D3D11_DEVICE;
if (handle_type) {
status =
g_list_prepend (parent_priv->child_session_list, priv->session.session);
#ifndef _WIN32
priv->display = parent_priv->display;
+#else
+ priv->device = parent_priv->device;
#endif
priv->parent_context = gst_object_ref (parent);
return obj;
}
+#ifndef _WIN32
GstMsdkContext *
gst_msdk_context_new_with_va_display (GstObject * display_obj,
gboolean hardware, GstMsdkContextJobType job_type)
{
GstMsdkContext *obj = NULL;
-#ifndef _WIN32
GstMsdkContextPrivate *priv;
mfxU16 codename;
mfxStatus status;
else
GST_WARNING ("Unknown MFX platform");
-#endif
+ return obj;
+}
+#else
+GstMsdkContext *
+gst_msdk_context_new_with_d3d11_device (GstD3D11Device * device,
+ gboolean hardware, GstMsdkContextJobType job_type)
+{
+ GstMsdkContext *obj = NULL;
+ GstMsdkContextPrivate *priv;
+ mfxU16 codename;
+ mfxStatus status;
+ ID3D10Multithread *multi_thread;
+ ID3D11Device *device_handle;
+ HRESULT hr;
+
+ obj = g_object_new (GST_TYPE_MSDK_CONTEXT, NULL);
+
+ priv = obj->priv;
+ priv->device = gst_object_ref (device);
+
+ priv->job_type = job_type;
+ priv->hardware = hardware;
+ priv->session =
+ msdk_open_session (hardware ? MFX_IMPL_HARDWARE_ANY : MFX_IMPL_SOFTWARE);
+ if (!priv->session.session) {
+ goto failed;
+ }
+
+ device_handle = gst_d3d11_device_get_device_handle (device);
+ hr = ID3D11Device_QueryInterface (device_handle,
+ &IID_ID3D10Multithread, (void **) &multi_thread);
+ if (FAILED (hr)) {
+ GST_ERROR ("ID3D10Multithread interface is unavailable");
+ goto failed;
+ }
+
+ hr = ID3D10Multithread_SetMultithreadProtected (multi_thread, TRUE);
+ ID3D10Multithread_Release (multi_thread);
+
+ if (hardware) {
+ status =
+ MFXVideoCORE_SetHandle (priv->session.session, MFX_HANDLE_D3D11_DEVICE,
+ device_handle);
+ if (status != MFX_ERR_NONE) {
+ GST_ERROR ("Setting D3D11VA handle failed (%s)",
+ msdk_status_to_string (status));
+ goto failed;
+ }
+ }
+
+ codename = msdk_get_platform_codename (priv->session.session);
+
+ if (codename != MFX_PLATFORM_UNKNOWN)
+ GST_INFO ("Detected MFX platform with device code %d", codename);
+ else
+ GST_WARNING ("Unknown MFX platform");
return obj;
+
+failed:
+ gst_object_unref (obj);
+ gst_object_unref (device);
+ return NULL;
}
+#endif
mfxSession
gst_msdk_context_get_session (GstMsdkContext * context)
#endif
}
+#ifndef _WIN32
GstObject *
-gst_msdk_context_get_display (GstMsdkContext * context)
+gst_msdk_context_get_va_display (GstMsdkContext * context)
{
-#ifndef _WIN32
if (context->priv->display)
return gst_object_ref (GST_OBJECT_CAST (context->priv->display));
-#endif
return NULL;
}
+#else
+GstD3D11Device *
+gst_msdk_context_get_d3d11_device (GstMsdkContext * context)
+{
+ if (context->priv->device)
+ return gst_object_ref (context->priv->device);
+ return NULL;
+}
+#endif
static gint
_find_response (gconstpointer resp, gconstpointer comp_resp)
#ifndef _WIN32
#include <va/va.h>
#include <va/va_drmcommon.h>
+#else
+#include <gst/d3d11/gstd3d11_fwd.h>
#endif
G_BEGIN_DECLS
GstMsdkContext * gst_msdk_context_new (gboolean hardware, GstMsdkContextJobType job_type);
GstMsdkContext * gst_msdk_context_new_with_parent (GstMsdkContext * parent);
+#ifndef _WIN32
GstMsdkContext * gst_msdk_context_new_with_va_display (GstObject * display_obj,
gboolean hardware, GstMsdkContextJobType job_type);
+#else
+GstMsdkContext * gst_msdk_context_new_with_d3d11_device (GstD3D11Device * device,
+ gboolean hardware, GstMsdkContextJobType job_type);
+#endif
mfxSession gst_msdk_context_get_session (GstMsdkContext * context);
gpointer gst_msdk_context_get_handle (GstMsdkContext * context);
-GstObject * gst_msdk_context_get_display (GstMsdkContext * context);
+#ifndef _WIN32
+GstObject * gst_msdk_context_get_va_display (GstMsdkContext * context);
+#else
+GstD3D11Device * gst_msdk_context_get_d3d11_device (GstMsdkContext * context);
+#endif
/* GstMsdkContext contains mfxFrameAllocResponses,
* if app calls MFXVideoCORE_SetFrameAllocator.
#ifndef _WIN32
#include <gst/va/gstvadisplay.h>
#include <gst/va/gstvautils.h>
+#else
+#include <gst/d3d11/gstd3d11device.h>
#endif
GST_DEBUG_CATEGORY_STATIC (GST_CAT_CONTEXT);
#ifndef _WIN32
/* 2) Query the neighbour the VA display. If already a valid VA display,
- using it by gst_msdk_context_from_external_display() in set_context(). */
+ using it by gst_msdk_context_from_external_va_display() in set_context(). */
gst_va_context_query (element, GST_VA_DISPLAY_HANDLE_CONTEXT_TYPE_STR);
msdk_context = g_atomic_pointer_get (context_ptr);
if (msdk_context) {
ret = TRUE;
goto done;
}
+#else
+ /* 2) Query the neighbour the D3D11 device. If already a valid D3D11 device,
+ using it by gst_msdk_context_from_external_d3d11_device() in set_context(). */
+ _context_query (element, GST_D3D11_DEVICE_HANDLE_CONTEXT_TYPE);
+ msdk_context = g_atomic_pointer_get (context_ptr);
+ if (msdk_context) {
+ gst_object_ref (msdk_context);
+ propagate_display = FALSE;
+ ret = TRUE;
+ goto done;
+ }
#endif
- /* 3) Create a MSDK context from scratch. */
+ /* 3) Create a MSDK context from scratch. Currently we use environment variable
+ to enable user to choose GPU device in multi-GPU environment. This variable
+ is only valid when there's no context returned by upstream or downstream.
+ Otherwise it will use the device that created by upstream or downstream. */
msdk_context = gst_msdk_context_new (hardware, job);
if (!msdk_context) {
GST_ERROR_OBJECT (element, "Context creation failed");
if (propagate_display) {
#ifndef _WIN32
GstVaDisplay *display =
- (GstVaDisplay *) gst_msdk_context_get_display (msdk_context);
+ (GstVaDisplay *) gst_msdk_context_get_va_display (msdk_context);
gst_va_element_propagate_display_context (element, display);
gst_clear_object (&display);
#endif
return ret;
}
+#ifndef _WIN32
gboolean
-gst_msdk_context_from_external_display (GstContext * context, gboolean hardware,
- GstMsdkContextJobType job_type, GstMsdkContext ** msdk_context)
+gst_msdk_context_from_external_va_display (GstContext * context,
+ gboolean hardware, GstMsdkContextJobType job_type,
+ GstMsdkContext ** msdk_context)
{
-#ifndef _WIN32
GstObject *va_display = NULL;
const gchar *type;
const GstStructure *s;
if (ctx)
return TRUE;
-#endif
+ return FALSE;
+}
+#else
+gboolean
+gst_msdk_context_from_external_d3d11_device (GstContext * context,
+ gboolean hardware, GstMsdkContextJobType job_type,
+ GstMsdkContext ** msdk_context)
+{
+ GstD3D11Device *d3d11_device = NULL;
+ const gchar *type;
+ const GstStructure *s;
+ GstMsdkContext *ctx = NULL;
+ guint vendor_id = 0;
+
+ _init_context_debug ();
+
+ type = gst_context_get_context_type (context);
+ if (g_strcmp0 (type, GST_D3D11_DEVICE_HANDLE_CONTEXT_TYPE))
+ return FALSE;
+
+ s = gst_context_get_structure (context);
+ if (gst_structure_get (s, "device", GST_TYPE_D3D11_DEVICE, &d3d11_device,
+ NULL)) {
+ g_object_get (d3d11_device, "vendor-id", &vendor_id, NULL);
+ if (vendor_id != 0x8086) {
+ GST_ERROR ("Not an Intel device");
+ gst_clear_object (&d3d11_device);
+ return FALSE;
+ }
+ ctx =
+ gst_msdk_context_new_with_d3d11_device (d3d11_device, hardware,
+ job_type);
+ if (ctx)
+ *msdk_context = ctx;
+
+ gst_clear_object (&d3d11_device);
+ }
+
+ if (ctx)
+ return TRUE;
return FALSE;
}
+#endif
gboolean
gst_msdk_handle_context_query (GstElement * element, GstQuery * query,
#ifndef _WIN32
if (g_strcmp0 (context_type, GST_VA_DISPLAY_HANDLE_CONTEXT_TYPE_STR) == 0) {
GstStructure *s;
- GstObject *display = gst_msdk_context_get_display (msdk_context);
+ GstObject *display = gst_msdk_context_get_va_display (msdk_context);
if (display) {
GST_CAT_LOG (GST_CAT_CONTEXT,
ret = TRUE;
}
} else
+#else
+ if (g_strcmp0 (context_type, GST_D3D11_DEVICE_HANDLE_CONTEXT_TYPE) == 0) {
+ GstStructure *s;
+ GstD3D11Device *device = gst_msdk_context_get_d3d11_device (msdk_context);
+
+ if (device) {
+ GST_CAT_LOG (GST_CAT_CONTEXT,
+ "setting GstD3D11Device (%" GST_PTR_FORMAT ") on context (%"
+ GST_PTR_FORMAT ")", device, ctxt);
+
+ s = gst_context_writable_structure (ctxt);
+ gst_structure_set (s, "device", GST_TYPE_D3D11_DEVICE, device, NULL);
+ gst_object_unref (device);
+ ret = TRUE;
+ }
+ } else
#endif
if (g_strcmp0 (context_type, GST_MSDK_CONTEXT_TYPE_NAME) == 0) {
GstStructure *s;
gboolean
gst_msdk_context_get_context (GstContext * context, GstMsdkContext ** msdk_context);
+#ifndef _WIN32
+gboolean
+gst_msdk_context_from_external_va_display (GstContext * context, gboolean hardware,
+ GstMsdkContextJobType job_type, GstMsdkContext ** msdk_context);
+#else
gboolean
-gst_msdk_context_from_external_display (GstContext * context, gboolean hardware,
+gst_msdk_context_from_external_d3d11_device (GstContext * context, gboolean hardware,
GstMsdkContextJobType job_type, GstMsdkContext ** msdk_context);
+#endif
gboolean
gst_msdk_handle_context_query (GstElement * element, GstQuery * query, GstMsdkContext * msdk_context);
gst_object_replace ((GstObject **) & thiz->context,
(GstObject *) msdk_context);
gst_object_unref (msdk_context);
- } else if (gst_msdk_context_from_external_display (context,
+ } else
+#ifndef _WIN32
+ if (gst_msdk_context_from_external_va_display (context,
thiz->hardware, 0 /* GST_MSDK_JOB_DECODER will be set later */ ,
&msdk_context)) {
gst_object_replace ((GstObject **) & thiz->context,
(GstObject *) msdk_context);
gst_object_unref (msdk_context);
}
+#else
+ if (gst_msdk_context_from_external_d3d11_device (context,
+ thiz->hardware, 0 /* GST_MSDK_JOB_DECODER will be set later */ ,
+ &msdk_context)) {
+ gst_object_replace ((GstObject **) & thiz->context,
+ (GstObject *) msdk_context);
+ gst_object_unref (msdk_context);
+ }
+#endif
GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
}
gst_object_replace ((GstObject **) & thiz->context,
(GstObject *) msdk_context);
gst_object_unref (msdk_context);
- } else if (gst_msdk_context_from_external_display (context,
+ } else
+#ifndef _WIN32
+ if (gst_msdk_context_from_external_va_display (context,
thiz->hardware, 0 /* GST_MSDK_JOB_ENCODER will be set later */ ,
&msdk_context)) {
gst_object_replace ((GstObject **) & thiz->context,
(GstObject *) msdk_context);
gst_object_unref (msdk_context);
}
+#else
+ if (gst_msdk_context_from_external_d3d11_device (context,
+ thiz->hardware, 0 /* GST_MSDK_JOB_ENCODER will be set later */ ,
+ &msdk_context)) {
+ gst_object_replace ((GstObject **) & thiz->context,
+ (GstObject *) msdk_context);
+ gst_object_unref (msdk_context);
+ }
+#endif
GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
}
GstVaDisplay *display = NULL;
GstVideoInfo info = thiz->input_state->info;
- display = (GstVaDisplay *) gst_msdk_context_get_display (thiz->context);
+ display = (GstVaDisplay *) gst_msdk_context_get_va_display (thiz->context);
if (thiz->use_dmabuf) {
allocator = gst_va_dmabuf_allocator_new (display);
GstVaDisplay *display = NULL;
GstCaps *aligned_caps = NULL;
- display = (GstVaDisplay *) gst_msdk_context_get_display (msdk_context);
+ display = (GstVaDisplay *) gst_msdk_context_get_va_display (msdk_context);
if (use_dmabuf)
allocator = gst_va_dmabuf_allocator_new (display);
gst_object_replace ((GstObject **) & thiz->context,
(GstObject *) msdk_context);
gst_object_unref (msdk_context);
- } else if (gst_msdk_context_from_external_display (context,
+ } else
+#ifndef _WIN32
+ if (gst_msdk_context_from_external_va_display (context,
thiz->hardware, 0 /* GST_MSDK_JOB_VPP will be set later */ ,
&msdk_context)) {
gst_object_replace ((GstObject **) & thiz->context,
(GstObject *) msdk_context);
gst_object_unref (msdk_context);
}
+#else
+ if (gst_msdk_context_from_external_d3d11_device (context,
+ thiz->hardware, 0 /* GST_MSDK_JOB_VPP will be set later */ ,
+ &msdk_context)) {
+ gst_object_replace ((GstObject **) & thiz->context,
+ (GstObject *) msdk_context);
+ gst_object_unref (msdk_context);
+ }
+#endif
GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
}