mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-27 08:26:39 +00:00
Add new property to support application allocated GstCudaMemory. CUDA memory alloc/free is a global device synchronization point as if launching CUDA kernel on default CUDA stream. To avoid the global synchronization, we added stream-ordered allocation support which allocates CUDA memory asynchronously. However, NVENC does not allow registering the stream-ordered allocated memory. Thus encoder was allocating normal CUDA memory in case that input CUDA memory is stream-ordered type. In this commit, newly introduced property will allow application to provide encoder with GstCudaBufferPool. Application can preallocate sufficient amount of CUDA memory in advance to avoid global device synchronization while pipeline is running. For now, this pool is used only if input CUDA memory is allocated via stream-ordered-allocation Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8516>
268 lines
7.7 KiB
C++
268 lines
7.7 KiB
C++
/* 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);
|
|
|
|
GArray * gst_nv_enc_task_get_sei_payload (GstNvEncTask * task);
|
|
|
|
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
|
|
|
|
enum GstNvEncCodec
|
|
{
|
|
GST_NV_ENC_CODEC_H264,
|
|
GST_NV_ENC_CODEC_H265,
|
|
GST_NV_ENC_CODEC_AV1,
|
|
};
|
|
|
|
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);
|
|
|
|
NVENCSTATUS AcquireResourceWithSize (GstMemory * mem,
|
|
guint width,
|
|
guint height,
|
|
guint stride,
|
|
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,
|
|
guint width,
|
|
guint height,
|
|
guint stride,
|
|
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 *> pending_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;
|
|
guint lookahead_ = 0;
|
|
|
|
NV_ENC_DEVICE_TYPE device_type_ = NV_ENC_DEVICE_TYPE_CUDA;
|
|
NV_ENC_BUFFER_FORMAT buffer_format_ = NV_ENC_BUFFER_FORMAT_UNDEFINED;
|
|
GstNvEncCodec codec_;
|
|
|
|
std::atomic<guint> buffer_seq_;
|
|
std::atomic<guint> resource_seq_;
|
|
std::atomic<guint> task_seq_;
|
|
};
|