va: Add GstVaSurfaceCopy class.
authorVíctor Manuel Jáquez Leal <vjaquez@igalia.com>
Tue, 5 Oct 2021 11:36:56 +0000 (13:36 +0200)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Sun, 10 Oct 2021 17:03:29 +0000 (17:03 +0000)
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: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1023>

subprojects/gst-plugins-bad/sys/va/gstvaallocator.c
subprojects/gst-plugins-bad/sys/va/gstvasurfacecopy.c [new file with mode: 0644]
subprojects/gst-plugins-bad/sys/va/gstvasurfacecopy.h [new file with mode: 0644]
subprojects/gst-plugins-bad/sys/va/meson.build
subprojects/gst-plugins-bad/sys/va/vasurfaceimage.c
subprojects/gst-plugins-bad/sys/va/vasurfaceimage.h

index c88124f..c0b2156 100644 (file)
@@ -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 (file)
index 0000000..fcbeee1
--- /dev/null
@@ -0,0 +1,144 @@
+/* GStreamer
+ * Copyright (C) 2021 Igalia, S.L.
+ *     Author: Víctor Jáquez <vjaquez@igalia.com>
+ *
+ * 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 (file)
index 0000000..eb4641a
--- /dev/null
@@ -0,0 +1,43 @@
+/* GStreamer
+ * Copyright (C) 2021 Igalia, S.L.
+ *     Author: Víctor Jáquez <vjaquez@igalia.com>
+ *
+ * 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 <gst/va/gstvadisplay.h>
+#include <gst/video/video.h>
+#include <va/va.h>
+
+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
index 48811ec..3b29cbd 100644 (file)
@@ -13,6 +13,7 @@ va_sources = [
   'gstvah265dec.c',
   'gstvapool.c',
   'gstvaprofile.c',
+  'gstvasurfacecopy.c',
   'gstvautils.c',
   'gstvavideoformat.c',
   'gstvavp8dec.c',
index 4b1b098..e8f324d 100644 (file)
@@ -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
+}
index 787d8ca..e0ced58 100644 (file)
@@ -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,