From 338745c6f4b7133d7b36f78562d46bc4e8d368f5 Mon Sep 17 00:00:00 2001 From: Thong Thai Date: Sat, 15 Aug 2020 14:36:45 -0400 Subject: [PATCH] frontends/va: Derive image from interlaced buffers in some cases Add an allowlist to make an exception when deriving images from interlaced buffers. Normally, the function should fail if the surface needs to be modified to derive the image. But some applications do not follow the fall-back method of using vaCreateImage + vaPutImage as mentioned in the VAAPI documentation, so we have to make an exception. Signed-off-by: Thong Thai Reviewed-by: Leo Liu Part-of: --- src/gallium/frontends/va/image.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/gallium/frontends/va/image.c b/src/gallium/frontends/va/image.c index 3d6e091..8c0f03e 100644 --- a/src/gallium/frontends/va/image.c +++ b/src/gallium/frontends/va/image.c @@ -32,6 +32,7 @@ #include "util/u_handle_table.h" #include "util/u_surface.h" #include "util/u_video.h" +#include "util/u_process.h" #include "vl/vl_winsys.h" #include "vl/vl_video_buffer.h" @@ -208,6 +209,17 @@ vlVaDeriveImage(VADriverContextP ctx, VASurfaceID surface, VAImage *image) unsigned stride = 0; unsigned offset = 0; + /* This function is used by some programs to test for hardware decoding, but on + * AMD devices, the buffers default to interlaced, which causes this function to fail. + * Some programs expect this function to fail, while others, assume this means + * hardware acceleration is not available and give up without trying the fall-back + * vaCreateImage + vaPutImage + */ + const char *proc = util_get_process_name(); + const char *derive_interlaced_allowlist[] = { + "vlc", + }; + if (!ctx) return VA_STATUS_ERROR_INVALID_CONTEXT; @@ -226,6 +238,15 @@ vlVaDeriveImage(VADriverContextP ctx, VASurfaceID surface, VAImage *image) if (!surf || !surf->buffer) return VA_STATUS_ERROR_INVALID_SURFACE; + if (surf->buffer->interlaced) { + for (i = 0; i < ARRAY_SIZE(derive_interlaced_allowlist); i++) + if ((strcmp(derive_interlaced_allowlist[i], proc) == 0)) + break; + + if (i >= ARRAY_SIZE(derive_interlaced_allowlist)) + return VA_STATUS_ERROR_OPERATION_FAILED; + } + surfaces = surf->buffer->get_surfaces(surf->buffer); if (!surfaces || !surfaces[0]->texture) return VA_STATUS_ERROR_ALLOCATION_FAILED; -- 2.7.4