msdkvpp: modify the way of copying system memory to msdk surface

Replace video_copy with memcpy to fix the issue when the sizes of the
src frame and dst frame don't match. Moreover, for Windows, you have to
do the copy first and call gst_msdk_import_to_msdk_surface later.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3231>
This commit is contained in:
Tong Wu 2022-09-07 15:29:37 +08:00 committed by GStreamer Marge Bot
parent 9a6dd525f7
commit 7becf35221

View file

@ -786,11 +786,12 @@ gst_msdkvpp_propose_allocation (GstBaseTransform * trans,
} }
static GstMsdkSurface * static GstMsdkSurface *
get_surface_from_pool (GstMsdkVPP * thiz, GstBufferPool * pool, gst_msdkvpp_get_surface_from_pool (GstMsdkVPP * thiz, GstBufferPool * pool,
GstBufferPoolAcquireParams * params) GstBuffer * buf)
{ {
GstBuffer *new_buffer; GstBuffer *upload_buf;
GstMsdkSurface *msdk_surface = NULL; GstMsdkSurface *msdk_surface = NULL;
GstVideoFrame src_frame, dst_frame;
if (!gst_buffer_pool_is_active (pool) && if (!gst_buffer_pool_is_active (pool) &&
!gst_buffer_pool_set_active (pool, TRUE)) { !gst_buffer_pool_set_active (pool, TRUE)) {
@ -798,20 +799,69 @@ get_surface_from_pool (GstMsdkVPP * thiz, GstBufferPool * pool,
return NULL; return NULL;
} }
if (gst_buffer_pool_acquire_buffer (pool, &new_buffer, params) != GST_FLOW_OK) { if (gst_buffer_pool_acquire_buffer (pool, &upload_buf, NULL) != GST_FLOW_OK) {
GST_ERROR_OBJECT (pool, "failed to acquire a buffer from pool"); GST_ERROR_OBJECT (pool, "failed to acquire a buffer from pool");
return NULL; return NULL;
} }
#ifndef _WIN32
msdk_surface = gst_msdk_import_to_msdk_surface (new_buffer, thiz->context, if (!gst_video_frame_map (&src_frame, &thiz->sinkpad_info, buf, GST_MAP_READ)) {
&thiz->sinkpad_info, 0); GST_ERROR_OBJECT (thiz, "failed to map the frame for source");
#else gst_buffer_unref (upload_buf);
msdk_surface = gst_msdk_import_sys_mem_to_msdk_surface return NULL;
(new_buffer, thiz->sinkpad_buffer_pool_info); }
#endif
if (!gst_video_frame_map (&dst_frame, &thiz->sinkpad_buffer_pool_info,
upload_buf, GST_MAP_WRITE)) {
GST_ERROR_OBJECT (thiz, "failed to map the frame for destination");
gst_video_frame_unmap (&src_frame);
gst_buffer_unref (upload_buf);
return NULL;
}
for (guint i = 0; i < GST_VIDEO_FRAME_N_PLANES (&src_frame); i++) {
guint src_width_in_bytes, src_height;
guint dst_width_in_bytes, dst_height;
guint width_in_bytes, height;
guint src_stride, dst_stride;
guint8 *src_data, *dst_data;
src_width_in_bytes = GST_VIDEO_FRAME_COMP_WIDTH (&src_frame, i) *
GST_VIDEO_FRAME_COMP_PSTRIDE (&src_frame, i);
src_height = GST_VIDEO_FRAME_COMP_HEIGHT (&src_frame, i);
src_stride = GST_VIDEO_FRAME_COMP_STRIDE (&src_frame, i);
dst_width_in_bytes = GST_VIDEO_FRAME_COMP_WIDTH (&dst_frame, i) *
GST_VIDEO_FRAME_COMP_PSTRIDE (&src_frame, i);
dst_height = GST_VIDEO_FRAME_COMP_HEIGHT (&src_frame, i);
dst_stride = GST_VIDEO_FRAME_COMP_STRIDE (&dst_frame, i);
width_in_bytes = MIN (src_width_in_bytes, dst_width_in_bytes);
height = MIN (src_height, dst_height);
src_data = (guint8 *) GST_VIDEO_FRAME_PLANE_DATA (&src_frame, i);
dst_data = (guint8 *) GST_VIDEO_FRAME_PLANE_DATA (&dst_frame, i);
for (guint j = 0; j < height; j++) {
memcpy (dst_data, src_data, width_in_bytes);
dst_data += dst_stride;
src_data += src_stride;
}
}
gst_video_frame_unmap (&dst_frame);
gst_video_frame_unmap (&src_frame);
if (thiz->use_video_memory) {
msdk_surface = gst_msdk_import_to_msdk_surface (upload_buf, thiz->context,
&thiz->sinkpad_info, GST_MAP_READ);
} else {
msdk_surface =
gst_msdk_import_sys_mem_to_msdk_surface (upload_buf,
thiz->sinkpad_buffer_pool_info);
}
if (msdk_surface) if (msdk_surface)
msdk_surface->buf = new_buffer; msdk_surface->buf = upload_buf;
return msdk_surface; return msdk_surface;
} }
@ -819,7 +869,6 @@ get_surface_from_pool (GstMsdkVPP * thiz, GstBufferPool * pool,
static GstMsdkSurface * static GstMsdkSurface *
get_msdk_surface_from_input_buffer (GstMsdkVPP * thiz, GstBuffer * inbuf) get_msdk_surface_from_input_buffer (GstMsdkVPP * thiz, GstBuffer * inbuf)
{ {
GstVideoFrame src_frame, out_frame;
GstMsdkSurface *msdk_surface = NULL; GstMsdkSurface *msdk_surface = NULL;
if (gst_msdk_is_msdk_buffer (inbuf)) { if (gst_msdk_is_msdk_buffer (inbuf)) {
@ -828,49 +877,20 @@ get_msdk_surface_from_input_buffer (GstMsdkVPP * thiz, GstBuffer * inbuf)
msdk_surface->buf = gst_buffer_ref (inbuf); msdk_surface->buf = gst_buffer_ref (inbuf);
return msdk_surface; return msdk_surface;
} }
#ifndef _WIN32
msdk_surface = gst_msdk_import_to_msdk_surface (inbuf, thiz->context, msdk_surface = gst_msdk_import_to_msdk_surface (inbuf, thiz->context,
&thiz->sinkpad_info, 0); &thiz->sinkpad_info, GST_MAP_READ);
if (msdk_surface) { if (msdk_surface) {
msdk_surface->buf = gst_buffer_ref (inbuf); msdk_surface->buf = gst_buffer_ref (inbuf);
return msdk_surface; return msdk_surface;
} }
#endif
/* If upstream hasn't accpeted the proposed msdk bufferpool, /* If upstream hasn't accpeted the proposed msdk bufferpool,
* just copy frame to msdk buffer and take a surface from it. * just copy frame to msdk buffer and take a surface from it.
*/ */
if (!(msdk_surface =
get_surface_from_pool (thiz, thiz->sinkpad_buffer_pool, NULL)))
goto error;
if (!gst_video_frame_map (&src_frame, &thiz->sinkpad_info, inbuf, return gst_msdkvpp_get_surface_from_pool (thiz, thiz->sinkpad_buffer_pool,
GST_MAP_READ)) { inbuf);
GST_ERROR_OBJECT (thiz, "failed to map the frame for source");
goto error;
}
if (!gst_video_frame_map (&out_frame, &thiz->sinkpad_buffer_pool_info,
msdk_surface->buf, GST_MAP_WRITE)) {
GST_ERROR_OBJECT (thiz, "failed to map the frame for destination");
gst_video_frame_unmap (&src_frame);
goto error;
}
if (!gst_video_frame_copy (&out_frame, &src_frame)) {
GST_ERROR_OBJECT (thiz, "failed to copy frame");
gst_video_frame_unmap (&out_frame);
gst_video_frame_unmap (&src_frame);
goto error;
}
gst_video_frame_unmap (&out_frame);
gst_video_frame_unmap (&src_frame);
return msdk_surface;
error:
return NULL;
} }
static GstFlowReturn static GstFlowReturn