From bef18d47cf8c1d416072ea232f5ec93e54b2054c Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Tue, 25 Feb 2025 22:53:30 +0900 Subject: [PATCH] nvjpegenc: Add autogpu mode element Similar to nvautogpu{h264,h265,av1}enc, adding auto gpu select mode element Part-of: --- .../sys/nvcodec/gstnvjpegenc.cpp | 391 ++++++++++++------ .../sys/nvcodec/gstnvjpegenc.h | 8 +- .../gst-plugins-bad/sys/nvcodec/plugin.c | 8 +- 3 files changed, 270 insertions(+), 137 deletions(-) diff --git a/subprojects/gst-plugins-bad/sys/nvcodec/gstnvjpegenc.cpp b/subprojects/gst-plugins-bad/sys/nvcodec/gstnvjpegenc.cpp index 18ceda453d..280b53702c 100644 --- a/subprojects/gst-plugins-bad/sys/nvcodec/gstnvjpegenc.cpp +++ b/subprojects/gst-plugins-bad/sys/nvcodec/gstnvjpegenc.cpp @@ -203,6 +203,7 @@ struct GstNvJpegEncCData guint cuda_device_id; GstCaps *sink_caps; gboolean have_nvrtc; + gboolean autogpu; }; /* *INDENT-OFF* */ @@ -227,10 +228,11 @@ struct GstNvJpegEncPrivate GstBufferPool *pool = nullptr; GstBuffer *fallback_buf = nullptr; - std::mutex lock; + std::recursive_mutex lock; guint quality = DEFAULT_JPEG_QUALITY; bool quality_updated = false; gboolean use_stream_ordered = FALSE; + guint cuda_device_id = 0; }; /* *INDENT-ON* */ @@ -247,6 +249,7 @@ struct GstNvJpegEncClass guint cuda_device_id; gboolean have_nvrtc; + gboolean autogpu; }; static void gst_nv_jpeg_enc_finalize (GObject * object); @@ -301,10 +304,18 @@ gst_nv_jpeg_enc_class_init (GstNvJpegEncClass * klass, gpointer data) "Quality of encoding", 1, 100, DEFAULT_JPEG_QUALITY, (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); - gst_element_class_set_static_metadata (element_class, - "NVIDIA JPEG Encoder", "Codec/Encoder/Video/Hardware", - "Encode JPEG image using nvJPEG library", - "Seungha Yang "); + if (cdata->autogpu) { + gst_element_class_set_static_metadata (element_class, + "NVIDIA JPEG Encoder Auto GPU Select Mode", + "Codec/Encoder/Video/Hardware", + "Encode JPEG image using nvJPEG library", + "Seungha Yang "); + } else { + gst_element_class_set_static_metadata (element_class, + "NVIDIA JPEG Encoder", "Codec/Encoder/Video/Hardware", + "Encode JPEG image using nvJPEG library", + "Seungha Yang "); + } auto sink_templ = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, cdata->sink_caps); @@ -327,6 +338,7 @@ gst_nv_jpeg_enc_class_init (GstNvJpegEncClass * klass, gpointer data) klass->cuda_device_id = cdata->cuda_device_id; klass->have_nvrtc = cdata->have_nvrtc; + klass->autogpu = cdata->autogpu; gst_caps_unref (cdata->sink_caps); g_free (cdata); } @@ -334,7 +346,10 @@ gst_nv_jpeg_enc_class_init (GstNvJpegEncClass * klass, gpointer data) static void gst_nv_jpeg_enc_init (GstNvJpegEnc * self) { + auto klass = GST_NV_JPEG_ENC_GET_CLASS (self); + self->priv = new GstNvJpegEncPrivate (); + self->priv->cuda_device_id = klass->cuda_device_id; } static void @@ -354,7 +369,7 @@ gst_nv_jpeg_enc_set_property (GObject * object, guint prop_id, auto self = GST_NV_JPEG_ENC (object); auto priv = self->priv; - std::lock_guard < std::mutex > lk (priv->lock); + std::lock_guard < std::recursive_mutex > lk (priv->lock); switch (prop_id) { case PROP_QUALITY: { @@ -377,12 +392,11 @@ gst_nv_jpeg_enc_get_property (GObject * object, guint prop_id, GValue * value, { auto self = GST_NV_JPEG_ENC (object); auto priv = self->priv; - auto klass = GST_NV_JPEG_ENC_GET_CLASS (self); - std::lock_guard < std::mutex > lk (priv->lock); + std::lock_guard < std::recursive_mutex > lk (priv->lock); switch (prop_id) { case PROP_CUDA_DEVICE_ID: - g_value_set_uint (value, klass->cuda_device_id); + g_value_set_uint (value, priv->cuda_device_id); break; case PROP_QUALITY: g_value_set_uint (value, priv->quality); @@ -398,10 +412,12 @@ gst_nv_jpeg_enc_set_context (GstElement * element, GstContext * context) { auto self = GST_NV_JPEG_ENC (element); auto priv = self->priv; - auto klass = GST_NV_JPEG_ENC_GET_CLASS (self); - gst_cuda_handle_set_context (element, context, klass->cuda_device_id, - &priv->context); + { + std::lock_guard < std::recursive_mutex > lk (priv->lock); + gst_cuda_handle_set_context (element, context, priv->cuda_device_id, + &priv->context); + } GST_ELEMENT_CLASS (parent_class)->set_context (element, context); } @@ -419,25 +435,12 @@ default_stream_ordered_alloc_enabled (void) return enabled; } +/* Caller should push context */ static gboolean -gst_nv_jpeg_enc_open (GstVideoEncoder * encoder) +gst_nv_jpeg_enc_load_module (GstNvJpegEnc * self) { - auto self = GST_NV_JPEG_ENC (encoder); - auto priv = self->priv; auto klass = GST_NV_JPEG_ENC_GET_CLASS (self); - - GST_DEBUG_OBJECT (self, "Open"); - - if (!gst_cuda_ensure_element_context (GST_ELEMENT_CAST (encoder), - klass->cuda_device_id, &priv->context)) { - GST_ERROR_OBJECT (self, "Couldn't create CUDA context"); - return FALSE; - } - - if (!gst_cuda_context_push (priv->context)) { - GST_ERROR_OBJECT (self, "Couldn't push context"); - return FALSE; - } + auto priv = self->priv; if (!priv->module && klass->have_nvrtc) { const gchar *program = nullptr; @@ -459,13 +462,13 @@ gst_nv_jpeg_enc_open (GstVideoEncoder * encoder) if (!program) { std::lock_guard < std::mutex > lk (g_kernel_table_lock); std::string cubin_kernel_name = - "GstJpegEnc_device_" + std::to_string (klass->cuda_device_id); + "GstJpegEnc_device_" + std::to_string (priv->cuda_device_id); auto cubin = g_cubin_table.find (cubin_kernel_name); if (cubin == g_cubin_table.end ()) { GST_DEBUG_OBJECT (self, "Building CUBIN"); program = gst_cuda_nvrtc_compile_cubin (GstNvJpegEncConvertMain_str, - klass->cuda_device_id); + priv->cuda_device_id); if (program) g_cubin_table[cubin_kernel_name] = program; } else { @@ -509,7 +512,6 @@ gst_nv_jpeg_enc_open (GstVideoEncoder * encoder) if (!priv->module) { GST_ERROR_OBJECT (self, "Couldn't load module"); - gst_cuda_context_pop (nullptr); return FALSE; } @@ -517,20 +519,34 @@ gst_nv_jpeg_enc_open (GstVideoEncoder * encoder) "GstNvJpegEncConvertMain"); if (!gst_cuda_result (ret)) { GST_ERROR_OBJECT (self, "Couldn't get kernel function"); - gst_cuda_context_pop (nullptr); return FALSE; } } - auto ret = g_vtable.NvjpegCreateSimple (&priv->handle); - gst_cuda_context_pop (nullptr); + return TRUE; +} - if (ret != NVJPEG_STATUS_SUCCESS) { - GST_ERROR_OBJECT (self, "Couldn't create encoder handle"); +static gboolean +gst_nv_jpeg_enc_open (GstVideoEncoder * encoder) +{ + auto self = GST_NV_JPEG_ENC (encoder); + auto priv = self->priv; + auto klass = GST_NV_JPEG_ENC_GET_CLASS (self); + + GST_DEBUG_OBJECT (self, "Open"); + + /* Will open GPU later */ + if (klass->autogpu) + return TRUE; + + if (!gst_cuda_ensure_element_context (GST_ELEMENT_CAST (encoder), + priv->cuda_device_id, &priv->context)) { + GST_ERROR_OBJECT (self, "Couldn't create CUDA context"); return FALSE; } - priv->stream = gst_cuda_stream_new (priv->context); + if (!priv->stream) + priv->stream = gst_cuda_stream_new (priv->context); return TRUE; } @@ -546,6 +562,9 @@ gst_nv_jpeg_enc_reset (GstNvJpegEnc * self) if (priv->params) g_vtable.NvjpegEncoderParamsDestroy (priv->params); + if (priv->handle) + g_vtable.NvjpegDestroy (priv->handle); + gboolean need_sync = FALSE; auto stream = gst_cuda_stream_get_handle (priv->stream); for (guint i = 0; i < G_N_ELEMENTS (priv->uv); i++) { @@ -568,6 +587,7 @@ gst_nv_jpeg_enc_reset (GstNvJpegEnc * self) priv->state = nullptr; priv->params = nullptr; + priv->handle = nullptr; priv->launch_kernel = false; gst_clear_buffer (&priv->fallback_buf); @@ -582,8 +602,26 @@ static gboolean gst_nv_jpeg_enc_stop (GstVideoEncoder * encoder) { auto self = GST_NV_JPEG_ENC (encoder); + auto priv = self->priv; + auto klass = GST_NV_JPEG_ENC_GET_CLASS (self); gst_nv_jpeg_enc_reset (self); + if (priv->context && priv->module) { + gst_cuda_context_push (priv->context); + if (priv->module) { + CuModuleUnload (priv->module); + priv->module = nullptr; + } + gst_cuda_context_pop (nullptr); + } + + priv->module = nullptr; + priv->handle = nullptr; + + if (klass->autogpu) { + gst_clear_cuda_stream (&priv->stream); + gst_clear_object (&priv->context); + } return TRUE; } @@ -596,19 +634,6 @@ gst_nv_jpeg_enc_close (GstVideoEncoder * encoder) GST_DEBUG_OBJECT (self, "Close"); - if (priv->context && gst_cuda_context_push (priv->context)) { - if (priv->handle) - g_vtable.NvjpegDestroy (priv->handle); - - if (priv->module) { - CuModuleUnload (priv->module); - priv->module = nullptr; - } - - gst_cuda_context_pop (nullptr); - } - - priv->handle = nullptr; gst_clear_cuda_stream (&priv->stream); gst_clear_object (&priv->context); @@ -622,8 +647,11 @@ gst_nv_jpeg_enc_handle_query (GstNvJpegEnc * self, GstQuery * query) switch (GST_QUERY_TYPE (query)) { case GST_QUERY_CONTEXT: + { + std::lock_guard < std::recursive_mutex > lk (priv->lock); return gst_cuda_handle_context_query (GST_ELEMENT (self), query, priv->context); + } default: break; } @@ -658,6 +686,7 @@ gst_nv_jpeg_enc_propose_allocation (GstVideoEncoder * encoder, GstQuery * query) { auto self = GST_NV_JPEG_ENC (encoder); auto priv = self->priv; + auto klass = GST_NV_JPEG_ENC_GET_CLASS (self); GstVideoInfo info; GstBufferPool *pool = nullptr; GstCaps *caps; @@ -669,6 +698,13 @@ gst_nv_jpeg_enc_propose_allocation (GstVideoEncoder * encoder, GstQuery * query) return FALSE; } + if (klass->autogpu) { + /* Use upstream pool in case of auto select mode. We don't know which + * GPU to use at this moment */ + gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, nullptr); + return TRUE; + } + if (!gst_video_info_from_caps (&info, caps)) { GST_WARNING_OBJECT (self, "Failed to convert caps into info"); return FALSE; @@ -719,21 +755,115 @@ gst_nv_jpeg_enc_propose_allocation (GstVideoEncoder * encoder, GstQuery * query) } static gboolean -gst_nv_jpeg_enc_set_format (GstVideoEncoder * encoder, - GstVideoCodecState * state) +gst_nv_jpeg_enc_prepare_kernel_resource (GstNvJpegEnc * self) { - auto self = GST_NV_JPEG_ENC (encoder); auto priv = self->priv; - priv->info = state->info; + if (!priv->launch_kernel) + return TRUE; - auto caps = gst_caps_new_empty_simple ("image/jpeg"); - auto output_state = gst_video_encoder_set_output_state (encoder, caps, - state); - gst_video_codec_state_unref (output_state); + if (!gst_nv_jpeg_enc_load_module (self)) + return FALSE; + + auto stream = gst_cuda_stream_get_handle (priv->stream); + auto width = (priv->info.width + 1) / 2; + auto height = (priv->info.height + 1) / 2; + size_t pitch; + CUresult ret = CUDA_SUCCESS; + + if (priv->use_stream_ordered) { + gint texture_align = gst_cuda_context_get_texture_alignment (priv->context); + pitch = ((width + texture_align - 1) / texture_align) * texture_align; + + ret = CuMemAllocAsync (&priv->uv[0], pitch * height, stream); + if (!gst_cuda_result (ret)) { + GST_ERROR_OBJECT (self, "Couldn't allocate U plane memory"); + return FALSE; + } + + ret = CuMemAllocAsync (&priv->uv[1], pitch * height, stream); + if (!gst_cuda_result (ret)) { + GST_ERROR_OBJECT (self, "Couldn't allocate V plane memory"); + return FALSE; + } + + if (!gst_cuda_result (CuStreamSynchronize (stream))) { + GST_ERROR_OBJECT (self, "Couldn't synchronize stream"); + return FALSE; + } + } else { + ret = CuMemAllocPitch (&priv->uv[0], &pitch, width, height, 16); + if (!gst_cuda_result (ret)) { + GST_ERROR_OBJECT (self, "Couldn't allocate U plane memory"); + return FALSE; + } + + ret = CuMemAllocPitch (&priv->uv[1], &pitch, width, height, 16); + if (!gst_cuda_result (ret)) { + GST_ERROR_OBJECT (self, "Couldn't allocate V plane memory"); + return FALSE; + } + } + + priv->pitch = pitch; + + return TRUE; +} + +static gboolean +gst_nv_jpeg_enc_init_session (GstNvJpegEnc * self, GstBuffer * in_buf) +{ + auto klass = GST_NV_JPEG_ENC_GET_CLASS (self); + auto priv = self->priv; gst_nv_jpeg_enc_reset (self); + if (klass->autogpu) { + if (!in_buf) { + GST_DEBUG_OBJECT (self, "Open session later for auto gpu mode"); + return TRUE; + } + + std::lock_guard < std::recursive_mutex > lk (priv->lock); + if (priv->module) { + gst_cuda_context_push (priv->context); + CuModuleUnload (priv->module); + priv->module = nullptr; + gst_cuda_context_pop (nullptr); + } + + gst_clear_cuda_stream (&priv->stream); + gst_clear_object (&priv->context); + + auto mem = gst_buffer_peek_memory (in_buf, 0); + if (gst_is_cuda_memory (mem)) { + auto cmem = GST_CUDA_MEMORY_CAST (mem); + priv->context = (GstCudaContext *) gst_object_ref (cmem->context); + guint device_id = 0; + g_object_get (priv->context, "cuda-device-id", &device_id, nullptr); + + GST_DEBUG_OBJECT (self, "Upstream is CUDA with device id %d", device_id); + + if (device_id != priv->cuda_device_id) { + priv->cuda_device_id = device_id; + g_object_notify (G_OBJECT (self), "cuda-device-id"); + } + + priv->stream = gst_cuda_memory_get_stream (cmem); + if (priv->stream) + gst_cuda_stream_ref (priv->stream); + } else { + GST_DEBUG_OBJECT (self, "Upstream is not CUDA"); + if (!gst_cuda_ensure_element_context (GST_ELEMENT_CAST (self), + priv->cuda_device_id, &priv->context)) { + GST_ERROR_OBJECT (self, "Couldn't create CUDA context"); + return FALSE; + } + + priv->stream = gst_cuda_stream_new (priv->context); + } + } + switch (GST_VIDEO_INFO_FORMAT (&priv->info)) { case GST_VIDEO_FORMAT_I420: priv->subsampling = NVJPEG_CSS_420; @@ -759,63 +889,32 @@ gst_nv_jpeg_enc_set_format (GstVideoEncoder * encoder, if (!priv->use_stream_ordered) priv->use_stream_ordered = default_stream_ordered_alloc_enabled (); - std::lock_guard < std::mutex > lk (priv->lock); + + std::lock_guard < std::recursive_mutex > lk (priv->lock); priv->quality_updated = false; if (!gst_cuda_context_push (priv->context)) { GST_ERROR_OBJECT (self, "Couldn't push context"); + gst_nv_jpeg_enc_reset (self); + return FALSE; + } + + if (!gst_nv_jpeg_enc_prepare_kernel_resource (self)) { + gst_cuda_context_pop (nullptr); + gst_nv_jpeg_enc_reset (self); + return FALSE; + } + + auto ret = g_vtable.NvjpegCreateSimple (&priv->handle); + if (ret != NVJPEG_STATUS_SUCCESS) { + GST_ERROR_OBJECT (self, "Couldn't create encoder handle"); + gst_cuda_context_pop (nullptr); + gst_nv_jpeg_enc_reset (self); return FALSE; } auto stream = gst_cuda_stream_get_handle (priv->stream); - - /* Allocate memory */ - if (priv->launch_kernel) { - auto width = (priv->info.width + 1) / 2; - auto height = (priv->info.height + 1) / 2; - size_t pitch; - CUresult ret = CUDA_SUCCESS; - - if (priv->use_stream_ordered) { - gint texture_align = - gst_cuda_context_get_texture_alignment (priv->context); - pitch = ((width + texture_align - 1) / texture_align) * texture_align; - - ret = CuMemAllocAsync (&priv->uv[0], pitch * height, stream); - if (!gst_cuda_result (ret)) { - GST_ERROR_OBJECT (self, "Couldn't allocate U plane memory"); - gst_cuda_context_pop (nullptr); - return FALSE; - } - - ret = CuMemAllocAsync (&priv->uv[1], pitch * height, stream); - if (!gst_cuda_result (ret)) { - GST_ERROR_OBJECT (self, "Couldn't allocate V plane memory"); - gst_nv_jpeg_enc_reset (self); - gst_cuda_context_pop (nullptr); - return FALSE; - } - } else { - ret = CuMemAllocPitch (&priv->uv[0], &pitch, width, height, 16); - if (!gst_cuda_result (ret)) { - GST_ERROR_OBJECT (self, "Couldn't allocate U plane memory"); - gst_cuda_context_pop (nullptr); - return FALSE; - } - - ret = CuMemAllocPitch (&priv->uv[1], &pitch, width, height, 16); - if (!gst_cuda_result (ret)) { - GST_ERROR_OBJECT (self, "Couldn't allocate V plane memory"); - gst_cuda_context_pop (nullptr); - gst_nv_jpeg_enc_reset (self); - return FALSE; - } - } - - priv->pitch = pitch; - } - - auto ret = g_vtable.NvjpegEncoderParamsCreate (priv->handle, &priv->params, + ret = g_vtable.NvjpegEncoderParamsCreate (priv->handle, &priv->params, stream); if (ret != NVJPEG_STATUS_SUCCESS) { GST_ERROR_OBJECT (self, "Couldn't create param handle, ret %d", ret); @@ -843,16 +942,7 @@ gst_nv_jpeg_enc_set_format (GstVideoEncoder * encoder, } ret = g_vtable.NvjpegEncoderStateCreate (priv->handle, &priv->state, stream); - if (priv->launch_kernel && priv->use_stream_ordered) { - if (!gst_cuda_result (CuStreamSynchronize (stream))) { - GST_ERROR_OBJECT (self, "Couldn't synchronize stream"); - gst_cuda_context_pop (nullptr); - gst_nv_jpeg_enc_reset (self); - return FALSE; - } - } gst_cuda_context_pop (nullptr); - if (ret != NVJPEG_STATUS_SUCCESS) { GST_ERROR_OBJECT (self, "Couldn't create state handle, ret %d", ret); gst_nv_jpeg_enc_reset (self); @@ -861,9 +951,11 @@ gst_nv_jpeg_enc_set_format (GstVideoEncoder * encoder, priv->pool = gst_cuda_buffer_pool_new (priv->context); auto config = gst_buffer_pool_get_config (priv->pool); + auto caps = gst_video_info_to_caps (&priv->info); gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META); - gst_buffer_pool_config_set_params (config, - state->caps, priv->info.size, 0, 0); + gst_buffer_pool_config_set_params (config, caps, priv->info.size, 0, 0); + gst_caps_unref (caps); + if (priv->stream) gst_buffer_pool_config_set_cuda_stream (config, priv->stream); @@ -882,6 +974,23 @@ gst_nv_jpeg_enc_set_format (GstVideoEncoder * encoder, return TRUE; } +static gboolean +gst_nv_jpeg_enc_set_format (GstVideoEncoder * encoder, + GstVideoCodecState * state) +{ + auto self = GST_NV_JPEG_ENC (encoder); + auto priv = self->priv; + + priv->info = state->info; + + auto caps = gst_caps_new_empty_simple ("image/jpeg"); + auto output_state = gst_video_encoder_set_output_state (encoder, caps, + state); + gst_video_codec_state_unref (output_state); + + return gst_nv_jpeg_enc_init_session (self, nullptr); +} + static GstBuffer * gst_nv_jpeg_enc_upload_system (GstNvJpegEnc * self, GstBuffer * buffer) { @@ -1006,6 +1115,12 @@ gst_nv_jpeg_enc_handle_frame (GstVideoEncoder * encoder, auto self = GST_NV_JPEG_ENC (encoder); auto priv = self->priv; + if (!priv->handle && !gst_nv_jpeg_enc_init_session (self, + frame->input_buffer)) { + gst_video_encoder_finish_frame (encoder, frame); + return GST_FLOW_ERROR; + } + if (!gst_cuda_context_push (priv->context)) { GST_ERROR_OBJECT (self, "Couldn't push context"); gst_video_encoder_finish_frame (encoder, frame); @@ -1015,7 +1130,7 @@ gst_nv_jpeg_enc_handle_frame (GstVideoEncoder * encoder, auto stream = gst_cuda_stream_get_handle (priv->stream); { - std::lock_guard < std::mutex > lk (priv->lock); + std::lock_guard < std::recursive_mutex > lk (priv->lock); if (priv->quality_updated) { priv->quality_updated = false; auto ret = g_vtable.NvjpegEncoderParamsSetQuality (priv->params, @@ -1083,14 +1198,14 @@ gst_nv_jpeg_enc_handle_frame (GstVideoEncoder * encoder, return gst_video_encoder_finish_frame (encoder, frame); } -void +gboolean gst_nv_jpeg_enc_register (GstPlugin * plugin, GstCudaContext * context, guint rank, gboolean have_nvrtc) { GST_DEBUG_CATEGORY_INIT (gst_nv_jpeg_enc_debug, "nvjpegenc", 0, "nvjpegenc"); if (!gst_nv_jpeg_enc_load_library ()) - return; + return FALSE; GType type; guint index = 0; @@ -1106,8 +1221,12 @@ gst_nv_jpeg_enc_register (GstPlugin * plugin, GstCudaContext * context, (GInstanceInitFunc) gst_nv_jpeg_enc_init, }; - guint cuda_device_id; - g_object_get (context, "cuda-device-id", &cuda_device_id, nullptr); + guint cuda_device_id = 0; + gboolean autogpu = FALSE; + if (!context) + autogpu = TRUE; + else + g_object_get (context, "cuda-device-id", &cuda_device_id, nullptr); std::string format_string; #ifdef NVCODEC_CUDA_PRECOMPILED @@ -1134,16 +1253,24 @@ gst_nv_jpeg_enc_register (GstPlugin * plugin, GstCudaContext * context, cdata->cuda_device_id = cuda_device_id; cdata->sink_caps = sink_caps; cdata->have_nvrtc = have_nvrtc; + cdata->autogpu = autogpu; type_info.class_data = cdata; - auto type_name = g_strdup ("GstNvJpegEnc"); - auto feature_name = g_strdup ("nvjpegenc"); - while (g_type_from_name (type_name)) { - index++; - g_free (type_name); - g_free (feature_name); - type_name = g_strdup_printf ("GstNvJpegDevice%dEnc", index); - feature_name = g_strdup_printf ("nvjpegdevice%denc", index); + gchar *type_name = nullptr; + gchar *feature_name = nullptr; + if (autogpu) { + type_name = g_strdup ("GstNvAutoGpuJpegEnc"); + feature_name = g_strdup ("nvautogpujpegenc"); + } else { + type_name = g_strdup ("GstNvJpegEnc"); + feature_name = g_strdup ("nvjpegenc"); + while (g_type_from_name (type_name)) { + index++; + g_free (type_name); + g_free (feature_name); + type_name = g_strdup_printf ("GstNvJpegDevice%dEnc", index); + feature_name = g_strdup_printf ("nvjpegdevice%denc", index); + } } type = g_type_register_static (GST_TYPE_VIDEO_ENCODER, @@ -1160,4 +1287,6 @@ gst_nv_jpeg_enc_register (GstPlugin * plugin, GstCudaContext * context, g_free (type_name); g_free (feature_name); + + return TRUE; } diff --git a/subprojects/gst-plugins-bad/sys/nvcodec/gstnvjpegenc.h b/subprojects/gst-plugins-bad/sys/nvcodec/gstnvjpegenc.h index 0433d7fc41..157eabca26 100644 --- a/subprojects/gst-plugins-bad/sys/nvcodec/gstnvjpegenc.h +++ b/subprojects/gst-plugins-bad/sys/nvcodec/gstnvjpegenc.h @@ -23,9 +23,9 @@ G_BEGIN_DECLS -void gst_nv_jpeg_enc_register (GstPlugin * plugin, - GstCudaContext * context, - guint rank, - gboolean have_nvrtc); +gboolean gst_nv_jpeg_enc_register (GstPlugin * plugin, + GstCudaContext * context, + guint rank, + gboolean have_nvrtc); G_END_DECLS diff --git a/subprojects/gst-plugins-bad/sys/nvcodec/plugin.c b/subprojects/gst-plugins-bad/sys/nvcodec/plugin.c index b93b12f532..700be874c0 100644 --- a/subprojects/gst-plugins-bad/sys/nvcodec/plugin.c +++ b/subprojects/gst-plugins-bad/sys/nvcodec/plugin.c @@ -129,6 +129,7 @@ plugin_init (GstPlugin * plugin) GList *h264_enc_cdata = NULL; GList *h265_enc_cdata = NULL; GList *av1_enc_cdata = NULL; + gboolean have_nvjpegenc = FALSE; #endif gboolean have_nvrtc = FALSE; @@ -327,8 +328,8 @@ plugin_init (GstPlugin * plugin) av1_enc_cdata = g_list_append (av1_enc_cdata, cdata); } - gst_nv_jpeg_enc_register (plugin, context, GST_RANK_NONE, have_nvrtc); - + if (gst_nv_jpeg_enc_register (plugin, context, GST_RANK_NONE, have_nvrtc)) + have_nvjpegenc = TRUE; #endif gst_object_unref (context); } @@ -348,6 +349,9 @@ plugin_init (GstPlugin * plugin) gst_nv_av1_encoder_register_auto_select (plugin, av1_enc_cdata, GST_RANK_NONE); } + + if (have_nvjpegenc) + gst_nv_jpeg_enc_register (plugin, NULL, GST_RANK_NONE, have_nvrtc); #endif gst_cuda_memory_copy_register (plugin, GST_RANK_NONE);