msdk: call vaExportSurfaceHandle() to get DMABuf FD

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>
This commit is contained in:
Haihao Xiang 2020-06-15 15:24:07 +08:00
parent 8335039ecd
commit df49114275
4 changed files with 51 additions and 32 deletions

View file

@ -46,7 +46,7 @@ struct _GstMsdkMemoryID {
#ifndef _WIN32 #ifndef _WIN32
VASurfaceID *surface; VASurfaceID *surface;
VAImage image; VAImage image;
VABufferInfo info; VADRMPRIMESurfaceDescriptor desc;
#else #else
/* TODO: This is just to avoid compile errors on Windows. /* TODO: This is just to avoid compile errors on Windows.
* Implement handling Windows-specific video-memory. * Implement handling Windows-specific video-memory.

View file

@ -32,6 +32,7 @@
#include <va/va.h> #include <va/va.h>
#include <va/va_drmcommon.h> #include <va/va_drmcommon.h>
#include <unistd.h>
#include "gstmsdkallocator.h" #include "gstmsdkallocator.h"
#include "gstmsdkallocator_libva.h" #include "gstmsdkallocator_libva.h"
#include "msdk_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++) { for (i = 0; i < surfaces_num; i++) {
/* Get dmabuf handle if MFX_MEMTYPE_EXPORT_FRAME */ /* Get dmabuf handle if MFX_MEMTYPE_EXPORT_FRAME */
if (req->Type & 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 = va_status =
vaDeriveImage (gst_msdk_context_get_handle (context), surfaces[i], vaExportSurfaceHandle (gst_msdk_context_get_handle (context),
&msdk_mids[i].image); 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); status = gst_msdk_get_mfx_status_from_va_status (va_status);
if (MFX_ERR_NONE != status) { if (MFX_ERR_NONE != status) {
GST_ERROR ("failed to derive image"); GST_ERROR ("Failed to export surface");
return status; return status;
} }
va_status = g_assert (va_desc.num_objects);
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);
if (MFX_ERR_NONE != status) { /* This plugin supports single object only */
GST_ERROR ("failed to get dmabuf handle"); if (va_desc.num_objects > 1) {
va_status = vaDestroyImage (gst_msdk_context_get_handle (context), GST_ERROR ("Can not support multiple objects");
msdk_mids[i].image.image_id); return MFX_ERR_UNSUPPORTED;
if (va_status == VA_STATUS_SUCCESS) {
msdk_mids[i].image.image_id = VA_INVALID_ID;
msdk_mids[i].image.buf = VA_INVALID_ID;
}
} }
} else {
/* useful to check the image mapping state later */ msdk_mids[i].desc = va_desc;
msdk_mids[i].image.image_id = VA_INVALID_ID;
msdk_mids[i].image.buf = VA_INVALID_ID;
} }
/* 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]; msdk_mids[i].surface = &surfaces[i];
mids[i] = (mfxMemId *) & msdk_mids[i]; mids[i] = (mfxMemId *) & msdk_mids[i];
} }
@ -225,6 +226,11 @@ gst_msdk_frame_alloc (mfxHDL pthis, mfxFrameAllocRequest * req,
surfaces[i] = coded_buf; surfaces[i] = coded_buf;
msdk_mids[i].surface = &surfaces[i]; msdk_mids[i].surface = &surfaces[i];
msdk_mids[i].fourcc = fourcc; 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]; 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++) { for (i = 0; i < resp->NumFrameActual; i++) {
GstMsdkMemoryID *mem = resp->mids[i]; GstMsdkMemoryID *mem = resp->mids[i];
/* Release dmabuf handle if used */ /* Release prime fd if used */
if (mem->info.mem_type == VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME) if (mem->desc.num_objects) {
vaReleaseBufferHandle (dpy, mem->image.buf); 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 && if (mem->image.image_id != VA_INVALID_ID &&
vaDestroyImage (dpy, mem->image.image_id) == VA_STATUS_SUCCESS) { 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; va_surface = mem_id->surface;
dpy = gst_msdk_context_get_handle (context); 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"); GST_WARNING ("Couldn't map the buffer since dmabuf is already in use");
return MFX_ERR_LOCK_MEMORY; return MFX_ERR_LOCK_MEMORY;
} }
@ -456,6 +465,8 @@ gst_msdk_frame_unlock (mfxHDL pthis, mfxMemId mid, mfxFrameData * ptr)
mem_id = (GstMsdkMemoryID *) mid; mem_id = (GstMsdkMemoryID *) mid;
dpy = gst_msdk_context_get_handle (context); dpy = gst_msdk_context_get_handle (context);
g_assert (mem_id->desc.num_objects == 0);
if (mem_id->fourcc != MFX_FOURCC_P8) { if (mem_id->fourcc != MFX_FOURCC_P8) {
vaUnmapBuffer (dpy, mem_id->image.buf); vaUnmapBuffer (dpy, mem_id->image.buf);
va_status = vaDestroyImage (dpy, mem_id->image.image_id); 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); g_return_val_if_fail (surface, FALSE);
mem_id = (GstMsdkMemoryID *) surface->Data.MemId; mem_id = (GstMsdkMemoryID *) surface->Data.MemId;
g_assert (mem_id->desc.num_objects == 1);
if (handle) if (handle)
*handle = mem_id->info.handle; *handle = mem_id->desc.objects[0].fd;
if (size) if (size)
*size = mem_id->info.mem_size; *size = mem_id->desc.objects[0].size;
return TRUE; return TRUE;
} }

View file

@ -36,6 +36,7 @@
#include "msdk.h" #include "msdk.h"
#ifndef _WIN32 #ifndef _WIN32
#include <va/va.h> #include <va/va.h>
#include <va/va_drmcommon.h>
#endif #endif
G_BEGIN_DECLS G_BEGIN_DECLS

View 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); g_return_val_if_fail (GST_IS_MSDK_DMABUF_ALLOCATOR (allocator), NULL);
mem_id = surface->Data.MemId; 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"); GST_ERROR ("Failed to get dmabuf handle");
return NULL; 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) { if (!mem) {
GST_ERROR ("failed ! dmabuf fd: %d", fd); GST_ERROR ("failed ! dmabuf fd: %d", fd);
close (fd);
return NULL; return NULL;
} }