libs: context: select vaCreateSurfaces version according attributes

This commit tries to centralize the selection of vaCreateSurfaces
version, instead of having fallbacks everywhere.

These fallbacks are hacks, added because new drivers use the latest
version of vaCreateSurfaces (with surface attributes) [1], meanwhile
old drivers (or profiles as JPEG decoder in i965) might rather use the
old version.

In order to select which method, there's detected hack: each config
context has a list of valid formats, in the case of JPEG decoder the
list only contains "rare" 4:2:2 formats (ICM3, GRAY8) which aren't
handled correctly by the current gstreamer-vaapi code [2].

The hack consist in identify if the format list contains an arbitrary
preferred format (which is suposedly well supported by
gstreamer-vaapi, mostly NV12). If no prefered colour format is found,
the the old version of vaCreateSurfaces is used, and the surfaces wil
be mapped into a image with their own color format.

1. https://bugzilla.gnome.org/show_bug.cgi?id=797143
2. https://bugzilla.gnome.org/show_bug.cgi?id=797222
This commit is contained in:
Víctor Manuel Jáquez Leal 2020-01-23 16:56:44 +01:00
parent 78c3afea71
commit 21dd66b5e4
4 changed files with 45 additions and 69 deletions

View file

@ -73,6 +73,33 @@ ensure_attributes (GstVaapiContext * context)
return (context->attribs != NULL);
}
/* looks for the (very arbritrary) preferred format from the requested
* context chroma type, in the context attributes */
static GstVideoFormat
get_preferred_format (GstVaapiContext * context)
{
const GstVaapiContextInfo *const cip = &context->info;
GArray *formats;
guint i;
if (context->preferred_format != GST_VIDEO_FORMAT_UNKNOWN)
return context->preferred_format;
if (!ensure_attributes (context) || !context->attribs->formats)
return GST_VIDEO_FORMAT_UNKNOWN;
formats = context->attribs->formats;
for (i = 0; i < formats->len; i++) {
GstVideoFormat format = g_array_index (formats, GstVideoFormat, i);
if (format == gst_vaapi_video_format_from_chroma (cip->chroma_type)) {
context->preferred_format = format;
break;
}
}
return context->preferred_format;
}
static inline gboolean
context_get_attribute (GstVaapiContext * context, VAConfigAttribType type,
guint * out_value_ptr)
@ -88,6 +115,9 @@ context_destroy_surfaces (GstVaapiContext * context)
g_ptr_array_unref (context->surfaces);
context->surfaces = NULL;
}
context->preferred_format = GST_VIDEO_FORMAT_UNKNOWN;
gst_vaapi_video_pool_replace (&context->surfaces_pool, NULL);
}
@ -130,18 +160,22 @@ context_destroy (GstVaapiContext * context)
static gboolean
context_ensure_surfaces (GstVaapiContext * context)
{
GstVaapiDisplay *display = GST_VAAPI_CONTEXT_DISPLAY (context);
const GstVaapiContextInfo *const cip = &context->info;
const guint num_surfaces = cip->ref_frames + SCRATCH_SURFACES_COUNT;
GstVaapiSurface *surface;
GstVideoFormat format;
guint i;
if (!ensure_attributes (context))
return FALSE;
format = get_preferred_format (context);
for (i = context->surfaces->len; i < num_surfaces; i++) {
surface =
gst_vaapi_surface_new_from_formats (GST_VAAPI_CONTEXT_DISPLAY (context),
cip->chroma_type, cip->width, cip->height, context->attribs->formats);
if (format != GST_VIDEO_FORMAT_UNKNOWN) {
surface = gst_vaapi_surface_new_with_format (display, format, cip->width,
cip->height);
} else {
surface = gst_vaapi_surface_new (display, cip->chroma_type, cip->width,
cip->height);
}
if (!surface)
return FALSE;
g_ptr_array_add (context->surfaces, surface);
@ -397,6 +431,7 @@ gst_vaapi_context_init (GstVaapiContext * context,
context->reset_on_resize = TRUE;
context->attribs = NULL;
context->preferred_format = GST_VIDEO_FORMAT_UNKNOWN;
}
/**

View file

@ -115,6 +115,7 @@ struct _GstVaapiContext
GstVaapiVideoPool *surfaces_pool;
gboolean reset_on_resize;
GstVaapiConfigSurfaceAttributes *attribs;
GstVideoFormat preferred_format;
};
#define GST_VAAPI_CONTEXT_ID(context) (((GstVaapiContext *)(context))->object_id)

View file

@ -342,53 +342,6 @@ gst_vaapi_surface_get_display (GstVaapiSurface * surface)
return GST_VAAPI_SURFACE_DISPLAY (surface);
}
/**
* gst_vaapi_surface_new_from_formats:
* @display: a #GstVaapiDisplay
* @chroma_type: the surface chroma format
* @width: the requested surface width
* @height: the requested surface height
* @formats: the limited format list
*
* Creates a new #GstVaapiSurface with a @chroma_type valid for any
* format in @formats; If there aren't any, the returned surface is
* created forcing the passed @chroma_type.
*
* Return value: the newly allocated #GstVaapiSurface object
*/
GstVaapiSurface *
gst_vaapi_surface_new_from_formats (GstVaapiDisplay * display,
GstVaapiChromaType chroma_type, guint width, guint height, GArray * formats)
{
GstVaapiSurface *surface;
guint i;
if (formats) {
for (i = 0; i < formats->len; i++) {
GstVideoFormat format = g_array_index (formats, GstVideoFormat, i);
if (format == gst_vaapi_video_format_from_chroma (chroma_type))
return gst_vaapi_surface_new (display, chroma_type, width, height);
}
}
/* Fallback: if there's no format valid for the chroma type let's
* just use the passed chroma */
surface = gst_vaapi_surface_create (display);
if (!surface)
return NULL;
if (!gst_vaapi_surface_init (surface, chroma_type, width, height))
goto error;
return surface;
/* ERRORS */
error:
{
gst_vaapi_surface_unref (surface);
return NULL;
}
}
/**
* gst_vaapi_surface_new:
* @display: a #GstVaapiDisplay
@ -399,6 +352,9 @@ error:
* Creates a new #GstVaapiSurface with the specified chroma format and
* dimensions.
*
* NOTE: this method for creating surfaces uses deprecated VA API,
* which is still used by drivers (v.gr. i965 for jpeg decoding).
*
* Return value: the newly allocated #GstVaapiSurface object
*/
GstVaapiSurface *
@ -413,18 +369,6 @@ gst_vaapi_surface_new (GstVaapiDisplay * display,
if (!surface)
return NULL;
/* first try a recent version of vaCreateSurface, and later use as
* fallback its old version */
{
GstVideoInfo vi;
GstVideoFormat surface_format;
surface_format = gst_vaapi_video_format_from_chroma (chroma_type);
gst_video_info_set_format (&vi, surface_format, width, height);
if (gst_vaapi_surface_init_full (surface, &vi, 0))
return surface;
}
if (!gst_vaapi_surface_init (surface, chroma_type, width, height))
goto error;
return surface;

View file

@ -206,10 +206,6 @@ gst_vaapi_surface_unref (GstVaapiSurface * surface)
GstVaapiDisplay *
gst_vaapi_surface_get_display (GstVaapiSurface * surface);
GstVaapiSurface *
gst_vaapi_surface_new_from_formats (GstVaapiDisplay * display,
GstVaapiChromaType chroma_type, guint width, guint height, GArray * formts);
GstVaapiSurface *
gst_vaapi_surface_new (GstVaapiDisplay * display,
GstVaapiChromaType chroma_type, guint width, guint height);