From 30f382fcdfb9ff790ce23aae7a076ad6fdf7b606 Mon Sep 17 00:00:00 2001 From: Gwenole Beauchesne Date: Thu, 28 Nov 2013 15:56:53 +0100 Subject: [PATCH] vaapiencode: optimize _handle_frame() to avoid extra allocation. Optimize gst_vaapiencode_handle_frame() to avoid extra memory allocation, and in particular the GstVaapiEncObjUserData object. i.e. directly use the VA surface proxy from the source buffer. This also makes the user data attached to the GstVideoCodecFrame more consistent between both the decoder and encoder plug-in elements. --- gst-libs/gst/vaapi/gstvaapiencoder_objects.c | 30 ++--- gst-libs/gst/vaapi/gstvaapiencoder_objects.h | 6 +- gst/vaapi/gstvaapiencode.c | 111 +++++++++---------- 3 files changed, 66 insertions(+), 81 deletions(-) diff --git a/gst-libs/gst/vaapi/gstvaapiencoder_objects.c b/gst-libs/gst/vaapi/gstvaapiencoder_objects.c index e87538ce17..2a6173625a 100644 --- a/gst-libs/gst/vaapi/gstvaapiencoder_objects.c +++ b/gst-libs/gst/vaapi/gstvaapiencoder_objects.c @@ -25,6 +25,7 @@ #include "gstvaapiencoder_objects.h" #include "gstvaapiencoder.h" #include "gstvaapiencoder_priv.h" +#include "gstvaapisurfaceproxy_priv.h" #include "gstvaapiutils.h" #define DEBUG 1 @@ -387,7 +388,7 @@ gst_vaapi_enc_picture_destroy (GstVaapiEncPicture * picture) gst_vaapi_mini_object_replace ( (GstVaapiMiniObject **) (&picture->sequence), NULL); - g_assert (picture->surface); + gst_vaapi_surface_proxy_replace (&picture->proxy, NULL); picture->surface_id = VA_INVALID_ID; picture->surface = NULL; @@ -405,19 +406,22 @@ gboolean gst_vaapi_enc_picture_create (GstVaapiEncPicture * picture, const GstVaapiCodecObjectConstructorArgs * args) { - GstVideoCodecFrame *frame; - GstVaapiSurface *surface; - GstVaapiEncObjUserDataHead *user_data; + GstVideoCodecFrame *const frame = (GstVideoCodecFrame *)args->data; gboolean success; - g_assert (args->data); - g_return_val_if_fail (args->data, FALSE); + g_return_val_if_fail (frame != NULL, FALSE); - frame = (GstVideoCodecFrame *) args->data; - user_data = gst_video_codec_frame_get_user_data (frame); - g_assert (user_data); - surface = user_data->surface; - g_return_val_if_fail (surface, FALSE); + picture->proxy = gst_video_codec_frame_get_user_data (frame); + if (!gst_vaapi_surface_proxy_ref (picture->proxy)) + return FALSE; + + picture->surface = GST_VAAPI_SURFACE_PROXY_SURFACE (picture->proxy); + if (!picture->surface) + return FALSE; + + picture->surface_id = GST_VAAPI_OBJECT_ID (picture->surface); + if (picture->surface_id == VA_INVALID_ID) + return FALSE; picture->sequence = NULL; picture->type = GST_VAAPI_PICTURE_TYPE_NONE; @@ -446,10 +450,6 @@ gst_vaapi_enc_picture_create (GstVaapiEncPicture * picture, return FALSE; picture->frame = gst_video_codec_frame_ref (frame); - picture->surface = surface; - g_assert (picture->surface); - picture->surface_id = gst_vaapi_surface_get_id (picture->surface); - g_assert (picture->surface_id != VA_INVALID_SURFACE); return TRUE; } diff --git a/gst-libs/gst/vaapi/gstvaapiencoder_objects.h b/gst-libs/gst/vaapi/gstvaapiencoder_objects.h index 240d55b521..fdc960ee24 100644 --- a/gst-libs/gst/vaapi/gstvaapiencoder_objects.h +++ b/gst-libs/gst/vaapi/gstvaapiencoder_objects.h @@ -261,11 +261,6 @@ typedef enum #define GST_VAAPI_ENC_PICTURE_GET_FRAME(picture) \ (picture)->frame -typedef struct -{ - GstVaapiSurface *surface; -} GstVaapiEncObjUserDataHead; - /** * GstVaapiEncPicture: * @@ -276,6 +271,7 @@ struct _GstVaapiEncPicture /*< private > */ GstVaapiCodecObject parent_instance; GstVideoCodecFrame *frame; + GstVaapiSurfaceProxy *proxy; GstVaapiSurface *surface; GstVaapiEncSequence *sequence; /*< private >, picture packed header */ diff --git a/gst/vaapi/gstvaapiencode.c b/gst/vaapi/gstvaapiencode.c index 86b630c9b5..a6bab1360d 100644 --- a/gst/vaapi/gstvaapiencode.c +++ b/gst/vaapi/gstvaapiencode.c @@ -41,12 +41,6 @@ #define GST_VAAPI_ENCODE_FLOW_CONVERT_ERROR GST_FLOW_CUSTOM_ERROR_1 #define GST_VAAPI_ENCODE_FLOW_CODEC_DATA_ERROR GST_FLOW_CUSTOM_ERROR_2 -typedef struct _GstVaapiEncodeFrameUserData -{ - GstVaapiEncObjUserDataHead head; - GstBuffer *vaapi_buf; -} GstVaapiEncodeFrameUserData; - GST_DEBUG_CATEGORY_STATIC (gst_vaapiencode_debug); #define GST_CAT_DEFAULT gst_vaapiencode_debug @@ -630,7 +624,6 @@ get_source_buffer (GstVaapiEncode * encode, GstBuffer * src_buffer, gboolean success; #endif - *out_buffer_ptr = NULL; meta = gst_buffer_get_vaapi_video_meta (src_buffer); if (meta) { *out_buffer_ptr = gst_buffer_ref (src_buffer); @@ -728,77 +721,73 @@ error_copy_buffer: } } -static inline gpointer -_create_user_data (GstBuffer * buf) -{ - GstVaapiVideoMeta *meta; - GstVaapiSurface *surface; - GstVaapiEncodeFrameUserData *user_data; - - meta = gst_buffer_get_vaapi_video_meta (buf); - if (!meta) { - GST_DEBUG ("convert to vaapi buffer failed"); - return NULL; - } - surface = gst_vaapi_video_meta_get_surface (meta); - if (!surface) { - GST_DEBUG ("vaapi_meta of codec frame doesn't have vaapisurfaceproxy"); - return NULL; - } - - user_data = g_slice_new0 (GstVaapiEncodeFrameUserData); - user_data->head.surface = surface; - user_data->vaapi_buf = gst_buffer_ref (buf); - return user_data; -} - -static void -_destroy_user_data (gpointer data) -{ - GstVaapiEncodeFrameUserData *user_data = (GstVaapiEncodeFrameUserData *) data; - - g_assert (data); - if (!user_data) - return; - gst_buffer_replace (&user_data->vaapi_buf, NULL); - g_slice_free (GstVaapiEncodeFrameUserData, user_data); -} - static GstFlowReturn gst_vaapiencode_handle_frame (GstVideoEncoder * venc, GstVideoCodecFrame * frame) { GstVaapiEncode *const encode = GST_VAAPIENCODE_CAST (venc); - GstFlowReturn ret = GST_FLOW_OK; - GstVaapiEncoderStatus status = GST_VAAPI_ENCODER_STATUS_SUCCESS; + GstVaapiEncoderStatus status; + GstVaapiVideoMeta *meta; + GstVaapiSurfaceProxy *proxy; + GstFlowReturn ret; GstBuffer *buf; - gpointer user_data; - - g_assert (encode && encode->encoder); - g_assert (frame && frame->input_buffer); + buf = NULL; ret = get_source_buffer (encode, frame->input_buffer, &buf); if (ret != GST_FLOW_OK) - return ret; + goto error_buffer_invalid; - user_data = _create_user_data (buf); - GST_VAAPI_ENCODER_CHECK_STATUS (user_data, - ret, "create frame user data failed"); + gst_buffer_replace (&frame->input_buffer, buf); + gst_buffer_unref (buf); - gst_video_codec_frame_set_user_data (frame, user_data, _destroy_user_data); + meta = gst_buffer_get_vaapi_video_meta (buf); + if (!meta) + goto error_buffer_no_meta; + + proxy = gst_vaapi_video_meta_get_surface_proxy (meta); + if (!proxy) + goto error_buffer_no_surface_proxy; + + gst_video_codec_frame_set_user_data (frame, + gst_vaapi_surface_proxy_ref (proxy), + (GDestroyNotify)gst_vaapi_surface_proxy_unref); GST_VIDEO_ENCODER_STREAM_UNLOCK (encode); - /*encoding frames */ status = gst_vaapi_encoder_put_frame (encode->encoder, frame); GST_VIDEO_ENCODER_STREAM_LOCK (encode); + if (status < GST_VAAPI_ENCODER_STATUS_SUCCESS) + goto error_encode_frame; - GST_VAAPI_ENCODER_CHECK_STATUS (GST_VAAPI_ENCODER_STATUS_SUCCESS <= - status, GST_FLOW_ERROR, "gst_vaapiencoder_encode failed."); - -end: gst_video_codec_frame_unref (frame); - gst_buffer_replace (&buf, NULL); - return ret; + return GST_FLOW_OK; + + /* ERRORS */ +error_buffer_invalid: + { + if (buf) + gst_buffer_unref (buf); + gst_video_codec_frame_unref (frame); + return ret; + } +error_buffer_no_meta: + { + GST_ERROR ("failed to get GstVaapiVideoMeta information"); + gst_video_codec_frame_unref (frame); + return GST_FLOW_ERROR; + } +error_buffer_no_surface_proxy: + { + GST_ERROR ("failed to get VA surface proxy"); + gst_video_codec_frame_unref (frame); + return GST_FLOW_ERROR; + } +error_encode_frame: + { + GST_ERROR ("failed to encode frame %d (status %d)", + frame->system_frame_number, status); + gst_video_codec_frame_unref (frame); + return GST_FLOW_ERROR; + } } static GstFlowReturn