mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-27 01:28:34 +00:00
decoder: add gst_vaapi_decoder_get_frame_with_timeout().
Add gst_vaapi_decoder_get_frame_with_timeout() helper function that will wait for a frame to be decoded, until the specified timeout in microseconds, prior to returning to the caller. This is a fix to performance regression from 851cc0, whereby the vaapidecode loop executed on the srcpad task was called to often, thus starving all CPU resources.
This commit is contained in:
parent
4b91e31a76
commit
c43a2d497a
5 changed files with 55 additions and 26 deletions
|
@ -426,6 +426,7 @@ gst_vaapi_decoder_get_codec_state
|
||||||
gst_vaapi_decoder_put_buffer
|
gst_vaapi_decoder_put_buffer
|
||||||
gst_vaapi_decoder_get_surface
|
gst_vaapi_decoder_get_surface
|
||||||
gst_vaapi_decoder_get_frame
|
gst_vaapi_decoder_get_frame
|
||||||
|
gst_vaapi_decoder_get_frame_with_timeout
|
||||||
gst_vaapi_decoder_parse
|
gst_vaapi_decoder_parse
|
||||||
gst_vaapi_decoder_decode
|
gst_vaapi_decoder_decode
|
||||||
<SUBSECTION Standard>
|
<SUBSECTION Standard>
|
||||||
|
|
|
@ -115,7 +115,7 @@ push_buffer(GstVaapiDecoder *decoder, GstBuffer *buffer)
|
||||||
GST_DEBUG("queue encoded data buffer %p (%d bytes)",
|
GST_DEBUG("queue encoded data buffer %p (%d bytes)",
|
||||||
buffer, gst_buffer_get_size(buffer));
|
buffer, gst_buffer_get_size(buffer));
|
||||||
|
|
||||||
g_queue_push_tail(priv->buffers, buffer);
|
g_async_queue_push(priv->buffers, buffer);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,7 +125,7 @@ pop_buffer(GstVaapiDecoder *decoder)
|
||||||
GstVaapiDecoderPrivate * const priv = decoder->priv;
|
GstVaapiDecoderPrivate * const priv = decoder->priv;
|
||||||
GstBuffer *buffer;
|
GstBuffer *buffer;
|
||||||
|
|
||||||
buffer = g_queue_pop_head(priv->buffers);
|
buffer = g_async_queue_try_pop(priv->buffers);
|
||||||
if (!buffer)
|
if (!buffer)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -381,7 +381,7 @@ drop_frame(GstVaapiDecoder *decoder, GstVideoCodecFrame *frame)
|
||||||
GST_VIDEO_CODEC_FRAME_FLAG_SET(frame,
|
GST_VIDEO_CODEC_FRAME_FLAG_SET(frame,
|
||||||
GST_VIDEO_CODEC_FRAME_FLAG_DECODE_ONLY);
|
GST_VIDEO_CODEC_FRAME_FLAG_DECODE_ONLY);
|
||||||
|
|
||||||
g_queue_push_tail(priv->frames, gst_video_codec_frame_ref(frame));
|
g_async_queue_push(priv->frames, gst_video_codec_frame_ref(frame));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
|
@ -393,17 +393,20 @@ push_frame(GstVaapiDecoder *decoder, GstVideoCodecFrame *frame)
|
||||||
GST_DEBUG("queue decoded surface %" GST_VAAPI_ID_FORMAT,
|
GST_DEBUG("queue decoded surface %" GST_VAAPI_ID_FORMAT,
|
||||||
GST_VAAPI_ID_ARGS(GST_VAAPI_SURFACE_PROXY_SURFACE_ID(proxy)));
|
GST_VAAPI_ID_ARGS(GST_VAAPI_SURFACE_PROXY_SURFACE_ID(proxy)));
|
||||||
|
|
||||||
g_queue_push_tail(priv->frames, gst_video_codec_frame_ref(frame));
|
g_async_queue_push(priv->frames, gst_video_codec_frame_ref(frame));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline GstVideoCodecFrame *
|
static inline GstVideoCodecFrame *
|
||||||
pop_frame(GstVaapiDecoder *decoder)
|
pop_frame(GstVaapiDecoder *decoder, guint64 timeout)
|
||||||
{
|
{
|
||||||
GstVaapiDecoderPrivate * const priv = decoder->priv;
|
GstVaapiDecoderPrivate * const priv = decoder->priv;
|
||||||
GstVideoCodecFrame *frame;
|
GstVideoCodecFrame *frame;
|
||||||
GstVaapiSurfaceProxy *proxy;
|
GstVaapiSurfaceProxy *proxy;
|
||||||
|
|
||||||
frame = g_queue_pop_head(priv->frames);
|
if (G_LIKELY(timeout > 0))
|
||||||
|
frame = g_async_queue_timeout_pop(priv->frames, timeout);
|
||||||
|
else
|
||||||
|
frame = g_async_queue_try_pop(priv->frames);
|
||||||
if (!frame)
|
if (!frame)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -448,13 +451,6 @@ get_caps(GstVaapiDecoder *decoder)
|
||||||
return GST_VAAPI_DECODER_CODEC_STATE(decoder)->caps;
|
return GST_VAAPI_DECODER_CODEC_STATE(decoder)->caps;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
clear_queue(GQueue *q, GDestroyNotify destroy)
|
|
||||||
{
|
|
||||||
while (!g_queue_is_empty(q))
|
|
||||||
destroy(g_queue_pop_head(q));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_vaapi_decoder_finalize(GObject *object)
|
gst_vaapi_decoder_finalize(GObject *object)
|
||||||
{
|
{
|
||||||
|
@ -467,15 +463,12 @@ gst_vaapi_decoder_finalize(GObject *object)
|
||||||
parser_state_finalize(&priv->parser_state);
|
parser_state_finalize(&priv->parser_state);
|
||||||
|
|
||||||
if (priv->buffers) {
|
if (priv->buffers) {
|
||||||
clear_queue(priv->buffers, (GDestroyNotify)gst_buffer_unref);
|
g_async_queue_unref(priv->buffers);
|
||||||
g_queue_free(priv->buffers);
|
|
||||||
priv->buffers = NULL;
|
priv->buffers = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv->frames) {
|
if (priv->frames) {
|
||||||
clear_queue(priv->frames, (GDestroyNotify)
|
g_async_queue_unref(priv->frames);
|
||||||
gst_video_codec_frame_unref);
|
|
||||||
g_queue_free(priv->frames);
|
|
||||||
priv->frames = NULL;
|
priv->frames = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -591,8 +584,10 @@ gst_vaapi_decoder_init(GstVaapiDecoder *decoder)
|
||||||
priv->va_context = VA_INVALID_ID;
|
priv->va_context = VA_INVALID_ID;
|
||||||
priv->codec = 0;
|
priv->codec = 0;
|
||||||
priv->codec_state = codec_state;
|
priv->codec_state = codec_state;
|
||||||
priv->buffers = g_queue_new();
|
|
||||||
priv->frames = g_queue_new();
|
priv->buffers = g_async_queue_new_full((GDestroyNotify)gst_buffer_unref);
|
||||||
|
priv->frames = g_async_queue_new_full((GDestroyNotify)
|
||||||
|
gst_video_codec_frame_unref);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -699,7 +694,7 @@ gst_vaapi_decoder_get_surface(GstVaapiDecoder *decoder,
|
||||||
GST_VAAPI_DECODER_STATUS_ERROR_INVALID_PARAMETER);
|
GST_VAAPI_DECODER_STATUS_ERROR_INVALID_PARAMETER);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
frame = pop_frame(decoder);
|
frame = pop_frame(decoder, 0);
|
||||||
while (frame) {
|
while (frame) {
|
||||||
if (!GST_VIDEO_CODEC_FRAME_IS_DECODE_ONLY(frame)) {
|
if (!GST_VIDEO_CODEC_FRAME_IS_DECODE_ONLY(frame)) {
|
||||||
GstVaapiSurfaceProxy * const proxy = frame->user_data;
|
GstVaapiSurfaceProxy * const proxy = frame->user_data;
|
||||||
|
@ -710,7 +705,7 @@ gst_vaapi_decoder_get_surface(GstVaapiDecoder *decoder,
|
||||||
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
gst_video_codec_frame_unref(frame);
|
gst_video_codec_frame_unref(frame);
|
||||||
frame = pop_frame(decoder);
|
frame = pop_frame(decoder, 0);
|
||||||
}
|
}
|
||||||
status = decode_step(decoder);
|
status = decode_step(decoder);
|
||||||
} while (status == GST_VAAPI_DECODER_STATUS_SUCCESS);
|
} while (status == GST_VAAPI_DECODER_STATUS_SUCCESS);
|
||||||
|
@ -734,11 +729,39 @@ gst_vaapi_decoder_get_surface(GstVaapiDecoder *decoder,
|
||||||
* to the user-data anchor of the output frame. Ownership of the proxy
|
* to the user-data anchor of the output frame. Ownership of the proxy
|
||||||
* is transferred to the frame.
|
* is transferred to the frame.
|
||||||
*
|
*
|
||||||
|
* This is equivalent to gst_vaapi_decoder_get_frame_with_timeout()
|
||||||
|
* with a timeout value of zero.
|
||||||
|
*
|
||||||
* Return value: a #GstVaapiDecoderStatus
|
* Return value: a #GstVaapiDecoderStatus
|
||||||
*/
|
*/
|
||||||
GstVaapiDecoderStatus
|
GstVaapiDecoderStatus
|
||||||
gst_vaapi_decoder_get_frame(GstVaapiDecoder *decoder,
|
gst_vaapi_decoder_get_frame(GstVaapiDecoder *decoder,
|
||||||
GstVideoCodecFrame **out_frame_ptr)
|
GstVideoCodecFrame **out_frame_ptr)
|
||||||
|
{
|
||||||
|
return gst_vaapi_decoder_get_frame_with_timeout(decoder, out_frame_ptr, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_vaapi_decoder_get_frame_with_timeout:
|
||||||
|
* @decoder: a #GstVaapiDecoder
|
||||||
|
* @out_frame_ptr: the next decoded frame as a #GstVideoCodecFrame
|
||||||
|
* @timeout: the number of microseconds to wait for the frame, at most
|
||||||
|
*
|
||||||
|
* On successful return, *@out_frame_ptr contains the next decoded
|
||||||
|
* frame available as a #GstVideoCodecFrame. The caller owns this
|
||||||
|
* object, so gst_video_codec_frame_unref() shall be called after
|
||||||
|
* usage. Otherwise, @GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA is
|
||||||
|
* returned if no decoded frame is available.
|
||||||
|
*
|
||||||
|
* The actual surface is available as a #GstVaapiSurfaceProxy attached
|
||||||
|
* to the user-data anchor of the output frame. Ownership of the proxy
|
||||||
|
* is transferred to the frame.
|
||||||
|
*
|
||||||
|
* Return value: a #GstVaapiDecoderStatus
|
||||||
|
*/
|
||||||
|
GstVaapiDecoderStatus
|
||||||
|
gst_vaapi_decoder_get_frame_with_timeout(GstVaapiDecoder *decoder,
|
||||||
|
GstVideoCodecFrame **out_frame_ptr, guint64 timeout)
|
||||||
{
|
{
|
||||||
GstVideoCodecFrame *out_frame;
|
GstVideoCodecFrame *out_frame;
|
||||||
|
|
||||||
|
@ -747,7 +770,7 @@ gst_vaapi_decoder_get_frame(GstVaapiDecoder *decoder,
|
||||||
g_return_val_if_fail(out_frame_ptr != NULL,
|
g_return_val_if_fail(out_frame_ptr != NULL,
|
||||||
GST_VAAPI_DECODER_STATUS_ERROR_INVALID_PARAMETER);
|
GST_VAAPI_DECODER_STATUS_ERROR_INVALID_PARAMETER);
|
||||||
|
|
||||||
out_frame = pop_frame(decoder);
|
out_frame = pop_frame(decoder, timeout);
|
||||||
if (!out_frame)
|
if (!out_frame)
|
||||||
return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
|
return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
|
||||||
|
|
||||||
|
|
|
@ -151,6 +151,10 @@ GstVaapiDecoderStatus
|
||||||
gst_vaapi_decoder_get_frame(GstVaapiDecoder *decoder,
|
gst_vaapi_decoder_get_frame(GstVaapiDecoder *decoder,
|
||||||
GstVideoCodecFrame **out_frame_ptr);
|
GstVideoCodecFrame **out_frame_ptr);
|
||||||
|
|
||||||
|
GstVaapiDecoderStatus
|
||||||
|
gst_vaapi_decoder_get_frame_with_timeout(GstVaapiDecoder *decoder,
|
||||||
|
GstVideoCodecFrame **out_frame_ptr, guint64 timeout);
|
||||||
|
|
||||||
GstVaapiDecoderStatus
|
GstVaapiDecoderStatus
|
||||||
gst_vaapi_decoder_parse(GstVaapiDecoder *decoder,
|
gst_vaapi_decoder_parse(GstVaapiDecoder *decoder,
|
||||||
GstVideoCodecFrame *frame, GstAdapter *adapter, gboolean at_eos,
|
GstVideoCodecFrame *frame, GstAdapter *adapter, gboolean at_eos,
|
||||||
|
|
|
@ -168,8 +168,8 @@ struct _GstVaapiDecoderPrivate {
|
||||||
VAContextID va_context;
|
VAContextID va_context;
|
||||||
GstVaapiCodec codec;
|
GstVaapiCodec codec;
|
||||||
GstVideoCodecState *codec_state;
|
GstVideoCodecState *codec_state;
|
||||||
GQueue *buffers;
|
GAsyncQueue *buffers;
|
||||||
GQueue *frames;
|
GAsyncQueue *frames;
|
||||||
GstVaapiParserState parser_state;
|
GstVaapiParserState parser_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -280,7 +280,8 @@ gst_vaapidecode_push_decoded_frame(GstVideoDecoder *vdec)
|
||||||
GstFlowReturn ret;
|
GstFlowReturn ret;
|
||||||
guint flags;
|
guint flags;
|
||||||
|
|
||||||
status = gst_vaapi_decoder_get_frame(decode->decoder, &out_frame);
|
status = gst_vaapi_decoder_get_frame_with_timeout(decode->decoder,
|
||||||
|
&out_frame, 100000);
|
||||||
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
|
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
|
||||||
return GST_VIDEO_DECODER_FLOW_NEED_DATA;
|
return GST_VIDEO_DECODER_FLOW_NEED_DATA;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue