mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-02 12:32:29 +00:00
libs: encoder: get surfaces resolution the same time with formats.
We can get all the information about the video format at one shot when we create the test context for getting the supported formats. The current way to get the width and height ranges are inefficient, since it calls the function gst_vaapi_profile_caps_append_encoder() and it creates another temporal context to detect the resolution information. Signed-off-by: Víctor Manuel Jáquez Leal <vjaquez@igalia.com>
This commit is contained in:
parent
b4d73433c3
commit
a6cf75e8c6
3 changed files with 92 additions and 70 deletions
|
@ -1476,12 +1476,7 @@ create_test_context_config (GstVaapiEncoder * encoder, GstVaapiProfile profile)
|
|||
GstVaapiContextInfo cip = { 0, };
|
||||
GstVaapiContext *ctxt;
|
||||
|
||||
if (encoder->context)
|
||||
return gst_vaapi_context_ref (encoder->context);
|
||||
|
||||
/* if there is no profile, let's figure out one */
|
||||
if (profile == GST_VAAPI_PROFILE_UNKNOWN)
|
||||
profile = get_profile (encoder);
|
||||
g_assert (profile != GST_VAAPI_PROFILE_UNKNOWN);
|
||||
|
||||
cip.profile = profile;
|
||||
cip.entrypoint = gst_vaapi_encoder_get_entrypoint (encoder, profile);
|
||||
|
@ -1499,69 +1494,96 @@ create_test_context_config (GstVaapiEncoder * encoder, GstVaapiProfile profile)
|
|||
return ctxt;
|
||||
}
|
||||
|
||||
static GArray *
|
||||
get_profile_surface_formats (GstVaapiEncoder * encoder, GstVaapiProfile profile)
|
||||
static gboolean
|
||||
get_profile_surface_attributes (GstVaapiEncoder * encoder,
|
||||
GstVaapiProfile profile, GstVaapiConfigSurfaceAttributes * attribs)
|
||||
{
|
||||
GstVaapiContext *ctxt;
|
||||
GArray *formats;
|
||||
GstVaapiContext *ctxt = NULL;
|
||||
gboolean ret;
|
||||
|
||||
g_return_val_if_fail (attribs != NULL, FALSE);
|
||||
g_return_val_if_fail (profile != GST_VAAPI_PROFILE_UNKNOWN, FALSE);
|
||||
|
||||
ctxt = create_test_context_config (encoder, profile);
|
||||
if (!ctxt)
|
||||
return NULL;
|
||||
formats = gst_vaapi_context_get_surface_formats (ctxt);
|
||||
return FALSE;
|
||||
|
||||
ret = gst_vaapi_context_get_surface_attributes (ctxt, attribs);
|
||||
if (ret)
|
||||
attribs->formats = gst_vaapi_context_get_surface_formats (ctxt);
|
||||
|
||||
gst_vaapi_context_unref (ctxt);
|
||||
return formats;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
merge_profile_surface_formats (GstVaapiEncoder * encoder,
|
||||
GstVaapiProfile profile, GArray * formats)
|
||||
merge_profile_surface_attributes (GstVaapiEncoder * encoder,
|
||||
GstVaapiProfile profile, GstVaapiConfigSurfaceAttributes * attribs)
|
||||
{
|
||||
GArray *surface_fmts;
|
||||
GstVaapiConfigSurfaceAttributes attr = { 0, };
|
||||
guint i, j;
|
||||
GstVideoFormat fmt, sfmt;
|
||||
|
||||
if (profile == GST_VAAPI_PROFILE_UNKNOWN)
|
||||
return FALSE;
|
||||
|
||||
surface_fmts = get_profile_surface_formats (encoder, profile);
|
||||
if (!surface_fmts)
|
||||
if (!get_profile_surface_attributes (encoder, profile, &attr))
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < surface_fmts->len; i++) {
|
||||
sfmt = g_array_index (surface_fmts, GstVideoFormat, i);
|
||||
for (j = 0; j < formats->len; j++) {
|
||||
fmt = g_array_index (formats, GstVideoFormat, j);
|
||||
for (i = 0; i < attr.formats->len; i++) {
|
||||
sfmt = g_array_index (attr.formats, GstVideoFormat, i);
|
||||
for (j = 0; j < attribs->formats->len; j++) {
|
||||
fmt = g_array_index (attribs->formats, GstVideoFormat, j);
|
||||
if (fmt == sfmt)
|
||||
break;
|
||||
}
|
||||
if (j >= formats->len)
|
||||
g_array_append_val (formats, sfmt);
|
||||
if (j >= attribs->formats->len)
|
||||
g_array_append_val (attribs->formats, sfmt);
|
||||
}
|
||||
|
||||
g_array_unref (surface_fmts);
|
||||
g_array_unref (attr.formats);
|
||||
|
||||
attribs->min_width = MIN (attribs->min_width, attr.min_width);
|
||||
attribs->min_height = MIN (attribs->min_height, attr.min_height);
|
||||
attribs->max_width = MAX (attribs->max_width, attr.max_width);
|
||||
attribs->max_height = MAX (attribs->max_height, attr.max_height);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_vaapi_encoder_get_surface_formats:
|
||||
* gst_vaapi_encoder_get_surface_attributres:
|
||||
* @encoder: a #GstVaapiEncoder instances
|
||||
* @profile: a #GstVaapiProfile to 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 formats for the current VAConfig
|
||||
* 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.
|
||||
*
|
||||
* Returns: a #GArray of valid formats for the current VAConfig
|
||||
* Returns: a #GArray of valid formats we get or %NULL if failed.
|
||||
**/
|
||||
GArray *
|
||||
gst_vaapi_encoder_get_surface_formats (GstVaapiEncoder * encoder,
|
||||
GstVaapiProfile profile)
|
||||
gst_vaapi_encoder_get_surface_attributes (GstVaapiEncoder * encoder,
|
||||
GstVaapiProfile profile, gint * min_width, gint * min_height,
|
||||
gint * max_width, gint * max_height)
|
||||
{
|
||||
const GstVaapiEncoderClassData *const cdata =
|
||||
GST_VAAPI_ENCODER_GET_CLASS (encoder)->class_data;
|
||||
GArray *profiles, *formats;
|
||||
GstVaapiConfigSurfaceAttributes attribs = {
|
||||
G_MAXINT, G_MAXINT, 1, 1, 0, NULL
|
||||
};
|
||||
GArray *profiles;
|
||||
guint i;
|
||||
|
||||
if (profile || encoder->context)
|
||||
return get_profile_surface_formats (encoder, profile);
|
||||
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 */
|
||||
|
@ -1569,21 +1591,33 @@ gst_vaapi_encoder_get_surface_formats (GstVaapiEncoder * encoder,
|
|||
if (!profiles)
|
||||
return NULL;
|
||||
|
||||
formats = g_array_new (FALSE, FALSE, sizeof (GstVideoFormat));
|
||||
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_formats (encoder, profile, formats)) {
|
||||
g_array_unref (formats);
|
||||
formats = NULL;
|
||||
break;
|
||||
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);
|
||||
|
||||
return formats;
|
||||
if (!attribs.formats)
|
||||
return NULL;
|
||||
|
||||
success:
|
||||
if (min_width)
|
||||
*min_width = attribs.min_width;
|
||||
if (min_height)
|
||||
*min_height = attribs.min_height;
|
||||
if (max_width)
|
||||
*max_width = attribs.max_width;
|
||||
if (max_height)
|
||||
*max_height = attribs.max_height;
|
||||
return attribs.formats;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -181,8 +181,9 @@ GstVaapiEncoderStatus
|
|||
gst_vaapi_encoder_flush (GstVaapiEncoder * encoder);
|
||||
|
||||
GArray *
|
||||
gst_vaapi_encoder_get_surface_formats (GstVaapiEncoder * encoder,
|
||||
GstVaapiProfile profile);
|
||||
gst_vaapi_encoder_get_surface_attributes (GstVaapiEncoder * encoder,
|
||||
GstVaapiProfile profile, gint * min_width, gint * min_height,
|
||||
gint * max_width, gint * max_height);
|
||||
|
||||
GstVaapiProfile
|
||||
gst_vaapi_encoder_get_profile (GstVaapiEncoder * encoder);
|
||||
|
|
|
@ -366,19 +366,6 @@ get_profile (GstVaapiEncode * encode)
|
|||
return GST_VAAPI_PROFILE_UNKNOWN;
|
||||
}
|
||||
|
||||
static GstVaapiEntrypoint
|
||||
get_entrypoint (GstVaapiEncode * encode, GstVaapiProfile profile)
|
||||
{
|
||||
GstVaapiEncoderTune tune = GST_VAAPI_ENCODER_TUNE_NONE;
|
||||
|
||||
g_object_get (encode, "tune", &tune, NULL);
|
||||
if (tune == GST_VAAPI_ENCODER_TUNE_LOW_POWER)
|
||||
return GST_VAAPI_ENTRYPOINT_SLICE_ENCODE_LP;
|
||||
if (profile == GST_VAAPI_PROFILE_JPEG_BASELINE)
|
||||
return GST_VAAPI_ENTRYPOINT_PICTURE_ENCODE;
|
||||
return GST_VAAPI_ENTRYPOINT_SLICE_ENCODE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ensure_allowed_sinkpad_caps (GstVaapiEncode * encode)
|
||||
{
|
||||
|
@ -390,6 +377,7 @@ ensure_allowed_sinkpad_caps (GstVaapiEncode * encode)
|
|||
GstVaapiProfile profile;
|
||||
guint i, size;
|
||||
GstStructure *structure;
|
||||
gint min_width, min_height, max_width, max_height;
|
||||
|
||||
if (encode->allowed_sinkpad_caps)
|
||||
return TRUE;
|
||||
|
@ -397,19 +385,28 @@ ensure_allowed_sinkpad_caps (GstVaapiEncode * encode)
|
|||
return TRUE;
|
||||
|
||||
profile = get_profile (encode);
|
||||
if (profile == GST_VAAPI_PROFILE_UNKNOWN)
|
||||
return TRUE;
|
||||
|
||||
/* First get all supported formats, all these formats should be recognized
|
||||
in video-format map. */
|
||||
formats = gst_vaapi_encoder_get_surface_formats (encode->encoder, profile);
|
||||
formats = gst_vaapi_encoder_get_surface_attributes (encode->encoder, profile,
|
||||
&min_width, &min_height, &max_width, &max_height);
|
||||
if (!formats)
|
||||
goto failed_get_formats;
|
||||
goto failed_get_attributes;
|
||||
|
||||
raw_caps = gst_vaapi_video_format_new_template_caps_from_list (formats);
|
||||
if (!raw_caps)
|
||||
goto failed_create_raw_caps;
|
||||
|
||||
/* Set the width/height info to caps */
|
||||
size = gst_caps_get_size (raw_caps);
|
||||
for (i = 0; i < size; i++) {
|
||||
structure = gst_caps_get_structure (raw_caps, i);
|
||||
if (!structure)
|
||||
continue;
|
||||
gst_structure_set (structure, "width", GST_TYPE_INT_RANGE, min_width,
|
||||
max_width, "height", GST_TYPE_INT_RANGE, min_height, max_height, NULL);
|
||||
}
|
||||
|
||||
va_caps = gst_caps_copy (raw_caps);
|
||||
gst_caps_set_features_simple (va_caps,
|
||||
gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_VAAPI_SURFACE));
|
||||
|
@ -424,16 +421,6 @@ ensure_allowed_sinkpad_caps (GstVaapiEncode * encode)
|
|||
gst_caps_append (out_caps, va_caps);
|
||||
gst_caps_append (out_caps, dma_caps);
|
||||
|
||||
/* Last, set the width/height info to caps */
|
||||
size = gst_caps_get_size (out_caps);
|
||||
for (i = 0; i < size; i++) {
|
||||
structure = gst_caps_get_structure (out_caps, i);
|
||||
if (!structure)
|
||||
continue;
|
||||
gst_vaapi_profile_caps_append_encoder (GST_VAAPI_PLUGIN_BASE_DISPLAY
|
||||
(encode), profile, get_entrypoint (encode, profile), structure);
|
||||
}
|
||||
|
||||
gst_caps_replace (&encode->allowed_sinkpad_caps, out_caps);
|
||||
GST_INFO_OBJECT (encode, "Allowed sink caps %" GST_PTR_FORMAT,
|
||||
encode->allowed_sinkpad_caps);
|
||||
|
@ -452,9 +439,9 @@ bail:
|
|||
g_array_unref (formats);
|
||||
return ret;
|
||||
|
||||
failed_get_formats:
|
||||
failed_get_attributes:
|
||||
{
|
||||
GST_WARNING_OBJECT (encode, "failed to get allowed surface formats");
|
||||
GST_WARNING_OBJECT (encode, "failed to get surface attributes");
|
||||
goto bail;
|
||||
}
|
||||
failed_create_raw_caps:
|
||||
|
|
Loading…
Reference in a new issue