msdk: call vaExportSurfaceHandle() to get DMABuf FD
authorHaihao Xiang <haihao.xiang@intel.com>
Mon, 15 Jun 2020 07:24:07 +0000 (15:24 +0800)
committerHaihao Xiang <haihao.xiang@intel.com>
Tue, 29 Sep 2020 02:06:02 +0000 (02:06 +0000)
Compared to vaAcquireBufferHandle(), vaExportSurfaceHandle() may
provide the handle details, so we needn't call vaDeriveImage().

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1353>

sys/msdk/gstmsdkallocator.h
sys/msdk/gstmsdkallocator_libva.c
sys/msdk/gstmsdkcontext.h
sys/msdk/gstmsdkvideomemory.c

index 4d94b8b..e0d5616 100644 (file)
@@ -46,7 +46,7 @@ struct _GstMsdkMemoryID {
 #ifndef _WIN32
   VASurfaceID *surface;
   VAImage image;
-  VABufferInfo info;
+  VADRMPRIMESurfaceDescriptor desc;
 #else
   /* TODO: This is just to avoid compile errors on Windows.
    * Implement handling Windows-specific video-memory.
index 90d8c36..1ddda23 100644 (file)
@@ -32,6 +32,7 @@
 
 #include <va/va.h>
 #include <va/va_drmcommon.h>
+#include <unistd.h>
 #include "gstmsdkallocator.h"
 #include "gstmsdkallocator_libva.h"
 #include "msdk_libva.h"
@@ -164,37 +165,37 @@ gst_msdk_frame_alloc (mfxHDL pthis, mfxFrameAllocRequest * req,
     for (i = 0; i < surfaces_num; i++) {
       /* Get dmabuf handle if MFX_MEMTYPE_EXPORT_FRAME */
       if (req->Type & MFX_MEMTYPE_EXPORT_FRAME) {
-        msdk_mids[i].info.mem_type = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME;
+        VADRMPRIMESurfaceDescriptor va_desc = { 0 };
+        uint32_t export_flags = VA_EXPORT_SURFACE_SEPARATE_LAYERS |
+            VA_EXPORT_SURFACE_READ_WRITE;
+
         va_status =
-            vaDeriveImage (gst_msdk_context_get_handle (context), surfaces[i],
-            &msdk_mids[i].image);
+            vaExportSurfaceHandle (gst_msdk_context_get_handle (context),
+            surfaces[i], VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2, export_flags,
+            &va_desc);
+
         status = gst_msdk_get_mfx_status_from_va_status (va_status);
 
         if (MFX_ERR_NONE != status) {
-          GST_ERROR ("failed to derive image");
+          GST_ERROR ("Failed to export surface");
           return status;
         }
 
-        va_status =
-            vaAcquireBufferHandle (gst_msdk_context_get_handle (context),
-            msdk_mids[i].image.buf, &msdk_mids[i].info);
-        status = gst_msdk_get_mfx_status_from_va_status (va_status);
+        g_assert (va_desc.num_objects);
 
-        if (MFX_ERR_NONE != status) {
-          GST_ERROR ("failed to get dmabuf handle");
-          va_status = vaDestroyImage (gst_msdk_context_get_handle (context),
-              msdk_mids[i].image.image_id);
-          if (va_status == VA_STATUS_SUCCESS) {
-            msdk_mids[i].image.image_id = VA_INVALID_ID;
-            msdk_mids[i].image.buf = VA_INVALID_ID;
-          }
+        /* This plugin supports single object only */
+        if (va_desc.num_objects > 1) {
+          GST_ERROR ("Can not support multiple objects");
+          return MFX_ERR_UNSUPPORTED;
         }
-      } else {
-        /* useful to check the image mapping state later */
-        msdk_mids[i].image.image_id = VA_INVALID_ID;
-        msdk_mids[i].image.buf = VA_INVALID_ID;
+
+        msdk_mids[i].desc = va_desc;
       }
 
+      /* Don't use image for DMABuf */
+      msdk_mids[i].image.image_id = VA_INVALID_ID;
+      msdk_mids[i].image.buf = VA_INVALID_ID;
+
       msdk_mids[i].surface = &surfaces[i];
       mids[i] = (mfxMemId *) & msdk_mids[i];
     }
@@ -225,6 +226,11 @@ gst_msdk_frame_alloc (mfxHDL pthis, mfxFrameAllocRequest * req,
       surfaces[i] = coded_buf;
       msdk_mids[i].surface = &surfaces[i];
       msdk_mids[i].fourcc = fourcc;
+
+      /* Don't use image for P208 */
+      msdk_mids[i].image.image_id = VA_INVALID_ID;
+      msdk_mids[i].image.buf = VA_INVALID_ID;
+
       mids[i] = (mfxMemId *) & msdk_mids[i];
     }
   }
@@ -271,9 +277,12 @@ gst_msdk_frame_free (mfxHDL pthis, mfxFrameAllocResponse * resp)
     for (i = 0; i < resp->NumFrameActual; i++) {
       GstMsdkMemoryID *mem = resp->mids[i];
 
-      /* Release dmabuf handle if used */
-      if (mem->info.mem_type == VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME)
-        vaReleaseBufferHandle (dpy, mem->image.buf);
+      /* Release prime fd if used */
+      if (mem->desc.num_objects) {
+        g_assert (mem->desc.num_objects == 1);
+        close (mem->desc.objects[0].fd);
+        mem->desc.num_objects = 0;
+      }
 
       if (mem->image.image_id != VA_INVALID_ID &&
           vaDestroyImage (dpy, mem->image.image_id) == VA_STATUS_SUCCESS) {
@@ -316,7 +325,7 @@ gst_msdk_frame_lock (mfxHDL pthis, mfxMemId mid, mfxFrameData * data)
   va_surface = mem_id->surface;
   dpy = gst_msdk_context_get_handle (context);
 
-  if (mem_id->info.mem_type == VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME) {
+  if (mem_id->desc.num_objects) {
     GST_WARNING ("Couldn't map the buffer since dmabuf is already in use");
     return MFX_ERR_LOCK_MEMORY;
   }
@@ -456,6 +465,8 @@ gst_msdk_frame_unlock (mfxHDL pthis, mfxMemId mid, mfxFrameData * ptr)
   mem_id = (GstMsdkMemoryID *) mid;
   dpy = gst_msdk_context_get_handle (context);
 
+  g_assert (mem_id->desc.num_objects == 0);
+
   if (mem_id->fourcc != MFX_FOURCC_P8) {
     vaUnmapBuffer (dpy, mem_id->image.buf);
     va_status = vaDestroyImage (dpy, mem_id->image.image_id);
@@ -510,10 +521,13 @@ gst_msdk_get_dmabuf_info_from_surface (mfxFrameSurface1 * surface,
   g_return_val_if_fail (surface, FALSE);
 
   mem_id = (GstMsdkMemoryID *) surface->Data.MemId;
+
+  g_assert (mem_id->desc.num_objects == 1);
+
   if (handle)
-    *handle = mem_id->info.handle;
+    *handle = mem_id->desc.objects[0].fd;
   if (size)
-    *size = mem_id->info.mem_size;
+    *size = mem_id->desc.objects[0].size;
 
   return TRUE;
 }
index f115b40..8fce6fe 100644 (file)
@@ -36,6 +36,7 @@
 #include "msdk.h"
 #ifndef _WIN32
 #include <va/va.h>
+#include <va/va_drmcommon.h>
 #endif
 
 G_BEGIN_DECLS
index 642d6b9..c296ae8 100644 (file)
@@ -499,18 +499,22 @@ gst_msdk_dmabuf_memory_new_with_surface (GstAllocator * allocator,
   g_return_val_if_fail (GST_IS_MSDK_DMABUF_ALLOCATOR (allocator), NULL);
 
   mem_id = surface->Data.MemId;
-  fd = mem_id->info.handle;
-  size = mem_id->info.mem_size;
 
-  if (fd < 0 || (fd = dup (fd)) < 0) {
+  g_assert (mem_id->desc.num_objects == 1);
+
+  fd = mem_id->desc.objects[0].fd;
+  size = mem_id->desc.objects[0].size;
+
+  if (fd < 0) {
     GST_ERROR ("Failed to get dmabuf handle");
     return NULL;
   }
 
-  mem = gst_dmabuf_allocator_alloc (allocator, fd, size);
+  mem = gst_fd_allocator_alloc (allocator, fd, size,
+      GST_FD_MEMORY_FLAG_DONT_CLOSE);
+
   if (!mem) {
     GST_ERROR ("failed ! dmabuf fd: %d", fd);
-    close (fd);
     return NULL;
   }