PROP_CODEC,
};
+static gboolean
+gst_vaapi_decoder_start(GstVaapiDecoder *decoder);
+
+static gboolean
+gst_vaapi_decoder_stop(GstVaapiDecoder *decoder);
+
static gpointer
decoder_thread_cb(gpointer data)
{
g_object_ref(decoder);
status = klass->decode(decoder);
g_object_unref(decoder);
+
+ /* Detect End-of-Stream conditions */
+ if (status != GST_VAAPI_DECODER_STATUS_SUCCESS &&
+ priv->is_eos &&
+ gst_vaapi_decoder_read_avail(decoder) == 0)
+ status = GST_VAAPI_DECODER_STATUS_END_OF_STREAM;
+
GST_DEBUG("decode frame (status = %d)", status);
}
else {
g_mutex_unlock(priv->adapter_mutex);
/* Signal the main thread we got an error */
- gst_vaapi_decoder_push_surface(decoder, NULL);
+ if (status != GST_VAAPI_DECODER_STATUS_END_OF_STREAM)
+ gst_vaapi_decoder_push_surface(decoder, NULL);
}
}
+
+ /* End-of-Stream reached, decoder thread is no longer necessary */
+ if (status == GST_VAAPI_DECODER_STATUS_END_OF_STREAM)
+ break;
}
return NULL;
}
{
GstBuffer *buffer;
+ if (!buf || !buf_size)
+ return NULL;
+
buffer = gst_buffer_new();
if (!buffer)
return NULL;
{
GstVaapiDecoderPrivate * const priv = decoder->priv;
- if (!buffer)
- return FALSE;
+ if (!buffer) {
+ priv->is_eos = TRUE;
+ return TRUE;
+ }
g_return_val_if_fail(priv->adapter_mutex && priv->adapter_cond, FALSE);
GST_DEBUG("queue encoded data buffer %p (%d bytes)",
buffer, GST_BUFFER_SIZE(buffer));
+ if (!priv->decoder_thread && !gst_vaapi_decoder_start(decoder))
+ return FALSE;
+
/* XXX: add a mechanism to wait for enough buffer bytes to be consumed */
g_mutex_lock(priv->adapter_mutex);
gst_adapter_push(priv->adapter, buffer);
g_cond_signal(priv->adapter_cond);
g_mutex_unlock(priv->adapter_mutex);
-
- if (!priv->decoder_thread) {
- priv->decoder_thread = g_thread_create(
- decoder_thread_cb, decoder,
- TRUE,
- NULL
- );
- if (!priv->decoder_thread)
- return FALSE;
- }
return TRUE;
}
static void
gst_vaapi_decoder_finalize(GObject *object)
{
- GstVaapiDecoderPrivate * const priv = GST_VAAPI_DECODER(object)->priv;
+ GstVaapiDecoder * const decoder = GST_VAAPI_DECODER(object);
+ GstVaapiDecoderPrivate * const priv = decoder->priv;
- if (priv->decoder_thread) {
- priv->decoder_thread_cancel = TRUE;
- if (priv->adapter_mutex && priv->adapter_cond) {
- g_mutex_lock(priv->adapter_mutex);
- g_cond_signal(priv->adapter_cond);
- g_mutex_unlock(priv->adapter_mutex);
- }
- g_thread_join(priv->decoder_thread);
- priv->decoder_thread = NULL;
- }
+ gst_vaapi_decoder_stop(decoder);
if (priv->adapter) {
gst_adapter_clear(priv->adapter);
priv->surfaces_cond = g_cond_new();
priv->decoder_thread = NULL;
priv->decoder_thread_cancel = FALSE;
+ priv->is_eos = FALSE;
g_queue_init(&priv->surfaces);
}
/**
+ * gst_vaapi_decoder_start:
+ * @decoder: a #GstVaapiDecoder
+ *
+ * Starts the decoder. This creates the internal decoder thread, if
+ * necessary.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gst_vaapi_decoder_start(GstVaapiDecoder *decoder)
+{
+ /* This is an internal function */
+ GstVaapiDecoderPrivate * const priv = decoder->priv;
+
+ if (!priv->decoder_thread) {
+ priv->decoder_thread = g_thread_create(
+ decoder_thread_cb, decoder,
+ TRUE,
+ NULL
+ );
+ if (!priv->decoder_thread)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * gst_vaapi_decoder_stop:
+ * @decoder: a #GstVaapiDecoder
+ *
+ * Stops the decoder. This destroys any decoding thread that was
+ * previously created by gst_vaapi_decoder_start(). Only
+ * gst_vaapi_decoder_get_surface() on the queued surfaces will be
+ * allowed at this point.
+ *
+ * Return value: %FALSE on success
+ */
+gboolean
+gst_vaapi_decoder_stop(GstVaapiDecoder *decoder)
+{
+ /* This is an internal function */
+ GstVaapiDecoderPrivate * const priv = decoder->priv;
+
+ if (priv->decoder_thread) {
+ priv->decoder_thread_cancel = TRUE;
+ if (priv->adapter_mutex && priv->adapter_cond) {
+ g_mutex_lock(priv->adapter_mutex);
+ g_cond_signal(priv->adapter_cond);
+ g_mutex_unlock(priv->adapter_mutex);
+ }
+ g_thread_join(priv->decoder_thread);
+ priv->decoder_thread = NULL;
+ }
+ return TRUE;
+}
+
+/**
* gst_vaapi_decoder_put_buffer_data:
* @decoder: a #GstVaapiDecoder
* @buf: pointer to buffer data
)
{
g_return_val_if_fail(GST_VAAPI_IS_DECODER(decoder), FALSE);
- g_return_val_if_fail(buf, FALSE);
- g_return_val_if_fail(buf_size > 0, FALSE);
return push_buffer(decoder, create_buffer(buf, buf_size, FALSE));
}
)
{
g_return_val_if_fail(GST_VAAPI_IS_DECODER(decoder), FALSE);
- g_return_val_if_fail(buf, FALSE);
- g_return_val_if_fail(buf_size > 0, FALSE);
return push_buffer(decoder, create_buffer(buf, buf_size, TRUE));
}
gst_vaapi_decoder_put_buffer(GstVaapiDecoder *decoder, GstBuffer *buf)
{
g_return_val_if_fail(GST_VAAPI_IS_DECODER(decoder), FALSE);
- g_return_val_if_fail(GST_IS_BUFFER(buf), FALSE);
- return push_buffer(decoder, gst_buffer_ref(buf));
+ return push_buffer(decoder, buf ? gst_buffer_ref(buf) : NULL);
}
/**