diff --git a/sys/msdk/gstmsdkenc.c b/sys/msdk/gstmsdkenc.c index 60fa8953bd..4493293642 100644 --- a/sys/msdk/gstmsdkenc.c +++ b/sys/msdk/gstmsdkenc.c @@ -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; }