mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 19:51:11 +00:00
nvencoder: Reuse input resource
Call input resource map functions (i.e., nvEncRegisterResource, nvEncUnregisterResource, nvEncMapInputResource, and nvEncUnmapInputResource) only once and reuse the mapped resources, instead of per input frame map/unmap Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3884>
This commit is contained in:
parent
ff3120a38c
commit
eb0fca4180
7 changed files with 1700 additions and 791 deletions
1200
subprojects/gst-plugins-bad/sys/nvcodec/gstnvencobject.cpp
Normal file
1200
subprojects/gst-plugins-bad/sys/nvcodec/gstnvencobject.cpp
Normal file
File diff suppressed because it is too large
Load diff
247
subprojects/gst-plugins-bad/sys/nvcodec/gstnvencobject.h
Normal file
247
subprojects/gst-plugins-bad/sys/nvcodec/gstnvencobject.h
Normal file
|
@ -0,0 +1,247 @@
|
||||||
|
/* GStreamer
|
||||||
|
* Copyright (C) 2023 Seungha Yang <seungha@centricular.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
#include <gst/video/video.h>
|
||||||
|
#include <gst/cuda/gstcuda.h>
|
||||||
|
#ifdef G_OS_WIN32
|
||||||
|
#include <gst/d3d11/gstd3d11.h>
|
||||||
|
#endif
|
||||||
|
#include "nvEncodeAPI.h"
|
||||||
|
#include "gstnvenc.h"
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
#include <condition_variable>
|
||||||
|
#include <queue>
|
||||||
|
#include <set>
|
||||||
|
#include <string>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GST_TYPE_NV_ENC_BUFFER (gst_nv_enc_buffer_get_type ())
|
||||||
|
struct GstNvEncBuffer;
|
||||||
|
|
||||||
|
GType gst_nv_enc_buffer_get_type (void);
|
||||||
|
|
||||||
|
NVENCSTATUS gst_nv_enc_buffer_lock (GstNvEncBuffer * buffer,
|
||||||
|
gpointer * data,
|
||||||
|
guint32 * pitch);
|
||||||
|
|
||||||
|
void gst_nv_enc_buffer_unlock (GstNvEncBuffer * buffer);
|
||||||
|
|
||||||
|
|
||||||
|
static inline GstNvEncBuffer *
|
||||||
|
gst_nv_enc_buffer_ref (GstNvEncBuffer * buffer)
|
||||||
|
{
|
||||||
|
return (GstNvEncBuffer *)
|
||||||
|
gst_mini_object_ref (GST_MINI_OBJECT_CAST (buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
gst_nv_enc_buffer_unref (GstNvEncBuffer * buffer)
|
||||||
|
{
|
||||||
|
gst_mini_object_unref (GST_MINI_OBJECT_CAST (buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
gst_clear_nv_encoder_buffer (GstNvEncBuffer ** buffer)
|
||||||
|
{
|
||||||
|
if (buffer && *buffer) {
|
||||||
|
gst_nv_enc_buffer_unref (*buffer);
|
||||||
|
*buffer = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GST_TYPE_NV_ENC_RESOURCE (gst_nv_enc_resource_get_type ())
|
||||||
|
struct GstNvEncResource;
|
||||||
|
|
||||||
|
GType gst_nv_enc_resource_get_type (void);
|
||||||
|
|
||||||
|
static inline GstNvEncResource *
|
||||||
|
gst_nv_enc_resource_ref (GstNvEncResource * resource)
|
||||||
|
{
|
||||||
|
return (GstNvEncResource *)
|
||||||
|
gst_mini_object_ref (GST_MINI_OBJECT_CAST (resource));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
gst_nv_enc_resource_unref (GstNvEncResource * resource)
|
||||||
|
{
|
||||||
|
gst_mini_object_unref (GST_MINI_OBJECT_CAST (resource));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
gst_clear_nv_encoder_resource (GstNvEncResource ** resource)
|
||||||
|
{
|
||||||
|
if (resource && *resource) {
|
||||||
|
gst_nv_enc_resource_unref (*resource);
|
||||||
|
*resource = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GST_TYPE_NV_ENC_TASK (gst_nv_enc_task_get_type ())
|
||||||
|
struct GstNvEncTask;
|
||||||
|
|
||||||
|
GType gst_nv_enc_task_get_type (void);
|
||||||
|
|
||||||
|
gboolean gst_nv_enc_task_set_buffer (GstNvEncTask * task,
|
||||||
|
GstNvEncBuffer * buffer);
|
||||||
|
|
||||||
|
gboolean gst_nv_enc_task_set_resource (GstNvEncTask * task,
|
||||||
|
GstBuffer * buffer,
|
||||||
|
GstNvEncResource * resource);
|
||||||
|
|
||||||
|
NVENCSTATUS gst_nv_enc_task_lock_bitstream (GstNvEncTask * task,
|
||||||
|
NV_ENC_LOCK_BITSTREAM * bitstream);
|
||||||
|
|
||||||
|
void gst_nv_enc_task_unlock_bitstream (GstNvEncTask * task);
|
||||||
|
|
||||||
|
static inline GstNvEncTask *
|
||||||
|
gst_nv_enc_task_ref (GstNvEncTask * task)
|
||||||
|
{
|
||||||
|
return (GstNvEncTask *)
|
||||||
|
gst_mini_object_ref (GST_MINI_OBJECT_CAST (task));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
gst_nv_enc_task_unref (GstNvEncTask * task)
|
||||||
|
{
|
||||||
|
gst_mini_object_unref (GST_MINI_OBJECT_CAST (task));
|
||||||
|
}
|
||||||
|
|
||||||
|
const gchar * nvenc_status_to_string (NVENCSTATUS status);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
class GstNvEncObject : public std::enable_shared_from_this <GstNvEncObject>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static bool IsSuccess (NVENCSTATUS status,
|
||||||
|
GstNvEncObject * self,
|
||||||
|
const gchar * file,
|
||||||
|
const gchar * function,
|
||||||
|
gint line);
|
||||||
|
|
||||||
|
static std::shared_ptr<GstNvEncObject>
|
||||||
|
CreateInstance (GstElement * client,
|
||||||
|
GstObject * device,
|
||||||
|
NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS * params);
|
||||||
|
|
||||||
|
~GstNvEncObject ();
|
||||||
|
|
||||||
|
gpointer GetHandle ();
|
||||||
|
|
||||||
|
guint GetTaskSize ();
|
||||||
|
|
||||||
|
NVENCSTATUS InitSession (NV_ENC_INITIALIZE_PARAMS * params,
|
||||||
|
GstCudaStream * stream,
|
||||||
|
const GstVideoInfo * info,
|
||||||
|
guint pool_size);
|
||||||
|
|
||||||
|
NVENCSTATUS Reconfigure (NV_ENC_RECONFIGURE_PARAMS * params);
|
||||||
|
|
||||||
|
void SetFlushing (bool flushing);
|
||||||
|
|
||||||
|
NVENCSTATUS Encode (GstVideoCodecFrame * codec_frame,
|
||||||
|
NV_ENC_PIC_STRUCT pic_struct,
|
||||||
|
GstNvEncTask * task);
|
||||||
|
|
||||||
|
NVENCSTATUS Drain (GstNvEncTask * task);
|
||||||
|
|
||||||
|
GstFlowReturn GetOutput (GstNvEncTask ** task);
|
||||||
|
|
||||||
|
NVENCSTATUS LockBitstream (NV_ENC_LOCK_BITSTREAM * bitstream);
|
||||||
|
|
||||||
|
NVENCSTATUS UnlockBitstream (NV_ENC_OUTPUT_PTR output_ptr);
|
||||||
|
|
||||||
|
NVENCSTATUS AcquireBuffer (GstNvEncBuffer ** buffer);
|
||||||
|
|
||||||
|
NVENCSTATUS AcquireResource (GstMemory * mem,
|
||||||
|
GstNvEncResource ** resource);
|
||||||
|
|
||||||
|
GstFlowReturn AcquireTask (GstNvEncTask ** task,
|
||||||
|
bool force);
|
||||||
|
|
||||||
|
void PushEmptyTask (GstNvEncTask * task);
|
||||||
|
|
||||||
|
void PushEmptyBuffer (GstNvEncBuffer * buffer);
|
||||||
|
|
||||||
|
void ReleaseResource (GstNvEncResource * resource);
|
||||||
|
|
||||||
|
void DeactivateResource (GstNvEncResource * resource);
|
||||||
|
|
||||||
|
bool DeviceLock ();
|
||||||
|
|
||||||
|
bool DeviceUnlock ();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void releaseResourceUnlocked (GstNvEncResource * resource);
|
||||||
|
|
||||||
|
void releaseTaskUnlocked (GstNvEncTask * task);
|
||||||
|
|
||||||
|
NVENCSTATUS acquireResourceCuda (GstMemory * mem,
|
||||||
|
GstNvEncResource ** resource);
|
||||||
|
|
||||||
|
#ifdef G_OS_WIN32
|
||||||
|
NVENCSTATUS acquireResourceD3D11 (GstMemory * mem,
|
||||||
|
GstNvEncResource ** resource);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void runResourceGC ();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string id_;
|
||||||
|
std::mutex lock_;
|
||||||
|
std::recursive_mutex resource_lock_;
|
||||||
|
std::condition_variable cond_;
|
||||||
|
/* holding unused GstNvEncBuffer object, holding ownership */
|
||||||
|
std::queue <GstNvEncBuffer *> buffer_queue_;
|
||||||
|
|
||||||
|
/* GstNvEncResource resource is always owned by GstMemory.
|
||||||
|
* below two data struct will track the resource's life cycle */
|
||||||
|
|
||||||
|
/* list of all registered GstNvEncResource, without ownership */
|
||||||
|
std::set <GstNvEncResource *> resource_queue_;
|
||||||
|
|
||||||
|
/* list of GstNvEncResource in task_queue */
|
||||||
|
std::set <GstNvEncResource *> active_resource_queue_;
|
||||||
|
std::queue <GstNvEncTask *> task_queue_;
|
||||||
|
std::queue <GstNvEncTask *> empty_task_queue_;
|
||||||
|
gint64 user_token_;
|
||||||
|
GstCudaContext *context_ = nullptr;
|
||||||
|
GstCudaStream *stream_ = nullptr;
|
||||||
|
#ifdef G_OS_WIN32
|
||||||
|
GstD3D11Device *device_ = nullptr;
|
||||||
|
#endif
|
||||||
|
GstVideoInfo info_;
|
||||||
|
gpointer session_ = nullptr;
|
||||||
|
bool initialized_ = false;
|
||||||
|
bool flushing_ = false;
|
||||||
|
guint task_size_ = 0;
|
||||||
|
|
||||||
|
NV_ENC_DEVICE_TYPE device_type_ = NV_ENC_DEVICE_TYPE_CUDA;
|
||||||
|
NV_ENC_BUFFER_FORMAT buffer_format_ = NV_ENC_BUFFER_FORMAT_UNDEFINED;
|
||||||
|
|
||||||
|
std::atomic<guint> buffer_seq_;
|
||||||
|
std::atomic<guint> resource_seq_;
|
||||||
|
std::atomic<guint> task_seq_;
|
||||||
|
};
|
File diff suppressed because it is too large
Load diff
|
@ -162,27 +162,6 @@ typedef struct
|
||||||
gint ref_count;
|
gint ref_count;
|
||||||
} GstNvEncoderClassData;
|
} GstNvEncoderClassData;
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
/* without ref */
|
|
||||||
GstNvEncoder *encoder;
|
|
||||||
|
|
||||||
/* Holds ownership */
|
|
||||||
GstBuffer *buffer;
|
|
||||||
GstMapInfo map_info;
|
|
||||||
|
|
||||||
NV_ENC_REGISTER_RESOURCE register_resource;
|
|
||||||
NV_ENC_MAP_INPUT_RESOURCE mapped_resource;
|
|
||||||
|
|
||||||
/* Used when input resource cannot be registered */
|
|
||||||
NV_ENC_CREATE_INPUT_BUFFER input_buffer;
|
|
||||||
NV_ENC_LOCK_INPUT_BUFFER lk_input_buffer;
|
|
||||||
|
|
||||||
NV_ENC_OUTPUT_PTR output_ptr;
|
|
||||||
gpointer event_handle;
|
|
||||||
gboolean is_eos;
|
|
||||||
} GstNvEncoderTask;
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
GstNvEncoderDeviceMode device_mode;
|
GstNvEncoderDeviceMode device_mode;
|
||||||
|
@ -228,12 +207,6 @@ struct _GstNvEncoderClass
|
||||||
|
|
||||||
GType gst_nv_encoder_get_type (void);
|
GType gst_nv_encoder_get_type (void);
|
||||||
|
|
||||||
guint gst_nv_encoder_get_task_size (GstNvEncoder * encoder);
|
|
||||||
|
|
||||||
const gchar * gst_nv_encoder_status_to_string (NVENCSTATUS status);
|
|
||||||
#define GST_NVENC_STATUS_FORMAT "s (%d)"
|
|
||||||
#define GST_NVENC_STATUS_ARGS(s) gst_nv_encoder_status_to_string (s), s
|
|
||||||
|
|
||||||
void gst_nv_encoder_preset_to_guid (GstNvEncoderPreset preset,
|
void gst_nv_encoder_preset_to_guid (GstNvEncoderPreset preset,
|
||||||
GUID * guid);
|
GUID * guid);
|
||||||
|
|
||||||
|
@ -258,6 +231,14 @@ void gst_nv_encoder_merge_device_caps (const GstNvEncoderDeviceCaps * a,
|
||||||
const GstNvEncoderDeviceCaps * b,
|
const GstNvEncoderDeviceCaps * b,
|
||||||
GstNvEncoderDeviceCaps * merged);
|
GstNvEncoderDeviceCaps * merged);
|
||||||
|
|
||||||
|
gboolean _gst_nv_enc_result (NVENCSTATUS status,
|
||||||
|
GObject * self,
|
||||||
|
const gchar * file,
|
||||||
|
const gchar * function,
|
||||||
|
gint line);
|
||||||
|
|
||||||
|
#define gst_nv_enc_result(status,self) \
|
||||||
|
_gst_nv_enc_result (status, (GObject *) self, __FILE__, GST_FUNCTION, __LINE__)
|
||||||
|
|
||||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstNvEncoder, gst_object_unref)
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstNvEncoder, gst_object_unref)
|
||||||
|
|
||||||
|
|
|
@ -1201,9 +1201,8 @@ gst_nv_h264_encoder_set_format (GstNvEncoder * encoder,
|
||||||
|
|
||||||
status = NvEncGetEncodePresetConfig (session, NV_ENC_CODEC_H264_GUID,
|
status = NvEncGetEncodePresetConfig (session, NV_ENC_CODEC_H264_GUID,
|
||||||
init_params->presetGUID, &preset_config);
|
init_params->presetGUID, &preset_config);
|
||||||
if (status != NV_ENC_SUCCESS) {
|
if (!gst_nv_enc_result (status, self)) {
|
||||||
GST_ERROR_OBJECT (self, "Failed to get preset config %"
|
GST_ERROR_OBJECT (self, "Failed to get preset config");
|
||||||
GST_NVENC_STATUS_FORMAT, GST_NVENC_STATUS_ARGS (status));
|
|
||||||
g_mutex_unlock (&self->prop_lock);
|
g_mutex_unlock (&self->prop_lock);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -1431,9 +1430,8 @@ gst_nv_h264_encoder_set_output_state (GstNvEncoder * encoder,
|
||||||
seq_params.spsppsBuffer = &spspps;
|
seq_params.spsppsBuffer = &spspps;
|
||||||
seq_params.outSPSPPSPayloadSize = &seq_size;
|
seq_params.outSPSPPSPayloadSize = &seq_size;
|
||||||
status = NvEncGetSequenceParams (session, &seq_params);
|
status = NvEncGetSequenceParams (session, &seq_params);
|
||||||
if (status != NV_ENC_SUCCESS) {
|
if (!gst_nv_enc_result (status, self)) {
|
||||||
GST_ERROR_OBJECT (self, "Failed to get sequence header, status %"
|
GST_ERROR_OBJECT (self, "Failed to get sequence header");
|
||||||
GST_NVENC_STATUS_FORMAT, GST_NVENC_STATUS_ARGS (status));
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1184,9 +1184,8 @@ gst_nv_h265_encoder_set_format (GstNvEncoder * encoder,
|
||||||
|
|
||||||
status = NvEncGetEncodePresetConfig (session, NV_ENC_CODEC_HEVC_GUID,
|
status = NvEncGetEncodePresetConfig (session, NV_ENC_CODEC_HEVC_GUID,
|
||||||
init_params->presetGUID, &preset_config);
|
init_params->presetGUID, &preset_config);
|
||||||
if (status != NV_ENC_SUCCESS) {
|
if (!gst_nv_enc_result (status, self)) {
|
||||||
GST_ERROR_OBJECT (self, "Failed to get preset config %"
|
GST_ERROR_OBJECT (self, "Failed to get preset config");
|
||||||
GST_NVENC_STATUS_FORMAT, GST_NVENC_STATUS_ARGS (status));
|
|
||||||
g_mutex_unlock (&self->prop_lock);
|
g_mutex_unlock (&self->prop_lock);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -1378,9 +1377,8 @@ gst_nv_h265_encoder_set_output_state (GstNvEncoder * encoder,
|
||||||
seq_params.spsppsBuffer = &vpsspspps;
|
seq_params.spsppsBuffer = &vpsspspps;
|
||||||
seq_params.outSPSPPSPayloadSize = &seq_size;
|
seq_params.outSPSPPSPayloadSize = &seq_size;
|
||||||
status = NvEncGetSequenceParams (session, &seq_params);
|
status = NvEncGetSequenceParams (session, &seq_params);
|
||||||
if (status != NV_ENC_SUCCESS) {
|
if (!gst_nv_enc_result (status, self)) {
|
||||||
GST_ERROR_OBJECT (self, "Failed to get sequence header, status %"
|
GST_ERROR_OBJECT (self, "Failed to get sequence header");
|
||||||
GST_NVENC_STATUS_FORMAT, GST_NVENC_STATUS_ARGS (status));
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ nvcodec_sources = [
|
||||||
'gstnvdecobject.cpp',
|
'gstnvdecobject.cpp',
|
||||||
'gstnvdecoder.cpp',
|
'gstnvdecoder.cpp',
|
||||||
'gstnvenc.c',
|
'gstnvenc.c',
|
||||||
|
'gstnvencobject.cpp',
|
||||||
'gstnvencoder.cpp',
|
'gstnvencoder.cpp',
|
||||||
'gstnvh264dec.cpp',
|
'gstnvh264dec.cpp',
|
||||||
'gstnvh264enc.c',
|
'gstnvh264enc.c',
|
||||||
|
@ -82,6 +83,7 @@ gstnvcodec = library('gstnvcodec',
|
||||||
cpp_args : gst_plugins_bad_args + extra_args,
|
cpp_args : gst_plugins_bad_args + extra_args,
|
||||||
include_directories : plugin_incdirs,
|
include_directories : plugin_incdirs,
|
||||||
dependencies : [gstbase_dep, gstvideo_dep, gstpbutils_dep, gstgl_dep, gstglproto_dep, gmodule_dep, gstcodecs_dep, gstd3d11_dep, gstcuda_dep],
|
dependencies : [gstbase_dep, gstvideo_dep, gstpbutils_dep, gstgl_dep, gstglproto_dep, gmodule_dep, gstcodecs_dep, gstd3d11_dep, gstcuda_dep],
|
||||||
|
override_options : ['cpp_std=c++14'],
|
||||||
install : true,
|
install : true,
|
||||||
install_dir : plugins_install_dir,
|
install_dir : plugins_install_dir,
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in a new issue