From e27ad1a273a9613d31d4c6eadbc7e221f21f8028 Mon Sep 17 00:00:00 2001 From: =?utf8?q?V=C3=ADctor=20Manuel=20J=C3=A1quez=20Leal?= Date: Sun, 29 May 2022 12:09:05 +0200 Subject: [PATCH] va: encoder: Rate control property. Fixes: #1241 Part-of: --- subprojects/gst-plugins-bad/sys/va/gstvaencoder.c | 99 ++++++++++++++++------- subprojects/gst-plugins-bad/sys/va/gstvaencoder.h | 5 +- subprojects/gst-plugins-bad/sys/va/gstvah264enc.c | 59 ++++++++++---- 3 files changed, 118 insertions(+), 45 deletions(-) diff --git a/subprojects/gst-plugins-bad/sys/va/gstvaencoder.c b/subprojects/gst-plugins-bad/sys/va/gstvaencoder.c index 30bd452..94f6f72 100644 --- a/subprojects/gst-plugins-bad/sys/va/gstvaencoder.c +++ b/subprojects/gst-plugins-bad/sys/va/gstvaencoder.c @@ -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) +/* 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"}, */ +}; + +static gint +_guint32_cmp (gconstpointer a, gconstpointer b) { - 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} - }; + 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; - if (g_once_init_enter (&type)) { - GType _type = g_enum_register_static ("GstVaEncoderRateControl", values); - g_once_init_leave (&type, _type); + 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); + } + } + + if (rcs->len == 0) { + g_clear_pointer (&rcs, g_array_unref); + return FALSE; } - return type; + 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; } diff --git a/subprojects/gst-plugins-bad/sys/va/gstvaencoder.h b/subprojects/gst-plugins-bad/sys/va/gstvaencoder.h index f1ebf36..dd46fd9 100644 --- a/subprojects/gst-plugins-bad/sys/va/gstvaencoder.h +++ b/subprojects/gst-plugins-bad/sys/va/gstvaencoder.h @@ -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, diff --git a/subprojects/gst-plugins-bad/sys/va/gstvah264enc.c b/subprojects/gst-plugins-bad/sys/va/gstvah264enc.c index 3b9934b..eaf7786 100644 --- a/subprojects/gst-plugins-bad/sys/va/gstvah264enc.c +++ b/subprojects/gst-plugins-bad/sys/va/gstvah264enc.c @@ -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); - - g_object_class_install_properties (object_class, N_PROPERTIES, properties); + 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; + } - 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: -- 2.7.4