From 84af15179643b402530ad53d8ac7cd4e8636e2ea Mon Sep 17 00:00:00 2001 From: Gwenole Beauchesne Date: Tue, 26 Nov 2013 15:31:03 +0100 Subject: [PATCH] vaapiencode: fix support for raw YUV sink buffers. Allow vaapiencode plug-in elements to encode from raw YUV buffers. The most efficient way to do so is to let the vaapiencode elements allocate a buffer pool, and subsequently buffers from it. This means that upstream elements are expected to honour downstream pools. If upstream elements insist on providing their own allocated buffers to the vaapiencode elements, then it possibly would be more efficient to insert a vaapipostproc element before the vaapiencode element. This is because vaapipostproc currently has better support than other elements for "foreign" raw YUV buffers. --- gst/vaapi/gstvaapiencode.c | 85 +++++++++++++++++++++++++--------------- gst/vaapi/gstvaapiencode_h264.c | 4 +- gst/vaapi/gstvaapiencode_mpeg2.c | 7 ++-- 3 files changed, 59 insertions(+), 37 deletions(-) diff --git a/gst/vaapi/gstvaapiencode.c b/gst/vaapi/gstvaapiencode.c index 2568832..eea6abf 100644 --- a/gst/vaapi/gstvaapiencode.c +++ b/gst/vaapi/gstvaapiencode.c @@ -541,13 +541,13 @@ gst_vaapiencode_reset (GstVideoEncoder * venc, gboolean hard) } static GstFlowReturn -gst_vaapiencode_get_vaapi_buffer (GstVaapiEncode * encode, - GstBuffer * src_buffer, GstBuffer ** out_buffer_ptr) +get_source_buffer (GstVaapiEncode * encode, GstBuffer * src_buffer, + GstBuffer ** out_buffer_ptr) { GstVaapiVideoMeta *meta; GstBuffer *out_buffer; GstVideoFrame src_frame, out_frame; - GstFlowReturn ret; + gboolean success; *out_buffer_ptr = NULL; meta = gst_buffer_get_vaapi_video_meta (src_buffer); @@ -556,12 +556,8 @@ gst_vaapiencode_get_vaapi_buffer (GstVaapiEncode * encode, return GST_FLOW_OK; } - if (!GST_VIDEO_INFO_IS_YUV (&encode->sink_video_info)) { - GST_ERROR ("unsupported video buffer"); - return GST_FLOW_EOS; - } - - GST_DEBUG ("buffer %p not from our pool, copying", src_buffer); + if (!GST_VIDEO_INFO_IS_YUV (&encode->sink_video_info)) + goto error_invalid_buffer; if (!encode->video_buffer_pool) goto error_no_pool; @@ -569,9 +565,10 @@ gst_vaapiencode_get_vaapi_buffer (GstVaapiEncode * encode, if (!gst_buffer_pool_set_active (encode->video_buffer_pool, TRUE)) goto error_activate_pool; - ret = gst_buffer_pool_acquire_buffer (encode->video_buffer_pool, - &out_buffer, NULL); - if (ret != GST_FLOW_OK) + out_buffer = NULL; + success = gst_buffer_pool_acquire_buffer (encode->video_buffer_pool, + &out_buffer, NULL) == GST_FLOW_OK; + if (!success) goto error_create_buffer; if (!gst_video_frame_map (&src_frame, &encode->sink_video_info, src_buffer, @@ -582,30 +579,56 @@ gst_vaapiencode_get_vaapi_buffer (GstVaapiEncode * encode, GST_MAP_WRITE)) goto error_map_dst_buffer; - gst_video_frame_copy (&out_frame, &src_frame); + success = gst_video_frame_copy (&out_frame, &src_frame); gst_video_frame_unmap (&out_frame); gst_video_frame_unmap (&src_frame); + if (!success) + goto error_copy_buffer; + + gst_buffer_copy_into (out_buffer, src_buffer, GST_BUFFER_COPY_TIMESTAMPS, 0, + -1); *out_buffer_ptr = out_buffer; return GST_FLOW_OK; /* ERRORS */ +error_invalid_buffer: + { + GST_ERROR ("unsupported video buffer"); + return GST_FLOW_EOS; + } error_no_pool: - GST_ERROR ("no buffer pool was negotiated"); - return GST_FLOW_ERROR; + { + GST_ERROR ("no buffer pool was negotiated"); + return GST_FLOW_ERROR; + } error_activate_pool: - GST_ERROR ("failed to activate buffer pool"); - return GST_FLOW_ERROR; + { + GST_ERROR ("failed to activate buffer pool"); + return GST_FLOW_ERROR; + } error_create_buffer: - GST_WARNING ("failed to create image. Skipping this frame"); - return GST_FLOW_OK; + { + GST_WARNING ("failed to create buffer. Skipping this frame"); + return GST_FLOW_OK; + } error_map_dst_buffer: - gst_video_frame_unmap (&src_frame); - // fall-through + { + gst_video_frame_unmap (&src_frame); + // fall-through + } error_map_src_buffer: - GST_WARNING ("failed to map buffer. Skipping this frame"); - gst_buffer_unref (out_buffer); - return GST_FLOW_OK; + { + GST_WARNING ("failed to map buffer. Skipping this frame"); + gst_buffer_unref (out_buffer); + return GST_FLOW_OK; + } +error_copy_buffer: + { + GST_WARNING ("failed to upload buffer to VA surface. Skipping this frame"); + gst_buffer_unref (out_buffer); + return GST_FLOW_OK; + } } static inline gpointer @@ -651,19 +674,17 @@ gst_vaapiencode_handle_frame (GstVideoEncoder * venc, GstVaapiEncode *const encode = GST_VAAPIENCODE (venc); GstFlowReturn ret = GST_FLOW_OK; GstVaapiEncoderStatus encoder_ret = GST_VAAPI_ENCODER_STATUS_SUCCESS; - GstBuffer *vaapi_buf = NULL; + GstBuffer *buf; gpointer user_data; g_assert (encode && encode->encoder); g_assert (frame && frame->input_buffer); - ret = - gst_vaapiencode_get_vaapi_buffer (encode, frame->input_buffer, - &vaapi_buf); - GST_VAAPI_ENCODER_CHECK_STATUS (ret == GST_FLOW_OK, ret, - "convert to vaapi buffer failed"); + ret = get_source_buffer (encode, frame->input_buffer, &buf); + if (ret != GST_FLOW_OK) + return ret; - user_data = _create_user_data (vaapi_buf); + user_data = _create_user_data (buf); GST_VAAPI_ENCODER_CHECK_STATUS (user_data, ret, "create frame user data failed"); @@ -679,7 +700,7 @@ gst_vaapiencode_handle_frame (GstVideoEncoder * venc, end: gst_video_codec_frame_unref (frame); - gst_buffer_replace (&vaapi_buf, NULL); + gst_buffer_replace (&buf, NULL); return ret; } diff --git a/gst/vaapi/gstvaapiencode_h264.c b/gst/vaapi/gstvaapiencode_h264.c index 221cfbf..2f9293c 100644 --- a/gst/vaapi/gstvaapiencode_h264.c +++ b/gst/vaapi/gstvaapiencode_h264.c @@ -43,10 +43,10 @@ static const char gst_vaapiencode_h264_sink_caps_str[] = GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_VAAPI_SURFACE, "{ ENCODED, NV12, I420, YV12 }") ", " #else - GST_VIDEO_CAPS_MAKE (GST_VIDEO_FORMATS_ALL) ", " - GST_CAPS_INTERLACED_FALSE "; " GST_VAAPI_SURFACE_CAPS ", " #endif + GST_CAPS_INTERLACED_FALSE "; " + GST_VIDEO_CAPS_MAKE (GST_VIDEO_FORMATS_ALL) ", " GST_CAPS_INTERLACED_FALSE; static const char gst_vaapiencode_h264_src_caps_str[] = diff --git a/gst/vaapi/gstvaapiencode_mpeg2.c b/gst/vaapi/gstvaapiencode_mpeg2.c index 46f501f..2bd9677 100644 --- a/gst/vaapi/gstvaapiencode_mpeg2.c +++ b/gst/vaapi/gstvaapiencode_mpeg2.c @@ -42,11 +42,12 @@ static const char gst_vaapiencode_mpeg2_sink_caps_str[] = #if GST_CHECK_VERSION(1,1,0) GST_VIDEO_CAPS_MAKE_WITH_FEATURES(GST_CAPS_FEATURE_MEMORY_VAAPI_SURFACE, "{ ENCODED, NV12, I420, YV12 }") ", " - GST_CAPS_INTERLACED_FALSE; #else - GST_VIDEO_CAPS_MAKE (GST_VIDEO_FORMATS_ALL) "; " - GST_VAAPI_SURFACE_CAPS; + GST_VAAPI_SURFACE_CAPS ", " #endif + GST_CAPS_INTERLACED_FALSE "; " + GST_VIDEO_CAPS_MAKE (GST_VIDEO_FORMATS_ALL) ", " + GST_CAPS_INTERLACED_FALSE; static const char gst_vaapiencode_mpeg2_src_caps_str[] = GST_CAPS_CODEC ("video/mpeg," -- 2.7.4