From 6003596e82b9aaaa699135f89bd7839ae7792cb7 Mon Sep 17 00:00:00 2001 From: Matthew Waters Date: Tue, 29 Jul 2014 16:22:01 +1000 Subject: [PATCH] vaapidecode: properly return from decode loop on downstream errors. Fixes a hang/race on shutdown where _decode_loop() had already completed its execution and _finish() was waiting on a GCond for decode_loop() to complete. Also fixes the possible race where _finish() is called but _decode_loop() endlessly returns before signalling completion iff the decoder instance returns GST_FLOW_OK. Found with: ... ! vaapidecode ! {glimagesink,cluttersink} https://bugzilla.gnome.org/show_bug.cgi?id=733897 [factored out GST_VIDEO_DECODER_STREAM_UNLOCK() call] Signed-off-by: Gwenole Beauchesne --- gst/vaapi/gstvaapidecode.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/gst/vaapi/gstvaapidecode.c b/gst/vaapi/gstvaapidecode.c index 49dd455e1f..6d93f33d99 100644 --- a/gst/vaapi/gstvaapidecode.c +++ b/gst/vaapi/gstvaapidecode.c @@ -439,19 +439,20 @@ gst_vaapidecode_decode_loop(GstVaapiDecode *decode) decode->decoder_loop_status = ret; GST_VIDEO_DECODER_STREAM_UNLOCK(vdec); - if (ret == GST_FLOW_OK) - return; - /* If invoked from gst_vaapidecode_finish(), then return right away no matter the errors, or the GstVaapiDecoder needs further data to complete decoding (there no more data to feed in) */ if (decode->decoder_finish) { g_mutex_lock(&decode->decoder_mutex); + decode->decoder_loop_status = GST_FLOW_EOS; g_cond_signal(&decode->decoder_finish_done); g_mutex_unlock(&decode->decoder_mutex); return; } + if (ret == GST_FLOW_OK) + return; + /* Suspend the task if an error occurred */ if (ret != GST_VIDEO_DECODER_FLOW_NEED_DATA) gst_pad_pause_task(GST_VAAPI_PLUGIN_BASE_SRC_PAD(decode)); @@ -494,13 +495,16 @@ gst_vaapidecode_finish(GstVideoDecoder *vdec) /* Make sure the decode loop function has a chance to return, thus possibly unlocking gst_video_decoder_finish_frame() */ - GST_VIDEO_DECODER_STREAM_UNLOCK(vdec); - g_mutex_lock(&decode->decoder_mutex); decode->decoder_finish = TRUE; - g_cond_wait(&decode->decoder_finish_done, &decode->decoder_mutex); - g_mutex_unlock(&decode->decoder_mutex); - gst_pad_stop_task(GST_VAAPI_PLUGIN_BASE_SRC_PAD(decode)); - GST_VIDEO_DECODER_STREAM_LOCK(vdec); + if (decode->decoder_loop_status == GST_FLOW_OK) { + GST_VIDEO_DECODER_STREAM_UNLOCK(vdec); + g_mutex_lock(&decode->decoder_mutex); + while (decode->decoder_loop_status != GST_FLOW_OK) + g_cond_wait(&decode->decoder_finish_done, &decode->decoder_mutex); + g_mutex_unlock(&decode->decoder_mutex); + gst_pad_stop_task(GST_VAAPI_PLUGIN_BASE_SRC_PAD(decode)); + GST_VIDEO_DECODER_STREAM_LOCK(vdec); + } return ret; }