diff --git a/subprojects/gst-plugins-bad/sys/qsv/gstqsvallocator_d3d11.cpp b/subprojects/gst-plugins-bad/sys/qsv/gstqsvallocator_d3d11.cpp index b4b0b19990..83ecc96dc9 100644 --- a/subprojects/gst-plugins-bad/sys/qsv/gstqsvallocator_d3d11.cpp +++ b/subprojects/gst-plugins-bad/sys/qsv/gstqsvallocator_d3d11.cpp @@ -25,6 +25,10 @@ #include #include +#ifdef HAVE_GST_D3D12 +#include +#endif + /* *INDENT-OFF* */ using namespace Microsoft::WRL; /* *INDENT-ON* */ @@ -38,6 +42,7 @@ struct _GstQsvD3D11Allocator GstD3D11Device *device; GstD3D11Fence *fence; + gboolean d3d12_import_allowed; }; #define gst_qsv_d3d11_allocator_parent_class parent_class @@ -438,6 +443,7 @@ static GstBuffer * gst_qsv_d3d11_allocator_upload (GstQsvAllocator * allocator, const GstVideoInfo * info, GstBuffer * buffer, GstBufferPool * pool) { + auto self = GST_QSV_D3D11_ALLOCATOR (allocator); GstMemory *mem; GstD3D11Memory *dmem; D3D11_TEXTURE2D_DESC desc; @@ -455,19 +461,48 @@ gst_qsv_d3d11_allocator_upload (GstQsvAllocator * allocator, */ if (!GST_IS_D3D11_BUFFER_POOL (pool)) { - GST_ERROR_OBJECT (allocator, "Not a d3d11 buffer pool"); + GST_ERROR_OBJECT (self, "Not a d3d11 buffer pool"); return nullptr; } flow_ret = gst_buffer_pool_acquire_buffer (pool, &dst_buf, nullptr); if (flow_ret != GST_FLOW_OK) { - GST_WARNING_OBJECT (allocator, + GST_WARNING_OBJECT (self, "Failed to acquire buffer from pool, return %s", gst_flow_get_name (flow_ret)); return nullptr; } mem = gst_buffer_peek_memory (buffer, 0); + +#ifdef HAVE_GST_D3D12 + if (self->d3d12_import_allowed && gst_is_d3d12_memory (mem)) { + auto dmem = GST_D3D12_MEMORY_CAST (mem); + gint64 luid, other_luid; + auto device11 = GST_D3D11_BUFFER_POOL (pool)->device; + g_object_get (dmem->device, "adapter-luid", &luid, nullptr); + g_object_get (device11, "adapter-luid", &other_luid, nullptr); + if (luid == other_luid) { + auto device_handle = gst_d3d11_device_get_device_handle (device11); + auto texture = gst_d3d12_memory_get_d3d11_texture (dmem, device_handle); + if (texture) { + gst_d3d12_memory_sync (dmem); + auto wrapped = gst_d3d11_allocator_alloc_wrapped (nullptr, + device11, texture, 1, nullptr, nullptr); + if (wrapped) { + GST_TRACE_OBJECT (allocator, "Importing D3D12 resource"); + + auto wrapped_buf = gst_buffer_new (); + gst_buffer_append_memory (wrapped_buf, wrapped); + gst_buffer_add_parent_buffer_meta (wrapped_buf, buffer); + gst_buffer_unref (dst_buf); + return wrapped_buf; + } + } + } + } +#endif + if (!gst_is_d3d11_memory (mem) || gst_buffer_n_memory (buffer) > 1) { /* d3d11 buffer should hold single memory object */ return gst_qsv_frame_upload_sysmem (info, buffer, dst_buf); @@ -491,14 +526,13 @@ gst_qsv_d3d11_allocator_upload (GstQsvAllocator * allocator, gst_d3d11_memory_get_texture_desc (dmem, &desc); if (desc.Usage == D3D11_USAGE_DEFAULT && !shared_copy) { - GST_TRACE_OBJECT (allocator, "Wrapping D3D11 buffer without copy"); + GST_TRACE_OBJECT (self, "Wrapping D3D11 buffer without copy"); gst_buffer_unref (dst_buf); return gst_buffer_ref (buffer); } - return gst_qsv_frame_copy_d3d11 (GST_QSV_D3D11_ALLOCATOR (allocator), info, - buffer, dst_buf, shared_copy); + return gst_qsv_frame_copy_d3d11 (self, info, buffer, dst_buf, shared_copy); } static GstBuffer * @@ -571,3 +605,11 @@ gst_qsv_d3d11_allocator_new (GstD3D11Device * device) return GST_QSV_ALLOCATOR (self); } + +void +gst_qsv_d3d11_allocator_set_d3d12_import_allowed (GstQsvAllocator * allocator, + gboolean allowed) +{ + auto self = GST_QSV_D3D11_ALLOCATOR (allocator); + self->d3d12_import_allowed = allowed; +} diff --git a/subprojects/gst-plugins-bad/sys/qsv/gstqsvallocator_d3d11.h b/subprojects/gst-plugins-bad/sys/qsv/gstqsvallocator_d3d11.h index 94b242fb46..a890e720e3 100644 --- a/subprojects/gst-plugins-bad/sys/qsv/gstqsvallocator_d3d11.h +++ b/subprojects/gst-plugins-bad/sys/qsv/gstqsvallocator_d3d11.h @@ -31,4 +31,7 @@ G_DECLARE_FINAL_TYPE (GstQsvD3D11Allocator, gst_qsv_d3d11_allocator, GstQsvAllocator * gst_qsv_d3d11_allocator_new (GstD3D11Device * device); +void gst_qsv_d3d11_allocator_set_d3d12_import_allowed (GstQsvAllocator * allocator, + gboolean allowed); + G_END_DECLS diff --git a/subprojects/gst-plugins-bad/sys/qsv/gstqsvav1enc.cpp b/subprojects/gst-plugins-bad/sys/qsv/gstqsvav1enc.cpp index 833e2694e4..4adb2dc9a4 100644 --- a/subprojects/gst-plugins-bad/sys/qsv/gstqsvav1enc.cpp +++ b/subprojects/gst-plugins-bad/sys/qsv/gstqsvav1enc.cpp @@ -46,6 +46,10 @@ #include #endif +#ifdef HAVE_GST_D3D12 +#include +#endif + GST_DEBUG_CATEGORY_STATIC (gst_qsv_av1_enc_debug); #define GST_CAT_DEFAULT gst_qsv_av1_enc_debug @@ -116,6 +120,7 @@ enum #define DOC_SINK_CAPS \ "video/x-raw(memory:D3D11Memory), " DOC_SINK_CAPS_COMM "; " \ + "video/x-raw(memory:D3D12Memory), " DOC_SINK_CAPS_COMM "; " \ "video/x-raw(memory:VAMemory), " DOC_SINK_CAPS_COMM "; " \ "video/x-raw, " DOC_SINK_CAPS_COMM @@ -131,6 +136,7 @@ typedef struct _GstQsvAV1EncClassData gint64 adapter_luid; gchar *display_path; gchar *description; + gboolean d3d12_interop; } GstQsvAV1EncClassData; typedef struct _GstQsvAV1Enc @@ -195,6 +201,7 @@ gst_qsv_av1_enc_class_init (GstQsvAV1EncClass * klass, gpointer data) qsvenc_class->impl_index = cdata->impl_index; qsvenc_class->adapter_luid = cdata->adapter_luid; qsvenc_class->display_path = cdata->display_path; + qsvenc_class->d3d12_interop = cdata->d3d12_interop; object_class->finalize = gst_qsv_av1_enc_finalize; object_class->set_property = gst_qsv_av1_enc_set_property; @@ -619,7 +626,7 @@ done: void gst_qsv_av1_enc_register (GstPlugin * plugin, guint rank, guint impl_index, - GstObject * device, mfxSession session) + GstObject * device, mfxSession session, gboolean d3d12_interop) { mfxVideoParam param; mfxInfoMFX *mfx; @@ -743,6 +750,13 @@ gst_qsv_av1_enc_register (GstPlugin * plugin, guint rank, guint impl_index, GstCapsFeatures *caps_features = gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, nullptr); gst_caps_set_features_simple (d3d11_caps, caps_features); +#ifdef HAVE_GST_D3D12 + auto d3d12_caps = gst_caps_copy (sink_caps); + auto d3d12_feature = + gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_D3D12_MEMORY, nullptr); + gst_caps_set_features_simple (d3d12_caps, d3d12_feature); + gst_caps_append (d3d11_caps, d3d12_caps); +#endif gst_caps_append (d3d11_caps, sink_caps); sink_caps = d3d11_caps; #else @@ -768,6 +782,7 @@ gst_qsv_av1_enc_register (GstPlugin * plugin, guint rank, guint impl_index, cdata->sink_caps = sink_caps; cdata->src_caps = src_caps; cdata->impl_index = impl_index; + cdata->d3d12_interop = d3d12_interop; #ifdef G_OS_WIN32 g_object_get (device, "adapter-luid", &cdata->adapter_luid, diff --git a/subprojects/gst-plugins-bad/sys/qsv/gstqsvav1enc.h b/subprojects/gst-plugins-bad/sys/qsv/gstqsvav1enc.h index a445b8b48f..67197251a3 100644 --- a/subprojects/gst-plugins-bad/sys/qsv/gstqsvav1enc.h +++ b/subprojects/gst-plugins-bad/sys/qsv/gstqsvav1enc.h @@ -29,6 +29,7 @@ void gst_qsv_av1_enc_register (GstPlugin * plugin, guint rank, guint impl_index, GstObject * device, - mfxSession session); + mfxSession session, + gboolean d3d12_interop); G_END_DECLS diff --git a/subprojects/gst-plugins-bad/sys/qsv/gstqsvencoder.cpp b/subprojects/gst-plugins-bad/sys/qsv/gstqsvencoder.cpp index c33805e8d2..0020911e28 100644 --- a/subprojects/gst-plugins-bad/sys/qsv/gstqsvencoder.cpp +++ b/subprojects/gst-plugins-bad/sys/qsv/gstqsvencoder.cpp @@ -38,6 +38,10 @@ using namespace Microsoft::WRL; #include "gstqsvallocator_va.h" #endif /* G_OS_WIN32 */ +#ifdef HAVE_GST_D3D12 +#include +#endif + GST_DEBUG_CATEGORY_STATIC (gst_qsv_encoder_debug); #define GST_CAT_DEFAULT gst_qsv_encoder_debug @@ -115,6 +119,7 @@ typedef struct _GstQsvEncoderTask struct _GstQsvEncoderPrivate { GstObject *device; + GstObject *device12; GstVideoCodecState *input_state; GstQsvAllocator *allocator; @@ -282,6 +287,7 @@ gst_qsv_encoder_dispose (GObject * object) GstQsvEncoderPrivate *priv = self->priv; gst_clear_object (&priv->device); + gst_clear_object (&priv->device12); G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -384,6 +390,8 @@ gst_qsv_encoder_open_platform_device (GstQsvEncoder * self) device = GST_D3D11_DEVICE_CAST (priv->device); priv->allocator = gst_qsv_d3d11_allocator_new (device); + gst_qsv_d3d11_allocator_set_d3d12_import_allowed (priv->allocator, + klass->d3d12_interop); /* For D3D11 device handle to be used by QSV, multithread protection layer * must be enabled before the MFXVideoCORE_SetHandle() call. @@ -1474,12 +1482,16 @@ gst_qsv_encoder_propose_allocation (GstVideoEncoder * encoder, GstQuery * query) GstQsvEncoderPrivate *priv = self->priv; GstD3D11Device *device = GST_D3D11_DEVICE (priv->device); GstVideoInfo info; - GstBufferPool *pool; + GstBufferPool *pool = nullptr; GstCaps *caps; guint size; GstStructure *config; GstCapsFeatures *features; gboolean is_d3d11 = FALSE; +#ifdef HAVE_GST_D3D12 + GstQsvEncoderClass *klass = GST_QSV_ENCODER_GET_CLASS (self); + gboolean is_d3d12 = FALSE; +#endif gst_query_parse_allocation (query, &caps, nullptr); if (!caps) { @@ -1493,14 +1505,25 @@ gst_qsv_encoder_propose_allocation (GstVideoEncoder * encoder, GstQuery * query) } features = gst_caps_get_features (caps, 0); - if (features && gst_caps_features_contains (features, + if (gst_caps_features_contains (features, GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY)) { GST_DEBUG_OBJECT (self, "upstream support d3d11 memory"); pool = gst_d3d11_buffer_pool_new (device); is_d3d11 = TRUE; - } else { - pool = gst_video_buffer_pool_new (); } +#ifdef HAVE_GST_D3D12 + else if (gst_caps_features_contains (features, + GST_CAPS_FEATURE_MEMORY_D3D12_MEMORY) && + gst_d3d12_ensure_element_data_for_adapter_luid (GST_ELEMENT (self), + klass->adapter_luid, (GstD3D12Device **) & priv->device12)) { + GST_DEBUG_OBJECT (self, "upstream support d3d12 memory"); + pool = gst_d3d12_buffer_pool_new ((GstD3D12Device *) priv->device12); + is_d3d12 = TRUE; + } +#endif + + if (!pool) + pool = gst_video_buffer_pool_new (); config = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META); @@ -1525,7 +1548,28 @@ gst_qsv_encoder_propose_allocation (GstVideoEncoder * encoder, GstQuery * query) gst_d3d11_allocation_params_alignment (d3d11_params, &align); gst_buffer_pool_config_set_d3d11_allocation_params (config, d3d11_params); gst_d3d11_allocation_params_free (d3d11_params); - } else { + } +#ifdef HAVE_GST_D3D12 + else if (is_d3d12) { + GstVideoAlignment align; + gst_video_alignment_reset (&align); + auto device12 = GST_D3D12_DEVICE (priv->device12); + + align.padding_right = GST_VIDEO_INFO_WIDTH (&priv->aligned_info) - + GST_VIDEO_INFO_WIDTH (&info); + align.padding_bottom = GST_VIDEO_INFO_HEIGHT (&priv->aligned_info) - + GST_VIDEO_INFO_HEIGHT (&info); + + auto params = gst_d3d12_allocation_params_new (device12, &info, + GST_D3D12_ALLOCATION_FLAG_DEFAULT, + D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS | + D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET, D3D12_HEAP_FLAG_SHARED); + gst_d3d12_allocation_params_alignment (params, &align); + gst_buffer_pool_config_set_d3d12_allocation_params (config, params); + gst_d3d12_allocation_params_free (params); + } +#endif + else { gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT); } diff --git a/subprojects/gst-plugins-bad/sys/qsv/gstqsvencoder.h b/subprojects/gst-plugins-bad/sys/qsv/gstqsvencoder.h index 079db648ec..3d12a7e3db 100644 --- a/subprojects/gst-plugins-bad/sys/qsv/gstqsvencoder.h +++ b/subprojects/gst-plugins-bad/sys/qsv/gstqsvencoder.h @@ -68,6 +68,8 @@ struct _GstQsvEncoderClass /* VA display device path, for Linux */ gchar *display_path; + gboolean d3d12_interop; + gboolean (*set_format) (GstQsvEncoder * encoder, GstVideoCodecState * state, mfxVideoParam * param, diff --git a/subprojects/gst-plugins-bad/sys/qsv/gstqsvh264enc.cpp b/subprojects/gst-plugins-bad/sys/qsv/gstqsvh264enc.cpp index 7f558ff25b..065a668b0e 100644 --- a/subprojects/gst-plugins-bad/sys/qsv/gstqsvh264enc.cpp +++ b/subprojects/gst-plugins-bad/sys/qsv/gstqsvh264enc.cpp @@ -49,6 +49,10 @@ #include #endif +#ifdef HAVE_GST_D3D12 +#include +#endif + GST_DEBUG_CATEGORY_STATIC (gst_qsv_h264_enc_debug); #define GST_CAT_DEFAULT gst_qsv_h264_enc_debug @@ -368,6 +372,7 @@ enum #define DOC_SINK_CAPS \ "video/x-raw(memory:D3D11Memory), " DOC_SINK_CAPS_COMM "; " \ + "video/x-raw(memory:D3D12Memory), " DOC_SINK_CAPS_COMM "; " \ "video/x-raw(memory:VAMemory), " DOC_SINK_CAPS_COMM "; " \ "video/x-raw, " DOC_SINK_CAPS_COMM @@ -385,6 +390,7 @@ typedef struct _GstQsvH264EncClassData gint64 adapter_luid; gchar *display_path; gchar *description; + gboolean d3d12_interop; } GstQsvH264EncClassData; typedef struct _GstQsvH264Enc @@ -494,6 +500,7 @@ gst_qsv_h264_enc_class_init (GstQsvH264EncClass * klass, gpointer data) qsvenc_class->impl_index = cdata->impl_index; qsvenc_class->adapter_luid = cdata->adapter_luid; qsvenc_class->display_path = cdata->display_path; + qsvenc_class->d3d12_interop = cdata->d3d12_interop; object_class->finalize = gst_qsv_h264_enc_finalize; object_class->set_property = gst_qsv_h264_enc_set_property; @@ -2111,7 +2118,7 @@ done: void gst_qsv_h264_enc_register (GstPlugin * plugin, guint rank, guint impl_index, - GstObject * device, mfxSession session) + GstObject * device, mfxSession session, gboolean d3d12_interop) { mfxStatus status; mfxVideoParam param; @@ -2233,6 +2240,13 @@ gst_qsv_h264_enc_register (GstPlugin * plugin, guint rank, guint impl_index, GstCapsFeatures *caps_features = gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, nullptr); gst_caps_set_features_simple (d3d11_caps, caps_features); +#ifdef HAVE_GST_D3D12 + auto d3d12_caps = gst_caps_copy (sink_caps); + auto d3d12_feature = + gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_D3D12_MEMORY, nullptr); + gst_caps_set_features_simple (d3d12_caps, d3d12_feature); + gst_caps_append (d3d11_caps, d3d12_caps); +#endif gst_caps_append (d3d11_caps, sink_caps); sink_caps = d3d11_caps; #else @@ -2278,6 +2292,7 @@ gst_qsv_h264_enc_register (GstPlugin * plugin, guint rank, guint impl_index, cdata->sink_caps = sink_caps; cdata->src_caps = src_caps; cdata->impl_index = impl_index; + cdata->d3d12_interop = d3d12_interop; #ifdef G_OS_WIN32 g_object_get (device, "adapter-luid", &cdata->adapter_luid, diff --git a/subprojects/gst-plugins-bad/sys/qsv/gstqsvh264enc.h b/subprojects/gst-plugins-bad/sys/qsv/gstqsvh264enc.h index ebdaf4957c..f1a9278c54 100644 --- a/subprojects/gst-plugins-bad/sys/qsv/gstqsvh264enc.h +++ b/subprojects/gst-plugins-bad/sys/qsv/gstqsvh264enc.h @@ -29,6 +29,7 @@ void gst_qsv_h264_enc_register (GstPlugin * plugin, guint rank, guint impl_index, GstObject * device, - mfxSession session); + mfxSession session, + gboolean d3d12_interop); G_END_DECLS diff --git a/subprojects/gst-plugins-bad/sys/qsv/gstqsvh265enc.cpp b/subprojects/gst-plugins-bad/sys/qsv/gstqsvh265enc.cpp index ea4c734668..27aba216f2 100644 --- a/subprojects/gst-plugins-bad/sys/qsv/gstqsvh265enc.cpp +++ b/subprojects/gst-plugins-bad/sys/qsv/gstqsvh265enc.cpp @@ -48,6 +48,10 @@ #include #endif +#ifdef HAVE_GST_D3D12 +#include +#endif + GST_DEBUG_CATEGORY_STATIC (gst_qsv_h265_enc_debug); #define GST_CAT_DEFAULT gst_qsv_h265_enc_debug @@ -209,6 +213,7 @@ enum #define DOC_SINK_CAPS \ "video/x-raw(memory:D3D11Memory), " DOC_SINK_CAPS_COMM "; " \ + "video/x-raw(memory:D3D12Memory), " DOC_SINK_CAPS_COMM "; " \ "video/x-raw(memory:VAMemory), " DOC_SINK_CAPS_COMM "; " \ "video/x-raw, " DOC_SINK_CAPS_COMM @@ -226,6 +231,7 @@ typedef struct _GstQsvH265EncClassData gchar *display_path; gchar *description; gboolean hdr10_aware; + gboolean d3d12_interop; } GstQsvH265EncClassData; typedef struct _GstQsvH265Enc @@ -322,6 +328,7 @@ gst_qsv_h265_enc_class_init (GstQsvH265EncClass * klass, gpointer data) qsvenc_class->impl_index = cdata->impl_index; qsvenc_class->adapter_luid = cdata->adapter_luid; qsvenc_class->display_path = cdata->display_path; + qsvenc_class->d3d12_interop = cdata->d3d12_interop; object_class->finalize = gst_qsv_h265_enc_finalize; object_class->set_property = gst_qsv_h265_enc_set_property; @@ -1422,7 +1429,7 @@ done: void gst_qsv_h265_enc_register (GstPlugin * plugin, guint rank, guint impl_index, - GstObject * device, mfxSession session) + GstObject * device, mfxSession session, gboolean d3d12_interop) { mfxVideoParam param; mfxInfoMFX *mfx; @@ -1572,6 +1579,13 @@ gst_qsv_h265_enc_register (GstPlugin * plugin, guint rank, guint impl_index, GstCapsFeatures *caps_features = gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, nullptr); gst_caps_set_features_simple (d3d11_caps, caps_features); +#ifdef HAVE_GST_D3D12 + auto d3d12_caps = gst_caps_copy (sink_caps); + auto d3d12_feature = + gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_D3D12_MEMORY, nullptr); + gst_caps_set_features_simple (d3d12_caps, d3d12_feature); + gst_caps_append (d3d11_caps, d3d12_caps); +#endif gst_caps_append (d3d11_caps, sink_caps); sink_caps = d3d11_caps; #else @@ -1618,6 +1632,7 @@ gst_qsv_h265_enc_register (GstPlugin * plugin, guint rank, guint impl_index, cdata->src_caps = src_caps; cdata->impl_index = impl_index; cdata->hdr10_aware = hdr10_aware; + cdata->d3d12_interop = d3d12_interop; #ifdef G_OS_WIN32 g_object_get (device, "adapter-luid", &cdata->adapter_luid, diff --git a/subprojects/gst-plugins-bad/sys/qsv/gstqsvh265enc.h b/subprojects/gst-plugins-bad/sys/qsv/gstqsvh265enc.h index 3aab2300f0..2565b0558d 100644 --- a/subprojects/gst-plugins-bad/sys/qsv/gstqsvh265enc.h +++ b/subprojects/gst-plugins-bad/sys/qsv/gstqsvh265enc.h @@ -29,6 +29,7 @@ void gst_qsv_h265_enc_register (GstPlugin * plugin, guint rank, guint impl_index, GstObject * device, - mfxSession session); + mfxSession session, + gboolean d3d12_interop); G_END_DECLS diff --git a/subprojects/gst-plugins-bad/sys/qsv/gstqsvjpegenc.cpp b/subprojects/gst-plugins-bad/sys/qsv/gstqsvjpegenc.cpp index 4cf4c36453..f64698925f 100644 --- a/subprojects/gst-plugins-bad/sys/qsv/gstqsvjpegenc.cpp +++ b/subprojects/gst-plugins-bad/sys/qsv/gstqsvjpegenc.cpp @@ -47,6 +47,10 @@ #include #endif +#ifdef HAVE_GST_D3D12 +#include +#endif + GST_DEBUG_CATEGORY_STATIC (gst_qsv_jpeg_enc_debug); #define GST_CAT_DEFAULT gst_qsv_jpeg_enc_debug @@ -64,6 +68,7 @@ enum #define DOC_SINK_CAPS \ "video/x-raw(memory:D3D11Memory), " DOC_SINK_CAPS_COMM "; " \ + "video/x-raw(memory:D3D12Memory), " DOC_SINK_CAPS_COMM "; " \ "video/x-raw(memory:VAMemory), " DOC_SINK_CAPS_COMM "; " \ "video/x-raw, " DOC_SINK_CAPS_COMM @@ -79,6 +84,7 @@ typedef struct _GstQsvJpegEncClassData gchar *display_path; gchar *description; gboolean interlaved; + gboolean d3d12_interop; } GstQsvJpegEncClassData; typedef struct _GstQsvJpegEnc @@ -134,6 +140,7 @@ gst_qsv_jpeg_enc_class_init (GstQsvJpegEncClass * klass, gpointer data) qsvenc_class->impl_index = cdata->impl_index; qsvenc_class->adapter_luid = cdata->adapter_luid; qsvenc_class->display_path = cdata->display_path; + qsvenc_class->d3d12_interop = cdata->d3d12_interop; object_class->finalize = gst_qsv_jpeg_enc_finalize; object_class->set_property = gst_qsv_jpeg_enc_set_property; @@ -360,7 +367,7 @@ gst_qsv_jpeg_enc_check_reconfigure (GstQsvEncoder * encoder, mfxSession session, void gst_qsv_jpeg_enc_register (GstPlugin * plugin, guint rank, guint impl_index, - GstObject * device, mfxSession session) + GstObject * device, mfxSession session, gboolean d3d12_interop) { mfxVideoParam param; mfxInfoMFX *mfx; @@ -475,6 +482,13 @@ gst_qsv_jpeg_enc_register (GstPlugin * plugin, guint rank, guint impl_index, GstCapsFeatures *caps_features = gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, nullptr); gst_caps_set_features_simple (d3d11_caps, caps_features); +#ifdef HAVE_GST_D3D12 + auto d3d12_caps = gst_caps_copy (sink_caps); + auto d3d12_feature = + gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_D3D12_MEMORY, nullptr); + gst_caps_set_features_simple (d3d12_caps, d3d12_feature); + gst_caps_append (d3d11_caps, d3d12_caps); +#endif gst_caps_append (d3d11_caps, sink_caps); sink_caps = d3d11_caps; #else @@ -500,6 +514,7 @@ gst_qsv_jpeg_enc_register (GstPlugin * plugin, guint rank, guint impl_index, cdata->src_caps = src_caps; cdata->impl_index = impl_index; cdata->interlaved = interlaved; + cdata->d3d12_interop = d3d12_interop; #ifdef G_OS_WIN32 g_object_get (device, "adapter-luid", &cdata->adapter_luid, diff --git a/subprojects/gst-plugins-bad/sys/qsv/gstqsvjpegenc.h b/subprojects/gst-plugins-bad/sys/qsv/gstqsvjpegenc.h index a073f0d3b4..b9ad347ae7 100644 --- a/subprojects/gst-plugins-bad/sys/qsv/gstqsvjpegenc.h +++ b/subprojects/gst-plugins-bad/sys/qsv/gstqsvjpegenc.h @@ -29,6 +29,7 @@ void gst_qsv_jpeg_enc_register (GstPlugin * plugin, guint rank, guint impl_index, GstObject * device, - mfxSession session); + mfxSession session, + gboolean d3d12_interop); G_END_DECLS diff --git a/subprojects/gst-plugins-bad/sys/qsv/gstqsvvp9enc.cpp b/subprojects/gst-plugins-bad/sys/qsv/gstqsvvp9enc.cpp index 7e2d3d07a9..6378d04dca 100644 --- a/subprojects/gst-plugins-bad/sys/qsv/gstqsvvp9enc.cpp +++ b/subprojects/gst-plugins-bad/sys/qsv/gstqsvvp9enc.cpp @@ -47,6 +47,10 @@ #include #endif +#ifdef HAVE_GST_D3D12 +#include +#endif + GST_DEBUG_CATEGORY_STATIC (gst_qsv_vp9_enc_debug); #define GST_CAT_DEFAULT gst_qsv_vp9_enc_debug @@ -127,6 +131,7 @@ enum #define DOC_SINK_CAPS \ "video/x-raw(memory:D3D11Memory), " DOC_SINK_CAPS_COMM "; " \ + "video/x-raw(memory:D3D12Memory), " DOC_SINK_CAPS_COMM "; " \ "video/x-raw(memory:VAMemory), " DOC_SINK_CAPS_COMM "; " \ "video/x-raw, " DOC_SINK_CAPS_COMM @@ -142,6 +147,7 @@ typedef struct _GstQsvVP9EncClassData gint64 adapter_luid; gchar *display_path; gchar *description; + gboolean d3d12_interop; } GstQsvVP9EncClassData; typedef struct _GstQsvVP9Enc @@ -212,6 +218,7 @@ gst_qsv_vp9_enc_class_init (GstQsvVP9EncClass * klass, gpointer data) qsvenc_class->impl_index = cdata->impl_index; qsvenc_class->adapter_luid = cdata->adapter_luid; qsvenc_class->display_path = cdata->display_path; + qsvenc_class->d3d12_interop = cdata->d3d12_interop; object_class->finalize = gst_qsv_vp9_enc_finalize; object_class->set_property = gst_qsv_vp9_enc_set_property; @@ -820,7 +827,7 @@ done: void gst_qsv_vp9_enc_register (GstPlugin * plugin, guint rank, guint impl_index, - GstObject * device, mfxSession session) + GstObject * device, mfxSession session, gboolean d3d12_interop) { mfxVideoParam param; mfxInfoMFX *mfx; @@ -962,6 +969,13 @@ gst_qsv_vp9_enc_register (GstPlugin * plugin, guint rank, guint impl_index, GstCapsFeatures *caps_features = gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, nullptr); gst_caps_set_features_simple (d3d11_caps, caps_features); +#ifdef HAVE_GST_D3D12 + auto d3d12_caps = gst_caps_copy (sink_caps); + auto d3d12_feature = + gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_D3D12_MEMORY, nullptr); + gst_caps_set_features_simple (d3d12_caps, d3d12_feature); + gst_caps_append (d3d11_caps, d3d12_caps); +#endif gst_caps_append (d3d11_caps, sink_caps); sink_caps = d3d11_caps; #else @@ -1005,6 +1019,7 @@ gst_qsv_vp9_enc_register (GstPlugin * plugin, guint rank, guint impl_index, cdata->sink_caps = sink_caps; cdata->src_caps = src_caps; cdata->impl_index = impl_index; + cdata->d3d12_interop = d3d12_interop; #ifdef G_OS_WIN32 g_object_get (device, "adapter-luid", &cdata->adapter_luid, diff --git a/subprojects/gst-plugins-bad/sys/qsv/gstqsvvp9enc.h b/subprojects/gst-plugins-bad/sys/qsv/gstqsvvp9enc.h index ed5cf5645b..4da6900b57 100644 --- a/subprojects/gst-plugins-bad/sys/qsv/gstqsvvp9enc.h +++ b/subprojects/gst-plugins-bad/sys/qsv/gstqsvvp9enc.h @@ -29,6 +29,7 @@ void gst_qsv_vp9_enc_register (GstPlugin * plugin, guint rank, guint impl_index, GstObject * device, - mfxSession session); + mfxSession session, + gboolean d3d12_interop); G_END_DECLS diff --git a/subprojects/gst-plugins-bad/sys/qsv/meson.build b/subprojects/gst-plugins-bad/sys/qsv/meson.build index cdb20112e3..5bd7e1683b 100644 --- a/subprojects/gst-plugins-bad/sys/qsv/meson.build +++ b/subprojects/gst-plugins-bad/sys/qsv/meson.build @@ -57,6 +57,10 @@ if host_system == 'windows' qsv_sources += qsv_d3d11_sources qsv_platform_deps += [gstd3d11_dep] + if gstd3d12_dep.found() + qsv_platform_deps += [gstd3d12_dep] + extra_args += ['-DHAVE_GST_D3D12'] + endif elif host_system == 'linux' if not gstva_dep.found() if qsv_option.enabled() diff --git a/subprojects/gst-plugins-bad/sys/qsv/plugin.cpp b/subprojects/gst-plugins-bad/sys/qsv/plugin.cpp index a6fdddd40d..eed9654412 100644 --- a/subprojects/gst-plugins-bad/sys/qsv/plugin.cpp +++ b/subprojects/gst-plugins-bad/sys/qsv/plugin.cpp @@ -61,6 +61,10 @@ #include #endif +#ifdef HAVE_GST_D3D12 +#include +#endif + #include GST_DEBUG_CATEGORY (gst_qsv_debug); @@ -250,6 +254,7 @@ plugin_init (GstPlugin * plugin) mfxSession session = nullptr; mfxImplDescription *desc = nullptr; GstObject *device = nullptr; + gboolean d3d12_interop = FALSE; status = MFXEnumImplementations (loader, i, MFX_IMPLCAPS_IMPLDESCSTRUCTURE, (mfxHDL *) & desc); @@ -268,16 +273,45 @@ plugin_init (GstPlugin * plugin) if (!session) goto next; +#ifdef HAVE_GST_D3D12 + { + gint64 luid; + g_object_get (device, "adapter-luid", &luid, nullptr); + auto device12 = gst_d3d12_device_new_for_adapter_luid (luid); + if (device12) { + auto handle12 = gst_d3d12_device_get_device_handle (device12); + D3D12_FEATURE_DATA_D3D12_OPTIONS4 feature_data = { }; + auto hr = handle12->CheckFeatureSupport (D3D12_FEATURE_D3D12_OPTIONS4, + &feature_data, sizeof (feature_data)); + if (SUCCEEDED (hr) && feature_data.SharedResourceCompatibilityTier >= + D3D12_SHARED_RESOURCE_COMPATIBILITY_TIER_2) { + GST_INFO_OBJECT (device, "Device supports D3D12 resource share"); + d3d12_interop = TRUE; + } else { + GST_INFO_OBJECT (device, + "Device does not support D3D12 resource share"); + } + + gst_object_unref (device12); + } + } +#endif + gst_qsv_h264_dec_register (plugin, GST_RANK_MARGINAL, i, device, session); gst_qsv_h265_dec_register (plugin, GST_RANK_MARGINAL, i, device, session); gst_qsv_jpeg_dec_register (plugin, GST_RANK_SECONDARY, i, device, session); gst_qsv_vp9_dec_register (plugin, GST_RANK_MARGINAL, i, device, session); - gst_qsv_h264_enc_register (plugin, enc_rank, i, device, session); - gst_qsv_h265_enc_register (plugin, enc_rank, i, device, session); - gst_qsv_jpeg_enc_register (plugin, enc_rank, i, device, session); - gst_qsv_vp9_enc_register (plugin, enc_rank, i, device, session); - gst_qsv_av1_enc_register (plugin, enc_rank, i, device, session); + gst_qsv_h264_enc_register (plugin, + enc_rank, i, device, session, d3d12_interop); + gst_qsv_h265_enc_register (plugin, + enc_rank, i, device, session, d3d12_interop); + gst_qsv_jpeg_enc_register (plugin, + enc_rank, i, device, session, d3d12_interop); + gst_qsv_vp9_enc_register (plugin, + enc_rank, i, device, session, d3d12_interop); + gst_qsv_av1_enc_register (plugin, + enc_rank, i, device, session, d3d12_interop); next: MFXDispReleaseImplDescription (loader, desc);