From 21dd66b5e4106fd075e13826eb7999fc4ca81f0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Manuel=20J=C3=A1quez=20Leal?= Date: Thu, 23 Jan 2020 16:56:44 +0100 Subject: [PATCH] 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 --- gst-libs/gst/vaapi/gstvaapicontext.c | 47 ++++++++++++++++++--- gst-libs/gst/vaapi/gstvaapicontext.h | 1 + gst-libs/gst/vaapi/gstvaapisurface.c | 62 ++-------------------------- gst-libs/gst/vaapi/gstvaapisurface.h | 4 -- 4 files changed, 45 insertions(+), 69 deletions(-) diff --git a/gst-libs/gst/vaapi/gstvaapicontext.c b/gst-libs/gst/vaapi/gstvaapicontext.c index 247cb743f7..315f9324a4 100644 --- a/gst-libs/gst/vaapi/gstvaapicontext.c +++ b/gst-libs/gst/vaapi/gstvaapicontext.c @@ -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; } /** diff --git a/gst-libs/gst/vaapi/gstvaapicontext.h b/gst-libs/gst/vaapi/gstvaapicontext.h index 26a1dfdc6c..900fc653f9 100644 --- a/gst-libs/gst/vaapi/gstvaapicontext.h +++ b/gst-libs/gst/vaapi/gstvaapicontext.h @@ -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) diff --git a/gst-libs/gst/vaapi/gstvaapisurface.c b/gst-libs/gst/vaapi/gstvaapisurface.c index 5e2e63f6be..6a4cb6a0b1 100644 --- a/gst-libs/gst/vaapi/gstvaapisurface.c +++ b/gst-libs/gst/vaapi/gstvaapisurface.c @@ -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; diff --git a/gst-libs/gst/vaapi/gstvaapisurface.h b/gst-libs/gst/vaapi/gstvaapisurface.h index 08e5d7de8b..13de604e44 100644 --- a/gst-libs/gst/vaapi/gstvaapisurface.h +++ b/gst-libs/gst/vaapi/gstvaapisurface.h @@ -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);