From 2042c2d4f0b99d2557c4a7e421cf444e258fbe7d Mon Sep 17 00:00:00 2001 From: He Junyan Date: Mon, 23 May 2022 20:58:47 +0800 Subject: [PATCH] va: H264enc: Add encoder for VAEntrypointEncSliceLP. We name vah264lpenc to support H264's VAEntrypointEncSliceLP encoder. Part-of: --- subprojects/gst-plugins-bad/sys/va/gstvabaseenc.c | 7 ++- subprojects/gst-plugins-bad/sys/va/gstvabaseenc.h | 2 + subprojects/gst-plugins-bad/sys/va/gstvaencoder.c | 40 +++++++++-------- subprojects/gst-plugins-bad/sys/va/gstvaencoder.h | 3 +- subprojects/gst-plugins-bad/sys/va/gstvah264enc.c | 53 +++++++++++++++-------- subprojects/gst-plugins-bad/sys/va/gstvah264enc.h | 3 +- subprojects/gst-plugins-bad/sys/va/plugin.c | 5 +-- 7 files changed, 71 insertions(+), 42 deletions(-) diff --git a/subprojects/gst-plugins-bad/sys/va/gstvabaseenc.c b/subprojects/gst-plugins-bad/sys/va/gstvabaseenc.c index ba5a0d7..2b8e77f 100644 --- a/subprojects/gst-plugins-bad/sys/va/gstvabaseenc.c +++ b/subprojects/gst-plugins-bad/sys/va/gstvabaseenc.c @@ -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; diff --git a/subprojects/gst-plugins-bad/sys/va/gstvabaseenc.h b/subprojects/gst-plugins-bad/sys/va/gstvabaseenc.h index dd422ed..67378fd 100644 --- a/subprojects/gst-plugins-bad/sys/va/gstvabaseenc.h +++ b/subprojects/gst-plugins-bad/sys/va/gstvabaseenc.h @@ -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; diff --git a/subprojects/gst-plugins-bad/sys/va/gstvaencoder.c b/subprojects/gst-plugins-bad/sys/va/gstvaencoder.c index 442f8cf..8062c6f 100644 --- a/subprojects/gst-plugins-bad/sys/va/gstvaencoder.c +++ b/subprojects/gst-plugins-bad/sys/va/gstvaencoder.c @@ -29,14 +29,12 @@ #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); diff --git a/subprojects/gst-plugins-bad/sys/va/gstvaencoder.h b/subprojects/gst-plugins-bad/sys/va/gstvaencoder.h index bb142eb..f1ebf36 100644 --- a/subprojects/gst-plugins-bad/sys/va/gstvaencoder.h +++ b/subprojects/gst-plugins-bad/sys/va/gstvaencoder.h @@ -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); diff --git a/subprojects/gst-plugins-bad/sys/va/gstvah264enc.c b/subprojects/gst-plugins-bad/sys/va/gstvah264enc.c index 35f3dca..e3bf1ab 100644 --- a/subprojects/gst-plugins-bad/sys/va/gstvah264enc.c +++ b/subprojects/gst-plugins-bad/sys/va/gstvah264enc.c @@ -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 "); + "Codec/Encoder/Video/Hardware", desc, "He Junyan "); 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) diff --git a/subprojects/gst-plugins-bad/sys/va/gstvah264enc.h b/subprojects/gst-plugins-bad/sys/va/gstvah264enc.h index abf97cc..c30efa9 100644 --- a/subprojects/gst-plugins-bad/sys/va/gstvah264enc.h +++ b/subprojects/gst-plugins-bad/sys/va/gstvah264enc.h @@ -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 diff --git a/subprojects/gst-plugins-bad/sys/va/plugin.c b/subprojects/gst-plugins-bad/sys/va/plugin.c index dc8fbd1..1ca31446 100644 --- a/subprojects/gst-plugins-bad/sys/va/plugin.c +++ b/subprojects/gst-plugins-bad/sys/va/plugin.c @@ -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) -- 2.7.4