From b62bd57bda595fb98a9fdc918df3ab5938c8e9f0 Mon Sep 17 00:00:00 2001 From: Wind Yuan Date: Fri, 1 Nov 2013 13:43:11 +0800 Subject: [PATCH] vaapipostproc: fix support for raw YUV data upload on GStreamer 1.0. Fix raw YUV data uploaded as in the following pipeline: $ gst-launch-1.0 filesrc video.yuv ! videoparse ! vaapipostproc ! vaapisink The main reason why it failed was that the videoparse element simply allocates GstBuffer with raw data chunk'ed off the sink pad without any prior knowledge of the actual frame info. i.e. it basically just calls gst_adapter_take_buffer(). We could avoid the extra copy performed in vaapipostproc if the videoparse element was aware of the downstream pool and bothers copying line by line, for each plane. This means that, for a single frame per buffer, the optimizatin will be to allocate the video buffer downstream, map it, and copy each line that is coming through until we need to fills in the successive planes. Still, optimized raw YUV uploads already worked with the following: $ gst-launch-1.0 videotestsrc ! vaapipostproc ! vaapisink https://bugzilla.gnome.org/show_bug.cgi?id=711250 [clean-ups, fixed error cases to unmap and unref outbuf] Signed-off-by: Gwenole Beauchesne --- gst/vaapi/gstvaapipostproc.c | 58 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/gst/vaapi/gstvaapipostproc.c b/gst/vaapi/gstvaapipostproc.c index 1e20287..99b400c 100755 --- a/gst/vaapi/gstvaapipostproc.c +++ b/gst/vaapi/gstvaapipostproc.c @@ -1030,14 +1030,43 @@ get_source_buffer(GstVaapiPostproc *postproc, GstBuffer *inbuf) { GstVaapiVideoMeta *meta; GstBuffer *outbuf; +#if GST_CHECK_VERSION(1,0,0) + GstVideoFrame src_frame, out_frame; +#endif meta = gst_buffer_get_vaapi_video_meta(inbuf); if (meta) return gst_buffer_ref(inbuf); #if GST_CHECK_VERSION(1,0,0) + if (!postproc->is_raw_yuv) + goto error_invalid_buffer; + + if (!postproc->sinkpad_buffer_pool) + goto error_no_pool; + + if (!gst_buffer_pool_set_active(postproc->sinkpad_buffer_pool, TRUE)) + goto error_active_pool; + outbuf = NULL; - goto error_invalid_buffer; + if (gst_buffer_pool_acquire_buffer(postproc->sinkpad_buffer_pool, + &outbuf, NULL) != GST_FLOW_OK) + goto error_create_buffer; + + if (!gst_video_frame_map(&src_frame, &postproc->sinkpad_info, inbuf, + GST_MAP_READ)) + goto error_map_src_buffer; + + if (!gst_video_frame_map(&out_frame, &postproc->sinkpad_info, outbuf, + GST_MAP_WRITE)) + goto error_map_dst_buffer; + + if (!gst_video_frame_copy(&out_frame, &src_frame)) + goto error_copy_buffer; + + gst_video_frame_unmap(&out_frame); + gst_video_frame_unmap(&src_frame); + gst_buffer_copy_into(outbuf, inbuf, GST_BUFFER_COPY_TIMESTAMPS, 0, -1); return outbuf; /* ERRORS */ @@ -1046,6 +1075,27 @@ error_invalid_buffer: GST_ERROR("failed to validate source buffer"); return NULL; } +error_no_pool: + { + GST_ERROR("no buffer pool was negotiated"); + return NULL; + } +error_active_pool: + { + GST_ERROR("failed to activate buffer pool"); + return NULL; + } +error_map_dst_buffer: + { + gst_video_frame_unmap(&src_frame); + // fall-through + } +error_map_src_buffer: + { + GST_ERROR("failed to map buffer"); + gst_buffer_unref(outbuf); + return NULL; + } #else outbuf = gst_vaapi_uploader_get_buffer(postproc->uploader); if (!outbuf) @@ -1056,6 +1106,7 @@ error_invalid_buffer: gst_buffer_copy_metadata(outbuf, inbuf, GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS); return outbuf; +#endif /* ERRORS */ error_create_buffer: @@ -1066,10 +1117,13 @@ error_create_buffer: error_copy_buffer: { GST_ERROR("failed to upload buffer to VA surface"); +#if GST_CHECK_VERSION(1,0,0) + gst_video_frame_unmap(&out_frame); + gst_video_frame_unmap(&src_frame); +#endif gst_buffer_unref(outbuf); return NULL; } -#endif } static GstFlowReturn -- 2.7.4