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.
This commit is contained in:
Gwenole Beauchesne 2013-11-28 15:56:53 +01:00
parent 081ff63f9a
commit 30f382fcdf
3 changed files with 66 additions and 81 deletions

View file

@ -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;
}

View file

@ -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 */

View file

@ -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