mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
nvenc: Add support for weighted prediction option
Note that this property will be exposed only if the device supports the weighted prediction.
This commit is contained in:
parent
d05cbdbd72
commit
ea19a7c715
7 changed files with 134 additions and 13 deletions
|
@ -1311,6 +1311,8 @@ gst_nv_base_enc_set_format (GstVideoEncoder * enc, GstVideoCodecState * state)
|
|||
}
|
||||
}
|
||||
|
||||
params->enableWeightedPrediction = nvenc->weighted_pred;
|
||||
|
||||
if (nvenc->gop_size < 0) {
|
||||
params->encodeConfig->gopLength = NVENC_INFINITE_GOPLENGTH;
|
||||
params->encodeConfig->frameIntervalP = 1;
|
||||
|
@ -2243,22 +2245,33 @@ gst_nv_base_enc_get_property (GObject * object, guint prop_id, GValue * value,
|
|||
}
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
guint cuda_device_id;
|
||||
GstNvEncDeviceCaps device_caps;
|
||||
} GstNvEncClassData;
|
||||
|
||||
static void
|
||||
gst_nv_base_enc_subclass_init (gpointer g_class, gpointer data)
|
||||
{
|
||||
GstNvBaseEncClass *nvbaseenc_class = GST_NV_BASE_ENC_CLASS (g_class);
|
||||
guint device_id = GPOINTER_TO_UINT (data);
|
||||
GstNvEncClassData *cdata = (GstNvEncClassData *) data;
|
||||
|
||||
nvbaseenc_class->cuda_device_id = device_id;
|
||||
nvbaseenc_class->cuda_device_id = cdata->cuda_device_id;
|
||||
nvbaseenc_class->device_caps = cdata->device_caps;
|
||||
|
||||
g_free (cdata);
|
||||
}
|
||||
|
||||
GType
|
||||
gst_nv_base_enc_register (const char *codec, guint device_id)
|
||||
gst_nv_base_enc_register (const char *codec, guint device_id,
|
||||
GstNvEncDeviceCaps * device_caps)
|
||||
{
|
||||
GTypeQuery type_query;
|
||||
GTypeInfo type_info = { 0, };
|
||||
GType subtype;
|
||||
gchar *type_name;
|
||||
GstNvEncClassData *cdata;
|
||||
|
||||
type_name = g_strdup_printf ("GstNvDevice%d%sEnc", device_id, codec);
|
||||
subtype = g_type_from_name (type_name);
|
||||
|
@ -2267,12 +2280,16 @@ gst_nv_base_enc_register (const char *codec, guint device_id)
|
|||
if (subtype)
|
||||
goto done;
|
||||
|
||||
cdata = g_new0 (GstNvEncClassData, 1);
|
||||
cdata->cuda_device_id = device_id;
|
||||
cdata->device_caps = *device_caps;
|
||||
|
||||
g_type_query (GST_TYPE_NV_BASE_ENC, &type_query);
|
||||
memset (&type_info, 0, sizeof (type_info));
|
||||
type_info.class_size = type_query.class_size;
|
||||
type_info.instance_size = type_query.instance_size;
|
||||
type_info.class_init = (GClassInitFunc) gst_nv_base_enc_subclass_init;
|
||||
type_info.class_data = GUINT_TO_POINTER (device_id);
|
||||
type_info.class_data = cdata;
|
||||
|
||||
subtype = g_type_register_static (GST_TYPE_NV_BASE_ENC,
|
||||
type_name, &type_info, 0);
|
||||
|
|
|
@ -58,6 +58,10 @@ typedef enum {
|
|||
GST_NV_RC_MODE_VBR_MINQP,
|
||||
} GstNvRCMode;
|
||||
|
||||
typedef struct {
|
||||
gboolean weighted_prediction;
|
||||
} GstNvEncDeviceCaps;
|
||||
|
||||
typedef struct {
|
||||
GstVideoEncoder video_encoder;
|
||||
|
||||
|
@ -107,6 +111,10 @@ typedef struct {
|
|||
GstVideoInfo input_info; /* buffer configuration for buffers sent to NVENC */
|
||||
|
||||
GstFlowReturn last_flow; /* ATOMIC */
|
||||
|
||||
/*< protected >*/
|
||||
/* device capability dependent properties, set by subclass */
|
||||
gboolean weighted_pred;
|
||||
} GstNvBaseEnc;
|
||||
|
||||
typedef struct {
|
||||
|
@ -114,6 +122,7 @@ typedef struct {
|
|||
|
||||
GUID codec_id;
|
||||
guint cuda_device_id;
|
||||
GstNvEncDeviceCaps device_caps;
|
||||
|
||||
gboolean (*set_src_caps) (GstNvBaseEnc * nvenc,
|
||||
GstVideoCodecState * state);
|
||||
|
@ -129,7 +138,8 @@ G_GNUC_INTERNAL
|
|||
GType gst_nv_base_enc_get_type (void);
|
||||
|
||||
GType gst_nv_base_enc_register (const char * codec,
|
||||
guint device_id);
|
||||
guint device_id,
|
||||
GstNvEncDeviceCaps * device_caps);
|
||||
|
||||
void gst_nv_base_enc_schedule_reconfig (GstNvBaseEnc * nvenc);
|
||||
|
||||
|
|
|
@ -592,6 +592,10 @@ gst_nvenc_get_supported_codec_profiles (gpointer enc, GUID codec_id)
|
|||
return ret;
|
||||
}
|
||||
|
||||
#define DEBUG_DEVICE_CAPS(d,c,caps,s) \
|
||||
GST_DEBUG ("[device-%d %s] %s: %s", \
|
||||
d, c, caps, s ? "supported" : "not supported");
|
||||
|
||||
static void
|
||||
gst_nv_enc_register (GstPlugin * plugin, GUID codec_id, const gchar * codec,
|
||||
guint rank, gint device_count)
|
||||
|
@ -615,6 +619,7 @@ gst_nv_enc_register (GstPlugin * plugin, GUID codec_id, const gchar * codec,
|
|||
GstCaps *src_templ = NULL;
|
||||
gchar *name;
|
||||
gint j;
|
||||
GstNvEncDeviceCaps device_caps = { 0, };
|
||||
|
||||
if (CuDeviceGet (&cuda_device, i) != CUDA_SUCCESS)
|
||||
continue;
|
||||
|
@ -676,6 +681,15 @@ gst_nv_enc_register (GstPlugin * plugin, GUID codec_id, const gchar * codec,
|
|||
max_height = 4096;
|
||||
}
|
||||
|
||||
caps_param.capsToQuery = NV_ENC_CAPS_SUPPORT_WEIGHTED_PREDICTION;
|
||||
if (NvEncGetEncodeCaps (enc, codec_id, &caps_param,
|
||||
&device_caps.weighted_prediction) != NV_ENC_SUCCESS) {
|
||||
device_caps.weighted_prediction = FALSE;
|
||||
}
|
||||
|
||||
DEBUG_DEVICE_CAPS (i,
|
||||
codec, "weighted prediction", device_caps.weighted_prediction);
|
||||
|
||||
interlace_modes = gst_nvenc_get_interlace_modes (enc, codec_id);
|
||||
|
||||
sink_templ = gst_caps_new_empty_simple ("video/x-raw");
|
||||
|
@ -732,9 +746,11 @@ gst_nv_enc_register (GstPlugin * plugin, GUID codec_id, const gchar * codec,
|
|||
|
||||
if (sink_templ && src_templ) {
|
||||
if (gst_nvenc_cmp_guid (codec_id, NV_ENC_CODEC_H264_GUID)) {
|
||||
gst_nv_h264_enc_register (plugin, i, rank, sink_templ, src_templ);
|
||||
gst_nv_h264_enc_register (plugin, i, rank, sink_templ, src_templ,
|
||||
&device_caps);
|
||||
} 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);
|
||||
gst_nv_h265_enc_register (plugin, i, rank, sink_templ, src_templ,
|
||||
&device_caps);
|
||||
} else {
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
|
|
@ -43,9 +43,11 @@ enum
|
|||
{
|
||||
PROP_0,
|
||||
PROP_AUD,
|
||||
PROP_WEIGHTED_PRED,
|
||||
};
|
||||
|
||||
#define DEFAULT_AUD TRUE
|
||||
#define DEFAULT_WEIGHTED_PRED FALSE
|
||||
|
||||
static gboolean gst_nv_h264_enc_open (GstVideoEncoder * enc);
|
||||
static gboolean gst_nv_h264_enc_close (GstVideoEncoder * enc);
|
||||
|
@ -68,6 +70,7 @@ gst_nv_h264_enc_class_init (GstNvH264EncClass * klass, gpointer data)
|
|||
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||
GstVideoEncoderClass *videoenc_class = GST_VIDEO_ENCODER_CLASS (klass);
|
||||
GstNvBaseEncClass *nvenc_class = GST_NV_BASE_ENC_CLASS (klass);
|
||||
GstNvEncDeviceCaps *device_caps = &nvenc_class->device_caps;
|
||||
GstNvH264EncClassData *cdata = (GstNvH264EncClassData *) data;
|
||||
gchar *long_name;
|
||||
|
||||
|
@ -91,6 +94,15 @@ gst_nv_h264_enc_class_init (GstNvH264EncClass * klass, gpointer data)
|
|||
G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
if (device_caps->weighted_prediction) {
|
||||
g_object_class_install_property (gobject_class, PROP_WEIGHTED_PRED,
|
||||
g_param_spec_boolean ("weighted-pred", "Weighted Pred",
|
||||
"Weighted Prediction "
|
||||
"(Exposed only if supported by device)", DEFAULT_WEIGHTED_PRED,
|
||||
G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
}
|
||||
|
||||
if (cdata->is_default)
|
||||
long_name = g_strdup ("NVENC H.264 Video Encoder");
|
||||
else
|
||||
|
@ -123,7 +135,12 @@ gst_nv_h264_enc_class_init (GstNvH264EncClass * klass, gpointer data)
|
|||
static void
|
||||
gst_nv_h264_enc_init (GstNvH264Enc * nvenc)
|
||||
{
|
||||
GstNvBaseEnc *baseenc = GST_NV_BASE_ENC (nvenc);
|
||||
|
||||
nvenc->aud = DEFAULT_AUD;
|
||||
|
||||
/* device capability dependent properties */
|
||||
baseenc->weighted_pred = DEFAULT_WEIGHTED_PRED;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -400,6 +417,9 @@ gst_nv_h264_enc_set_property (GObject * object, guint prop_id,
|
|||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstNvH264Enc *self = (GstNvH264Enc *) object;
|
||||
GstNvBaseEnc *nvenc = GST_NV_BASE_ENC (object);
|
||||
GstNvBaseEncClass *klass = GST_NV_BASE_ENC_GET_CLASS (object);
|
||||
GstNvEncDeviceCaps *device_caps = &klass->device_caps;
|
||||
gboolean reconfig = FALSE;
|
||||
|
||||
switch (prop_id) {
|
||||
|
@ -414,6 +434,14 @@ gst_nv_h264_enc_set_property (GObject * object, guint prop_id,
|
|||
}
|
||||
break;
|
||||
}
|
||||
case PROP_WEIGHTED_PRED:
|
||||
if (!device_caps->weighted_prediction) {
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
} else {
|
||||
nvenc->weighted_pred = g_value_get_boolean (value);
|
||||
reconfig = TRUE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -428,11 +456,21 @@ gst_nv_h264_enc_get_property (GObject * object, guint prop_id, GValue * value,
|
|||
GParamSpec * pspec)
|
||||
{
|
||||
GstNvH264Enc *self = (GstNvH264Enc *) object;
|
||||
GstNvBaseEnc *nvenc = GST_NV_BASE_ENC (object);
|
||||
GstNvBaseEncClass *klass = GST_NV_BASE_ENC_GET_CLASS (object);
|
||||
GstNvEncDeviceCaps *device_caps = &klass->device_caps;
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_AUD:
|
||||
g_value_set_boolean (value, self->aud);
|
||||
break;
|
||||
case PROP_WEIGHTED_PRED:
|
||||
if (!device_caps->weighted_prediction) {
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
} else {
|
||||
g_value_set_boolean (value, nvenc->weighted_pred);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -441,7 +479,7 @@ gst_nv_h264_enc_get_property (GObject * object, guint prop_id, GValue * value,
|
|||
|
||||
void
|
||||
gst_nv_h264_enc_register (GstPlugin * plugin, guint device_id, guint rank,
|
||||
GstCaps * sink_caps, GstCaps * src_caps)
|
||||
GstCaps * sink_caps, GstCaps * src_caps, GstNvEncDeviceCaps * device_caps)
|
||||
{
|
||||
GType parent_type;
|
||||
GType type;
|
||||
|
@ -461,7 +499,7 @@ gst_nv_h264_enc_register (GstPlugin * plugin, guint device_id, guint rank,
|
|||
(GInstanceInitFunc) gst_nv_h264_enc_init,
|
||||
};
|
||||
|
||||
parent_type = gst_nv_base_enc_register ("H264", device_id);
|
||||
parent_type = gst_nv_base_enc_register ("H264", device_id, device_caps);
|
||||
|
||||
cdata = g_new0 (GstNvH264EncClassData, 1);
|
||||
cdata->sink_caps = gst_caps_ref (sink_caps);
|
||||
|
|
|
@ -37,7 +37,8 @@ void gst_nv_h264_enc_register (GstPlugin * plugin,
|
|||
guint device_id,
|
||||
guint rank,
|
||||
GstCaps * sink_caps,
|
||||
GstCaps * src_caps);
|
||||
GstCaps * src_caps,
|
||||
GstNvEncDeviceCaps * device_caps);
|
||||
|
||||
|
||||
#endif /* __GST_NV_H264_ENC_H_INCLUDED__ */
|
||||
|
|
|
@ -45,9 +45,11 @@ enum
|
|||
{
|
||||
PROP_0,
|
||||
PROP_AUD,
|
||||
PROP_WEIGHTED_PRED,
|
||||
};
|
||||
|
||||
#define DEFAULT_AUD TRUE
|
||||
#define DEFAULT_WEIGHTED_PRED FALSE
|
||||
|
||||
static gboolean gst_nv_h265_enc_open (GstVideoEncoder * enc);
|
||||
static gboolean gst_nv_h265_enc_close (GstVideoEncoder * enc);
|
||||
|
@ -71,6 +73,7 @@ gst_nv_h265_enc_class_init (GstNvH265EncClass * klass, gpointer data)
|
|||
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||
GstVideoEncoderClass *videoenc_class = GST_VIDEO_ENCODER_CLASS (klass);
|
||||
GstNvBaseEncClass *nvenc_class = GST_NV_BASE_ENC_CLASS (klass);
|
||||
GstNvEncDeviceCaps *device_caps = &nvenc_class->device_caps;
|
||||
GstNvH265EncClassData *cdata = (GstNvH265EncClassData *) data;
|
||||
gchar *long_name;
|
||||
|
||||
|
@ -95,6 +98,15 @@ gst_nv_h265_enc_class_init (GstNvH265EncClass * klass, gpointer data)
|
|||
G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
if (device_caps->weighted_prediction) {
|
||||
g_object_class_install_property (gobject_class, PROP_WEIGHTED_PRED,
|
||||
g_param_spec_boolean ("weighted-pred", "Weighted Pred",
|
||||
"Weighted Prediction "
|
||||
"(Exposed only if supported by device)", DEFAULT_WEIGHTED_PRED,
|
||||
G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
}
|
||||
|
||||
if (cdata->is_default)
|
||||
long_name = g_strdup ("NVENC HEVC Video Encoder");
|
||||
else
|
||||
|
@ -127,7 +139,12 @@ gst_nv_h265_enc_class_init (GstNvH265EncClass * klass, gpointer data)
|
|||
static void
|
||||
gst_nv_h265_enc_init (GstNvH265Enc * nvenc)
|
||||
{
|
||||
GstNvBaseEnc *baseenc = GST_NV_BASE_ENC (nvenc);
|
||||
|
||||
nvenc->aud = DEFAULT_AUD;
|
||||
|
||||
/* device capability dependent properties */
|
||||
baseenc->weighted_pred = DEFAULT_WEIGHTED_PRED;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -555,6 +572,9 @@ gst_nv_h265_enc_set_property (GObject * object, guint prop_id,
|
|||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstNvH265Enc *self = (GstNvH265Enc *) object;
|
||||
GstNvBaseEnc *nvenc = GST_NV_BASE_ENC (object);
|
||||
GstNvBaseEncClass *klass = GST_NV_BASE_ENC_GET_CLASS (object);
|
||||
GstNvEncDeviceCaps *device_caps = &klass->device_caps;
|
||||
gboolean reconfig = FALSE;
|
||||
|
||||
switch (prop_id) {
|
||||
|
@ -569,6 +589,14 @@ gst_nv_h265_enc_set_property (GObject * object, guint prop_id,
|
|||
}
|
||||
break;
|
||||
}
|
||||
case PROP_WEIGHTED_PRED:
|
||||
if (!device_caps->weighted_prediction) {
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
} else {
|
||||
nvenc->weighted_pred = g_value_get_boolean (value);
|
||||
reconfig = TRUE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -583,11 +611,21 @@ gst_nv_h265_enc_get_property (GObject * object, guint prop_id, GValue * value,
|
|||
GParamSpec * pspec)
|
||||
{
|
||||
GstNvH265Enc *self = (GstNvH265Enc *) object;
|
||||
GstNvBaseEnc *nvenc = GST_NV_BASE_ENC (object);
|
||||
GstNvBaseEncClass *klass = GST_NV_BASE_ENC_GET_CLASS (object);
|
||||
GstNvEncDeviceCaps *device_caps = &klass->device_caps;
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_AUD:
|
||||
g_value_set_boolean (value, self->aud);
|
||||
break;
|
||||
case PROP_WEIGHTED_PRED:
|
||||
if (!device_caps->weighted_prediction) {
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
} else {
|
||||
g_value_set_boolean (value, nvenc->weighted_pred);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -596,7 +634,7 @@ gst_nv_h265_enc_get_property (GObject * object, guint prop_id, GValue * value,
|
|||
|
||||
void
|
||||
gst_nv_h265_enc_register (GstPlugin * plugin, guint device_id, guint rank,
|
||||
GstCaps * sink_caps, GstCaps * src_caps)
|
||||
GstCaps * sink_caps, GstCaps * src_caps, GstNvEncDeviceCaps * device_caps)
|
||||
{
|
||||
GType parent_type;
|
||||
GType type;
|
||||
|
@ -616,7 +654,7 @@ gst_nv_h265_enc_register (GstPlugin * plugin, guint device_id, guint rank,
|
|||
(GInstanceInitFunc) gst_nv_h265_enc_init,
|
||||
};
|
||||
|
||||
parent_type = gst_nv_base_enc_register ("H265", device_id);
|
||||
parent_type = gst_nv_base_enc_register ("H265", device_id, device_caps);
|
||||
|
||||
cdata = g_new0 (GstNvH265EncClassData, 1);
|
||||
cdata->sink_caps = gst_caps_ref (sink_caps);
|
||||
|
|
|
@ -42,6 +42,7 @@ void gst_nv_h265_enc_register (GstPlugin * plugin,
|
|||
guint device_id,
|
||||
guint rank,
|
||||
GstCaps * sink_caps,
|
||||
GstCaps * src_caps);
|
||||
GstCaps * src_caps,
|
||||
GstNvEncDeviceCaps * device_caps);
|
||||
|
||||
#endif /* __GST_NV_HEVC_ENC_H_INCLUDED__ */
|
||||
|
|
Loading…
Reference in a new issue