mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-06 14:32:31 +00:00
d3d12decoder: Use GstD3D12BufferPool
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5345>
This commit is contained in:
parent
884f4122b5
commit
ff7bde06f2
1 changed files with 114 additions and 79 deletions
|
@ -26,6 +26,7 @@
|
|||
#include "gstd3d12utils.h"
|
||||
#include "gstd3d12format.h"
|
||||
#include "gstd3d12memory.h"
|
||||
#include "gstd3d12bufferpool.h"
|
||||
#include "gstd3d12fence.h"
|
||||
#include <wrl.h>
|
||||
#include <string.h>
|
||||
|
@ -151,11 +152,11 @@ private:
|
|||
|
||||
struct GstD3D12DecoderPicture : public GstMiniObject
|
||||
{
|
||||
GstD3D12DecoderPicture (GstMemory * dpb_mem, GstMemory * out_mem,
|
||||
GstD3D12DecoderPicture (GstBuffer * dpb_buf, GstBuffer * out_buf,
|
||||
std::shared_ptr<GstD3D12Dpb> d3d12_dpb,
|
||||
ID3D12VideoDecoderHeap * decoder_heap, guint8 dxva_id)
|
||||
: mem(dpb_mem), output_mem(out_mem), dpb(d3d12_dpb), heap(decoder_heap)
|
||||
, view_id(dxva_id)
|
||||
: buffer(dpb_buf), output_buffer(out_buf), dpb(d3d12_dpb)
|
||||
, heap(decoder_heap), view_id(dxva_id)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -165,14 +166,14 @@ struct GstD3D12DecoderPicture : public GstMiniObject
|
|||
if (d3d12_dpb)
|
||||
d3d12_dpb->Release (view_id);
|
||||
|
||||
if (mem)
|
||||
gst_memory_unref (mem);
|
||||
if (output_mem)
|
||||
gst_memory_unref (output_mem);
|
||||
if (buffer)
|
||||
gst_buffer_unref (buffer);
|
||||
if (output_buffer)
|
||||
gst_buffer_unref (output_buffer);
|
||||
}
|
||||
|
||||
GstMemory *mem;
|
||||
GstMemory *output_mem;
|
||||
GstBuffer *buffer;
|
||||
GstBuffer *output_buffer;
|
||||
ComPtr<ID3D12VideoDecoderHeap> heap;
|
||||
std::weak_ptr<GstD3D12Dpb> dpb;
|
||||
|
||||
|
@ -197,14 +198,14 @@ struct GstD3D12DecoderPrivate
|
|||
gst_d3d12_fence_unref (fence);
|
||||
}
|
||||
|
||||
if (allocator) {
|
||||
gst_d3d12_allocator_set_active (allocator, FALSE);
|
||||
gst_object_unref (allocator);
|
||||
if (dpb_pool) {
|
||||
gst_buffer_pool_set_active (dpb_pool, FALSE);
|
||||
gst_object_unref (dpb_pool);
|
||||
}
|
||||
|
||||
if (output_allocator) {
|
||||
gst_d3d12_allocator_set_active (output_allocator, FALSE);
|
||||
gst_object_unref (output_allocator);
|
||||
if (output_pool) {
|
||||
gst_buffer_pool_set_active (output_pool, FALSE);
|
||||
gst_object_unref (output_pool);
|
||||
}
|
||||
|
||||
if (device)
|
||||
|
@ -215,11 +216,11 @@ struct GstD3D12DecoderPrivate
|
|||
|
||||
GstDxvaCodec codec = GST_DXVA_CODEC_NONE;
|
||||
|
||||
/* Allocator for dpb textures */
|
||||
GstD3D12Allocator *allocator = nullptr;
|
||||
/* reference textures */
|
||||
GstBufferPool *dpb_pool = nullptr;
|
||||
|
||||
/* Used for output */
|
||||
GstD3D12Allocator *output_allocator = nullptr;
|
||||
/* Used for output if reference-only texture is required */
|
||||
GstBufferPool *output_pool = nullptr;
|
||||
|
||||
gboolean configured = FALSE;
|
||||
gboolean opened = FALSE;
|
||||
|
@ -232,6 +233,7 @@ struct GstD3D12DecoderPrivate
|
|||
gint coded_height = 0;
|
||||
DXGI_FORMAT decoder_format = DXGI_FORMAT_UNKNOWN;
|
||||
gboolean reference_only = FALSE;
|
||||
gboolean use_array_of_texture = FALSE;
|
||||
|
||||
D3D12_FEATURE_DATA_VIDEO_DECODE_SUPPORT support = { 0, };
|
||||
|
||||
|
@ -318,14 +320,14 @@ gst_d3d12_decoder_clear_resource (GstD3D12Decoder * self)
|
|||
|
||||
gst_d3d12_fence_wait (priv->fence);
|
||||
|
||||
if (priv->allocator) {
|
||||
gst_d3d12_allocator_set_active (priv->allocator, FALSE);
|
||||
gst_clear_object (&priv->allocator);
|
||||
if (priv->dpb_pool) {
|
||||
gst_buffer_pool_set_active (priv->dpb_pool, FALSE);
|
||||
gst_clear_object (&priv->dpb_pool);
|
||||
}
|
||||
|
||||
if (priv->output_allocator) {
|
||||
gst_d3d12_allocator_set_active (priv->output_allocator, FALSE);
|
||||
gst_clear_object (&priv->output_allocator);
|
||||
if (priv->output_pool) {
|
||||
gst_buffer_pool_set_active (priv->output_pool, FALSE);
|
||||
gst_clear_object (&priv->output_pool);
|
||||
}
|
||||
|
||||
priv->heap = nullptr;
|
||||
|
@ -470,24 +472,29 @@ gst_d3d12_decoder_configure (GstD3D12Decoder * decoder,
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_d3d12_decoder_prepare_allocator (GstD3D12Decoder * self)
|
||||
gst_d3d12_decoder_prepare_pool (GstD3D12Decoder * self)
|
||||
{
|
||||
GstD3D12DecoderPrivate *priv = self->priv;
|
||||
GstVideoInfo *info = &priv->info;
|
||||
GstVideoAlignment align;
|
||||
GstD3D12AllocationParams *params;
|
||||
GstStructure *config;
|
||||
GstCaps *caps;
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Preparing allocator");
|
||||
|
||||
std::lock_guard < std::mutex > lk (priv->lock);
|
||||
if (priv->allocator) {
|
||||
gst_d3d12_allocator_set_active (priv->allocator, FALSE);
|
||||
gst_clear_object (&priv->allocator);
|
||||
if (priv->dpb_pool) {
|
||||
gst_buffer_pool_set_active (priv->dpb_pool, FALSE);
|
||||
gst_clear_object (&priv->dpb_pool);
|
||||
}
|
||||
|
||||
if (priv->output_allocator) {
|
||||
gst_d3d12_allocator_set_active (priv->output_allocator, FALSE);
|
||||
gst_clear_object (&priv->output_allocator);
|
||||
if (priv->output_pool) {
|
||||
gst_buffer_pool_set_active (priv->output_pool, FALSE);
|
||||
gst_clear_object (&priv->output_pool);
|
||||
}
|
||||
|
||||
D3D12_RESOURCE_FLAGS resource_flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
D3D12_RESOURCE_FLAGS resource_flags;
|
||||
if ((priv->support.ConfigurationFlags &
|
||||
D3D12_VIDEO_DECODE_CONFIGURATION_FLAG_REFERENCE_ONLY_ALLOCATIONS_REQUIRED)
|
||||
!= 0) {
|
||||
|
@ -496,43 +503,72 @@ gst_d3d12_decoder_prepare_allocator (GstD3D12Decoder * self)
|
|||
D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE;
|
||||
priv->reference_only = TRUE;
|
||||
} else {
|
||||
resource_flags = D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS;
|
||||
priv->reference_only = FALSE;
|
||||
}
|
||||
|
||||
UINT16 array_size;
|
||||
GstD3D12AllocationFlags alloc_flags = GST_D3D12_ALLOCATION_FLAG_DEFAULT;
|
||||
guint max_buffers = priv->dpb_size;
|
||||
/* Tier 1 decoder requires array */
|
||||
if (priv->support.DecodeTier == D3D12_VIDEO_DECODE_TIER_1) {
|
||||
array_size = priv->dpb_size;
|
||||
priv->use_array_of_texture = FALSE;
|
||||
alloc_flags = GST_D3D12_ALLOCATION_FLAG_TEXTURE_ARRAY;
|
||||
} else {
|
||||
array_size = 1;
|
||||
priv->use_array_of_texture = TRUE;
|
||||
max_buffers = 0;
|
||||
}
|
||||
|
||||
D3D12_HEAP_PROPERTIES heap_prop =
|
||||
CD3D12_HEAP_PROPERTIES (D3D12_HEAP_TYPE_DEFAULT);
|
||||
D3D12_RESOURCE_DESC desc = CD3D12_RESOURCE_DESC::Tex2D (priv->decoder_format,
|
||||
priv->aligned_width, priv->aligned_height, resource_flags, array_size);
|
||||
params = gst_d3d12_allocation_params_new (priv->device, info, alloc_flags,
|
||||
resource_flags);
|
||||
|
||||
priv->allocator = (GstD3D12Allocator *)
|
||||
gst_d3d12_pool_allocator_new (priv->device,
|
||||
&heap_prop, D3D12_HEAP_FLAG_NONE,
|
||||
&desc, D3D12_RESOURCE_STATE_COMMON, nullptr);
|
||||
gst_d3d12_allocator_set_active (priv->allocator, TRUE);
|
||||
gst_video_alignment_reset (&align);
|
||||
align.padding_right = priv->aligned_width - GST_VIDEO_INFO_WIDTH (info);
|
||||
align.padding_bottom = priv->aligned_height - GST_VIDEO_INFO_HEIGHT (info);
|
||||
gst_d3d12_allocation_params_alignment (params, &align);
|
||||
|
||||
if (!priv->use_array_of_texture)
|
||||
params->desc[0].DepthOrArraySize = (UINT16) max_buffers;
|
||||
|
||||
priv->dpb_pool = gst_d3d12_buffer_pool_new (priv->device);
|
||||
config = gst_buffer_pool_get_config (priv->dpb_pool);
|
||||
caps = gst_video_info_to_caps (info);
|
||||
|
||||
gst_buffer_pool_config_set_d3d12_allocation_params (config, params);
|
||||
gst_d3d12_allocation_params_free (params);
|
||||
gst_buffer_pool_config_set_params (config, caps, GST_VIDEO_INFO_SIZE (info),
|
||||
0, max_buffers);
|
||||
if (!gst_buffer_pool_set_config (priv->dpb_pool, config)) {
|
||||
GST_ERROR_OBJECT (self, "Pool config failed");
|
||||
gst_caps_unref (caps);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gst_buffer_pool_set_active (priv->dpb_pool, TRUE);
|
||||
|
||||
/* In case that device requires reference only dpb texture, we need another
|
||||
* texture pool for outputting without VIDEO_DECODE_REFERENCE_ONLY flag */
|
||||
if (priv->reference_only) {
|
||||
GST_DEBUG_OBJECT (self, "Creating output only allocator");
|
||||
D3D12_RESOURCE_DESC ref_desc =
|
||||
CD3D12_RESOURCE_DESC::Tex2D (priv->decoder_format,
|
||||
priv->aligned_width,
|
||||
priv->aligned_height);
|
||||
priv->output_pool = gst_d3d12_buffer_pool_new (priv->device);
|
||||
config = gst_buffer_pool_get_config (priv->output_pool);
|
||||
|
||||
priv->output_allocator = (GstD3D12Allocator *)
|
||||
gst_d3d12_pool_allocator_new (priv->device, &heap_prop,
|
||||
D3D12_HEAP_FLAG_NONE, &ref_desc, D3D12_RESOURCE_STATE_COMMON, nullptr);
|
||||
gst_d3d12_allocator_set_active (priv->output_allocator, TRUE);
|
||||
params = gst_d3d12_allocation_params_new (priv->device, info, alloc_flags,
|
||||
D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS);
|
||||
gst_d3d12_allocation_params_alignment (params, &align);
|
||||
gst_buffer_pool_config_set_d3d12_allocation_params (config, params);
|
||||
gst_d3d12_allocation_params_free (params);
|
||||
gst_buffer_pool_config_set_params (config, caps, GST_VIDEO_INFO_SIZE (info),
|
||||
0, 0);
|
||||
if (!gst_buffer_pool_set_config (priv->output_pool, config)) {
|
||||
GST_ERROR_OBJECT (self, "Output pool config failed");
|
||||
gst_caps_unref (caps);
|
||||
return FALSE;
|
||||
}
|
||||
gst_buffer_pool_set_active (priv->output_pool, TRUE);
|
||||
}
|
||||
|
||||
gst_caps_unref (caps);
|
||||
|
||||
priv->dpb = std::make_shared < GstD3D12Dpb > ((guint8) priv->dpb_size);
|
||||
|
||||
return TRUE;
|
||||
|
@ -545,23 +581,23 @@ gst_d3d12_decoder_picture_free (GstD3D12DecoderPicture * self)
|
|||
}
|
||||
|
||||
static GstD3D12DecoderPicture *
|
||||
gst_d3d12_decoder_picture_new (GstD3D12Decoder * self, GstMemory * mem,
|
||||
GstMemory * output_mem, ID3D12VideoDecoderHeap * heap)
|
||||
gst_d3d12_decoder_picture_new (GstD3D12Decoder * self, GstBuffer * buffer,
|
||||
GstBuffer * output_buffer, ID3D12VideoDecoderHeap * heap)
|
||||
{
|
||||
GstD3D12DecoderPrivate *priv = self->priv;
|
||||
GstD3D12DecoderPicture *picture;
|
||||
GstMemory *mem = gst_buffer_peek_memory (buffer, 0);
|
||||
|
||||
auto view_id = priv->dpb->Acquire (GST_D3D12_MEMORY_CAST (mem), heap);
|
||||
if (view_id == 0xff) {
|
||||
GST_WARNING_OBJECT (self, "No empty picture");
|
||||
if (mem)
|
||||
gst_memory_unref (mem);
|
||||
if (output_mem)
|
||||
gst_memory_unref (output_mem);
|
||||
gst_buffer_unref (buffer);
|
||||
if (output_buffer)
|
||||
gst_buffer_unref (output_buffer);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
picture = new GstD3D12DecoderPicture (mem, output_mem, priv->dpb, heap,
|
||||
picture = new GstD3D12DecoderPicture (buffer, output_buffer, priv->dpb, heap,
|
||||
view_id);
|
||||
|
||||
gst_mini_object_init (picture, 0, GST_TYPE_D3D12_DECODER_PICTURE,
|
||||
|
@ -577,8 +613,8 @@ gst_d3d12_decoder_new_picture (GstD3D12Decoder * decoder,
|
|||
{
|
||||
GstD3D12DecoderPrivate *priv;
|
||||
GstD3D12DecoderPicture *decoder_pic = nullptr;
|
||||
GstMemory *mem;
|
||||
GstMemory *output_mem = nullptr;
|
||||
GstBuffer *buffer;
|
||||
GstBuffer *output_buffer = nullptr;
|
||||
GstFlowReturn ret;
|
||||
|
||||
g_return_val_if_fail (GST_IS_D3D12_DECODER (decoder), GST_FLOW_ERROR);
|
||||
|
@ -587,7 +623,7 @@ gst_d3d12_decoder_new_picture (GstD3D12Decoder * decoder,
|
|||
|
||||
priv = decoder->priv;
|
||||
|
||||
if (!priv->allocator) {
|
||||
if (!priv->dpb_pool) {
|
||||
/* Try negotiate again whatever the previous negotiation result was.
|
||||
* There could be updated field(s) in sinkpad caps after we negotiated with
|
||||
* downstream on new_sequence() call. For example, h264/h265 parse
|
||||
|
@ -596,32 +632,29 @@ gst_d3d12_decoder_new_picture (GstD3D12Decoder * decoder,
|
|||
* headers */
|
||||
gst_video_decoder_negotiate (videodec);
|
||||
|
||||
if (!gst_d3d12_decoder_prepare_allocator (decoder)) {
|
||||
if (!gst_d3d12_decoder_prepare_pool (decoder)) {
|
||||
GST_ERROR_OBJECT (videodec, "Failed to setup dpb pool");
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
ret =
|
||||
gst_d3d12_pool_allocator_acquire_memory (GST_D3D12_POOL_ALLOCATOR
|
||||
(priv->allocator), &mem);
|
||||
ret = gst_buffer_pool_acquire_buffer (priv->dpb_pool, &buffer, nullptr);
|
||||
if (ret != GST_FLOW_OK) {
|
||||
GST_WARNING_OBJECT (videodec, "Couldn't acquire memory");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (priv->reference_only) {
|
||||
ret =
|
||||
gst_d3d12_pool_allocator_acquire_memory (GST_D3D12_POOL_ALLOCATOR
|
||||
(priv->output_allocator), &output_mem);
|
||||
ret = gst_buffer_pool_acquire_buffer (priv->output_pool,
|
||||
&output_buffer, nullptr);
|
||||
if (ret != GST_FLOW_OK) {
|
||||
GST_WARNING_OBJECT (videodec, "Couldn't acquire output memory");
|
||||
gst_memory_unref (mem);
|
||||
gst_buffer_unref (buffer);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
decoder_pic = gst_d3d12_decoder_picture_new (decoder, mem, output_mem,
|
||||
decoder_pic = gst_d3d12_decoder_picture_new (decoder, buffer, output_buffer,
|
||||
priv->heap.Get ());
|
||||
if (!decoder_pic) {
|
||||
GST_ERROR_OBJECT (videodec, "Couldn't create new picture");
|
||||
|
@ -802,7 +835,7 @@ gst_d3d12_decoder_end_picture (GstD3D12Decoder * decoder,
|
|||
|
||||
configured_ref_pics.push_back (ref_dec_pic);
|
||||
|
||||
dmem = (GstD3D12Memory *) ref_dec_pic->mem;
|
||||
dmem = (GstD3D12Memory *) gst_buffer_peek_memory (ref_dec_pic->buffer, 0);
|
||||
|
||||
resource = gst_d3d12_memory_get_resource_handle (dmem);
|
||||
gst_d3d12_memory_get_subresource_index (dmem, 0, &subresource[0]);
|
||||
|
@ -823,8 +856,9 @@ gst_d3d12_decoder_end_picture (GstD3D12Decoder * decoder,
|
|||
subresource[1]));
|
||||
}
|
||||
|
||||
dmem = (GstD3D12Memory *) decoder_pic->output_mem;
|
||||
if (dmem) {
|
||||
if (decoder_pic->output_buffer) {
|
||||
dmem = (GstD3D12Memory *)
|
||||
gst_buffer_peek_memory (decoder_pic->output_buffer, 0);
|
||||
out_resource = gst_d3d12_memory_get_resource_handle (dmem);
|
||||
|
||||
pre_barriers.push_back (CD3D12_RESOURCE_BARRIER::Transition (out_resource,
|
||||
|
@ -835,7 +869,7 @@ gst_d3d12_decoder_end_picture (GstD3D12Decoder * decoder,
|
|||
D3D12_RESOURCE_STATE_COMMON));
|
||||
}
|
||||
|
||||
dmem = (GstD3D12Memory *) decoder_pic->mem;
|
||||
dmem = (GstD3D12Memory *) gst_buffer_peek_memory (decoder_pic->buffer, 0);
|
||||
resource = gst_d3d12_memory_get_resource_handle (dmem);
|
||||
gst_d3d12_memory_get_subresource_index (GST_D3D12_MEMORY_CAST (dmem), 0,
|
||||
&subresource[0]);
|
||||
|
@ -981,7 +1015,7 @@ gst_d3d12_decoder_output_picture (GstD3D12Decoder * decoder,
|
|||
GstFlowReturn ret = GST_FLOW_ERROR;
|
||||
ID3D12CommandList *list[1];
|
||||
UINT64 fence_value;
|
||||
GstMemory *mem;
|
||||
GstBuffer *buffer;
|
||||
GstD3D12Memory *dmem;
|
||||
ID3D12Resource *resource;
|
||||
UINT subresource[2];
|
||||
|
@ -1046,8 +1080,9 @@ gst_d3d12_decoder_output_picture (GstD3D12Decoder * decoder,
|
|||
/* Wait for pending decoding operation before copying */
|
||||
gst_d3d12_fence_wait (priv->fence);
|
||||
|
||||
mem = decoder_pic->output_mem ? decoder_pic->output_mem : decoder_pic->mem;
|
||||
dmem = GST_D3D12_MEMORY_CAST (mem);
|
||||
buffer = decoder_pic->output_buffer ?
|
||||
decoder_pic->output_buffer : decoder_pic->buffer;
|
||||
dmem = (GstD3D12Memory *) gst_buffer_peek_memory (buffer, 0);
|
||||
resource = gst_d3d12_memory_get_resource_handle (dmem);
|
||||
|
||||
gst_d3d12_memory_get_subresource_index (dmem, 0, &subresource[0]);
|
||||
|
|
Loading…
Reference in a new issue