mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 02:01:12 +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;
|
||||
} 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
|
||||
{
|
||||
GstNvEncoderDeviceMode device_mode;
|
||||
|
@ -228,12 +207,6 @@ struct _GstNvEncoderClass
|
|||
|
||||
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,
|
||||
GUID * guid);
|
||||
|
||||
|
@ -258,6 +231,14 @@ void gst_nv_encoder_merge_device_caps (const GstNvEncoderDeviceCaps * a,
|
|||
const GstNvEncoderDeviceCaps * b,
|
||||
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)
|
||||
|
||||
|
|
|
@ -1201,9 +1201,8 @@ gst_nv_h264_encoder_set_format (GstNvEncoder * encoder,
|
|||
|
||||
status = NvEncGetEncodePresetConfig (session, NV_ENC_CODEC_H264_GUID,
|
||||
init_params->presetGUID, &preset_config);
|
||||
if (status != NV_ENC_SUCCESS) {
|
||||
GST_ERROR_OBJECT (self, "Failed to get preset config %"
|
||||
GST_NVENC_STATUS_FORMAT, GST_NVENC_STATUS_ARGS (status));
|
||||
if (!gst_nv_enc_result (status, self)) {
|
||||
GST_ERROR_OBJECT (self, "Failed to get preset config");
|
||||
g_mutex_unlock (&self->prop_lock);
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -1431,9 +1430,8 @@ gst_nv_h264_encoder_set_output_state (GstNvEncoder * encoder,
|
|||
seq_params.spsppsBuffer = &spspps;
|
||||
seq_params.outSPSPPSPayloadSize = &seq_size;
|
||||
status = NvEncGetSequenceParams (session, &seq_params);
|
||||
if (status != NV_ENC_SUCCESS) {
|
||||
GST_ERROR_OBJECT (self, "Failed to get sequence header, status %"
|
||||
GST_NVENC_STATUS_FORMAT, GST_NVENC_STATUS_ARGS (status));
|
||||
if (!gst_nv_enc_result (status, self)) {
|
||||
GST_ERROR_OBJECT (self, "Failed to get sequence header");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
@ -1184,9 +1184,8 @@ gst_nv_h265_encoder_set_format (GstNvEncoder * encoder,
|
|||
|
||||
status = NvEncGetEncodePresetConfig (session, NV_ENC_CODEC_HEVC_GUID,
|
||||
init_params->presetGUID, &preset_config);
|
||||
if (status != NV_ENC_SUCCESS) {
|
||||
GST_ERROR_OBJECT (self, "Failed to get preset config %"
|
||||
GST_NVENC_STATUS_FORMAT, GST_NVENC_STATUS_ARGS (status));
|
||||
if (!gst_nv_enc_result (status, self)) {
|
||||
GST_ERROR_OBJECT (self, "Failed to get preset config");
|
||||
g_mutex_unlock (&self->prop_lock);
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -1378,9 +1377,8 @@ gst_nv_h265_encoder_set_output_state (GstNvEncoder * encoder,
|
|||
seq_params.spsppsBuffer = &vpsspspps;
|
||||
seq_params.outSPSPPSPayloadSize = &seq_size;
|
||||
status = NvEncGetSequenceParams (session, &seq_params);
|
||||
if (status != NV_ENC_SUCCESS) {
|
||||
GST_ERROR_OBJECT (self, "Failed to get sequence header, status %"
|
||||
GST_NVENC_STATUS_FORMAT, GST_NVENC_STATUS_ARGS (status));
|
||||
if (!gst_nv_enc_result (status, self)) {
|
||||
GST_ERROR_OBJECT (self, "Failed to get sequence header");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ nvcodec_sources = [
|
|||
'gstnvdecobject.cpp',
|
||||
'gstnvdecoder.cpp',
|
||||
'gstnvenc.c',
|
||||
'gstnvencobject.cpp',
|
||||
'gstnvencoder.cpp',
|
||||
'gstnvh264dec.cpp',
|
||||
'gstnvh264enc.c',
|
||||
|
@ -82,6 +83,7 @@ gstnvcodec = library('gstnvcodec',
|
|||
cpp_args : gst_plugins_bad_args + extra_args,
|
||||
include_directories : plugin_incdirs,
|
||||
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_dir : plugins_install_dir,
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue