mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-25 17:50:36 +00:00
Use a GstTask with start/stop semantics for the decoder thread.
This commit is contained in:
parent
5f5ed724dd
commit
2356ceb0d9
3 changed files with 59 additions and 53 deletions
|
@ -52,11 +52,8 @@ enum {
|
||||||
PROP_CODEC_DATA
|
PROP_CODEC_DATA
|
||||||
};
|
};
|
||||||
|
|
||||||
static gboolean
|
/* Wait _at most_ 10 ms for encoded buffers between each decoding step */
|
||||||
gst_vaapi_decoder_start(GstVaapiDecoder *decoder);
|
#define GST_VAAPI_DECODER_TIMEOUT (10000)
|
||||||
|
|
||||||
static gboolean
|
|
||||||
gst_vaapi_decoder_stop(GstVaapiDecoder *decoder);
|
|
||||||
|
|
||||||
static GstBuffer *
|
static GstBuffer *
|
||||||
pop_buffer(GstVaapiDecoder *decoder);
|
pop_buffer(GstVaapiDecoder *decoder);
|
||||||
|
@ -67,19 +64,21 @@ push_surface(GstVaapiDecoder *decoder, GstVaapiSurface *surface);
|
||||||
static DecodedSurface *
|
static DecodedSurface *
|
||||||
pop_surface(GstVaapiDecoder *decoder, GTimeVal *end_time);
|
pop_surface(GstVaapiDecoder *decoder, GTimeVal *end_time);
|
||||||
|
|
||||||
static gpointer
|
static void
|
||||||
decoder_thread_cb(gpointer data)
|
decoder_task(gpointer data)
|
||||||
{
|
{
|
||||||
GstVaapiDecoder * const decoder = data;
|
GstVaapiDecoder * const decoder = GST_VAAPI_DECODER_CAST(data);
|
||||||
GstVaapiDecoderPrivate * const priv = decoder->priv;
|
GstVaapiDecoderPrivate * const priv = decoder->priv;
|
||||||
GstVaapiDecoderClass * const klass = GST_VAAPI_DECODER_GET_CLASS(decoder);
|
GstVaapiDecoderClass * const klass = GST_VAAPI_DECODER_GET_CLASS(decoder);
|
||||||
GstBuffer *buffer;
|
GstBuffer *buffer;
|
||||||
|
|
||||||
g_object_ref(decoder);
|
|
||||||
while (!priv->decoder_thread_cancel) {
|
|
||||||
buffer = pop_buffer(decoder);
|
buffer = pop_buffer(decoder);
|
||||||
|
if (!buffer)
|
||||||
|
return;
|
||||||
|
|
||||||
priv->decoder_status = klass->decode(decoder, buffer);
|
priv->decoder_status = klass->decode(decoder, buffer);
|
||||||
GST_DEBUG("decode frame (status = %d)", priv->decoder_status);
|
GST_DEBUG("decode frame (status = %d)", priv->decoder_status);
|
||||||
|
|
||||||
switch (priv->decoder_status) {
|
switch (priv->decoder_status) {
|
||||||
case GST_VAAPI_DECODER_STATUS_SUCCESS:
|
case GST_VAAPI_DECODER_STATUS_SUCCESS:
|
||||||
case GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA:
|
case GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA:
|
||||||
|
@ -87,13 +86,9 @@ decoder_thread_cb(gpointer data)
|
||||||
default:
|
default:
|
||||||
/* Send an empty surface to signal an error */
|
/* Send an empty surface to signal an error */
|
||||||
push_surface(decoder, NULL);
|
push_surface(decoder, NULL);
|
||||||
priv->decoder_thread_cancel = TRUE;
|
gst_task_pause(priv->decoder_task);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
gst_buffer_unref(buffer);
|
|
||||||
}
|
|
||||||
g_object_unref(decoder);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -182,9 +177,6 @@ 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_SIZE(buffer));
|
buffer, GST_BUFFER_SIZE(buffer));
|
||||||
|
|
||||||
if (!priv->decoder_thread && !gst_vaapi_decoder_start(decoder))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
g_async_queue_push(priv->buffers, buffer);
|
g_async_queue_push(priv->buffers, buffer);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -193,10 +185,15 @@ static GstBuffer *
|
||||||
pop_buffer(GstVaapiDecoder *decoder)
|
pop_buffer(GstVaapiDecoder *decoder)
|
||||||
{
|
{
|
||||||
GstVaapiDecoderPrivate * const priv = decoder->priv;
|
GstVaapiDecoderPrivate * const priv = decoder->priv;
|
||||||
|
GTimeVal end_time;
|
||||||
GstBuffer *buffer;
|
GstBuffer *buffer;
|
||||||
|
|
||||||
buffer = g_async_queue_pop(priv->buffers);
|
g_get_current_time(&end_time);
|
||||||
g_return_val_if_fail(buffer, NULL);
|
g_time_val_add(&end_time, GST_VAAPI_DECODER_TIMEOUT);
|
||||||
|
|
||||||
|
buffer = g_async_queue_timed_pop(priv->buffers, &end_time);
|
||||||
|
if (!buffer)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
GST_DEBUG("dequeue buffer %p for decoding (%d bytes)",
|
GST_DEBUG("dequeue buffer %p for decoding (%d bytes)",
|
||||||
buffer, GST_BUFFER_SIZE(buffer));
|
buffer, GST_BUFFER_SIZE(buffer));
|
||||||
|
@ -251,6 +248,9 @@ pop_surface(GstVaapiDecoder *decoder, GTimeVal *end_time)
|
||||||
{
|
{
|
||||||
GstVaapiDecoderPrivate * const priv = decoder->priv;
|
GstVaapiDecoderPrivate * const priv = decoder->priv;
|
||||||
|
|
||||||
|
if (!gst_vaapi_decoder_start(decoder))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
return g_async_queue_timed_pop(priv->surfaces, end_time);
|
return g_async_queue_timed_pop(priv->surfaces, end_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -423,8 +423,9 @@ gst_vaapi_decoder_init(GstVaapiDecoder *decoder)
|
||||||
priv->surface_duration = GST_CLOCK_TIME_NONE;
|
priv->surface_duration = GST_CLOCK_TIME_NONE;
|
||||||
priv->buffers = g_async_queue_new();
|
priv->buffers = g_async_queue_new();
|
||||||
priv->surfaces = g_async_queue_new();
|
priv->surfaces = g_async_queue_new();
|
||||||
priv->decoder_thread = NULL;
|
priv->decoder_task = NULL;
|
||||||
priv->decoder_thread_cancel = FALSE;
|
|
||||||
|
g_static_rec_mutex_init(&priv->decoder_task_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -442,16 +443,15 @@ gst_vaapi_decoder_start(GstVaapiDecoder *decoder)
|
||||||
/* This is an internal function */
|
/* This is an internal function */
|
||||||
GstVaapiDecoderPrivate * const priv = decoder->priv;
|
GstVaapiDecoderPrivate * const priv = decoder->priv;
|
||||||
|
|
||||||
if (!priv->decoder_thread) {
|
if (priv->decoder_task)
|
||||||
priv->decoder_thread = g_thread_create(
|
|
||||||
decoder_thread_cb, decoder,
|
|
||||||
TRUE,
|
|
||||||
NULL
|
|
||||||
);
|
|
||||||
if (!priv->decoder_thread)
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
priv->decoder_task = gst_task_create(decoder_task, decoder);
|
||||||
|
if (!priv->decoder_task)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
gst_task_set_lock(priv->decoder_task, &priv->decoder_task_lock);
|
||||||
|
return gst_task_start(priv->decoder_task);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -470,14 +470,14 @@ gst_vaapi_decoder_stop(GstVaapiDecoder *decoder)
|
||||||
{
|
{
|
||||||
/* This is an internal function */
|
/* This is an internal function */
|
||||||
GstVaapiDecoderPrivate * const priv = decoder->priv;
|
GstVaapiDecoderPrivate * const priv = decoder->priv;
|
||||||
|
gboolean success;
|
||||||
|
|
||||||
if (priv->decoder_thread) {
|
if (!priv->decoder_task)
|
||||||
push_buffer(decoder, NULL);
|
return FALSE;
|
||||||
priv->decoder_thread_cancel = TRUE;
|
|
||||||
g_thread_join(priv->decoder_thread);
|
success = gst_task_join(priv->decoder_task);
|
||||||
priv->decoder_thread = NULL;
|
priv->decoder_task = NULL;
|
||||||
}
|
return success;
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -124,6 +124,12 @@ gst_vaapi_decoder_set_frame_rate(
|
||||||
guint den
|
guint den
|
||||||
);
|
);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gst_vaapi_decoder_start(GstVaapiDecoder *decoder);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gst_vaapi_decoder_stop(GstVaapiDecoder *decoder);
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
gst_vaapi_decoder_put_buffer_data(
|
gst_vaapi_decoder_put_buffer_data(
|
||||||
GstVaapiDecoder *decoder,
|
GstVaapiDecoder *decoder,
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#define GST_VAAPI_DECODER_PRIV_H
|
#define GST_VAAPI_DECODER_PRIV_H
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <gst/base/gstadapter.h>
|
#include <gst/gsttask.h>
|
||||||
#include <gst/vaapi/gstvaapidecoder.h>
|
#include <gst/vaapi/gstvaapidecoder.h>
|
||||||
#include <gst/vaapi/gstvaapicontext.h>
|
#include <gst/vaapi/gstvaapicontext.h>
|
||||||
|
|
||||||
|
@ -97,9 +97,9 @@ struct _GstVaapiDecoderPrivate {
|
||||||
GAsyncQueue *surfaces;
|
GAsyncQueue *surfaces;
|
||||||
GstClockTime surface_timestamp;
|
GstClockTime surface_timestamp;
|
||||||
GstClockTime surface_duration;
|
GstClockTime surface_duration;
|
||||||
GThread *decoder_thread;
|
GstTask *decoder_task;
|
||||||
|
GStaticRecMutex decoder_task_lock;
|
||||||
GstVaapiDecoderStatus decoder_status;
|
GstVaapiDecoderStatus decoder_status;
|
||||||
guint decoder_thread_cancel : 1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
|
|
Loading…
Reference in a new issue