summaryrefslogtreecommitdiff
path: root/sys/nvdec
diff options
context:
space:
mode:
authorPer-Erik Brodin <per-erik.brodin@ericsson.com>2017-06-27 18:47:37 -0700
committerSebastian Dröge <sebastian@centricular.com>2017-06-28 10:15:52 +0300
commit3223d605bf054f064d67b10de0f5bf6dd26ce203 (patch)
treeb57ff8a67d496f660d7da221baf38ed6d624a82e /sys/nvdec
parentaf6db6861e85cf937cffce312dc5d775e52b4b8d (diff)
nvdec: Use qdata on memory instead of buffer meta
Using a meta can be problematic since the memory contained in the buffer can be transferred to a new buffer in which case the meta would be lost. https://bugzilla.gnome.org/show_bug.cgi?id=784235
Diffstat (limited to 'sys/nvdec')
-rw-r--r--sys/nvdec/gstnvdec.c250
1 files changed, 79 insertions, 171 deletions
diff --git a/sys/nvdec/gstnvdec.c b/sys/nvdec/gstnvdec.c
index 07ac0bea3..aec8dcbd8 100644
--- a/sys/nvdec/gstnvdec.c
+++ b/sys/nvdec/gstnvdec.c
@@ -112,180 +112,96 @@ gst_nvdec_cuda_context_init (GstNvDecCudaContext * self)
GST_ERROR ("failed to create CUDA context lock");
}
-typedef struct _GstNvDecCudaGraphicsResourcesMeta
+typedef struct _GstNvDecCudaGraphicsResourceInfo
{
- GstMeta meta;
-
+ GstGLContext *gl_context;
GstNvDecCudaContext *cuda_context;
- CUgraphicsResource *resources;
- guint num_resources;
-} GstNvDecCudaGraphicsResourcesMeta;
-
-GType gst_nvdec_cuda_graphics_resources_meta_api_get_type (void);
-#define GST_NVDEC_CUDA_GRAPHICS_RESOURCES_META_API_TYPE (gst_nvdec_cuda_graphics_resources_meta_api_get_type())
-#define gst_buffer_get_nvdec_cuda_graphics_resources_meta(b) \
- ((GstNvDecCudaGraphicsResourcesMeta *)gst_buffer_get_meta((b), GST_NVDEC_CUDA_GRAPHICS_RESOURCES_META_API_TYPE))
-
-GType
-gst_nvdec_cuda_graphics_resources_meta_api_get_type (void)
-{
- static volatile GType type;
- static const gchar *tags[] = { GST_META_TAG_MEMORY_STR, NULL };
-
- if (g_once_init_enter (&type)) {
- GType _type =
- gst_meta_api_type_register ("GstNvDecCudaGraphicsResourcesMetaAPI",
- tags);
- g_once_init_leave (&type, _type);
- }
-
- return type;
-}
-
-const GstMetaInfo *gst_nvdec_cuda_graphics_resources_meta_get_info (void);
-#define GST_NVDEC_CUDA_GRAPHICS_RESOURCES_META_INFO (gst_nvdec_cuda_graphics_resources_meta_get_info())
-
-GstNvDecCudaGraphicsResourcesMeta
- * gst_buffer_add_nvdec_cuda_graphics_resources_meta (GstBuffer * buffer,
- GstNvDecCudaContext * cuda_context);
+ CUgraphicsResource resource;
+} GstNvDecCudaGraphicsResourceInfo;
static void
-add_cgr_meta (GstGLContext * context, GstBuffer * buffer)
+register_cuda_resource (GstGLContext * context, gpointer * args)
{
- GstNvDecCudaGraphicsResourcesMeta *meta;
- GstMemory *mem;
+ GstMemory *mem = GST_MEMORY_CAST (args[0]);
+ GstNvDecCudaGraphicsResourceInfo *cgr_info =
+ (GstNvDecCudaGraphicsResourceInfo *) args[1];
GstMapInfo map_info = GST_MAP_INFO_INIT;
- CUgraphicsResource *resources;
- guint n, i, texture_id;
-
- meta = gst_buffer_get_nvdec_cuda_graphics_resources_meta (buffer);
- n = gst_buffer_n_memory (buffer);
- resources = g_new0 (CUgraphicsResource, n);
+ guint texture_id;
- if (!cuda_OK (cuvidCtxLock (meta->cuda_context->lock, 0)))
+ if (!cuda_OK (cuvidCtxLock (cgr_info->cuda_context->lock, 0)))
GST_WARNING ("failed to lock CUDA context");
- for (i = 0; i < n; i++) {
- mem = gst_buffer_get_memory (buffer, i);
+ if (gst_memory_map (mem, &map_info, GST_MAP_READ | GST_MAP_GL)) {
+ texture_id = *(guint *) map_info.data;
- if (gst_memory_map (mem, &map_info, GST_MAP_READ | GST_MAP_GL)) {
- texture_id = *(guint *) map_info.data;
+ if (!cuda_OK (cuGraphicsGLRegisterImage (&cgr_info->resource, texture_id,
+ GL_TEXTURE_2D, CU_GRAPHICS_REGISTER_FLAGS_WRITE_DISCARD)))
+ GST_WARNING ("failed to register texture with CUDA");
- if (!cuda_OK (cuGraphicsGLRegisterImage (&resources[i], texture_id,
- GL_TEXTURE_2D, CU_GRAPHICS_REGISTER_FLAGS_WRITE_DISCARD)))
- GST_WARNING ("failed to register texture with CUDA");
+ gst_memory_unmap (mem, &map_info);
+ } else
+ GST_WARNING ("failed to map memory");
- gst_memory_unmap (mem, &map_info);
- } else
- GST_WARNING ("failed to map memory");
-
- gst_memory_unref (mem);
- }
-
- if (!cuda_OK (cuvidCtxUnlock (meta->cuda_context->lock, 0)))
+ if (!cuda_OK (cuvidCtxUnlock (cgr_info->cuda_context->lock, 0)))
GST_WARNING ("failed to unlock CUDA context");
-
- meta->resources = resources;
- meta->num_resources = n;
}
static void
-free_cgr_meta (GstGLContext * context, GstNvDecCudaGraphicsResourcesMeta * meta)
+unregister_cuda_resource (GstGLContext * context,
+ GstNvDecCudaGraphicsResourceInfo * cgr_info)
{
- guint i;
-
- if (!cuda_OK (cuvidCtxLock (meta->cuda_context->lock, 0)))
+ if (!cuda_OK (cuvidCtxLock (cgr_info->cuda_context->lock, 0)))
GST_WARNING ("failed to lock CUDA context");
- for (i = 0; i < meta->num_resources; i++) {
- if (!cuda_OK (cuGraphicsUnregisterResource ((const CUgraphicsResource)
- meta->resources[i])))
- GST_WARNING ("failed to unregister resource");
- }
+ if (!cuda_OK (cuGraphicsUnregisterResource ((const CUgraphicsResource)
+ cgr_info->resource)))
+ GST_WARNING ("failed to unregister resource");
- if (!cuda_OK (cuvidCtxUnlock (meta->cuda_context->lock, 0)))
+ if (!cuda_OK (cuvidCtxUnlock (cgr_info->cuda_context->lock, 0)))
GST_WARNING ("failed to unlock CUDA context");
-
- meta->num_resources = 0;
- g_free (meta->resources);
- meta->resources = NULL;
- g_object_unref (meta->cuda_context);
- meta->cuda_context = NULL;
-}
-
-static gboolean
-gst_nvdec_cuda_graphics_resources_meta_init (GstMeta * meta, gpointer params,
- GstBuffer * buffer)
-{
- GstNvDecCudaGraphicsResourcesMeta *cgrmeta =
- (GstNvDecCudaGraphicsResourcesMeta *) meta;
- cgrmeta->cuda_context = NULL;
- cgrmeta->resources = NULL;
- cgrmeta->num_resources = 0;
-
- return TRUE;
-}
-
-static gboolean
-gst_nvdec_cuda_graphics_resources_meta_transform (GstBuffer * transbuf,
- GstMeta * meta, GstBuffer * buffer, GQuark type, gpointer data)
-{
- return FALSE;
}
static void
-gst_nvdec_cuda_graphics_resources_meta_free (GstMeta * meta, GstBuffer * buffer)
+free_cgr_info (GstNvDecCudaGraphicsResourceInfo * cgr_info)
{
- GstMemory *mem = gst_buffer_get_memory (buffer, 0);
- gst_gl_context_thread_add (GST_GL_BASE_MEMORY_CAST (mem)->context,
- (GstGLContextThreadFunc) free_cgr_meta, meta);
- gst_memory_unref (mem);
+ gst_gl_context_thread_add (cgr_info->gl_context,
+ (GstGLContextThreadFunc) unregister_cuda_resource, cgr_info);
+ gst_object_unref (cgr_info->gl_context);
+ g_object_unref (cgr_info->cuda_context);
+ g_slice_free (GstNvDecCudaGraphicsResourceInfo, cgr_info);
}
-const GstMetaInfo *
-gst_nvdec_cuda_graphics_resources_meta_get_info (void)
-{
- static const GstMetaInfo *meta_info = NULL;
-
- if (g_once_init_enter ((GstMetaInfo **) & meta_info)) {
- const GstMetaInfo *mi =
- gst_meta_register (GST_NVDEC_CUDA_GRAPHICS_RESOURCES_META_API_TYPE,
- "GstNvDecCudaGraphicsResourcesMeta",
- sizeof (GstNvDecCudaGraphicsResourcesMeta),
- gst_nvdec_cuda_graphics_resources_meta_init,
- gst_nvdec_cuda_graphics_resources_meta_free,
- gst_nvdec_cuda_graphics_resources_meta_transform);
- g_once_init_leave ((GstMetaInfo **) & meta_info, (GstMetaInfo *) mi);
- }
-
- return meta_info;
-}
-
-GstNvDecCudaGraphicsResourcesMeta *
-gst_buffer_add_nvdec_cuda_graphics_resources_meta (GstBuffer * buffer,
+static CUgraphicsResource
+ensure_cuda_graphics_resource (GstMemory * mem,
GstNvDecCudaContext * cuda_context)
{
- GstNvDecCudaGraphicsResourcesMeta *meta;
- GstMemory *mem;
+ static GQuark quark = 0;
+ GstNvDecCudaGraphicsResourceInfo *cgr_info;
+ gpointer args[2];
- g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
- g_return_val_if_fail (gst_buffer_n_memory (buffer) > 0, NULL);
-
- mem = gst_buffer_get_memory (buffer, 0);
- if (!gst_is_gl_memory (mem)) {
- GST_WARNING ("memory is not GL memory");
- gst_memory_unref (mem);
+ if (!gst_is_gl_base_memory (mem)) {
+ GST_WARNING ("memory is not GL base memory");
return NULL;
}
- meta = (GstNvDecCudaGraphicsResourcesMeta *) gst_buffer_add_meta (buffer,
- GST_NVDEC_CUDA_GRAPHICS_RESOURCES_META_INFO, NULL);
- meta->cuda_context = g_object_ref (cuda_context);
- gst_gl_context_thread_add (GST_GL_BASE_MEMORY_CAST (mem)->context,
- (GstGLContextThreadFunc) add_cgr_meta, buffer);
- gst_memory_unref (mem);
+ if (!quark)
+ quark = g_quark_from_static_string ("GstNvDecCudaGraphicsResourceInfo");
+
+ cgr_info = gst_mini_object_get_qdata (GST_MINI_OBJECT (mem), quark);
+ if (!cgr_info) {
+ cgr_info = g_slice_new (GstNvDecCudaGraphicsResourceInfo);
+ cgr_info->gl_context =
+ gst_object_ref (GST_GL_BASE_MEMORY_CAST (mem)->context);
+ cgr_info->cuda_context = g_object_ref (cuda_context);
+ args[0] = mem;
+ args[1] = cgr_info;
+ gst_gl_context_thread_add (cgr_info->gl_context,
+ (GstGLContextThreadFunc) register_cuda_resource, args);
+ gst_mini_object_set_qdata (GST_MINI_OBJECT (mem), quark, cgr_info,
+ (GDestroyNotify) free_cgr_info);
+ }
- return meta;
+ return cgr_info->resource;
}
static gboolean gst_nvdec_start (GstVideoDecoder * decoder);
@@ -647,8 +563,8 @@ copy_video_frame_to_gl_textures (GstGLContext * context, gpointer * args)
{
GstNvDec *nvdec = GST_NVDEC (args[0]);
CUVIDPARSERDISPINFO *dispinfo = (CUVIDPARSERDISPINFO *) args[1];
- GstNvDecCudaGraphicsResourcesMeta *meta =
- (GstNvDecCudaGraphicsResourcesMeta *) args[2];
+ CUgraphicsResource *resources = (CUgraphicsResource *) args[2];
+ guint num_resources = GPOINTER_TO_UINT (args[3]);
CUVIDPROCPARAMS proc_params = { 0, };
CUdeviceptr dptr;
CUarray array;
@@ -672,8 +588,7 @@ copy_video_frame_to_gl_textures (GstGLContext * context, gpointer * args)
goto unlock_cuda_context;
}
- if (!cuda_OK (cuGraphicsMapResources (meta->num_resources, meta->resources,
- NULL))) {
+ if (!cuda_OK (cuGraphicsMapResources (num_resources, resources, NULL))) {
GST_WARNING_OBJECT (nvdec, "failed to map CUDA resources");
goto unmap_video_frame;
}
@@ -684,9 +599,9 @@ copy_video_frame_to_gl_textures (GstGLContext * context, gpointer * args)
mcpy2d.dstPitch = nvdec->width;
mcpy2d.WidthInBytes = nvdec->width;
- for (i = 0; i < meta->num_resources; i++) {
- if (!cuda_OK (cuGraphicsSubResourceGetMappedArray (&array,
- meta->resources[i], 0, 0))) {
+ for (i = 0; i < num_resources; i++) {
+ if (!cuda_OK (cuGraphicsSubResourceGetMappedArray (&array, resources[i], 0,
+ 0))) {
GST_WARNING_OBJECT (nvdec, "failed to map CUDA array");
break;
}
@@ -699,8 +614,7 @@ copy_video_frame_to_gl_textures (GstGLContext * context, gpointer * args)
GST_WARNING_OBJECT (nvdec, "memcpy to mapped array failed");
}
- if (!cuda_OK (cuGraphicsUnmapResources (meta->num_resources, meta->resources,
- NULL)))
+ if (!cuda_OK (cuGraphicsUnmapResources (num_resources, resources, NULL)))
GST_WARNING_OBJECT (nvdec, "failed to unmap CUDA resources");
unmap_video_frame:
@@ -723,11 +637,11 @@ handle_pending_frames (GstNvDec * nvdec)
GstNvDecQueueItem *item;
CUVIDEOFORMAT *format;
GstVideoCodecState *state;
- guint width, height, fps_n, fps_d, i;
+ guint width, height, fps_n, fps_d, i, num_resources;
CUVIDPICPARAMS *decode_params;
CUVIDPARSERDISPINFO *dispinfo;
- GstNvDecCudaGraphicsResourcesMeta *meta;
- gpointer args[3];
+ CUgraphicsResource *resources;
+ gpointer args[4];
GstMemory *mem;
GstFlowReturn ret = GST_FLOW_OK;
@@ -850,31 +764,25 @@ handle_pending_frames (GstNvDec * nvdec)
break;
}
- meta = gst_buffer_get_nvdec_cuda_graphics_resources_meta
- (pending_frame->output_buffer);
- if (!meta) {
- meta = gst_buffer_add_nvdec_cuda_graphics_resources_meta
- (pending_frame->output_buffer, nvdec->cuda_context);
- if (!meta) {
- GST_WARNING_OBJECT (nvdec,
- "failed to add CUDA graphics resources meta");
- break;
- }
- GST_META_FLAG_SET (meta, GST_META_FLAG_POOLED);
+ num_resources = gst_buffer_n_memory (pending_frame->output_buffer);
+ resources = g_new (CUgraphicsResource, num_resources);
+
+ for (i = 0; i < num_resources; i++) {
+ mem = gst_buffer_get_memory (pending_frame->output_buffer, i);
+ resources[i] =
+ ensure_cuda_graphics_resource (mem, nvdec->cuda_context);
+ GST_MINI_OBJECT_FLAG_SET (mem,
+ GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD);
+ gst_memory_unref (mem);
}
args[0] = nvdec;
args[1] = dispinfo;
- args[2] = meta;
+ args[2] = resources;
+ args[3] = GUINT_TO_POINTER (num_resources);
gst_gl_context_thread_add (nvdec->gl_context,
(GstGLContextThreadFunc) copy_video_frame_to_gl_textures, args);
-
- for (i = gst_buffer_n_memory (pending_frame->output_buffer); i;) {
- mem = gst_buffer_get_memory (pending_frame->output_buffer, --i);
- GST_MINI_OBJECT_FLAG_SET (mem,
- GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD);
- gst_memory_unref (mem);
- }
+ g_free (resources);
if (!dispinfo->progressive_frame) {
GST_BUFFER_FLAG_SET (pending_frame->output_buffer,