hipmemorycopy: Add support for GL interop
Enable memory copy between HIP and GL Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8923>
This commit is contained in:
parent
baa9bc9d95
commit
be3d7b6f13
@ -25,8 +25,12 @@
|
||||
|
||||
#ifdef HAVE_GST_CUDA
|
||||
#include <gst/cuda/gstcuda.h>
|
||||
#else
|
||||
#define GST_CAPS_FEATURE_MEMORY_CUDA_MEMORY "memory:CUDAMemory"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GST_GL
|
||||
#include <gst/gl/gl.h>
|
||||
#include "gsthiploader-gl.h"
|
||||
#include "gsthip-interop-gl.h"
|
||||
#endif
|
||||
|
||||
#include "gsthip.h"
|
||||
@ -42,53 +46,13 @@ GST_DEBUG_CATEGORY_STATIC (gst_hip_memory_copy_debug);
|
||||
"BGR, BGR10A2_LE, RGB10A2_LE, Y42B, I422_10LE, I422_12LE, YUY2, UYVY, RGBP, " \
|
||||
"BGRP, GBR, GBR_10LE, GBR_12LE, GBR_16LE, GBRA, VUYA }"
|
||||
|
||||
#ifdef HAVE_GST_CUDA
|
||||
#define CAPS_STR \
|
||||
GST_VIDEO_CAPS_MAKE_WITH_FEATURES \
|
||||
(GST_CAPS_FEATURE_MEMORY_HIP_MEMORY, GST_HIP_FORMATS) "; " \
|
||||
GST_VIDEO_CAPS_MAKE_WITH_FEATURES \
|
||||
(GST_CAPS_FEATURE_MEMORY_HIP_MEMORY "," \
|
||||
GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION, \
|
||||
GST_HIP_FORMATS) "; " \
|
||||
GST_VIDEO_CAPS_MAKE_WITH_FEATURES \
|
||||
(GST_CAPS_FEATURE_MEMORY_CUDA_MEMORY, GST_HIP_FORMATS) "; " \
|
||||
GST_VIDEO_CAPS_MAKE_WITH_FEATURES \
|
||||
(GST_CAPS_FEATURE_MEMORY_CUDA_MEMORY "," \
|
||||
GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION, \
|
||||
GST_HIP_FORMATS) "; " \
|
||||
GST_VIDEO_CAPS_MAKE (GST_HIP_FORMATS) "; " \
|
||||
GST_VIDEO_CAPS_MAKE_WITH_FEATURES \
|
||||
(GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY "," \
|
||||
GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION, \
|
||||
GST_HIP_FORMATS)
|
||||
#else
|
||||
#define CAPS_STR \
|
||||
GST_VIDEO_CAPS_MAKE_WITH_FEATURES \
|
||||
(GST_CAPS_FEATURE_MEMORY_HIP_MEMORY, GST_HIP_FORMATS) "; " \
|
||||
GST_VIDEO_CAPS_MAKE_WITH_FEATURES \
|
||||
(GST_CAPS_FEATURE_MEMORY_HIP_MEMORY "," \
|
||||
GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION, \
|
||||
GST_HIP_FORMATS) "; " \
|
||||
GST_VIDEO_CAPS_MAKE (GST_HIP_FORMATS) "; " \
|
||||
GST_VIDEO_CAPS_MAKE_WITH_FEATURES \
|
||||
(GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY "," \
|
||||
GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION, \
|
||||
GST_HIP_FORMATS)
|
||||
#endif
|
||||
|
||||
static GstStaticPadTemplate sink_template =
|
||||
GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS (CAPS_STR));
|
||||
|
||||
static GstStaticPadTemplate src_template =
|
||||
GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS (CAPS_STR));
|
||||
|
||||
enum class TransferType
|
||||
{
|
||||
SYSTEM,
|
||||
CUDA_TO_HIP,
|
||||
GL_TO_HIP,
|
||||
HIP_TO_CUDA,
|
||||
HIP_TO_GL,
|
||||
};
|
||||
|
||||
enum class MemoryType
|
||||
@ -96,6 +60,7 @@ enum class MemoryType
|
||||
SYSTEM,
|
||||
HIP,
|
||||
CUDA,
|
||||
GL,
|
||||
};
|
||||
|
||||
enum class DeviceSearchType
|
||||
@ -138,6 +103,11 @@ struct _GstHipMemoryCopyPrivate
|
||||
gst_clear_object (&device);
|
||||
#ifdef HAVE_GST_CUDA
|
||||
gst_clear_object (&cuda_ctx);
|
||||
#endif
|
||||
#ifdef HAVE_GST_GL
|
||||
gst_clear_object (&other_gl_ctx);
|
||||
gst_clear_object (&gl_ctx);
|
||||
gst_clear_object (&gl_dpy);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -155,6 +125,12 @@ struct _GstHipMemoryCopyPrivate
|
||||
GstCudaContext *cuda_ctx = nullptr;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GST_GL
|
||||
GstGLDisplay *gl_dpy = nullptr;
|
||||
GstGLContext *gl_ctx = nullptr;
|
||||
GstGLContext *other_gl_ctx = nullptr;
|
||||
#endif
|
||||
|
||||
DeviceSearchType search_type = DeviceSearchType::PROPERTY;
|
||||
TransferType transfer_type = TransferType::SYSTEM;
|
||||
MemoryType in_type = MemoryType::SYSTEM;
|
||||
@ -222,9 +198,6 @@ gst_hip_memory_copy_class_init (GstHipMemoryCopyClass * klass)
|
||||
element_class->set_context =
|
||||
GST_DEBUG_FUNCPTR (gst_hip_memory_copy_set_context);
|
||||
|
||||
gst_element_class_add_static_pad_template (element_class, &sink_template);
|
||||
gst_element_class_add_static_pad_template (element_class, &src_template);
|
||||
|
||||
trans_class->passthrough_on_same_caps = TRUE;
|
||||
|
||||
trans_class->start = GST_DEBUG_FUNCPTR (gst_hip_memory_copy_start);
|
||||
@ -314,6 +287,11 @@ gst_hip_memory_copy_set_context (GstElement * element, GstContext * context)
|
||||
|
||||
{
|
||||
std::lock_guard < std::recursive_mutex > lk (priv->lock);
|
||||
#ifdef HAVE_GST_GL
|
||||
gst_gl_handle_set_context (element, context, &priv->gl_dpy,
|
||||
&priv->other_gl_ctx);
|
||||
#endif
|
||||
|
||||
switch (priv->search_type) {
|
||||
case DeviceSearchType::ANY:
|
||||
gst_hip_handle_set_context (element, context, GST_HIP_VENDOR_UNKNOWN,
|
||||
@ -446,6 +424,64 @@ gst_hip_memory_copy_ensure_device (GstHipMemoryCopy * self)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GST_GL
|
||||
static gboolean
|
||||
gst_hip_memory_copy_ensure_gl_context (GstHipMemoryCopy * self)
|
||||
{
|
||||
auto priv = self->priv;
|
||||
|
||||
if (!gst_gl_ensure_element_data (GST_ELEMENT (self),
|
||||
&priv->gl_dpy, &priv->other_gl_ctx)) {
|
||||
GST_DEBUG_OBJECT (self, "No available OpenGL display");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
auto gl_dpy = priv->gl_dpy;
|
||||
if (!gst_gl_query_local_gl_context (GST_ELEMENT (self), GST_PAD_SRC,
|
||||
&priv->gl_ctx) &&
|
||||
!gst_gl_query_local_gl_context (GST_ELEMENT (self), GST_PAD_SINK,
|
||||
&priv->gl_ctx)) {
|
||||
GST_INFO_OBJECT (self, "failed to query local OpenGL context");
|
||||
|
||||
gst_clear_object (&priv->gl_ctx);
|
||||
priv->gl_ctx = gst_gl_display_get_gl_context_for_thread (gl_dpy, nullptr);
|
||||
if (!priv->gl_ctx
|
||||
|| !gst_gl_display_add_context (gl_dpy,
|
||||
GST_GL_CONTEXT (priv->gl_ctx))) {
|
||||
gst_clear_object (&priv->gl_ctx);
|
||||
if (!gst_gl_display_create_context (gl_dpy,
|
||||
priv->other_gl_ctx, &priv->gl_ctx, nullptr)) {
|
||||
GST_WARNING_OBJECT (self, "failed to create OpenGL context");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!gst_gl_display_add_context (gl_dpy, priv->gl_ctx)) {
|
||||
GST_WARNING_OBJECT (self,
|
||||
"failed to add the OpenGL context to the display");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto gl_ctx = priv->gl_ctx;
|
||||
if (!gst_gl_context_check_gl_version (gl_ctx,
|
||||
(GstGLAPI) (GST_GL_API_OPENGL | GST_GL_API_OPENGL3), 3, 0)) {
|
||||
GST_WARNING_OBJECT (self, "OpenGL context could not support PBO");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Found GL context");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#else
|
||||
static gboolean
|
||||
gst_hip_memory_copy_ensure_gl_context (GstHipMemoryCopy * self)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static gboolean
|
||||
gst_hip_memory_copy_set_caps (GstBaseTransform * trans, GstCaps * incaps,
|
||||
GstCaps * outcaps)
|
||||
@ -478,6 +514,12 @@ gst_hip_memory_copy_set_caps (GstBaseTransform * trans, GstCaps * incaps,
|
||||
priv->in_type = MemoryType::CUDA;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_GST_GL
|
||||
else if (gst_caps_features_contains (features,
|
||||
GST_CAPS_FEATURE_MEMORY_GL_MEMORY)) {
|
||||
priv->in_type = MemoryType::GL;
|
||||
}
|
||||
#endif
|
||||
|
||||
features = gst_caps_get_features (outcaps, 0);
|
||||
if (features && gst_caps_features_contains (features,
|
||||
@ -490,8 +532,27 @@ gst_hip_memory_copy_set_caps (GstBaseTransform * trans, GstCaps * incaps,
|
||||
priv->out_type = MemoryType::CUDA;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_GST_GL
|
||||
else if (gst_caps_features_contains (features,
|
||||
GST_CAPS_FEATURE_MEMORY_GL_MEMORY)) {
|
||||
priv->out_type = MemoryType::GL;
|
||||
}
|
||||
#endif
|
||||
|
||||
priv->transfer_type = TransferType::SYSTEM;
|
||||
#ifdef HAVE_GST_GL
|
||||
if (priv->in_type == MemoryType::GL && priv->out_type == MemoryType::HIP &&
|
||||
gst_hip_memory_copy_ensure_gl_context (self)) {
|
||||
priv->transfer_type = TransferType::GL_TO_HIP;
|
||||
return TRUE;
|
||||
} else if (priv->out_type == MemoryType::GL &&
|
||||
priv->in_type == MemoryType::HIP &&
|
||||
gst_hip_memory_copy_ensure_gl_context (self)) {
|
||||
priv->transfer_type = TransferType::HIP_TO_GL;
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
return gst_hip_memory_copy_ensure_device (self);
|
||||
}
|
||||
|
||||
@ -508,6 +569,13 @@ gst_hip_memory_copy_query (GstBaseTransform * trans,
|
||||
if (gst_hip_handle_context_query (elem, query, priv->device))
|
||||
return TRUE;
|
||||
|
||||
#ifdef HAVE_GST_GL
|
||||
if (gst_gl_handle_context_query (elem, query,
|
||||
priv->gl_dpy, priv->gl_ctx, priv->other_gl_ctx)) {
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GST_CUDA
|
||||
if (gst_cuda_handle_context_query (elem, query, priv->cuda_ctx))
|
||||
return TRUE;
|
||||
@ -629,6 +697,18 @@ _set_caps_features (const GstCaps * caps, const gchar * feature_name)
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static void
|
||||
_remove_field (GstCaps * caps, const gchar * field)
|
||||
{
|
||||
guint n = gst_caps_get_size (caps);
|
||||
guint i = 0;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
GstStructure *s = gst_caps_get_structure (caps, i);
|
||||
gst_structure_remove_field (s, field);
|
||||
}
|
||||
}
|
||||
|
||||
static GstCaps *
|
||||
gst_hip_memory_copy_transform_caps (GstBaseTransform * trans,
|
||||
GstPadDirection direction, GstCaps * caps, GstCaps * filter)
|
||||
@ -647,29 +727,41 @@ gst_hip_memory_copy_transform_caps (GstBaseTransform * trans,
|
||||
_set_caps_features (caps, GST_CAPS_FEATURE_MEMORY_HIP_MEMORY);
|
||||
tmp = gst_caps_merge (caps_hip, gst_caps_ref (caps));
|
||||
} else {
|
||||
auto caps_sys =
|
||||
_set_caps_features (caps, GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY);
|
||||
auto ret = gst_caps_ref (caps);
|
||||
|
||||
#ifdef HAVE_GST_CUDA
|
||||
auto caps_cuda =
|
||||
_set_caps_features (caps, GST_CAPS_FEATURE_MEMORY_CUDA_MEMORY);
|
||||
tmp = gst_caps_merge (caps_cuda, caps_sys);
|
||||
tmp = gst_caps_merge (gst_caps_ref (caps), tmp);
|
||||
#else
|
||||
tmp = gst_caps_merge (gst_caps_ref (caps), caps_sys);
|
||||
ret = gst_caps_merge (ret, caps_cuda);
|
||||
#endif
|
||||
#ifdef HAVE_GST_GL
|
||||
auto caps_gl =
|
||||
_set_caps_features (caps, GST_CAPS_FEATURE_MEMORY_GL_MEMORY);
|
||||
ret = gst_caps_merge (ret, caps_gl);
|
||||
#endif
|
||||
|
||||
auto caps_sys =
|
||||
_set_caps_features (caps, GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY);
|
||||
tmp = gst_caps_merge (ret, caps_sys);
|
||||
}
|
||||
} else {
|
||||
if (priv->is_uploader) {
|
||||
auto caps_sys =
|
||||
_set_caps_features (caps, GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY);
|
||||
auto ret = gst_caps_ref (caps);
|
||||
|
||||
#ifdef HAVE_GST_CUDA
|
||||
auto caps_cuda =
|
||||
_set_caps_features (caps, GST_CAPS_FEATURE_MEMORY_CUDA_MEMORY);
|
||||
tmp = gst_caps_merge (caps_cuda, caps_sys);
|
||||
tmp = gst_caps_merge (tmp, gst_caps_ref (caps));
|
||||
#else
|
||||
tmp = gst_caps_merge (caps_sys, gst_caps_ref (caps));
|
||||
ret = gst_caps_merge (ret, caps_cuda);
|
||||
#endif
|
||||
#ifdef HAVE_GST_GL
|
||||
auto caps_gl =
|
||||
_set_caps_features (caps, GST_CAPS_FEATURE_MEMORY_GL_MEMORY);
|
||||
ret = gst_caps_merge (ret, caps_gl);
|
||||
#endif
|
||||
|
||||
auto caps_sys =
|
||||
_set_caps_features (caps, GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY);
|
||||
tmp = gst_caps_merge (ret, caps_sys);
|
||||
} else {
|
||||
auto caps_hip =
|
||||
_set_caps_features (caps, GST_CAPS_FEATURE_MEMORY_HIP_MEMORY);
|
||||
@ -677,6 +769,9 @@ gst_hip_memory_copy_transform_caps (GstBaseTransform * trans,
|
||||
}
|
||||
}
|
||||
|
||||
tmp = gst_caps_make_writable (tmp);
|
||||
_remove_field (tmp, "texture-target");
|
||||
|
||||
if (filter) {
|
||||
result = gst_caps_intersect_full (filter, tmp, GST_CAPS_INTERSECT_FIRST);
|
||||
gst_caps_unref (tmp);
|
||||
@ -737,6 +832,15 @@ gst_hip_memory_copy_propose_allocation (GstBaseTransform * trans,
|
||||
is_system = false;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_GST_GL
|
||||
else if (gst_caps_features_contains (features,
|
||||
GST_CAPS_FEATURE_MEMORY_GL_MEMORY) &&
|
||||
gst_hip_memory_copy_ensure_gl_context (self)) {
|
||||
GST_DEBUG_OBJECT (self, "upstream support gl memory");
|
||||
pool = gst_gl_buffer_pool_new (priv->gl_ctx);
|
||||
is_system = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!pool)
|
||||
pool = gst_video_buffer_pool_new ();
|
||||
@ -769,8 +873,6 @@ gst_hip_memory_copy_propose_allocation (GstBaseTransform * trans,
|
||||
}
|
||||
|
||||
gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, nullptr);
|
||||
gst_query_add_allocation_meta (query,
|
||||
GST_VIDEO_OVERLAY_COMPOSITION_META_API_TYPE, nullptr);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -841,6 +943,18 @@ gst_hip_memory_copy_decide_allocation (GstBaseTransform * trans,
|
||||
pool = gst_cuda_buffer_pool_new (priv->cuda_ctx);
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_GST_GL
|
||||
else if (gst_caps_features_contains (features,
|
||||
GST_CAPS_FEATURE_MEMORY_GL_MEMORY) &&
|
||||
gst_hip_memory_copy_ensure_gl_context (self)) {
|
||||
GST_DEBUG_OBJECT (self, "downstream support gl memory");
|
||||
if (pool && !GST_IS_GL_BUFFER_POOL (pool))
|
||||
gst_clear_object (&pool);
|
||||
|
||||
if (!pool)
|
||||
pool = gst_gl_buffer_pool_new (priv->gl_ctx);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!pool)
|
||||
pool = gst_video_buffer_pool_new ();
|
||||
@ -965,15 +1079,220 @@ gst_hip_memory_copy_device_copy (GstHipMemoryCopy * self, GstBuffer * inbuf,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GST_GL
|
||||
struct GLCopyData
|
||||
{
|
||||
GstHipMemoryCopy *self;
|
||||
GstHipDevice *device;
|
||||
GstBuffer *gl_buf;
|
||||
GstBuffer *hip_buf;
|
||||
gboolean gl_to_hip;
|
||||
gboolean ret = FALSE;
|
||||
};
|
||||
|
||||
static void
|
||||
gl_copy_thread_func (GstGLContext * gl_ctx, GLCopyData * data)
|
||||
{
|
||||
auto self = data->self;
|
||||
auto priv = self->priv;
|
||||
auto vendor = gst_hip_device_get_vendor (data->device);
|
||||
guint device_count = 0;
|
||||
int device_list[1] = { 0, };
|
||||
GstHipGraphicsResource *resources[4] = { };
|
||||
GstVideoFrame hip_frame;
|
||||
/* TODO: use stream */
|
||||
hipStream_t stream = nullptr;
|
||||
|
||||
data->ret = FALSE;
|
||||
|
||||
auto hip_ret = HipGLGetDevices (vendor,
|
||||
&device_count, device_list, 1, hipGLDeviceListAll);
|
||||
if (!gst_hip_result (hip_ret, vendor) || device_count == 0) {
|
||||
GST_WARNING_OBJECT (self, "GL context is not compatible with HIP device");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!gst_hip_device_set_current (data->device)) {
|
||||
GST_ERROR_OBJECT (self, "Couldn't set device");
|
||||
return;
|
||||
}
|
||||
|
||||
auto n_mem = gst_buffer_n_memory (data->gl_buf);
|
||||
if (n_mem != GST_VIDEO_INFO_N_PLANES (&priv->info)) {
|
||||
GST_ERROR_OBJECT (self, "Plane count mismatch");
|
||||
return;
|
||||
}
|
||||
|
||||
for (guint i = 0; i < n_mem; i++) {
|
||||
auto mem = gst_buffer_peek_memory (data->gl_buf, i);
|
||||
auto pbo_mem = (GstGLMemoryPBO *) mem;
|
||||
|
||||
hip_ret = gst_hip_get_graphics_resource_from_gl_memory (data->device,
|
||||
mem, &resources[i]);
|
||||
if (!gst_hip_result (hip_ret, vendor)) {
|
||||
GST_WARNING_OBJECT (self, "Couldn't get graphics resource");
|
||||
for (guint j = 0; j < i; j++)
|
||||
gst_clear_hip_graphics_resource (&resources[j]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (data->gl_to_hip) {
|
||||
/* get the texture into the PBO */
|
||||
gst_gl_memory_pbo_upload_transfer (pbo_mem);
|
||||
gst_gl_memory_pbo_download_transfer (pbo_mem);
|
||||
} else {
|
||||
/* Need PBO -> texture */
|
||||
GST_MINI_OBJECT_FLAG_SET (mem, GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD);
|
||||
|
||||
/* PBO -> sysmem */
|
||||
GST_MINI_OBJECT_FLAG_SET (pbo_mem->pbo,
|
||||
GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD);
|
||||
}
|
||||
}
|
||||
|
||||
GstMapFlags map_flags;
|
||||
if (data->gl_to_hip)
|
||||
map_flags = GST_MAP_WRITE_HIP;
|
||||
else
|
||||
map_flags = GST_MAP_READ_HIP;
|
||||
|
||||
if (!gst_video_frame_map (&hip_frame, &priv->info, data->hip_buf, map_flags)) {
|
||||
GST_ERROR_OBJECT (self, "Couldn't map HIP frame");
|
||||
for (guint i = 0; i < n_mem; i++)
|
||||
gst_clear_hip_graphics_resource (&resources[i]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
gboolean copy_ret = TRUE;
|
||||
for (guint i = 0; i < GST_VIDEO_FRAME_N_PLANES (&hip_frame); i++) {
|
||||
hip_ret = gst_hip_graphics_resource_map (resources[i], stream);
|
||||
copy_ret = gst_hip_result (hip_ret, vendor);
|
||||
if (!copy_ret) {
|
||||
GST_ERROR_OBJECT (self, "Couldn't map resource %d", i);
|
||||
break;
|
||||
}
|
||||
|
||||
void *gl_dev_ptr;
|
||||
size_t gl_size;
|
||||
hip_ret = gst_hip_graphics_resource_get_mapped_pointer (resources[i],
|
||||
&gl_dev_ptr, &gl_size);
|
||||
copy_ret = gst_hip_result (hip_ret, vendor);
|
||||
if (!copy_ret) {
|
||||
GST_ERROR_OBJECT (self, "Couldn't get mapped pointer %d", i);
|
||||
gst_hip_graphics_resource_unmap (resources[i], stream);
|
||||
break;
|
||||
}
|
||||
|
||||
hip_Memcpy2D param = { };
|
||||
|
||||
param.srcMemoryType = hipMemoryTypeDevice;
|
||||
param.dstMemoryType = hipMemoryTypeDevice;
|
||||
param.Height = GST_VIDEO_FRAME_COMP_HEIGHT (&hip_frame, i);
|
||||
|
||||
if (data->gl_to_hip) {
|
||||
param.srcDevice = gl_dev_ptr;
|
||||
param.srcPitch = GST_VIDEO_INFO_PLANE_STRIDE (&priv->info, i);
|
||||
|
||||
param.dstDevice = GST_VIDEO_FRAME_PLANE_DATA (&hip_frame, i);
|
||||
param.dstPitch = GST_VIDEO_FRAME_PLANE_STRIDE (&hip_frame, i);
|
||||
|
||||
} else {
|
||||
param.dstDevice = gl_dev_ptr;
|
||||
param.dstPitch = GST_VIDEO_INFO_PLANE_STRIDE (&priv->info, i);
|
||||
|
||||
param.srcDevice = GST_VIDEO_FRAME_PLANE_DATA (&hip_frame, i);
|
||||
param.srcPitch = GST_VIDEO_FRAME_PLANE_STRIDE (&hip_frame, i);
|
||||
}
|
||||
|
||||
param.WidthInBytes = MIN (param.srcPitch, param.dstPitch);
|
||||
|
||||
hip_ret = HipMemcpyParam2DAsync (vendor, ¶m, stream);
|
||||
copy_ret = gst_hip_result (hip_ret, vendor);
|
||||
gst_hip_graphics_resource_unmap (resources[i], stream);
|
||||
|
||||
if (!copy_ret) {
|
||||
GST_ERROR_OBJECT (self, "Couldn't copy plane %d", i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (copy_ret)
|
||||
HipStreamSynchronize (vendor, stream);
|
||||
|
||||
for (guint i = 0; i < n_mem; i++)
|
||||
gst_clear_hip_graphics_resource (&resources[i]);
|
||||
|
||||
gst_video_frame_unmap (&hip_frame);
|
||||
|
||||
data->ret = copy_ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_hip_memory_copy_gl_copy (GstHipMemoryCopy * self, GstBuffer * inbuf,
|
||||
GstBuffer * outbuf)
|
||||
{
|
||||
auto priv = self->priv;
|
||||
GstGLContext *gl_ctx = nullptr;
|
||||
GLCopyData data;
|
||||
|
||||
data.self = self;
|
||||
data.ret = FALSE;
|
||||
|
||||
if (priv->transfer_type == TransferType::GL_TO_HIP) {
|
||||
data.gl_buf = inbuf;
|
||||
data.hip_buf = outbuf;
|
||||
data.gl_to_hip = TRUE;
|
||||
} else {
|
||||
data.gl_buf = outbuf;
|
||||
data.hip_buf = inbuf;
|
||||
data.gl_to_hip = FALSE;
|
||||
}
|
||||
|
||||
auto mem = gst_buffer_peek_memory (data.gl_buf, 0);
|
||||
if (!gst_is_gl_memory_pbo (mem)) {
|
||||
GST_WARNING_OBJECT (self, "Not a GL PBO buffer");
|
||||
return FALSE;
|
||||
}
|
||||
gl_ctx = GST_GL_MEMORY_CAST (mem)->mem.context;
|
||||
|
||||
mem = gst_buffer_peek_memory (data.hip_buf, 0);
|
||||
if (!gst_is_hip_memory (mem)) {
|
||||
GST_WARNING_OBJECT (self, "Not a HIP buffer");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
data.device = GST_HIP_MEMORY_CAST (mem)->device;
|
||||
|
||||
gst_gl_context_thread_add (gl_ctx,
|
||||
(GstGLContextThreadFunc) gl_copy_thread_func, &data);
|
||||
|
||||
return data.ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static GstFlowReturn
|
||||
gst_hip_memory_copy_transform (GstBaseTransform * trans, GstBuffer * inbuf,
|
||||
GstBuffer * outbuf)
|
||||
{
|
||||
auto self = GST_HIP_MEMORY_COPY (trans);
|
||||
|
||||
#ifdef HAVE_GST_CUDA
|
||||
auto priv = self->priv;
|
||||
if (priv->transfer_type != TransferType::SYSTEM) {
|
||||
|
||||
if (priv->transfer_type == TransferType::GL_TO_HIP ||
|
||||
priv->transfer_type == TransferType::HIP_TO_GL) {
|
||||
if (gst_hip_memory_copy_gl_copy (self, inbuf, outbuf)) {
|
||||
GST_TRACE_OBJECT (self, "Done GL interop copy");
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
GST_WARNING_OBJECT (self,
|
||||
"GL interop copy failed, fallback to system copy");
|
||||
priv->transfer_type = TransferType::SYSTEM;
|
||||
}
|
||||
#ifdef HAVE_GST_CUDA
|
||||
if (priv->transfer_type == TransferType::HIP_TO_CUDA ||
|
||||
priv->transfer_type == TransferType::CUDA_TO_HIP) {
|
||||
auto ret = gst_hip_memory_copy_device_copy (self, inbuf, outbuf);
|
||||
if (ret) {
|
||||
GST_TRACE_OBJECT (self, "Done using device copy");
|
||||
@ -1003,6 +1322,36 @@ gst_hip_upload_class_init (GstHipUploadClass * klass)
|
||||
"HIP Uploader", "Filter/Video",
|
||||
"Uploads system memory into HIP device memory",
|
||||
"Seungha Yang <seungha@centricular.com>");
|
||||
|
||||
auto sys_caps = gst_caps_from_string (GST_VIDEO_CAPS_MAKE (GST_HIP_FORMATS));
|
||||
auto hip_caps = gst_caps_from_string (GST_VIDEO_CAPS_MAKE_WITH_FEATURES
|
||||
(GST_CAPS_FEATURE_MEMORY_HIP_MEMORY, GST_HIP_FORMATS));
|
||||
|
||||
auto src_caps = gst_caps_merge (gst_caps_ref (hip_caps),
|
||||
gst_caps_ref (sys_caps));
|
||||
|
||||
auto sink_caps = sys_caps;
|
||||
#ifdef HAVE_GST_GL
|
||||
auto gl_caps = gst_caps_from_string (GST_VIDEO_CAPS_MAKE_WITH_FEATURES
|
||||
(GST_CAPS_FEATURE_MEMORY_GL_MEMORY, GST_HIP_FORMATS));
|
||||
sink_caps = gst_caps_merge (sink_caps, gl_caps);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GST_CUDA
|
||||
auto cuda_caps = gst_caps_from_string (GST_VIDEO_CAPS_MAKE_WITH_FEATURES
|
||||
(GST_CAPS_FEATURE_MEMORY_CUDA_MEMORY, GST_HIP_FORMATS));
|
||||
sink_caps = gst_caps_merge (sink_caps, cuda_caps);
|
||||
#endif
|
||||
|
||||
sink_caps = gst_caps_merge (sink_caps, hip_caps);
|
||||
|
||||
GST_MINI_OBJECT_FLAG_SET (sink_caps, GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED);
|
||||
GST_MINI_OBJECT_FLAG_SET (src_caps, GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED);
|
||||
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, sink_caps));
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, src_caps));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1028,6 +1377,36 @@ gst_hip_download_class_init (GstHipDownloadClass * klass)
|
||||
"HIP Downloader", "Filter/Video",
|
||||
"Downloads HIP device memory into system memory",
|
||||
"Seungha Yang <seungha@centricular.com>");
|
||||
|
||||
auto sys_caps = gst_caps_from_string (GST_VIDEO_CAPS_MAKE (GST_HIP_FORMATS));
|
||||
auto hip_caps = gst_caps_from_string (GST_VIDEO_CAPS_MAKE_WITH_FEATURES
|
||||
(GST_CAPS_FEATURE_MEMORY_HIP_MEMORY, GST_HIP_FORMATS));
|
||||
|
||||
auto sink_caps = gst_caps_merge (gst_caps_ref (hip_caps),
|
||||
gst_caps_ref (sys_caps));
|
||||
|
||||
auto src_caps = sys_caps;
|
||||
#ifdef HAVE_GST_GL
|
||||
auto gl_caps = gst_caps_from_string (GST_VIDEO_CAPS_MAKE_WITH_FEATURES
|
||||
(GST_CAPS_FEATURE_MEMORY_GL_MEMORY, GST_HIP_FORMATS));
|
||||
src_caps = gst_caps_merge (src_caps, gl_caps);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GST_CUDA
|
||||
auto cuda_caps = gst_caps_from_string (GST_VIDEO_CAPS_MAKE_WITH_FEATURES
|
||||
(GST_CAPS_FEATURE_MEMORY_CUDA_MEMORY, GST_HIP_FORMATS));
|
||||
src_caps = gst_caps_merge (src_caps, cuda_caps);
|
||||
#endif
|
||||
|
||||
src_caps = gst_caps_merge (src_caps, hip_caps);
|
||||
|
||||
GST_MINI_OBJECT_FLAG_SET (sink_caps, GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED);
|
||||
GST_MINI_OBJECT_FLAG_SET (src_caps, GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED);
|
||||
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, sink_caps));
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, src_caps));
|
||||
}
|
||||
|
||||
static void
|
||||
|
Loading…
x
Reference in New Issue
Block a user