mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-03-30 12:49:40 +00:00
d3d11upload/d3d11download: Make use of staging buffer
... instead of direct cpu map for d3d11memory object. In this way, we don't need per GstD3D11Memory staging texture. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1627>
This commit is contained in:
parent
f35eeaa02b
commit
a9314b4554
4 changed files with 405 additions and 7 deletions
|
@ -65,12 +65,18 @@ static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
|
|||
struct _GstD3D11Download
|
||||
{
|
||||
GstD3D11BaseFilter parent;
|
||||
|
||||
GstBuffer *staging_buffer;
|
||||
};
|
||||
|
||||
#define gst_d3d11_download_parent_class parent_class
|
||||
G_DEFINE_TYPE (GstD3D11Download, gst_d3d11_download,
|
||||
GST_TYPE_D3D11_BASE_FILTER);
|
||||
|
||||
static void gst_d3d11_download_dispose (GObject * object);
|
||||
static gboolean gst_d3d11_download_stop (GstBaseTransform * trans);
|
||||
static gboolean gst_d3d11_download_sink_event (GstBaseTransform * trans,
|
||||
GstEvent * event);
|
||||
static GstCaps *gst_d3d11_download_transform_caps (GstBaseTransform * trans,
|
||||
GstPadDirection direction, GstCaps * caps, GstCaps * filter);
|
||||
static gboolean gst_d3d11_download_propose_allocation (GstBaseTransform * trans,
|
||||
|
@ -79,12 +85,19 @@ static gboolean gst_d3d11_download_decide_allocation (GstBaseTransform * trans,
|
|||
GstQuery * query);
|
||||
static GstFlowReturn gst_d3d11_download_transform (GstBaseTransform * trans,
|
||||
GstBuffer * inbuf, GstBuffer * outbuf);
|
||||
static gboolean gst_d3d11_download_set_info (GstD3D11BaseFilter * filter,
|
||||
GstCaps * incaps, GstVideoInfo * in_info, GstCaps * outcaps,
|
||||
GstVideoInfo * out_info);
|
||||
|
||||
static void
|
||||
gst_d3d11_download_class_init (GstD3D11DownloadClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||
GstBaseTransformClass *trans_class = GST_BASE_TRANSFORM_CLASS (klass);
|
||||
GstD3D11BaseFilterClass *bfilter_class = GST_D3D11_BASE_FILTER_CLASS (klass);
|
||||
|
||||
gobject_class->dispose = gst_d3d11_download_dispose;
|
||||
|
||||
gst_element_class_add_static_pad_template (element_class, &sink_template);
|
||||
gst_element_class_add_static_pad_template (element_class, &src_template);
|
||||
|
@ -96,6 +109,8 @@ gst_d3d11_download_class_init (GstD3D11DownloadClass * klass)
|
|||
|
||||
trans_class->passthrough_on_same_caps = TRUE;
|
||||
|
||||
trans_class->stop = GST_DEBUG_FUNCPTR (gst_d3d11_download_stop);
|
||||
trans_class->sink_event = GST_DEBUG_FUNCPTR (gst_d3d11_download_sink_event);
|
||||
trans_class->transform_caps =
|
||||
GST_DEBUG_FUNCPTR (gst_d3d11_download_transform_caps);
|
||||
trans_class->propose_allocation =
|
||||
|
@ -104,6 +119,8 @@ gst_d3d11_download_class_init (GstD3D11DownloadClass * klass)
|
|||
GST_DEBUG_FUNCPTR (gst_d3d11_download_decide_allocation);
|
||||
trans_class->transform = GST_DEBUG_FUNCPTR (gst_d3d11_download_transform);
|
||||
|
||||
bfilter_class->set_info = GST_DEBUG_FUNCPTR (gst_d3d11_download_set_info);
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (gst_d3d11_download_debug,
|
||||
"d3d11download", 0, "d3d11download Element");
|
||||
}
|
||||
|
@ -113,6 +130,43 @@ gst_d3d11_download_init (GstD3D11Download * download)
|
|||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gst_d3d11_download_dispose (GObject * object)
|
||||
{
|
||||
GstD3D11Download *self = GST_D3D11_DOWNLOAD (object);
|
||||
|
||||
gst_clear_buffer (&self->staging_buffer);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_d3d11_download_stop (GstBaseTransform * trans)
|
||||
{
|
||||
GstD3D11Download *self = GST_D3D11_DOWNLOAD (trans);
|
||||
|
||||
gst_clear_buffer (&self->staging_buffer);
|
||||
|
||||
return GST_BASE_TRANSFORM_CLASS (parent_class)->stop (trans);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_d3d11_download_sink_event (GstBaseTransform * trans, GstEvent * event)
|
||||
{
|
||||
GstD3D11Download *self = GST_D3D11_DOWNLOAD (trans);
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_EOS:
|
||||
/* We don't need to hold this staging buffer after eos */
|
||||
gst_clear_buffer (&self->staging_buffer);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return GST_BASE_TRANSFORM_CLASS (parent_class)->sink_event (trans, event);
|
||||
}
|
||||
|
||||
static GstCaps *
|
||||
_set_caps_features (const GstCaps * caps, const gchar * feature_name)
|
||||
{
|
||||
|
@ -289,15 +343,63 @@ gst_d3d11_download_decide_allocation (GstBaseTransform * trans,
|
|||
query);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_d3d11_download_can_use_staging_buffer (GstD3D11Download * self,
|
||||
GstBuffer * inbuf)
|
||||
{
|
||||
GstD3D11BaseFilter *filter = GST_D3D11_BASE_FILTER (self);
|
||||
gint i;
|
||||
|
||||
/* 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 (self->staging_buffer)
|
||||
return TRUE;
|
||||
|
||||
self->staging_buffer = gst_d3d11_allocate_staging_buffer_for (inbuf,
|
||||
&filter->in_info, TRUE);
|
||||
|
||||
if (!self->staging_buffer) {
|
||||
GST_WARNING_OBJECT (self, "Couldn't allocate staging buffer");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_d3d11_download_transform (GstBaseTransform * trans, GstBuffer * inbuf,
|
||||
GstBuffer * outbuf)
|
||||
{
|
||||
GstD3D11BaseFilter *filter = GST_D3D11_BASE_FILTER (trans);
|
||||
GstD3D11Download *self = GST_D3D11_DOWNLOAD (trans);
|
||||
GstVideoFrame in_frame, out_frame;
|
||||
GstFlowReturn ret = GST_FLOW_OK;
|
||||
gboolean use_staging_buf;
|
||||
GstBuffer *target_inbuf = inbuf;
|
||||
gint i;
|
||||
|
||||
if (!gst_video_frame_map (&in_frame, &filter->in_info, inbuf,
|
||||
use_staging_buf = gst_d3d11_download_can_use_staging_buffer (self, inbuf);
|
||||
|
||||
if (use_staging_buf) {
|
||||
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)) {
|
||||
GST_ERROR_OBJECT (self,
|
||||
"Failed to copy input buffer into staging texture");
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
|
||||
target_inbuf = self->staging_buffer;
|
||||
}
|
||||
|
||||
if (!gst_video_frame_map (&in_frame, &filter->in_info, target_inbuf,
|
||||
GST_MAP_READ | GST_VIDEO_FRAME_MAP_FLAG_NO_REF))
|
||||
goto invalid_buffer;
|
||||
|
||||
|
@ -310,14 +412,15 @@ gst_d3d11_download_transform (GstBaseTransform * trans, GstBuffer * inbuf,
|
|||
for (i = 0; i < GST_VIDEO_FRAME_N_PLANES (&in_frame); i++) {
|
||||
if (!gst_video_frame_copy_plane (&out_frame, &in_frame, i)) {
|
||||
GST_ERROR_OBJECT (filter, "Couldn't copy %dth plane", i);
|
||||
return GST_FLOW_ERROR;
|
||||
ret = GST_FLOW_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gst_video_frame_unmap (&out_frame);
|
||||
gst_video_frame_unmap (&in_frame);
|
||||
|
||||
return GST_FLOW_OK;
|
||||
return ret;
|
||||
|
||||
/* ERRORS */
|
||||
invalid_buffer:
|
||||
|
@ -327,3 +430,15 @@ invalid_buffer:
|
|||
return GST_FLOW_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_d3d11_download_set_info (GstD3D11BaseFilter * filter,
|
||||
GstCaps * incaps, GstVideoInfo * in_info, GstCaps * outcaps,
|
||||
GstVideoInfo * out_info)
|
||||
{
|
||||
GstD3D11Download *self = GST_D3D11_DOWNLOAD (filter);
|
||||
|
||||
gst_clear_buffer (&self->staging_buffer);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -60,11 +60,17 @@ static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
|
|||
struct _GstD3D11Upload
|
||||
{
|
||||
GstD3D11BaseFilter parent;
|
||||
|
||||
GstBuffer *staging_buffer;
|
||||
};
|
||||
|
||||
#define gst_d3d11_upload_parent_class parent_class
|
||||
G_DEFINE_TYPE (GstD3D11Upload, gst_d3d11_upload, GST_TYPE_D3D11_BASE_FILTER);
|
||||
|
||||
static void gst_d3d11_upload_dispose (GObject * object);
|
||||
static gboolean gst_d3d11_upload_stop (GstBaseTransform * trans);
|
||||
static gboolean gst_d3d11_upload_sink_event (GstBaseTransform * trans,
|
||||
GstEvent * event);
|
||||
static GstCaps *gst_d3d11_upload_transform_caps (GstBaseTransform * trans,
|
||||
GstPadDirection direction, GstCaps * caps, GstCaps * filter);
|
||||
static gboolean gst_d3d11_upload_propose_allocation (GstBaseTransform * trans,
|
||||
|
@ -73,12 +79,19 @@ static gboolean gst_d3d11_upload_decide_allocation (GstBaseTransform * trans,
|
|||
GstQuery * query);
|
||||
static GstFlowReturn gst_d3d11_upload_transform (GstBaseTransform * trans,
|
||||
GstBuffer * inbuf, GstBuffer * outbuf);
|
||||
static gboolean gst_d3d11_upload_set_info (GstD3D11BaseFilter * filter,
|
||||
GstCaps * incaps, GstVideoInfo * in_info, GstCaps * outcaps,
|
||||
GstVideoInfo * out_info);
|
||||
|
||||
static void
|
||||
gst_d3d11_upload_class_init (GstD3D11UploadClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||
GstBaseTransformClass *trans_class = GST_BASE_TRANSFORM_CLASS (klass);
|
||||
GstD3D11BaseFilterClass *bfilter_class = GST_D3D11_BASE_FILTER_CLASS (klass);
|
||||
|
||||
gobject_class->dispose = gst_d3d11_upload_dispose;
|
||||
|
||||
gst_element_class_add_static_pad_template (element_class, &sink_template);
|
||||
gst_element_class_add_static_pad_template (element_class, &src_template);
|
||||
|
@ -90,6 +103,8 @@ gst_d3d11_upload_class_init (GstD3D11UploadClass * klass)
|
|||
|
||||
trans_class->passthrough_on_same_caps = TRUE;
|
||||
|
||||
trans_class->stop = GST_DEBUG_FUNCPTR (gst_d3d11_upload_stop);
|
||||
trans_class->sink_event = GST_DEBUG_FUNCPTR (gst_d3d11_upload_sink_event);
|
||||
trans_class->transform_caps =
|
||||
GST_DEBUG_FUNCPTR (gst_d3d11_upload_transform_caps);
|
||||
trans_class->propose_allocation =
|
||||
|
@ -98,6 +113,8 @@ gst_d3d11_upload_class_init (GstD3D11UploadClass * klass)
|
|||
GST_DEBUG_FUNCPTR (gst_d3d11_upload_decide_allocation);
|
||||
trans_class->transform = GST_DEBUG_FUNCPTR (gst_d3d11_upload_transform);
|
||||
|
||||
bfilter_class->set_info = GST_DEBUG_FUNCPTR (gst_d3d11_upload_set_info);
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (gst_d3d11_upload_debug,
|
||||
"d3d11upload", 0, "d3d11upload Element");
|
||||
}
|
||||
|
@ -107,6 +124,43 @@ gst_d3d11_upload_init (GstD3D11Upload * upload)
|
|||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gst_d3d11_upload_dispose (GObject * object)
|
||||
{
|
||||
GstD3D11Upload *self = GST_D3D11_UPLOAD (object);
|
||||
|
||||
gst_clear_buffer (&self->staging_buffer);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_d3d11_upload_stop (GstBaseTransform * trans)
|
||||
{
|
||||
GstD3D11Upload *self = GST_D3D11_UPLOAD (trans);
|
||||
|
||||
gst_clear_buffer (&self->staging_buffer);
|
||||
|
||||
return GST_BASE_TRANSFORM_CLASS (parent_class)->stop (trans);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_d3d11_upload_sink_event (GstBaseTransform * trans, GstEvent * event)
|
||||
{
|
||||
GstD3D11Upload *self = GST_D3D11_UPLOAD (trans);
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_EOS:
|
||||
/* We don't need to hold this staging buffer after eos */
|
||||
gst_clear_buffer (&self->staging_buffer);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return GST_BASE_TRANSFORM_CLASS (parent_class)->sink_event (trans, event);
|
||||
}
|
||||
|
||||
static GstCaps *
|
||||
_set_caps_features (const GstCaps * caps, const gchar * feature_name)
|
||||
{
|
||||
|
@ -331,21 +385,59 @@ gst_d3d11_upload_decide_allocation (GstBaseTransform * trans, GstQuery * query)
|
|||
query);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_d3d11_upload_can_use_staging_buffer (GstD3D11Upload * self,
|
||||
GstBuffer * outbuf)
|
||||
{
|
||||
GstD3D11BaseFilter *filter = GST_D3D11_BASE_FILTER (self);
|
||||
gint i;
|
||||
|
||||
/* 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 (self->staging_buffer)
|
||||
return TRUE;
|
||||
|
||||
self->staging_buffer = gst_d3d11_allocate_staging_buffer_for (outbuf,
|
||||
&filter->out_info, TRUE);
|
||||
|
||||
if (!self->staging_buffer) {
|
||||
GST_WARNING_OBJECT (self, "Couldn't allocate staging buffer");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_d3d11_upload_transform (GstBaseTransform * trans, GstBuffer * inbuf,
|
||||
GstBuffer * outbuf)
|
||||
{
|
||||
GstD3D11BaseFilter *filter = GST_D3D11_BASE_FILTER (trans);
|
||||
|
||||
GstD3D11Upload *self = GST_D3D11_UPLOAD (trans);
|
||||
GstVideoFrame in_frame, out_frame;
|
||||
gint i;
|
||||
GstFlowReturn ret = GST_FLOW_OK;
|
||||
gboolean use_staging_buf;
|
||||
GstBuffer *target_outbuf = outbuf;
|
||||
gint i;
|
||||
|
||||
use_staging_buf = gst_d3d11_upload_can_use_staging_buffer (self, outbuf);
|
||||
|
||||
if (use_staging_buf) {
|
||||
GST_TRACE_OBJECT (self, "Copy input buffer to staging buffer");
|
||||
target_outbuf = self->staging_buffer;
|
||||
}
|
||||
|
||||
if (!gst_video_frame_map (&in_frame, &filter->in_info, inbuf,
|
||||
GST_MAP_READ | GST_VIDEO_FRAME_MAP_FLAG_NO_REF))
|
||||
goto invalid_buffer;
|
||||
|
||||
if (!gst_video_frame_map (&out_frame, &filter->out_info, outbuf,
|
||||
if (!gst_video_frame_map (&out_frame, &filter->out_info, target_outbuf,
|
||||
GST_MAP_WRITE | GST_VIDEO_FRAME_MAP_FLAG_NO_REF)) {
|
||||
gst_video_frame_unmap (&in_frame);
|
||||
goto invalid_buffer;
|
||||
|
@ -353,7 +445,7 @@ gst_d3d11_upload_transform (GstBaseTransform * trans, GstBuffer * inbuf,
|
|||
|
||||
for (i = 0; i < GST_VIDEO_FRAME_N_PLANES (&in_frame); i++) {
|
||||
if (!gst_video_frame_copy_plane (&out_frame, &in_frame, i)) {
|
||||
GST_ERROR_OBJECT (filter, "Couldn't copy %dth plane", i);
|
||||
GST_ERROR_OBJECT (filter, "Couldn't copy plane %d", i);
|
||||
ret = GST_FLOW_ERROR;
|
||||
break;
|
||||
}
|
||||
|
@ -362,6 +454,14 @@ gst_d3d11_upload_transform (GstBaseTransform * trans, GstBuffer * inbuf,
|
|||
gst_video_frame_unmap (&out_frame);
|
||||
gst_video_frame_unmap (&in_frame);
|
||||
|
||||
/* Copy staging texture to d3d11 texture */
|
||||
if (use_staging_buf) {
|
||||
if (!gst_d3d11_buffer_copy_into (outbuf, self->staging_buffer)) {
|
||||
GST_ERROR_OBJECT (self, "Cannot copy staging texture into texture");
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
/* ERRORS */
|
||||
|
@ -372,3 +472,15 @@ invalid_buffer:
|
|||
return GST_FLOW_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_d3d11_upload_set_info (GstD3D11BaseFilter * filter,
|
||||
GstCaps * incaps, GstVideoInfo * in_info, GstCaps * outcaps,
|
||||
GstVideoInfo * out_info)
|
||||
{
|
||||
GstD3D11Upload *self = GST_D3D11_UPLOAD (filter);
|
||||
|
||||
gst_clear_buffer (&self->staging_buffer);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -471,6 +471,80 @@ error:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
GstBuffer *
|
||||
gst_d3d11_allocate_staging_buffer_for (GstBuffer * buffer,
|
||||
const GstVideoInfo * info, gboolean add_videometa)
|
||||
{
|
||||
GstD3D11Memory *dmem;
|
||||
GstD3D11Device *device;
|
||||
GstD3D11AllocationParams *params = NULL;
|
||||
GstD3D11Allocator *alloc = NULL;
|
||||
GstBuffer *staging_buffer = NULL;
|
||||
D3D11_TEXTURE2D_DESC *desc;
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
|
||||
GstMemory *mem = gst_buffer_peek_memory (buffer, i);
|
||||
|
||||
if (!gst_is_d3d11_memory (mem)) {
|
||||
GST_DEBUG ("Not a d3d11 memory");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
dmem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, 0);
|
||||
device = dmem->device;
|
||||
|
||||
params = gst_d3d11_allocation_params_new (device, (GstVideoInfo *) info,
|
||||
0, 0);
|
||||
|
||||
if (!params) {
|
||||
GST_WARNING ("Couldn't create alloc params");
|
||||
goto done;
|
||||
}
|
||||
|
||||
desc = ¶ms->desc[0];
|
||||
/* resolution of semi-planar formats must be multiple of 2 */
|
||||
if (desc[0].Format == DXGI_FORMAT_NV12 || desc[0].Format == DXGI_FORMAT_P010
|
||||
|| desc[0].Format == DXGI_FORMAT_P016) {
|
||||
if (desc[0].Width % 2 || desc[0].Height % 2) {
|
||||
gint width, height;
|
||||
GstVideoAlignment align;
|
||||
|
||||
width = GST_ROUND_UP_2 (desc[0].Width);
|
||||
height = GST_ROUND_UP_2 (desc[0].Height);
|
||||
|
||||
gst_video_alignment_reset (&align);
|
||||
align.padding_right = width - desc[0].Width;
|
||||
align.padding_bottom = height - desc[0].Height;
|
||||
|
||||
gst_d3d11_allocation_params_alignment (params, &align);
|
||||
}
|
||||
}
|
||||
|
||||
alloc = gst_d3d11_allocator_new (device);
|
||||
if (!alloc) {
|
||||
GST_WARNING ("Couldn't create allocator");
|
||||
goto done;
|
||||
}
|
||||
|
||||
staging_buffer = gst_d3d11_allocate_staging_buffer (alloc,
|
||||
info, params->d3d11_format, params->desc, add_videometa);
|
||||
|
||||
if (!staging_buffer)
|
||||
GST_WARNING ("Couldn't allocate staging buffer");
|
||||
|
||||
done:
|
||||
if (params)
|
||||
gst_d3d11_allocation_params_free (params);
|
||||
|
||||
if (alloc)
|
||||
gst_object_unref (alloc);
|
||||
|
||||
return staging_buffer;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_gst_d3d11_result (HRESULT hr, GstD3D11Device * device, GstDebugCategory * cat,
|
||||
const gchar * file, const gchar * function, gint line)
|
||||
|
@ -504,3 +578,93 @@ _gst_d3d11_result (HRESULT hr, GstD3D11Device * device, GstDebugCategory * cat,
|
|||
return SUCCEEDED (hr);
|
||||
#endif
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_d3d11_buffer_copy_into (GstBuffer * dst, GstBuffer * src)
|
||||
{
|
||||
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);
|
||||
|
||||
num_mem = gst_buffer_n_memory (dst);
|
||||
if (num_mem != gst_buffer_n_memory (src)) {
|
||||
GST_WARNING ("different num memory");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_mem; i++) {
|
||||
GstMemory *dst_mem, *src_mem;
|
||||
GstD3D11Memory *dst_dmem, *src_dmem;
|
||||
GstMapInfo dst_info;
|
||||
GstMapInfo src_info;
|
||||
ID3D11Resource *dst_texture, *src_texture;
|
||||
ID3D11DeviceContext *device_context;
|
||||
GstD3D11Device *device;
|
||||
D3D11_BOX src_box = { 0, };
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (dst_dmem->desc.Format != src_dmem->desc.Format) {
|
||||
GST_WARNING ("different dxgi format");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
device_context = gst_d3d11_device_get_device_context_handle (device);
|
||||
|
||||
if (!gst_memory_map (dst_mem, &dst_info, GST_MAP_WRITE | GST_MAP_D3D11)) {
|
||||
GST_ERROR ("Cannot map dst d3d11 memory");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!gst_memory_map (src_mem, &src_info, GST_MAP_READ | GST_MAP_D3D11)) {
|
||||
GST_ERROR ("Cannot map src d3d11 memory");
|
||||
gst_memory_unmap (dst_mem, &dst_info);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
dst_texture = (ID3D11Resource *) dst_info.data;
|
||||
src_texture = (ID3D11Resource *) src_info.data;
|
||||
|
||||
/* src/dst texture size might be different if padding was used.
|
||||
* select smaller size */
|
||||
src_box.left = 0;
|
||||
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);
|
||||
|
||||
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);
|
||||
gst_d3d11_device_unlock (device);
|
||||
|
||||
gst_memory_unmap (src_mem, &src_info);
|
||||
gst_memory_unmap (dst_mem, &dst_info);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -60,6 +60,13 @@ GstBuffer * gst_d3d11_allocate_staging_buffer (GstD3D11Allocator * allocat
|
|||
const D3D11_TEXTURE2D_DESC desc[GST_VIDEO_MAX_PLANES],
|
||||
gboolean add_videometa);
|
||||
|
||||
GstBuffer * gst_d3d11_allocate_staging_buffer_for (GstBuffer * buffer,
|
||||
const GstVideoInfo * info,
|
||||
gboolean add_videometa);
|
||||
|
||||
gboolean gst_d3d11_buffer_copy_into (GstBuffer * dst,
|
||||
GstBuffer * src);
|
||||
|
||||
gboolean _gst_d3d11_result (HRESULT hr,
|
||||
GstD3D11Device * device,
|
||||
GstDebugCategory * cat,
|
||||
|
|
Loading…
Reference in a new issue