va: encoder: Rate control property.
authorVíctor Manuel Jáquez Leal <vjaquez@igalia.com>
Sun, 29 May 2022 10:09:05 +0000 (12:09 +0200)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Tue, 7 Jun 2022 12:02:21 +0000 (12:02 +0000)
Fixes: #1241
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2522>

subprojects/gst-plugins-bad/sys/va/gstvaencoder.c
subprojects/gst-plugins-bad/sys/va/gstvaencoder.h
subprojects/gst-plugins-bad/sys/va/gstvah264enc.c

index 30bd452..94f6f72 100644 (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)
+/* 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;
 }
index f1ebf36..dd46fd9 100644 (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,
index 3b9934b..eaf7786 100644 (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);
-
-  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: