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 <gwenole.beauchesne@intel.com>
This commit is contained in:
Matthew Waters 2014-07-29 16:22:01 +10:00 committed by Gwenole Beauchesne
parent 1afcede093
commit 6003596e82

View file

@ -439,19 +439,20 @@ gst_vaapidecode_decode_loop(GstVaapiDecode *decode)
decode->decoder_loop_status = ret; decode->decoder_loop_status = ret;
GST_VIDEO_DECODER_STREAM_UNLOCK(vdec); GST_VIDEO_DECODER_STREAM_UNLOCK(vdec);
if (ret == GST_FLOW_OK)
return;
/* If invoked from gst_vaapidecode_finish(), then return right /* If invoked from gst_vaapidecode_finish(), then return right
away no matter the errors, or the GstVaapiDecoder needs further away no matter the errors, or the GstVaapiDecoder needs further
data to complete decoding (there no more data to feed in) */ data to complete decoding (there no more data to feed in) */
if (decode->decoder_finish) { if (decode->decoder_finish) {
g_mutex_lock(&decode->decoder_mutex); g_mutex_lock(&decode->decoder_mutex);
decode->decoder_loop_status = GST_FLOW_EOS;
g_cond_signal(&decode->decoder_finish_done); g_cond_signal(&decode->decoder_finish_done);
g_mutex_unlock(&decode->decoder_mutex); g_mutex_unlock(&decode->decoder_mutex);
return; return;
} }
if (ret == GST_FLOW_OK)
return;
/* Suspend the task if an error occurred */ /* Suspend the task if an error occurred */
if (ret != GST_VIDEO_DECODER_FLOW_NEED_DATA) if (ret != GST_VIDEO_DECODER_FLOW_NEED_DATA)
gst_pad_pause_task(GST_VAAPI_PLUGIN_BASE_SRC_PAD(decode)); 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 /* Make sure the decode loop function has a chance to return, thus
possibly unlocking gst_video_decoder_finish_frame() */ possibly unlocking gst_video_decoder_finish_frame() */
decode->decoder_finish = TRUE;
if (decode->decoder_loop_status == GST_FLOW_OK) {
GST_VIDEO_DECODER_STREAM_UNLOCK(vdec); GST_VIDEO_DECODER_STREAM_UNLOCK(vdec);
g_mutex_lock(&decode->decoder_mutex); g_mutex_lock(&decode->decoder_mutex);
decode->decoder_finish = TRUE; while (decode->decoder_loop_status != GST_FLOW_OK)
g_cond_wait(&decode->decoder_finish_done, &decode->decoder_mutex); g_cond_wait(&decode->decoder_finish_done, &decode->decoder_mutex);
g_mutex_unlock(&decode->decoder_mutex); g_mutex_unlock(&decode->decoder_mutex);
gst_pad_stop_task(GST_VAAPI_PLUGIN_BASE_SRC_PAD(decode)); gst_pad_stop_task(GST_VAAPI_PLUGIN_BASE_SRC_PAD(decode));
GST_VIDEO_DECODER_STREAM_LOCK(vdec); GST_VIDEO_DECODER_STREAM_LOCK(vdec);
}
return ret; return ret;
} }