mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 19:51:11 +00:00
d3d11: Add support for D3D11_USAGE_DYNAMIC
D3D11 dynamic texture is a special memory type, which is mainly used for frequent CPU write access to the texture. For now, this texture type does not support gst_memory_{map,unmap}
This commit is contained in:
parent
5ce4748cc0
commit
ddd13fc7c0
8 changed files with 361 additions and 48 deletions
|
@ -151,7 +151,7 @@ gst_d3d11_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config)
|
|||
if (!priv->d3d11_params) {
|
||||
/* allocate memory with resource format by default */
|
||||
priv->d3d11_params = gst_d3d11_allocation_params_new (&info,
|
||||
GST_D3D11_ALLOCATION_FLAG_USE_RESOURCE_FORMAT);
|
||||
GST_D3D11_ALLOCATION_FLAG_USE_RESOURCE_FORMAT, D3D11_USAGE_DEFAULT, 0);
|
||||
}
|
||||
#ifndef GST_DISABLE_GST_DEBUG
|
||||
{
|
||||
|
|
|
@ -261,6 +261,8 @@ static GstFlowReturn gst_d3d11_color_convert_transform (GstBaseTransform *
|
|||
static gboolean gst_d3d11_color_convert_set_info (GstD3D11BaseFilter * filter,
|
||||
GstCaps * incaps, GstVideoInfo * in_info, GstCaps * outcaps,
|
||||
GstVideoInfo * out_info);
|
||||
static gboolean gst_d3d11_color_convert_query (GstBaseTransform * trans,
|
||||
GstPadDirection direction, GstQuery * query);
|
||||
|
||||
/* copies the given caps */
|
||||
static GstCaps *
|
||||
|
@ -458,6 +460,7 @@ gst_d3d11_color_convert_class_init (GstD3D11ColorConvertClass * klass)
|
|||
trans_class->transform =
|
||||
GST_DEBUG_FUNCPTR (gst_d3d11_color_convert_transform);
|
||||
trans_class->start = GST_DEBUG_FUNCPTR (gst_d3d11_color_convert_start);
|
||||
trans_class->query = GST_DEBUG_FUNCPTR (gst_d3d11_color_convert_query);
|
||||
|
||||
bfilter_class->set_info =
|
||||
GST_DEBUG_FUNCPTR (gst_d3d11_color_convert_set_info);
|
||||
|
@ -740,13 +743,15 @@ gst_d3d11_color_convert_propose_allocation (GstBaseTransform * trans,
|
|||
gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
|
||||
|
||||
d3d11_params = gst_buffer_pool_config_get_d3d11_allocation_params (config);
|
||||
if (!d3d11_params)
|
||||
if (!d3d11_params) {
|
||||
d3d11_params = gst_d3d11_allocation_params_new (&info,
|
||||
GST_D3D11_ALLOCATION_FLAG_USE_RESOURCE_FORMAT);
|
||||
|
||||
/* Set bind flag */
|
||||
for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&info); i++) {
|
||||
d3d11_params->desc[i].BindFlags |= D3D11_BIND_SHADER_RESOURCE;
|
||||
GST_D3D11_ALLOCATION_FLAG_USE_RESOURCE_FORMAT, D3D11_USAGE_DEFAULT,
|
||||
D3D11_BIND_SHADER_RESOURCE);
|
||||
} else {
|
||||
/* Set bind flag */
|
||||
for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&info); i++) {
|
||||
d3d11_params->desc[i].BindFlags |= D3D11_BIND_SHADER_RESOURCE;
|
||||
}
|
||||
}
|
||||
|
||||
gst_buffer_pool_config_set_d3d11_allocation_params (config, d3d11_params);
|
||||
|
@ -817,14 +822,16 @@ gst_d3d11_color_convert_decide_allocation (GstBaseTransform * trans,
|
|||
gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
|
||||
|
||||
d3d11_params = gst_buffer_pool_config_get_d3d11_allocation_params (config);
|
||||
if (!d3d11_params)
|
||||
if (!d3d11_params) {
|
||||
d3d11_params = gst_d3d11_allocation_params_new (&info,
|
||||
GST_D3D11_ALLOCATION_FLAG_USE_RESOURCE_FORMAT);
|
||||
|
||||
/* Set bind flag */
|
||||
for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&info); i++) {
|
||||
d3d11_params->desc[i].BindFlags |=
|
||||
(D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET);
|
||||
GST_D3D11_ALLOCATION_FLAG_USE_RESOURCE_FORMAT, D3D11_USAGE_DEFAULT,
|
||||
D3D11_BIND_RENDER_TARGET);
|
||||
} else {
|
||||
/* Set bind flag */
|
||||
for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&info); i++) {
|
||||
d3d11_params->desc[i].BindFlags |=
|
||||
(D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET);
|
||||
}
|
||||
}
|
||||
|
||||
gst_buffer_pool_config_set_d3d11_allocation_params (config, d3d11_params);
|
||||
|
@ -868,6 +875,26 @@ gst_d3d11_color_convert_start (GstBaseTransform * trans)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_d3d11_color_convert_query (GstBaseTransform * trans,
|
||||
GstPadDirection direction, GstQuery * query)
|
||||
{
|
||||
if (gst_query_is_d3d11_usage (query) && direction == GST_PAD_SINK) {
|
||||
D3D11_USAGE usage = D3D11_USAGE_DEFAULT;
|
||||
|
||||
gst_query_parse_d3d11_usage (query, &usage);
|
||||
if (usage == D3D11_USAGE_DEFAULT || usage == D3D11_USAGE_DYNAMIC)
|
||||
gst_query_set_d3d11_usage_result (query, TRUE);
|
||||
else
|
||||
gst_query_set_d3d11_usage_result (query, FALSE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return GST_BASE_TRANSFORM_CLASS (parent_class)->query (trans, direction,
|
||||
query);
|
||||
}
|
||||
|
||||
/* from video-converter.c */
|
||||
typedef struct
|
||||
{
|
||||
|
@ -1897,11 +1924,13 @@ do_convert (GstD3D11Device * device, DoConvertData * data)
|
|||
|
||||
g_assert (gst_is_d3d11_memory (mem));
|
||||
|
||||
/* map to transfer pending staging data if any */
|
||||
gst_memory_map (mem, &info, GST_MAP_READ | GST_MAP_D3D11);
|
||||
gst_memory_unmap (mem, &info);
|
||||
|
||||
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 (mem)) {
|
||||
for (j = 0; j < d3d11_mem->num_shader_resource_views; j++) {
|
||||
resource_view[view_index] = d3d11_mem->shader_resource_view[j];
|
||||
|
|
|
@ -31,11 +31,12 @@ GST_DEBUG_CATEGORY_STATIC (gst_d3d11_allocator_debug);
|
|||
|
||||
GstD3D11AllocationParams *
|
||||
gst_d3d11_allocation_params_new (GstVideoInfo * info,
|
||||
GstD3D11AllocationFlags flags)
|
||||
GstD3D11AllocationFlags flags, D3D11_USAGE usage, gint bind_flags)
|
||||
{
|
||||
GstD3D11AllocationParams *ret;
|
||||
const GstD3D11Format *d3d11_format;
|
||||
gint i;
|
||||
gint cpu_access_flags;
|
||||
|
||||
g_return_val_if_fail (info != NULL, NULL);
|
||||
|
||||
|
@ -45,6 +46,15 @@ gst_d3d11_allocation_params_new (GstVideoInfo * info,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (usage == D3D11_USAGE_DEFAULT) {
|
||||
cpu_access_flags = 0;
|
||||
} else if (usage == D3D11_USAGE_DYNAMIC) {
|
||||
cpu_access_flags = D3D11_CPU_ACCESS_WRITE;
|
||||
} else {
|
||||
GST_FIXME ("Neither default nor dynamic usage");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = g_new0 (GstD3D11AllocationParams, 1);
|
||||
|
||||
ret->info = *info;
|
||||
|
@ -79,8 +89,9 @@ gst_d3d11_allocation_params_new (GstVideoInfo * info,
|
|||
ret->desc[i].Format = d3d11_format->resource_format[i];
|
||||
ret->desc[i].SampleDesc.Count = 1;
|
||||
ret->desc[i].SampleDesc.Quality = 0;
|
||||
ret->desc[i].Usage = D3D11_USAGE_DEFAULT;
|
||||
/* User must set proper BindFlags and MiscFlags manually */
|
||||
ret->desc[i].Usage = usage;
|
||||
ret->desc[i].BindFlags = bind_flags;
|
||||
ret->desc[i].CPUAccessFlags = cpu_access_flags;
|
||||
}
|
||||
} else {
|
||||
g_assert (d3d11_format->dxgi_format != DXGI_FORMAT_UNKNOWN);
|
||||
|
@ -92,7 +103,9 @@ gst_d3d11_allocation_params_new (GstVideoInfo * info,
|
|||
ret->desc[0].Format = d3d11_format->dxgi_format;
|
||||
ret->desc[0].SampleDesc.Count = 1;
|
||||
ret->desc[0].SampleDesc.Quality = 0;
|
||||
ret->desc[0].Usage = D3D11_USAGE_DEFAULT;
|
||||
ret->desc[0].Usage = usage;
|
||||
ret->desc[0].BindFlags = bind_flags;
|
||||
ret->desc[0].CPUAccessFlags = cpu_access_flags;
|
||||
}
|
||||
|
||||
ret->flags = flags;
|
||||
|
@ -242,8 +255,13 @@ gst_d3d11_memory_map (GstMemory * mem, gsize maxsize, GstMapFlags flags)
|
|||
{
|
||||
GstD3D11Memory *dmem = (GstD3D11Memory *) mem;
|
||||
|
||||
g_mutex_lock (&dmem->lock);
|
||||
if (dmem->desc.Usage == D3D11_USAGE_DYNAMIC) {
|
||||
GST_FIXME_OBJECT (mem->allocator,
|
||||
"D3D11_USAGE_DYNAMIC shouldn't be used with gst_memory_map");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_mutex_lock (&dmem->lock);
|
||||
if ((flags & GST_MAP_D3D11) == GST_MAP_D3D11) {
|
||||
if (dmem->staging &&
|
||||
GST_MEMORY_FLAG_IS_SET (dmem, GST_D3D11_MEMORY_TRANSFER_NEED_UPLOAD)) {
|
||||
|
@ -325,6 +343,12 @@ gst_d3d11_memory_unmap_full (GstMemory * mem, GstMapInfo * info)
|
|||
{
|
||||
GstD3D11Memory *dmem = (GstD3D11Memory *) mem;
|
||||
|
||||
if (dmem->desc.Usage == D3D11_USAGE_DYNAMIC) {
|
||||
GST_FIXME_OBJECT (mem->allocator,
|
||||
"D3D11_USAGE_DYNAMIC shouldn't be used with gst_memory_unmap");
|
||||
return;
|
||||
}
|
||||
|
||||
g_mutex_lock (&dmem->lock);
|
||||
if ((info->flags & GST_MAP_D3D11) == GST_MAP_D3D11) {
|
||||
if ((info->flags & GST_MAP_WRITE) == GST_MAP_WRITE)
|
||||
|
@ -454,8 +478,9 @@ gst_d3d11_allocator_new (GstD3D11Device * device)
|
|||
|
||||
typedef struct
|
||||
{
|
||||
ID3D11Resource *staging;
|
||||
ID3D11Resource *texture;
|
||||
D3D11_TEXTURE2D_DESC *desc;
|
||||
D3D11_MAP map_mode;
|
||||
|
||||
gint stride[GST_VIDEO_MAX_PLANES];
|
||||
gsize size;
|
||||
|
@ -473,11 +498,10 @@ calculate_mem_size (GstD3D11Device * device, CalSizeData * data)
|
|||
gst_d3d11_device_get_device_context_handle (device);
|
||||
|
||||
hr = ID3D11DeviceContext_Map (device_context,
|
||||
data->staging, 0, D3D11_MAP_READ, 0, &map);
|
||||
data->texture, 0, data->map_mode, 0, &map);
|
||||
|
||||
if (FAILED (hr)) {
|
||||
GST_ERROR_OBJECT (device,
|
||||
"Failed to map staging texture (0x%x)", (guint) hr);
|
||||
GST_ERROR_OBJECT (device, "Failed to map texture (0x%x)", (guint) hr);
|
||||
data->ret = FALSE;
|
||||
}
|
||||
|
||||
|
@ -485,7 +509,7 @@ calculate_mem_size (GstD3D11Device * device, CalSizeData * data)
|
|||
data->desc->Width, data->desc->Height, map.RowPitch,
|
||||
offset, data->stride, &data->size);
|
||||
|
||||
ID3D11DeviceContext_Unmap (device_context, data->staging, 0);
|
||||
ID3D11DeviceContext_Unmap (device_context, data->texture, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -649,6 +673,7 @@ gst_d3d11_allocator_alloc (GstD3D11Allocator * allocator,
|
|||
D3D11_TEXTURE2D_DESC *desc;
|
||||
gsize *size;
|
||||
gboolean is_first = FALSE;
|
||||
GstMemoryFlags memory_flags;
|
||||
|
||||
g_return_val_if_fail (GST_IS_D3D11_ALLOCATOR (allocator), NULL);
|
||||
g_return_val_if_fail (params != NULL, NULL);
|
||||
|
@ -657,6 +682,16 @@ gst_d3d11_allocator_alloc (GstD3D11Allocator * allocator,
|
|||
desc = ¶ms->desc[params->plane];
|
||||
size = ¶ms->size[params->plane];
|
||||
|
||||
if (desc->Usage == D3D11_USAGE_DEFAULT) {
|
||||
memory_flags = 0;
|
||||
} else if (desc->Usage == D3D11_USAGE_DYNAMIC) {
|
||||
/* FIXME: how we can make D3D11_USAGE_DYNAMIC work with GST_MAP_READWRITE ? */
|
||||
memory_flags = GST_MEMORY_FLAG_NOT_MAPPABLE;
|
||||
} else {
|
||||
GST_FIXME_OBJECT (allocator, "Cannot support usage %d", desc->Usage);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (*size == 0)
|
||||
is_first = TRUE;
|
||||
|
||||
|
@ -673,13 +708,22 @@ gst_d3d11_allocator_alloc (GstD3D11Allocator * allocator,
|
|||
gint num_plane;
|
||||
gint i;
|
||||
|
||||
staging = create_staging_texture (device, desc);
|
||||
if (!staging) {
|
||||
GST_ERROR_OBJECT (allocator, "Couldn't create staging texture");
|
||||
goto error;
|
||||
if (desc->Usage == D3D11_USAGE_DEFAULT) {
|
||||
staging = create_staging_texture (device, desc);
|
||||
if (!staging) {
|
||||
GST_ERROR_OBJECT (allocator, "Couldn't create staging texture");
|
||||
goto error;
|
||||
}
|
||||
|
||||
data.texture = (ID3D11Resource *) staging;
|
||||
data.map_mode = D3D11_MAP_READ;
|
||||
} else if (desc->Usage == D3D11_USAGE_DYNAMIC) {
|
||||
data.texture = (ID3D11Resource *) texture;
|
||||
data.map_mode = D3D11_MAP_WRITE_DISCARD;
|
||||
} else {
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
data.staging = (ID3D11Resource *) staging;
|
||||
data.desc = desc;
|
||||
|
||||
gst_d3d11_device_thread_add (device,
|
||||
|
@ -697,7 +741,7 @@ gst_d3d11_allocator_alloc (GstD3D11Allocator * allocator,
|
|||
mem = g_new0 (GstD3D11Memory, 1);
|
||||
|
||||
gst_memory_init (GST_MEMORY_CAST (mem),
|
||||
0, GST_ALLOCATOR_CAST (allocator), NULL, *size, 0, 0, *size);
|
||||
memory_flags, GST_ALLOCATOR_CAST (allocator), NULL, *size, 0, 0, *size);
|
||||
|
||||
g_mutex_init (&mem->lock);
|
||||
mem->info = params->info;
|
||||
|
|
|
@ -146,7 +146,9 @@ struct _GstD3D11AllocatorClass
|
|||
GType gst_d3d11_allocation_params_get_type (void);
|
||||
|
||||
GstD3D11AllocationParams * gst_d3d11_allocation_params_new (GstVideoInfo * info,
|
||||
GstD3D11AllocationFlags flags);
|
||||
GstD3D11AllocationFlags flags,
|
||||
D3D11_USAGE usage,
|
||||
gint bind_flags);
|
||||
|
||||
GstD3D11AllocationParams * gst_d3d11_allocation_params_copy (GstD3D11AllocationParams * src);
|
||||
|
||||
|
|
|
@ -25,6 +25,9 @@
|
|||
#include "gstd3d11memory.h"
|
||||
#include "gstd3d11device.h"
|
||||
#include "gstd3d11bufferpool.h"
|
||||
#include "gstd3d11utils.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (gst_d3d11_upload_debug);
|
||||
#define GST_CAT_DEFAULT gst_d3d11_upload_debug
|
||||
|
@ -224,12 +227,16 @@ gst_d3d11_upload_decide_allocation (GstBaseTransform * trans, GstQuery * query)
|
|||
guint size, min, max;
|
||||
GstStructure *config;
|
||||
gboolean update_pool = FALSE;
|
||||
GstVideoInfo vinfo;
|
||||
gint i;
|
||||
|
||||
gst_query_parse_allocation (query, &outcaps, NULL);
|
||||
|
||||
if (!outcaps)
|
||||
return FALSE;
|
||||
|
||||
gst_video_info_from_caps (&vinfo, outcaps);
|
||||
|
||||
if (gst_query_get_n_allocation_pools (query) > 0) {
|
||||
gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max);
|
||||
if (pool && !GST_IS_D3D11_BUFFER_POOL (pool)) {
|
||||
|
@ -239,8 +246,6 @@ gst_d3d11_upload_decide_allocation (GstBaseTransform * trans, GstQuery * query)
|
|||
|
||||
update_pool = TRUE;
|
||||
} else {
|
||||
GstVideoInfo vinfo;
|
||||
gst_video_info_from_caps (&vinfo, outcaps);
|
||||
size = GST_VIDEO_INFO_SIZE (&vinfo);
|
||||
min = max = 0;
|
||||
}
|
||||
|
@ -254,6 +259,45 @@ gst_d3d11_upload_decide_allocation (GstBaseTransform * trans, GstQuery * query)
|
|||
config = gst_buffer_pool_get_config (pool);
|
||||
gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
|
||||
gst_buffer_pool_config_set_params (config, outcaps, size, min, max);
|
||||
|
||||
{
|
||||
GstQuery *usage_query;
|
||||
gboolean can_dynamic = FALSE;
|
||||
|
||||
usage_query = gst_query_new_d3d11_usage (D3D11_USAGE_DYNAMIC);
|
||||
gst_pad_peer_query (GST_BASE_TRANSFORM_SRC_PAD (trans), usage_query);
|
||||
gst_query_parse_d3d11_usage_result (usage_query, &can_dynamic);
|
||||
gst_query_unref (usage_query);
|
||||
|
||||
if (can_dynamic) {
|
||||
GstD3D11AllocationParams *d3d11_params;
|
||||
|
||||
GST_DEBUG_OBJECT (trans, "downstream support dynamic usage");
|
||||
|
||||
d3d11_params =
|
||||
gst_buffer_pool_config_get_d3d11_allocation_params (config);
|
||||
if (!d3d11_params) {
|
||||
/* dynamic usage should have at least one bind flag.
|
||||
* but followings are not allowed in this case
|
||||
* D3D11_BIND_STREAM_OUTPUT
|
||||
* D3D11_BIND_RENDER_TARGET
|
||||
* D3D11_BIND_DEPTH_STENCIL
|
||||
* D3D11_BIND_UNORDERED_ACCESS */
|
||||
d3d11_params = gst_d3d11_allocation_params_new (&vinfo,
|
||||
GST_D3D11_ALLOCATION_FLAG_USE_RESOURCE_FORMAT,
|
||||
D3D11_USAGE_DYNAMIC, D3D11_BIND_SHADER_RESOURCE);
|
||||
} else {
|
||||
for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) {
|
||||
d3d11_params->desc[i].Usage = D3D11_USAGE_DYNAMIC;
|
||||
d3d11_params->desc[i].CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
}
|
||||
}
|
||||
|
||||
gst_buffer_pool_config_set_d3d11_allocation_params (config, d3d11_params);
|
||||
gst_d3d11_allocation_params_free (d3d11_params);
|
||||
}
|
||||
}
|
||||
|
||||
gst_buffer_pool_set_config (pool, config);
|
||||
|
||||
/* update size with calculated one */
|
||||
|
@ -278,6 +322,82 @@ typedef struct
|
|||
GstFlowReturn ret;
|
||||
} UploadTransformData;
|
||||
|
||||
static void
|
||||
upload_transform_dynamic (GstD3D11Device * device, UploadTransformData * data)
|
||||
{
|
||||
GstVideoFrame in_frame;
|
||||
GstD3D11BaseFilter *filter = data->filter;
|
||||
gint i, j, k;
|
||||
ID3D11DeviceContext *device_context =
|
||||
gst_d3d11_device_get_device_context_handle (device);
|
||||
|
||||
data->ret = GST_FLOW_OK;
|
||||
|
||||
if (!gst_video_frame_map (&in_frame, &filter->in_info, data->inbuf,
|
||||
GST_MAP_READ | GST_VIDEO_FRAME_MAP_FLAG_NO_REF))
|
||||
goto invalid_buffer;
|
||||
|
||||
for (i = 0, j = 0; i < gst_buffer_n_memory (data->outbuf); i++) {
|
||||
GstD3D11Memory *dmem =
|
||||
(GstD3D11Memory *) gst_buffer_peek_memory (data->outbuf, i);
|
||||
D3D11_MAPPED_SUBRESOURCE map;
|
||||
HRESULT hr;
|
||||
D3D11_TEXTURE2D_DESC *desc = &dmem->desc;
|
||||
gsize offset[GST_VIDEO_MAX_PLANES];
|
||||
gint stride[GST_VIDEO_MAX_PLANES];
|
||||
gsize dummy;
|
||||
|
||||
hr = ID3D11DeviceContext_Map (device_context,
|
||||
(ID3D11Resource *) dmem->texture, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
|
||||
|
||||
if (FAILED (hr)) {
|
||||
GST_ERROR_OBJECT (filter,
|
||||
"Failed to map staging texture (0x%x)", (guint) hr);
|
||||
data->ret = GST_FLOW_ERROR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
gst_d3d11_dxgi_format_get_size (desc->Format, desc->Width, desc->Height,
|
||||
map.RowPitch, offset, stride, &dummy);
|
||||
|
||||
for (k = 0; k < gst_d3d11_dxgi_format_n_planes (dmem->desc.Format); k++) {
|
||||
gint h, width;
|
||||
guint8 *dst, *src;
|
||||
|
||||
dst = (guint8 *) map.pData + offset[k];
|
||||
src = GST_VIDEO_FRAME_PLANE_DATA (&in_frame, j);
|
||||
width = GST_VIDEO_FRAME_COMP_WIDTH (&in_frame, j) *
|
||||
GST_VIDEO_FRAME_COMP_PSTRIDE (&in_frame, j);
|
||||
|
||||
for (h = 0; h < GST_VIDEO_FRAME_COMP_HEIGHT (&in_frame, j); h++) {
|
||||
memcpy (dst, src, width);
|
||||
dst += stride[k];
|
||||
src += GST_VIDEO_FRAME_PLANE_STRIDE (&in_frame, j);
|
||||
}
|
||||
|
||||
j++;
|
||||
}
|
||||
|
||||
ID3D11DeviceContext_Unmap (device_context,
|
||||
(ID3D11Resource *) dmem->texture, 0);
|
||||
}
|
||||
|
||||
done:
|
||||
gst_video_frame_unmap (&in_frame);
|
||||
|
||||
data->ret = GST_FLOW_OK;
|
||||
return;
|
||||
|
||||
/* ERRORS */
|
||||
invalid_buffer:
|
||||
{
|
||||
GST_ELEMENT_WARNING (filter, CORE, NOT_IMPLEMENTED, (NULL),
|
||||
("invalid video buffer received"));
|
||||
data->ret = GST_FLOW_ERROR;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
upload_transform (GstD3D11Device * device, UploadTransformData * data)
|
||||
{
|
||||
|
@ -327,11 +447,15 @@ gst_d3d11_upload_transform (GstBaseTransform * trans, GstBuffer * inbuf,
|
|||
GstMemory *mem;
|
||||
GstD3D11Device *device;
|
||||
UploadTransformData data;
|
||||
gboolean to_dynamic = FALSE;
|
||||
|
||||
mem = gst_buffer_peek_memory (outbuf, 0);
|
||||
if (gst_is_d3d11_memory (mem)) {
|
||||
GstD3D11Memory *dmem = (GstD3D11Memory *) mem;
|
||||
device = dmem->device;
|
||||
|
||||
if (dmem->desc.Usage == D3D11_USAGE_DYNAMIC)
|
||||
to_dynamic = TRUE;
|
||||
} else {
|
||||
device = filter->device;
|
||||
}
|
||||
|
@ -341,8 +465,13 @@ gst_d3d11_upload_transform (GstBaseTransform * trans, GstBuffer * inbuf,
|
|||
data.outbuf = outbuf;
|
||||
data.ret = GST_FLOW_OK;
|
||||
|
||||
gst_d3d11_device_thread_add (device,
|
||||
(GstD3D11DeviceThreadFunc) upload_transform, &data);
|
||||
if (to_dynamic) {
|
||||
gst_d3d11_device_thread_add (device,
|
||||
(GstD3D11DeviceThreadFunc) upload_transform_dynamic, &data);
|
||||
} else {
|
||||
gst_d3d11_device_thread_add (device,
|
||||
(GstD3D11DeviceThreadFunc) upload_transform, &data);
|
||||
}
|
||||
|
||||
return data.ret;
|
||||
}
|
||||
|
|
|
@ -355,3 +355,84 @@ gst_d3d11_is_windows_8_or_greater (void)
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
GstQuery *
|
||||
gst_query_new_d3d11_usage (D3D11_USAGE usage)
|
||||
{
|
||||
GstQuery *query;
|
||||
GstStructure *structure;
|
||||
|
||||
structure = gst_structure_new ("GstQueryD3D11Usage",
|
||||
"usage", G_TYPE_INT, usage, "result", G_TYPE_BOOLEAN, FALSE, NULL);
|
||||
query = gst_query_new_custom (GST_QUERY_CUSTOM, structure);
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
void
|
||||
gst_query_parse_d3d11_usage (GstQuery * query, D3D11_USAGE * usage)
|
||||
{
|
||||
const GstStructure *structure;
|
||||
|
||||
g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CUSTOM);
|
||||
|
||||
if (!gst_query_is_d3d11_usage (query))
|
||||
return;
|
||||
|
||||
structure = gst_query_get_structure (query);
|
||||
|
||||
gst_structure_get (structure, "usage", G_TYPE_INT, usage, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
gst_query_set_d3d11_usage_result (GstQuery * query, gboolean result)
|
||||
{
|
||||
GstStructure *structure;
|
||||
const gchar *name;
|
||||
|
||||
g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CUSTOM);
|
||||
g_return_if_fail (gst_query_is_writable (query));
|
||||
|
||||
structure = gst_query_writable_structure (query);
|
||||
name = gst_structure_get_name (structure);
|
||||
|
||||
g_return_if_fail (g_strcmp0 (name, "GstQueryD3D11Usage") == 0);
|
||||
gst_structure_set (structure, "result", G_TYPE_BOOLEAN, result, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
gst_query_parse_d3d11_usage_result (GstQuery * query, gboolean * result)
|
||||
{
|
||||
const GstStructure *structure;
|
||||
const gchar *name;
|
||||
|
||||
g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CUSTOM);
|
||||
g_return_if_fail (gst_query_is_writable (query));
|
||||
g_return_if_fail (result != NULL);
|
||||
|
||||
structure = gst_query_get_structure (query);
|
||||
name = gst_structure_get_name (structure);
|
||||
|
||||
g_return_if_fail (g_strcmp0 (name, "GstQueryD3D11Usage") == 0);
|
||||
|
||||
gst_structure_get (structure, "result", G_TYPE_BOOLEAN, result, NULL);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_query_is_d3d11_usage (GstQuery * query)
|
||||
{
|
||||
const GstStructure *structure;
|
||||
|
||||
g_return_val_if_fail (GST_IS_QUERY (query), FALSE);
|
||||
|
||||
if (GST_QUERY_TYPE (query) != GST_QUERY_CUSTOM)
|
||||
return FALSE;
|
||||
|
||||
structure = gst_query_get_structure (query);
|
||||
|
||||
if (!structure ||
|
||||
g_strcmp0 (gst_structure_get_name (structure), "GstQueryD3D11Usage"))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -42,6 +42,19 @@ gboolean gst_d3d11_ensure_element_data (GstElement * element,
|
|||
|
||||
gboolean gst_d3d11_is_windows_8_or_greater (void);
|
||||
|
||||
GstQuery * gst_query_new_d3d11_usage (D3D11_USAGE usage);
|
||||
|
||||
void gst_query_parse_d3d11_usage (GstQuery * query,
|
||||
D3D11_USAGE *usage);
|
||||
|
||||
void gst_query_set_d3d11_usage_result (GstQuery * query,
|
||||
gboolean result);
|
||||
|
||||
void gst_query_parse_d3d11_usage_result (GstQuery * query,
|
||||
gboolean * result);
|
||||
|
||||
gboolean gst_query_is_d3d11_usage (GstQuery * query);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_D3D11_UTILS_H__ */
|
||||
|
|
|
@ -584,6 +584,19 @@ gst_d3d11_video_sink_query (GstBaseSink * sink, GstQuery * query)
|
|||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case GST_QUERY_CUSTOM:
|
||||
if (gst_query_is_d3d11_usage (query)) {
|
||||
D3D11_USAGE usage = D3D11_USAGE_DEFAULT;
|
||||
|
||||
gst_query_parse_d3d11_usage (query, &usage);
|
||||
if (usage == D3D11_USAGE_DEFAULT || usage == D3D11_USAGE_DYNAMIC)
|
||||
gst_query_set_d3d11_usage_result (query, TRUE);
|
||||
else
|
||||
gst_query_set_d3d11_usage_result (query, FALSE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -657,23 +670,28 @@ gst_d3d11_video_sink_show_frame (GstVideoSink * sink, GstBuffer * buf)
|
|||
ID3D11Texture2D *texture;
|
||||
GstMapInfo map;
|
||||
GstFlowReturn ret;
|
||||
gboolean need_unmap = FALSE;
|
||||
GstMemory *mem;
|
||||
GstVideoRectangle rect = { 0, };
|
||||
GstVideoCropMeta *crop;
|
||||
|
||||
if (gst_buffer_n_memory (buf) == 1 && (mem = gst_buffer_peek_memory (buf, 0))
|
||||
&& gst_memory_is_type (mem, GST_D3D11_MEMORY_NAME)) {
|
||||
GstD3D11Memory *dmem = (GstD3D11Memory *) mem;
|
||||
|
||||
/* If this buffer has been allocated using our buffer management we simply
|
||||
put the ximage which is in the PRIVATE pointer */
|
||||
GST_TRACE_OBJECT (self, "buffer %p from our pool, writing directly", buf);
|
||||
if (!gst_memory_map (mem, &map, (GST_MAP_READ | GST_MAP_D3D11))) {
|
||||
GST_ERROR_OBJECT (self, "cannot map d3d11 memory");
|
||||
return GST_FLOW_ERROR;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
texture = (ID3D11Texture2D *) map.data;
|
||||
need_unmap = TRUE;
|
||||
texture = dmem->texture;
|
||||
} else {
|
||||
if (!gst_video_frame_map (&frame, &self->info, buf, GST_MAP_READ)) {
|
||||
GST_ERROR_OBJECT (self, "cannot map video frame");
|
||||
|
@ -714,9 +732,6 @@ gst_d3d11_video_sink_show_frame (GstVideoSink * sink, GstBuffer * buf)
|
|||
|
||||
ret = gst_d3d11_window_render (self->window, texture, &rect);
|
||||
|
||||
if (need_unmap)
|
||||
gst_memory_unmap (mem, &map);
|
||||
|
||||
if (ret == GST_D3D11_WINDOW_FLOW_CLOSED) {
|
||||
GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND,
|
||||
("Output window was closed"), (NULL));
|
||||
|
|
Loading…
Reference in a new issue