mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 01:00:37 +00:00
nvenc: Refactor class hierarchy to handle device capability dependent options
Introducing new dynamic class between GstNvBaseEncClass and each subclass to be able to access device specific properties and capabilities from each subclass implementation side.
This commit is contained in:
parent
f402cb07f9
commit
b3b723462e
7 changed files with 230 additions and 134 deletions
|
@ -2243,91 +2243,41 @@ gst_nv_base_enc_get_property (GObject * object, guint prop_id, GValue * value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
GstCaps *sink_caps;
|
|
||||||
GstCaps *src_caps;
|
|
||||||
guint cuda_device_id;
|
|
||||||
gboolean is_default;
|
|
||||||
} GstNvEncClassData;
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_nv_base_enc_subclass_init (gpointer g_class, gpointer data)
|
gst_nv_base_enc_subclass_init (gpointer g_class, gpointer data)
|
||||||
{
|
{
|
||||||
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
|
|
||||||
GstNvBaseEncClass *nvbaseenc_class = GST_NV_BASE_ENC_CLASS (g_class);
|
GstNvBaseEncClass *nvbaseenc_class = GST_NV_BASE_ENC_CLASS (g_class);
|
||||||
GstNvEncClassData *cdata = data;
|
guint device_id = GPOINTER_TO_UINT (data);
|
||||||
|
|
||||||
if (!cdata->is_default) {
|
nvbaseenc_class->cuda_device_id = device_id;
|
||||||
const gchar *long_name;
|
|
||||||
gchar *new_long_name;
|
|
||||||
|
|
||||||
long_name = gst_element_class_get_metadata (element_class,
|
|
||||||
GST_ELEMENT_METADATA_LONGNAME);
|
|
||||||
|
|
||||||
new_long_name = g_strdup_printf ("%s with devide-id %d", long_name,
|
|
||||||
cdata->cuda_device_id);
|
|
||||||
|
|
||||||
gst_element_class_add_metadata (element_class,
|
|
||||||
GST_ELEMENT_METADATA_LONGNAME, new_long_name);
|
|
||||||
g_free (new_long_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
gst_element_class_add_pad_template (element_class,
|
|
||||||
gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
|
|
||||||
cdata->sink_caps));
|
|
||||||
gst_element_class_add_pad_template (element_class,
|
|
||||||
gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
|
|
||||||
cdata->src_caps));
|
|
||||||
|
|
||||||
nvbaseenc_class->cuda_device_id = cdata->cuda_device_id;
|
|
||||||
|
|
||||||
gst_caps_unref (cdata->sink_caps);
|
|
||||||
gst_caps_unref (cdata->src_caps);
|
|
||||||
g_free (cdata);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
GType
|
||||||
gst_nv_base_enc_register (GstPlugin * plugin, GType type, const char *codec,
|
gst_nv_base_enc_register (const char *codec, guint device_id)
|
||||||
guint device_id, guint rank, GstCaps * sink_caps, GstCaps * src_caps)
|
|
||||||
{
|
{
|
||||||
GTypeQuery type_query;
|
GTypeQuery type_query;
|
||||||
GTypeInfo type_info = { 0, };
|
GTypeInfo type_info = { 0, };
|
||||||
GType subtype;
|
GType subtype;
|
||||||
gchar *type_name;
|
gchar *type_name;
|
||||||
GstNvEncClassData *cdata;
|
|
||||||
gboolean is_default = TRUE;
|
|
||||||
|
|
||||||
cdata = g_new0 (GstNvEncClassData, 1);
|
type_name = g_strdup_printf ("GstNvDevice%d%sEnc", device_id, codec);
|
||||||
cdata->sink_caps = gst_caps_ref (sink_caps);
|
subtype = g_type_from_name (type_name);
|
||||||
cdata->src_caps = gst_caps_ref (src_caps);
|
|
||||||
cdata->cuda_device_id = device_id;
|
|
||||||
|
|
||||||
g_type_query (type, &type_query);
|
/* has already registered nvdeviceenc class */
|
||||||
|
if (subtype)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
g_type_query (GST_TYPE_NV_BASE_ENC, &type_query);
|
||||||
memset (&type_info, 0, sizeof (type_info));
|
memset (&type_info, 0, sizeof (type_info));
|
||||||
type_info.class_size = type_query.class_size;
|
type_info.class_size = type_query.class_size;
|
||||||
type_info.instance_size = type_query.instance_size;
|
type_info.instance_size = type_query.instance_size;
|
||||||
type_info.class_init = gst_nv_base_enc_subclass_init;
|
type_info.class_init = (GClassInitFunc) gst_nv_base_enc_subclass_init;
|
||||||
type_info.class_data = cdata;
|
type_info.class_data = GUINT_TO_POINTER (device_id);
|
||||||
|
|
||||||
type_name = g_strdup_printf ("nv%senc", codec);
|
subtype = g_type_register_static (GST_TYPE_NV_BASE_ENC,
|
||||||
|
type_name, &type_info, 0);
|
||||||
if (g_type_from_name (type_name) != 0) {
|
|
||||||
g_free (type_name);
|
|
||||||
type_name = g_strdup_printf ("nv%sdevice%denc", codec, device_id);
|
|
||||||
is_default = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
cdata->is_default = is_default;
|
|
||||||
subtype = g_type_register_static (type, type_name, &type_info, 0);
|
|
||||||
|
|
||||||
/* make lower rank than default device */
|
|
||||||
if (rank > 0 && !is_default)
|
|
||||||
rank--;
|
|
||||||
|
|
||||||
if (!gst_element_register (plugin, type_name, rank, subtype))
|
|
||||||
GST_WARNING ("Failed to register plugin '%s'", type_name);
|
|
||||||
|
|
||||||
|
done:
|
||||||
g_free (type_name);
|
g_free (type_name);
|
||||||
|
return subtype;
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,13 +128,8 @@ typedef struct {
|
||||||
G_GNUC_INTERNAL
|
G_GNUC_INTERNAL
|
||||||
GType gst_nv_base_enc_get_type (void);
|
GType gst_nv_base_enc_get_type (void);
|
||||||
|
|
||||||
void gst_nv_base_enc_register (GstPlugin * plugin,
|
GType gst_nv_base_enc_register (const char * codec,
|
||||||
GType type,
|
guint device_id);
|
||||||
const char * codec,
|
|
||||||
guint device_id,
|
|
||||||
guint rank,
|
|
||||||
GstCaps * sink_caps,
|
|
||||||
GstCaps * src_caps);
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* __GST_NV_BASE_ENC_H_INCLUDED__ */
|
#endif /* __GST_NV_BASE_ENC_H_INCLUDED__ */
|
||||||
|
|
|
@ -593,8 +593,8 @@ gst_nvenc_get_supported_codec_profiles (gpointer enc, GUID codec_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_nv_enc_register (GstPlugin * plugin, GType type, GUID codec_id,
|
gst_nv_enc_register (GstPlugin * plugin, GUID codec_id, const gchar * codec,
|
||||||
const gchar * codec, guint rank, gint device_count)
|
guint rank, gint device_count)
|
||||||
{
|
{
|
||||||
gint i;
|
gint i;
|
||||||
|
|
||||||
|
@ -730,9 +730,15 @@ gst_nv_enc_register (GstPlugin * plugin, GType type, GUID codec_id,
|
||||||
cuda_free:
|
cuda_free:
|
||||||
CuCtxDestroy (cuda_ctx);
|
CuCtxDestroy (cuda_ctx);
|
||||||
|
|
||||||
if (sink_templ && src_templ)
|
if (sink_templ && src_templ) {
|
||||||
gst_nv_base_enc_register (plugin, type, codec, i, rank, sink_templ,
|
if (gst_nvenc_cmp_guid (codec_id, NV_ENC_CODEC_H264_GUID)) {
|
||||||
src_templ);
|
gst_nv_h264_enc_register (plugin, i, rank, sink_templ, src_templ);
|
||||||
|
} else if (gst_nvenc_cmp_guid (codec_id, NV_ENC_CODEC_HEVC_GUID)) {
|
||||||
|
gst_nv_h265_enc_register (plugin, i, rank, sink_templ, src_templ);
|
||||||
|
} else {
|
||||||
|
g_assert_not_reached ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gst_clear_caps (&sink_templ);
|
gst_clear_caps (&sink_templ);
|
||||||
gst_clear_caps (&src_templ);
|
gst_clear_caps (&src_templ);
|
||||||
|
@ -821,10 +827,10 @@ gst_nvenc_plugin_init (GstPlugin * plugin)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_nv_enc_register (plugin, GST_TYPE_NV_H264_ENC,
|
gst_nv_enc_register (plugin, NV_ENC_CODEC_H264_GUID,
|
||||||
NV_ENC_CODEC_H264_GUID, "h264", GST_RANK_PRIMARY * 2, dev_count);
|
"h264", GST_RANK_PRIMARY * 2, dev_count);
|
||||||
gst_nv_enc_register (plugin, GST_TYPE_NV_H265_ENC,
|
gst_nv_enc_register (plugin, NV_ENC_CODEC_HEVC_GUID,
|
||||||
NV_ENC_CODEC_HEVC_GUID, "h265", GST_RANK_PRIMARY * 2, dev_count);
|
"h265", GST_RANK_PRIMARY * 2, dev_count);
|
||||||
} else {
|
} else {
|
||||||
GST_ERROR ("too old driver, could not load api vtable");
|
GST_ERROR ("too old driver, could not load api vtable");
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,11 +27,17 @@
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GstCaps *sink_caps;
|
||||||
|
GstCaps *src_caps;
|
||||||
|
gboolean is_default;
|
||||||
|
} GstNvH264EncClassData;
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_STATIC (gst_nv_h264_enc_debug);
|
GST_DEBUG_CATEGORY_STATIC (gst_nv_h264_enc_debug);
|
||||||
#define GST_CAT_DEFAULT gst_nv_h264_enc_debug
|
#define GST_CAT_DEFAULT gst_nv_h264_enc_debug
|
||||||
|
|
||||||
#define parent_class gst_nv_h264_enc_parent_class
|
static GstElementClass *parent_class = NULL;
|
||||||
G_DEFINE_TYPE (GstNvH264Enc, gst_nv_h264_enc, GST_TYPE_NV_BASE_ENC);
|
|
||||||
|
|
||||||
static gboolean gst_nv_h264_enc_open (GstVideoEncoder * enc);
|
static gboolean gst_nv_h264_enc_open (GstVideoEncoder * enc);
|
||||||
static gboolean gst_nv_h264_enc_close (GstVideoEncoder * enc);
|
static gboolean gst_nv_h264_enc_close (GstVideoEncoder * enc);
|
||||||
|
@ -48,12 +54,16 @@ static void gst_nv_h264_enc_get_property (GObject * object, guint prop_id,
|
||||||
static void gst_nv_h264_enc_finalize (GObject * obj);
|
static void gst_nv_h264_enc_finalize (GObject * obj);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_nv_h264_enc_class_init (GstNvH264EncClass * klass)
|
gst_nv_h264_enc_class_init (GstNvH264EncClass * klass, gpointer data)
|
||||||
{
|
{
|
||||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||||
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||||
GstVideoEncoderClass *videoenc_class = GST_VIDEO_ENCODER_CLASS (klass);
|
GstVideoEncoderClass *videoenc_class = GST_VIDEO_ENCODER_CLASS (klass);
|
||||||
GstNvBaseEncClass *nvenc_class = GST_NV_BASE_ENC_CLASS (klass);
|
GstNvBaseEncClass *nvenc_class = GST_NV_BASE_ENC_CLASS (klass);
|
||||||
|
GstNvH264EncClassData *cdata = (GstNvH264EncClassData *) data;
|
||||||
|
gchar *long_name;
|
||||||
|
|
||||||
|
parent_class = g_type_class_peek_parent (klass);
|
||||||
|
|
||||||
gobject_class->set_property = gst_nv_h264_enc_set_property;
|
gobject_class->set_property = gst_nv_h264_enc_set_property;
|
||||||
gobject_class->get_property = gst_nv_h264_enc_get_property;
|
gobject_class->get_property = gst_nv_h264_enc_get_property;
|
||||||
|
@ -67,16 +77,33 @@ gst_nv_h264_enc_class_init (GstNvH264EncClass * klass)
|
||||||
nvenc_class->set_src_caps = gst_nv_h264_enc_set_src_caps;
|
nvenc_class->set_src_caps = gst_nv_h264_enc_set_src_caps;
|
||||||
nvenc_class->set_pic_params = gst_nv_h264_enc_set_pic_params;
|
nvenc_class->set_pic_params = gst_nv_h264_enc_set_pic_params;
|
||||||
|
|
||||||
gst_element_class_set_static_metadata (element_class,
|
if (cdata->is_default)
|
||||||
"NVENC H.264 Video Encoder",
|
long_name = g_strdup ("NVENC H.264 Video Encoder");
|
||||||
|
else
|
||||||
|
long_name = g_strdup_printf ("NVENC H.264 Video Encoder with device %d",
|
||||||
|
nvenc_class->cuda_device_id);
|
||||||
|
|
||||||
|
gst_element_class_set_metadata (element_class, long_name,
|
||||||
"Codec/Encoder/Video/Hardware",
|
"Codec/Encoder/Video/Hardware",
|
||||||
"Encode H.264 video streams using NVIDIA's hardware-accelerated NVENC encoder API",
|
"Encode H.264 video streams using NVIDIA's hardware-accelerated NVENC encoder API",
|
||||||
"Tim-Philipp Müller <tim@centricular.com>, "
|
"Tim-Philipp Müller <tim@centricular.com>, "
|
||||||
"Matthew Waters <matthew@centricular.com>, "
|
"Matthew Waters <matthew@centricular.com>, "
|
||||||
"Seungha Yang <seungha.yang@navercorp.com>");
|
"Seungha Yang <seungha.yang@navercorp.com>");
|
||||||
|
g_free (long_name);
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_INIT (gst_nv_h264_enc_debug,
|
GST_DEBUG_CATEGORY_INIT (gst_nv_h264_enc_debug,
|
||||||
"nvh264enc", 0, "Nvidia H.264 encoder");
|
"nvh264enc", 0, "Nvidia H.264 encoder");
|
||||||
|
|
||||||
|
gst_element_class_add_pad_template (element_class,
|
||||||
|
gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
|
||||||
|
cdata->sink_caps));
|
||||||
|
gst_element_class_add_pad_template (element_class,
|
||||||
|
gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
|
||||||
|
cdata->src_caps));
|
||||||
|
|
||||||
|
gst_caps_unref (cdata->sink_caps);
|
||||||
|
gst_caps_unref (cdata->src_caps);
|
||||||
|
g_free (cdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -87,7 +114,7 @@ gst_nv_h264_enc_init (GstNvH264Enc * nvenc)
|
||||||
static void
|
static void
|
||||||
gst_nv_h264_enc_finalize (GObject * obj)
|
gst_nv_h264_enc_finalize (GObject * obj)
|
||||||
{
|
{
|
||||||
G_OBJECT_CLASS (gst_nv_h264_enc_parent_class)->finalize (obj);
|
G_OBJECT_CLASS (parent_class)->finalize (obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -95,7 +122,7 @@ gst_nv_h264_enc_open (GstVideoEncoder * enc)
|
||||||
{
|
{
|
||||||
GstNvBaseEnc *base = GST_NV_BASE_ENC (enc);
|
GstNvBaseEnc *base = GST_NV_BASE_ENC (enc);
|
||||||
|
|
||||||
if (!GST_VIDEO_ENCODER_CLASS (gst_nv_h264_enc_parent_class)->open (enc))
|
if (!GST_VIDEO_ENCODER_CLASS (parent_class)->open (enc))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* Check if H.264 is supported */
|
/* Check if H.264 is supported */
|
||||||
|
@ -122,7 +149,7 @@ gst_nv_h264_enc_open (GstVideoEncoder * enc)
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_nv_h264_enc_close (GstVideoEncoder * enc)
|
gst_nv_h264_enc_close (GstVideoEncoder * enc)
|
||||||
{
|
{
|
||||||
return GST_VIDEO_ENCODER_CLASS (gst_nv_h264_enc_parent_class)->close (enc);
|
return GST_VIDEO_ENCODER_CLASS (parent_class)->close (enc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -214,7 +241,7 @@ no_peer:
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_nv_h264_enc_set_src_caps (GstNvBaseEnc * nvenc, GstVideoCodecState * state)
|
gst_nv_h264_enc_set_src_caps (GstNvBaseEnc * nvenc, GstVideoCodecState * state)
|
||||||
{
|
{
|
||||||
GstNvH264Enc *h264enc = GST_NV_H264_ENC (nvenc);
|
GstNvH264Enc *h264enc = (GstNvH264Enc *) nvenc;
|
||||||
GstVideoCodecState *out_state;
|
GstVideoCodecState *out_state;
|
||||||
GstStructure *s;
|
GstStructure *s;
|
||||||
GstCaps *out_caps;
|
GstCaps *out_caps;
|
||||||
|
@ -247,7 +274,7 @@ static gboolean
|
||||||
gst_nv_h264_enc_set_encoder_config (GstNvBaseEnc * nvenc,
|
gst_nv_h264_enc_set_encoder_config (GstNvBaseEnc * nvenc,
|
||||||
GstVideoCodecState * state, NV_ENC_CONFIG * config)
|
GstVideoCodecState * state, NV_ENC_CONFIG * config)
|
||||||
{
|
{
|
||||||
GstNvH264Enc *h264enc = GST_NV_H264_ENC (nvenc);
|
GstNvH264Enc *h264enc = (GstNvH264Enc *) nvenc;
|
||||||
GstCaps *allowed_caps, *template_caps;
|
GstCaps *allowed_caps, *template_caps;
|
||||||
GUID selected_profile = NV_ENC_CODEC_PROFILE_AUTOSELECT_GUID;
|
GUID selected_profile = NV_ENC_CODEC_PROFILE_AUTOSELECT_GUID;
|
||||||
int level_idc = NV_ENC_LEVEL_AUTOSELECT;
|
int level_idc = NV_ENC_LEVEL_AUTOSELECT;
|
||||||
|
@ -376,3 +403,57 @@ gst_nv_h264_enc_get_property (GObject * object, guint prop_id, GValue * value,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gst_nv_h264_enc_register (GstPlugin * plugin, guint device_id, guint rank,
|
||||||
|
GstCaps * sink_caps, GstCaps * src_caps)
|
||||||
|
{
|
||||||
|
GType parent_type;
|
||||||
|
GType type;
|
||||||
|
gchar *type_name;
|
||||||
|
gchar *feature_name;
|
||||||
|
GstNvH264EncClassData *cdata;
|
||||||
|
gboolean is_default = TRUE;
|
||||||
|
GTypeInfo type_info = {
|
||||||
|
sizeof (GstNvH264EncClass),
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
(GClassInitFunc) gst_nv_h264_enc_class_init,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
sizeof (GstNvH264Enc),
|
||||||
|
0,
|
||||||
|
(GInstanceInitFunc) gst_nv_h264_enc_init,
|
||||||
|
};
|
||||||
|
|
||||||
|
parent_type = gst_nv_base_enc_register ("H264", device_id);
|
||||||
|
|
||||||
|
cdata = g_new0 (GstNvH264EncClassData, 1);
|
||||||
|
cdata->sink_caps = gst_caps_ref (sink_caps);
|
||||||
|
cdata->src_caps = gst_caps_ref (src_caps);
|
||||||
|
type_info.class_data = cdata;
|
||||||
|
|
||||||
|
type_name = g_strdup ("GstNvH264Enc");
|
||||||
|
feature_name = g_strdup ("nvh264enc");
|
||||||
|
|
||||||
|
if (g_type_from_name (type_name) != 0) {
|
||||||
|
g_free (type_name);
|
||||||
|
g_free (feature_name);
|
||||||
|
type_name = g_strdup_printf ("GstNvH264Device%dEnc", device_id);
|
||||||
|
feature_name = g_strdup_printf ("nvh264device%denc", device_id);
|
||||||
|
is_default = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
cdata->is_default = is_default;
|
||||||
|
type = g_type_register_static (parent_type, type_name, &type_info, 0);
|
||||||
|
|
||||||
|
/* make lower rank than default device */
|
||||||
|
if (rank > 0 && !is_default)
|
||||||
|
rank--;
|
||||||
|
|
||||||
|
if (!gst_element_register (plugin, feature_name, rank, type))
|
||||||
|
GST_WARNING ("Failed to register plugin '%s'", type_name);
|
||||||
|
|
||||||
|
g_free (type_name);
|
||||||
|
g_free (feature_name);
|
||||||
|
}
|
||||||
|
|
|
@ -22,19 +22,6 @@
|
||||||
|
|
||||||
#include "gstnvbaseenc.h"
|
#include "gstnvbaseenc.h"
|
||||||
|
|
||||||
#define GST_TYPE_NV_H264_ENC \
|
|
||||||
(gst_nv_h264_enc_get_type())
|
|
||||||
#define GST_NV_H264_ENC(obj) \
|
|
||||||
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_NV_H264_ENC,GstNvH264Enc))
|
|
||||||
#define GST_NV_H264_ENC_CLASS(klass) \
|
|
||||||
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_NV_H264_ENC,GstNvH264EncClass))
|
|
||||||
#define GST_NV_H264_ENC_GET_CLASS(obj) \
|
|
||||||
(G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_NV_H264_ENC,GstNvH264EncClass))
|
|
||||||
#define GST_IS_NV_H264_ENC(obj) \
|
|
||||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_NV_H264_ENC))
|
|
||||||
#define GST_IS_NV_H264_ENC_CLASS(obj) \
|
|
||||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_NV_H264_ENC))
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
GstNvBaseEnc base_nvenc;
|
GstNvBaseEnc base_nvenc;
|
||||||
} GstNvH264Enc;
|
} GstNvH264Enc;
|
||||||
|
@ -44,6 +31,11 @@ typedef struct {
|
||||||
} GstNvH264EncClass;
|
} GstNvH264EncClass;
|
||||||
|
|
||||||
G_GNUC_INTERNAL
|
G_GNUC_INTERNAL
|
||||||
GType gst_nv_h264_enc_get_type (void);
|
void gst_nv_h264_enc_register (GstPlugin * plugin,
|
||||||
|
guint device_id,
|
||||||
|
guint rank,
|
||||||
|
GstCaps * sink_caps,
|
||||||
|
GstCaps * src_caps);
|
||||||
|
|
||||||
|
|
||||||
#endif /* __GST_NV_H264_ENC_H_INCLUDED__ */
|
#endif /* __GST_NV_H264_ENC_H_INCLUDED__ */
|
||||||
|
|
|
@ -29,11 +29,17 @@
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GstCaps *sink_caps;
|
||||||
|
GstCaps *src_caps;
|
||||||
|
gboolean is_default;
|
||||||
|
} GstNvH265EncClassData;
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_STATIC (gst_nv_h265_enc_debug);
|
GST_DEBUG_CATEGORY_STATIC (gst_nv_h265_enc_debug);
|
||||||
#define GST_CAT_DEFAULT gst_nv_h265_enc_debug
|
#define GST_CAT_DEFAULT gst_nv_h265_enc_debug
|
||||||
|
|
||||||
#define parent_class gst_nv_h265_enc_parent_class
|
static GstElementClass *parent_class = NULL;
|
||||||
G_DEFINE_TYPE (GstNvH265Enc, gst_nv_h265_enc, GST_TYPE_NV_BASE_ENC);
|
|
||||||
|
|
||||||
static gboolean gst_nv_h265_enc_open (GstVideoEncoder * enc);
|
static gboolean gst_nv_h265_enc_open (GstVideoEncoder * enc);
|
||||||
static gboolean gst_nv_h265_enc_close (GstVideoEncoder * enc);
|
static gboolean gst_nv_h265_enc_close (GstVideoEncoder * enc);
|
||||||
|
@ -51,12 +57,16 @@ static void gst_nv_h265_enc_get_property (GObject * object, guint prop_id,
|
||||||
static void gst_nv_h265_enc_finalize (GObject * obj);
|
static void gst_nv_h265_enc_finalize (GObject * obj);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_nv_h265_enc_class_init (GstNvH265EncClass * klass)
|
gst_nv_h265_enc_class_init (GstNvH265EncClass * klass, gpointer data)
|
||||||
{
|
{
|
||||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||||
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||||
GstVideoEncoderClass *videoenc_class = GST_VIDEO_ENCODER_CLASS (klass);
|
GstVideoEncoderClass *videoenc_class = GST_VIDEO_ENCODER_CLASS (klass);
|
||||||
GstNvBaseEncClass *nvenc_class = GST_NV_BASE_ENC_CLASS (klass);
|
GstNvBaseEncClass *nvenc_class = GST_NV_BASE_ENC_CLASS (klass);
|
||||||
|
GstNvH265EncClassData *cdata = (GstNvH265EncClassData *) data;
|
||||||
|
gchar *long_name;
|
||||||
|
|
||||||
|
parent_class = g_type_class_peek_parent (klass);
|
||||||
|
|
||||||
gobject_class->set_property = gst_nv_h265_enc_set_property;
|
gobject_class->set_property = gst_nv_h265_enc_set_property;
|
||||||
gobject_class->get_property = gst_nv_h265_enc_get_property;
|
gobject_class->get_property = gst_nv_h265_enc_get_property;
|
||||||
|
@ -71,16 +81,33 @@ gst_nv_h265_enc_class_init (GstNvH265EncClass * klass)
|
||||||
nvenc_class->set_src_caps = gst_nv_h265_enc_set_src_caps;
|
nvenc_class->set_src_caps = gst_nv_h265_enc_set_src_caps;
|
||||||
nvenc_class->set_pic_params = gst_nv_h265_enc_set_pic_params;
|
nvenc_class->set_pic_params = gst_nv_h265_enc_set_pic_params;
|
||||||
|
|
||||||
gst_element_class_set_static_metadata (element_class,
|
if (cdata->is_default)
|
||||||
"NVENC HEVC Video Encoder",
|
long_name = g_strdup ("NVENC HEVC Video Encoder");
|
||||||
|
else
|
||||||
|
long_name = g_strdup_printf ("NVENC HEVC Video Encoder with device %d",
|
||||||
|
nvenc_class->cuda_device_id);
|
||||||
|
|
||||||
|
gst_element_class_set_metadata (element_class, long_name,
|
||||||
"Codec/Encoder/Video/Hardware",
|
"Codec/Encoder/Video/Hardware",
|
||||||
"Encode HEVC video streams using NVIDIA's hardware-accelerated NVENC encoder API",
|
"Encode HEVC video streams using NVIDIA's hardware-accelerated NVENC encoder API",
|
||||||
"Tim-Philipp Müller <tim@centricular.com>, "
|
"Tim-Philipp Müller <tim@centricular.com>, "
|
||||||
"Matthew Waters <matthew@centricular.com>, "
|
"Matthew Waters <matthew@centricular.com>, "
|
||||||
"Seungha Yang <pudding8757@gmail.com>");
|
"Seungha Yang <pudding8757@gmail.com>");
|
||||||
|
g_free (long_name);
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_INIT (gst_nv_h265_enc_debug,
|
GST_DEBUG_CATEGORY_INIT (gst_nv_h265_enc_debug,
|
||||||
"nvh265enc", 0, "Nvidia HEVC encoder");
|
"nvh265enc", 0, "Nvidia HEVC encoder");
|
||||||
|
|
||||||
|
gst_element_class_add_pad_template (element_class,
|
||||||
|
gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
|
||||||
|
cdata->sink_caps));
|
||||||
|
gst_element_class_add_pad_template (element_class,
|
||||||
|
gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
|
||||||
|
cdata->src_caps));
|
||||||
|
|
||||||
|
gst_caps_unref (cdata->sink_caps);
|
||||||
|
gst_caps_unref (cdata->src_caps);
|
||||||
|
g_free (cdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -91,7 +118,7 @@ gst_nv_h265_enc_init (GstNvH265Enc * nvenc)
|
||||||
static void
|
static void
|
||||||
gst_nv_h265_enc_finalize (GObject * obj)
|
gst_nv_h265_enc_finalize (GObject * obj)
|
||||||
{
|
{
|
||||||
G_OBJECT_CLASS (gst_nv_h265_enc_parent_class)->finalize (obj);
|
G_OBJECT_CLASS (parent_class)->finalize (obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -99,7 +126,7 @@ gst_nv_h265_enc_open (GstVideoEncoder * enc)
|
||||||
{
|
{
|
||||||
GstNvBaseEnc *base = GST_NV_BASE_ENC (enc);
|
GstNvBaseEnc *base = GST_NV_BASE_ENC (enc);
|
||||||
|
|
||||||
if (!GST_VIDEO_ENCODER_CLASS (gst_nv_h265_enc_parent_class)->open (enc))
|
if (!GST_VIDEO_ENCODER_CLASS (parent_class)->open (enc))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* Check if HEVC is supported */
|
/* Check if HEVC is supported */
|
||||||
|
@ -126,7 +153,7 @@ gst_nv_h265_enc_open (GstVideoEncoder * enc)
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_nv_h265_enc_close (GstVideoEncoder * enc)
|
gst_nv_h265_enc_close (GstVideoEncoder * enc)
|
||||||
{
|
{
|
||||||
return GST_VIDEO_ENCODER_CLASS (gst_nv_h265_enc_parent_class)->close (enc);
|
return GST_VIDEO_ENCODER_CLASS (parent_class)->close (enc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -148,11 +175,11 @@ gst_nv_h265_enc_clear_stream_data (GstNvH265Enc * h265enc)
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_nv_h265_enc_stop (GstVideoEncoder * enc)
|
gst_nv_h265_enc_stop (GstVideoEncoder * enc)
|
||||||
{
|
{
|
||||||
GstNvH265Enc *h265enc = GST_NV_H265_ENC (enc);
|
GstNvH265Enc *h265enc = (GstNvH265Enc *) enc;
|
||||||
|
|
||||||
gst_nv_h265_enc_clear_stream_data (h265enc);
|
gst_nv_h265_enc_clear_stream_data (h265enc);
|
||||||
|
|
||||||
return GST_VIDEO_ENCODER_CLASS (gst_nv_h265_enc_parent_class)->stop (enc);
|
return GST_VIDEO_ENCODER_CLASS (parent_class)->stop (enc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -198,7 +225,7 @@ gst_nv_h265_enc_set_level_tier_and_profile (GstNvH265Enc * nvenc,
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_nv_h265_enc_set_src_caps (GstNvBaseEnc * nvenc, GstVideoCodecState * state)
|
gst_nv_h265_enc_set_src_caps (GstNvBaseEnc * nvenc, GstVideoCodecState * state)
|
||||||
{
|
{
|
||||||
GstNvH265Enc *h265enc = GST_NV_H265_ENC (nvenc);
|
GstNvH265Enc *h265enc = (GstNvH265Enc *) nvenc;
|
||||||
GstVideoCodecState *out_state;
|
GstVideoCodecState *out_state;
|
||||||
GstStructure *s;
|
GstStructure *s;
|
||||||
GstCaps *out_caps;
|
GstCaps *out_caps;
|
||||||
|
@ -345,7 +372,7 @@ static gboolean
|
||||||
gst_nv_h265_enc_set_encoder_config (GstNvBaseEnc * nvenc,
|
gst_nv_h265_enc_set_encoder_config (GstNvBaseEnc * nvenc,
|
||||||
GstVideoCodecState * state, NV_ENC_CONFIG * config)
|
GstVideoCodecState * state, NV_ENC_CONFIG * config)
|
||||||
{
|
{
|
||||||
GstNvH265Enc *h265enc = GST_NV_H265_ENC (nvenc);
|
GstNvH265Enc *h265enc = (GstNvH265Enc *) nvenc;
|
||||||
GstCaps *allowed_caps, *template_caps;
|
GstCaps *allowed_caps, *template_caps;
|
||||||
GUID selected_profile = NV_ENC_CODEC_PROFILE_AUTOSELECT_GUID;
|
GUID selected_profile = NV_ENC_CODEC_PROFILE_AUTOSELECT_GUID;
|
||||||
int level_idc = NV_ENC_LEVEL_AUTOSELECT;
|
int level_idc = NV_ENC_LEVEL_AUTOSELECT;
|
||||||
|
@ -493,7 +520,7 @@ static gboolean
|
||||||
gst_nv_h265_enc_set_pic_params (GstNvBaseEnc * enc, GstVideoCodecFrame * frame,
|
gst_nv_h265_enc_set_pic_params (GstNvBaseEnc * enc, GstVideoCodecFrame * frame,
|
||||||
NV_ENC_PIC_PARAMS * pic_params)
|
NV_ENC_PIC_PARAMS * pic_params)
|
||||||
{
|
{
|
||||||
GstNvH265Enc *h265enc = GST_NV_H265_ENC (enc);
|
GstNvH265Enc *h265enc = (GstNvH265Enc *) enc;
|
||||||
|
|
||||||
/* encode whole picture in one single slice */
|
/* encode whole picture in one single slice */
|
||||||
pic_params->codecPicParams.hevcPicParams.sliceMode = 0;
|
pic_params->codecPicParams.hevcPicParams.sliceMode = 0;
|
||||||
|
@ -530,3 +557,57 @@ gst_nv_h265_enc_get_property (GObject * object, guint prop_id, GValue * value,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gst_nv_h265_enc_register (GstPlugin * plugin, guint device_id, guint rank,
|
||||||
|
GstCaps * sink_caps, GstCaps * src_caps)
|
||||||
|
{
|
||||||
|
GType parent_type;
|
||||||
|
GType type;
|
||||||
|
gchar *type_name;
|
||||||
|
gchar *feature_name;
|
||||||
|
GstNvH265EncClassData *cdata;
|
||||||
|
gboolean is_default = TRUE;
|
||||||
|
GTypeInfo type_info = {
|
||||||
|
sizeof (GstNvH265EncClass),
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
(GClassInitFunc) gst_nv_h265_enc_class_init,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
sizeof (GstNvH265Enc),
|
||||||
|
0,
|
||||||
|
(GInstanceInitFunc) gst_nv_h265_enc_init,
|
||||||
|
};
|
||||||
|
|
||||||
|
parent_type = gst_nv_base_enc_register ("H265", device_id);
|
||||||
|
|
||||||
|
cdata = g_new0 (GstNvH265EncClassData, 1);
|
||||||
|
cdata->sink_caps = gst_caps_ref (sink_caps);
|
||||||
|
cdata->src_caps = gst_caps_ref (src_caps);
|
||||||
|
type_info.class_data = cdata;
|
||||||
|
|
||||||
|
type_name = g_strdup ("GstNvH265Enc");
|
||||||
|
feature_name = g_strdup ("nvh265enc");
|
||||||
|
|
||||||
|
if (g_type_from_name (type_name) != 0) {
|
||||||
|
g_free (type_name);
|
||||||
|
g_free (feature_name);
|
||||||
|
type_name = g_strdup_printf ("GstNvH265Device%dEnc", device_id);
|
||||||
|
feature_name = g_strdup_printf ("nvh265device%denc", device_id);
|
||||||
|
is_default = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
cdata->is_default = is_default;
|
||||||
|
type = g_type_register_static (parent_type, type_name, &type_info, 0);
|
||||||
|
|
||||||
|
/* make lower rank than default device */
|
||||||
|
if (rank > 0 && !is_default)
|
||||||
|
rank--;
|
||||||
|
|
||||||
|
if (!gst_element_register (plugin, feature_name, rank, type))
|
||||||
|
GST_WARNING ("Failed to register plugin '%s'", type_name);
|
||||||
|
|
||||||
|
g_free (type_name);
|
||||||
|
g_free (feature_name);
|
||||||
|
}
|
||||||
|
|
|
@ -23,19 +23,6 @@
|
||||||
|
|
||||||
#include "gstnvbaseenc.h"
|
#include "gstnvbaseenc.h"
|
||||||
|
|
||||||
#define GST_TYPE_NV_H265_ENC \
|
|
||||||
(gst_nv_h265_enc_get_type())
|
|
||||||
#define GST_NV_H265_ENC(obj) \
|
|
||||||
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_NV_H265_ENC,GstNvH265Enc))
|
|
||||||
#define GST_NV_H265_ENC_CLASS(klass) \
|
|
||||||
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_NV_H265_ENC,GstNvH265EncClass))
|
|
||||||
#define GST_NV_H265_ENC_GET_CLASS(obj) \
|
|
||||||
(G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_NV_H265_ENC,GstNvH265EncClass))
|
|
||||||
#define GST_IS_NV_H265_ENC(obj) \
|
|
||||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_NV_H265_ENC))
|
|
||||||
#define GST_IS_NV_H265_ENC_CLASS(obj) \
|
|
||||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_NV_H265_ENC))
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
GstNvBaseEnc base_nvenc;
|
GstNvBaseEnc base_nvenc;
|
||||||
|
|
||||||
|
@ -48,6 +35,10 @@ typedef struct {
|
||||||
} GstNvH265EncClass;
|
} GstNvH265EncClass;
|
||||||
|
|
||||||
G_GNUC_INTERNAL
|
G_GNUC_INTERNAL
|
||||||
GType gst_nv_h265_enc_get_type (void);
|
void gst_nv_h265_enc_register (GstPlugin * plugin,
|
||||||
|
guint device_id,
|
||||||
|
guint rank,
|
||||||
|
GstCaps * sink_caps,
|
||||||
|
GstCaps * src_caps);
|
||||||
|
|
||||||
#endif /* __GST_NV_HEVC_ENC_H_INCLUDED__ */
|
#endif /* __GST_NV_HEVC_ENC_H_INCLUDED__ */
|
||||||
|
|
Loading…
Reference in a new issue