commit 770626df1c60f82dd0925fefde4701d655c4447e
Author: Dave Craig <dcraig@brightsign.biz>
Date:   Mon Aug 7 14:56:21 2017 +0100

    adaptivedemux: Stop prepared streams as well as running streams
    
    There can be twice as many stream tasks running as there are output
    pads for playback of variant HLS playlists. Half of them are the
    current pads, and the other half are the pads that are about to be
    switched to due to a bitrate change.
    The old code only stopped the current streams which could result
    in a deadlock on stopping the pipeline. The changes force stopping
    and joining of any prepared streams too.

diff --git a/gst-libs/gst/adaptivedemux/gstadaptivedemux.c b/gst-libs/gst/adaptivedemux/gstadaptivedemux.c
index 28ddac0a1..d430a48ed 100644
--- a/gst-libs/gst/adaptivedemux/gstadaptivedemux.c
+++ b/gst-libs/gst/adaptivedemux/gstadaptivedemux.c
@@ -1989,20 +1989,27 @@ gst_adaptive_demux_start_manifest_update_task (GstAdaptiveDemux * demux)
 static void
 gst_adaptive_demux_stop_tasks (GstAdaptiveDemux * demux, gboolean stop_updates)
 {
+  int i;
   GList *iter;
+  GList *list_to_process;
 
   GST_LOG_OBJECT (demux, "Stopping tasks");
 
   if (stop_updates)
     gst_adaptive_demux_stop_manifest_update_task (demux);
-  for (iter = demux->streams; iter; iter = g_list_next (iter)) {
-    GstAdaptiveDemuxStream *stream = iter->data;
 
-    g_mutex_lock (&stream->fragment_download_lock);
-    stream->cancelled = TRUE;
-    gst_task_stop (stream->download_task);
-    g_cond_signal (&stream->fragment_download_cond);
-    g_mutex_unlock (&stream->fragment_download_lock);
+  list_to_process = demux->streams;
+  for (i = 0; i < 2; ++i) {
+    for (iter = list_to_process; iter; iter = g_list_next (iter)) {
+      GstAdaptiveDemuxStream *stream = iter->data;
+
+      g_mutex_lock (&stream->fragment_download_lock);
+      stream->cancelled = TRUE;
+      gst_task_stop (stream->download_task);
+      g_cond_signal (&stream->fragment_download_cond);
+      g_mutex_unlock (&stream->fragment_download_lock);
+    }
+    list_to_process = demux->prepared_streams;
   }
 
   GST_MANIFEST_UNLOCK (demux);
@@ -2020,23 +2027,27 @@ gst_adaptive_demux_stop_tasks (GstAdaptiveDemux * demux, gboolean stop_updates)
    * object. Even if we temporarily release manifest_lock, the demux->streams
    * cannot change and iter cannot be invalidated.
    */
-  for (iter = demux->streams; iter; iter = g_list_next (iter)) {
-    GstAdaptiveDemuxStream *stream = iter->data;
-    GstElement *src = stream->src;
+  list_to_process = demux->streams;
+  for (i = 0; i < 2; ++i) {
+    for (iter = list_to_process; iter; iter = g_list_next (iter)) {
+      GstAdaptiveDemuxStream *stream = iter->data;
+      GstElement *src = stream->src;
 
-    GST_MANIFEST_UNLOCK (demux);
+      GST_MANIFEST_UNLOCK (demux);
 
-    if (src) {
-      gst_element_set_locked_state (src, TRUE);
-      gst_element_set_state (src, GST_STATE_READY);
-    }
+      if (src) {
+        gst_element_set_locked_state (src, TRUE);
+        gst_element_set_state (src, GST_STATE_READY);
+      }
 
-    /* stream->download_task value never changes, so it is safe to read it
-     * outside critical section
-     */
-    gst_task_join (stream->download_task);
+      /* stream->download_task value never changes, so it is safe to read it
+       * outside critical section
+       */
+      gst_task_join (stream->download_task);
 
-    GST_MANIFEST_LOCK (demux);
+      GST_MANIFEST_LOCK (demux);
+    }
+    list_to_process = demux->prepared_streams;
   }
 
   GST_MANIFEST_UNLOCK (demux);
@@ -2045,11 +2056,15 @@ gst_adaptive_demux_stop_tasks (GstAdaptiveDemux * demux, gboolean stop_updates)
 
   GST_MANIFEST_LOCK (demux);
 
-  for (iter = demux->streams; iter; iter = g_list_next (iter)) {
-    GstAdaptiveDemuxStream *stream = iter->data;
+  list_to_process = demux->streams;
+  for (i = 0; i < 2; ++i) {
+    for (iter = list_to_process; iter; iter = g_list_next (iter)) {
+      GstAdaptiveDemuxStream *stream = iter->data;
 
-    stream->download_error_count = 0;
-    stream->need_header = TRUE;
+      stream->download_error_count = 0;
+      stream->need_header = TRUE;
+    }
+    list_to_process = demux->prepared_streams;
   }
 }
 
