mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-11 18:05:37 +00:00
nvdec: Do not access nvdec object from destroy function of qdata
The destroy callback can be called just before the fìnalization of GstMiniObject. So the nvdec object might be destroyed already. Instead, store the GstCudaContext with increased ref to safely unregister the CUDA resource.
This commit is contained in:
parent
736df5604f
commit
b64733972e
1 changed files with 62 additions and 29 deletions
|
@ -51,34 +51,50 @@ gst_nvdec_copy_device_to_system (GstNvDec * nvdec,
|
|||
typedef struct _GstNvDecCudaGraphicsResourceInfo
|
||||
{
|
||||
GstGLContext *gl_context;
|
||||
GstNvDec *nvdec;
|
||||
GstCudaContext *cuda_context;
|
||||
CUgraphicsResource resource;
|
||||
} GstNvDecCudaGraphicsResourceInfo;
|
||||
|
||||
static void
|
||||
register_cuda_resource (GstGLContext * context, gpointer * args)
|
||||
typedef struct _GstNvDecRegisterResourceData
|
||||
{
|
||||
GstMemory *mem = GST_MEMORY_CAST (args[0]);
|
||||
GstNvDecCudaGraphicsResourceInfo *cgr_info =
|
||||
(GstNvDecCudaGraphicsResourceInfo *) args[1];
|
||||
GstMemory *mem;
|
||||
GstNvDecCudaGraphicsResourceInfo *info;
|
||||
GstNvDec *nvdec;
|
||||
gboolean ret;
|
||||
} GstNvDecRegisterResourceData;
|
||||
|
||||
static void
|
||||
register_cuda_resource (GstGLContext * context,
|
||||
GstNvDecRegisterResourceData * data)
|
||||
{
|
||||
GstMemory *mem = data->mem;
|
||||
GstNvDecCudaGraphicsResourceInfo *cgr_info = data->info;
|
||||
GstNvDec *nvdec = data->nvdec;
|
||||
GstMapInfo map_info = GST_MAP_INFO_INIT;
|
||||
guint texture_id;
|
||||
GstNvDec *nvdec = cgr_info->nvdec;
|
||||
|
||||
if (!gst_cuda_context_push (nvdec->cuda_ctx))
|
||||
GST_WARNING_OBJECT (nvdec, "failed to lock CUDA context");
|
||||
data->ret = FALSE;
|
||||
|
||||
if (!gst_cuda_context_push (nvdec->cuda_ctx)) {
|
||||
GST_WARNING_OBJECT (nvdec, "failed to push CUDA context");
|
||||
return;
|
||||
}
|
||||
|
||||
if (gst_memory_map (mem, &map_info, GST_MAP_READ | GST_MAP_GL)) {
|
||||
texture_id = *(guint *) map_info.data;
|
||||
|
||||
if (!gst_cuda_result (CuGraphicsGLRegisterImage (&cgr_info->resource,
|
||||
texture_id, GL_TEXTURE_2D,
|
||||
CU_GRAPHICS_REGISTER_FLAGS_WRITE_DISCARD)))
|
||||
CU_GRAPHICS_REGISTER_FLAGS_WRITE_DISCARD))) {
|
||||
GST_WARNING_OBJECT (nvdec, "failed to register texture with CUDA");
|
||||
} else {
|
||||
data->ret = TRUE;
|
||||
}
|
||||
|
||||
gst_memory_unmap (mem, &map_info);
|
||||
} else
|
||||
} else {
|
||||
GST_WARNING_OBJECT (nvdec, "failed to map memory");
|
||||
}
|
||||
|
||||
if (!gst_cuda_context_pop (NULL))
|
||||
GST_WARNING_OBJECT (nvdec, "failed to unlock CUDA context");
|
||||
|
@ -88,17 +104,19 @@ static void
|
|||
unregister_cuda_resource (GstGLContext * context,
|
||||
GstNvDecCudaGraphicsResourceInfo * cgr_info)
|
||||
{
|
||||
GstNvDec *nvdec = cgr_info->nvdec;
|
||||
GstCudaContext *cuda_context = cgr_info->cuda_context;
|
||||
|
||||
if (!gst_cuda_context_push (nvdec->cuda_ctx))
|
||||
GST_WARNING_OBJECT (nvdec, "failed to lock CUDA context");
|
||||
if (!gst_cuda_context_push (cuda_context)) {
|
||||
GST_WARNING_OBJECT (context, "failed to push CUDA context");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!gst_cuda_result (CuGraphicsUnregisterResource ((const CUgraphicsResource)
|
||||
cgr_info->resource)))
|
||||
GST_WARNING_OBJECT (nvdec, "failed to unregister resource");
|
||||
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 (nvdec, "failed to unlock CUDA context");
|
||||
if (!gst_cuda_context_pop (NULL)) {
|
||||
GST_WARNING_OBJECT (cuda_context, "failed to pop CUDA context");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -107,7 +125,8 @@ 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);
|
||||
g_slice_free (GstNvDecCudaGraphicsResourceInfo, cgr_info);
|
||||
gst_object_unref (cgr_info->cuda_context);
|
||||
g_free (cgr_info);
|
||||
}
|
||||
|
||||
static CUgraphicsResource
|
||||
|
@ -115,10 +134,10 @@ ensure_cuda_graphics_resource (GstMemory * mem, GstNvDec * nvdec)
|
|||
{
|
||||
static GQuark quark = 0;
|
||||
GstNvDecCudaGraphicsResourceInfo *cgr_info;
|
||||
gpointer args[2];
|
||||
GstNvDecRegisterResourceData data;
|
||||
|
||||
if (!gst_is_gl_base_memory (mem)) {
|
||||
GST_WARNING ("memory is not GL base memory");
|
||||
GST_WARNING_OBJECT (nvdec, "memory is not GL base memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -127,14 +146,24 @@ ensure_cuda_graphics_resource (GstMemory * mem, GstNvDec * nvdec)
|
|||
|
||||
cgr_info = gst_mini_object_get_qdata (GST_MINI_OBJECT (mem), quark);
|
||||
if (!cgr_info) {
|
||||
cgr_info = g_slice_new (GstNvDecCudaGraphicsResourceInfo);
|
||||
cgr_info = g_new0 (GstNvDecCudaGraphicsResourceInfo, 1);
|
||||
cgr_info->gl_context =
|
||||
gst_object_ref (GST_GL_BASE_MEMORY_CAST (mem)->context);
|
||||
cgr_info->nvdec = nvdec;
|
||||
args[0] = mem;
|
||||
args[1] = cgr_info;
|
||||
cgr_info->cuda_context = gst_object_ref (nvdec->cuda_ctx);
|
||||
data.mem = mem;
|
||||
data.info = cgr_info;
|
||||
data.nvdec = nvdec;
|
||||
gst_gl_context_thread_add (cgr_info->gl_context,
|
||||
(GstGLContextThreadFunc) register_cuda_resource, args);
|
||||
(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);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gst_mini_object_set_qdata (GST_MINI_OBJECT (mem), quark, cgr_info,
|
||||
(GDestroyNotify) free_cgr_info);
|
||||
}
|
||||
|
@ -847,10 +876,14 @@ gst_nvdec_copy_device_to_gl (GstNvDec * nvdec,
|
|||
data.resources = g_newa (CUgraphicsResource, data.num_resources);
|
||||
|
||||
for (i = 0; i < data.num_resources; i++) {
|
||||
mem = gst_buffer_get_memory (output_buffer, 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;
|
||||
}
|
||||
|
||||
GST_MINI_OBJECT_FLAG_SET (mem, GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD);
|
||||
gst_memory_unref (mem);
|
||||
}
|
||||
|
||||
gst_gl_context_thread_add (nvdec->gl_context,
|
||||
|
|
Loading…
Reference in a new issue