nvjpegenc: Add autogpu mode element
Similar to nvautogpu{h264,h265,av1}enc, adding auto gpu select mode element Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8555>
This commit is contained in:
parent
7d45eca2ce
commit
bef18d47cf
@ -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 <seungha@centricular.com>");
|
||||
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 <seungha@centricular.com>");
|
||||
} else {
|
||||
gst_element_class_set_static_metadata (element_class,
|
||||
"NVIDIA JPEG Encoder", "Codec/Encoder/Video/Hardware",
|
||||
"Encode JPEG image using nvJPEG library",
|
||||
"Seungha Yang <seungha@centricular.com>");
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user