From 0239152bca152fee69e2b21c1db14f4b1fc527dc Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Sun, 21 Jul 2019 21:23:30 +0900 Subject: [PATCH] nvdec: Create CUDA context with registered device id Only the default device has been used by NVDEC so far. This commit make it possible to use registered device id. To simplify device id selection, GstNvDecCudaContext usage is removed. --- sys/nvcodec/gstnvdec.c | 146 ++++++++++++++++++----------------------- sys/nvcodec/gstnvdec.h | 22 +------ 2 files changed, 66 insertions(+), 102 deletions(-) diff --git a/sys/nvcodec/gstnvdec.c b/sys/nvcodec/gstnvdec.c index 1870942f11..b0e2c9be04 100644 --- a/sys/nvcodec/gstnvdec.c +++ b/sys/nvcodec/gstnvdec.c @@ -52,58 +52,10 @@ cuda_OK (CUresult result) return TRUE; } -G_DEFINE_TYPE (GstNvDecCudaContext, gst_nvdec_cuda_context, G_TYPE_OBJECT); - -static void -gst_nvdec_cuda_context_finalize (GObject * object) -{ - GstNvDecCudaContext *self = (GstNvDecCudaContext *) object; - - if (self->lock) { - GST_DEBUG ("destroying CUDA context lock"); - if (cuda_OK (CuvidCtxLockDestroy (self->lock))) - self->lock = NULL; - else - GST_ERROR ("failed to destroy CUDA context lock"); - } - - if (self->context) { - GST_DEBUG ("destroying CUDA context"); - if (cuda_OK (CuCtxDestroy (self->context))) - self->context = NULL; - else - GST_ERROR ("failed to destroy CUDA context"); - } - - G_OBJECT_CLASS (gst_nvdec_cuda_context_parent_class)->finalize (object); -} - -static void -gst_nvdec_cuda_context_class_init (GstNvDecCudaContextClass * klass) -{ - G_OBJECT_CLASS (klass)->finalize = gst_nvdec_cuda_context_finalize; -} - -static void -gst_nvdec_cuda_context_init (GstNvDecCudaContext * self) -{ - if (!cuda_OK (CuInit (0))) - GST_ERROR ("failed to init CUDA"); - - if (!cuda_OK (CuCtxCreate (&self->context, CU_CTX_SCHED_AUTO, 0))) - GST_ERROR ("failed to create CUDA context"); - - if (!cuda_OK (CuCtxPopCurrent (NULL))) - GST_ERROR ("failed to pop current CUDA context"); - - if (!cuda_OK (CuvidCtxLockCreate (&self->lock, self->context))) - GST_ERROR ("failed to create CUDA context lock"); -} - typedef struct _GstNvDecCudaGraphicsResourceInfo { GstGLContext *gl_context; - GstNvDecCudaContext *cuda_context; + GstNvDec *nvdec; CUgraphicsResource resource; } GstNvDecCudaGraphicsResourceInfo; @@ -115,38 +67,41 @@ register_cuda_resource (GstGLContext * context, gpointer * args) (GstNvDecCudaGraphicsResourceInfo *) args[1]; GstMapInfo map_info = GST_MAP_INFO_INIT; guint texture_id; + GstNvDec *nvdec = cgr_info->nvdec; - if (!cuda_OK (CuvidCtxLock (cgr_info->cuda_context->lock, 0))) - GST_WARNING ("failed to lock CUDA context"); + if (!cuda_OK (CuvidCtxLock (nvdec->ctx_lock, 0))) + GST_WARNING_OBJECT (nvdec, "failed to lock CUDA context"); 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"); + GST_WARNING_OBJECT (nvdec, "failed to register texture with CUDA"); gst_memory_unmap (mem, &map_info); } else - GST_WARNING ("failed to map memory"); + GST_WARNING_OBJECT (nvdec, "failed to map memory"); - if (!cuda_OK (CuvidCtxUnlock (cgr_info->cuda_context->lock, 0))) - GST_WARNING ("failed to unlock CUDA context"); + if (!cuda_OK (CuvidCtxUnlock (nvdec->ctx_lock, 0))) + GST_WARNING_OBJECT (nvdec, "failed to unlock CUDA context"); } static void unregister_cuda_resource (GstGLContext * context, GstNvDecCudaGraphicsResourceInfo * cgr_info) { - if (!cuda_OK (CuvidCtxLock (cgr_info->cuda_context->lock, 0))) - GST_WARNING ("failed to lock CUDA context"); + GstNvDec *nvdec = cgr_info->nvdec; + + if (!cuda_OK (CuvidCtxLock (nvdec->ctx_lock, 0))) + GST_WARNING_OBJECT (nvdec, "failed to lock CUDA context"); if (!cuda_OK (CuGraphicsUnregisterResource ((const CUgraphicsResource) cgr_info->resource))) - GST_WARNING ("failed to unregister resource"); + GST_WARNING_OBJECT (nvdec, "failed to unregister resource"); - if (!cuda_OK (CuvidCtxUnlock (cgr_info->cuda_context->lock, 0))) - GST_WARNING ("failed to unlock CUDA context"); + if (!cuda_OK (CuvidCtxUnlock (nvdec->ctx_lock, 0))) + GST_WARNING_OBJECT (nvdec, "failed to unlock CUDA context"); } static void @@ -155,13 +110,11 @@ 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_object_unref (cgr_info->cuda_context); g_slice_free (GstNvDecCudaGraphicsResourceInfo, cgr_info); } static CUgraphicsResource -ensure_cuda_graphics_resource (GstMemory * mem, - GstNvDecCudaContext * cuda_context) +ensure_cuda_graphics_resource (GstMemory * mem, GstNvDec * nvdec) { static GQuark quark = 0; GstNvDecCudaGraphicsResourceInfo *cgr_info; @@ -180,7 +133,7 @@ ensure_cuda_graphics_resource (GstMemory * mem, 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); + cgr_info->nvdec = nvdec; args[0] = mem; args[1] = cgr_info; gst_gl_context_thread_add (cgr_info->gl_context, @@ -248,7 +201,7 @@ parser_sequence_callback (GstNvDec * nvdec, CUVIDEOFORMAT * format) GST_DEBUG_OBJECT (nvdec, "width: %u, height: %u", width, height); if (!nvdec->decoder || (nvdec->width != width || nvdec->height != height)) { - if (!cuda_OK (CuvidCtxLock (nvdec->cuda_context->lock, 0))) { + if (!cuda_OK (CuvidCtxLock (nvdec->ctx_lock, 0))) { GST_ERROR_OBJECT (nvdec, "failed to lock CUDA context"); goto error; } @@ -278,7 +231,7 @@ parser_sequence_callback (GstNvDec * nvdec, CUVIDEOFORMAT * format) create_info.ulTargetWidth = width; create_info.ulTargetHeight = height; create_info.ulNumOutputSurfaces = 1; - create_info.vidLock = nvdec->cuda_context->lock; + create_info.vidLock = nvdec->ctx_lock; create_info.target_rect.left = 0; create_info.target_rect.top = 0; create_info.target_rect.right = width; @@ -290,7 +243,7 @@ parser_sequence_callback (GstNvDec * nvdec, CUVIDEOFORMAT * format) goto error; } - if (!cuda_OK (CuvidCtxUnlock (nvdec->cuda_context->lock, 0))) { + if (!cuda_OK (CuvidCtxUnlock (nvdec->ctx_lock, 0))) { GST_ERROR_OBJECT (nvdec, "failed to unlock CUDA context"); goto error; } @@ -402,7 +355,7 @@ parser_decode_callback (GstNvDec * nvdec, CUVIDPICPARAMS * params) GST_LOG_OBJECT (nvdec, "picture index: %u", params->CurrPicIdx); - if (!cuda_OK (CuvidCtxLock (nvdec->cuda_context->lock, 0))) { + if (!cuda_OK (CuvidCtxLock (nvdec->ctx_lock, 0))) { GST_ERROR_OBJECT (nvdec, "failed to lock CUDA context"); goto error; } @@ -412,7 +365,7 @@ parser_decode_callback (GstNvDec * nvdec, CUVIDPICPARAMS * params) goto error; } - if (!cuda_OK (CuvidCtxUnlock (nvdec->cuda_context->lock, 0))) { + if (!cuda_OK (CuvidCtxUnlock (nvdec->ctx_lock, 0))) { GST_ERROR_OBJECT (nvdec, "failed to unlock CUDA context"); goto error; } @@ -529,7 +482,7 @@ parser_display_callback (GstNvDec * nvdec, CUVIDPARSERDISPINFO * dispinfo) for (i = 0; i < num_resources; i++) { mem = gst_buffer_get_memory (output_buffer, i); - resources[i] = ensure_cuda_graphics_resource (mem, nvdec->cuda_context); + resources[i] = ensure_cuda_graphics_resource (mem, nvdec); GST_MINI_OBJECT_FLAG_SET (mem, GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD); gst_memory_unref (mem); } @@ -576,13 +529,37 @@ static gboolean gst_nvdec_start (GstVideoDecoder * decoder) { GstNvDec *nvdec = GST_NVDEC (decoder); + GstNvDecClass *klass = GST_NVDEC_GET_CLASS (nvdec); nvdec->state = GST_NVDEC_STATE_INIT; GST_DEBUG_OBJECT (nvdec, "creating CUDA context"); - nvdec->cuda_context = g_object_new (gst_nvdec_cuda_context_get_type (), NULL); - if (!nvdec->cuda_context->context || !nvdec->cuda_context->lock) { - GST_ERROR_OBJECT (nvdec, "failed to create CUDA context or lock"); + if (!cuda_OK (CuInit (0))) { + GST_ERROR_OBJECT (nvdec, "failed to init CUDA"); + return FALSE; + } + + if (!cuda_OK (CuCtxCreate (&nvdec->context, 0, klass->cuda_device_id))) { + GST_ERROR_OBJECT (nvdec, + "failed to create CUDA context with device id %d", + klass->cuda_device_id); + return FALSE; + } + + if (!cuda_OK (CuCtxPopCurrent (NULL))) { + GST_ERROR_OBJECT (nvdec, "failed to pop current CUDA context"); + CuCtxDestroy (nvdec->context); + nvdec->context = NULL; + + return FALSE; + } + + if (!cuda_OK (CuvidCtxLockCreate (&nvdec->ctx_lock, nvdec->context))) { + GST_ERROR_OBJECT (nvdec, "failed to create CUDA context lock"); + + CuCtxDestroy (nvdec->context); + nvdec->context = NULL; + return FALSE; } @@ -596,7 +573,7 @@ maybe_destroy_decoder_and_parser (GstNvDec * nvdec) { gboolean ret = TRUE; - if (!cuda_OK (CuvidCtxLock (nvdec->cuda_context->lock, 0))) { + if (!cuda_OK (CuvidCtxLock (nvdec->ctx_lock, 0))) { GST_ERROR_OBJECT (nvdec, "failed to lock CUDA context"); return FALSE; } @@ -610,7 +587,7 @@ maybe_destroy_decoder_and_parser (GstNvDec * nvdec) GST_ERROR_OBJECT (nvdec, "failed to destroy decoder"); } - if (!cuda_OK (CuvidCtxUnlock (nvdec->cuda_context->lock, 0))) { + if (!cuda_OK (CuvidCtxUnlock (nvdec->ctx_lock, 0))) { GST_ERROR_OBJECT (nvdec, "failed to unlock CUDA context"); return FALSE; } @@ -637,11 +614,6 @@ gst_nvdec_stop (GstVideoDecoder * decoder) if (!maybe_destroy_decoder_and_parser (nvdec)) return FALSE; - if (nvdec->cuda_context) { - g_object_unref (nvdec->cuda_context); - nvdec->cuda_context = NULL; - } - if (nvdec->gl_context) { gst_object_unref (nvdec->gl_context); nvdec->gl_context = NULL; @@ -662,6 +634,16 @@ gst_nvdec_stop (GstVideoDecoder * decoder) nvdec->input_state = NULL; } + if (nvdec->ctx_lock) { + CuvidCtxLockDestroy (nvdec->ctx_lock); + nvdec->ctx_lock = NULL; + } + + if (nvdec->context) { + CuCtxDestroy (nvdec->context); + nvdec->context = NULL; + } + return TRUE; } @@ -723,7 +705,7 @@ copy_video_frame_to_gl_textures (GstGLContext * context, gpointer * args) proc_params.top_field_first = dispinfo->top_field_first; proc_params.unpaired_field = dispinfo->repeat_first_field == -1; - if (!cuda_OK (CuvidCtxLock (nvdec->cuda_context->lock, 0))) { + if (!cuda_OK (CuvidCtxLock (nvdec->ctx_lock, 0))) { GST_WARNING_OBJECT (nvdec, "failed to lock CUDA context"); return; } @@ -768,7 +750,7 @@ unmap_video_frame: GST_WARNING_OBJECT (nvdec, "failed to unmap CUDA video frame"); unlock_cuda_context: - if (!cuda_OK (CuvidCtxUnlock (nvdec->cuda_context->lock, 0))) + if (!cuda_OK (CuvidCtxUnlock (nvdec->ctx_lock, 0))) GST_WARNING_OBJECT (nvdec, "failed to unlock CUDA context"); } diff --git a/sys/nvcodec/gstnvdec.h b/sys/nvcodec/gstnvdec.h index 72d263baf0..f8577ee74b 100644 --- a/sys/nvcodec/gstnvdec.h +++ b/sys/nvcodec/gstnvdec.h @@ -35,25 +35,6 @@ G_BEGIN_DECLS -typedef struct _GstNvDecCudaContext GstNvDecCudaContext; -typedef struct _GstNvDecCudaContextClass GstNvDecCudaContextClass; - -struct _GstNvDecCudaContext -{ - GObject parent; - - CUcontext context; - CUvideoctxlock lock; -}; - -struct _GstNvDecCudaContextClass -{ - GObjectClass parent_class; -}; - -GType gst_nvdec_cuda_context_get_type (void); - - #define GST_TYPE_NVDEC (gst_nvdec_get_type()) #define GST_NVDEC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_NVDEC, GstNvDec)) #define GST_NVDEC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_NVDEC, GstNvDecClass)) @@ -79,9 +60,10 @@ struct _GstNvDec GstGLContext *gl_context; GstGLContext *other_gl_context; - GstNvDecCudaContext *cuda_context; CUvideoparser parser; CUvideodecoder decoder; + CUcontext context; + CUvideoctxlock ctx_lock; guint width; guint height;