mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 10:11:08 +00:00
msdk: vpp: Add supprot for dmabuf-import
MediaSDK requires all the input and output buffers to be pre-allocated during init phase and this won't work with current design of GStreamer or gst-msdk. But this can be done with https://bugzilla.gnome.org/show_bug.cgi?id=795747 There is a workaround possible as per https://github.com/Intel-Media-SDK/MediaSDK/issues/155#issuecomment-381790504 by faking the mem-id during MFXInit. This patch do this in gst-msdk by replacing the MemID of mfxSurface with dmabuf-backed vasurface dynamically. Important: v4l2 ! msdkvpp won't work without a copy because of the GMMLib (https://github.com/intel/gmmlib) memory restrictions. https://bugzilla.gnome.org/show_bug.cgi?id=794817
This commit is contained in:
parent
a7b7939dd7
commit
a972d76784
1 changed files with 85 additions and 2 deletions
|
@ -44,6 +44,10 @@
|
|||
#include "gstmsdkcontextutil.h"
|
||||
#include "gstmsdkvpputil.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include "gstmsdkallocator_libva.h"
|
||||
#endif
|
||||
|
||||
GST_DEBUG_CATEGORY_EXTERN (gst_msdkvpp_debug);
|
||||
#define GST_CAT_DEFAULT gst_msdkvpp_debug
|
||||
|
||||
|
@ -508,11 +512,76 @@ get_surface_from_pool (GstMsdkVPP * thiz, GstBufferPool * pool,
|
|||
return msdk_surface;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
import_dmabuf_to_msdk_surface (GstMsdkVPP * thiz, GstBuffer * buf,
|
||||
MsdkSurface * msdk_surface)
|
||||
{
|
||||
GstMemory *mem = NULL;
|
||||
GstVideoInfo vinfo;
|
||||
GstVideoMeta *vmeta;
|
||||
GstMsdkMemoryID *msdk_mid = NULL;
|
||||
mfxFrameSurface1 *mfx_surface = NULL;
|
||||
gint fd, i;
|
||||
|
||||
mem = gst_buffer_peek_memory (buf, 0);
|
||||
fd = gst_dmabuf_memory_get_fd (mem);
|
||||
if (fd < 0)
|
||||
return FALSE;
|
||||
|
||||
vinfo = thiz->sinkpad_info;
|
||||
|
||||
/* Update offset/stride/size if there is VideoMeta attached to
|
||||
* the buffer */
|
||||
vmeta = gst_buffer_get_video_meta (buf);
|
||||
if (vmeta) {
|
||||
if (GST_VIDEO_INFO_FORMAT (&vinfo) != vmeta->format ||
|
||||
GST_VIDEO_INFO_WIDTH (&vinfo) != vmeta->width ||
|
||||
GST_VIDEO_INFO_HEIGHT (&vinfo) != vmeta->height ||
|
||||
GST_VIDEO_INFO_N_PLANES (&vinfo) != vmeta->n_planes) {
|
||||
GST_ERROR_OBJECT (thiz, "VideoMeta attached to buffer is not matching"
|
||||
"the negotiated width/height/format");
|
||||
return FALSE;
|
||||
}
|
||||
for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&vinfo); ++i) {
|
||||
GST_VIDEO_INFO_PLANE_OFFSET (&vinfo, i) = vmeta->offset[i];
|
||||
GST_VIDEO_INFO_PLANE_STRIDE (&vinfo, i) = vmeta->stride[i];
|
||||
}
|
||||
GST_VIDEO_INFO_SIZE (&vinfo) = gst_buffer_get_size (buf);
|
||||
}
|
||||
|
||||
/* Upstream neither accepted the msdk pool nor the msdk buffer size restrictions.
|
||||
* Current media-driver and GMMLib will fail due to strict memory size restrictions.
|
||||
* Ideally, media-driver should accept what ever memory coming from other drivers
|
||||
* in case of dmabuf-import and this is how the intel-vaapi-driver works.
|
||||
* For now, in order to avoid any crash we check the buffer size and fallback
|
||||
* to copy frame method.
|
||||
*
|
||||
* See this: https://github.com/intel/media-driver/issues/169
|
||||
* */
|
||||
if (GST_VIDEO_INFO_SIZE (&vinfo) <
|
||||
GST_VIDEO_INFO_SIZE (&thiz->sinkpad_buffer_pool_info))
|
||||
return FALSE;
|
||||
|
||||
mfx_surface = msdk_surface->surface;
|
||||
msdk_mid = (GstMsdkMemoryID *) mfx_surface->Data.MemId;
|
||||
|
||||
/* release the internal memory storage of associated mfxSurface */
|
||||
gst_msdk_replace_mfx_memid (thiz->context, mfx_surface, VA_INVALID_ID);
|
||||
|
||||
/* export dmabuf to vasurface */
|
||||
if (!gst_msdk_export_dmabuf_to_vasurface (thiz->context, &vinfo, fd,
|
||||
msdk_mid->surface))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static MsdkSurface *
|
||||
get_msdk_surface_from_input_buffer (GstMsdkVPP * thiz, GstBuffer * inbuf)
|
||||
{
|
||||
GstVideoFrame src_frame, out_frame;
|
||||
MsdkSurface *msdk_surface;
|
||||
GstMemory *mem = NULL;
|
||||
|
||||
if (gst_msdk_is_msdk_buffer (inbuf)) {
|
||||
msdk_surface = g_slice_new0 (MsdkSurface);
|
||||
|
@ -522,12 +591,26 @@ get_msdk_surface_from_input_buffer (GstMsdkVPP * thiz, GstBuffer * inbuf)
|
|||
}
|
||||
|
||||
/* If upstream hasn't accpeted the proposed msdk bufferpool,
|
||||
* just copy frame to msdk buffer and take a surface from it.
|
||||
*/
|
||||
* just copy frame (if not dmabuf backed) to msdk buffer and
|
||||
* take a surface from it. */
|
||||
if (!(msdk_surface =
|
||||
get_surface_from_pool (thiz, thiz->sinkpad_buffer_pool, NULL)))
|
||||
goto error;
|
||||
|
||||
#ifndef _WIN32
|
||||
/************ dmabuf-import ************* */
|
||||
/* if upstream provided a dmabuf backed memory, but not an msdk
|
||||
* buffer, we could export the dmabuf to underlined vasurface */
|
||||
mem = gst_buffer_peek_memory (inbuf, 0);
|
||||
if (gst_is_dmabuf_memory (mem)) {
|
||||
if (import_dmabuf_to_msdk_surface (thiz, inbuf, msdk_surface))
|
||||
return msdk_surface;
|
||||
else
|
||||
GST_INFO_OBJECT (thiz, "Upstream dmabuf-backed memory is not imported"
|
||||
"to the msdk surface, fall back to the copy input frame method");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!gst_video_frame_map (&src_frame, &thiz->sinkpad_info, inbuf,
|
||||
GST_MAP_READ)) {
|
||||
GST_ERROR_OBJECT (thiz, "failed to map the frame for source");
|
||||
|
|
Loading…
Reference in a new issue