From 5c51601cdf2de5a40e69ae63e02e816c0e001f92 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Sat, 7 Mar 2020 16:42:14 +0900 Subject: [PATCH] d3d11decoder: Use aligned resolution for staging texture Not only any textures for decoder output view, any destination texture which would be copied from decoder output texture need to be aligned too. Otherwise driver sometimes crashed/hung (not sure why). --- sys/d3d11/gstd3d11decoder.c | 63 ++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 33 deletions(-) diff --git a/sys/d3d11/gstd3d11decoder.c b/sys/d3d11/gstd3d11decoder.c index 41ab4e9a9e..2f53398e7d 100644 --- a/sys/d3d11/gstd3d11decoder.c +++ b/sys/d3d11/gstd3d11decoder.c @@ -79,8 +79,8 @@ struct _GstD3D11DecoderPrivate /* for staging */ ID3D11Texture2D *staging; - D3D11_TEXTURE2D_DESC staging_desc; - D3D11_BOX staging_box; + gsize staging_texture_offset[GST_VIDEO_MAX_PLANES]; + gint stating_texture_stride[GST_VIDEO_MAX_PLANES]; GUID decoder_profile; }; @@ -559,6 +559,7 @@ gst_d3d11_decoder_open (GstD3D11Decoder * decoder, GstD3D11Codec codec, D3D11_VIDEO_DECODER_CONFIG *config_list; D3D11_VIDEO_DECODER_CONFIG *best_config = NULL; D3D11_VIDEO_DECODER_DESC decoder_desc = { 0, }; + D3D11_TEXTURE2D_DESC staging_desc = { 0, }; GUID selected_profile; gint i; guint aligned_width, aligned_height; @@ -686,34 +687,26 @@ gst_d3d11_decoder_open (GstD3D11Decoder * decoder, GstD3D11Codec codec, GST_DEBUG_OBJECT (decoder, "Decoder object %p created", priv->decoder); /* create stage texture to copy out */ - memset (&priv->staging_desc, 0, sizeof (D3D11_TEXTURE2D_DESC)); - priv->staging_desc.Width = GST_VIDEO_INFO_WIDTH (info); - priv->staging_desc.Height = GST_VIDEO_INFO_HEIGHT (info); - priv->staging_desc.MipLevels = 1; - priv->staging_desc.Format = d3d11_format->dxgi_format; - priv->staging_desc.SampleDesc.Count = 1; - priv->staging_desc.ArraySize = 1; - priv->staging_desc.Usage = D3D11_USAGE_STAGING; - priv->staging_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + staging_desc.Width = aligned_width; + staging_desc.Height = aligned_height; + staging_desc.MipLevels = 1; + staging_desc.Format = d3d11_format->dxgi_format; + staging_desc.SampleDesc.Count = 1; + staging_desc.ArraySize = 1; + staging_desc.Usage = D3D11_USAGE_STAGING; + staging_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; priv->staging = gst_d3d11_device_create_texture (priv->device, - &priv->staging_desc, NULL); + &staging_desc, NULL); if (!priv->staging) { GST_ERROR_OBJECT (decoder, "Couldn't create staging texture"); goto error; } - /* This D3D11_BOX structure is used to copy decoder view to staging texture, - * in case of system memory downstream. - * Since resolution of decoder view might be larger than this staging texture, - * this D3D11_BOX structure will guide the target area which need to be copied. - */ - priv->staging_box.left = 0; - priv->staging_box.top = 0; - priv->staging_box.front = 0; - priv->staging_box.back = 1; - priv->staging_box.right = GST_VIDEO_INFO_WIDTH (info); - priv->staging_box.bottom = GST_VIDEO_INFO_HEIGHT (info); + memset (priv->staging_texture_offset, + 0, sizeof (priv->staging_texture_offset)); + memset (priv->stating_texture_stride, + 0, sizeof (priv->stating_texture_stride)); priv->decoder_profile = selected_profile; decoder->opened = TRUE; @@ -949,14 +942,10 @@ copy_to_system (GstD3D11Decoder * self, GstVideoInfo * info, GstBuffer * decoder_buffer, GstBuffer * output) { GstD3D11DecoderPrivate *priv = self->priv; - D3D11_TEXTURE2D_DESC *desc = &priv->staging_desc; GstVideoFrame out_frame; gint i; GstD3D11Memory *in_mem; D3D11_MAPPED_SUBRESOURCE map; - gsize offset[GST_VIDEO_MAX_PLANES]; - gint stride[GST_VIDEO_MAX_PLANES]; - gsize dummy; HRESULT hr; ID3D11DeviceContext *device_context = gst_d3d11_device_get_device_context_handle (priv->device); @@ -971,8 +960,7 @@ copy_to_system (GstD3D11Decoder * self, GstVideoInfo * info, gst_d3d11_device_lock (priv->device); ID3D11DeviceContext_CopySubresourceRegion (device_context, (ID3D11Resource *) priv->staging, 0, 0, 0, 0, - (ID3D11Resource *) in_mem->texture, in_mem->subresource_index, - &priv->staging_box); + (ID3D11Resource *) in_mem->texture, in_mem->subresource_index, NULL); hr = ID3D11DeviceContext_Map (device_context, (ID3D11Resource *) priv->staging, 0, D3D11_MAP_READ, 0, &map); @@ -983,15 +971,24 @@ copy_to_system (GstD3D11Decoder * self, GstVideoInfo * info, return FALSE; } - gst_d3d11_dxgi_format_get_size (desc->Format, desc->Width, desc->Height, - map.RowPitch, offset, stride, &dummy); + /* calculate stride and offset only once */ + if (priv->stating_texture_stride[0] == 0) { + D3D11_TEXTURE2D_DESC desc; + gsize dummy; + + ID3D11Texture2D_GetDesc (priv->staging, &desc); + + gst_d3d11_dxgi_format_get_size (desc.Format, desc.Width, desc.Height, + map.RowPitch, priv->staging_texture_offset, + priv->stating_texture_stride, &dummy); + } for (i = 0; i < GST_VIDEO_FRAME_N_PLANES (&out_frame); i++) { guint8 *src, *dst; gint j; gint width; - src = (guint8 *) map.pData + offset[i]; + src = (guint8 *) map.pData + priv->staging_texture_offset[i]; dst = GST_VIDEO_FRAME_PLANE_DATA (&out_frame, i); width = GST_VIDEO_FRAME_COMP_WIDTH (&out_frame, i) * GST_VIDEO_FRAME_COMP_PSTRIDE (&out_frame, i); @@ -999,7 +996,7 @@ copy_to_system (GstD3D11Decoder * self, GstVideoInfo * info, for (j = 0; j < GST_VIDEO_FRAME_COMP_HEIGHT (&out_frame, i); j++) { memcpy (dst, src, width); dst += GST_VIDEO_FRAME_PLANE_STRIDE (&out_frame, i); - src += map.RowPitch; + src += priv->stating_texture_stride[i]; } }