mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-07-16 11:28:36 +00:00
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:
parent
081ff63f9a
commit
30f382fcdf
|
@ -25,6 +25,7 @@
|
||||||
#include "gstvaapiencoder_objects.h"
|
#include "gstvaapiencoder_objects.h"
|
||||||
#include "gstvaapiencoder.h"
|
#include "gstvaapiencoder.h"
|
||||||
#include "gstvaapiencoder_priv.h"
|
#include "gstvaapiencoder_priv.h"
|
||||||
|
#include "gstvaapisurfaceproxy_priv.h"
|
||||||
#include "gstvaapiutils.h"
|
#include "gstvaapiutils.h"
|
||||||
|
|
||||||
#define DEBUG 1
|
#define DEBUG 1
|
||||||
|
@ -387,7 +388,7 @@ gst_vaapi_enc_picture_destroy (GstVaapiEncPicture * picture)
|
||||||
gst_vaapi_mini_object_replace (
|
gst_vaapi_mini_object_replace (
|
||||||
(GstVaapiMiniObject **) (&picture->sequence), NULL);
|
(GstVaapiMiniObject **) (&picture->sequence), NULL);
|
||||||
|
|
||||||
g_assert (picture->surface);
|
gst_vaapi_surface_proxy_replace (&picture->proxy, NULL);
|
||||||
picture->surface_id = VA_INVALID_ID;
|
picture->surface_id = VA_INVALID_ID;
|
||||||
picture->surface = NULL;
|
picture->surface = NULL;
|
||||||
|
|
||||||
|
@ -405,19 +406,22 @@ gboolean
|
||||||
gst_vaapi_enc_picture_create (GstVaapiEncPicture * picture,
|
gst_vaapi_enc_picture_create (GstVaapiEncPicture * picture,
|
||||||
const GstVaapiCodecObjectConstructorArgs * args)
|
const GstVaapiCodecObjectConstructorArgs * args)
|
||||||
{
|
{
|
||||||
GstVideoCodecFrame *frame;
|
GstVideoCodecFrame *const frame = (GstVideoCodecFrame *)args->data;
|
||||||
GstVaapiSurface *surface;
|
|
||||||
GstVaapiEncObjUserDataHead *user_data;
|
|
||||||
gboolean success;
|
gboolean success;
|
||||||
|
|
||||||
g_assert (args->data);
|
g_return_val_if_fail (frame != NULL, FALSE);
|
||||||
g_return_val_if_fail (args->data, FALSE);
|
|
||||||
|
|
||||||
frame = (GstVideoCodecFrame *) args->data;
|
picture->proxy = gst_video_codec_frame_get_user_data (frame);
|
||||||
user_data = gst_video_codec_frame_get_user_data (frame);
|
if (!gst_vaapi_surface_proxy_ref (picture->proxy))
|
||||||
g_assert (user_data);
|
return FALSE;
|
||||||
surface = user_data->surface;
|
|
||||||
g_return_val_if_fail (surface, 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->sequence = NULL;
|
||||||
picture->type = GST_VAAPI_PICTURE_TYPE_NONE;
|
picture->type = GST_VAAPI_PICTURE_TYPE_NONE;
|
||||||
|
@ -446,10 +450,6 @@ gst_vaapi_enc_picture_create (GstVaapiEncPicture * picture,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
picture->frame = gst_video_codec_frame_ref (frame);
|
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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -261,11 +261,6 @@ typedef enum
|
||||||
#define GST_VAAPI_ENC_PICTURE_GET_FRAME(picture) \
|
#define GST_VAAPI_ENC_PICTURE_GET_FRAME(picture) \
|
||||||
(picture)->frame
|
(picture)->frame
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
GstVaapiSurface *surface;
|
|
||||||
} GstVaapiEncObjUserDataHead;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GstVaapiEncPicture:
|
* GstVaapiEncPicture:
|
||||||
*
|
*
|
||||||
|
@ -276,6 +271,7 @@ struct _GstVaapiEncPicture
|
||||||
/*< private > */
|
/*< private > */
|
||||||
GstVaapiCodecObject parent_instance;
|
GstVaapiCodecObject parent_instance;
|
||||||
GstVideoCodecFrame *frame;
|
GstVideoCodecFrame *frame;
|
||||||
|
GstVaapiSurfaceProxy *proxy;
|
||||||
GstVaapiSurface *surface;
|
GstVaapiSurface *surface;
|
||||||
GstVaapiEncSequence *sequence;
|
GstVaapiEncSequence *sequence;
|
||||||
/*< private >, picture packed header */
|
/*< private >, picture packed header */
|
||||||
|
|
|
@ -41,12 +41,6 @@
|
||||||
#define GST_VAAPI_ENCODE_FLOW_CONVERT_ERROR GST_FLOW_CUSTOM_ERROR_1
|
#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
|
#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);
|
GST_DEBUG_CATEGORY_STATIC (gst_vaapiencode_debug);
|
||||||
#define GST_CAT_DEFAULT gst_vaapiencode_debug
|
#define GST_CAT_DEFAULT gst_vaapiencode_debug
|
||||||
|
|
||||||
|
@ -630,7 +624,6 @@ get_source_buffer (GstVaapiEncode * encode, GstBuffer * src_buffer,
|
||||||
gboolean success;
|
gboolean success;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
*out_buffer_ptr = NULL;
|
|
||||||
meta = gst_buffer_get_vaapi_video_meta (src_buffer);
|
meta = gst_buffer_get_vaapi_video_meta (src_buffer);
|
||||||
if (meta) {
|
if (meta) {
|
||||||
*out_buffer_ptr = gst_buffer_ref (src_buffer);
|
*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
|
static GstFlowReturn
|
||||||
gst_vaapiencode_handle_frame (GstVideoEncoder * venc,
|
gst_vaapiencode_handle_frame (GstVideoEncoder * venc,
|
||||||
GstVideoCodecFrame * frame)
|
GstVideoCodecFrame * frame)
|
||||||
{
|
{
|
||||||
GstVaapiEncode *const encode = GST_VAAPIENCODE_CAST (venc);
|
GstVaapiEncode *const encode = GST_VAAPIENCODE_CAST (venc);
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstVaapiEncoderStatus status;
|
||||||
GstVaapiEncoderStatus status = GST_VAAPI_ENCODER_STATUS_SUCCESS;
|
GstVaapiVideoMeta *meta;
|
||||||
|
GstVaapiSurfaceProxy *proxy;
|
||||||
|
GstFlowReturn ret;
|
||||||
GstBuffer *buf;
|
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);
|
ret = get_source_buffer (encode, frame->input_buffer, &buf);
|
||||||
if (ret != GST_FLOW_OK)
|
if (ret != GST_FLOW_OK)
|
||||||
return ret;
|
goto error_buffer_invalid;
|
||||||
|
|
||||||
user_data = _create_user_data (buf);
|
gst_buffer_replace (&frame->input_buffer, buf);
|
||||||
GST_VAAPI_ENCODER_CHECK_STATUS (user_data,
|
gst_buffer_unref (buf);
|
||||||
ret, "create frame user data failed");
|
|
||||||
|
|
||||||
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);
|
GST_VIDEO_ENCODER_STREAM_UNLOCK (encode);
|
||||||
/*encoding frames */
|
|
||||||
status = gst_vaapi_encoder_put_frame (encode->encoder, frame);
|
status = gst_vaapi_encoder_put_frame (encode->encoder, frame);
|
||||||
GST_VIDEO_ENCODER_STREAM_LOCK (encode);
|
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_video_codec_frame_unref (frame);
|
||||||
gst_buffer_replace (&buf, NULL);
|
return GST_FLOW_OK;
|
||||||
return ret;
|
|
||||||
|
/* 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
|
static GstFlowReturn
|
||||||
|
|
Loading…
Reference in a new issue