[GStreamer] Fix deadlock when shutting down AudioDestination
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 16 Dec 2014 08:17:58 +0000 (08:17 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 16 Dec 2014 08:17:58 +0000 (08:17 +0000)
https://bugs.webkit.org/show_bug.cgi?id=139496

Patch by Sebastian Dröge <sebastian@centricular.com> on 2014-12-16
Reviewed by Philippe Normand.

* platform/audio/gstreamer/WebKitWebAudioSourceGStreamer.cpp:
(webKitWebAudioSrcLoop):
(webKitWebAudioSrcChangeState):
Sometimes we would wait forever for the task to shut down. This
was happening because of a bug in GStreamer that caused joining
a paused task to deadlock.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@177341 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/platform/audio/gstreamer/WebKitWebAudioSourceGStreamer.cpp

index f0bef15..5129681 100644 (file)
@@ -1,3 +1,17 @@
+2014-12-16  Sebastian Dröge  <sebastian@centricular.com>
+
+        [GStreamer] Fix deadlock when shutting down AudioDestination
+        https://bugs.webkit.org/show_bug.cgi?id=139496
+
+        Reviewed by Philippe Normand.
+
+        * platform/audio/gstreamer/WebKitWebAudioSourceGStreamer.cpp:
+        (webKitWebAudioSrcLoop):
+        (webKitWebAudioSrcChangeState):
+        Sometimes we would wait forever for the task to shut down. This
+        was happening because of a bug in GStreamer that caused joining
+        a paused task to deadlock.
+
 2014-12-15  Dhi Aurrahman  <diorahman@rockybars.com>
 
         Extend :lang()'s selector checker to handle ranges with '*' properly and perform matching within the ASCII range
index 5c08a18..8ed1eb6 100644 (file)
@@ -314,7 +314,7 @@ static void webKitWebAudioSrcLoop(WebKitWebAudioSrc* src)
     ASSERT(priv->provider);
     if (!priv->provider || !priv->bus) {
         GST_ELEMENT_ERROR(src, CORE, FAILED, ("Internal WebAudioSrc error"), ("Can't start without provider or bus"));
-        gst_task_pause(src->priv->task.get());
+        gst_task_stop(src->priv->task.get());
         return;
     }
 
@@ -339,8 +339,11 @@ static void webKitWebAudioSrcLoop(WebKitWebAudioSrc* src)
                 g_free(buffer);
                 channelBufferList = g_slist_delete_link(channelBufferList, channelBufferList);
             }
-            GST_ELEMENT_ERROR(src, CORE, PAD, ("Internal WebAudioSrc error"), ("Failed to allocate buffer for flow: %s", gst_flow_get_name(ret)));
-            gst_task_pause(src->priv->task.get());
+
+            // FLUSHING and EOS are not errors.
+            if (ret < GST_FLOW_EOS || ret == GST_FLOW_NOT_LINKED)
+                GST_ELEMENT_ERROR(src, CORE, PAD, ("Internal WebAudioSrc error"), ("Failed to allocate buffer for flow: %s", gst_flow_get_name(ret)));
+            gst_task_stop(src->priv->task.get());
             return;
         }
 
@@ -359,6 +362,7 @@ static void webKitWebAudioSrcLoop(WebKitWebAudioSrc* src)
     GSList* sourcesIt = priv->sources;
     GSList* buffersIt = channelBufferList;
 
+    GstFlowReturn ret = GST_FLOW_OK;
     for (i = 0; sourcesIt && buffersIt; sourcesIt = g_slist_next(sourcesIt), buffersIt = g_slist_next(buffersIt), ++i) {
         GstElement* appsrc = static_cast<GstElement*>(sourcesIt->data);
         AudioSrcBuffer* buffer = static_cast<AudioSrcBuffer*>(buffersIt->data);
@@ -368,11 +372,16 @@ static void webKitWebAudioSrcLoop(WebKitWebAudioSrc* src)
         gst_buffer_unmap(channelBuffer, &buffer->info);
         g_free(buffer);
 
-        GstFlowReturn ret = gst_app_src_push_buffer(GST_APP_SRC(appsrc), channelBuffer);
-        if (ret != GST_FLOW_OK) {
-            GST_ELEMENT_ERROR(src, CORE, PAD, ("Internal WebAudioSrc error"), ("Failed to push buffer on %s flow: %s", GST_OBJECT_NAME(appsrc), gst_flow_get_name(ret)));
-            gst_task_pause(src->priv->task.get());
-        }
+        if (ret == GST_FLOW_OK) {
+            ret = gst_app_src_push_buffer(GST_APP_SRC(appsrc), channelBuffer);
+            if (ret != GST_FLOW_OK) {
+                // FLUSHING and EOS are not errors.
+                if (ret < GST_FLOW_EOS || ret == GST_FLOW_NOT_LINKED)
+                    GST_ELEMENT_ERROR(src, CORE, PAD, ("Internal WebAudioSrc error"), ("Failed to push buffer on %s flow: %s", GST_OBJECT_NAME(appsrc), gst_flow_get_name(ret)));
+                gst_task_stop(src->priv->task.get());
+            }
+        } else
+            gst_buffer_unref(channelBuffer);
     }
 
     g_slist_free(channelBufferList);
@@ -417,6 +426,9 @@ static GstStateChangeReturn webKitWebAudioSrcChangeState(GstElement* element, Gs
     }
     case GST_STATE_CHANGE_PAUSED_TO_READY:
         GST_DEBUG_OBJECT(src, "PAUSED->READY");
+#if GST_CHECK_VERSION(1, 4, 0)
+        gst_buffer_pool_set_flushing(src->priv->pool, TRUE);
+#endif
         if (!gst_task_join(src->priv->task.get()))
             returnValue = GST_STATE_CHANGE_FAILURE;
         gst_buffer_pool_set_active(src->priv->pool, FALSE);