summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHe Junyan <junyan.he@hotmail.com>2019-12-23 14:29:08 +0800
committerVíctor Manuel Jáquez Leal <vjaquez@igalia.com>2020-01-14 11:36:18 +0000
commit36fd4d5d8ad17abdbb0388c2a23b6b786bb9d75f (patch)
tree83f06862003711d642c4313bb64f985eb10b090c
parent67e7e15408dd4077899c533cde2f9e537ff8dc38 (diff)
plugin: encode: List all possible profiles to detect input formats.
The current get_profile just return one possible profile for the encode, which is not enough. For example, if we want to support HEVC 4:4:4 profile, the input of encode should be VYUA rather than NV12 in HEVC main profile. So the command line: gst-launch-1.0 videotestsrc num-buffers=200 ! capsfilter \ caps=video/x-raw,format=VUYA,width=800,height=600 ! vaapih265enc \ tune=low-power init-qp=30 ! fakesink can not work because vaapih265enc just report NV12 in sink caps, we need to specify the profile obviously like: gst-launch-1.0 videotestsrc num-buffers=200 ! capsfilter \ caps=video/x-raw,format=VUYA,width=800,height=600 ! vaapih265enc \ tune=low-power init-qp=30 ! capsfilter caps=video/x-h265, \ profile=main-444 ! fakesink The encode should have the ability to choose the profile based on input format automatically. If the input video format is VUYA, the main-444 profile should be auto choosed. We modify to let get_allowed_profiles of each encode sub class to return an array of all supported profiles based on downstream's allowed caps, or return NULL if no valid profiles specified by downstream. If no allowed profiles found, all profiles which belong to the current encoder's codec will be the candidates. The function gst_vaapi_encoder_get_surface_attributes collects the surface's attributes for that profile list we just get. So for this case, both NV12 and VUYA should be returned. TODO: some codec like VP9, need to implement the get_profile() function.
-rw-r--r--gst-libs/gst/vaapi/gstvaapiencoder.c41
-rw-r--r--gst-libs/gst/vaapi/gstvaapiencoder.h2
-rw-r--r--gst/vaapi/gstvaapiencode.c45
-rw-r--r--gst/vaapi/gstvaapiencode.h4
-rw-r--r--gst/vaapi/gstvaapiencode_h264.c24
-rw-r--r--gst/vaapi/gstvaapiencode_h265.c24
6 files changed, 57 insertions, 83 deletions
diff --git a/gst-libs/gst/vaapi/gstvaapiencoder.c b/gst-libs/gst/vaapi/gstvaapiencoder.c
index b743a5a5..e34db34a 100644
--- a/gst-libs/gst/vaapi/gstvaapiencoder.c
+++ b/gst-libs/gst/vaapi/gstvaapiencoder.c
@@ -1554,61 +1554,44 @@ merge_profile_surface_attributes (GstVaapiEncoder * encoder,
/**
* gst_vaapi_encoder_get_surface_attributres:
* @encoder: a #GstVaapiEncoder instances
- * @profile: a #GstVaapiProfile to test
+ * @profiles: a #GArray of #GstVaapiProfile to be test
* @min_width (out): the minimal surface width
* @min_height (out): the minimal surface height
* @max_width (out): the maximal surface width
* @max_height (out): the maximal surface height
*
- * Fetches the valid surface's attributes for @profile if it is valid,
- * Otherwise, it collects surface's attributes for all profiles which
- * belong to the current encoder's codec.
+ * Fetches the valid surface's attributes for the specified @profiles
*
* Returns: a #GArray of valid formats we get or %NULL if failed.
**/
GArray *
gst_vaapi_encoder_get_surface_attributes (GstVaapiEncoder * encoder,
- GstVaapiProfile profile, gint * min_width, gint * min_height,
+ GArray * profiles, gint * min_width, gint * min_height,
gint * max_width, gint * max_height)
{
- const GstVaapiEncoderClassData *const cdata =
- GST_VAAPI_ENCODER_GET_CLASS (encoder)->class_data;
GstVaapiConfigSurfaceAttributes attribs = {
G_MAXINT, G_MAXINT, 1, 1, 0, NULL
};
- GArray *profiles;
+ GstVaapiProfile profile;
guint i;
- if (profile != GST_VAAPI_PROFILE_UNKNOWN) {
- if (get_profile_surface_attributes (encoder, profile, &attribs))
- goto success;
- return NULL;
- }
-
- /* no specific context neither specific profile, let's iterate among
- * the codec's profiles */
- profiles = gst_vaapi_display_get_encode_profiles (encoder->display);
- if (!profiles)
- return NULL;
-
attribs.formats = g_array_new (FALSE, FALSE, sizeof (GstVideoFormat));
for (i = 0; i < profiles->len; i++) {
profile = g_array_index (profiles, GstVaapiProfile, i);
- if (gst_vaapi_profile_get_codec (profile) == cdata->codec) {
- if (!merge_profile_surface_attributes (encoder, profile, &attribs)) {
- GST_INFO ("Can not get surface formats for profile %s",
- gst_vaapi_profile_get_va_name (profile));
- continue;
- }
+ g_assert (profile != GST_VAAPI_PROFILE_UNKNOWN);
+ GST_LOG ("Detect input formats of profile %s",
+ gst_vaapi_profile_get_va_name (profile));
+
+ if (!merge_profile_surface_attributes (encoder, profile, &attribs)) {
+ GST_INFO ("Can not get surface formats for profile %s",
+ gst_vaapi_profile_get_va_name (profile));
+ continue;
}
}
- g_array_unref (profiles);
-
if (!attribs.formats)
return NULL;
-success:
if (min_width)
*min_width = attribs.min_width;
if (min_height)
diff --git a/gst-libs/gst/vaapi/gstvaapiencoder.h b/gst-libs/gst/vaapi/gstvaapiencoder.h
index fbc81e39..71da2be1 100644
--- a/gst-libs/gst/vaapi/gstvaapiencoder.h
+++ b/gst-libs/gst/vaapi/gstvaapiencoder.h
@@ -182,7 +182,7 @@ gst_vaapi_encoder_flush (GstVaapiEncoder * encoder);
GArray *
gst_vaapi_encoder_get_surface_attributes (GstVaapiEncoder * encoder,
- GstVaapiProfile profile, gint * min_width, gint * min_height,
+ GArray * profiles, gint * min_width, gint * min_height,
gint * max_width, gint * max_height);
GstVaapiProfile
diff --git a/gst/vaapi/gstvaapiencode.c b/gst/vaapi/gstvaapiencode.c
index f19f2213..97e8e61b 100644
--- a/gst/vaapi/gstvaapiencode.c
+++ b/gst/vaapi/gstvaapiencode.c
@@ -340,30 +340,29 @@ gst_vaapiencode_buffer_loop (GstVaapiEncode * encode)
gst_pad_pause_task (GST_VAAPI_PLUGIN_BASE_SRC_PAD (encode));
}
-static GstVaapiProfile
-get_profile (GstVaapiEncode * encode)
+static GArray *
+get_profiles (GstVaapiEncode * encode)
{
GstVaapiEncodeClass *klass = GST_VAAPIENCODE_GET_CLASS (encode);
+ GArray *profiles = NULL;
- if (klass->get_profile) {
- GstVaapiProfile profile = GST_VAAPI_PROFILE_UNKNOWN;
+ if (klass->get_allowed_profiles) {
GstCaps *allowed =
gst_pad_get_allowed_caps (GST_VAAPI_PLUGIN_BASE_SRC_PAD (encode));
+ GST_LOG_OBJECT (encode,
+ "Get allowed sink caps from downstream %" GST_PTR_FORMAT, allowed);
+ if (allowed && !gst_caps_is_empty (allowed) && !gst_caps_is_any (allowed))
+ profiles = klass->get_allowed_profiles (encode, allowed);
- if (allowed) {
- if (!gst_caps_is_empty (allowed) && !gst_caps_is_any (allowed))
- profile = klass->get_profile (allowed);
+ if (allowed)
gst_caps_unref (allowed);
- }
- if (profile != GST_VAAPI_PROFILE_UNKNOWN)
- return profile;
+ if (profiles)
+ return profiles;
}
- if (encode->encoder)
- return gst_vaapi_encoder_get_profile (encode->encoder);
-
- return GST_VAAPI_PROFILE_UNKNOWN;
+ profiles = gst_vaapi_encoder_get_available_profiles (encode->encoder);
+ return profiles;
}
static gboolean
@@ -374,7 +373,7 @@ ensure_allowed_sinkpad_caps (GstVaapiEncode * encode)
GstCaps *va_caps, *dma_caps;
GArray *formats = NULL;
gboolean ret = FALSE;
- GstVaapiProfile profile;
+ GArray *profiles = NULL;
guint i, size;
GstStructure *structure;
gint min_width, min_height, max_width, max_height;
@@ -384,11 +383,14 @@ ensure_allowed_sinkpad_caps (GstVaapiEncode * encode)
if (!encode->encoder)
return TRUE;
- profile = get_profile (encode);
+ /* First, get all possible profiles. */
+ profiles = get_profiles (encode);
+ if (profiles == NULL)
+ goto failed_get_profiles;
- /* First get all supported formats, all these formats should be recognized
+ /* Then get all supported formats, all these formats should be recognized
in video-format map. */
- formats = gst_vaapi_encoder_get_surface_attributes (encode->encoder, profile,
+ formats = gst_vaapi_encoder_get_surface_attributes (encode->encoder, profiles,
&min_width, &min_height, &max_width, &max_height);
if (!formats)
goto failed_get_attributes;
@@ -431,6 +433,8 @@ bail:
if (!encode->allowed_sinkpad_caps)
encode->allowed_sinkpad_caps = gst_caps_new_empty ();
+ if (profiles)
+ g_array_unref (profiles);
if (out_caps)
gst_caps_unref (out_caps);
if (raw_caps)
@@ -449,6 +453,11 @@ failed_create_raw_caps:
GST_WARNING_OBJECT (encode, "failed to create raw sink caps");
goto bail;
}
+failed_get_profiles:
+ {
+ GST_WARNING_OBJECT (encode, "failed to get supported profiles");
+ goto bail;
+ }
}
static GstCaps *
diff --git a/gst/vaapi/gstvaapiencode.h b/gst/vaapi/gstvaapiencode.h
index 2b8eab6d..9f15f1c1 100644
--- a/gst/vaapi/gstvaapiencode.h
+++ b/gst/vaapi/gstvaapiencode.h
@@ -81,7 +81,9 @@ struct _GstVaapiEncodeClass
GstFlowReturn (*alloc_buffer) (GstVaapiEncode * encode,
GstVaapiCodedBuffer * coded_buf,
GstBuffer ** outbuf_ptr);
- GstVaapiProfile (*get_profile) (GstCaps * caps);
+ /* Get all possible profiles based on allowed caps */
+ GArray * (*get_allowed_profiles) (GstVaapiEncode * encode,
+ GstCaps * allowed);
#if USE_H264_FEI_ENCODER
diff --git a/gst/vaapi/gstvaapiencode_h264.c b/gst/vaapi/gstvaapiencode_h264.c
index 018917f8..3a119bcc 100644
--- a/gst/vaapi/gstvaapiencode_h264.c
+++ b/gst/vaapi/gstvaapiencode_h264.c
@@ -128,23 +128,12 @@ gst_vaapiencode_h264_finalize (GObject * object)
G_OBJECT_CLASS (gst_vaapiencode_h264_parent_class)->finalize (object);
}
-static GstVaapiProfile
-gst_vaapiencode_h264_get_profile (GstCaps * caps)
+static GArray *
+gst_vaapiencode_h264_get_allowed_profiles (GstVaapiEncode * encode,
+ GstCaps * allowed)
{
- guint i;
-
- for (i = 0; i < gst_caps_get_size (caps); i++) {
- GstStructure *const structure = gst_caps_get_structure (caps, i);
- const GValue *const value = gst_structure_get_value (structure, "profile");
-
- if (value && G_VALUE_HOLDS_STRING (value)) {
- const gchar *str = g_value_get_string (value);
- if (str)
- return gst_vaapi_utils_h264_get_profile_from_string (str);
- }
- }
-
- return GST_VAAPI_PROFILE_UNKNOWN;
+ return gst_vaapi_h26x_encoder_get_profiles_from_caps (allowed,
+ gst_vaapi_utils_h264_get_profile_from_string);
}
typedef struct
@@ -556,7 +545,8 @@ gst_vaapiencode_h264_class_init (GstVaapiEncodeH264Class * klass)
object_class->set_property = gst_vaapiencode_set_property_subclass;
object_class->get_property = gst_vaapiencode_get_property_subclass;
- encode_class->get_profile = gst_vaapiencode_h264_get_profile;
+ encode_class->get_allowed_profiles =
+ gst_vaapiencode_h264_get_allowed_profiles;
encode_class->set_config = gst_vaapiencode_h264_set_config;
encode_class->get_caps = gst_vaapiencode_h264_get_caps;
encode_class->alloc_encoder = gst_vaapiencode_h264_alloc_encoder;
diff --git a/gst/vaapi/gstvaapiencode_h265.c b/gst/vaapi/gstvaapiencode_h265.c
index 5fb2cfbd..a3325e6a 100644
--- a/gst/vaapi/gstvaapiencode_h265.c
+++ b/gst/vaapi/gstvaapiencode_h265.c
@@ -99,23 +99,12 @@ gst_vaapiencode_h265_finalize (GObject * object)
G_OBJECT_CLASS (gst_vaapiencode_h265_parent_class)->finalize (object);
}
-static GstVaapiProfile
-gst_vaapiencode_h265_get_profile (GstCaps * caps)
+static GArray *
+gst_vaapiencode_h265_get_allowed_profiles (GstVaapiEncode * encode,
+ GstCaps * allowed)
{
- guint i;
-
- for (i = 0; i < gst_caps_get_size (caps); i++) {
- GstStructure *const structure = gst_caps_get_structure (caps, i);
- const GValue *const value = gst_structure_get_value (structure, "profile");
-
- if (value && G_VALUE_HOLDS_STRING (value)) {
- const gchar *str = g_value_get_string (value);
- if (str)
- return gst_vaapi_utils_h265_get_profile_from_string (str);
- }
- }
-
- return GST_VAAPI_PROFILE_UNKNOWN;
+ return gst_vaapi_h26x_encoder_get_profiles_from_caps (allowed,
+ gst_vaapi_utils_h265_get_profile_from_string);
}
typedef struct
@@ -386,7 +375,8 @@ gst_vaapiencode_h265_class_init (GstVaapiEncodeH265Class * klass)
object_class->set_property = gst_vaapiencode_set_property_subclass;
object_class->get_property = gst_vaapiencode_get_property_subclass;
- encode_class->get_profile = gst_vaapiencode_h265_get_profile;
+ encode_class->get_allowed_profiles =
+ gst_vaapiencode_h265_get_allowed_profiles;
encode_class->set_config = gst_vaapiencode_h265_set_config;
encode_class->get_caps = gst_vaapiencode_h265_get_caps;
encode_class->alloc_encoder = gst_vaapiencode_h265_alloc_encoder;