From e962069dbe15fb7cfedced1b325de6dc758bf190 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Manuel=20J=C3=A1quez=20Leal?= Date: Tue, 21 Jul 2020 20:14:57 +0200 Subject: [PATCH] vaapidecode: merge common profiles before setting size range The synthetic profiles, such as H264 baseline, H265 intra, etc. are added at the end of processing all available VA profiles. This generated an non-optimal caps for negotiation, since the synthetic profiles don't have frame size ranges. This patch adds those possible synthetic profiles when the associated profile is processed, with its frame size ranges. Now allowed sink caps are simpler. Part-of: --- gst/vaapi/gstvaapidecode.c | 142 +++++++++++++++------------------ gst/vaapi/gstvaapipluginutil.c | 31 +++++++ gst/vaapi/gstvaapipluginutil.h | 4 + 3 files changed, 100 insertions(+), 77 deletions(-) diff --git a/gst/vaapi/gstvaapidecode.c b/gst/vaapi/gstvaapidecode.c index 2796ab147b..0f631e707c 100644 --- a/gst/vaapi/gstvaapidecode.c +++ b/gst/vaapi/gstvaapidecode.c @@ -1170,14 +1170,18 @@ is_svc_profile (GstVaapiProfile profile) || profile == GST_VAAPI_PROFILE_H264_SCALABLE_HIGH; } - -static GstCaps * -add_h264_profile_in_caps (GstCaps * caps, const gchar * profile_name) +static void +find_mvc_and_svc (GArray * profiles, gboolean * have_mvc, gboolean * have_svc) { - GstCaps *caps_new = - gst_caps_new_simple ("video/x-h264", "profile", G_TYPE_STRING, - profile_name, NULL); - return gst_caps_merge (caps_new, caps); + guint i; + + for (i = 0; i < profiles->len; i++) { + const GstVaapiProfile profile = + g_array_index (profiles, GstVaapiProfile, i); + + *have_mvc |= is_mvc_profile (profile); + *have_svc |= is_svc_profile (profile); + } } static gboolean @@ -1189,7 +1193,6 @@ gst_vaapidecode_ensure_allowed_sinkpad_caps (GstVaapiDecode * decode) GstVaapiDisplay *const display = GST_VAAPI_PLUGIN_BASE_DISPLAY (decode); guint i; gboolean base_only = FALSE; - gboolean have_high = FALSE; gboolean have_mvc = FALSE; gboolean have_svc = FALSE; @@ -1205,6 +1208,8 @@ gst_vaapidecode_ensure_allowed_sinkpad_caps (GstVaapiDecode * decode) g_object_get (decode, "base-only", &base_only, NULL); } + find_mvc_and_svc (profiles, &have_mvc, &have_svc); + for (i = 0; i < profiles->len; i++) { const GstVaapiProfile profile = g_array_index (profiles, GstVaapiProfile, i); @@ -1224,84 +1229,67 @@ gst_vaapidecode_ensure_allowed_sinkpad_caps (GstVaapiDecode * decode) continue; profile_name = gst_vaapi_profile_get_name (profile); - if (profile_name) { - /* Add all according -intra profile for HEVC */ - if (profile == GST_VAAPI_PROFILE_H265_MAIN - || profile == GST_VAAPI_PROFILE_H265_MAIN10 - || profile == GST_VAAPI_PROFILE_H265_MAIN_422_10 - || profile == GST_VAAPI_PROFILE_H265_MAIN_444 - || profile == GST_VAAPI_PROFILE_H265_MAIN_444_10 - || profile == GST_VAAPI_PROFILE_H265_MAIN12) { - GValue list_value = G_VALUE_INIT; - GValue value = G_VALUE_INIT; - gchar *intra_name; + if (!profile_name) + continue; - g_value_init (&list_value, GST_TYPE_LIST); - g_value_init (&value, G_TYPE_STRING); - g_value_set_string (&value, profile_name); - gst_value_list_append_value (&list_value, &value); + /* Add all according -intra profile for HEVC */ + if (profile == GST_VAAPI_PROFILE_H265_MAIN + || profile == GST_VAAPI_PROFILE_H265_MAIN10 + || profile == GST_VAAPI_PROFILE_H265_MAIN_422_10 + || profile == GST_VAAPI_PROFILE_H265_MAIN_444 + || profile == GST_VAAPI_PROFILE_H265_MAIN_444_10 + || profile == GST_VAAPI_PROFILE_H265_MAIN12) { + gchar *profiles[3], *intra_name; - intra_name = g_strdup_printf ("%s-intra", profile_name); - g_value_take_string (&value, intra_name); - gst_value_list_append_value (&list_value, &value); + intra_name = g_strdup_printf ("%s-intra", profile_name); - gst_structure_set_value (structure, "profile", &list_value); - g_value_unset (&list_value); - g_value_unset (&value); - } else { - gst_structure_set (structure, "profile", G_TYPE_STRING, - profile_name, NULL); + profiles[0] = (gchar *) profile_name; + profiles[1] = intra_name; + profiles[2] = NULL; + + gst_vaapi_structure_set_profiles (structure, profiles); + g_free (intra_name); + + } else if (profile == GST_VAAPI_PROFILE_H264_CONSTRAINED_BASELINE) { + /* XXX: artificially adding baseline if constrained_baseline is + * available. */ + gchar *profiles[] = { (gchar *) profile_name, "baseline", NULL }; + + gst_vaapi_structure_set_profiles (structure, profiles); + } else if (profile == GST_VAAPI_PROFILE_H264_HIGH) { + gchar *profiles[11] = { (gchar *) profile_name, "progressive-high", + "constrained-high" + }; + gint i = 3; + + if (base_only && !have_mvc) { + GST_DEBUG ("base_only: force adding MVC profiles in caps"); + + profiles[i++] = "multiview-high"; + profiles[i++] = "stereo-high"; } + + if (base_only && !have_svc) { + GST_DEBUG ("base_only: force adding SVC profiles in caps"); + + profiles[i++] = "scalable-constrained-baseline"; + profiles[i++] = "scalable-baseline"; + profiles[i++] = "scalable-high-intra"; + profiles[i++] = "scalable-constrained-high"; + profiles[i++] = "scalable-high"; + } + + profiles[i++] = NULL; + + gst_vaapi_structure_set_profiles (structure, profiles); + } else { + gst_structure_set (structure, "profile", G_TYPE_STRING, + profile_name, NULL); } gst_vaapi_profile_caps_append_decoder (display, profile, structure); allowed_sinkpad_caps = gst_caps_merge (allowed_sinkpad_caps, caps); - have_mvc |= is_mvc_profile (profile); - have_svc |= is_svc_profile (profile); - have_high |= profile == GST_VAAPI_PROFILE_H264_HIGH; - - /* XXX: artificially adding baseline if constrained_baseline is - * available. */ - if (profile == GST_VAAPI_PROFILE_H264_CONSTRAINED_BASELINE) - allowed_sinkpad_caps = - add_h264_profile_in_caps (allowed_sinkpad_caps, "baseline"); - } - - if (have_high) { - allowed_sinkpad_caps = - add_h264_profile_in_caps (allowed_sinkpad_caps, "progressive-high"); - allowed_sinkpad_caps = - add_h264_profile_in_caps (allowed_sinkpad_caps, "constrained-high"); - } - - if (base_only && (!have_mvc || !have_svc) && have_high) { - if (!have_mvc) { - GST_DEBUG ("base_only: force adding MVC profiles in caps"); - - allowed_sinkpad_caps = - add_h264_profile_in_caps (allowed_sinkpad_caps, "multiview-high"); - allowed_sinkpad_caps = - add_h264_profile_in_caps (allowed_sinkpad_caps, "stereo-high"); - } - - if (!have_svc) { - GST_DEBUG ("base_only: force adding SVC profiles in caps"); - - allowed_sinkpad_caps = - add_h264_profile_in_caps (allowed_sinkpad_caps, - "scalable-constrained-baseline"); - allowed_sinkpad_caps = - add_h264_profile_in_caps (allowed_sinkpad_caps, "scalable-baseline"); - allowed_sinkpad_caps = - add_h264_profile_in_caps (allowed_sinkpad_caps, - "scalable-high-intra"); - allowed_sinkpad_caps = - add_h264_profile_in_caps (allowed_sinkpad_caps, - "scalable-constrained-high"); - allowed_sinkpad_caps = - add_h264_profile_in_caps (allowed_sinkpad_caps, "scalable-high"); - } } caps = gst_pad_get_pad_template_caps (sinkpad); diff --git a/gst/vaapi/gstvaapipluginutil.c b/gst/vaapi/gstvaapipluginutil.c index c558138a3b..ece8a683b7 100644 --- a/gst/vaapi/gstvaapipluginutil.c +++ b/gst/vaapi/gstvaapipluginutil.c @@ -1244,3 +1244,34 @@ out: return out_caps; } + +/** + * gst_vaapi_structure_set_profiles: + * @st: a #GstStructure + * @list: a %NULL-terminated array of strings + * + * The @list of profiles are set in @st + **/ +void +gst_vaapi_structure_set_profiles (GstStructure * st, gchar ** list) +{ + guint i; + GValue vlist = G_VALUE_INIT; + GValue value = G_VALUE_INIT; + + g_value_init (&vlist, GST_TYPE_LIST); + g_value_init (&value, G_TYPE_STRING); + + for (i = 0; list[i]; i++) { + g_value_set_string (&value, list[i]); + gst_value_list_append_value (&vlist, &value); + } + + if (i == 1) + gst_structure_set_value (st, "profile", &value); + else if (i > 1) + gst_structure_set_value (st, "profile", &vlist); + + g_value_unset (&value); + g_value_unset (&vlist); +} diff --git a/gst/vaapi/gstvaapipluginutil.h b/gst/vaapi/gstvaapipluginutil.h index abdaf1e95f..cad6b8719e 100644 --- a/gst/vaapi/gstvaapipluginutil.h +++ b/gst/vaapi/gstvaapipluginutil.h @@ -171,4 +171,8 @@ GstCaps * gst_vaapi_build_template_caps_by_codec (GstVaapiDisplay * display, GstVaapiContextUsage usage, GstVaapiCodec codec, GArray * extra_fmts); +G_GNUC_INTERNAL +void +gst_vaapi_structure_set_profiles (GstStructure * st, gchar ** list); + #endif /* GST_VAAPI_PLUGIN_UTIL_H */