mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-11 09:55:36 +00:00
msdk: enc: Add supprot for dmabuf-import
MediaSDK requires all the input 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 in future once we have a solution for: 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 enabling it in gst-msdk by replacing the MemID of mfxSurface with dmabuf-backed vasurface dynamically. Important: v4l2 ! msdkenc 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
a972d76784
commit
57b9875260
1 changed files with 81 additions and 16 deletions
|
@ -50,6 +50,10 @@
|
|||
#include "gstmsdksystemmemory.h"
|
||||
#include "gstmsdkcontextutil.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include "gstmsdkallocator_libva.h"
|
||||
#endif
|
||||
|
||||
static inline void *
|
||||
_aligned_alloc (size_t alignment, size_t size)
|
||||
{
|
||||
|
@ -1092,6 +1096,67 @@ gst_msdkenc_get_surface_from_pool (GstMsdkEnc * thiz, GstBufferPool * pool,
|
|||
return msdk_surface;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
import_dmabuf_to_msdk_surface (GstMsdkEnc * 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->input_state->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->aligned_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 *
|
||||
gst_msdkenc_get_surface_from_frame (GstMsdkEnc * thiz,
|
||||
GstVideoCodecFrame * frame)
|
||||
|
@ -1099,6 +1164,7 @@ gst_msdkenc_get_surface_from_frame (GstMsdkEnc * thiz,
|
|||
GstVideoFrame src_frame, out_frame;
|
||||
MsdkSurface *msdk_surface;
|
||||
GstBuffer *inbuf;
|
||||
GstMemory *mem = NULL;
|
||||
|
||||
inbuf = frame->input_buffer;
|
||||
if (gst_msdk_is_msdk_buffer (inbuf)) {
|
||||
|
@ -1107,22 +1173,27 @@ gst_msdkenc_get_surface_from_frame (GstMsdkEnc * thiz,
|
|||
return msdk_surface;
|
||||
}
|
||||
|
||||
/* If the pipeline negotiated dmabuf (use_dmabuf == TRUE) and the
|
||||
* upstream rejected the pool proposed by msdkencoder, then
|
||||
* we won't be able create a mappalbe buffer from the internal pool.
|
||||
*
|
||||
* Fixme: One possible fix could be to maintain an internal pool backed by the
|
||||
* videomemory always and providee a dmabuf-backed pool in propose_allocation */
|
||||
if (thiz->use_dmabuf)
|
||||
goto error_copying;
|
||||
|
||||
/* 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 =
|
||||
gst_msdkenc_get_surface_from_pool (thiz, thiz->msdk_pool, NULL)))
|
||||
goto error;
|
||||
|
||||
#ifndef _WIN32
|
||||
/************ dmabuf-import ************* */
|
||||
/* if upstream provided a dmabuf backed memory, but not an msdk
|
||||
* buffer, we could try to 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->input_state->info, inbuf,
|
||||
GST_MAP_READ)) {
|
||||
GST_ERROR_OBJECT (thiz, "failed to map the frame for source");
|
||||
|
@ -1157,13 +1228,7 @@ error:
|
|||
if (msdk_surface->buf)
|
||||
gst_buffer_unref (msdk_surface->buf);
|
||||
g_slice_free (MsdkSurface, msdk_surface);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
error_copying:
|
||||
GST_ERROR_OBJECT (thiz,
|
||||
"Upstream rejected the proposed dmabuf pool, "
|
||||
"and we can't copy the incoming buffers to msdk pool!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue