diff --git a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12av1dec.cpp b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12av1dec.cpp index aa50d3c9e5..a11c1afce3 100644 --- a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12av1dec.cpp +++ b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12av1dec.cpp @@ -95,11 +95,9 @@ gst_d3d12_av1_dec_class_init (GstD3D12AV1DecClass * klass, gpointer data) static void gst_d3d12_av1_dec_init (GstD3D12AV1Dec * self) { - GstD3D12AV1DecClass *klass = GST_D3D12_AV1_DEC_GET_CLASS (self); - GstD3D12DecoderSubClassData *cdata = &klass->class_data; + auto klass = GST_D3D12_AV1_DEC_GET_CLASS (self); - self->decoder = gst_d3d12_decoder_new (GST_DXVA_CODEC_AV1, - cdata->adapter_luid); + self->decoder = gst_d3d12_decoder_new (&klass->class_data); } static void @@ -116,8 +114,8 @@ static void gst_d3d12_av1_dec_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { - GstD3D12AV1DecClass *klass = GST_D3D12_AV1_DEC_GET_CLASS (object); - GstD3D12DecoderSubClassData *cdata = &klass->class_data; + auto klass = GST_D3D12_AV1_DEC_GET_CLASS (object); + auto cdata = &klass->class_data; gst_d3d12_decoder_proxy_get_property (object, prop_id, value, pspec, cdata); } @@ -322,7 +320,7 @@ gst_d3d12_av1_dec_output_picture (GstDxvaAV1Decoder * decoder, void gst_d3d12_av1_dec_register (GstPlugin * plugin, GstD3D12Device * device, - ID3D12VideoDevice * video_device, guint rank) + ID3D12VideoDevice * video_device, guint rank, gboolean d3d11_interop) { GType type; gchar *type_name; @@ -343,12 +341,14 @@ gst_d3d12_av1_dec_register (GstPlugin * plugin, GstD3D12Device * device, GST_DEBUG_CATEGORY_INIT (gst_d3d12_av1_dec_debug, "d3d12av1dec", 0, "d3d12av1dec"); - type_info.class_data = - gst_d3d12_decoder_check_feature_support (device, video_device, + auto cdata = gst_d3d12_decoder_check_feature_support (device, video_device, GST_DXVA_CODEC_AV1); - if (!type_info.class_data) + if (!cdata) return; + cdata->subclass_data.d3d11_interop = d3d11_interop; + type_info.class_data = cdata; + type_name = g_strdup ("GstD3D12AV1Dec"); feature_name = g_strdup ("d3d12av1dec"); diff --git a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12av1dec.h b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12av1dec.h index 7d977ddb8e..2f6e3e36b9 100644 --- a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12av1dec.h +++ b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12av1dec.h @@ -26,7 +26,8 @@ G_BEGIN_DECLS void gst_d3d12_av1_dec_register (GstPlugin * plugin, GstD3D12Device * device, ID3D12VideoDevice * video_device, - guint rank); + guint rank, + gboolean d3d11_interop); G_END_DECLS diff --git a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12decoder.cpp b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12decoder.cpp index 6a9707c8cb..593e73c77e 100644 --- a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12decoder.cpp +++ b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12decoder.cpp @@ -21,6 +21,8 @@ #include #endif +#include "gstd3d12plugin-config.h" + #include "gstd3d12decoder.h" #include "gstd3d12decodercpbpool.h" #include @@ -38,6 +40,12 @@ #include #include +#ifdef HAVE_GST_D3D11 +#include +#include +#include +#endif + #ifndef GST_DISABLE_GST_DEBUG #define GST_CAT_DEFAULT ensure_debug_category() static GstDebugCategory * @@ -210,6 +218,7 @@ enum GstD3D12DecoderOutputType GST_D3D12_DECODER_OUTPUT_UNKNOWN = 0, GST_D3D12_DECODER_OUTPUT_SYSTEM = (1 << 0), GST_D3D12_DECODER_OUTPUT_D3D12 = (1 << 1), + GST_D3D12_DECODER_OUTPUT_D3D11 = (1 << 2), }; DEFINE_ENUM_FLAG_OPERATORS (GstD3D12DecoderOutputType); @@ -226,6 +235,15 @@ struct DecoderCmdData /* Fence to wait at command record thread */ UINT64 fence_val = 0; + +#ifdef HAVE_GST_D3D11 + ComPtr device11_5; + ComPtr context11_4; + ComPtr fence11; + ComPtr fence12; + + UINT64 fence_val_11 = 0; +#endif }; struct DecoderOutputData @@ -355,6 +373,11 @@ struct _GstD3D12Decoder GstDxvaCodec codec; GstD3D12Device *device; gint64 adapter_luid; + gboolean d3d11_interop; + +#ifdef HAVE_GST_D3D11 + GstD3D11Device *device11; +#endif GstD3D12DecoderPrivate *priv; }; @@ -385,6 +408,9 @@ gst_d3d12_decoder_finalize (GObject * object) auto self = GST_D3D12_DECODER (object); gst_clear_object (&self->device); +#ifdef HAVE_GST_D3D11 + gst_clear_object (&self->device11); +#endif delete self->priv; @@ -392,16 +418,16 @@ gst_d3d12_decoder_finalize (GObject * object) } GstD3D12Decoder * -gst_d3d12_decoder_new (GstDxvaCodec codec, gint64 adapter_luid) +gst_d3d12_decoder_new (const GstD3D12DecoderSubClassData * cdata) { GstD3D12Decoder *self; - g_return_val_if_fail (codec > GST_DXVA_CODEC_NONE, nullptr); - g_return_val_if_fail (codec < GST_DXVA_CODEC_LAST, nullptr); + g_return_val_if_fail (cdata, nullptr); self = (GstD3D12Decoder *) g_object_new (GST_TYPE_D3D12_DECODER, nullptr); - self->codec = codec; - self->adapter_luid = adapter_luid; + self->codec = cdata->codec; + self->adapter_luid = cdata->adapter_luid; + self->d3d11_interop = cdata->d3d11_interop; return self; } @@ -409,13 +435,17 @@ gst_d3d12_decoder_new (GstDxvaCodec codec, gint64 adapter_luid) gboolean gst_d3d12_decoder_open (GstD3D12Decoder * decoder, GstElement * element) { - if (!gst_d3d12_ensure_element_data_for_adapter_luid (element, - decoder->adapter_luid, &decoder->device)) { - GST_ERROR_OBJECT (element, "Cannot create d3d12device"); - return FALSE; + auto priv = decoder->priv; + + { + std::lock_guard < std::recursive_mutex > lk (priv->context_lock); + if (!gst_d3d12_ensure_element_data_for_adapter_luid (element, + decoder->adapter_luid, &decoder->device)) { + GST_ERROR_OBJECT (element, "Cannot create d3d12device"); + return FALSE; + } } - auto priv = decoder->priv; auto cmd = std::make_unique < DecoderCmdData > (); HRESULT hr; @@ -1289,6 +1319,245 @@ gst_d3d12_decoder_can_direct_render (GstD3D12Decoder * self, return TRUE; } +static GstFlowReturn +gst_d3d12_decoder_copy_output_12 (GstD3D12Decoder * self, GstBuffer * srcbuf, + ID3D12Resource * src, D3D12_TEXTURE_COPY_LOCATION dst[2], + D3D12_COMMAND_LIST_TYPE cmd_type, guint64 * fence_val) +{ + auto priv = self->priv; + D3D12_BOX src_box[2]; + std::vector < GstD3D12CopyTextureRegionArgs > copy_args; + + for (guint i = 0; i < 2; i++) { + GstD3D12CopyTextureRegionArgs args; + memset (&args, 0, sizeof (args)); + + args.src = CD3DX12_TEXTURE_COPY_LOCATION (src, i); + args.dst = dst[i]; + + /* FIXME: only 4:2:0 */ + if (i == 0) { + src_box[i].left = GST_ROUND_UP_2 (priv->session->crop_x); + src_box[i].top = GST_ROUND_UP_2 (priv->session->crop_y); + src_box[i].right = GST_ROUND_UP_2 (priv->session->crop_x + + priv->session->output_info.width); + src_box[i].bottom = + GST_ROUND_UP_2 (priv->session->crop_y + + priv->session->output_info.height); + } else { + src_box[i].left = GST_ROUND_UP_2 (priv->session->crop_x) / 2; + src_box[i].top = GST_ROUND_UP_2 (priv->session->crop_y) / 2; + src_box[i].right = + GST_ROUND_UP_2 (priv->session->crop_x + + priv->session->output_info.width) / 2; + src_box[i].bottom = + GST_ROUND_UP_2 (priv->session->crop_y + + priv->session->output_info.height) / 2; + } + + src_box[i].front = 0; + src_box[i].back = 1; + + args.src_box = &src_box[i]; + copy_args.push_back (args); + } + + GstD3D12FenceData *fence_data = nullptr; + if (cmd_type != D3D12_COMMAND_LIST_TYPE_COPY) { + gst_d3d12_fence_data_pool_acquire (priv->fence_data_pool, &fence_data); + gst_d3d12_fence_data_push (fence_data, + FENCE_NOTIFY_MINI_OBJECT (gst_buffer_ref (srcbuf))); + } + + guint64 copy_fence_val = 0; + auto copy_ret = gst_d3d12_device_copy_texture_region (self->device, + copy_args.size (), copy_args.data (), fence_data, 0, nullptr, nullptr, + cmd_type, ©_fence_val); + if (!copy_ret) { + GST_ERROR_OBJECT (self, "Couldn't copy decoded texture to output"); + gst_clear_d3d12_fence_data (&fence_data); + return GST_FLOW_ERROR; + } + + if (fence_val) + *fence_val = copy_fence_val; + + return GST_FLOW_OK; +} + +static GstFlowReturn +gst_d3d12_decoder_copy_output (GstD3D12Decoder * self, GstBuffer * src_buf, + GstBuffer * dst_buf) +{ + auto priv = self->priv; + auto session = priv->session.get (); + + auto in_dmem = (GstD3D12Memory *) gst_buffer_peek_memory (src_buf, 0); + auto out_mem = gst_buffer_peek_memory (dst_buf, 0); + if (gst_is_d3d12_memory (out_mem)) { + auto out_dmem = GST_D3D12_MEMORY_CAST (out_mem); + if (gst_d3d12_device_is_equal (out_dmem->device, self->device)) { + D3D12_TEXTURE_COPY_LOCATION dst_location[2]; + UINT out_subresource[2]; + guint64 copy_fence_val; + + auto in_resource = gst_d3d12_memory_get_resource_handle (in_dmem); + auto out_resource = gst_d3d12_memory_get_resource_handle (out_dmem); + gst_d3d12_memory_get_subresource_index (out_dmem, 0, &out_subresource[0]); + gst_d3d12_memory_get_subresource_index (out_dmem, 1, &out_subresource[1]); + + dst_location[0] = CD3DX12_TEXTURE_COPY_LOCATION (out_resource, + out_subresource[0]); + dst_location[1] = CD3DX12_TEXTURE_COPY_LOCATION (out_resource, + out_subresource[1]); + + auto ret = gst_d3d12_decoder_copy_output_12 (self, src_buf, in_resource, + dst_location, D3D12_COMMAND_LIST_TYPE_DIRECT, ©_fence_val); + if (ret != GST_FLOW_OK) + return ret; + + auto fence = gst_d3d12_device_get_fence_handle (self->device, + D3D12_COMMAND_LIST_TYPE_DIRECT); + gst_d3d12_memory_set_fence (out_dmem, fence, copy_fence_val, FALSE); + + GST_MINI_OBJECT_FLAG_SET (out_dmem, + GST_D3D12_MEMORY_TRANSFER_NEED_DOWNLOAD); + GST_MINI_OBJECT_FLAG_UNSET (out_dmem, + GST_D3D12_MEMORY_TRANSFER_NEED_UPLOAD); + + GST_TRACE_OBJECT (self, "d3d12 copy done"); + + return GST_FLOW_OK; + } + } +#ifdef HAVE_GST_D3D11 + else if (session->output_type == GST_D3D12_DECODER_OUTPUT_D3D11 && + self->d3d11_interop && gst_is_d3d11_memory (out_mem)) { + auto out_dmem = GST_D3D11_MEMORY_CAST (out_mem); + if (out_dmem->device == self->device11) { + GstMapInfo out_map; + auto device11 = gst_d3d11_device_get_device_handle (self->device11); + auto in_texture11 = + gst_d3d12_memory_get_d3d11_texture (in_dmem, device11); + + if (!in_texture11) { + GST_ERROR_OBJECT (self, + "Couldn't get d3d11 texture from decoded texture"); + return GST_FLOW_ERROR; + } + + if (!gst_memory_map (out_mem, &out_map, + (GstMapFlags) (GST_MAP_WRITE | GST_MAP_D3D11))) { + GST_ERROR_OBJECT (self, "Couldn't map output d3d11 memory"); + return GST_FLOW_ERROR; + } + + HRESULT hr; + { + GstD3D11DeviceLockGuard device11_lk (self->device11); + D3D11_BOX src_box = { }; + src_box.left = GST_ROUND_UP_2 (session->crop_x); + src_box.top = GST_ROUND_UP_2 (session->crop_y); + src_box.right = GST_ROUND_UP_2 (session->crop_x + + session->output_info.width); + src_box.bottom = GST_ROUND_UP_2 (session->crop_y + + session->output_info.height); + src_box.front = 0; + src_box.back = 1; + + auto out_texture11 = gst_d3d11_memory_get_resource_handle (out_dmem); + auto out_subresource = + gst_d3d11_memory_get_subresource_index (out_dmem); + + priv->cmd->context11_4->CopySubresourceRegion (out_texture11, + out_subresource, 0, 0, 0, in_texture11, 0, &src_box); + priv->cmd->fence_val_11++; + hr = priv->cmd->context11_4->Signal (priv->cmd->fence11.Get (), + priv->cmd->fence_val_11); + } + + gst_memory_unmap (out_mem, &out_map); + + if (!gst_d3d11_result (hr, self->device11)) { + GST_ERROR_OBJECT (self, "Signal failed"); + return GST_FLOW_ERROR; + } + + /* Set d3d11 device signalled fence to d3d12 memory. + * d3d12 buffer pool or allocator will wait for this fence + * to keep resource alive if it's still being used by d3d11 */ + gst_d3d12_memory_set_fence (in_dmem, priv->cmd->fence12.Get (), + priv->cmd->fence_val_11, FALSE); + + GST_TRACE_OBJECT (self, "Copy done via d3d11 interop"); + + return GST_FLOW_OK; + } + } +#endif + + if (!gst_d3d12_decoder_ensure_staging_texture (self)) { + GST_ERROR_OBJECT (self, "Couldn't allocate staging texture"); + return GST_FLOW_ERROR; + } + + auto in_resource = gst_d3d12_memory_get_resource_handle (in_dmem); + D3D12_TEXTURE_COPY_LOCATION dst_location[2]; + + dst_location[0] = CD3DX12_TEXTURE_COPY_LOCATION (session->staging.Get (), + session->layout[0]); + dst_location[1] = CD3DX12_TEXTURE_COPY_LOCATION (session->staging.Get (), + session->layout[1]); + + guint64 copy_fence_val; + auto ret = gst_d3d12_decoder_copy_output_12 (self, src_buf, in_resource, + dst_location, D3D12_COMMAND_LIST_TYPE_COPY, ©_fence_val); + if (ret != GST_FLOW_OK) { + GST_ERROR_OBJECT (self, "Couldn't download to staging buffer"); + return ret; + } + + auto hr = gst_d3d12_device_fence_wait (self->device, + D3D12_COMMAND_LIST_TYPE_COPY, copy_fence_val); + if (!gst_d3d12_result (hr, self->device)) { + GST_ERROR_OBJECT (self, "Couldn't wait for fence"); + return GST_FLOW_ERROR; + } + + guint8 *map_data; + GstVideoFrame vframe; + hr = session->staging->Map (0, nullptr, (void **) &map_data); + if (!gst_d3d12_result (hr, self->device)) { + GST_ERROR_OBJECT (self, "Couldn't map staging texture"); + return GST_FLOW_ERROR; + } + + if (!gst_video_frame_map (&vframe, + &session->output_info, dst_buf, GST_MAP_WRITE)) { + GST_ERROR_OBJECT (self, "Couldn't map output buffer"); + session->staging->Unmap (0, nullptr); + return GST_FLOW_ERROR; + } + + for (guint i = 0; i < GST_VIDEO_FRAME_N_PLANES (&vframe); i++) { + guint8 *src_data = map_data + session->layout[i].Offset; + guint8 *dst_data = (guint8 *) GST_VIDEO_FRAME_PLANE_DATA (&vframe, i); + gint width = GST_VIDEO_FRAME_COMP_WIDTH (&vframe, i) * + GST_VIDEO_FRAME_COMP_PSTRIDE (&vframe, i); + + for (gint j = 0; j < GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, i); j++) { + memcpy (dst_data, src_data, width); + dst_data += GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, i); + src_data += session->layout[i].Footprint.RowPitch; + } + } + + session->staging->Unmap (0, nullptr); + gst_video_frame_unmap (&vframe); + + return GST_FLOW_OK; +} + static GstFlowReturn gst_d3d12_decoder_process_output (GstD3D12Decoder * self, GstVideoDecoder * videodec, GstVideoCodecFrame * frame, @@ -1297,10 +1566,6 @@ gst_d3d12_decoder_process_output (GstD3D12Decoder * self, { GstFlowReturn ret = GST_FLOW_ERROR; GstBuffer *buffer; - GstD3D12Memory *dmem; - ID3D12Resource *resource; - UINT subresource[2]; - HRESULT hr; bool attach_crop_meta = false; auto priv = self->priv; @@ -1337,153 +1602,30 @@ gst_d3d12_decoder_process_output (GstD3D12Decoder * self, buffer = decoder_pic->output_buffer ? decoder_pic->output_buffer : decoder_pic->buffer; - dmem = (GstD3D12Memory *) gst_buffer_peek_memory (buffer, 0); priv->session->lock.lock (); if (gst_d3d12_decoder_can_direct_render (self, videodec, decoder_pic->buffer, display_width, display_height)) { GST_LOG_OBJECT (self, "Outputting without copy"); - GST_MINI_OBJECT_FLAG_SET (dmem, GST_D3D12_MEMORY_TRANSFER_NEED_DOWNLOAD); - GST_MINI_OBJECT_FLAG_UNSET (dmem, GST_D3D12_MEMORY_TRANSFER_NEED_UPLOAD); + auto mem = gst_buffer_peek_memory (buffer, 0); + GST_MINI_OBJECT_FLAG_SET (mem, GST_D3D12_MEMORY_TRANSFER_NEED_DOWNLOAD); + GST_MINI_OBJECT_FLAG_UNSET (mem, GST_D3D12_MEMORY_TRANSFER_NEED_UPLOAD); if (priv->session->need_crop) attach_crop_meta = true; frame->output_buffer = gst_buffer_ref (buffer); } else { - ID3D12Resource *out_resource = nullptr; - UINT out_subresource[2]; - ret = gst_video_decoder_allocate_output_frame (videodec, frame); if (ret != GST_FLOW_OK) { GST_ERROR_OBJECT (videodec, "Couldn't allocate output buffer"); goto error; } - auto out_mem = gst_buffer_peek_memory (frame->output_buffer, 0); - if (gst_is_d3d12_memory (out_mem)) { - auto out_dmem = GST_D3D12_MEMORY_CAST (out_mem); - if (gst_d3d12_device_is_equal (dmem->device, self->device)) { - out_resource = gst_d3d12_memory_get_resource_handle (out_dmem); - gst_d3d12_memory_get_subresource_index (out_dmem, 0, - &out_subresource[0]); - gst_d3d12_memory_get_subresource_index (out_dmem, 1, - &out_subresource[1]); - - GST_MINI_OBJECT_FLAG_SET (out_dmem, - GST_D3D12_MEMORY_TRANSFER_NEED_DOWNLOAD); - GST_MINI_OBJECT_FLAG_UNSET (out_dmem, - GST_D3D12_MEMORY_TRANSFER_NEED_UPLOAD); - } - } - - if (!out_resource && !gst_d3d12_decoder_ensure_staging_texture (self)) { - GST_ERROR_OBJECT (videodec, "Couldn't allocate staging texture"); - ret = GST_FLOW_ERROR; + ret = gst_d3d12_decoder_copy_output (self, buffer, frame->output_buffer); + if (ret != GST_FLOW_OK) goto error; - } - - resource = gst_d3d12_memory_get_resource_handle (dmem); - - gst_d3d12_memory_get_subresource_index (dmem, 0, &subresource[0]); - gst_d3d12_memory_get_subresource_index (dmem, 1, &subresource[1]); - - /* Copy texture to staging */ - D3D12_BOX src_box[2]; - std::vector < GstD3D12CopyTextureRegionArgs > copy_args; - - for (guint i = 0; i < 2; i++) { - GstD3D12CopyTextureRegionArgs args; - memset (&args, 0, sizeof (args)); - - args.src = CD3DX12_TEXTURE_COPY_LOCATION (resource, subresource[i]); - - if (out_resource) { - args.dst = - CD3DX12_TEXTURE_COPY_LOCATION (out_resource, out_subresource[i]); - } else { - args.dst = - CD3DX12_TEXTURE_COPY_LOCATION (priv->session->staging.Get (), - priv->session->layout[i]); - } - - /* FIXME: only 4:2:0 */ - if (i == 0) { - src_box[i].left = GST_ROUND_UP_2 (priv->session->crop_x); - src_box[i].top = GST_ROUND_UP_2 (priv->session->crop_y); - src_box[i].right = GST_ROUND_UP_2 (priv->session->crop_x + - priv->session->output_info.width); - src_box[i].bottom = - GST_ROUND_UP_2 (priv->session->crop_y + - priv->session->output_info.height); - } else { - src_box[i].left = GST_ROUND_UP_2 (priv->session->crop_x) / 2; - src_box[i].top = GST_ROUND_UP_2 (priv->session->crop_y) / 2; - src_box[i].right = - GST_ROUND_UP_2 (priv->session->crop_x + - priv->session->output_info.width) / 2; - src_box[i].bottom = - GST_ROUND_UP_2 (priv->session->crop_y + - priv->session->output_info.height) / 2; - } - - src_box[i].front = 0; - src_box[i].back = 1; - - args.src_box = &src_box[i]; - copy_args.push_back (args); - } - - guint64 copy_fence_val = 0; - GstD3D12FenceData *fence_data = nullptr; - D3D12_COMMAND_LIST_TYPE queue_type = D3D12_COMMAND_LIST_TYPE_COPY; - if (out_resource) { - queue_type = D3D12_COMMAND_LIST_TYPE_DIRECT; - gst_d3d12_fence_data_pool_acquire (priv->fence_data_pool, &fence_data); - gst_d3d12_fence_data_push (fence_data, - FENCE_NOTIFY_MINI_OBJECT (gst_buffer_ref (buffer))); - } - - gst_d3d12_device_copy_texture_region (self->device, copy_args.size (), - copy_args.data (), fence_data, 0, nullptr, nullptr, queue_type, - ©_fence_val); - auto fence = gst_d3d12_device_get_fence_handle (self->device, queue_type); - - if (!out_resource) { - guint8 *map_data; - GstVideoFrame vframe; - - gst_d3d12_device_fence_wait (self->device, queue_type, copy_fence_val); - - hr = priv->session->staging->Map (0, nullptr, (void **) &map_data); - if (!gst_d3d12_result (hr, self->device)) { - ret = GST_FLOW_ERROR; - goto error; - } - - gst_video_frame_map (&vframe, - &priv->session->output_info, frame->output_buffer, GST_MAP_WRITE); - - for (guint i = 0; i < GST_VIDEO_FRAME_N_PLANES (&vframe); i++) { - guint8 *src = map_data + priv->session->layout[i].Offset; - guint8 *dst = (guint8 *) GST_VIDEO_FRAME_PLANE_DATA (&vframe, i); - gint width = GST_VIDEO_FRAME_COMP_WIDTH (&vframe, i) * - GST_VIDEO_FRAME_COMP_PSTRIDE (&vframe, i); - - for (gint j = 0; j < GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, i); j++) { - memcpy (dst, src, width); - dst += GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, i); - src += priv->session->layout[i].Footprint.RowPitch; - } - } - - priv->session->staging->Unmap (0, nullptr); - gst_video_frame_unmap (&vframe); - } else { - gst_d3d12_buffer_set_fence (frame->output_buffer, - fence, copy_fence_val, FALSE); - } } priv->session->lock.unlock (); @@ -1646,6 +1788,12 @@ gst_d3d12_decoder_negotiate (GstD3D12Decoder * decoder, GST_CAPS_FEATURE_MEMORY_D3D12_MEMORY)) { allowed_types |= GST_D3D12_DECODER_OUTPUT_D3D12; } +#ifdef HAVE_GST_D3D11 + if (gst_caps_features_contains (features, + GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY)) { + allowed_types |= GST_D3D12_DECODER_OUTPUT_D3D11; + } +#endif } } gst_clear_caps (&peer_caps); @@ -1685,6 +1833,57 @@ gst_d3d12_decoder_negotiate (GstD3D12Decoder * decoder, g_clear_pointer (&priv->session->output_state, gst_video_codec_state_unref); priv->session->output_state = state; +#ifdef HAVE_GST_D3D11 + /* Try d3d11 only if downstream does not support d3d12 but does d3d11, + * otherwise decoder will create unnecessary d3d11 device */ + if ((allowed_types & GST_D3D12_DECODER_OUTPUT_D3D11) == + GST_D3D12_DECODER_OUTPUT_D3D11 && + (allowed_types & GST_D3D12_DECODER_OUTPUT_D3D12) != + GST_D3D12_DECODER_OUTPUT_D3D12) { + auto elem = GST_ELEMENT (videodec); + if (decoder->d3d11_interop) { + if (gst_d3d11_ensure_element_data_for_adapter_luid (elem, + decoder->adapter_luid, &decoder->device11)) { + if (!priv->cmd->device11_5) { + auto device11 = + gst_d3d11_device_get_device_handle (decoder->device11); + device11->QueryInterface (IID_PPV_ARGS (&priv->cmd->device11_5)); + } + + if (priv->cmd->device11_5 && !priv->cmd->context11_4) { + ComPtr < ID3D11DeviceContext > context11; + ComPtr < ID3D11DeviceContext4 > context11_4; + priv->cmd->device11_5->GetImmediateContext (&context11); + context11.As (&priv->cmd->context11_4); + } + + if (priv->cmd->context11_4 && !priv->cmd->fence11) { + priv->cmd->device11_5->CreateFence (0, D3D11_FENCE_FLAG_SHARED, + IID_PPV_ARGS (&priv->cmd->fence11)); + } + + if (priv->cmd->fence11 && !priv->cmd->fence12) { + HANDLE handle; + auto hr = priv->cmd->fence11->CreateSharedHandle (nullptr, + GENERIC_ALL, nullptr, &handle); + if (SUCCEEDED (hr)) { + priv->cmd->device->OpenSharedHandle (handle, + IID_PPV_ARGS (&priv->cmd->fence12)); + CloseHandle (handle); + } + } + + if (!priv->cmd->fence12) + allowed_types &= ~GST_D3D12_DECODER_OUTPUT_D3D11; + } else { + allowed_types &= ~GST_D3D12_DECODER_OUTPUT_D3D11; + } + } else if (!gst_d3d11_ensure_element_data (elem, -1, &decoder->device11)) { + allowed_types &= ~GST_D3D12_DECODER_OUTPUT_D3D11; + } + } +#endif + auto prev_output_type = priv->session->output_type; if (prev_output_type != GST_D3D12_DECODER_OUTPUT_UNKNOWN && (prev_output_type & allowed_types) == prev_output_type) { @@ -1692,14 +1891,25 @@ gst_d3d12_decoder_negotiate (GstD3D12Decoder * decoder, } else { if ((allowed_types & GST_D3D12_DECODER_OUTPUT_D3D12) != 0) priv->session->output_type = GST_D3D12_DECODER_OUTPUT_D3D12; + else if ((allowed_types & GST_D3D12_DECODER_OUTPUT_D3D11) != 0) + priv->session->output_type = GST_D3D12_DECODER_OUTPUT_D3D11; else priv->session->output_type = GST_D3D12_DECODER_OUTPUT_SYSTEM; } - if (priv->session->output_type == GST_D3D12_DECODER_OUTPUT_D3D12) { - gst_caps_set_features (state->caps, 0, - gst_caps_features_new_single (GST_CAPS_FEATURE_MEMORY_D3D12_MEMORY)); - priv->session->output_type = GST_D3D12_DECODER_OUTPUT_D3D12; + switch (priv->session->output_type) { + case GST_D3D12_DECODER_OUTPUT_D3D12: + gst_caps_set_features (state->caps, 0, + gst_caps_features_new_single (GST_CAPS_FEATURE_MEMORY_D3D12_MEMORY)); + break; +#ifdef HAVE_GST_D3D11 + case GST_D3D12_DECODER_OUTPUT_D3D11: + gst_caps_set_features (state->caps, 0, + gst_caps_features_new_single (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY)); + break; +#endif + default: + break; } GST_DEBUG_OBJECT (decoder, "Selected output type %d", @@ -1756,13 +1966,28 @@ gst_d3d12_decoder_decide_allocation (GstD3D12Decoder * decoder, "Downstream pool is not d3d12, will create new one"); gst_clear_object (&pool); } else { - GstD3D12BufferPool *dpool = GST_D3D12_BUFFER_POOL (pool); + auto dpool = GST_D3D12_BUFFER_POOL (pool); if (!gst_d3d12_device_is_equal (dpool->device, decoder->device)) { GST_DEBUG_OBJECT (videodec, "Different device, will create new one"); gst_clear_object (&pool); } } } +#ifdef HAVE_GST_D3D11 + if (priv->session->output_type == GST_D3D12_DECODER_OUTPUT_D3D11) { + if (!GST_IS_D3D12_BUFFER_POOL (pool)) { + GST_DEBUG_OBJECT (videodec, + "Downstream pool is not d3d11, will create new one"); + gst_clear_object (&pool); + } else if (decoder->d3d11_interop) { + auto dpool = GST_D3D11_BUFFER_POOL (pool); + if (dpool->device != decoder->device11) { + GST_DEBUG_OBJECT (videodec, "Different device, will create new one"); + gst_clear_object (&pool); + } + } + } +#endif } if (!pool) { @@ -1770,6 +1995,11 @@ gst_d3d12_decoder_decide_allocation (GstD3D12Decoder * decoder, case GST_D3D12_DECODER_OUTPUT_D3D12: pool = gst_d3d12_buffer_pool_new (decoder->device); break; +#ifdef HAVE_GST_D3D11 + case GST_D3D12_DECODER_OUTPUT_D3D11: + pool = gst_d3d11_buffer_pool_new (decoder->device11); + break; +#endif default: pool = gst_video_buffer_pool_new (); break; @@ -1783,13 +2013,12 @@ gst_d3d12_decoder_decide_allocation (GstD3D12Decoder * decoder, gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META); if (priv->session->output_type == GST_D3D12_DECODER_OUTPUT_D3D12) { - GstD3D12AllocationParams *params; GstVideoAlignment align; gint width, height; gst_video_alignment_reset (&align); - params = gst_buffer_pool_config_get_d3d12_allocation_params (config); + auto params = gst_buffer_pool_config_get_d3d12_allocation_params (config); if (!params) { params = gst_d3d12_allocation_params_new (decoder->device, &vinfo, GST_D3D12_ALLOCATION_FLAG_DEFAULT, @@ -1811,14 +2040,20 @@ gst_d3d12_decoder_decide_allocation (GstD3D12Decoder * decoder, gst_d3d12_allocation_params_alignment (params, &align); gst_buffer_pool_config_set_d3d12_allocation_params (config, params); gst_d3d12_allocation_params_free (params); - - - GST_DEBUG_OBJECT (videodec, "Downstream min buffres: %d", min); - - /* We will not use downstream pool for decoding, and therefore preallocation - * is unnecessary. So, Non-zero min buffer will be a waste of GPU memory */ - min = 0; } +#ifdef HAVE_GST_D3D11 + else if (priv->session->output_type == GST_D3D12_DECODER_OUTPUT_D3D11) { + auto params = gst_buffer_pool_config_get_d3d11_allocation_params (config); + if (!params) { + params = gst_d3d11_allocation_params_new (decoder->device11, &vinfo, + GST_D3D11_ALLOCATION_FLAG_DEFAULT, + D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE, 0); + } + + gst_buffer_pool_config_set_d3d11_allocation_params (config, params); + gst_d3d11_allocation_params_free (params); + } +#endif gst_buffer_pool_set_config (pool, config); /* d3d12 buffer pool will update buffer size based on allocated texture, @@ -1850,6 +2085,15 @@ gst_d3d12_decoder_set_context (GstD3D12Decoder * decoder, GstElement * element, std::lock_guard < std::recursive_mutex > lk (priv->context_lock); gst_d3d12_handle_set_context_for_adapter_luid (element, context, decoder->adapter_luid, &decoder->device); +#ifdef HAVE_GST_D3D11 + if (decoder->d3d11_interop) { + gst_d3d11_handle_set_context_for_adapter_luid (element, + context, decoder->adapter_luid, &decoder->device11); + } else { + /* Since we will do system copy, accept any device */ + gst_d3d11_handle_set_context (element, context, -1, &decoder->device11); + } +#endif } gboolean @@ -1861,6 +2105,11 @@ gst_d3d12_decoder_handle_query (GstD3D12Decoder * decoder, GstElement * element, auto priv = decoder->priv; std::lock_guard < std::recursive_mutex > lk (priv->context_lock); +#ifdef HAVE_GST_D3D11 + if (gst_d3d11_handle_context_query (element, query, decoder->device11)) + return TRUE; +#endif + return gst_d3d12_handle_context_query (element, query, decoder->device); } @@ -1871,14 +2120,6 @@ enum PROP_DECODER_VENDOR_ID, }; -struct _GstD3D12DecoderClassData -{ - GstD3D12DecoderSubClassData subclass_data; - GstCaps *sink_caps; - GstCaps *src_caps; - gchar *description; -}; - static void gst_d3d12_decoder_get_profiles (const GUID & profile, std::vector < std::string > &list) @@ -2102,11 +2343,17 @@ gst_d3d12_decoder_check_feature_support (GstD3D12Device * device, } /* *INDENT-ON* */ - GstCaps *sink_caps = gst_caps_from_string (sink_caps_string.c_str ()); - GstCaps *raw_caps = gst_caps_from_string (src_caps_string.c_str ()); - GstCaps *src_caps = gst_caps_copy (raw_caps); + auto sink_caps = gst_caps_from_string (sink_caps_string.c_str ()); + auto raw_caps = gst_caps_from_string (src_caps_string.c_str ()); + auto src_caps = gst_caps_copy (raw_caps); gst_caps_set_features_simple (src_caps, gst_caps_features_new_single (GST_CAPS_FEATURE_MEMORY_D3D12_MEMORY)); +#ifdef HAVE_GST_D3D11 + auto d3d11_caps = gst_caps_copy (raw_caps); + gst_caps_set_features_simple (d3d11_caps, + gst_caps_features_new_single (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY)); + gst_caps_append (src_caps, d3d11_caps); +#endif gst_caps_append (src_caps, raw_caps); gint max_res = MAX (max_resolution.width, max_resolution.height); diff --git a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12decoder.h b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12decoder.h index f9788a5301..b854a60f0e 100644 --- a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12decoder.h +++ b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12decoder.h @@ -31,14 +31,21 @@ G_BEGIN_DECLS G_DECLARE_FINAL_TYPE (GstD3D12Decoder, gst_d3d12_decoder, GST, D3D12_DECODER, GstObject); -typedef struct _GstD3D12DecoderClassData GstD3D12DecoderClassData; - struct GstD3D12DecoderSubClassData { GstDxvaCodec codec; gint64 adapter_luid; guint device_id; guint vendor_id; + gboolean d3d11_interop; +}; + +struct GstD3D12DecoderClassData +{ + GstD3D12DecoderSubClassData subclass_data; + GstCaps *sink_caps; + GstCaps *src_caps; + gchar *description; }; #define GST_D3D12_DECODER_DEFINE_TYPE(ModuleObjName,module_obj_name,MODULE,OBJ_NAME,ParentName) \ @@ -100,8 +107,7 @@ struct GstD3D12DecoderSubClassData static GstFlowReturn module_obj_name##_duplicate_picture (ParentName * decoder, \ GstCodecPicture * src, GstCodecPicture * dst); -GstD3D12Decoder * gst_d3d12_decoder_new (GstDxvaCodec codec, - gint64 adapter_luid); +GstD3D12Decoder * gst_d3d12_decoder_new (const GstD3D12DecoderSubClassData * cdata); gboolean gst_d3d12_decoder_open (GstD3D12Decoder * decoder, GstElement * element); diff --git a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12h264dec.cpp b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12h264dec.cpp index 3f5a15d625..46a01ea876 100644 --- a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12h264dec.cpp +++ b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12h264dec.cpp @@ -95,17 +95,15 @@ gst_d3d12_h264_dec_class_init (GstD3D12H264DecClass * klass, gpointer data) static void gst_d3d12_h264_dec_init (GstD3D12H264Dec * self) { - GstD3D12H264DecClass *klass = GST_D3D12_H264_DEC_GET_CLASS (self); - GstD3D12DecoderSubClassData *cdata = &klass->class_data; + auto klass = GST_D3D12_H264_DEC_GET_CLASS (self); - self->decoder = gst_d3d12_decoder_new (GST_DXVA_CODEC_H264, - cdata->adapter_luid); + self->decoder = gst_d3d12_decoder_new (&klass->class_data); } static void gst_d3d12_h264_dec_finalize (GObject * object) { - GstD3D12H264Dec *self = GST_D3D12_H264_DEC (object); + auto self = GST_D3D12_H264_DEC (object); gst_object_unref (self->decoder); @@ -116,8 +114,8 @@ static void gst_d3d12_h264_dec_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { - GstD3D12H264DecClass *klass = GST_D3D12_H264_DEC_GET_CLASS (object); - GstD3D12DecoderSubClassData *cdata = &klass->class_data; + auto klass = GST_D3D12_H264_DEC_GET_CLASS (object); + auto cdata = &klass->class_data; gst_d3d12_decoder_proxy_get_property (object, prop_id, value, pspec, cdata); } @@ -125,7 +123,7 @@ gst_d3d12_h264_dec_get_property (GObject * object, guint prop_id, static void gst_d3d12_h264_dec_set_context (GstElement * element, GstContext * context) { - GstD3D12H264Dec *self = GST_D3D12_H264_DEC (element); + auto self = GST_D3D12_H264_DEC (element); gst_d3d12_decoder_set_context (self->decoder, element, context); @@ -322,7 +320,7 @@ gst_d3d12_h264_dec_output_picture (GstDxvaH264Decoder * decoder, void gst_d3d12_h264_dec_register (GstPlugin * plugin, GstD3D12Device * device, - ID3D12VideoDevice * video_device, guint rank) + ID3D12VideoDevice * video_device, guint rank, gboolean d3d11_interop) { GType type; gchar *type_name; @@ -343,12 +341,14 @@ gst_d3d12_h264_dec_register (GstPlugin * plugin, GstD3D12Device * device, GST_DEBUG_CATEGORY_INIT (gst_d3d12_h264_dec_debug, "d3d12h264dec", 0, "d3d12h264dec"); - type_info.class_data = - gst_d3d12_decoder_check_feature_support (device, video_device, + auto cdata = gst_d3d12_decoder_check_feature_support (device, video_device, GST_DXVA_CODEC_H264); - if (!type_info.class_data) + if (!cdata) return; + cdata->subclass_data.d3d11_interop = d3d11_interop; + type_info.class_data = cdata; + type_name = g_strdup ("GstD3D12H264Dec"); feature_name = g_strdup ("d3d12h264dec"); diff --git a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12h264dec.h b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12h264dec.h index afd8994c13..baf731dbe5 100644 --- a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12h264dec.h +++ b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12h264dec.h @@ -26,7 +26,8 @@ G_BEGIN_DECLS void gst_d3d12_h264_dec_register (GstPlugin * plugin, GstD3D12Device * device, ID3D12VideoDevice * video_device, - guint rank); + guint rank, + gboolean d3d11_interop); G_END_DECLS diff --git a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12h265dec.cpp b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12h265dec.cpp index 2074971fd9..8654c481c0 100644 --- a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12h265dec.cpp +++ b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12h265dec.cpp @@ -93,11 +93,9 @@ gst_d3d12_h265_dec_class_init (GstD3D12H265DecClass * klass, gpointer data) static void gst_d3d12_h265_dec_init (GstD3D12H265Dec * self) { - GstD3D12H265DecClass *klass = GST_D3D12_H265_DEC_GET_CLASS (self); - GstD3D12DecoderSubClassData *cdata = &klass->class_data; + auto klass = GST_D3D12_H265_DEC_GET_CLASS (self); - self->decoder = gst_d3d12_decoder_new (GST_DXVA_CODEC_H265, - cdata->adapter_luid); + self->decoder = gst_d3d12_decoder_new (&klass->class_data); } static void @@ -114,8 +112,8 @@ static void gst_d3d12_h265_dec_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { - GstD3D12H265DecClass *klass = GST_D3D12_H265_DEC_GET_CLASS (object); - GstD3D12DecoderSubClassData *cdata = &klass->class_data; + auto klass = GST_D3D12_H265_DEC_GET_CLASS (object); + auto cdata = &klass->class_data; gst_d3d12_decoder_proxy_get_property (object, prop_id, value, pspec, cdata); } @@ -311,7 +309,7 @@ gst_d3d12_h265_dec_output_picture (GstDxvaH265Decoder * decoder, void gst_d3d12_h265_dec_register (GstPlugin * plugin, GstD3D12Device * device, - ID3D12VideoDevice * video_device, guint rank) + ID3D12VideoDevice * video_device, guint rank, gboolean d3d11_interop) { GType type; gchar *type_name; @@ -332,12 +330,14 @@ gst_d3d12_h265_dec_register (GstPlugin * plugin, GstD3D12Device * device, GST_DEBUG_CATEGORY_INIT (gst_d3d12_h265_dec_debug, "d3d12h265dec", 0, "d3d12h265dec"); - type_info.class_data = - gst_d3d12_decoder_check_feature_support (device, video_device, + auto cdata = gst_d3d12_decoder_check_feature_support (device, video_device, GST_DXVA_CODEC_H265); - if (!type_info.class_data) + if (!cdata) return; + cdata->subclass_data.d3d11_interop = d3d11_interop; + type_info.class_data = cdata; + type_name = g_strdup ("GstD3D12H265Dec"); feature_name = g_strdup ("d3d12h265dec"); diff --git a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12h265dec.h b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12h265dec.h index 3de9de9260..d3c281850b 100644 --- a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12h265dec.h +++ b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12h265dec.h @@ -26,7 +26,8 @@ G_BEGIN_DECLS void gst_d3d12_h265_dec_register (GstPlugin * plugin, GstD3D12Device * device, ID3D12VideoDevice * video_device, - guint rank); + guint rank, + gboolean d3d11_interop); G_END_DECLS diff --git a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12mpeg2dec.cpp b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12mpeg2dec.cpp index 992b1e3372..3eba22054c 100644 --- a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12mpeg2dec.cpp +++ b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12mpeg2dec.cpp @@ -98,10 +98,8 @@ static void gst_d3d12_mpeg2_dec_init (GstD3D12Mpeg2Dec * self) { auto klass = GST_D3D12_MPEG2_DEC_GET_CLASS (self); - auto cdata = &klass->class_data; - self->decoder = gst_d3d12_decoder_new (GST_DXVA_CODEC_MPEG2, - cdata->adapter_luid); + self->decoder = gst_d3d12_decoder_new (&klass->class_data); gst_dxva_mpeg2_decoder_disable_postproc (GST_DXVA_MPEG2_DECODER (self)); } @@ -325,7 +323,7 @@ gst_d3d12_mpeg2_dec_output_picture (GstDxvaMpeg2Decoder * decoder, void gst_d3d12_mpeg2_dec_register (GstPlugin * plugin, GstD3D12Device * device, - ID3D12VideoDevice * video_device, guint rank) + ID3D12VideoDevice * video_device, guint rank, gboolean d3d11_interop) { GType type; gchar *type_name; @@ -346,12 +344,14 @@ gst_d3d12_mpeg2_dec_register (GstPlugin * plugin, GstD3D12Device * device, GST_DEBUG_CATEGORY_INIT (gst_d3d12_mpeg2_dec_debug, "d3d12mpeg2dec", 0, "d3d12mpeg2dec"); - type_info.class_data = - gst_d3d12_decoder_check_feature_support (device, video_device, + auto cdata = gst_d3d12_decoder_check_feature_support (device, video_device, GST_DXVA_CODEC_MPEG2); - if (!type_info.class_data) + if (!cdata) return; + cdata->subclass_data.d3d11_interop = d3d11_interop; + type_info.class_data = cdata; + type_name = g_strdup ("GstD3D12Mpeg2Dec"); feature_name = g_strdup ("d3d12mpeg2dec"); diff --git a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12mpeg2dec.h b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12mpeg2dec.h index 3eff1d3154..39380d99a7 100644 --- a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12mpeg2dec.h +++ b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12mpeg2dec.h @@ -26,7 +26,8 @@ G_BEGIN_DECLS void gst_d3d12_mpeg2_dec_register (GstPlugin * plugin, GstD3D12Device * device, ID3D12VideoDevice * video_device, - guint rank); + guint rank, + gboolean d3d11_interop); G_END_DECLS diff --git a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12vp8dec.cpp b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12vp8dec.cpp index a5be313a06..8be48ab6f6 100644 --- a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12vp8dec.cpp +++ b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12vp8dec.cpp @@ -94,10 +94,8 @@ static void gst_d3d12_vp8_dec_init (GstD3D12Vp8Dec * self) { auto klass = GST_D3D12_VP8_DEC_GET_CLASS (self); - auto cdata = &klass->class_data; - self->decoder = gst_d3d12_decoder_new (GST_DXVA_CODEC_VP8, - cdata->adapter_luid); + self->decoder = gst_d3d12_decoder_new (&klass->class_data); } static void @@ -311,7 +309,7 @@ gst_d3d12_vp8_dec_output_picture (GstDxvaVp8Decoder * decoder, void gst_d3d12_vp8_dec_register (GstPlugin * plugin, GstD3D12Device * device, - ID3D12VideoDevice * video_device, guint rank) + ID3D12VideoDevice * video_device, guint rank, gboolean d3d11_interop) { GType type; gchar *type_name; @@ -332,12 +330,14 @@ gst_d3d12_vp8_dec_register (GstPlugin * plugin, GstD3D12Device * device, GST_DEBUG_CATEGORY_INIT (gst_d3d12_vp8_dec_debug, "d3d12vp8dec", 0, "d3d12vp8dec"); - type_info.class_data = - gst_d3d12_decoder_check_feature_support (device, video_device, + auto cdata = gst_d3d12_decoder_check_feature_support (device, video_device, GST_DXVA_CODEC_VP8); - if (!type_info.class_data) + if (!cdata) return; + cdata->subclass_data.d3d11_interop = d3d11_interop; + type_info.class_data = cdata; + type_name = g_strdup ("GstD3D12Vp8Dec"); feature_name = g_strdup ("d3d12vp8dec"); diff --git a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12vp8dec.h b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12vp8dec.h index 3759de3195..3a1149dd43 100644 --- a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12vp8dec.h +++ b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12vp8dec.h @@ -26,7 +26,8 @@ G_BEGIN_DECLS void gst_d3d12_vp8_dec_register (GstPlugin * plugin, GstD3D12Device * device, ID3D12VideoDevice * video_device, - guint rank); + guint rank, + gboolean d3d11_interop); G_END_DECLS diff --git a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12vp9dec.cpp b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12vp9dec.cpp index 86e57258ca..55e3db8d39 100644 --- a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12vp9dec.cpp +++ b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12vp9dec.cpp @@ -95,11 +95,9 @@ gst_d3d12_vp9_dec_class_init (GstD3D12Vp9DecClass * klass, gpointer data) static void gst_d3d12_vp9_dec_init (GstD3D12Vp9Dec * self) { - GstD3D12Vp9DecClass *klass = GST_D3D12_VP9_DEC_GET_CLASS (self); - GstD3D12DecoderSubClassData *cdata = &klass->class_data; + auto klass = GST_D3D12_VP9_DEC_GET_CLASS (self); - self->decoder = gst_d3d12_decoder_new (GST_DXVA_CODEC_VP9, - cdata->adapter_luid); + self->decoder = gst_d3d12_decoder_new (&klass->class_data); } static void @@ -116,8 +114,8 @@ static void gst_d3d12_vp9_dec_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { - GstD3D12Vp9DecClass *klass = GST_D3D12_VP9_DEC_GET_CLASS (object); - GstD3D12DecoderSubClassData *cdata = &klass->class_data; + auto klass = GST_D3D12_VP9_DEC_GET_CLASS (object); + auto cdata = &klass->class_data; gst_d3d12_decoder_proxy_get_property (object, prop_id, value, pspec, cdata); } @@ -324,7 +322,7 @@ gst_d3d12_vp9_dec_output_picture (GstDxvaVp9Decoder * decoder, void gst_d3d12_vp9_dec_register (GstPlugin * plugin, GstD3D12Device * device, - ID3D12VideoDevice * video_device, guint rank) + ID3D12VideoDevice * video_device, guint rank, gboolean d3d11_interop) { GType type; gchar *type_name; @@ -345,12 +343,14 @@ gst_d3d12_vp9_dec_register (GstPlugin * plugin, GstD3D12Device * device, GST_DEBUG_CATEGORY_INIT (gst_d3d12_vp9_dec_debug, "d3d12vp9dec", 0, "d3d12vp9dec"); - type_info.class_data = - gst_d3d12_decoder_check_feature_support (device, video_device, + auto cdata = gst_d3d12_decoder_check_feature_support (device, video_device, GST_DXVA_CODEC_VP9); - if (!type_info.class_data) + if (!cdata) return; + cdata->subclass_data.d3d11_interop = d3d11_interop; + type_info.class_data = cdata; + type_name = g_strdup ("GstD3D12Vp9Dec"); feature_name = g_strdup ("d3d12vp9dec"); diff --git a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12vp9dec.h b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12vp9dec.h index 63089ddda0..fbc5bde4b1 100644 --- a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12vp9dec.h +++ b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12vp9dec.h @@ -26,7 +26,8 @@ G_BEGIN_DECLS void gst_d3d12_vp9_dec_register (GstPlugin * plugin, GstD3D12Device * device, ID3D12VideoDevice * video_device, - guint rank); + guint rank, + gboolean d3d11_interop); G_END_DECLS diff --git a/subprojects/gst-plugins-bad/sys/d3d12/plugin.cpp b/subprojects/gst-plugins-bad/sys/d3d12/plugin.cpp index 52e931fee8..8e69b5dd9f 100644 --- a/subprojects/gst-plugins-bad/sys/d3d12/plugin.cpp +++ b/subprojects/gst-plugins-bad/sys/d3d12/plugin.cpp @@ -55,6 +55,9 @@ #ifdef HAVE_GST_D3D11 #include "gstd3d12memorycopy.h" +#include +#include +#include #else #include "gstd3d12download.h" #include "gstd3d12upload.h" @@ -94,6 +97,7 @@ plugin_init (GstPlugin * plugin) ID3D12Device *device_handle; ComPtr < ID3D12VideoDevice > video_device; HRESULT hr; + gboolean d3d11_interop = FALSE; device = gst_d3d12_device_new (i); if (!device) @@ -106,21 +110,43 @@ plugin_init (GstPlugin * plugin) gst_object_unref (device); continue; } +#ifdef HAVE_GST_D3D11 + gint64 luid; + g_object_get (device, "adapter-luid", &luid, nullptr); + auto device11 = gst_d3d11_device_new_for_adapter_luid (luid, + D3D11_CREATE_DEVICE_BGRA_SUPPORT); + if (device11 && gst_d3d11_device_d3d12_import_supported (device11)) { + auto device11_handle = gst_d3d11_device_get_device_handle (device11); + ComPtr < ID3D11Device5 > device11_5; + hr = device11_handle->QueryInterface (IID_PPV_ARGS (&device11_5)); + if (SUCCEEDED (hr)) { + ComPtr < ID3D11DeviceContext > context11; + ComPtr < ID3D11DeviceContext4 > context11_4; + device11_5->GetImmediateContext (&context11); + hr = context11.As (&context11_4); + if (SUCCEEDED (hr)) + d3d11_interop = TRUE; + } + } + + gst_clear_object (&device11); +#endif + have_video_device = true; gst_d3d12_mpeg2_dec_register (plugin, device, video_device.Get (), - decoder_rank); + decoder_rank, d3d11_interop); gst_d3d12_h264_dec_register (plugin, device, video_device.Get (), - decoder_rank); + decoder_rank, d3d11_interop); gst_d3d12_h265_dec_register (plugin, device, video_device.Get (), - decoder_rank); + decoder_rank, d3d11_interop); gst_d3d12_vp8_dec_register (plugin, device, video_device.Get (), - decoder_rank); + decoder_rank, d3d11_interop); gst_d3d12_vp9_dec_register (plugin, device, video_device.Get (), - decoder_rank); + decoder_rank, d3d11_interop); gst_d3d12_av1_dec_register (plugin, device, video_device.Get (), - decoder_rank); + decoder_rank, d3d11_interop); gst_d3d12_h264_enc_register (plugin, device, video_device.Get (), GST_RANK_NONE);