vaapidecode: properly return from decode loop on downstream errors.
authorMatthew Waters <ystreet00@gmail.com>
Tue, 29 Jul 2014 06:22:01 +0000 (16:22 +1000)
committerGwenole Beauchesne <gwenole.beauchesne@intel.com>
Tue, 29 Jul 2014 08:21:02 +0000 (10:21 +0200)
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>
gst/vaapi/gstvaapidecode.c

index 49dd455..6d93f33 100644 (file)
@@ -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;
 }