diff --git a/sys/d3d11/gstd3d11colorconvert.c b/sys/d3d11/gstd3d11colorconvert.c index 5143acc84d..68514c31c7 100644 --- a/sys/d3d11/gstd3d11colorconvert.c +++ b/sys/d3d11/gstd3d11colorconvert.c @@ -1627,10 +1627,10 @@ gst_d3d11_convert_prefer_video_processor (GstD3D11Convert * self, /* If we can use shader, we prefer to use shader instead of video processor * because video processor implementation is vendor dependent * and not flexible */ - if (gst_d3d11_memory_ensure_shader_resource_view (dmem)) + if (gst_d3d11_memory_get_shader_resource_view_size (dmem)) return FALSE; - if (!gst_d3d11_video_processor_ensure_input_view (self->processor, dmem)) + if (!gst_d3d11_video_processor_get_input_view (self->processor, dmem)) return FALSE; mem = gst_buffer_peek_memory (outbuf, 0); @@ -1640,35 +1640,34 @@ gst_d3d11_convert_prefer_video_processor (GstD3D11Convert * self, if (dmem->device != filter->device) return FALSE; - if (!gst_d3d11_video_processor_ensure_output_view (self->processor, dmem)) + if (!gst_d3d11_video_processor_get_output_view (self->processor, dmem)) return FALSE; return TRUE; } -static GstFlowReturn +static gboolean gst_d3d11_convert_transform_using_processor (GstD3D11Convert * self, GstBuffer * inbuf, GstBuffer * outbuf) { - GstMemory *in_mem, *out_mem; - GstD3D11Memory *in_dmem, *out_dmem; - GstMapInfo in_map, out_map; + GstD3D11Memory *in_mem, *out_mem; RECT in_rect, out_rect; - gboolean ret; + ID3D11VideoProcessorInputView *piv; + ID3D11VideoProcessorOutputView *pov; - in_mem = gst_buffer_peek_memory (inbuf, 0); - in_dmem = (GstD3D11Memory *) in_mem; - if (!gst_memory_map (in_mem, &in_map, GST_MAP_D3D11 | GST_MAP_READ)) { - GST_ERROR_OBJECT (self, "Failed to map input d3d11 memory"); - return GST_FLOW_ERROR; + in_mem = (GstD3D11Memory *) gst_buffer_peek_memory (inbuf, 0); + out_mem = (GstD3D11Memory *) gst_buffer_peek_memory (outbuf, 0); + + piv = gst_d3d11_video_processor_get_input_view (self->processor, in_mem); + if (!piv) { + GST_ERROR_OBJECT (self, "ID3D11VideoProcessorInputView is unavailable"); + return FALSE; } - out_mem = gst_buffer_peek_memory (outbuf, 0); - out_dmem = (GstD3D11Memory *) out_mem; - if (!gst_memory_map (out_mem, &out_map, GST_MAP_D3D11 | GST_MAP_WRITE)) { - GST_ERROR_OBJECT (self, "Failed to map output d3d11 memory"); - gst_memory_unmap (in_mem, &in_map); - return GST_FLOW_ERROR; + pov = gst_d3d11_video_processor_get_output_view (self->processor, out_mem); + if (!pov) { + GST_ERROR_OBJECT (self, "ID3D11VideoProcessorOutputView is unavailable"); + return FALSE; } in_rect.left = 0; @@ -1681,19 +1680,8 @@ gst_d3d11_convert_transform_using_processor (GstD3D11Convert * self, out_rect.right = self->out_src_box.right; out_rect.bottom = self->out_src_box.bottom; - ret = gst_d3d11_video_processor_render (self->processor, - &in_rect, in_dmem->processor_input_view, &out_rect, - out_dmem->processor_output_view); - - gst_memory_unmap (in_mem, &in_map); - gst_memory_unmap (out_mem, &out_map); - - if (!ret) { - GST_ERROR_OBJECT (self, "Couldn't convert using video processor"); - return GST_FLOW_ERROR; - } - - return GST_FLOW_OK; + return gst_d3d11_video_processor_render (self->processor, + &in_rect, piv, &out_rect, pov); } static GstFlowReturn @@ -1702,135 +1690,156 @@ gst_d3d11_convert_transform (GstBaseTransform * trans, { GstD3D11BaseFilter *filter = GST_D3D11_BASE_FILTER (trans); GstD3D11Convert *self = GST_D3D11_CONVERT (trans); + GstD3D11Device *device = filter->device; + ID3D11Device *device_handle; ID3D11DeviceContext *context_handle; ID3D11ShaderResourceView *resource_view[GST_VIDEO_MAX_PLANES] = { NULL, }; ID3D11RenderTargetView *render_view[GST_VIDEO_MAX_PLANES] = { NULL, }; - gint i, j, view_index; + gint i; gboolean copy_input = FALSE; gboolean copy_output = FALSE; - GstD3D11Device *device = filter->device; - - if (gst_d3d11_convert_prefer_video_processor (self, inbuf, outbuf)) - return gst_d3d11_convert_transform_using_processor (self, inbuf, outbuf); + GstMapInfo in_map[GST_VIDEO_MAX_PLANES]; + GstMapInfo out_map[GST_VIDEO_MAX_PLANES]; + device_handle = gst_d3d11_device_get_device_handle (device); context_handle = gst_d3d11_device_get_device_context_handle (device); - view_index = 0; - for (i = 0; i < gst_buffer_n_memory (inbuf); i++) { - GstMemory *mem = gst_buffer_peek_memory (inbuf, i); - GstD3D11Memory *d3d11_mem; - GstMapInfo info; - - g_assert (gst_is_d3d11_memory (mem)); - - d3d11_mem = (GstD3D11Memory *) mem; - /* map to transfer pending staging data if any */ - if (d3d11_mem->desc.Usage == D3D11_USAGE_DEFAULT) { - gst_memory_map (mem, &info, GST_MAP_READ | GST_MAP_D3D11); - gst_memory_unmap (mem, &info); - } - - if (gst_d3d11_memory_ensure_shader_resource_view (d3d11_mem)) { - GST_TRACE_OBJECT (self, "Use input texture resource without copy"); - - for (j = 0; j < d3d11_mem->num_shader_resource_views; j++) { - resource_view[view_index] = d3d11_mem->shader_resource_view[j]; - view_index++; - } - } else { - GST_TRACE_OBJECT (self, "Render using fallback input texture"); - copy_input = TRUE; - - if (!create_shader_input_resource (self, device, - self->in_d3d11_format, &filter->in_info)) { - GST_ERROR_OBJECT (self, "Failed to configure fallback input texture"); - return GST_FLOW_ERROR; - } - break; - } + if (!gst_d3d11_buffer_map (inbuf, device_handle, in_map, GST_MAP_READ)) { + GST_ERROR_OBJECT (self, "Couldn't map input buffer"); + goto invalid_memory; } - /* if input memory has no resource view, - * copy texture into our fallback texture */ - if (copy_input) { + if (!gst_d3d11_buffer_map (outbuf, device_handle, out_map, GST_MAP_WRITE)) { + GST_ERROR_OBJECT (self, "Couldn't map output buffer"); + gst_d3d11_buffer_unmap (inbuf, in_map); + goto invalid_memory; + } + + if (gst_d3d11_convert_prefer_video_processor (self, inbuf, outbuf)) { + gboolean ret = + gst_d3d11_convert_transform_using_processor (self, inbuf, outbuf); + + if (!ret) { + GST_ERROR_OBJECT (self, "Couldn't convert using video processor"); + goto conversion_failed; + } + + gst_d3d11_buffer_unmap (inbuf, in_map); + gst_d3d11_buffer_unmap (outbuf, out_map); + + return GST_FLOW_OK; + } + + /* Ensure shader resource views */ + if (!gst_d3d11_buffer_get_shader_resource_view (inbuf, resource_view)) { + if (!create_shader_input_resource (self, device, + self->in_d3d11_format, &filter->in_info)) { + GST_ERROR_OBJECT (self, "Failed to configure fallback input texture"); + goto fallback_failed; + } + + copy_input = TRUE; gst_d3d11_device_lock (device); for (i = 0; i < gst_buffer_n_memory (inbuf); i++) { - GstMemory *mem = gst_buffer_peek_memory (inbuf, i); - GstD3D11Memory *d3d11_mem; + GstD3D11Memory *mem = + (GstD3D11Memory *) gst_buffer_peek_memory (inbuf, i); + guint subidx; + D3D11_BOX src_box = { 0, }; + D3D11_TEXTURE2D_DESC src_desc; + D3D11_TEXTURE2D_DESC dst_desc; - g_assert (gst_is_d3d11_memory (mem)); + subidx = gst_d3d11_memory_get_subresource_index (mem); + gst_d3d11_memory_get_texture_desc (mem, &src_desc); - d3d11_mem = (GstD3D11Memory *) mem; + ID3D11Texture2D_GetDesc (self->in_texture[i], &dst_desc); + + src_box.left = 0; + src_box.top = 0; + src_box.front = 0; + src_box.back = 1; + src_box.right = MIN (src_desc.Width, dst_desc.Width); + src_box.bottom = MIN (src_desc.Height, dst_desc.Height); ID3D11DeviceContext_CopySubresourceRegion (context_handle, (ID3D11Resource *) self->in_texture[i], 0, 0, 0, 0, - (ID3D11Resource *) d3d11_mem->texture, d3d11_mem->subresource_index, - &self->in_src_box); + (ID3D11Resource *) in_map[i].data, subidx, &src_box); } gst_d3d11_device_unlock (device); } - view_index = 0; - for (i = 0; i < gst_buffer_n_memory (outbuf); i++) { - GstMemory *mem = gst_buffer_peek_memory (outbuf, i); - GstD3D11Memory *d3d11_mem; - - g_assert (gst_is_d3d11_memory (mem)); - - d3d11_mem = (GstD3D11Memory *) mem; - - if (gst_d3d11_memory_ensure_render_target_view (d3d11_mem)) { - GST_TRACE_OBJECT (self, "Render to output texture directly"); - - for (j = 0; j < d3d11_mem->num_render_target_views; j++) { - render_view[view_index] = d3d11_mem->render_target_view[j]; - view_index++; - } - } else { - GST_TRACE_OBJECT (self, "Render to fallback output texture"); - copy_output = TRUE; - - if (!create_shader_output_resource (self, device, self->out_d3d11_format, - &filter->out_info)) { - GST_ERROR_OBJECT (self, "Failed to configure fallback output texture"); - return GST_FLOW_ERROR; - } - break; + /* Ensure render target views */ + if (!gst_d3d11_buffer_get_render_target_view (outbuf, render_view)) { + if (!create_shader_output_resource (self, device, + self->out_d3d11_format, &filter->out_info)) { + GST_ERROR_OBJECT (self, "Failed to configure fallback output texture"); + goto fallback_failed; } + + copy_output = TRUE; } if (!gst_d3d11_color_converter_convert (self->converter, copy_input ? self->shader_resource_view : resource_view, copy_output ? self->render_target_view : render_view, NULL, NULL)) { - GST_ERROR_OBJECT (self, "Failed to convert"); - - return GST_FLOW_ERROR; + goto conversion_failed; } if (copy_output) { gst_d3d11_device_lock (device); for (i = 0; i < gst_buffer_n_memory (outbuf); i++) { - GstMemory *mem = gst_buffer_peek_memory (outbuf, i); - GstD3D11Memory *d3d11_mem; + GstD3D11Memory *mem = + (GstD3D11Memory *) gst_buffer_peek_memory (outbuf, i); + guint subidx; + D3D11_BOX src_box = { 0, }; + D3D11_TEXTURE2D_DESC src_desc; + D3D11_TEXTURE2D_DESC dst_desc; - g_assert (gst_is_d3d11_memory (mem)); + ID3D11Texture2D_GetDesc (self->out_texture[i], &src_desc); + subidx = gst_d3d11_memory_get_subresource_index (mem); + gst_d3d11_memory_get_texture_desc (mem, &dst_desc); - d3d11_mem = (GstD3D11Memory *) mem; + src_box.left = 0; + src_box.top = 0; + src_box.front = 0; + src_box.back = 1; + src_box.right = MIN (src_desc.Width, dst_desc.Width); + src_box.bottom = MIN (src_desc.Height, dst_desc.Height); ID3D11DeviceContext_CopySubresourceRegion (context_handle, - (ID3D11Resource *) d3d11_mem->texture, d3d11_mem->subresource_index, - 0, 0, 0, (ID3D11Resource *) self->out_texture[i], 0, - &self->out_src_box); + (ID3D11Resource *) out_map[i].data, subidx, 0, 0, 0, + (ID3D11Resource *) self->out_texture[i], 0, &src_box); } gst_d3d11_device_unlock (device); - } else { - for (i = 0; i < gst_buffer_n_memory (outbuf); i++) { - GstMemory *mem = gst_buffer_peek_memory (outbuf, i); - GST_MINI_OBJECT_FLAG_SET (mem, GST_D3D11_MEMORY_TRANSFER_NEED_DOWNLOAD); - } } + gst_d3d11_buffer_unmap (inbuf, in_map); + gst_d3d11_buffer_unmap (outbuf, out_map); + return GST_FLOW_OK; + +invalid_memory: + { + GST_ELEMENT_ERROR (self, CORE, FAILED, (NULL), ("Invalid memory")); + return GST_FLOW_ERROR; + } +fallback_failed: + { + GST_ELEMENT_ERROR (self, CORE, FAILED, (NULL), + ("Couldn't prepare fallback memory")); + gst_d3d11_buffer_unmap (inbuf, in_map); + gst_d3d11_buffer_unmap (outbuf, out_map); + + return GST_FLOW_ERROR; + } +conversion_failed: + { + GST_ELEMENT_ERROR (self, CORE, FAILED, (NULL), + ("Couldn't convert texture")); + gst_d3d11_buffer_unmap (inbuf, in_map); + gst_d3d11_buffer_unmap (outbuf, out_map); + + return GST_FLOW_ERROR; + } } static GstCaps *gst_d3d11_color_convert_transform_caps (GstBaseTransform * diff --git a/sys/d3d11/gstd3d11compositor.c b/sys/d3d11/gstd3d11compositor.c index e8bf20fbed..1371da2a73 100644 --- a/sys/d3d11/gstd3d11compositor.c +++ b/sys/d3d11/gstd3d11compositor.c @@ -864,12 +864,12 @@ gst_d3d11_compsitor_prepare_fallback_buffer (GstD3D11Compositor * self, GstD3D11Memory *new_mem = (GstD3D11Memory *) gst_buffer_peek_memory (new_buf, i); - if (is_input && !gst_d3d11_memory_ensure_shader_resource_view (new_mem)) { + if (is_input && !gst_d3d11_memory_get_shader_resource_view_size (new_mem)) { GST_ERROR_OBJECT (self, "Couldn't prepare shader resource view"); gst_buffer_unref (new_buf); return FALSE; } else if (!is_input && - !gst_d3d11_memory_ensure_render_target_view (new_mem)) { + !gst_d3d11_memory_get_render_target_view_size (new_mem)) { GST_ERROR_OBJECT (self, "Couldn't prepare render target view"); gst_buffer_unref (new_buf); return FALSE; @@ -889,7 +889,7 @@ gst_d3d11_compositor_copy_buffer (GstD3D11Compositor * self, gint i; if (do_device_copy) { - return gst_d3d11_buffer_copy_into (dest_buf, src_buf); + return gst_d3d11_buffer_copy_into (dest_buf, src_buf, info); } else { GstVideoFrame src_frame, dest_frame; @@ -949,10 +949,10 @@ gst_d3d11_compositor_check_d3d11_memory (GstD3D11Compositor * self, } if (is_input) { - if (!gst_d3d11_memory_ensure_shader_resource_view (dmem)) + if (!gst_d3d11_memory_get_shader_resource_view_size (dmem)) *view_available = FALSE; } else { - if (!gst_d3d11_memory_ensure_render_target_view (dmem)) + if (!gst_d3d11_memory_get_render_target_view_size (dmem)) *view_available = FALSE; } } @@ -2097,6 +2097,7 @@ gst_d3d11_compositor_aggregate_frames (GstVideoAggregator * vagg, for (i = 0; i < gst_buffer_n_memory (target_buf); i++) { GstMemory *mem = gst_buffer_peek_memory (target_buf, i); GstD3D11Memory *dmem; + guint rtv_size; if (!gst_is_d3d11_memory (mem)) { GST_ERROR_OBJECT (self, "Invalid output memory"); @@ -2104,15 +2105,16 @@ gst_d3d11_compositor_aggregate_frames (GstVideoAggregator * vagg, } dmem = (GstD3D11Memory *) mem; - if (!gst_d3d11_memory_ensure_render_target_view (dmem)) { + rtv_size = gst_d3d11_memory_get_render_target_view_size (dmem); + if (!rtv_size) { GST_ERROR_OBJECT (self, "Render target view is unavailable"); return GST_FLOW_ERROR; } - for (j = 0; j < dmem->num_render_target_views; j++) { + for (j = 0; j < rtv_size; j++) { g_assert (view_idx < GST_VIDEO_MAX_PLANES); - rtv[view_idx] = dmem->render_target_view[j]; + rtv[view_idx] = gst_d3d11_memory_get_render_target_view (dmem, j); view_idx++; } @@ -2155,11 +2157,12 @@ gst_d3d11_compositor_aggregate_frames (GstVideoAggregator * vagg, for (i = 0; i < gst_buffer_n_memory (buffer); i++) { GstD3D11Memory *dmem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, i); + guint srv_size = gst_d3d11_memory_get_shader_resource_view_size (dmem); - for (j = 0; j < dmem->num_shader_resource_views; j++) { + for (j = 0; j < srv_size; j++) { g_assert (view_idx < GST_VIDEO_MAX_PLANES); - srv[view_idx] = dmem->shader_resource_view[j]; + srv[view_idx] = gst_d3d11_memory_get_shader_resource_view (dmem, j); view_idx++; } } diff --git a/sys/d3d11/gstd3d11decoder.c b/sys/d3d11/gstd3d11decoder.c index 7736cd8b24..10b478d8a2 100644 --- a/sys/d3d11/gstd3d11decoder.c +++ b/sys/d3d11/gstd3d11decoder.c @@ -357,9 +357,8 @@ gst_d3d11_decoder_ensure_output_view (GstD3D11Decoder * self, GstD3D11Memory *mem; mem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, 0); - if (!gst_d3d11_memory_ensure_decoder_output_view (mem, priv->video_device, + if (!gst_d3d11_memory_get_decoder_output_view (mem, priv->video_device, &priv->decoder_profile)) { - GST_ERROR_OBJECT (self, "Decoder output view is unavailable"); return FALSE; } @@ -1065,12 +1064,16 @@ ID3D11VideoDecoderOutputView * gst_d3d11_decoder_get_output_view_from_buffer (GstD3D11Decoder * decoder, GstBuffer * buffer) { + GstD3D11DecoderPrivate *priv; GstMemory *mem; GstD3D11Memory *dmem; + ID3D11VideoDecoderOutputView *view; g_return_val_if_fail (GST_IS_D3D11_DECODER (decoder), NULL); g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL); + priv = decoder->priv; + mem = gst_buffer_peek_memory (buffer, 0); if (!gst_is_d3d11_memory (mem)) { GST_WARNING_OBJECT (decoder, "Not a d3d11 memory"); @@ -1078,13 +1081,15 @@ gst_d3d11_decoder_get_output_view_from_buffer (GstD3D11Decoder * decoder, } dmem = (GstD3D11Memory *) mem; + view = gst_d3d11_memory_get_decoder_output_view (dmem, priv->video_device, + &priv->decoder_profile); - if (!dmem->decoder_output_view) { - GST_WARNING_OBJECT (decoder, "memory does not have output view"); + if (!view) { + GST_ERROR_OBJECT (decoder, "Decoder output view is unavailable"); return NULL; } - return dmem->decoder_output_view; + return view; } guint8 @@ -1123,15 +1128,17 @@ copy_to_system (GstD3D11Decoder * self, GstVideoInfo * info, gint display_width, in_mem = (GstD3D11Memory *) gst_buffer_peek_memory (decoder_buffer, 0); - in_texture = in_mem->texture; - in_subresource_index = in_mem->subresource_index; + in_texture = gst_d3d11_memory_get_texture_handle (in_mem); + in_subresource_index = gst_d3d11_memory_get_subresource_index (in_mem); gst_d3d11_device_lock (priv->device); if (need_convert) { D3D11_BOX src_box; RECT rect; - ID3D11ShaderResourceView **srv = NULL; + ID3D11ShaderResourceView *srv[GST_VIDEO_MAX_PLANES] = { NULL, }; + guint srv_size; + guint i; GST_LOG_OBJECT (self, "convert resolution, %dx%d -> %dx%d", display_width, display_height, @@ -1146,21 +1153,23 @@ copy_to_system (GstD3D11Decoder * self, GstVideoInfo * info, gint display_width, /* array of texture can be used for shader resource view */ if (priv->use_array_of_texture && - gst_d3d11_memory_ensure_shader_resource_view (in_mem)) { + (srv_size = + gst_d3d11_memory_get_shader_resource_view_size (in_mem)) != 0) { GST_TRACE_OBJECT (self, "Decoded texture supports shader resource view"); - srv = in_mem->shader_resource_view; + for (i = 0; i < srv_size; i++) + srv[i] = gst_d3d11_memory_get_shader_resource_view (in_mem, i); } - if (!srv) { + if (!srv[0]) { /* copy decoded texture into shader resource texture */ GST_TRACE_OBJECT (self, "Copy decoded texture to internal shader texture"); ID3D11DeviceContext_CopySubresourceRegion (device_context, (ID3D11Resource *) priv->shader_resource_texture, 0, 0, 0, 0, - (ID3D11Resource *) in_mem->texture, in_mem->subresource_index, - &src_box); + (ID3D11Resource *) in_texture, in_subresource_index, &src_box); - srv = priv->shader_resource_view; + for (i = 0; i < priv->num_resource_views; i++) + srv[i] = priv->shader_resource_view[i]; } rect.left = 0; @@ -1241,19 +1250,26 @@ copy_to_d3d11 (GstD3D11Decoder * self, GstVideoInfo * info, gint display_width, GstD3D11DecoderPrivate *priv = self->priv; GstD3D11Memory *in_mem; GstD3D11Memory *out_mem; + GstMapInfo out_map; D3D11_BOX src_box; ID3D11Texture2D *in_texture; - guint in_subresource_index; + guint in_subresource_index, out_subresource_index; ID3D11DeviceContext *device_context = gst_d3d11_device_get_device_context_handle (priv->device); - - gst_d3d11_device_lock (priv->device); + gboolean ret = FALSE; in_mem = (GstD3D11Memory *) gst_buffer_peek_memory (decoder_buffer, 0); out_mem = (GstD3D11Memory *) gst_buffer_peek_memory (output, 0); - in_texture = in_mem->texture; - in_subresource_index = in_mem->subresource_index; + if (!gst_memory_map (GST_MEMORY_CAST (out_mem), + &out_map, GST_MAP_WRITE | GST_MAP_D3D11)) { + GST_ERROR_OBJECT (self, "Couldn't map output d3d11 memory"); + return FALSE; + } + + gst_d3d11_device_lock (priv->device); + in_texture = gst_d3d11_memory_get_texture_handle (in_mem); + in_subresource_index = gst_d3d11_memory_get_subresource_index (in_mem); src_box.left = 0; src_box.top = 0; @@ -1262,21 +1278,28 @@ copy_to_d3d11 (GstD3D11Decoder * self, GstVideoInfo * info, gint display_width, if (need_convert) { gboolean need_copy = FALSE; - ID3D11RenderTargetView **rtv; - ID3D11ShaderResourceView **srv = NULL; + ID3D11RenderTargetView *rtv[GST_VIDEO_MAX_PLANES] = { NULL, }; + ID3D11ShaderResourceView *srv[GST_VIDEO_MAX_PLANES] = { NULL, }; RECT rect; + guint rtv_size; + guint srv_size; + guint i; GST_LOG_OBJECT (self, "convert resolution, %dx%d -> %dx%d", display_width, display_height, priv->display_width, priv->display_height); - if (!gst_d3d11_memory_ensure_render_target_view (out_mem)) { + rtv_size = gst_d3d11_memory_get_render_target_view_size (out_mem); + + if (!rtv_size) { /* convert to fallback output view */ GST_LOG_OBJECT (self, "output memory cannot support render target view"); - rtv = priv->fallback_render_target_view; + for (i = 0; priv->num_resource_views; i++) + rtv[i] = priv->fallback_render_target_view[i]; need_copy = TRUE; } else { - rtv = out_mem->render_target_view; + for (i = 0; rtv_size; i++) + rtv[i] = gst_d3d11_memory_get_render_target_view (out_mem, i); } src_box.right = GST_ROUND_UP_2 (display_width); @@ -1284,20 +1307,21 @@ copy_to_d3d11 (GstD3D11Decoder * self, GstVideoInfo * info, gint display_width, /* array of texture can be used for shader resource view */ if (priv->use_array_of_texture && - gst_d3d11_memory_ensure_shader_resource_view (in_mem)) { + (srv_size = + gst_d3d11_memory_get_shader_resource_view_size (in_mem)) != 0) { GST_TRACE_OBJECT (self, "Decoded texture supports shader resource view"); - srv = in_mem->shader_resource_view; - } - - if (!srv) { + for (i = 0; i < srv_size; i++) + srv[i] = gst_d3d11_memory_get_shader_resource_view (in_mem, i); + } else { /* copy decoded texture into shader resource texture */ GST_TRACE_OBJECT (self, "Copy decoded texture to internal shader texture"); ID3D11DeviceContext_CopySubresourceRegion (device_context, (ID3D11Resource *) priv->shader_resource_texture, 0, 0, 0, 0, - (ID3D11Resource *) in_texture, in_mem->subresource_index, &src_box); + (ID3D11Resource *) in_texture, in_subresource_index, &src_box); - srv = priv->shader_resource_view; + for (i = 0; i < priv->num_resource_views; i++) + srv[i] = priv->shader_resource_view[i]; } rect.left = 0; @@ -1310,12 +1334,13 @@ copy_to_d3d11 (GstD3D11Decoder * self, GstVideoInfo * info, gint display_width, if (!gst_d3d11_color_converter_convert_unlocked (priv->converter, srv, rtv, NULL, NULL)) { GST_ERROR_OBJECT (self, "Failed to convert"); - goto error; + ret = FALSE; + goto out; } if (!need_copy) { - gst_d3d11_device_unlock (priv->device); - return TRUE; + ret = TRUE; + goto out; } in_texture = priv->fallback_shader_output_texture; @@ -1325,19 +1350,19 @@ copy_to_d3d11 (GstD3D11Decoder * self, GstVideoInfo * info, gint display_width, src_box.right = GST_ROUND_UP_2 (priv->display_width); src_box.bottom = GST_ROUND_UP_2 (priv->display_height); + out_subresource_index = gst_d3d11_memory_get_subresource_index (out_mem); ID3D11DeviceContext_CopySubresourceRegion (device_context, - (ID3D11Resource *) out_mem->texture, - out_mem->subresource_index, 0, 0, 0, + (ID3D11Resource *) out_map.data, out_subresource_index, 0, 0, 0, (ID3D11Resource *) in_texture, in_subresource_index, &src_box); - GST_MINI_OBJECT_FLAG_SET (out_mem, GST_D3D11_MEMORY_TRANSFER_NEED_DOWNLOAD); + ret = TRUE; + +out: gst_d3d11_device_unlock (priv->device); - return TRUE; + gst_memory_unmap (GST_MEMORY_CAST (out_mem), &out_map); -error: - gst_d3d11_device_unlock (priv->device); - return FALSE; + return ret; } gboolean diff --git a/sys/d3d11/gstd3d11download.c b/sys/d3d11/gstd3d11download.c index 769e88b9e0..499832fb60 100644 --- a/sys/d3d11/gstd3d11download.c +++ b/sys/d3d11/gstd3d11download.c @@ -348,15 +348,11 @@ gst_d3d11_download_can_use_staging_buffer (GstD3D11Download * self, GstBuffer * inbuf) { GstD3D11BaseFilter *filter = GST_D3D11_BASE_FILTER (self); - gint i; + ID3D11Device *device_handle = + gst_d3d11_device_get_device_handle (filter->device); - /* staging buffer doesn't need to be used for non-d3d11 memory */ - for (i = 0; i < gst_buffer_n_memory (inbuf); i++) { - GstMemory *mem = gst_buffer_peek_memory (inbuf, i); - - if (!gst_is_d3d11_memory (mem)) - return FALSE; - } + if (!gst_d3d11_buffer_can_access_device (inbuf, device_handle)) + return FALSE; if (self->staging_buffer) return TRUE; @@ -390,7 +386,8 @@ gst_d3d11_download_transform (GstBaseTransform * trans, GstBuffer * inbuf, GST_TRACE_OBJECT (self, "Copy input buffer to staging buffer"); /* Copy d3d11 texture to staging texture */ - if (!gst_d3d11_buffer_copy_into (self->staging_buffer, inbuf)) { + if (!gst_d3d11_buffer_copy_into (self->staging_buffer, + inbuf, &filter->in_info)) { GST_ERROR_OBJECT (self, "Failed to copy input buffer into staging texture"); return GST_FLOW_ERROR; diff --git a/sys/d3d11/gstd3d11h264dec.c b/sys/d3d11/gstd3d11h264dec.c index 2792aa8ddc..72aee4d726 100644 --- a/sys/d3d11/gstd3d11h264dec.c +++ b/sys/d3d11/gstd3d11h264dec.c @@ -766,7 +766,6 @@ gst_d3d11_h264_dec_new_picture (GstH264Decoder * decoder, { GstD3D11H264Dec *self = GST_D3D11_H264_DEC (decoder); GstBuffer *view_buffer; - GstD3D11Memory *mem; view_buffer = gst_d3d11_decoder_get_output_view_buffer (self->d3d11_decoder); if (!view_buffer) { @@ -774,10 +773,7 @@ gst_d3d11_h264_dec_new_picture (GstH264Decoder * decoder, return FALSE; } - mem = (GstD3D11Memory *) gst_buffer_peek_memory (view_buffer, 0); - - GST_LOG_OBJECT (self, "New output view buffer %" GST_PTR_FORMAT " (index %d)", - view_buffer, mem->subresource_index); + GST_LOG_OBJECT (self, "New output view buffer %" GST_PTR_FORMAT, view_buffer); gst_h264_picture_set_user_data (picture, view_buffer, (GDestroyNotify) gst_buffer_unref); @@ -793,7 +789,6 @@ gst_d3d11_h264_dec_new_field_picture (GstH264Decoder * decoder, { GstD3D11H264Dec *self = GST_D3D11_H264_DEC (decoder); GstBuffer *view_buffer; - GstD3D11Memory *mem; view_buffer = gst_h264_picture_get_user_data ((GstH264Picture *) first_field); @@ -802,10 +797,8 @@ gst_d3d11_h264_dec_new_field_picture (GstH264Decoder * decoder, return TRUE; } - mem = (GstD3D11Memory *) gst_buffer_peek_memory (view_buffer, 0); - - GST_LOG_OBJECT (self, "New field picture with buffer %" GST_PTR_FORMAT - " (index %d)", view_buffer, mem->subresource_index); + GST_LOG_OBJECT (self, "New field picture with buffer %" GST_PTR_FORMAT, + view_buffer); gst_h264_picture_set_user_data (second_field, gst_buffer_ref (view_buffer), (GDestroyNotify) gst_buffer_unref); diff --git a/sys/d3d11/gstd3d11h265dec.c b/sys/d3d11/gstd3d11h265dec.c index 62468dbe1f..a4f18572ae 100644 --- a/sys/d3d11/gstd3d11h265dec.c +++ b/sys/d3d11/gstd3d11h265dec.c @@ -750,7 +750,6 @@ gst_d3d11_h265_dec_new_picture (GstH265Decoder * decoder, { GstD3D11H265Dec *self = GST_D3D11_H265_DEC (decoder); GstBuffer *view_buffer; - GstD3D11Memory *mem; view_buffer = gst_d3d11_decoder_get_output_view_buffer (self->d3d11_decoder); if (!view_buffer) { @@ -758,10 +757,7 @@ gst_d3d11_h265_dec_new_picture (GstH265Decoder * decoder, return FALSE; } - mem = (GstD3D11Memory *) gst_buffer_peek_memory (view_buffer, 0); - - GST_LOG_OBJECT (self, "New output view buffer %" GST_PTR_FORMAT " (index %d)", - view_buffer, mem->subresource_index); + GST_LOG_OBJECT (self, "New output view buffer %" GST_PTR_FORMAT, view_buffer); gst_h265_picture_set_user_data (picture, view_buffer, (GDestroyNotify) gst_buffer_unref); diff --git a/sys/d3d11/gstd3d11memory.c b/sys/d3d11/gstd3d11memory.c index f8291d8f19..0fe3e9beaf 100644 --- a/sys/d3d11/gstd3d11memory.c +++ b/sys/d3d11/gstd3d11memory.c @@ -34,7 +34,7 @@ GST_DEBUG_CATEGORY_STATIC (gst_d3d11_allocator_debug); #define GST_D3D11_ALLOCATOR_UNLOCK(a) g_mutex_unlock(GST_D3D11_ALLOCATOR_GET_LOCK(a)) #define GST_D3D11_MEMORY_CAST(m) ((GstD3D11Memory *) m) -#define GST_D3D11_MEMORY_GET_LOCK(m) (&(GST_D3D11_MEMORY_CAST(m)->lock)) +#define GST_D3D11_MEMORY_GET_LOCK(m) (&(GST_D3D11_MEMORY_CAST(m)->priv->lock)) #define GST_D3D11_MEMORY_LOCK(m) g_mutex_lock(GST_D3D11_MEMORY_GET_LOCK(m)) #define GST_D3D11_MEMORY_UNLOCK(m) g_mutex_unlock(GST_D3D11_MEMORY_GET_LOCK(m)) @@ -191,6 +191,41 @@ G_DEFINE_BOXED_TYPE_WITH_CODE (GstD3D11AllocationParams, (GBoxedFreeFunc) gst_d3d11_allocation_params_free, _init_alloc_params (g_define_type_id)); +typedef enum +{ + GST_D3D11_MEMORY_TYPE_TEXTURE = 0, + GST_D3D11_MEMORY_TYPE_ARRAY = 1, + GST_D3D11_MEMORY_TYPE_STAGING = 2, +} GstD3D11MemoryType; + +struct _GstD3D11MemoryPrivate +{ + GstD3D11MemoryType type; + + ID3D11Texture2D *texture; + D3D11_TEXTURE2D_DESC desc; + + /* valid only for array typed memory */ + guint subresource_index; + + ID3D11Texture2D *staging; + + ID3D11ShaderResourceView *shader_resource_view[GST_VIDEO_MAX_PLANES]; + guint num_shader_resource_views; + + ID3D11RenderTargetView *render_target_view[GST_VIDEO_MAX_PLANES]; + guint num_render_target_views; + + ID3D11VideoDecoderOutputView *decoder_output_view; + ID3D11VideoProcessorInputView *processor_input_view; + ID3D11VideoProcessorOutputView *processor_output_view; + + D3D11_MAPPED_SUBRESOURCE map; + + GMutex lock; + gint cpu_map_count; +}; + struct _GstD3D11AllocatorPrivate { /* parent texture when array typed memory is used */ @@ -254,21 +289,22 @@ create_staging_texture (GstD3D11Device * device, static gboolean map_cpu_access_data (GstD3D11Memory * dmem, D3D11_MAP map_type) { + GstD3D11MemoryPrivate *priv = dmem->priv; HRESULT hr; gboolean ret = TRUE; - ID3D11Resource *texture = (ID3D11Resource *) dmem->texture; - ID3D11Resource *staging = (ID3D11Resource *) dmem->staging; + ID3D11Resource *texture = (ID3D11Resource *) priv->texture; + ID3D11Resource *staging = (ID3D11Resource *) priv->staging; ID3D11DeviceContext *device_context = gst_d3d11_device_get_device_context_handle (dmem->device); gst_d3d11_device_lock (dmem->device); if (GST_MEMORY_FLAG_IS_SET (dmem, GST_D3D11_MEMORY_TRANSFER_NEED_DOWNLOAD)) { ID3D11DeviceContext_CopySubresourceRegion (device_context, - staging, 0, 0, 0, 0, texture, dmem->subresource_index, NULL); + staging, 0, 0, 0, 0, texture, priv->subresource_index, NULL); } hr = ID3D11DeviceContext_Map (device_context, - staging, 0, map_type, 0, &dmem->map); + staging, 0, map_type, 0, &priv->map); if (!gst_d3d11_result (hr, dmem->device)) { GST_ERROR_OBJECT (GST_MEMORY_CAST (dmem)->allocator, @@ -285,9 +321,10 @@ static gpointer gst_d3d11_memory_map_staging (GstMemory * mem, GstMapFlags flags) { GstD3D11Memory *dmem = (GstD3D11Memory *) mem; + GstD3D11MemoryPrivate *priv = dmem->priv; GST_D3D11_MEMORY_LOCK (dmem); - if (dmem->cpu_map_count == 0) { + if (priv->cpu_map_count == 0) { ID3D11DeviceContext *device_context = gst_d3d11_device_get_device_context_handle (dmem->device); D3D11_MAP map_type; @@ -298,7 +335,7 @@ gst_d3d11_memory_map_staging (GstMemory * mem, GstMapFlags flags) gst_d3d11_device_lock (dmem->device); hr = ID3D11DeviceContext_Map (device_context, - (ID3D11Resource *) dmem->texture, 0, map_type, 0, &dmem->map); + (ID3D11Resource *) priv->texture, 0, map_type, 0, &priv->map); if (!gst_d3d11_result (hr, dmem->device)) { GST_ERROR_OBJECT (GST_MEMORY_CAST (dmem)->allocator, "Failed to map staging texture (0x%x)", (guint) hr); @@ -312,35 +349,36 @@ gst_d3d11_memory_map_staging (GstMemory * mem, GstMapFlags flags) } } - dmem->cpu_map_count++; + priv->cpu_map_count++; GST_D3D11_MEMORY_UNLOCK (dmem); - return dmem->map.pData; + return dmem->priv->map.pData; } static gpointer gst_d3d11_memory_map (GstMemory * mem, gsize maxsize, GstMapFlags flags) { GstD3D11Memory *dmem = (GstD3D11Memory *) mem; + GstD3D11MemoryPrivate *priv = dmem->priv; - if (dmem->type == GST_D3D11_MEMORY_TYPE_STAGING) { + if (priv->type == GST_D3D11_MEMORY_TYPE_STAGING) { if ((flags & GST_MAP_D3D11) == GST_MAP_D3D11) - return dmem->texture; + return priv->texture; return gst_d3d11_memory_map_staging (mem, flags); } GST_D3D11_MEMORY_LOCK (dmem); if ((flags & GST_MAP_D3D11) == GST_MAP_D3D11) { - if (dmem->staging && + if (priv->staging && GST_MEMORY_FLAG_IS_SET (dmem, GST_D3D11_MEMORY_TRANSFER_NEED_UPLOAD)) { ID3D11DeviceContext *device_context = gst_d3d11_device_get_device_context_handle (dmem->device); gst_d3d11_device_lock (dmem->device); ID3D11DeviceContext_CopySubresourceRegion (device_context, - (ID3D11Resource *) dmem->texture, dmem->subresource_index, 0, 0, 0, - (ID3D11Resource *) dmem->staging, 0, NULL); + (ID3D11Resource *) priv->texture, priv->subresource_index, 0, 0, 0, + (ID3D11Resource *) priv->staging, 0, NULL); gst_d3d11_device_unlock (dmem->device); } @@ -349,21 +387,21 @@ gst_d3d11_memory_map (GstMemory * mem, gsize maxsize, GstMapFlags flags) if ((flags & GST_MAP_WRITE) == GST_MAP_WRITE) GST_MINI_OBJECT_FLAG_SET (dmem, GST_D3D11_MEMORY_TRANSFER_NEED_DOWNLOAD); - g_assert (dmem->texture != NULL); + g_assert (priv->texture != NULL); GST_D3D11_MEMORY_UNLOCK (dmem); - return dmem->texture; + return priv->texture; } - if (dmem->cpu_map_count == 0) { + if (priv->cpu_map_count == 0) { D3D11_MAP map_type; /* Allocate staging texture for CPU access */ - if (!dmem->staging) { - dmem->staging = create_staging_texture (dmem->device, &dmem->desc); - if (!dmem->staging) { + if (!priv->staging) { + priv->staging = create_staging_texture (dmem->device, &priv->desc); + if (!priv->staging) { GST_ERROR_OBJECT (mem->allocator, "Couldn't create staging texture"); - g_mutex_unlock (&dmem->lock); + GST_D3D11_MEMORY_UNLOCK (dmem); return NULL; } @@ -387,21 +425,22 @@ gst_d3d11_memory_map (GstMemory * mem, gsize maxsize, GstMapFlags flags) GST_MEMORY_FLAG_UNSET (mem, GST_D3D11_MEMORY_TRANSFER_NEED_DOWNLOAD); - dmem->cpu_map_count++; + priv->cpu_map_count++; GST_D3D11_MEMORY_UNLOCK (dmem); - return dmem->map.pData; + return dmem->priv->map.pData; } static void unmap_cpu_access_data (GstD3D11Memory * dmem) { - ID3D11Resource *staging = (ID3D11Resource *) dmem->staging; + GstD3D11MemoryPrivate *priv = dmem->priv; + ID3D11Resource *staging = (ID3D11Resource *) priv->staging; ID3D11DeviceContext *device_context = gst_d3d11_device_get_device_context_handle (dmem->device); - if (dmem->type == GST_D3D11_MEMORY_TYPE_STAGING) - staging = (ID3D11Resource *) dmem->texture; + if (priv->type == GST_D3D11_MEMORY_TYPE_STAGING) + staging = (ID3D11Resource *) priv->texture; gst_d3d11_device_lock (dmem->device); ID3D11DeviceContext_Unmap (device_context, staging, 0); @@ -412,10 +451,11 @@ static void gst_d3d11_memory_unmap_full (GstMemory * mem, GstMapInfo * info) { GstD3D11Memory *dmem = (GstD3D11Memory *) mem; + GstD3D11MemoryPrivate *priv = dmem->priv; GST_D3D11_MEMORY_LOCK (dmem); if ((info->flags & GST_MAP_D3D11) == GST_MAP_D3D11) { - if (dmem->type != GST_D3D11_MEMORY_TYPE_STAGING && + if (priv->type != GST_D3D11_MEMORY_TYPE_STAGING && (info->flags & GST_MAP_WRITE) == GST_MAP_WRITE) GST_MINI_OBJECT_FLAG_SET (mem, GST_D3D11_MEMORY_TRANSFER_NEED_DOWNLOAD); @@ -423,12 +463,12 @@ gst_d3d11_memory_unmap_full (GstMemory * mem, GstMapInfo * info) return; } - if (dmem->type != GST_D3D11_MEMORY_TYPE_STAGING && + if (priv->type != GST_D3D11_MEMORY_TYPE_STAGING && (info->flags & GST_MAP_WRITE)) GST_MINI_OBJECT_FLAG_SET (mem, GST_D3D11_MEMORY_TRANSFER_NEED_UPLOAD); - dmem->cpu_map_count--; - if (dmem->cpu_map_count > 0) { + priv->cpu_map_count--; + if (priv->cpu_map_count > 0) { GST_D3D11_MEMORY_UNLOCK (dmem); return; } @@ -458,43 +498,43 @@ gst_d3d11_allocator_free (GstAllocator * allocator, GstMemory * mem) GstD3D11Allocator *self = GST_D3D11_ALLOCATOR (allocator); GstD3D11AllocatorPrivate *priv = self->priv; GstD3D11Memory *dmem = (GstD3D11Memory *) mem; + GstD3D11MemoryPrivate *dmem_priv = dmem->priv; gint i; if (priv->array_in_use) { GST_D3D11_ALLOCATOR_LOCK (self); - g_array_index (priv->array_in_use, guint8, dmem->subresource_index) = 0; + g_array_index (priv->array_in_use, + guint8, dmem_priv->subresource_index) = 0; g_cond_broadcast (&priv->cond); GST_D3D11_ALLOCATOR_UNLOCK (self); } for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) { - if (dmem->render_target_view[i]) - ID3D11RenderTargetView_Release (dmem->render_target_view[i]); - dmem->render_target_view[i] = NULL; + if (dmem_priv->render_target_view[i]) + ID3D11RenderTargetView_Release (dmem_priv->render_target_view[i]); - if (dmem->shader_resource_view[i]) - ID3D11ShaderResourceView_Release (dmem->shader_resource_view[i]); - dmem->shader_resource_view[i] = NULL; + if (dmem_priv->shader_resource_view[i]) + ID3D11ShaderResourceView_Release (dmem_priv->shader_resource_view[i]); } - if (dmem->decoder_output_view) - ID3D11VideoDecoderOutputView_Release (dmem->decoder_output_view); + if (dmem_priv->decoder_output_view) + ID3D11VideoDecoderOutputView_Release (dmem_priv->decoder_output_view); - if (dmem->processor_input_view) - ID3D11VideoProcessorInputView_Release (dmem->processor_input_view); + if (dmem_priv->processor_input_view) + ID3D11VideoProcessorInputView_Release (dmem_priv->processor_input_view); - if (dmem->processor_output_view) - ID3D11VideoProcessorOutputView_Release (dmem->processor_output_view); + if (dmem_priv->processor_output_view) + ID3D11VideoProcessorOutputView_Release (dmem_priv->processor_output_view); - if (dmem->texture) - ID3D11Texture2D_Release (dmem->texture); + if (dmem_priv->texture) + ID3D11Texture2D_Release (dmem_priv->texture); - if (dmem->staging) - ID3D11Texture2D_Release (dmem->staging); + if (dmem_priv->staging) + ID3D11Texture2D_Release (dmem_priv->staging); gst_clear_object (&dmem->device); - g_mutex_clear (&dmem->lock); - + g_mutex_clear (&dmem_priv->lock); + g_free (dmem->priv); g_free (dmem); } @@ -615,6 +655,7 @@ calculate_mem_size (GstD3D11Device * device, ID3D11Texture2D * texture, static gboolean create_shader_resource_views (GstD3D11Memory * mem) { + GstD3D11MemoryPrivate *priv = mem->priv; gint i; HRESULT hr; guint num_views = 0; @@ -624,7 +665,7 @@ create_shader_resource_views (GstD3D11Memory * mem) device_handle = gst_d3d11_device_get_device_handle (mem->device); - switch (mem->desc.Format) { + switch (priv->desc.Format) { case DXGI_FORMAT_B8G8R8A8_UNORM: case DXGI_FORMAT_R8G8B8A8_UNORM: case DXGI_FORMAT_R10G10B10A2_UNORM: @@ -636,7 +677,7 @@ create_shader_resource_views (GstD3D11Memory * mem) case DXGI_FORMAT_R8G8_B8G8_UNORM: case DXGI_FORMAT_R16G16B16A16_UNORM: num_views = 1; - formats[0] = mem->desc.Format; + formats[0] = priv->desc.Format; break; case DXGI_FORMAT_AYUV: case DXGI_FORMAT_YUY2: @@ -667,7 +708,7 @@ create_shader_resource_views (GstD3D11Memory * mem) return FALSE; } - if ((mem->desc.BindFlags & D3D11_BIND_SHADER_RESOURCE) == + if ((priv->desc.BindFlags & D3D11_BIND_SHADER_RESOURCE) == D3D11_BIND_SHADER_RESOURCE) { resource_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; resource_desc.Texture2D.MipLevels = 1; @@ -675,8 +716,8 @@ create_shader_resource_views (GstD3D11Memory * mem) for (i = 0; i < num_views; i++) { resource_desc.Format = formats[i]; hr = ID3D11Device_CreateShaderResourceView (device_handle, - (ID3D11Resource *) mem->texture, &resource_desc, - &mem->shader_resource_view[i]); + (ID3D11Resource *) priv->texture, &resource_desc, + &priv->shader_resource_view[i]); if (!gst_d3d11_result (hr, mem->device)) { GST_ERROR_OBJECT (GST_MEMORY_CAST (mem)->allocator, @@ -685,7 +726,7 @@ create_shader_resource_views (GstD3D11Memory * mem) } } - mem->num_shader_resource_views = num_views; + priv->num_shader_resource_views = num_views; return TRUE; } @@ -694,12 +735,12 @@ create_shader_resource_views (GstD3D11Memory * mem) error: for (i = 0; i < num_views; i++) { - if (mem->shader_resource_view[i]) - ID3D11ShaderResourceView_Release (mem->shader_resource_view[i]); - mem->shader_resource_view[i] = NULL; + if (priv->shader_resource_view[i]) + ID3D11ShaderResourceView_Release (priv->shader_resource_view[i]); + priv->shader_resource_view[i] = NULL; } - mem->num_shader_resource_views = 0; + priv->num_shader_resource_views = 0; return FALSE; } @@ -707,6 +748,7 @@ error: static gboolean create_render_target_views (GstD3D11Memory * mem) { + GstD3D11MemoryPrivate *priv = mem->priv; gint i; HRESULT hr; guint num_views = 0; @@ -716,7 +758,7 @@ create_render_target_views (GstD3D11Memory * mem) device_handle = gst_d3d11_device_get_device_handle (mem->device); - switch (mem->desc.Format) { + switch (priv->desc.Format) { case DXGI_FORMAT_B8G8R8A8_UNORM: case DXGI_FORMAT_R8G8B8A8_UNORM: case DXGI_FORMAT_R10G10B10A2_UNORM: @@ -725,7 +767,7 @@ create_render_target_views (GstD3D11Memory * mem) case DXGI_FORMAT_R16_UNORM: case DXGI_FORMAT_R16G16_UNORM: num_views = 1; - formats[0] = mem->desc.Format; + formats[0] = priv->desc.Format; break; case DXGI_FORMAT_AYUV: num_views = 1; @@ -747,7 +789,7 @@ create_render_target_views (GstD3D11Memory * mem) return FALSE; } - if ((mem->desc.BindFlags & D3D11_BIND_RENDER_TARGET) == + if ((priv->desc.BindFlags & D3D11_BIND_RENDER_TARGET) == D3D11_BIND_RENDER_TARGET) { render_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; render_desc.Texture2D.MipSlice = 0; @@ -756,8 +798,8 @@ create_render_target_views (GstD3D11Memory * mem) render_desc.Format = formats[i]; hr = ID3D11Device_CreateRenderTargetView (device_handle, - (ID3D11Resource *) mem->texture, &render_desc, - &mem->render_target_view[i]); + (ID3D11Resource *) priv->texture, &render_desc, + &priv->render_target_view[i]); if (!gst_d3d11_result (hr, mem->device)) { GST_ERROR_OBJECT (GST_MEMORY_CAST (mem)->allocator, "Failed to create %dth render target view (0x%x)", i, (guint) hr); @@ -765,7 +807,7 @@ create_render_target_views (GstD3D11Memory * mem) } } - mem->num_render_target_views = num_views; + priv->num_render_target_views = num_views; return TRUE; } @@ -774,12 +816,12 @@ create_render_target_views (GstD3D11Memory * mem) error: for (i = 0; i < num_views; i++) { - if (mem->render_target_view[i]) - ID3D11RenderTargetView_Release (mem->render_target_view[i]); - mem->render_target_view[i] = NULL; + if (priv->render_target_view[i]) + ID3D11RenderTargetView_Release (priv->render_target_view[i]); + priv->render_target_view[i] = NULL; } - mem->num_render_target_views = 0; + priv->num_render_target_views = 0; return FALSE; } @@ -915,16 +957,17 @@ gst_d3d11_allocator_alloc (GstD3D11Allocator * allocator, } mem = g_new0 (GstD3D11Memory, 1); + mem->priv = g_new0 (GstD3D11MemoryPrivate, 1); gst_memory_init (GST_MEMORY_CAST (mem), 0, GST_ALLOCATOR_CAST (allocator), NULL, size, 0, 0, size); - g_mutex_init (&mem->lock); - mem->desc = *desc; - mem->texture = texture; + g_mutex_init (&mem->priv->lock); + mem->priv->texture = texture; + mem->priv->desc = *desc; + mem->priv->type = type; + mem->priv->subresource_index = index_to_use; mem->device = gst_object_ref (device); - mem->type = type; - mem->subresource_index = index_to_use; return GST_MEMORY_CAST (mem); @@ -964,15 +1007,16 @@ gst_d3d11_allocator_alloc_staging (GstD3D11Allocator * allocator, } mem = g_new0 (GstD3D11Memory, 1); + mem->priv = g_new0 (GstD3D11MemoryPrivate, 1); gst_memory_init (GST_MEMORY_CAST (mem), 0, GST_ALLOCATOR_CAST (allocator), NULL, mem_size, 0, 0, mem_size); - g_mutex_init (&mem->lock); - mem->desc = *desc; - mem->texture = texture; + g_mutex_init (&mem->priv->lock); + mem->priv->texture = texture; + mem->priv->desc = *desc; + mem->priv->type = GST_D3D11_MEMORY_TYPE_STAGING; mem->device = gst_object_ref (device); - mem->type = GST_D3D11_MEMORY_TYPE_STAGING; /* every plan will have identical size */ if (stride) @@ -1010,21 +1054,48 @@ gst_is_d3d11_memory (GstMemory * mem) GST_IS_D3D11_ALLOCATOR (mem->allocator); } +ID3D11Texture2D * +gst_d3d11_memory_get_texture_handle (GstD3D11Memory * mem) +{ + g_return_val_if_fail (gst_is_d3d11_memory (GST_MEMORY_CAST (mem)), NULL); + + return mem->priv->texture; +} + +guint +gst_d3d11_memory_get_subresource_index (GstD3D11Memory * mem) +{ + g_return_val_if_fail (gst_is_d3d11_memory (GST_MEMORY_CAST (mem)), 0); + + return mem->priv->subresource_index; +} + gboolean +gst_d3d11_memory_get_texture_desc (GstD3D11Memory * mem, + D3D11_TEXTURE2D_DESC * desc) +{ + g_return_val_if_fail (gst_is_d3d11_memory (GST_MEMORY_CAST (mem)), FALSE); + g_return_val_if_fail (desc != NULL, FALSE); + + *desc = mem->priv->desc; + + return TRUE; +} + +static gboolean gst_d3d11_memory_ensure_shader_resource_view (GstD3D11Memory * mem) { + GstD3D11MemoryPrivate *priv = mem->priv; gboolean ret = FALSE; - g_return_val_if_fail (gst_is_d3d11_memory (GST_MEMORY_CAST (mem)), FALSE); - - if (!(mem->desc.BindFlags & D3D11_BIND_SHADER_RESOURCE)) { + if (!(priv->desc.BindFlags & D3D11_BIND_SHADER_RESOURCE)) { GST_LOG_OBJECT (GST_MEMORY_CAST (mem)->allocator, - "Need BindFlags, current flag 0x%x", mem->desc.BindFlags); + "Need BindFlags, current flag 0x%x", priv->desc.BindFlags); return FALSE; } GST_D3D11_MEMORY_LOCK (mem); - if (mem->num_shader_resource_views) { + if (priv->num_shader_resource_views) { ret = TRUE; goto done; } @@ -1037,21 +1108,51 @@ done: return ret; } -gboolean +guint +gst_d3d11_memory_get_shader_resource_view_size (GstD3D11Memory * mem) +{ + g_return_val_if_fail (gst_is_d3d11_memory (GST_MEMORY_CAST (mem)), 0); + + if (!gst_d3d11_memory_ensure_shader_resource_view (mem)) + return 0; + + return mem->priv->num_shader_resource_views; +} + +ID3D11ShaderResourceView * +gst_d3d11_memory_get_shader_resource_view (GstD3D11Memory * mem, guint index) +{ + GstD3D11MemoryPrivate *priv; + + g_return_val_if_fail (gst_is_d3d11_memory (GST_MEMORY_CAST (mem)), NULL); + + if (!gst_d3d11_memory_ensure_shader_resource_view (mem)) + return NULL; + + priv = mem->priv; + + if (index >= priv->num_shader_resource_views) { + GST_ERROR ("Invalid SRV index %d", index); + return NULL; + } + + return priv->shader_resource_view[index]; +} + +static gboolean gst_d3d11_memory_ensure_render_target_view (GstD3D11Memory * mem) { + GstD3D11MemoryPrivate *priv = mem->priv; gboolean ret = FALSE; - g_return_val_if_fail (gst_is_d3d11_memory (GST_MEMORY_CAST (mem)), FALSE); - - if (!(mem->desc.BindFlags & D3D11_BIND_RENDER_TARGET)) { + if (!(priv->desc.BindFlags & D3D11_BIND_RENDER_TARGET)) { GST_WARNING_OBJECT (GST_MEMORY_CAST (mem)->allocator, - "Need BindFlags, current flag 0x%x", mem->desc.BindFlags); + "Need BindFlags, current flag 0x%x", priv->desc.BindFlags); return FALSE; } GST_D3D11_MEMORY_LOCK (mem); - if (mem->num_render_target_views) { + if (priv->num_render_target_views) { ret = TRUE; goto done; } @@ -1064,10 +1165,42 @@ done: return ret; } -gboolean +guint +gst_d3d11_memory_get_render_target_view_size (GstD3D11Memory * mem) +{ + g_return_val_if_fail (gst_is_d3d11_memory (GST_MEMORY_CAST (mem)), 0); + + if (!gst_d3d11_memory_ensure_render_target_view (mem)) + return 0; + + return mem->priv->num_render_target_views; +} + +ID3D11RenderTargetView * +gst_d3d11_memory_get_render_target_view (GstD3D11Memory * mem, guint index) +{ + GstD3D11MemoryPrivate *priv; + + g_return_val_if_fail (gst_is_d3d11_memory (GST_MEMORY_CAST (mem)), NULL); + + if (!gst_d3d11_memory_ensure_render_target_view (mem)) + return NULL; + + priv = mem->priv; + + if (index >= priv->num_render_target_views) { + GST_ERROR ("Invalid RTV index %d", index); + return NULL; + } + + return priv->render_target_view[index]; +} + +static gboolean gst_d3d11_memory_ensure_decoder_output_view (GstD3D11Memory * mem, ID3D11VideoDevice * video_device, GUID * decoder_profile) { + GstD3D11MemoryPrivate *dmem_priv = mem->priv; GstD3D11Allocator *allocator; GstD3D11AllocatorPrivate *priv; D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC desc; @@ -1075,37 +1208,34 @@ gst_d3d11_memory_ensure_decoder_output_view (GstD3D11Memory * mem, HRESULT hr; gboolean ret = FALSE; - g_return_val_if_fail (gst_is_d3d11_memory (GST_MEMORY_CAST (mem)), FALSE); - g_return_val_if_fail (video_device != NULL, FALSE); - g_return_val_if_fail (decoder_profile != NULL, FALSE); - allocator = GST_D3D11_ALLOCATOR (GST_MEMORY_CAST (mem)->allocator); priv = allocator->priv; - if (!(mem->desc.BindFlags & D3D11_BIND_DECODER)) { + if (!(dmem_priv->desc.BindFlags & D3D11_BIND_DECODER)) { GST_LOG_OBJECT (allocator, - "Need BindFlags, current flag 0x%x", mem->desc.BindFlags); + "Need BindFlags, current flag 0x%x", dmem_priv->desc.BindFlags); return FALSE; } GST_D3D11_MEMORY_LOCK (mem); - if (mem->decoder_output_view) { - ID3D11VideoDecoderOutputView_GetDesc (mem->decoder_output_view, &desc); + if (dmem_priv->decoder_output_view) { + ID3D11VideoDecoderOutputView_GetDesc (dmem_priv->decoder_output_view, + &desc); if (IsEqualGUID (&desc.DecodeProfile, decoder_profile)) { goto succeeded; } else { /* Shouldn't happen, but try again anyway */ GST_WARNING_OBJECT (allocator, "Existing view has different decoder profile"); - ID3D11VideoDecoderOutputView_Release (mem->decoder_output_view); - mem->decoder_output_view = NULL; + ID3D11VideoDecoderOutputView_Release (dmem_priv->decoder_output_view); + dmem_priv->decoder_output_view = NULL; } } if (priv->decoder_output_view_array) { GST_D3D11_ALLOCATOR_LOCK (allocator); view = g_array_index (priv->decoder_output_view_array, - ID3D11VideoDecoderOutputView *, mem->subresource_index); + ID3D11VideoDecoderOutputView *, dmem_priv->subresource_index); if (view) { ID3D11VideoDecoderOutputView_GetDesc (view, &desc); @@ -1117,25 +1247,27 @@ gst_d3d11_memory_ensure_decoder_output_view (GstD3D11Memory * mem, ID3D11VideoDecoderOutputView_Release (view); view = NULL; g_array_index (priv->decoder_output_view_array, - ID3D11VideoDecoderOutputView *, mem->subresource_index) = NULL; + ID3D11VideoDecoderOutputView *, + dmem_priv->subresource_index) = NULL; } else { /* Increase refcount and reuse existing view */ - mem->decoder_output_view = view; + dmem_priv->decoder_output_view = view; ID3D11VideoDecoderOutputView_AddRef (view); } } GST_D3D11_ALLOCATOR_UNLOCK (allocator); } - if (mem->decoder_output_view) + if (dmem_priv->decoder_output_view) goto succeeded; desc.DecodeProfile = *decoder_profile; desc.ViewDimension = D3D11_VDOV_DIMENSION_TEXTURE2D; - desc.Texture2D.ArraySlice = mem->subresource_index; + desc.Texture2D.ArraySlice = dmem_priv->subresource_index; hr = ID3D11VideoDevice_CreateVideoDecoderOutputView (video_device, - (ID3D11Resource *) mem->texture, &desc, &mem->decoder_output_view); + (ID3D11Resource *) dmem_priv->texture, &desc, + &dmem_priv->decoder_output_view); if (!gst_d3d11_result (hr, mem->device)) { GST_ERROR_OBJECT (allocator, "Could not create decoder output view, hr: 0x%x", (guint) hr); @@ -1146,15 +1278,15 @@ gst_d3d11_memory_ensure_decoder_output_view (GstD3D11Memory * mem, if (priv->decoder_output_view_array) { GST_D3D11_ALLOCATOR_LOCK (allocator); view = g_array_index (priv->decoder_output_view_array, - ID3D11VideoDecoderOutputView *, mem->subresource_index); + ID3D11VideoDecoderOutputView *, dmem_priv->subresource_index); if (view) ID3D11VideoDecoderOutputView_Release (view); g_array_index (priv->decoder_output_view_array, - ID3D11VideoDecoderOutputView *, mem->subresource_index) = - mem->decoder_output_view; - ID3D11VideoDecoderOutputView_AddRef (mem->decoder_output_view); + ID3D11VideoDecoderOutputView *, dmem_priv->subresource_index) = + dmem_priv->decoder_output_view; + ID3D11VideoDecoderOutputView_AddRef (dmem_priv->decoder_output_view); GST_D3D11_ALLOCATOR_UNLOCK (allocator); } @@ -1167,11 +1299,27 @@ done: return ret; } -gboolean +ID3D11VideoDecoderOutputView * +gst_d3d11_memory_get_decoder_output_view (GstD3D11Memory * mem, + ID3D11VideoDevice * video_device, GUID * decoder_profile) +{ + g_return_val_if_fail (gst_is_d3d11_memory (GST_MEMORY_CAST (mem)), NULL); + g_return_val_if_fail (video_device != NULL, NULL); + g_return_val_if_fail (decoder_profile != NULL, NULL); + + if (!gst_d3d11_memory_ensure_decoder_output_view (mem, + video_device, decoder_profile)) + return NULL; + + return mem->priv->decoder_output_view; +} + +static gboolean gst_d3d11_memory_ensure_processor_input_view (GstD3D11Memory * mem, ID3D11VideoDevice * video_device, ID3D11VideoProcessorEnumerator * enumerator) { + GstD3D11MemoryPrivate *dmem_priv = mem->priv; GstD3D11Allocator *allocator; GstD3D11AllocatorPrivate *priv; D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC desc; @@ -1179,47 +1327,43 @@ gst_d3d11_memory_ensure_processor_input_view (GstD3D11Memory * mem, HRESULT hr; gboolean ret = FALSE; - g_return_val_if_fail (gst_is_d3d11_memory (GST_MEMORY_CAST (mem)), FALSE); - g_return_val_if_fail (video_device != NULL, FALSE); - g_return_val_if_fail (enumerator != NULL, FALSE); - allocator = GST_D3D11_ALLOCATOR (GST_MEMORY_CAST (mem)->allocator); priv = allocator->priv; - if (!check_bind_flags_for_processor_input_view (mem->desc.BindFlags)) { + if (!check_bind_flags_for_processor_input_view (dmem_priv->desc.BindFlags)) { GST_LOG_OBJECT (allocator, - "Need BindFlags, current flag 0x%x", mem->desc.BindFlags); + "Need BindFlags, current flag 0x%x", dmem_priv->desc.BindFlags); return FALSE; } GST_D3D11_MEMORY_LOCK (mem); - if (mem->processor_input_view) + if (dmem_priv->processor_input_view) goto succeeded; if (priv->processor_input_view_array) { GST_D3D11_ALLOCATOR_LOCK (allocator); view = g_array_index (priv->processor_input_view_array, - ID3D11VideoProcessorInputView *, mem->subresource_index); + ID3D11VideoProcessorInputView *, dmem_priv->subresource_index); /* Increase refcount and reuse existing view */ if (view) { - mem->processor_input_view = view; + dmem_priv->processor_input_view = view; ID3D11VideoProcessorInputView_AddRef (view); } GST_D3D11_ALLOCATOR_UNLOCK (allocator); } - if (mem->processor_input_view) + if (dmem_priv->processor_input_view) goto succeeded; desc.FourCC = 0; desc.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D; desc.Texture2D.MipSlice = 0; - desc.Texture2D.ArraySlice = mem->subresource_index; + desc.Texture2D.ArraySlice = dmem_priv->subresource_index; hr = ID3D11VideoDevice_CreateVideoProcessorInputView (video_device, - (ID3D11Resource *) mem->texture, enumerator, &desc, - &mem->processor_input_view); + (ID3D11Resource *) dmem_priv->texture, enumerator, &desc, + &dmem_priv->processor_input_view); if (!gst_d3d11_result (hr, mem->device)) { GST_ERROR_OBJECT (allocator, "Could not create processor input view, hr: 0x%x", (guint) hr); @@ -1230,15 +1374,15 @@ gst_d3d11_memory_ensure_processor_input_view (GstD3D11Memory * mem, if (priv->processor_input_view_array) { GST_D3D11_ALLOCATOR_LOCK (allocator); view = g_array_index (priv->processor_input_view_array, - ID3D11VideoProcessorInputView *, mem->subresource_index); + ID3D11VideoProcessorInputView *, dmem_priv->subresource_index); if (view) ID3D11VideoProcessorInputView_Release (view); g_array_index (priv->processor_input_view_array, - ID3D11VideoProcessorInputView *, mem->subresource_index) = - mem->processor_input_view; - ID3D11VideoProcessorInputView_AddRef (mem->processor_input_view); + ID3D11VideoProcessorInputView *, dmem_priv->subresource_index) = + dmem_priv->processor_input_view; + ID3D11VideoProcessorInputView_AddRef (dmem_priv->processor_input_view); GST_D3D11_ALLOCATOR_UNLOCK (allocator); } @@ -1251,45 +1395,58 @@ done: return ret; } -gboolean +ID3D11VideoProcessorInputView * +gst_d3d11_memory_get_processor_input_view (GstD3D11Memory * mem, + ID3D11VideoDevice * video_device, + ID3D11VideoProcessorEnumerator * enumerator) +{ + g_return_val_if_fail (gst_is_d3d11_memory (GST_MEMORY_CAST (mem)), NULL); + g_return_val_if_fail (video_device != NULL, NULL); + g_return_val_if_fail (enumerator != NULL, NULL); + + if (!gst_d3d11_memory_ensure_processor_input_view (mem, video_device, + enumerator)) + return NULL; + + return mem->priv->processor_input_view; +} + +static gboolean gst_d3d11_memory_ensure_processor_output_view (GstD3D11Memory * mem, ID3D11VideoDevice * video_device, ID3D11VideoProcessorEnumerator * enumerator) { + GstD3D11MemoryPrivate *priv = mem->priv; GstD3D11Allocator *allocator; D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC desc = { 0, }; HRESULT hr; gboolean ret; - g_return_val_if_fail (gst_is_d3d11_memory (GST_MEMORY_CAST (mem)), FALSE); - g_return_val_if_fail (video_device != NULL, FALSE); - g_return_val_if_fail (enumerator != NULL, FALSE); - allocator = GST_D3D11_ALLOCATOR (GST_MEMORY_CAST (mem)->allocator); - if (!(mem->desc.BindFlags & D3D11_BIND_RENDER_TARGET)) { + if (!(priv->desc.BindFlags & D3D11_BIND_RENDER_TARGET)) { GST_LOG_OBJECT (allocator, - "Need BindFlags, current flag 0x%x", mem->desc.BindFlags); + "Need BindFlags, current flag 0x%x", priv->desc.BindFlags); return FALSE; } /* FIXME: texture array should be supported at some point */ - if (mem->subresource_index != 0) { + if (priv->subresource_index != 0) { GST_FIXME_OBJECT (allocator, "Texture array is not suppoted for processor output view"); return FALSE; } GST_D3D11_MEMORY_LOCK (mem); - if (mem->processor_output_view) + if (priv->processor_output_view) goto succeeded; desc.ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2D; desc.Texture2D.MipSlice = 0; hr = ID3D11VideoDevice_CreateVideoProcessorOutputView (video_device, - (ID3D11Resource *) mem->texture, enumerator, &desc, - &mem->processor_output_view); + (ID3D11Resource *) priv->texture, enumerator, &desc, + &priv->processor_output_view); if (!gst_d3d11_result (hr, mem->device)) { GST_ERROR_OBJECT (allocator, "Could not create processor input view, hr: 0x%x", (guint) hr); @@ -1304,3 +1461,19 @@ done: return ret; } + +ID3D11VideoProcessorOutputView * +gst_d3d11_memory_get_processor_output_view (GstD3D11Memory * mem, + ID3D11VideoDevice * video_device, + ID3D11VideoProcessorEnumerator * enumerator) +{ + g_return_val_if_fail (gst_is_d3d11_memory (GST_MEMORY_CAST (mem)), NULL); + g_return_val_if_fail (video_device != NULL, NULL); + g_return_val_if_fail (enumerator != NULL, NULL); + + if (!gst_d3d11_memory_ensure_processor_output_view (mem, video_device, + enumerator)) + return NULL; + + return mem->priv->processor_output_view; +} diff --git a/sys/d3d11/gstd3d11memory.h b/sys/d3d11/gstd3d11memory.h index 01ce9e8a7e..760b96603d 100644 --- a/sys/d3d11/gstd3d11memory.h +++ b/sys/d3d11/gstd3d11memory.h @@ -38,6 +38,8 @@ G_BEGIN_DECLS #define GST_D3D11_ALLOCATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GST_TYPE_D3D11_ALLOCATOR, GstD3D11AllocatorClass)) #define GST_D3D11_ALLOCATOR_CAST(obj) ((GstD3D11Allocator *)obj) +typedef struct _GstD3D11MemoryPrivate GstD3D11MemoryPrivate; + #define GST_D3D11_MEMORY_NAME "D3D11Memory" /** @@ -91,13 +93,6 @@ struct _GstD3D11AllocationParams gpointer _gst_reserved[GST_PADDING_LARGE]; }; -typedef enum -{ - GST_D3D11_MEMORY_TYPE_TEXTURE = 0, - GST_D3D11_MEMORY_TYPE_ARRAY = 1, - GST_D3D11_MEMORY_TYPE_STAGING = 2, -} GstD3D11MemoryType; - struct _GstD3D11Memory { GstMemory mem; @@ -105,30 +100,9 @@ struct _GstD3D11Memory /*< public > */ GstD3D11Device *device; - ID3D11Texture2D *texture; - ID3D11Texture2D *staging; - - ID3D11ShaderResourceView *shader_resource_view[GST_VIDEO_MAX_PLANES]; - guint num_shader_resource_views; - - ID3D11RenderTargetView *render_target_view[GST_VIDEO_MAX_PLANES]; - guint num_render_target_views; - - ID3D11VideoDecoderOutputView *decoder_output_view; - ID3D11VideoProcessorInputView *processor_input_view; - ID3D11VideoProcessorOutputView *processor_output_view; - - GstD3D11MemoryType type; - - /* > 0 if this is Array typed memory */ - guint subresource_index; - - D3D11_TEXTURE2D_DESC desc; - D3D11_MAPPED_SUBRESOURCE map; - /*< private >*/ - GMutex lock; - gint cpu_map_count; + GstD3D11MemoryPrivate *priv; + gpointer _gst_reserved[GST_PADDING]; }; struct _GstD3D11Allocator @@ -184,21 +158,34 @@ void gst_d3d11_allocator_set_flushing (GstD3D11Allocator * alloca gboolean gst_is_d3d11_memory (GstMemory * mem); -gboolean gst_d3d11_memory_ensure_shader_resource_view (GstD3D11Memory * mem); +ID3D11Texture2D * gst_d3d11_memory_get_texture_handle (GstD3D11Memory * mem); -gboolean gst_d3d11_memory_ensure_render_target_view (GstD3D11Memory * mem); +gboolean gst_d3d11_memory_get_texture_desc (GstD3D11Memory * mem, + D3D11_TEXTURE2D_DESC * desc); -gboolean gst_d3d11_memory_ensure_decoder_output_view (GstD3D11Memory * mem, - ID3D11VideoDevice * video_device, - GUID * decoder_profile); +guint gst_d3d11_memory_get_subresource_index (GstD3D11Memory * mem); -gboolean gst_d3d11_memory_ensure_processor_input_view (GstD3D11Memory * mem, - ID3D11VideoDevice * video_device, - ID3D11VideoProcessorEnumerator * enumerator); +guint gst_d3d11_memory_get_shader_resource_view_size (GstD3D11Memory * mem); -gboolean gst_d3d11_memory_ensure_processor_output_view (GstD3D11Memory * mem, - ID3D11VideoDevice * video_device, - ID3D11VideoProcessorEnumerator * enumerator); +ID3D11ShaderResourceView * gst_d3d11_memory_get_shader_resource_view (GstD3D11Memory * mem, + guint index); + +guint gst_d3d11_memory_get_render_target_view_size (GstD3D11Memory * mem); + +ID3D11RenderTargetView * gst_d3d11_memory_get_render_target_view (GstD3D11Memory * mem, + guint index); + +ID3D11VideoDecoderOutputView * gst_d3d11_memory_get_decoder_output_view (GstD3D11Memory * mem, + ID3D11VideoDevice * video_device, + GUID * decoder_profile); + +ID3D11VideoProcessorInputView * gst_d3d11_memory_get_processor_input_view (GstD3D11Memory * mem, + ID3D11VideoDevice * video_device, + ID3D11VideoProcessorEnumerator * enumerator); + +ID3D11VideoProcessorOutputView * gst_d3d11_memory_get_processor_output_view (GstD3D11Memory * mem, + ID3D11VideoDevice * video_device, + ID3D11VideoProcessorEnumerator * enumerator); G_END_DECLS diff --git a/sys/d3d11/gstd3d11upload.c b/sys/d3d11/gstd3d11upload.c index 17e05ffc39..32afca3776 100644 --- a/sys/d3d11/gstd3d11upload.c +++ b/sys/d3d11/gstd3d11upload.c @@ -396,15 +396,11 @@ gst_d3d11_upload_can_use_staging_buffer (GstD3D11Upload * self, GstBuffer * outbuf) { GstD3D11BaseFilter *filter = GST_D3D11_BASE_FILTER (self); - gint i; + ID3D11Device *device_handle = + gst_d3d11_device_get_device_handle (filter->device); - /* staging buffer doesn't need to be used for non-d3d11 memory */ - for (i = 0; i < gst_buffer_n_memory (outbuf); i++) { - GstMemory *mem = gst_buffer_peek_memory (outbuf, i); - - if (!gst_is_d3d11_memory (mem)) - return FALSE; - } + if (!gst_d3d11_buffer_can_access_device (outbuf, device_handle)) + return FALSE; if (self->staging_buffer) return TRUE; @@ -462,7 +458,8 @@ gst_d3d11_upload_transform (GstBaseTransform * trans, GstBuffer * inbuf, /* Copy staging texture to d3d11 texture */ if (use_staging_buf) { - if (!gst_d3d11_buffer_copy_into (outbuf, self->staging_buffer)) { + if (!gst_d3d11_buffer_copy_into (outbuf, + self->staging_buffer, &filter->out_info)) { GST_ERROR_OBJECT (self, "Cannot copy staging texture into texture"); return GST_FLOW_ERROR; } diff --git a/sys/d3d11/gstd3d11utils.c b/sys/d3d11/gstd3d11utils.c index 2451f4faa2..06a4545a56 100644 --- a/sys/d3d11/gstd3d11utils.c +++ b/sys/d3d11/gstd3d11utils.c @@ -579,22 +579,59 @@ _gst_d3d11_result (HRESULT hr, GstD3D11Device * device, GstDebugCategory * cat, #endif } +static gboolean +gst_d3d11_buffer_copy_into_fallback (GstBuffer * dst, GstBuffer * src, + const GstVideoInfo * info) +{ + GstVideoFrame in_frame, out_frame; + gboolean ret; + + if (!gst_video_frame_map (&in_frame, (GstVideoInfo *) info, src, + GST_MAP_READ | GST_VIDEO_FRAME_MAP_FLAG_NO_REF)) + goto invalid_buffer; + + if (!gst_video_frame_map (&out_frame, (GstVideoInfo *) info, dst, + GST_MAP_WRITE | GST_VIDEO_FRAME_MAP_FLAG_NO_REF)) { + gst_video_frame_unmap (&in_frame); + goto invalid_buffer; + } + + ret = gst_video_frame_copy (&out_frame, &in_frame); + + gst_video_frame_unmap (&in_frame); + gst_video_frame_unmap (&out_frame); + + return ret; + + /* ERRORS */ +invalid_buffer: + { + GST_ERROR ("Invalid video buffer"); + return FALSE; + } +} + gboolean -gst_d3d11_buffer_copy_into (GstBuffer * dst, GstBuffer * src) +gst_d3d11_buffer_copy_into (GstBuffer * dst, GstBuffer * src, + const GstVideoInfo * info) { guint i; - guint num_mem; g_return_val_if_fail (GST_IS_BUFFER (dst), FALSE); g_return_val_if_fail (GST_IS_BUFFER (src), FALSE); + g_return_val_if_fail (info != NULL, FALSE); - num_mem = gst_buffer_n_memory (dst); - if (num_mem != gst_buffer_n_memory (src)) { - GST_WARNING ("different num memory"); - return FALSE; + if (gst_buffer_n_memory (dst) != gst_buffer_n_memory (src)) { + GST_LOG ("different memory layout, perform fallback copy"); + return gst_d3d11_buffer_copy_into_fallback (dst, src, info); } - for (i = 0; i < num_mem; i++) { + if (!gst_is_d3d11_buffer (dst) || !gst_is_d3d11_buffer (src)) { + GST_LOG ("non-d3d11 memory, perform fallback copy"); + return gst_d3d11_buffer_copy_into_fallback (dst, src, info); + } + + for (i = 0; i < gst_buffer_n_memory (dst); i++) { GstMemory *dst_mem, *src_mem; GstD3D11Memory *dst_dmem, *src_dmem; GstMapInfo dst_info; @@ -603,30 +640,25 @@ gst_d3d11_buffer_copy_into (GstBuffer * dst, GstBuffer * src) ID3D11DeviceContext *device_context; GstD3D11Device *device; D3D11_BOX src_box = { 0, }; + D3D11_TEXTURE2D_DESC dst_desc, src_desc; + guint dst_subidx, src_subidx; dst_mem = gst_buffer_peek_memory (dst, i); src_mem = gst_buffer_peek_memory (src, i); - if (!gst_is_d3d11_memory (dst_mem)) { - GST_WARNING ("dst memory is not d3d11"); - return FALSE; - } - - if (!gst_is_d3d11_memory (src_mem)) { - GST_WARNING ("src memory is not d3d11"); - return FALSE; - } - dst_dmem = (GstD3D11Memory *) dst_mem; src_dmem = (GstD3D11Memory *) src_mem; device = dst_dmem->device; if (device != src_dmem->device) { - GST_WARNING ("different device"); - return FALSE; + GST_LOG ("different device, perform fallback copy"); + return gst_d3d11_buffer_copy_into_fallback (dst, src, info); } - if (dst_dmem->desc.Format != src_dmem->desc.Format) { + gst_d3d11_memory_get_texture_desc (dst_dmem, &dst_desc); + gst_d3d11_memory_get_texture_desc (src_dmem, &src_desc); + + if (dst_desc.Format != src_desc.Format) { GST_WARNING ("different dxgi format"); return FALSE; } @@ -653,13 +685,15 @@ gst_d3d11_buffer_copy_into (GstBuffer * dst, GstBuffer * src) src_box.top = 0; src_box.front = 0; src_box.back = 1; - src_box.right = MIN (src_dmem->desc.Width, dst_dmem->desc.Width); - src_box.bottom = MIN (src_dmem->desc.Height, dst_dmem->desc.Height); + src_box.right = MIN (src_desc.Width, dst_desc.Width); + src_box.bottom = MIN (src_desc.Height, dst_desc.Height); + + dst_subidx = gst_d3d11_memory_get_subresource_index (dst_dmem); + src_subidx = gst_d3d11_memory_get_subresource_index (src_dmem); gst_d3d11_device_lock (device); ID3D11DeviceContext_CopySubresourceRegion (device_context, - dst_texture, dst_dmem->subresource_index, 0, 0, 0, - src_texture, src_dmem->subresource_index, &src_box); + dst_texture, dst_subidx, 0, 0, 0, src_texture, src_subidx, &src_box); gst_d3d11_device_unlock (device); gst_memory_unmap (src_mem, &src_info); @@ -669,6 +703,189 @@ gst_d3d11_buffer_copy_into (GstBuffer * dst, GstBuffer * src) return TRUE; } +gboolean +gst_is_d3d11_buffer (GstBuffer * buffer) +{ + guint i; + guint size; + + g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE); + + size = gst_buffer_n_memory (buffer); + if (size == 0) + return FALSE; + + for (i = 0; i < size; i++) { + GstMemory *mem = gst_buffer_peek_memory (buffer, i); + + if (!gst_is_d3d11_memory (mem)) + return FALSE; + } + + return TRUE; +} + +gboolean +gst_d3d11_buffer_can_access_device (GstBuffer * buffer, ID3D11Device * device) +{ + guint i; + + g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE); + g_return_val_if_fail (device != NULL, FALSE); + + if (!gst_is_d3d11_buffer (buffer)) { + GST_LOG ("Not a d3d11 buffer"); + return FALSE; + } + + for (i = 0; i < gst_buffer_n_memory (buffer); i++) { + GstD3D11Memory *mem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, i); + ID3D11Device *handle; + + handle = gst_d3d11_device_get_device_handle (mem->device); + if (handle != device) { + GST_LOG ("D3D11 device is incompatible"); + return FALSE; + } + } + + return TRUE; +} + +gboolean +gst_d3d11_buffer_map (GstBuffer * buffer, ID3D11Device * device, + GstMapInfo info[GST_VIDEO_MAX_PLANES], GstMapFlags flags) +{ + GstMapFlags map_flags; + gint num_mapped = 0; + + g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE); + g_return_val_if_fail (info != NULL, FALSE); + + if (!gst_d3d11_buffer_can_access_device (buffer, device)) + return FALSE; + + map_flags = flags | GST_MAP_D3D11; + + for (num_mapped = 0; num_mapped < gst_buffer_n_memory (buffer); num_mapped++) { + GstMemory *mem = gst_buffer_peek_memory (buffer, num_mapped); + + if (!gst_memory_map (mem, &info[num_mapped], map_flags)) { + GST_ERROR ("Couldn't map memory"); + goto error; + } + } + + return TRUE; + +error: + { + gint i; + for (i = 0; i < num_mapped; i++) { + GstMemory *mem = gst_buffer_peek_memory (buffer, num_mapped); + gst_memory_unmap (mem, &info[i]); + } + + return FALSE; + } +} + +gboolean +gst_d3d11_buffer_unmap (GstBuffer * buffer, + GstMapInfo info[GST_VIDEO_MAX_PLANES]) +{ + gint i; + + g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE); + g_return_val_if_fail (info != NULL, FALSE); + + for (i = 0; i < gst_buffer_n_memory (buffer); i++) { + GstMemory *mem = gst_buffer_peek_memory (buffer, i); + + gst_memory_unmap (mem, &info[i]); + } + + return TRUE; +} + +guint +gst_d3d11_buffer_get_shader_resource_view (GstBuffer * buffer, + ID3D11ShaderResourceView * view[GST_VIDEO_MAX_PLANES]) +{ + gint i; + guint num_views = 0; + + g_return_val_if_fail (GST_IS_BUFFER (buffer), 0); + g_return_val_if_fail (view != NULL, 0); + + if (!gst_is_d3d11_buffer (buffer)) { + GST_ERROR ("Buffer contains non-d3d11 memory"); + return 0; + } + + for (i = 0; i < gst_buffer_n_memory (buffer); i++) { + GstD3D11Memory *mem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, i); + guint view_size; + gint j; + + view_size = gst_d3d11_memory_get_shader_resource_view_size (mem); + if (!view_size) { + GST_LOG ("SRV is unavailable for memory index %d", i); + return 0; + } + + for (j = 0; j < view_size; j++) { + if (num_views >= GST_VIDEO_MAX_PLANES) { + GST_ERROR ("Too many SRVs"); + return 0; + } + + view[num_views++] = gst_d3d11_memory_get_shader_resource_view (mem, j); + } + } + + return num_views; +} + +guint +gst_d3d11_buffer_get_render_target_view (GstBuffer * buffer, + ID3D11RenderTargetView * view[GST_VIDEO_MAX_PLANES]) +{ + gint i; + guint num_views = 0; + + g_return_val_if_fail (GST_IS_BUFFER (buffer), 0); + g_return_val_if_fail (view != NULL, 0); + + if (!gst_is_d3d11_buffer (buffer)) { + GST_ERROR ("Buffer contains non-d3d11 memory"); + return 0; + } + + for (i = 0; i < gst_buffer_n_memory (buffer); i++) { + GstD3D11Memory *mem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, i); + guint view_size; + gint j; + + view_size = gst_d3d11_memory_get_render_target_view_size (mem); + if (!view_size) { + GST_LOG ("RTV is unavailable for memory index %d", i); + return 0; + } + + for (j = 0; j < view_size; j++) { + if (num_views >= GST_VIDEO_MAX_PLANES) { + GST_ERROR ("Too many RTVs"); + return 0; + } + + view[num_views++] = gst_d3d11_memory_get_render_target_view (mem, j); + } + } + + return num_views; +} + GstBufferPool * gst_d3d11_buffer_pool_new_with_options (GstD3D11Device * device, GstCaps * caps, GstD3D11AllocationParams * alloc_params, diff --git a/sys/d3d11/gstd3d11utils.h b/sys/d3d11/gstd3d11utils.h index ef356b4fb4..fb0c2357b0 100644 --- a/sys/d3d11/gstd3d11utils.h +++ b/sys/d3d11/gstd3d11utils.h @@ -66,7 +66,27 @@ GstBuffer * gst_d3d11_allocate_staging_buffer_for (GstBuffer * buffer, gboolean add_videometa); gboolean gst_d3d11_buffer_copy_into (GstBuffer * dst, - GstBuffer * src); + GstBuffer * src, + const GstVideoInfo * info); + +gboolean gst_is_d3d11_buffer (GstBuffer * buffer); + +gboolean gst_d3d11_buffer_can_access_device (GstBuffer * buffer, + ID3D11Device * device); + +gboolean gst_d3d11_buffer_map (GstBuffer * buffer, + ID3D11Device * device, + GstMapInfo info[GST_VIDEO_MAX_PLANES], + GstMapFlags flags); + +gboolean gst_d3d11_buffer_unmap (GstBuffer * buffer, + GstMapInfo info[GST_VIDEO_MAX_PLANES]); + +guint gst_d3d11_buffer_get_shader_resource_view (GstBuffer * buffer, + ID3D11ShaderResourceView * view[GST_VIDEO_MAX_PLANES]); + +guint gst_d3d11_buffer_get_render_target_view (GstBuffer * buffer, + ID3D11RenderTargetView * view[GST_VIDEO_MAX_PLANES]); GstBufferPool * gst_d3d11_buffer_pool_new_with_options (GstD3D11Device * device, GstCaps * caps, @@ -74,7 +94,6 @@ GstBufferPool * gst_d3d11_buffer_pool_new_with_options (GstD3D11Device * device guint min_buffers, guint max_buffers); - gboolean _gst_d3d11_result (HRESULT hr, GstD3D11Device * device, GstDebugCategory * cat, diff --git a/sys/d3d11/gstd3d11videoprocessor.c b/sys/d3d11/gstd3d11videoprocessor.c index 7ea02211f9..bdd2a1ecf9 100644 --- a/sys/d3d11/gstd3d11videoprocessor.c +++ b/sys/d3d11/gstd3d11videoprocessor.c @@ -445,11 +445,11 @@ gst_d3d11_video_processor_create_input_view (GstD3D11VideoProcessor * processor, return TRUE; } -gboolean -gst_d3d11_video_processor_ensure_input_view (GstD3D11VideoProcessor * processor, +ID3D11VideoProcessorInputView * +gst_d3d11_video_processor_get_input_view (GstD3D11VideoProcessor * processor, GstD3D11Memory * mem) { - return gst_d3d11_memory_ensure_processor_input_view (mem, + return gst_d3d11_memory_get_processor_input_view (mem, processor->video_device, processor->enumerator); } @@ -473,11 +473,11 @@ gst_d3d11_video_processor_create_output_view (GstD3D11VideoProcessor * return TRUE; } -gboolean -gst_d3d11_video_processor_ensure_output_view (GstD3D11VideoProcessor * +ID3D11VideoProcessorOutputView * +gst_d3d11_video_processor_get_output_view (GstD3D11VideoProcessor * processor, GstD3D11Memory * mem) { - return gst_d3d11_memory_ensure_processor_output_view (mem, + return gst_d3d11_memory_get_processor_output_view (mem, processor->video_device, processor->enumerator); } diff --git a/sys/d3d11/gstd3d11videoprocessor.h b/sys/d3d11/gstd3d11videoprocessor.h index f535ddafc8..337b062ee5 100644 --- a/sys/d3d11/gstd3d11videoprocessor.h +++ b/sys/d3d11/gstd3d11videoprocessor.h @@ -78,16 +78,16 @@ gboolean gst_d3d11_video_processor_create_input_view (GstD3D11VideoProcessor * ID3D11Resource *resource, ID3D11VideoProcessorInputView ** view); -gboolean gst_d3d11_video_processor_ensure_input_view (GstD3D11VideoProcessor * processor, - GstD3D11Memory *mem); +ID3D11VideoProcessorInputView * gst_d3d11_video_processor_get_input_view (GstD3D11VideoProcessor * processor, + GstD3D11Memory *mem); gboolean gst_d3d11_video_processor_create_output_view (GstD3D11VideoProcessor * processor, D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC * desc, ID3D11Resource *resource, ID3D11VideoProcessorOutputView ** view); -gboolean gst_d3d11_video_processor_ensure_output_view (GstD3D11VideoProcessor * processor, - GstD3D11Memory *mem); +ID3D11VideoProcessorOutputView * gst_d3d11_video_processor_get_output_view (GstD3D11VideoProcessor * processor, + GstD3D11Memory *mem); void gst_d3d11_video_processor_input_view_release (ID3D11VideoProcessorInputView * view); diff --git a/sys/d3d11/gstd3d11videosink.c b/sys/d3d11/gstd3d11videosink.c index 478a0f0583..e1953d26c4 100644 --- a/sys/d3d11/gstd3d11videosink.c +++ b/sys/d3d11/gstd3d11videosink.c @@ -785,7 +785,6 @@ gst_d3d11_video_sink_upload_frame (GstD3D11VideoSink * self, GstBuffer * inbuf, { GstVideoFrame in_frame, out_frame; gboolean ret; - gint i; GST_LOG_OBJECT (self, "Copy to fallback buffer"); @@ -804,22 +803,6 @@ gst_d3d11_video_sink_upload_frame (GstD3D11VideoSink * self, GstBuffer * inbuf, gst_video_frame_unmap (&in_frame); gst_video_frame_unmap (&out_frame); - if (ret) { - /* map to upload staging texture to render texture */ - for (i = 0; i < gst_buffer_n_memory (outbuf); i++) { - GstMemory *mem; - GstMapInfo map; - - mem = gst_buffer_peek_memory (outbuf, i); - if (!gst_memory_map (mem, &map, (GST_MAP_READ | GST_MAP_D3D11))) { - GST_ERROR_OBJECT (self, "cannot upload staging texture"); - ret = FALSE; - break; - } - gst_memory_unmap (mem, &map); - } - } - return ret; /* ERRORS */ @@ -835,136 +818,105 @@ static gboolean gst_d3d11_video_sink_copy_d3d11_to_d3d11 (GstD3D11VideoSink * self, GstBuffer * inbuf, GstBuffer * outbuf) { - gint i; - ID3D11DeviceContext *context_handle = - gst_d3d11_device_get_device_context_handle (self->device); - - g_return_val_if_fail (gst_buffer_n_memory (inbuf) == - gst_buffer_n_memory (outbuf), FALSE); - GST_LOG_OBJECT (self, "Copy to fallback buffer using device memory copy"); - gst_d3d11_device_lock (self->device); - for (i = 0; i < gst_buffer_n_memory (inbuf); i++) { - GstD3D11Memory *in_mem = - (GstD3D11Memory *) gst_buffer_peek_memory (inbuf, i); - GstD3D11Memory *out_mem = - (GstD3D11Memory *) gst_buffer_peek_memory (outbuf, i); - D3D11_BOX src_box; + return gst_d3d11_buffer_copy_into (outbuf, inbuf, &self->info); +} - /* input buffer might be larger than render size */ - src_box.left = 0; - src_box.top = 0; - src_box.front = 0; - src_box.back = 1; - src_box.right = out_mem->desc.Width; - src_box.bottom = out_mem->desc.Height; +static gboolean +gst_d3d11_video_sink_get_fallback_buffer (GstD3D11VideoSink * self, + GstBuffer * inbuf, GstBuffer ** fallback_buf, gboolean device_copy) +{ + GstBuffer *outbuf = NULL; + ID3D11ShaderResourceView *view[GST_VIDEO_MAX_PLANES]; + GstVideoOverlayCompositionMeta *compo_meta; - ID3D11DeviceContext_CopySubresourceRegion (context_handle, - (ID3D11Resource *) out_mem->texture, 0, 0, 0, 0, - (ID3D11Resource *) in_mem->texture, in_mem->subresource_index, - &src_box); + if (!self->fallback_pool || + !gst_buffer_pool_set_active (self->fallback_pool, TRUE) || + gst_buffer_pool_acquire_buffer (self->fallback_pool, &outbuf, + NULL) != GST_FLOW_OK) { + GST_ERROR_OBJECT (self, "fallback pool is unavailable"); + return FALSE; } - gst_d3d11_device_unlock (self->device); + + /* Ensure SRV */ + if (!gst_d3d11_buffer_get_shader_resource_view (outbuf, view)) { + GST_ERROR_OBJECT (self, "fallback SRV is unavailable"); + goto error; + } + + if (device_copy) { + if (!gst_d3d11_video_sink_copy_d3d11_to_d3d11 (self, inbuf, outbuf)) { + GST_ERROR_OBJECT (self, "cannot copy frame"); + goto error; + } + } else if (!gst_d3d11_video_sink_upload_frame (self, inbuf, outbuf)) { + GST_ERROR_OBJECT (self, "cannot upload frame"); + goto error; + } + + /* Copy overlaycomposition meta if any */ + compo_meta = gst_buffer_get_video_overlay_composition_meta (inbuf); + if (compo_meta) + gst_buffer_add_video_overlay_composition_meta (outbuf, compo_meta->overlay); + + *fallback_buf = outbuf; return TRUE; + +error: + gst_buffer_unref (outbuf); + return FALSE; } static GstFlowReturn gst_d3d11_video_sink_show_frame (GstVideoSink * sink, GstBuffer * buf) { GstD3D11VideoSink *self = GST_D3D11_VIDEO_SINK (sink); - GstMapInfo map; GstFlowReturn ret; GstVideoRectangle rect = { 0, }; - GstBuffer *render_buf; - gboolean need_unref = FALSE; - gboolean do_device_copy = TRUE; - gint i; + GstBuffer *fallback_buf = NULL; GstStructure *stats = NULL; + ID3D11Device *device_handle = + gst_d3d11_device_get_device_handle (self->device); + ID3D11ShaderResourceView *view[GST_VIDEO_MAX_PLANES]; - render_buf = buf; - - for (i = 0; i < gst_buffer_n_memory (buf); i++) { - GstMemory *mem; - GstD3D11Memory *dmem; - - mem = gst_buffer_peek_memory (buf, i); - if (!gst_is_d3d11_memory (mem)) { - GST_LOG_OBJECT (sink, "not a d3d11 memory, need fallback"); - render_buf = NULL; - do_device_copy = FALSE; - break; - } - - dmem = (GstD3D11Memory *) mem; - if (dmem->device != self->device) { - GST_LOG_OBJECT (sink, "different d3d11 device, need fallback"); - render_buf = NULL; - do_device_copy = FALSE; - break; - } - - if (dmem->desc.Usage == D3D11_USAGE_DEFAULT) { - if (!gst_memory_map (mem, &map, (GST_MAP_READ | GST_MAP_D3D11))) { - GST_ERROR_OBJECT (self, "cannot map d3d11 memory"); - return GST_FLOW_ERROR; - } - - gst_memory_unmap (mem, &map); - } - - if (gst_buffer_n_memory (buf) == 1 && self->have_video_processor && - gst_d3d11_video_processor_check_bind_flags_for_input_view - (dmem->desc.BindFlags)) { - break; - } - - if (!gst_d3d11_memory_ensure_shader_resource_view (dmem)) { - GST_LOG_OBJECT (sink, - "shader resource view is unavailable, need fallback"); - render_buf = NULL; - /* keep run loop in order to upload staging memory to device memory */ - } - } - - if (!render_buf) { - if (!self->fallback_pool || - !gst_buffer_pool_set_active (self->fallback_pool, TRUE) || - gst_buffer_pool_acquire_buffer (self->fallback_pool, &render_buf, - NULL) != GST_FLOW_OK) { - GST_ERROR_OBJECT (self, "fallback pool is unavailable"); + if (!gst_d3d11_buffer_can_access_device (buf, device_handle)) { + GST_LOG_OBJECT (self, "Need fallback buffer"); + if (!gst_d3d11_video_sink_get_fallback_buffer (self, buf, &fallback_buf, + FALSE)) { return GST_FLOW_ERROR; } + } else { + gboolean direct_rendering = FALSE; - for (i = 0; i < gst_buffer_n_memory (render_buf); i++) { - GstD3D11Memory *dmem; + /* Check if we can use video processor for conversion */ + if (gst_buffer_n_memory (buf) == 1 && self->have_video_processor) { + GstD3D11Memory *mem = (GstD3D11Memory *) gst_buffer_peek_memory (buf, 0); + D3D11_TEXTURE2D_DESC desc; - dmem = (GstD3D11Memory *) gst_buffer_peek_memory (render_buf, i); - if (!gst_d3d11_memory_ensure_shader_resource_view (dmem)) { - GST_ERROR_OBJECT (self, "fallback shader resource view is unavailable"); - gst_buffer_unref (render_buf); - - return GST_FLOW_ERROR; + gst_d3d11_memory_get_texture_desc (mem, &desc); + if ((desc.BindFlags & D3D11_BIND_DECODER) == D3D11_BIND_DECODER) { + GST_TRACE_OBJECT (self, + "Got VideoProcessor compatible texture, do direct rendering"); + direct_rendering = TRUE; } } - if (do_device_copy) { - if (!gst_d3d11_video_sink_copy_d3d11_to_d3d11 (self, buf, render_buf)) { - GST_ERROR_OBJECT (self, "cannot copy frame"); - gst_buffer_unref (render_buf); - - return GST_FLOW_ERROR; + /* Or, SRV should be available */ + if (!direct_rendering) { + if (gst_d3d11_buffer_get_shader_resource_view (buf, view)) { + GST_TRACE_OBJECT (self, "SRV is available, do direct rendering"); + direct_rendering = TRUE; } - } else if (!gst_d3d11_video_sink_upload_frame (self, buf, render_buf)) { - GST_ERROR_OBJECT (self, "cannot upload frame"); - gst_buffer_unref (render_buf); + } + if (!direct_rendering && + !gst_d3d11_video_sink_get_fallback_buffer (self, buf, &fallback_buf, + TRUE)) { return GST_FLOW_ERROR; } - - need_unref = TRUE; } gst_d3d11_window_show (self->window); @@ -976,9 +928,9 @@ gst_d3d11_video_sink_show_frame (GstVideoSink * sink, GstBuffer * buf) if (self->render_stats) stats = gst_base_sink_get_stats (GST_BASE_SINK_CAST (self)); - ret = gst_d3d11_window_render (self->window, render_buf, &rect, stats); - if (need_unref) - gst_buffer_unref (render_buf); + ret = gst_d3d11_window_render (self->window, + fallback_buf ? fallback_buf : buf, &rect, stats); + gst_clear_buffer (&fallback_buf); if (ret == GST_D3D11_WINDOW_FLOW_CLOSED) { GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND, diff --git a/sys/d3d11/gstd3d11vp8dec.c b/sys/d3d11/gstd3d11vp8dec.c index 4f46f1b9a3..620b9887de 100644 --- a/sys/d3d11/gstd3d11vp8dec.c +++ b/sys/d3d11/gstd3d11vp8dec.c @@ -341,7 +341,6 @@ gst_d3d11_vp8_dec_new_picture (GstVp8Decoder * decoder, { GstD3D11Vp8Dec *self = GST_D3D11_VP8_DEC (decoder); GstBuffer *view_buffer; - GstD3D11Memory *mem; view_buffer = gst_d3d11_decoder_get_output_view_buffer (self->d3d11_decoder); if (!view_buffer) { @@ -349,10 +348,7 @@ gst_d3d11_vp8_dec_new_picture (GstVp8Decoder * decoder, return FALSE; } - mem = (GstD3D11Memory *) gst_buffer_peek_memory (view_buffer, 0); - - GST_LOG_OBJECT (self, "New output view buffer %" GST_PTR_FORMAT " (index %d)", - view_buffer, mem->subresource_index); + GST_LOG_OBJECT (self, "New output view buffer %" GST_PTR_FORMAT, view_buffer); gst_vp8_picture_set_user_data (picture, view_buffer, (GDestroyNotify) gst_buffer_unref); diff --git a/sys/d3d11/gstd3d11vp9dec.c b/sys/d3d11/gstd3d11vp9dec.c index db34bdae6d..523fffe2f8 100644 --- a/sys/d3d11/gstd3d11vp9dec.c +++ b/sys/d3d11/gstd3d11vp9dec.c @@ -413,7 +413,6 @@ gst_d3d11_vp9_dec_new_picture (GstVp9Decoder * decoder, { GstD3D11Vp9Dec *self = GST_D3D11_VP9_DEC (decoder); GstBuffer *view_buffer; - GstD3D11Memory *mem; view_buffer = gst_d3d11_decoder_get_output_view_buffer (self->d3d11_decoder); if (!view_buffer) { @@ -421,10 +420,7 @@ gst_d3d11_vp9_dec_new_picture (GstVp9Decoder * decoder, return FALSE; } - mem = (GstD3D11Memory *) gst_buffer_peek_memory (view_buffer, 0); - - GST_LOG_OBJECT (self, "New output view buffer %" GST_PTR_FORMAT " (index %d)", - view_buffer, mem->subresource_index); + GST_LOG_OBJECT (self, "New output view buffer %" GST_PTR_FORMAT, view_buffer); gst_vp9_picture_set_user_data (picture, view_buffer, (GDestroyNotify) gst_buffer_unref); @@ -440,7 +436,6 @@ gst_d3d11_vp9_dec_duplicate_picture (GstVp9Decoder * decoder, { GstD3D11Vp9Dec *self = GST_D3D11_VP9_DEC (decoder); GstBuffer *view_buffer; - GstD3D11Memory *mem; GstVp9Picture *new_picture; view_buffer = gst_vp9_picture_get_user_data (picture); @@ -453,10 +448,8 @@ gst_d3d11_vp9_dec_duplicate_picture (GstVp9Decoder * decoder, new_picture = gst_vp9_picture_new (); new_picture->frame_hdr = picture->frame_hdr; - mem = (GstD3D11Memory *) gst_buffer_peek_memory (view_buffer, 0); - - GST_LOG_OBJECT (self, "Duplicate output with buffer %" GST_PTR_FORMAT - " (index %d)", view_buffer, mem->subresource_index); + GST_LOG_OBJECT (self, "Duplicate output with buffer %" GST_PTR_FORMAT, + view_buffer); gst_vp9_picture_set_user_data (new_picture, gst_buffer_ref (view_buffer), (GDestroyNotify) gst_buffer_unref); diff --git a/sys/d3d11/gstd3d11window.cpp b/sys/d3d11/gstd3d11window.cpp index 77051b7d47..635ee4b92c 100644 --- a/sys/d3d11/gstd3d11window.cpp +++ b/sys/d3d11/gstd3d11window.cpp @@ -1008,6 +1008,7 @@ gst_d3d11_window_buffer_ensure_processor_input (GstD3D11Window * self, GstBuffer * buffer, ID3D11VideoProcessorInputView ** in_view) { GstD3D11Memory *mem; + ID3D11VideoProcessorInputView *piv; if (!self->processor) return FALSE; @@ -1016,18 +1017,13 @@ gst_d3d11_window_buffer_ensure_processor_input (GstD3D11Window * self, return FALSE; mem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, 0); - - if (!gst_d3d11_video_processor_check_bind_flags_for_input_view - (mem->desc.BindFlags)) { + piv = gst_d3d11_video_processor_get_input_view (self->processor, mem); + if (!piv) { + GST_LOG_OBJECT (self, "Failed to get processor input view"); return FALSE; } - if (!gst_d3d11_video_processor_ensure_input_view (self->processor, mem)) { - GST_LOG_OBJECT (self, "Failed to create processor input view"); - return FALSE; - } - - *in_view = mem->processor_input_view; + *in_view = piv; return TRUE; } @@ -1096,19 +1092,25 @@ gst_d3d111_window_present (GstD3D11Window * self, GstBuffer * buffer, } if (self->cached_buffer) { + GstMapInfo infos[GST_VIDEO_MAX_PLANES]; ID3D11ShaderResourceView *srv[GST_VIDEO_MAX_PLANES]; ID3D11VideoProcessorInputView *piv = NULL; - guint i, j, k; + ID3D11Device *device_handle = + gst_d3d11_device_get_device_handle (self->device); - if (!gst_d3d11_window_buffer_ensure_processor_input (self, - self->cached_buffer, &piv)) { - for (i = 0, j = 0; i < gst_buffer_n_memory (self->cached_buffer); i++) { - GstD3D11Memory *mem = - (GstD3D11Memory *) gst_buffer_peek_memory (self->cached_buffer, i); - for (k = 0; k < mem->num_shader_resource_views; k++) { - srv[j] = mem->shader_resource_view[k]; - j++; - } + /* Map memory in any case so that we can upload pending stage texture */ + if (!gst_d3d11_buffer_map (self->cached_buffer, device_handle, + infos, GST_MAP_READ)) { + GST_ERROR_OBJECT (self, "Couldn't map buffer"); + + return GST_FLOW_ERROR; + } + + if (!gst_d3d11_buffer_get_shader_resource_view (self->cached_buffer, srv)) { + if (!gst_d3d11_window_buffer_ensure_processor_input (self, + self->cached_buffer, &piv)) { + GST_ERROR_OBJECT (self, "Input texture cannot be used for converter"); + return GST_FLOW_ERROR; } } @@ -1131,7 +1133,8 @@ gst_d3d111_window_present (GstD3D11Window * self, GstBuffer * buffer, if (!gst_d3d11_video_processor_render_unlocked (self->processor, &self->input_rect, piv, &self->render_rect, self->pov)) { GST_ERROR_OBJECT (self, "Couldn't render to backbuffer using processor"); - return GST_FLOW_ERROR; + ret = GST_FLOW_ERROR; + goto unmap_and_out; } else { GST_TRACE_OBJECT (self, "Rendered using processor"); } @@ -1139,7 +1142,8 @@ gst_d3d111_window_present (GstD3D11Window * self, GstBuffer * buffer, if (!gst_d3d11_color_converter_convert_unlocked (self->converter, srv, &self->rtv, NULL, NULL)) { GST_ERROR_OBJECT (self, "Couldn't render to backbuffer using converter"); - return GST_FLOW_ERROR; + ret = GST_FLOW_ERROR; + goto unmap_and_out; } else { GST_TRACE_OBJECT (self, "Rendered using converter"); } @@ -1161,6 +1165,9 @@ gst_d3d111_window_present (GstD3D11Window * self, GstBuffer * buffer, ret = klass->present (self, present_flags); self->first_present = FALSE; + +unmap_and_out: + gst_d3d11_buffer_unmap (self->cached_buffer, infos); } return ret;