qsv: Add support for d3d12 interop in encoder

Since QSV API does not support D3D12, try to import d3d12 resource
into d3d11 texture. Note that resource sharing requires
D3D12_SHARED_RESOURCE_COMPATIBILITY_TIER_2 for NV12 texure sharing.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6501>
This commit is contained in:
Seungha Yang 2024-04-02 01:36:28 +09:00 committed by GStreamer Marge Bot
parent 78f1299ce4
commit 707ac69f5f
16 changed files with 234 additions and 25 deletions

View file

@ -25,6 +25,10 @@
#include <string.h> #include <string.h>
#include <wrl.h> #include <wrl.h>
#ifdef HAVE_GST_D3D12
#include <gst/d3d12/gstd3d12.h>
#endif
/* *INDENT-OFF* */ /* *INDENT-OFF* */
using namespace Microsoft::WRL; using namespace Microsoft::WRL;
/* *INDENT-ON* */ /* *INDENT-ON* */
@ -38,6 +42,7 @@ struct _GstQsvD3D11Allocator
GstD3D11Device *device; GstD3D11Device *device;
GstD3D11Fence *fence; GstD3D11Fence *fence;
gboolean d3d12_import_allowed;
}; };
#define gst_qsv_d3d11_allocator_parent_class parent_class #define gst_qsv_d3d11_allocator_parent_class parent_class
@ -438,6 +443,7 @@ static GstBuffer *
gst_qsv_d3d11_allocator_upload (GstQsvAllocator * allocator, gst_qsv_d3d11_allocator_upload (GstQsvAllocator * allocator,
const GstVideoInfo * info, GstBuffer * buffer, GstBufferPool * pool) const GstVideoInfo * info, GstBuffer * buffer, GstBufferPool * pool)
{ {
auto self = GST_QSV_D3D11_ALLOCATOR (allocator);
GstMemory *mem; GstMemory *mem;
GstD3D11Memory *dmem; GstD3D11Memory *dmem;
D3D11_TEXTURE2D_DESC desc; D3D11_TEXTURE2D_DESC desc;
@ -455,19 +461,48 @@ gst_qsv_d3d11_allocator_upload (GstQsvAllocator * allocator,
*/ */
if (!GST_IS_D3D11_BUFFER_POOL (pool)) { 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; return nullptr;
} }
flow_ret = gst_buffer_pool_acquire_buffer (pool, &dst_buf, nullptr); flow_ret = gst_buffer_pool_acquire_buffer (pool, &dst_buf, nullptr);
if (flow_ret != GST_FLOW_OK) { if (flow_ret != GST_FLOW_OK) {
GST_WARNING_OBJECT (allocator, GST_WARNING_OBJECT (self,
"Failed to acquire buffer from pool, return %s", "Failed to acquire buffer from pool, return %s",
gst_flow_get_name (flow_ret)); gst_flow_get_name (flow_ret));
return nullptr; return nullptr;
} }
mem = gst_buffer_peek_memory (buffer, 0); 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) { if (!gst_is_d3d11_memory (mem) || gst_buffer_n_memory (buffer) > 1) {
/* d3d11 buffer should hold single memory object */ /* d3d11 buffer should hold single memory object */
return gst_qsv_frame_upload_sysmem (info, buffer, dst_buf); 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); gst_d3d11_memory_get_texture_desc (dmem, &desc);
if (desc.Usage == D3D11_USAGE_DEFAULT && !shared_copy) { 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); gst_buffer_unref (dst_buf);
return gst_buffer_ref (buffer); return gst_buffer_ref (buffer);
} }
return gst_qsv_frame_copy_d3d11 (GST_QSV_D3D11_ALLOCATOR (allocator), info, return gst_qsv_frame_copy_d3d11 (self, info, buffer, dst_buf, shared_copy);
buffer, dst_buf, shared_copy);
} }
static GstBuffer * static GstBuffer *
@ -571,3 +605,11 @@ gst_qsv_d3d11_allocator_new (GstD3D11Device * device)
return GST_QSV_ALLOCATOR (self); 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;
}

View file

@ -31,4 +31,7 @@ G_DECLARE_FINAL_TYPE (GstQsvD3D11Allocator, gst_qsv_d3d11_allocator,
GstQsvAllocator * gst_qsv_d3d11_allocator_new (GstD3D11Device * device); GstQsvAllocator * gst_qsv_d3d11_allocator_new (GstD3D11Device * device);
void gst_qsv_d3d11_allocator_set_d3d12_import_allowed (GstQsvAllocator * allocator,
gboolean allowed);
G_END_DECLS G_END_DECLS

View file

@ -46,6 +46,10 @@
#include <gst/va/gstva.h> #include <gst/va/gstva.h>
#endif #endif
#ifdef HAVE_GST_D3D12
#include <gst/d3d12/gstd3d12.h>
#endif
GST_DEBUG_CATEGORY_STATIC (gst_qsv_av1_enc_debug); GST_DEBUG_CATEGORY_STATIC (gst_qsv_av1_enc_debug);
#define GST_CAT_DEFAULT gst_qsv_av1_enc_debug #define GST_CAT_DEFAULT gst_qsv_av1_enc_debug
@ -116,6 +120,7 @@ enum
#define DOC_SINK_CAPS \ #define DOC_SINK_CAPS \
"video/x-raw(memory:D3D11Memory), " DOC_SINK_CAPS_COMM "; " \ "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(memory:VAMemory), " DOC_SINK_CAPS_COMM "; " \
"video/x-raw, " DOC_SINK_CAPS_COMM "video/x-raw, " DOC_SINK_CAPS_COMM
@ -131,6 +136,7 @@ typedef struct _GstQsvAV1EncClassData
gint64 adapter_luid; gint64 adapter_luid;
gchar *display_path; gchar *display_path;
gchar *description; gchar *description;
gboolean d3d12_interop;
} GstQsvAV1EncClassData; } GstQsvAV1EncClassData;
typedef struct _GstQsvAV1Enc 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->impl_index = cdata->impl_index;
qsvenc_class->adapter_luid = cdata->adapter_luid; qsvenc_class->adapter_luid = cdata->adapter_luid;
qsvenc_class->display_path = cdata->display_path; qsvenc_class->display_path = cdata->display_path;
qsvenc_class->d3d12_interop = cdata->d3d12_interop;
object_class->finalize = gst_qsv_av1_enc_finalize; object_class->finalize = gst_qsv_av1_enc_finalize;
object_class->set_property = gst_qsv_av1_enc_set_property; object_class->set_property = gst_qsv_av1_enc_set_property;
@ -619,7 +626,7 @@ done:
void void
gst_qsv_av1_enc_register (GstPlugin * plugin, guint rank, guint impl_index, 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; mfxVideoParam param;
mfxInfoMFX *mfx; mfxInfoMFX *mfx;
@ -743,6 +750,13 @@ gst_qsv_av1_enc_register (GstPlugin * plugin, guint rank, guint impl_index,
GstCapsFeatures *caps_features = GstCapsFeatures *caps_features =
gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, nullptr); gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, nullptr);
gst_caps_set_features_simple (d3d11_caps, caps_features); 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); gst_caps_append (d3d11_caps, sink_caps);
sink_caps = d3d11_caps; sink_caps = d3d11_caps;
#else #else
@ -768,6 +782,7 @@ gst_qsv_av1_enc_register (GstPlugin * plugin, guint rank, guint impl_index,
cdata->sink_caps = sink_caps; cdata->sink_caps = sink_caps;
cdata->src_caps = src_caps; cdata->src_caps = src_caps;
cdata->impl_index = impl_index; cdata->impl_index = impl_index;
cdata->d3d12_interop = d3d12_interop;
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
g_object_get (device, "adapter-luid", &cdata->adapter_luid, g_object_get (device, "adapter-luid", &cdata->adapter_luid,

View file

@ -29,6 +29,7 @@ void gst_qsv_av1_enc_register (GstPlugin * plugin,
guint rank, guint rank,
guint impl_index, guint impl_index,
GstObject * device, GstObject * device,
mfxSession session); mfxSession session,
gboolean d3d12_interop);
G_END_DECLS G_END_DECLS

View file

@ -38,6 +38,10 @@ using namespace Microsoft::WRL;
#include "gstqsvallocator_va.h" #include "gstqsvallocator_va.h"
#endif /* G_OS_WIN32 */ #endif /* G_OS_WIN32 */
#ifdef HAVE_GST_D3D12
#include <gst/d3d12/gstd3d12.h>
#endif
GST_DEBUG_CATEGORY_STATIC (gst_qsv_encoder_debug); GST_DEBUG_CATEGORY_STATIC (gst_qsv_encoder_debug);
#define GST_CAT_DEFAULT gst_qsv_encoder_debug #define GST_CAT_DEFAULT gst_qsv_encoder_debug
@ -115,6 +119,7 @@ typedef struct _GstQsvEncoderTask
struct _GstQsvEncoderPrivate struct _GstQsvEncoderPrivate
{ {
GstObject *device; GstObject *device;
GstObject *device12;
GstVideoCodecState *input_state; GstVideoCodecState *input_state;
GstQsvAllocator *allocator; GstQsvAllocator *allocator;
@ -282,6 +287,7 @@ gst_qsv_encoder_dispose (GObject * object)
GstQsvEncoderPrivate *priv = self->priv; GstQsvEncoderPrivate *priv = self->priv;
gst_clear_object (&priv->device); gst_clear_object (&priv->device);
gst_clear_object (&priv->device12);
G_OBJECT_CLASS (parent_class)->dispose (object); 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); device = GST_D3D11_DEVICE_CAST (priv->device);
priv->allocator = gst_qsv_d3d11_allocator_new (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 /* For D3D11 device handle to be used by QSV, multithread protection layer
* must be enabled before the MFXVideoCORE_SetHandle() call. * 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; GstQsvEncoderPrivate *priv = self->priv;
GstD3D11Device *device = GST_D3D11_DEVICE (priv->device); GstD3D11Device *device = GST_D3D11_DEVICE (priv->device);
GstVideoInfo info; GstVideoInfo info;
GstBufferPool *pool; GstBufferPool *pool = nullptr;
GstCaps *caps; GstCaps *caps;
guint size; guint size;
GstStructure *config; GstStructure *config;
GstCapsFeatures *features; GstCapsFeatures *features;
gboolean is_d3d11 = FALSE; 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); gst_query_parse_allocation (query, &caps, nullptr);
if (!caps) { if (!caps) {
@ -1493,14 +1505,25 @@ gst_qsv_encoder_propose_allocation (GstVideoEncoder * encoder, GstQuery * query)
} }
features = gst_caps_get_features (caps, 0); 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_CAPS_FEATURE_MEMORY_D3D11_MEMORY)) {
GST_DEBUG_OBJECT (self, "upstream support d3d11 memory"); GST_DEBUG_OBJECT (self, "upstream support d3d11 memory");
pool = gst_d3d11_buffer_pool_new (device); pool = gst_d3d11_buffer_pool_new (device);
is_d3d11 = TRUE; 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); config = gst_buffer_pool_get_config (pool);
gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META); 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_d3d11_allocation_params_alignment (d3d11_params, &align);
gst_buffer_pool_config_set_d3d11_allocation_params (config, d3d11_params); gst_buffer_pool_config_set_d3d11_allocation_params (config, d3d11_params);
gst_d3d11_allocation_params_free (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_config_add_option (config,
GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT); GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT);
} }

View file

@ -68,6 +68,8 @@ struct _GstQsvEncoderClass
/* VA display device path, for Linux */ /* VA display device path, for Linux */
gchar *display_path; gchar *display_path;
gboolean d3d12_interop;
gboolean (*set_format) (GstQsvEncoder * encoder, gboolean (*set_format) (GstQsvEncoder * encoder,
GstVideoCodecState * state, GstVideoCodecState * state,
mfxVideoParam * param, mfxVideoParam * param,

View file

@ -49,6 +49,10 @@
#include <gst/va/gstva.h> #include <gst/va/gstva.h>
#endif #endif
#ifdef HAVE_GST_D3D12
#include <gst/d3d12/gstd3d12.h>
#endif
GST_DEBUG_CATEGORY_STATIC (gst_qsv_h264_enc_debug); GST_DEBUG_CATEGORY_STATIC (gst_qsv_h264_enc_debug);
#define GST_CAT_DEFAULT gst_qsv_h264_enc_debug #define GST_CAT_DEFAULT gst_qsv_h264_enc_debug
@ -368,6 +372,7 @@ enum
#define DOC_SINK_CAPS \ #define DOC_SINK_CAPS \
"video/x-raw(memory:D3D11Memory), " DOC_SINK_CAPS_COMM "; " \ "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(memory:VAMemory), " DOC_SINK_CAPS_COMM "; " \
"video/x-raw, " DOC_SINK_CAPS_COMM "video/x-raw, " DOC_SINK_CAPS_COMM
@ -385,6 +390,7 @@ typedef struct _GstQsvH264EncClassData
gint64 adapter_luid; gint64 adapter_luid;
gchar *display_path; gchar *display_path;
gchar *description; gchar *description;
gboolean d3d12_interop;
} GstQsvH264EncClassData; } GstQsvH264EncClassData;
typedef struct _GstQsvH264Enc 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->impl_index = cdata->impl_index;
qsvenc_class->adapter_luid = cdata->adapter_luid; qsvenc_class->adapter_luid = cdata->adapter_luid;
qsvenc_class->display_path = cdata->display_path; qsvenc_class->display_path = cdata->display_path;
qsvenc_class->d3d12_interop = cdata->d3d12_interop;
object_class->finalize = gst_qsv_h264_enc_finalize; object_class->finalize = gst_qsv_h264_enc_finalize;
object_class->set_property = gst_qsv_h264_enc_set_property; object_class->set_property = gst_qsv_h264_enc_set_property;
@ -2111,7 +2118,7 @@ done:
void void
gst_qsv_h264_enc_register (GstPlugin * plugin, guint rank, guint impl_index, 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; mfxStatus status;
mfxVideoParam param; mfxVideoParam param;
@ -2233,6 +2240,13 @@ gst_qsv_h264_enc_register (GstPlugin * plugin, guint rank, guint impl_index,
GstCapsFeatures *caps_features = GstCapsFeatures *caps_features =
gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, nullptr); gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, nullptr);
gst_caps_set_features_simple (d3d11_caps, caps_features); 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); gst_caps_append (d3d11_caps, sink_caps);
sink_caps = d3d11_caps; sink_caps = d3d11_caps;
#else #else
@ -2278,6 +2292,7 @@ gst_qsv_h264_enc_register (GstPlugin * plugin, guint rank, guint impl_index,
cdata->sink_caps = sink_caps; cdata->sink_caps = sink_caps;
cdata->src_caps = src_caps; cdata->src_caps = src_caps;
cdata->impl_index = impl_index; cdata->impl_index = impl_index;
cdata->d3d12_interop = d3d12_interop;
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
g_object_get (device, "adapter-luid", &cdata->adapter_luid, g_object_get (device, "adapter-luid", &cdata->adapter_luid,

View file

@ -29,6 +29,7 @@ void gst_qsv_h264_enc_register (GstPlugin * plugin,
guint rank, guint rank,
guint impl_index, guint impl_index,
GstObject * device, GstObject * device,
mfxSession session); mfxSession session,
gboolean d3d12_interop);
G_END_DECLS G_END_DECLS

View file

@ -48,6 +48,10 @@
#include <gst/va/gstva.h> #include <gst/va/gstva.h>
#endif #endif
#ifdef HAVE_GST_D3D12
#include <gst/d3d12/gstd3d12.h>
#endif
GST_DEBUG_CATEGORY_STATIC (gst_qsv_h265_enc_debug); GST_DEBUG_CATEGORY_STATIC (gst_qsv_h265_enc_debug);
#define GST_CAT_DEFAULT gst_qsv_h265_enc_debug #define GST_CAT_DEFAULT gst_qsv_h265_enc_debug
@ -209,6 +213,7 @@ enum
#define DOC_SINK_CAPS \ #define DOC_SINK_CAPS \
"video/x-raw(memory:D3D11Memory), " DOC_SINK_CAPS_COMM "; " \ "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(memory:VAMemory), " DOC_SINK_CAPS_COMM "; " \
"video/x-raw, " DOC_SINK_CAPS_COMM "video/x-raw, " DOC_SINK_CAPS_COMM
@ -226,6 +231,7 @@ typedef struct _GstQsvH265EncClassData
gchar *display_path; gchar *display_path;
gchar *description; gchar *description;
gboolean hdr10_aware; gboolean hdr10_aware;
gboolean d3d12_interop;
} GstQsvH265EncClassData; } GstQsvH265EncClassData;
typedef struct _GstQsvH265Enc 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->impl_index = cdata->impl_index;
qsvenc_class->adapter_luid = cdata->adapter_luid; qsvenc_class->adapter_luid = cdata->adapter_luid;
qsvenc_class->display_path = cdata->display_path; qsvenc_class->display_path = cdata->display_path;
qsvenc_class->d3d12_interop = cdata->d3d12_interop;
object_class->finalize = gst_qsv_h265_enc_finalize; object_class->finalize = gst_qsv_h265_enc_finalize;
object_class->set_property = gst_qsv_h265_enc_set_property; object_class->set_property = gst_qsv_h265_enc_set_property;
@ -1422,7 +1429,7 @@ done:
void void
gst_qsv_h265_enc_register (GstPlugin * plugin, guint rank, guint impl_index, 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; mfxVideoParam param;
mfxInfoMFX *mfx; mfxInfoMFX *mfx;
@ -1572,6 +1579,13 @@ gst_qsv_h265_enc_register (GstPlugin * plugin, guint rank, guint impl_index,
GstCapsFeatures *caps_features = GstCapsFeatures *caps_features =
gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, nullptr); gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, nullptr);
gst_caps_set_features_simple (d3d11_caps, caps_features); 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); gst_caps_append (d3d11_caps, sink_caps);
sink_caps = d3d11_caps; sink_caps = d3d11_caps;
#else #else
@ -1618,6 +1632,7 @@ gst_qsv_h265_enc_register (GstPlugin * plugin, guint rank, guint impl_index,
cdata->src_caps = src_caps; cdata->src_caps = src_caps;
cdata->impl_index = impl_index; cdata->impl_index = impl_index;
cdata->hdr10_aware = hdr10_aware; cdata->hdr10_aware = hdr10_aware;
cdata->d3d12_interop = d3d12_interop;
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
g_object_get (device, "adapter-luid", &cdata->adapter_luid, g_object_get (device, "adapter-luid", &cdata->adapter_luid,

View file

@ -29,6 +29,7 @@ void gst_qsv_h265_enc_register (GstPlugin * plugin,
guint rank, guint rank,
guint impl_index, guint impl_index,
GstObject * device, GstObject * device,
mfxSession session); mfxSession session,
gboolean d3d12_interop);
G_END_DECLS G_END_DECLS

View file

@ -47,6 +47,10 @@
#include <gst/va/gstva.h> #include <gst/va/gstva.h>
#endif #endif
#ifdef HAVE_GST_D3D12
#include <gst/d3d12/gstd3d12.h>
#endif
GST_DEBUG_CATEGORY_STATIC (gst_qsv_jpeg_enc_debug); GST_DEBUG_CATEGORY_STATIC (gst_qsv_jpeg_enc_debug);
#define GST_CAT_DEFAULT gst_qsv_jpeg_enc_debug #define GST_CAT_DEFAULT gst_qsv_jpeg_enc_debug
@ -64,6 +68,7 @@ enum
#define DOC_SINK_CAPS \ #define DOC_SINK_CAPS \
"video/x-raw(memory:D3D11Memory), " DOC_SINK_CAPS_COMM "; " \ "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(memory:VAMemory), " DOC_SINK_CAPS_COMM "; " \
"video/x-raw, " DOC_SINK_CAPS_COMM "video/x-raw, " DOC_SINK_CAPS_COMM
@ -79,6 +84,7 @@ typedef struct _GstQsvJpegEncClassData
gchar *display_path; gchar *display_path;
gchar *description; gchar *description;
gboolean interlaved; gboolean interlaved;
gboolean d3d12_interop;
} GstQsvJpegEncClassData; } GstQsvJpegEncClassData;
typedef struct _GstQsvJpegEnc 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->impl_index = cdata->impl_index;
qsvenc_class->adapter_luid = cdata->adapter_luid; qsvenc_class->adapter_luid = cdata->adapter_luid;
qsvenc_class->display_path = cdata->display_path; qsvenc_class->display_path = cdata->display_path;
qsvenc_class->d3d12_interop = cdata->d3d12_interop;
object_class->finalize = gst_qsv_jpeg_enc_finalize; object_class->finalize = gst_qsv_jpeg_enc_finalize;
object_class->set_property = gst_qsv_jpeg_enc_set_property; 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 void
gst_qsv_jpeg_enc_register (GstPlugin * plugin, guint rank, guint impl_index, 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; mfxVideoParam param;
mfxInfoMFX *mfx; mfxInfoMFX *mfx;
@ -475,6 +482,13 @@ gst_qsv_jpeg_enc_register (GstPlugin * plugin, guint rank, guint impl_index,
GstCapsFeatures *caps_features = GstCapsFeatures *caps_features =
gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, nullptr); gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, nullptr);
gst_caps_set_features_simple (d3d11_caps, caps_features); 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); gst_caps_append (d3d11_caps, sink_caps);
sink_caps = d3d11_caps; sink_caps = d3d11_caps;
#else #else
@ -500,6 +514,7 @@ gst_qsv_jpeg_enc_register (GstPlugin * plugin, guint rank, guint impl_index,
cdata->src_caps = src_caps; cdata->src_caps = src_caps;
cdata->impl_index = impl_index; cdata->impl_index = impl_index;
cdata->interlaved = interlaved; cdata->interlaved = interlaved;
cdata->d3d12_interop = d3d12_interop;
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
g_object_get (device, "adapter-luid", &cdata->adapter_luid, g_object_get (device, "adapter-luid", &cdata->adapter_luid,

View file

@ -29,6 +29,7 @@ void gst_qsv_jpeg_enc_register (GstPlugin * plugin,
guint rank, guint rank,
guint impl_index, guint impl_index,
GstObject * device, GstObject * device,
mfxSession session); mfxSession session,
gboolean d3d12_interop);
G_END_DECLS G_END_DECLS

View file

@ -47,6 +47,10 @@
#include <gst/va/gstva.h> #include <gst/va/gstva.h>
#endif #endif
#ifdef HAVE_GST_D3D12
#include <gst/d3d12/gstd3d12.h>
#endif
GST_DEBUG_CATEGORY_STATIC (gst_qsv_vp9_enc_debug); GST_DEBUG_CATEGORY_STATIC (gst_qsv_vp9_enc_debug);
#define GST_CAT_DEFAULT gst_qsv_vp9_enc_debug #define GST_CAT_DEFAULT gst_qsv_vp9_enc_debug
@ -127,6 +131,7 @@ enum
#define DOC_SINK_CAPS \ #define DOC_SINK_CAPS \
"video/x-raw(memory:D3D11Memory), " DOC_SINK_CAPS_COMM "; " \ "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(memory:VAMemory), " DOC_SINK_CAPS_COMM "; " \
"video/x-raw, " DOC_SINK_CAPS_COMM "video/x-raw, " DOC_SINK_CAPS_COMM
@ -142,6 +147,7 @@ typedef struct _GstQsvVP9EncClassData
gint64 adapter_luid; gint64 adapter_luid;
gchar *display_path; gchar *display_path;
gchar *description; gchar *description;
gboolean d3d12_interop;
} GstQsvVP9EncClassData; } GstQsvVP9EncClassData;
typedef struct _GstQsvVP9Enc 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->impl_index = cdata->impl_index;
qsvenc_class->adapter_luid = cdata->adapter_luid; qsvenc_class->adapter_luid = cdata->adapter_luid;
qsvenc_class->display_path = cdata->display_path; qsvenc_class->display_path = cdata->display_path;
qsvenc_class->d3d12_interop = cdata->d3d12_interop;
object_class->finalize = gst_qsv_vp9_enc_finalize; object_class->finalize = gst_qsv_vp9_enc_finalize;
object_class->set_property = gst_qsv_vp9_enc_set_property; object_class->set_property = gst_qsv_vp9_enc_set_property;
@ -820,7 +827,7 @@ done:
void void
gst_qsv_vp9_enc_register (GstPlugin * plugin, guint rank, guint impl_index, 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; mfxVideoParam param;
mfxInfoMFX *mfx; mfxInfoMFX *mfx;
@ -962,6 +969,13 @@ gst_qsv_vp9_enc_register (GstPlugin * plugin, guint rank, guint impl_index,
GstCapsFeatures *caps_features = GstCapsFeatures *caps_features =
gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, nullptr); gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, nullptr);
gst_caps_set_features_simple (d3d11_caps, caps_features); 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); gst_caps_append (d3d11_caps, sink_caps);
sink_caps = d3d11_caps; sink_caps = d3d11_caps;
#else #else
@ -1005,6 +1019,7 @@ gst_qsv_vp9_enc_register (GstPlugin * plugin, guint rank, guint impl_index,
cdata->sink_caps = sink_caps; cdata->sink_caps = sink_caps;
cdata->src_caps = src_caps; cdata->src_caps = src_caps;
cdata->impl_index = impl_index; cdata->impl_index = impl_index;
cdata->d3d12_interop = d3d12_interop;
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
g_object_get (device, "adapter-luid", &cdata->adapter_luid, g_object_get (device, "adapter-luid", &cdata->adapter_luid,

View file

@ -29,6 +29,7 @@ void gst_qsv_vp9_enc_register (GstPlugin * plugin,
guint rank, guint rank,
guint impl_index, guint impl_index,
GstObject * device, GstObject * device,
mfxSession session); mfxSession session,
gboolean d3d12_interop);
G_END_DECLS G_END_DECLS

View file

@ -57,6 +57,10 @@ if host_system == 'windows'
qsv_sources += qsv_d3d11_sources qsv_sources += qsv_d3d11_sources
qsv_platform_deps += [gstd3d11_dep] qsv_platform_deps += [gstd3d11_dep]
if gstd3d12_dep.found()
qsv_platform_deps += [gstd3d12_dep]
extra_args += ['-DHAVE_GST_D3D12']
endif
elif host_system == 'linux' elif host_system == 'linux'
if not gstva_dep.found() if not gstva_dep.found()
if qsv_option.enabled() if qsv_option.enabled()

View file

@ -61,6 +61,10 @@
#include <gst/va/gstva.h> #include <gst/va/gstva.h>
#endif #endif
#ifdef HAVE_GST_D3D12
#include <gst/d3d12/gstd3d12.h>
#endif
#include <glib/gi18n-lib.h> #include <glib/gi18n-lib.h>
GST_DEBUG_CATEGORY (gst_qsv_debug); GST_DEBUG_CATEGORY (gst_qsv_debug);
@ -250,6 +254,7 @@ plugin_init (GstPlugin * plugin)
mfxSession session = nullptr; mfxSession session = nullptr;
mfxImplDescription *desc = nullptr; mfxImplDescription *desc = nullptr;
GstObject *device = nullptr; GstObject *device = nullptr;
gboolean d3d12_interop = FALSE;
status = MFXEnumImplementations (loader, status = MFXEnumImplementations (loader,
i, MFX_IMPLCAPS_IMPLDESCSTRUCTURE, (mfxHDL *) & desc); i, MFX_IMPLCAPS_IMPLDESCSTRUCTURE, (mfxHDL *) & desc);
@ -268,16 +273,45 @@ plugin_init (GstPlugin * plugin)
if (!session) if (!session)
goto next; 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_h264_dec_register (plugin, GST_RANK_MARGINAL, i, device, session);
gst_qsv_h265_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_jpeg_dec_register (plugin, GST_RANK_SECONDARY, i, device, session);
gst_qsv_vp9_dec_register (plugin, GST_RANK_MARGINAL, 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_h264_enc_register (plugin,
gst_qsv_h265_enc_register (plugin, enc_rank, i, device, session); enc_rank, i, device, session, d3d12_interop);
gst_qsv_jpeg_enc_register (plugin, enc_rank, i, device, session); gst_qsv_h265_enc_register (plugin,
gst_qsv_vp9_enc_register (plugin, enc_rank, i, device, session); enc_rank, i, device, session, d3d12_interop);
gst_qsv_av1_enc_register (plugin, enc_rank, i, device, session); 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: next:
MFXDispReleaseImplDescription (loader, desc); MFXDispReleaseImplDescription (loader, desc);