va: encoder: Rate control property.

Fixes: #1241
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2522>
This commit is contained in:
Víctor Manuel Jáquez Leal 2022-05-29 12:09:05 +02:00 committed by GStreamer Marge Bot
parent c287711418
commit e27ad1a273
3 changed files with 119 additions and 46 deletions

View file

@ -1125,35 +1125,80 @@ gst_va_encode_picture_free (GstVaEncodePicture * pic)
g_slice_free (GstVaEncodePicture, pic);
}
/**
* GstVaEncoderRateControl:
*
* Since: 1.22
*/
GType
gst_va_encoder_rate_control_get_type (void)
{
static gsize type = 0;
static const GEnumValue values[] = {
{VA_RC_CBR, "Constant Bitrate", "cbr"},
{VA_RC_VBR, "Variable Bitrate", "vbr"},
{VA_RC_VCM, "Video Conferencing Mode (Non HRD compliant)", "vcm"},
{VA_RC_CQP, "Constant Quantizer", "cqp"},
/* {VA_RC_VBR_CONSTRAINED, "VBR with peak rate higher than average bitrate", */
/* "vbr-constrained"}, */
/* {VA_RC_ICQ, "Intelligent Constant Quality", "icq"}, */
/* {VA_RC_MB, "Macroblock based rate control", "mb"}, */
/* {VA_RC_CFS, "Constant Frame Size", "cfs"}, */
/* {VA_RC_PARALLEL, "Parallel BRC", "parallel"}, */
/* {VA_RC_QVBR, "Quality defined VBR", "qvbr"}, */
/* {VA_RC_AVBR, "Average VBR", "avbr"}, */
{0, NULL, NULL}
};
/* currently supported rate controls */
static const GEnumValue rate_control_map[] = {
{VA_RC_CBR, "Constant Bitrate", "cbr"},
{VA_RC_VBR, "Variable Bitrate", "vbr"},
{VA_RC_VCM, "Video Conferencing Mode (Non HRD compliant)", "vcm"},
{VA_RC_CQP, "Constant Quantizer", "cqp"},
/* {VA_RC_VBR_CONSTRAINED, "VBR with peak rate higher than average bitrate", */
/* "vbr-constrained"}, */
/* {VA_RC_ICQ, "Intelligent Constant Quality", "icq"}, */
/* {VA_RC_MB, "Macroblock based rate control", "mb"}, */
/* {VA_RC_CFS, "Constant Frame Size", "cfs"}, */
/* {VA_RC_PARALLEL, "Parallel BRC", "parallel"}, */
/* {VA_RC_QVBR, "Quality defined VBR", "qvbr"}, */
/* {VA_RC_AVBR, "Average VBR", "avbr"}, */
};
if (g_once_init_enter (&type)) {
GType _type = g_enum_register_static ("GstVaEncoderRateControl", values);
g_once_init_leave (&type, _type);
static gint
_guint32_cmp (gconstpointer a, gconstpointer b)
{
return *((const guint32 *) a) - *((const guint32 *) b);
}
gboolean
gst_va_encoder_get_rate_control_enum (GstVaEncoder * self,
GEnumValue ratectl[16])
{
guint i, j, k = 0;
guint32 rc, rc_prev = 0;
VAProfile profile;
GArray *rcs;
g_return_val_if_fail (GST_IS_VA_ENCODER (self), FALSE);
/* reseve the number of supported rate controls per profile */
rcs = g_array_sized_new (FALSE, FALSE, sizeof (guint32),
G_N_ELEMENTS (rate_control_map) * self->available_profiles->len);
for (i = 0; i < self->available_profiles->len; i++) {
profile = g_array_index (self->available_profiles, VAProfile, i);
rc = gst_va_encoder_get_rate_control_mode (self, profile, self->entrypoint);
if (rc == 0)
continue;
for (j = 0; j < G_N_ELEMENTS (rate_control_map); j++) {
if (rc & rate_control_map[j].value)
rcs = g_array_append_val (rcs, rate_control_map[j].value);
}
}
return type;
if (rcs->len == 0) {
g_clear_pointer (&rcs, g_array_unref);
return FALSE;
}
g_array_sort (rcs, _guint32_cmp);
for (i = 0; i < rcs->len; i++) {
rc = g_array_index (rcs, guint32, i);
if (rc == rc_prev)
continue;
for (j = 0; j < G_N_ELEMENTS (rate_control_map); j++) {
if (rc == rate_control_map[j].value && k < 15)
ratectl[k++] = rate_control_map[j];
}
rc_prev = rc;
}
g_clear_pointer (&rcs, g_array_unref);
if (k == 0)
return FALSE;
/* *INDENT-OFF* */
ratectl[k] = (GEnumValue) { 0, NULL, NULL };
/* *INDENT-ON* */
return TRUE;
}

View file

@ -44,9 +44,6 @@ struct _GstVaEncodePicture
VABufferID coded_buffer;
};
#define GST_TYPE_VA_ENCODER_RATE_CONTROL (gst_va_encoder_rate_control_get_type())
GType gst_va_encoder_rate_control_get_type (void);
gboolean gst_va_encoder_is_open (GstVaEncoder * self);
gboolean gst_va_encoder_open (GstVaEncoder * self,
VAProfile profile,
@ -86,6 +83,8 @@ guint32 gst_va_encoder_get_rtformat (GstVaEncoder * self,
guint32 gst_va_encoder_get_packed_headers (GstVaEncoder * self,
VAProfile profile,
VAEntrypoint entrypoint);
gboolean gst_va_encoder_get_rate_control_enum (GstVaEncoder * self,
GEnumValue ratectl[16]);
gboolean gst_va_encoder_add_param (GstVaEncoder * self,
GstVaEncodePicture * pic,
VABufferType type,

View file

@ -124,6 +124,10 @@ static GstElementClass *parent_class = NULL;
struct _GstVaH264EncClass
{
GstVaBaseEncClass parent_class;
GType rate_control_type;
char rate_control_type_name[34];
GEnumValue rate_control[16];
};
/* *INDENT-ON* */
@ -3230,13 +3234,17 @@ gst_va_h264_enc_class_init (gpointer g_klass, gpointer class_data)
{
GstCaps *src_doc_caps, *sink_doc_caps;
GstPadTemplate *sink_pad_templ, *src_pad_templ;
GObjectClass *const object_class = G_OBJECT_CLASS (g_klass);
GstElementClass *const element_class = GST_ELEMENT_CLASS (g_klass);
GstVideoEncoderClass *const venc_class = GST_VIDEO_ENCODER_CLASS (g_klass);
GObjectClass *object_class = G_OBJECT_CLASS (g_klass);
GstElementClass *element_class = GST_ELEMENT_CLASS (g_klass);
GstVideoEncoderClass *venc_class = GST_VIDEO_ENCODER_CLASS (g_klass);
GstVaBaseEncClass *va_enc_class = GST_VA_BASE_ENC_CLASS (g_klass);
GstVaH264EncClass *vah264enc_class = GST_VA_H264_ENC_CLASS (g_klass);
GstVaDisplay *display;
GstVaEncoder *encoder;
struct CData *cdata = class_data;
gchar *long_name;
const gchar *name, *desc;
gint n_props = N_PROPERTIES;
if (cdata->entrypoint == VAEntrypointEncSlice) {
desc = "VA-API based H.264 video encoder";
@ -3292,6 +3300,27 @@ gst_va_h264_enc_class_init (gpointer g_klass, gpointer class_data)
va_enc_class->prepare_output =
GST_DEBUG_FUNCPTR (gst_va_h264_enc_prepare_output);
{
display =
gst_va_display_drm_new_from_path (va_enc_class->render_device_path);
encoder = gst_va_encoder_new (display, va_enc_class->codec,
va_enc_class->entrypoint);
if (gst_va_encoder_get_rate_control_enum (encoder,
vah264enc_class->rate_control)) {
g_snprintf (vah264enc_class->rate_control_type_name,
G_N_ELEMENTS (vah264enc_class->rate_control_type_name) - 1,
"GstVaEncoderRateControl_%" GST_FOURCC_FORMAT "%s",
GST_FOURCC_ARGS (va_enc_class->codec),
(va_enc_class->entrypoint == VAEntrypointEncSliceLP) ? "_LP" : "");
vah264enc_class->rate_control_type =
g_enum_register_static (vah264enc_class->rate_control_type_name,
vah264enc_class->rate_control);
gst_type_mark_as_plugin_api (vah264enc_class->rate_control_type, 0);
}
gst_object_unref (encoder);
gst_object_unref (display);
}
g_free (long_name);
g_free (cdata->description);
g_free (cdata->render_device_path);
@ -3513,19 +3542,19 @@ gst_va_h264_enc_class_init (gpointer g_klass, gpointer class_data)
"The desired max CPB size in Kb (0: auto-calculate)", 0, 2000 * 1024, 0,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
/**
* GstVaH264Enc:rate-control:
*
* The desired rate control mode for the encoder.
*/
properties[PROP_RATE_CONTROL] = g_param_spec_enum ("rate-control",
"rate control mode", "The desired rate control mode for the encoder",
GST_TYPE_VA_ENCODER_RATE_CONTROL, VA_RC_CBR,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
if (vah264enc_class->rate_control_type > 0) {
properties[PROP_RATE_CONTROL] = g_param_spec_enum ("rate-control",
"rate control mode", "The desired rate control mode for the encoder",
vah264enc_class->rate_control_type,
vah264enc_class->rate_control[0].value,
GST_PARAM_CONDITIONALLY_AVAILABLE | G_PARAM_READWRITE
| G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
} else {
n_props--;
properties[PROP_RATE_CONTROL] = NULL;
}
g_object_class_install_properties (object_class, N_PROPERTIES, properties);
gst_type_mark_as_plugin_api (gst_va_encoder_rate_control_get_type (), 0);
g_object_class_install_properties (object_class, n_props, properties);
/**
* GstVaFeature: