va: H264enc: Add encoder for VAEntrypointEncSliceLP.
authorHe Junyan <junyan.he@intel.com>
Mon, 23 May 2022 12:58:47 +0000 (20:58 +0800)
committerVíctor Manuel Jáquez Leal <vjaquez@igalia.com>
Wed, 25 May 2022 20:40:48 +0000 (20:40 +0000)
We name vah264lpenc to support H264's VAEntrypointEncSliceLP encoder.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2472>

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

index ba5a0d7..2b8e77f 100644 (file)
@@ -61,12 +61,14 @@ G_DEFINE_TYPE_WITH_CODE (GstVaBaseEnc, gst_va_base_enc,
 static void
 gst_va_base_enc_reset_state (GstVaBaseEnc * base)
 {
+  GstVaBaseEncClass *klass = GST_VA_BASE_ENC_GET_CLASS (base);
+
   base->frame_duration = GST_CLOCK_TIME_NONE;
 
   base->width = 0;
   base->height = 0;
   base->profile = VAProfileNone;
-  base->entrypoint = 0;
+  base->entrypoint = klass->entrypoint;
   base->rt_format = 0;
   base->codedbuf_size = 0;
 }
@@ -98,7 +100,8 @@ gst_va_base_enc_open (GstVideoEncoder * venc)
   if (!g_atomic_pointer_get (&base->encoder)) {
     GstVaEncoder *va_encoder;
 
-    va_encoder = gst_va_encoder_new (base->display, klass->codec);
+    va_encoder = gst_va_encoder_new (base->display, klass->codec,
+        klass->entrypoint);
     if (va_encoder)
       ret = TRUE;
 
index dd422ed..67378fd 100644 (file)
@@ -88,6 +88,7 @@ struct _GstVaBaseEncClass
                               GstVideoCodecFrame * frame);
 
   GstVaCodecs codec;
+  VAEntrypoint entrypoint;
   gchar *render_device_path;
 
   gpointer _padding[GST_PADDING];
@@ -95,6 +96,7 @@ struct _GstVaBaseEncClass
 
 struct CData
 {
+  VAEntrypoint entrypoint;
   gchar *render_device_path;
   gchar *description;
   GstCaps *sink_caps;
index 442f8cf..8062c6f 100644 (file)
 #include "gstvadisplay_priv.h"
 #include "vacompat.h"
 
-#define VA_ENTRYPOINT_FLAG(entry) (1U << G_PASTE(VAEntrypoint, entry))
-
 typedef struct _GstVaProfileConfig GstVaProfileConfig;
 
 struct _GstVaProfileConfig
 {
   VAProfile profile;
-  guint32 entrypoints;          /* bits map of GstVaapiEntrypoint */
+  guint32 entrypoint;
 };
 
 struct _GstVaEncoder
@@ -133,6 +131,10 @@ gst_va_encoder_set_property (GObject * object, guint prop_id,
       self->display = g_value_dup_object (value);
       break;
     }
+    case PROP_ENTRYPOINT:{
+      self->entrypoint = g_value_get_int (value);
+      break;
+    }
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -404,7 +406,6 @@ gst_va_encoder_open (GstVaEncoder * self, VAProfile profile,
   self->config = config;
   self->context = context;
   self->profile = profile;
-  self->entrypoint = entrypoint;
   self->rt_format = rt_format;
   self->coded_width = coded_width;
   self->coded_height = coded_height;
@@ -466,7 +467,8 @@ gst_va_encoder_class_init (GstVaEncoderClass * klass)
 
   g_properties[PROP_ENTRYPOINT] =
       g_param_spec_int ("va-entrypoint", "VAEntrypoint", "VA Entrypoint",
-      0, 14, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+      0, 14, 0,
+      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
 
   g_properties[PROP_CHROMA] =
       g_param_spec_uint ("va-rt-format", "VARTFormat", "VA RT Fromat or chroma",
@@ -501,7 +503,7 @@ gst_va_encoder_initialize (GstVaEncoder * self, guint32 codec)
     return FALSE;
 
   enc_profiles = gst_va_display_get_profiles (self->display, codec,
-      VAEntrypointEncSlice);
+      self->entrypoint);
 
   if (!enc_profiles)
     return FALSE;
@@ -514,7 +516,7 @@ gst_va_encoder_initialize (GstVaEncoder * self, guint32 codec)
       GstVaProfileConfig config;
 
       config.profile = g_array_index (enc_profiles, VAProfile, i);
-      config.entrypoints = VA_ENTRYPOINT_FLAG (EncSlice);
+      config.entrypoint = self->entrypoint;
       g_array_append_val (self->available_profiles, config);
     }
   }
@@ -528,13 +530,15 @@ gst_va_encoder_initialize (GstVaEncoder * self, guint32 codec)
 }
 
 GstVaEncoder *
-gst_va_encoder_new (GstVaDisplay * display, guint32 codec)
+gst_va_encoder_new (GstVaDisplay * display, guint32 codec,
+    VAEntrypoint entrypoint)
 {
   GstVaEncoder *self;
 
   g_return_val_if_fail (GST_IS_VA_DISPLAY (display), NULL);
 
-  self = g_object_new (GST_TYPE_VA_ENCODER, "display", display, NULL);
+  self = g_object_new (GST_TYPE_VA_ENCODER, "display", display,
+      "va-entrypoint", entrypoint, NULL);
   if (!gst_va_encoder_initialize (self, codec))
     gst_clear_object (&self);
 
@@ -559,7 +563,7 @@ gst_va_encoder_has_profile_and_entrypoint (GstVaEncoder * self,
       if (entrypoint == 0)
         break;
 
-      if (config->entrypoints & (1U << entrypoint))
+      if (config->entrypoint == entrypoint)
         break;
     }
   }
@@ -582,7 +586,7 @@ gst_va_encoder_get_max_slice_num (GstVaEncoder * self,
   if (profile == VAProfileNone)
     return -1;
 
-  if (entrypoint != VAEntrypointEncSlice)
+  if (entrypoint != self->entrypoint)
     return -1;
 
   dpy = gst_va_display_get_va_dpy (self->display);
@@ -616,7 +620,7 @@ gst_va_encoder_get_max_num_reference (GstVaEncoder * self,
   if (profile == VAProfileNone)
     return FALSE;
 
-  if (entrypoint != VAEntrypointEncSlice)
+  if (entrypoint != self->entrypoint)
     return FALSE;
 
   dpy = gst_va_display_get_va_dpy (self->display);
@@ -657,7 +661,7 @@ gst_va_encoder_get_rate_control_mode (GstVaEncoder * self,
   if (profile == VAProfileNone)
     return 0;
 
-  if (entrypoint != VAEntrypointEncSlice)
+  if (entrypoint != self->entrypoint)
     return 0;
 
   dpy = gst_va_display_get_va_dpy (self->display);
@@ -689,7 +693,7 @@ gst_va_encoder_get_quality_level (GstVaEncoder * self,
   if (profile == VAProfileNone)
     return 0;
 
-  if (entrypoint != VAEntrypointEncSlice)
+  if (entrypoint != self->entrypoint)
     return 0;
 
   dpy = gst_va_display_get_va_dpy (self->display);
@@ -721,7 +725,7 @@ gst_va_encoder_has_trellis (GstVaEncoder * self,
   if (profile == VAProfileNone)
     return FALSE;
 
-  if (entrypoint != VAEntrypointEncSlice)
+  if (entrypoint != self->entrypoint)
     return FALSE;
 
   dpy = gst_va_display_get_va_dpy (self->display);
@@ -751,7 +755,7 @@ gst_va_encoder_get_rtformat (GstVaEncoder * self,
   if (profile == VAProfileNone)
     return 0;
 
-  if (entrypoint != VAEntrypointEncSlice)
+  if (entrypoint != self->entrypoint)
     return 0;
 
   dpy = gst_va_display_get_va_dpy (self->display);
@@ -781,7 +785,7 @@ gst_va_encoder_get_packed_headers (GstVaEncoder * self, VAProfile profile,
   if (profile == VAProfileNone)
     return 0;
 
-  if (entrypoint != VAEntrypointEncSlice)
+  if (entrypoint != self->entrypoint)
     return 0;
 
   dpy = gst_va_display_get_va_dpy (self->display);
@@ -884,7 +888,7 @@ _get_codec_caps (GstVaEncoder * self)
   if (!gst_va_encoder_is_open (self)
       && GST_IS_VA_DISPLAY_WRAPPED (self->display)) {
     if (gst_va_caps_from_profiles (self->display, self->available_profiles,
-            VAEntrypointEncSlice, &sinkpad_caps, &srcpad_caps)) {
+            self->entrypoint, &sinkpad_caps, &srcpad_caps)) {
       gst_caps_replace (&self->sinkpad_caps, sinkpad_caps);
       gst_caps_replace (&self->srcpad_caps, srcpad_caps);
       gst_caps_unref (srcpad_caps);
index bb142eb..f1ebf36 100644 (file)
@@ -98,7 +98,8 @@ gboolean              gst_va_encoder_add_packed_header    (GstVaEncoder * self,
                                                            gsize size_in_bits,
                                                            gboolean has_emulation_bytes);
 GstVaEncoder *        gst_va_encoder_new                  (GstVaDisplay * display,
-                                                           guint32 codec);
+                                                           guint32 codec,
+                                                           VAEntrypoint entrypoint);
 GArray *              gst_va_encoder_get_surface_formats  (GstVaEncoder * self);
 GstCaps *             gst_va_encoder_get_sinkpad_caps     (GstVaEncoder * self);
 GstCaps *             gst_va_encoder_get_srcpad_caps      (GstVaEncoder * self);
index 35f3dca..e3bf1ab 100644 (file)
@@ -1372,15 +1372,14 @@ _decide_profile (GstVaH264Enc * self)
       continue;
 
     if (!gst_va_encoder_has_profile_and_entrypoint (base->encoder,
-            profile, VAEntrypointEncSlice))
+            profile, base->entrypoint))
       continue;
 
     if ((rt_format & gst_va_encoder_get_rtformat (base->encoder,
-                profile, VAEntrypointEncSlice)) == 0)
+                profile, base->entrypoint)) == 0)
       continue;
 
     base->profile = profile;
-    base->entrypoint = VAEntrypointEncSlice;
     base->rt_format = rt_format;
     ret = TRUE;
     goto out;
@@ -1396,15 +1395,14 @@ _decide_profile (GstVaH264Enc * self)
       continue;
 
     if (!gst_va_encoder_has_profile_and_entrypoint (base->encoder,
-            profile, VAEntrypointEncSlice))
+            profile, base->entrypoint))
       continue;
 
     if ((rt_format & gst_va_encoder_get_rtformat (base->encoder,
-                profile, VAEntrypointEncSlice)) == 0)
+                profile, base->entrypoint)) == 0)
       continue;
 
     base->profile = profile;
-    base->entrypoint = VAEntrypointEncSlice;
     base->rt_format = rt_format;
     ret = TRUE;
   }
@@ -3238,17 +3236,23 @@ gst_va_h264_enc_class_init (gpointer g_klass, gpointer class_data)
   GstVaBaseEncClass *va_enc_class = GST_VA_BASE_ENC_CLASS (g_klass);
   struct CData *cdata = class_data;
   gchar *long_name;
+  const gchar *name, *desc;
 
-  if (cdata->description) {
-    long_name = g_strdup_printf ("VA-API H.264 Encoder in %s",
-        cdata->description);
+  if (cdata->entrypoint == VAEntrypointEncSlice) {
+    desc = "VA-API based H.264 video encoder";
+    name = "VA-API H.264 Encoder";
   } else {
-    long_name = g_strdup ("VA-API H.264 Encoder");
+    desc = "VA-API based H.264 low power video encoder";
+    name = "VA-API H.264 Low Power Encoder";
   }
 
+  if (cdata->description)
+    long_name = g_strdup_printf ("%s in %s", name, cdata->description);
+  else
+    long_name = g_strdup (name);
+
   gst_element_class_set_metadata (element_class, long_name,
-      "Codec/Encoder/Video/Hardware", "VA-API based H.264 video encoder",
-      "He Junyan <junyan.he@intel.com>");
+      "Codec/Encoder/Video/Hardware", desc, "He Junyan <junyan.he@intel.com>");
 
   sink_doc_caps = gst_caps_from_string (sink_caps_str);
   src_doc_caps = gst_caps_from_string (src_caps_str);
@@ -3256,6 +3260,7 @@ gst_va_h264_enc_class_init (gpointer g_klass, gpointer class_data)
   parent_class = g_type_class_peek_parent (g_klass);
 
   va_enc_class->codec = H264;
+  va_enc_class->entrypoint = cdata->entrypoint;
   va_enc_class->render_device_path = g_strdup (cdata->render_device_path);
 
   sink_pad_templ = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
@@ -3546,7 +3551,8 @@ _complete_src_caps (GstCaps * srccaps)
 
 gboolean
 gst_va_h264_enc_register (GstPlugin * plugin, GstVaDevice * device,
-    GstCaps * sink_caps, GstCaps * src_caps, guint rank)
+    GstCaps * sink_caps, GstCaps * src_caps, guint rank,
+    VAEntrypoint entrypoint)
 {
   static GOnce debug_once = G_ONCE_INIT;
   GType type;
@@ -3564,8 +3570,11 @@ gst_va_h264_enc_register (GstPlugin * plugin, GstVaDevice * device,
   g_return_val_if_fail (GST_IS_VA_DEVICE (device), FALSE);
   g_return_val_if_fail (GST_IS_CAPS (sink_caps), FALSE);
   g_return_val_if_fail (GST_IS_CAPS (src_caps), FALSE);
+  g_return_val_if_fail (entrypoint == VAEntrypointEncSlice ||
+      entrypoint == VAEntrypointEncSliceLP, FALSE);
 
   cdata = g_new (struct CData, 1);
+  cdata->entrypoint = entrypoint;
   cdata->description = NULL;
   cdata->render_device_path = g_strdup (device->render_device_path);
   cdata->sink_caps = gst_caps_ref (sink_caps);
@@ -3578,8 +3587,13 @@ gst_va_h264_enc_register (GstPlugin * plugin, GstVaDevice * device,
       GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED);
 
   type_info.class_data = cdata;
-  type_name = g_strdup ("GstVaH264Enc");
-  feature_name = g_strdup ("vah264enc");
+  if (entrypoint == VAEntrypointEncSlice) {
+    type_name = g_strdup ("GstVaH264Enc");
+    feature_name = g_strdup ("vah264enc");
+  } else {
+    type_name = g_strdup ("GstVaH264LPEnc");
+    feature_name = g_strdup ("vah264lpenc");
+  }
 
   /* The first encoder to be registered should use a constant name,
    * like vah264enc, for any additional encoders, we create unique
@@ -3588,8 +3602,13 @@ gst_va_h264_enc_register (GstPlugin * plugin, GstVaDevice * device,
     gchar *basename = g_path_get_basename (device->render_device_path);
     g_free (type_name);
     g_free (feature_name);
-    type_name = g_strdup_printf ("GstVa%sH264Enc", basename);
-    feature_name = g_strdup_printf ("va%sh264enc", basename);
+    if (entrypoint == VAEntrypointEncSlice) {
+      type_name = g_strdup_printf ("GstVa%sH264Enc", basename);
+      feature_name = g_strdup_printf ("va%sh264enc", basename);
+    } else {
+      type_name = g_strdup_printf ("GstVa%sH264LPEnc", basename);
+      feature_name = g_strdup_printf ("va%sh264lpenc", basename);
+    }
     cdata->description = basename;
     /* lower rank for non-first device */
     if (rank > 0)
index abf97cc..c30efa9 100644 (file)
@@ -29,6 +29,7 @@ gboolean     gst_va_h264_enc_register                (GstPlugin * plugin,
                                                       GstVaDevice * device,
                                                       GstCaps * sink_caps,
                                                       GstCaps * src_caps,
-                                                      guint rank);
+                                                      guint rank,
+                                                      VAEntrypoint entrypoint);
 
 G_END_DECLS
index dc8fbd1..1ca3144 100644 (file)
@@ -182,7 +182,7 @@ plugin_register_encoders (GstPlugin * plugin, GstVaDevice * device,
     switch (codec) {
       case H264:
         if (!gst_va_h264_enc_register (plugin, device, sinkcaps, srccaps,
-                GST_RANK_NONE)) {
+                GST_RANK_NONE, entrypoint)) {
           GST_WARNING ("Failed to register H264 decoder: %s",
               device->render_device_path);
         }
@@ -309,8 +309,7 @@ plugin_register_elements (GstPlugin * plugin, GstVaDevice * device)
 
   plugin_register_decoders (plugin, device, decoders);
   plugin_register_encoders (plugin, device, encoders, VAEntrypointEncSlice);
-  /* @TODO: ignore low power encoders temporarly */
-  /* plugin_register_encoders (plugin, device, encoderslp, VAEntrypointEncSliceLP); */
+  plugin_register_encoders (plugin, device, encoderslp, VAEntrypointEncSliceLP);
   plugin_register_encoders (plugin, device, encodersimg,
       VAEntrypointEncPicture);
   if (has_vpp)