mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-28 03:00:35 +00:00
nvdec: Port to GstCudaGraphicsResource
Make it possible to share registered graphics resource among nvidia encoders and decoders.
This commit is contained in:
parent
da075b94a9
commit
d0846f8eab
1 changed files with 56 additions and 90 deletions
|
@ -50,17 +50,10 @@ gst_nvdec_copy_device_to_system (GstNvDec * nvdec,
|
|||
CUVIDPARSERDISPINFO * dispinfo, GstBuffer * output_buffer);
|
||||
|
||||
#ifdef HAVE_NVCODEC_GST_GL
|
||||
typedef struct _GstNvDecCudaGraphicsResourceInfo
|
||||
{
|
||||
GstGLContext *gl_context;
|
||||
GstCudaContext *cuda_context;
|
||||
CUgraphicsResource resource;
|
||||
} GstNvDecCudaGraphicsResourceInfo;
|
||||
|
||||
typedef struct _GstNvDecRegisterResourceData
|
||||
{
|
||||
GstMemory *mem;
|
||||
GstNvDecCudaGraphicsResourceInfo *info;
|
||||
GstCudaGraphicsResource *resource;
|
||||
GstNvDec *nvdec;
|
||||
gboolean ret;
|
||||
} GstNvDecRegisterResourceData;
|
||||
|
@ -70,10 +63,9 @@ register_cuda_resource (GstGLContext * context,
|
|||
GstNvDecRegisterResourceData * data)
|
||||
{
|
||||
GstMemory *mem = data->mem;
|
||||
GstNvDecCudaGraphicsResourceInfo *cgr_info = data->info;
|
||||
GstCudaGraphicsResource *resource = data->resource;
|
||||
GstNvDec *nvdec = data->nvdec;
|
||||
GstMapInfo map_info = GST_MAP_INFO_INIT;
|
||||
CUresult cuda_ret;
|
||||
GstGLBuffer *gl_buf_obj;
|
||||
|
||||
data->ret = FALSE;
|
||||
|
@ -90,9 +82,11 @@ register_cuda_resource (GstGLContext * context,
|
|||
GST_LOG_OBJECT (nvdec,
|
||||
"registure glbuffer %d to CUDA resource", gl_buf_obj->id);
|
||||
|
||||
cuda_ret = CuGraphicsGLRegisterBuffer (&cgr_info->resource, gl_buf_obj->id,
|
||||
CU_GRAPHICS_REGISTER_FLAGS_WRITE_DISCARD);
|
||||
if (gst_cuda_result (cuda_ret)) {
|
||||
/* register resource without read/write only flags, since
|
||||
* downstream CUDA elements (e.g., nvenc) might want to access
|
||||
* this resource later. Instead, use map flags during map/unmap */
|
||||
if (gst_cuda_graphics_resource_register_gl_buffer (resource,
|
||||
gl_buf_obj->id, CU_GRAPHICS_REGISTER_FLAGS_NONE)) {
|
||||
data->ret = TRUE;
|
||||
} else {
|
||||
GST_WARNING_OBJECT (nvdec, "failed to register memory");
|
||||
|
@ -107,40 +101,11 @@ register_cuda_resource (GstGLContext * context,
|
|||
GST_WARNING_OBJECT (nvdec, "failed to unlock CUDA context");
|
||||
}
|
||||
|
||||
static void
|
||||
unregister_cuda_resource (GstGLContext * context,
|
||||
GstNvDecCudaGraphicsResourceInfo * cgr_info)
|
||||
{
|
||||
GstCudaContext *cuda_context = cgr_info->cuda_context;
|
||||
|
||||
if (!gst_cuda_context_push (cuda_context)) {
|
||||
GST_WARNING_OBJECT (context, "failed to push CUDA context");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!gst_cuda_result (CuGraphicsUnregisterResource (cgr_info->resource)))
|
||||
GST_WARNING_OBJECT (cuda_context, "failed to unregister resource");
|
||||
|
||||
if (!gst_cuda_context_pop (NULL)) {
|
||||
GST_WARNING_OBJECT (cuda_context, "failed to pop CUDA context");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
free_cgr_info (GstNvDecCudaGraphicsResourceInfo * cgr_info)
|
||||
{
|
||||
gst_gl_context_thread_add (cgr_info->gl_context,
|
||||
(GstGLContextThreadFunc) unregister_cuda_resource, cgr_info);
|
||||
gst_object_unref (cgr_info->gl_context);
|
||||
gst_object_unref (cgr_info->cuda_context);
|
||||
g_free (cgr_info);
|
||||
}
|
||||
|
||||
static CUgraphicsResource
|
||||
static GstCudaGraphicsResource *
|
||||
ensure_cuda_graphics_resource (GstMemory * mem, GstNvDec * nvdec)
|
||||
{
|
||||
static GQuark quark = 0;
|
||||
GstNvDecCudaGraphicsResourceInfo *cgr_info;
|
||||
GQuark quark;
|
||||
GstCudaGraphicsResource *cgr_info;
|
||||
GstNvDecRegisterResourceData data;
|
||||
|
||||
if (!gst_is_gl_memory_pbo (mem)) {
|
||||
|
@ -149,34 +114,30 @@ ensure_cuda_graphics_resource (GstMemory * mem, GstNvDec * nvdec)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (!quark)
|
||||
quark = g_quark_from_static_string ("GstNvDecCudaGraphicsResourceInfo");
|
||||
quark = gst_cuda_quark_from_id (GST_CUDA_QUARK_GRAPHICS_RESOURCE);
|
||||
|
||||
cgr_info = gst_mini_object_get_qdata (GST_MINI_OBJECT (mem), quark);
|
||||
if (!cgr_info) {
|
||||
cgr_info = g_new0 (GstNvDecCudaGraphicsResourceInfo, 1);
|
||||
cgr_info->gl_context =
|
||||
gst_object_ref (GST_GL_BASE_MEMORY_CAST (mem)->context);
|
||||
cgr_info->cuda_context = gst_object_ref (nvdec->cuda_ctx);
|
||||
cgr_info = gst_cuda_graphics_resource_new (nvdec->cuda_ctx,
|
||||
GST_OBJECT (GST_GL_BASE_MEMORY_CAST (mem)->context),
|
||||
GST_CUDA_GRAPHICS_RESOURCE_GL_BUFFER);
|
||||
data.mem = mem;
|
||||
data.info = cgr_info;
|
||||
data.resource = cgr_info;
|
||||
data.nvdec = nvdec;
|
||||
gst_gl_context_thread_add (cgr_info->gl_context,
|
||||
gst_gl_context_thread_add ((GstGLContext *) cgr_info->graphics_context,
|
||||
(GstGLContextThreadFunc) register_cuda_resource, &data);
|
||||
if (!data.ret) {
|
||||
GST_WARNING_OBJECT (nvdec, "could not register resource");
|
||||
gst_object_unref (cgr_info->gl_context);
|
||||
gst_object_unref (cgr_info->cuda_context);
|
||||
g_free (cgr_info);
|
||||
gst_cuda_graphics_resource_free (cgr_info);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gst_mini_object_set_qdata (GST_MINI_OBJECT (mem), quark, cgr_info,
|
||||
(GDestroyNotify) free_cgr_info);
|
||||
(GDestroyNotify) gst_cuda_graphics_resource_free);
|
||||
}
|
||||
|
||||
return cgr_info->resource;
|
||||
return cgr_info;
|
||||
}
|
||||
#endif /* HAVE_NVCODEC_GST_GL */
|
||||
|
||||
|
@ -807,9 +768,8 @@ typedef struct
|
|||
{
|
||||
GstNvDec *nvdec;
|
||||
CUVIDPARSERDISPINFO *dispinfo;
|
||||
CUgraphicsResource *resources;
|
||||
guint num_resources;
|
||||
gboolean ret;
|
||||
GstBuffer *output_buffer;
|
||||
} GstNvDecCopyToGLData;
|
||||
|
||||
static void
|
||||
|
@ -818,8 +778,8 @@ copy_video_frame_to_gl_textures (GstGLContext * context,
|
|||
{
|
||||
GstNvDec *nvdec = data->nvdec;
|
||||
CUVIDPARSERDISPINFO *dispinfo = data->dispinfo;
|
||||
CUgraphicsResource *resources = data->resources;
|
||||
guint num_resources = data->num_resources;
|
||||
GstCudaGraphicsResource **resources;
|
||||
guint num_resources;
|
||||
CUVIDPROCPARAMS proc_params = { 0, };
|
||||
guintptr dptr;
|
||||
guint pitch, i;
|
||||
|
@ -834,6 +794,25 @@ copy_video_frame_to_gl_textures (GstGLContext * context,
|
|||
|
||||
data->ret = TRUE;
|
||||
|
||||
num_resources = gst_buffer_n_memory (data->output_buffer);
|
||||
resources = g_newa (GstCudaGraphicsResource *, num_resources);
|
||||
|
||||
for (i = 0; i < num_resources; i++) {
|
||||
GstMemory *mem;
|
||||
|
||||
mem = gst_buffer_peek_memory (data->output_buffer, i);
|
||||
resources[i] = ensure_cuda_graphics_resource (mem, nvdec);
|
||||
if (!resources[i]) {
|
||||
GST_WARNING_OBJECT (nvdec, "could not register %dth memory", i);
|
||||
data->ret = FALSE;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Need PBO -> texture */
|
||||
GST_MINI_OBJECT_FLAG_SET (mem, GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD);
|
||||
}
|
||||
|
||||
if (!gst_cuda_context_push (nvdec->cuda_ctx)) {
|
||||
GST_WARNING_OBJECT (nvdec, "failed to lock CUDA context");
|
||||
data->ret = FALSE;
|
||||
|
@ -847,13 +826,6 @@ copy_video_frame_to_gl_textures (GstGLContext * context,
|
|||
goto unlock_cuda_context;
|
||||
}
|
||||
|
||||
if (!gst_cuda_result (CuGraphicsMapResources (num_resources, resources,
|
||||
nvdec->cuda_stream))) {
|
||||
GST_WARNING_OBJECT (nvdec, "failed to map CUDA resources");
|
||||
data->ret = FALSE;
|
||||
goto unmap_video_frame;
|
||||
}
|
||||
|
||||
mcpy2d.srcMemoryType = CU_MEMORYTYPE_DEVICE;
|
||||
mcpy2d.srcPitch = pitch;
|
||||
mcpy2d.dstMemoryType = CU_MEMORYTYPE_DEVICE;
|
||||
|
@ -861,9 +833,18 @@ copy_video_frame_to_gl_textures (GstGLContext * context,
|
|||
for (i = 0; i < num_resources; i++) {
|
||||
CUdeviceptr cuda_ptr;
|
||||
gsize size;
|
||||
CUgraphicsResource cuda_resource =
|
||||
gst_cuda_graphics_resource_map (resources[i], nvdec->cuda_stream,
|
||||
CU_GRAPHICS_MAP_RESOURCE_FLAGS_WRITE_DISCARD);
|
||||
|
||||
if (!cuda_resource) {
|
||||
GST_WARNING_OBJECT (nvdec, "failed to map CUDA resources");
|
||||
data->ret = FALSE;
|
||||
goto unmap_video_frame;
|
||||
}
|
||||
|
||||
if (!gst_cuda_result (CuGraphicsResourceGetMappedPointer (&cuda_ptr, &size,
|
||||
resources[i]))) {
|
||||
cuda_resource))) {
|
||||
GST_WARNING_OBJECT (nvdec, "failed to map CUDA resource");
|
||||
data->ret = FALSE;
|
||||
break;
|
||||
|
@ -883,13 +864,13 @@ copy_video_frame_to_gl_textures (GstGLContext * context,
|
|||
}
|
||||
}
|
||||
|
||||
if (!gst_cuda_result (CuGraphicsUnmapResources (num_resources, resources,
|
||||
nvdec->cuda_stream)))
|
||||
GST_WARNING_OBJECT (nvdec, "failed to unmap CUDA resources");
|
||||
|
||||
gst_cuda_result (CuStreamSynchronize (nvdec->cuda_stream));
|
||||
|
||||
unmap_video_frame:
|
||||
for (i = 0; i < num_resources; i++) {
|
||||
gst_cuda_graphics_resource_unmap (resources[i], nvdec->cuda_stream);
|
||||
}
|
||||
|
||||
if (!gst_cuda_result (CuvidUnmapVideoFrame (nvdec->decoder, dptr)))
|
||||
GST_WARNING_OBJECT (nvdec, "failed to unmap CUDA video frame");
|
||||
|
||||
|
@ -902,26 +883,11 @@ static gboolean
|
|||
gst_nvdec_copy_device_to_gl (GstNvDec * nvdec,
|
||||
CUVIDPARSERDISPINFO * dispinfo, GstBuffer * output_buffer)
|
||||
{
|
||||
guint i;
|
||||
GstMemory *mem;
|
||||
GstNvDecCopyToGLData data = { 0, };
|
||||
|
||||
data.nvdec = nvdec;
|
||||
data.dispinfo = dispinfo;
|
||||
data.num_resources = gst_buffer_n_memory (output_buffer);
|
||||
data.resources = g_newa (CUgraphicsResource, data.num_resources);
|
||||
|
||||
for (i = 0; i < data.num_resources; i++) {
|
||||
mem = gst_buffer_peek_memory (output_buffer, i);
|
||||
data.resources[i] = ensure_cuda_graphics_resource (mem, nvdec);
|
||||
if (!data.resources[i]) {
|
||||
GST_WARNING_OBJECT (nvdec, "could not register %dth memory", i);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Need PBO -> texture */
|
||||
GST_MINI_OBJECT_FLAG_SET (mem, GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD);
|
||||
}
|
||||
data.output_buffer = output_buffer;
|
||||
|
||||
gst_gl_context_thread_add (nvdec->gl_context,
|
||||
(GstGLContextThreadFunc) copy_video_frame_to_gl_textures, &data);
|
||||
|
|
Loading…
Reference in a new issue