From ffa2522fc02f63ac215deaee01e8041844256e81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Manuel=20J=C3=A1quez=20Leal?= Date: Tue, 5 Oct 2021 13:36:56 +0200 Subject: [PATCH] va: Add GstVaSurfaceCopy class. This new class is a helper for fast/tricky copy of surfaces. First it tries to copy using the function vaCopy in libva 1.12. If it fails, or it's not available, a GstVaFilter is tried to be instantiated with the allocator's parameters, and if succeed, it's used for copying the source surface. This is required for dmabuf surfaces with drm modifier. Part-of: --- .../gst-plugins-bad/sys/va/gstvaallocator.c | 2 +- .../gst-plugins-bad/sys/va/gstvasurfacecopy.c | 144 ++++++++++++++++++ .../gst-plugins-bad/sys/va/gstvasurfacecopy.h | 43 ++++++ .../gst-plugins-bad/sys/va/meson.build | 1 + .../gst-plugins-bad/sys/va/vasurfaceimage.c | 40 +++++ .../gst-plugins-bad/sys/va/vasurfaceimage.h | 3 + 6 files changed, 232 insertions(+), 1 deletion(-) create mode 100644 subprojects/gst-plugins-bad/sys/va/gstvasurfacecopy.c create mode 100644 subprojects/gst-plugins-bad/sys/va/gstvasurfacecopy.h diff --git a/subprojects/gst-plugins-bad/sys/va/gstvaallocator.c b/subprojects/gst-plugins-bad/sys/va/gstvaallocator.c index c88124f54d..c0b21560e0 100644 --- a/subprojects/gst-plugins-bad/sys/va/gstvaallocator.c +++ b/subprojects/gst-plugins-bad/sys/va/gstvaallocator.c @@ -32,7 +32,7 @@ #include "vasurfaceimage.h" #define GST_CAT_DEFAULT gst_va_memory_debug -GST_DEBUG_CATEGORY_STATIC (gst_va_memory_debug); +GST_DEBUG_CATEGORY (gst_va_memory_debug); static void _init_debug_category (void) diff --git a/subprojects/gst-plugins-bad/sys/va/gstvasurfacecopy.c b/subprojects/gst-plugins-bad/sys/va/gstvasurfacecopy.c new file mode 100644 index 0000000000..fcbeee1df7 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/va/gstvasurfacecopy.c @@ -0,0 +1,144 @@ +/* GStreamer + * Copyright (C) 2021 Igalia, S.L. + * Author: Víctor Jáquez + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "gstvasurfacecopy.h" + +#include "gstvaallocator.h" +#include "gstvadisplay_priv.h" +#include "gstvafilter.h" +#include "vasurfaceimage.h" + +#define GST_CAT_DEFAULT gst_va_memory_debug +GST_DEBUG_CATEGORY_EXTERN (gst_va_memory_debug); + +struct _GstVaSurfaceCopy +{ + GstVaDisplay *display; + + GstVideoInfo info; + gboolean has_copy; + GstVaFilter *filter; +}; + +static gboolean +_has_copy (GstVaDisplay * display) +{ +#if VA_CHECK_VERSION (1, 12, 0) + VADisplay dpy; + VADisplayAttribute attr = { + .type = VADisplayAttribCopy, + .flags = VA_DISPLAY_ATTRIB_GETTABLE, + }; + VAStatus status; + + dpy = gst_va_display_get_va_dpy (display); + + gst_va_display_lock (display); + status = vaGetDisplayAttributes (dpy, &attr, 1); + gst_va_display_unlock (display); + if (status != VA_STATUS_SUCCESS) { + GST_INFO ("vaGetDisplayAttribures: %s", vaErrorStr (status)); + return FALSE; + } + + return TRUE; +#else + return FALSE; +#endif +} + +GstVaSurfaceCopy * +gst_va_surface_copy_new (GstVaDisplay * display, GstVideoInfo * vinfo) +{ + GstVaSurfaceCopy *self; + + g_return_val_if_fail (GST_IS_VA_DISPLAY (display), NULL); + g_return_val_if_fail (vinfo != NULL, NULL); + + self = g_slice_new (GstVaSurfaceCopy); + self->display = gst_object_ref (display); + self->has_copy = _has_copy (display); + self->info = *vinfo; + self->filter = NULL; + + if (gst_va_display_has_vpp (display)) { + self->filter = gst_va_filter_new (display); + if (!(gst_va_filter_open (self->filter) + && gst_va_filter_set_video_info (self->filter, vinfo, vinfo))) + gst_clear_object (&self->filter); + } + + return self; +} + +void +gst_va_surface_copy_free (GstVaSurfaceCopy * self) +{ + g_return_if_fail (self && GST_IS_VA_DISPLAY (self->display)); + + gst_clear_object (&self->display); + if (self->filter) { + gst_va_filter_close (self->filter); + gst_clear_object (&self->filter); + } + g_slice_free (GstVaSurfaceCopy, self); +} + +static gboolean +_vpp_copy_surface (GstVaFilter * filter, VASurfaceID dst, VASurfaceID src) +{ + GstVaSample gst_src = { + .surface = src, + }; + GstVaSample gst_dst = { + .surface = dst, + }; + return gst_va_filter_process (filter, &gst_src, &gst_dst); +} + +gboolean +gst_va_surface_copy (GstVaSurfaceCopy * self, VASurfaceID dst, VASurfaceID src) +{ + VAImage image = {.image_id = VA_INVALID_ID, }; + gboolean ret; + + g_return_val_if_fail (self && GST_IS_VA_DISPLAY (self->display), FALSE); + + if (self->has_copy && va_copy_surface (self->display, dst, src)) { + GST_LOG ("GPU copy of %#x to %#x", src, dst); + return TRUE; + } + + if (self->filter && _vpp_copy_surface (self->filter, dst, src)) { + GST_LOG ("VPP copy of %#x to %#x", src, dst); + return TRUE; + } + + if (!va_ensure_image (self->display, src, &self->info, &image, FALSE)) + return FALSE; + + if ((ret = va_put_image (self->display, dst, &image))) + GST_LOG ("shallow copy of %#x to %#x", src, dst); + + va_unmap_buffer (self->display, image.buf); + va_destroy_image (self->display, image.image_id); + + return ret; +} diff --git a/subprojects/gst-plugins-bad/sys/va/gstvasurfacecopy.h b/subprojects/gst-plugins-bad/sys/va/gstvasurfacecopy.h new file mode 100644 index 0000000000..eb4641a7ef --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/va/gstvasurfacecopy.h @@ -0,0 +1,43 @@ +/* GStreamer + * Copyright (C) 2021 Igalia, S.L. + * Author: Víctor Jáquez + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#pragma once + +#include +#include +#include + +G_BEGIN_DECLS + +/** + * Opaque object helper for copying surfaces. + * + * It's purpose is to avoid circular dependencies. + */ +typedef struct _GstVaSurfaceCopy GstVaSurfaceCopy; + +GstVaSurfaceCopy * gst_va_surface_copy_new (GstVaDisplay * display, + GstVideoInfo * vinfo); +void gst_va_surface_copy_free (GstVaSurfaceCopy * self); +gboolean gst_va_surface_copy (GstVaSurfaceCopy * self, + VASurfaceID dst, + VASurfaceID src); + +G_END_DECLS diff --git a/subprojects/gst-plugins-bad/sys/va/meson.build b/subprojects/gst-plugins-bad/sys/va/meson.build index 48811ec6e7..3b29cbd2d4 100644 --- a/subprojects/gst-plugins-bad/sys/va/meson.build +++ b/subprojects/gst-plugins-bad/sys/va/meson.build @@ -13,6 +13,7 @@ va_sources = [ 'gstvah265dec.c', 'gstvapool.c', 'gstvaprofile.c', + 'gstvasurfacecopy.c', 'gstvautils.c', 'gstvavideoformat.c', 'gstvavp8dec.c', diff --git a/subprojects/gst-plugins-bad/sys/va/vasurfaceimage.c b/subprojects/gst-plugins-bad/sys/va/vasurfaceimage.c index 4b1b0982a4..e8f324df8a 100644 --- a/subprojects/gst-plugins-bad/sys/va/vasurfaceimage.c +++ b/subprojects/gst-plugins-bad/sys/va/vasurfaceimage.c @@ -310,3 +310,43 @@ va_check_surface (GstVaDisplay * display, VASurfaceID surface) return (status == VA_STATUS_SUCCESS); } + +gboolean +va_copy_surface (GstVaDisplay * display, VASurfaceID dst, VASurfaceID src) +{ +#if VA_CHECK_VERSION (1, 12, 0) + VADisplay dpy = gst_va_display_get_va_dpy (display); + /* *INDENT-OFF* */ + VACopyObject obj_src = { + .obj_type = VACopyObjectSurface, + .object = { + .surface_id = src, + }, + }; + VACopyObject obj_dst = { + .obj_type = VACopyObjectSurface, + .object = { + .surface_id = dst, + }, + }; + VACopyOption option = { + .bits = { + .va_copy_sync = VA_EXEC_SYNC, + .va_copy_mode = VA_EXEC_MODE_DEFAULT, + }, + }; + /* *INDENT-ON* */ + VAStatus status; + + gst_va_display_lock (display); + status = vaCopy (dpy, &obj_dst, &obj_src, option); + gst_va_display_unlock (display); + if (status != VA_STATUS_SUCCESS) { + GST_INFO ("vaCopy: %s", vaErrorStr (status)); + return FALSE; + } + return TRUE; +#else + return FALSE; +#endif +} diff --git a/subprojects/gst-plugins-bad/sys/va/vasurfaceimage.h b/subprojects/gst-plugins-bad/sys/va/vasurfaceimage.h index 787d8ca4f7..e0ced582c9 100644 --- a/subprojects/gst-plugins-bad/sys/va/vasurfaceimage.h +++ b/subprojects/gst-plugins-bad/sys/va/vasurfaceimage.h @@ -46,6 +46,9 @@ gboolean va_sync_surface (GstVaDisplay * displa VASurfaceID surface); gboolean va_check_surface (GstVaDisplay * display, VASurfaceID surface); +gboolean va_copy_surface (GstVaDisplay * display, + VASurfaceID dst, + VASurfaceID src); /* images */ gboolean va_create_image (GstVaDisplay * display,