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:
Seungha Yang 2019-09-03 18:46:30 +09:00
parent f402cb07f9
commit b3b723462e
7 changed files with 230 additions and 134 deletions

View file

@ -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;
} }

View file

@ -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__ */

View file

@ -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");
} }

View file

@ -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);
}

View file

@ -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__ */

View file

@ -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);
}

View file

@ -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__ */