}
static GstVaapiDecoderStatus
-decode_step(GstVaapiDecoder *decoder)
+decode_step(GstVaapiDecoder *decoder, gboolean *try_again)
{
GstVaapiDecoderStatus status;
GstBuffer *buffer;
return status;
do {
- buffer = pop_buffer(decoder);
+ if (*try_again){
+ buffer = gst_buffer_new();
+ if (buffer){
+ gst_buffer_set_data(buffer, NULL, 0);
+ }
+ *try_again = FALSE;
+ }else{
+ buffer = pop_buffer(decoder);
+ }
if (!buffer)
return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
status = GST_VAAPI_DECODER_GET_CLASS(decoder)->decode(decoder, buffer);
GST_DEBUG("decode frame (status = %d)", status);
+ if (status == GST_VAAPI_DECODER_STATUS_ERROR_NO_SURFACE) {
+ *try_again = TRUE;
+ }
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS && GST_BUFFER_IS_EOS(buffer))
status = GST_VAAPI_DECODER_STATUS_END_OF_STREAM;
gst_buffer_unref(buffer);
* gst_vaapi_decoder_get_surface:
* @decoder: a #GstVaapiDecoder
* @pstatus: return location for the decoder status, or %NULL
+ * @try_again: a #gboolean
*
* Flushes encoded buffers to the decoder and returns a decoded
* surface, if any.
GstVaapiSurfaceProxy *
gst_vaapi_decoder_get_surface(
GstVaapiDecoder *decoder,
- GstVaapiDecoderStatus *pstatus
+ GstVaapiDecoderStatus *pstatus,
+ gboolean *try_again
)
{
GstVaapiSurfaceProxy *proxy;
proxy = pop_surface(decoder);
if (!proxy) {
do {
- status = decode_step(decoder);
+ status = decode_step(decoder, try_again);
} while (status == GST_VAAPI_DECODER_STATUS_SUCCESS);
proxy = pop_surface(decoder);
}
GstVaapiSurfaceProxy *
gst_vaapi_decoder_get_surface(
GstVaapiDecoder *decoder,
- GstVaapiDecoderStatus *pstatus
+ GstVaapiDecoderStatus *pstatus,
+ gboolean *try_again
);
void
GstBuffer *buffer;
GstFlowReturn ret;
GstClockTime timestamp;
- gint64 end_time;
+ gboolean try_again = FALSE;
for (;;) {
- end_time = decode->render_time_base;
- if (!end_time)
- end_time = g_get_monotonic_time();
- end_time += GST_TIME_AS_USECONDS(decode->last_buffer_time);
- end_time += G_TIME_SPAN_SECOND;
-
- proxy = gst_vaapi_decoder_get_surface(decode->decoder, &status);
+ proxy = gst_vaapi_decoder_get_surface(decode->decoder, &status, &try_again);
+ try_again = FALSE;
if (!proxy) {
if (status == GST_VAAPI_DECODER_STATUS_ERROR_NO_SURFACE) {
- gboolean was_signalled;
g_mutex_lock(&decode->decoder_mutex);
- was_signalled = g_cond_wait_until(
+ if (decode->break_flag){
+ goto handle_break_flag;
+ }
+ g_cond_wait(
&decode->decoder_ready,
- &decode->decoder_mutex,
- end_time
+ &decode->decoder_mutex
);
+ if (decode->break_flag){
+ goto handle_break_flag;
+ }
g_mutex_unlock(&decode->decoder_mutex);
- if (was_signalled)
- continue;
- goto error_decode_timeout;
+ try_again = TRUE;
+ continue;
}
if (status != GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA)
goto error_decode;
return GST_FLOW_OK;
/* ERRORS */
-error_decode_timeout:
+handle_break_flag:
+ {
+ g_mutex_unlock(&decode->decoder_mutex);
+ goto error_receive_event;
+ }
+error_receive_event:
{
- GST_DEBUG("decode timeout. Decoder required a VA surface but none "
- "got available within one second");
return GST_FLOW_UNEXPECTED;
}
error_decode:
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
+ g_mutex_lock(&decode->decoder_mutex);
+ decode->break_flag = TRUE;
+ g_cond_signal(&decode->decoder_ready);
+ g_mutex_unlock(&decode->decoder_mutex);
break;
case GST_STATE_CHANGE_READY_TO_NULL:
gst_vaapidecode_destroy(decode);
GstVaapiDecode * const decode = GST_VAAPIDECODE(GST_OBJECT_PARENT(pad));
GST_DEBUG("handle sink event '%s'", GST_EVENT_TYPE_NAME(event));
-
/* Propagate event downstream */
switch (GST_EVENT_TYPE(event)) {
case GST_EVENT_FLUSH_STOP:
gst_vaapidecode_configure_segment(decode, event);
break;
case GST_EVENT_EOS:
+ g_mutex_lock(&decode->decoder_mutex);
+ decode->break_flag = TRUE;
+ g_cond_signal(&decode->decoder_ready);
+ g_mutex_unlock(&decode->decoder_mutex);
if (!gst_vaapidecode_flush(decode)) {
GST_WARNING("failed to flush buffers");
}
decode->render_time_base = 0;
decode->last_buffer_time = 0;
decode->is_ready = FALSE;
+ decode->break_flag = FALSE;
g_mutex_init(&decode->decoder_mutex);
g_cond_init(&decode->decoder_ready);
gint64 render_time_base;
GstClockTime last_buffer_time;
unsigned int is_ready : 1;
+ gboolean break_flag;
};
struct _GstVaapiDecodeClass {
if (!gst_vaapi_decoder_put_buffer(decoder, NULL))
g_error("could not send EOS to the decoder");
- proxy = gst_vaapi_decoder_get_surface(decoder, &status);
+ gboolean try_again = FALSE;
+ proxy = gst_vaapi_decoder_get_surface(decoder, &status, &try_again);
if (!proxy)
g_error("could not get decoded surface (decoder status %d)", status);
if (!gst_vaapi_decoder_put_buffer(decoder, NULL))
g_error("could not send EOS to the decoder");
- proxy = gst_vaapi_decoder_get_surface(decoder, &status);
+ gboolean try_again = FALSE;
+ proxy = gst_vaapi_decoder_get_surface(decoder, &status, &try_again);
if (!proxy)
g_error("could not get decoded surface (decoder status %d)", status);