From 533f11ac090c475fcceedcc9caf70ba766561541 Mon Sep 17 00:00:00 2001 From: Zhong Cong Date: Tue, 9 Apr 2013 16:33:03 +0800 Subject: [PATCH] vaapidecode: fix surface timeout error --- gst-libs/gst/vaapi/gstvaapidecoder.c | 21 ++++++++++++--- gst-libs/gst/vaapi/gstvaapidecoder.h | 3 ++- gst/vaapi/gstvaapidecode.c | 47 ++++++++++++++++++++-------------- gst/vaapi/gstvaapidecode.h | 1 + tests/test-decode.c | 3 ++- tests/test-subpicture.c | 3 ++- 6 files changed, 52 insertions(+), 26 deletions(-) diff --git a/gst-libs/gst/vaapi/gstvaapidecoder.c b/gst-libs/gst/vaapi/gstvaapidecoder.c index 0df566d..dad1e4b 100644 --- a/gst-libs/gst/vaapi/gstvaapidecoder.c +++ b/gst-libs/gst/vaapi/gstvaapidecoder.c @@ -90,7 +90,7 @@ pop_buffer(GstVaapiDecoder *decoder) } static GstVaapiDecoderStatus -decode_step(GstVaapiDecoder *decoder) +decode_step(GstVaapiDecoder *decoder, gboolean *try_again) { GstVaapiDecoderStatus status; GstBuffer *buffer; @@ -101,12 +101,23 @@ decode_step(GstVaapiDecoder *decoder) 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); @@ -413,6 +424,7 @@ gst_vaapi_decoder_put_buffer(GstVaapiDecoder *decoder, GstBuffer *buf) * 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. @@ -424,7 +436,8 @@ gst_vaapi_decoder_put_buffer(GstVaapiDecoder *decoder, GstBuffer *buf) GstVaapiSurfaceProxy * gst_vaapi_decoder_get_surface( GstVaapiDecoder *decoder, - GstVaapiDecoderStatus *pstatus + GstVaapiDecoderStatus *pstatus, + gboolean *try_again ) { GstVaapiSurfaceProxy *proxy; @@ -438,7 +451,7 @@ gst_vaapi_decoder_get_surface( 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); } diff --git a/gst-libs/gst/vaapi/gstvaapidecoder.h b/gst-libs/gst/vaapi/gstvaapidecoder.h index ebcead9..d935b1d 100644 --- a/gst-libs/gst/vaapi/gstvaapidecoder.h +++ b/gst-libs/gst/vaapi/gstvaapidecoder.h @@ -129,7 +129,8 @@ gst_vaapi_decoder_put_buffer(GstVaapiDecoder *decoder, GstBuffer *buf); GstVaapiSurfaceProxy * gst_vaapi_decoder_get_surface( GstVaapiDecoder *decoder, - GstVaapiDecoderStatus *pstatus + GstVaapiDecoderStatus *pstatus, + gboolean *try_again ); void diff --git a/gst/vaapi/gstvaapidecode.c b/gst/vaapi/gstvaapidecode.c index 5e2c8ef..33587e7 100644 --- a/gst/vaapi/gstvaapidecode.c +++ b/gst/vaapi/gstvaapidecode.c @@ -199,29 +199,27 @@ gst_vaapidecode_step(GstVaapiDecode *decode) 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; @@ -271,10 +269,13 @@ gst_vaapidecode_step(GstVaapiDecode *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: @@ -538,6 +539,10 @@ gst_vaapidecode_change_state(GstElement *element, GstStateChange transition) 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); @@ -707,7 +712,6 @@ gst_vaapidecode_sink_event(GstPad *pad, GstEvent *event) 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: @@ -727,6 +731,10 @@ gst_vaapidecode_sink_event(GstPad *pad, GstEvent *event) 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"); } @@ -778,6 +786,7 @@ gst_vaapidecode_init(GstVaapiDecode *decode) 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); diff --git a/gst/vaapi/gstvaapidecode.h b/gst/vaapi/gstvaapidecode.h index c8b2583..a15aeb3 100644 --- a/gst/vaapi/gstvaapidecode.h +++ b/gst/vaapi/gstvaapidecode.h @@ -76,6 +76,7 @@ struct _GstVaapiDecode { gint64 render_time_base; GstClockTime last_buffer_time; unsigned int is_ready : 1; + gboolean break_flag; }; struct _GstVaapiDecodeClass { diff --git a/tests/test-decode.c b/tests/test-decode.c index 458416e..81eb7ff 100644 --- a/tests/test-decode.c +++ b/tests/test-decode.c @@ -179,7 +179,8 @@ main(int argc, char *argv[]) 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); diff --git a/tests/test-subpicture.c b/tests/test-subpicture.c index 7a65fe3..89643d7 100644 --- a/tests/test-subpicture.c +++ b/tests/test-subpicture.c @@ -157,7 +157,8 @@ main(int argc, char *argv[]) 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); -- 1.7.9.5