d3d11: Privatize d3d11memory implementation

Hide most of symbols of GstD3D11Memory object.
GstD3D11Memory is one of primary resource for imcoming d3d11 library
and it's expected to be a extensible feature.
Hiding implementation detail would be helpful for later use case.

Summary of this commit:
* Now all native Direct3D11 resources are private of GstD3D11Memory.
  To access native resources, getter methods need to be used
  or generic map (e.g., gst_memory_map) API should be called
  apart from some exceptional case such as d3d11decoder case.
* Various helper methods are added for GstBuffer related operations
  and in order to remove duplicated code.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1892>
This commit is contained in:
Seungha Yang 2020-12-20 02:39:40 +09:00
parent f1e3e5276a
commit 59a1897c39
17 changed files with 941 additions and 577 deletions

View file

@ -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 *

View file

@ -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++;
}
}

View file

@ -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

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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;
}

View file

@ -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

View file

@ -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;
}

View file

@ -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,

View file

@ -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,

View file

@ -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);
}

View file

@ -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);

View file

@ -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,

View file

@ -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);

View file

@ -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);

View file

@ -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;