From: Eunhye Choi Date: Wed, 26 Feb 2020 04:01:05 +0000 (+0900) Subject: adaptivedemux: resolve deadlock issue X-Git-Tag: submit/tizen_5.5/20200226.063151^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fheads%2Faccepted%2Ftizen_5.5_unified;p=platform%2Fupstream%2Fgst-plugins-bad.git adaptivedemux: resolve deadlock issue - adaptivedemux raise a deadlock issue in case of unstable network env. - get patch from upstream which is applied from 1.16.2 https://cgit.freedesktop.org/gstreamer/gst-plugins-bad/commit/?id=659d76a633641292be68459f5e4496c04059622d Change-Id: I9f9541e83d4528e78f242239b2fc7eaae29a9d24 --- diff --git a/ext/hls/gsthlsdemux.c b/ext/hls/gsthlsdemux.c index 8482a5ab4..06af13119 100644 --- a/ext/hls/gsthlsdemux.c +++ b/ext/hls/gsthlsdemux.c @@ -1519,7 +1519,8 @@ retry: if (download == NULL) { gchar *base_uri; - if (!update || main_checked || demux->master->is_simple) { + if (!update || main_checked || demux->master->is_simple + || !gst_adaptive_demux_is_running (GST_ADAPTIVE_DEMUX_CAST (demux))) { g_free (uri); return FALSE; } @@ -1774,7 +1775,7 @@ retry_failover_protection: if (changed) *changed = TRUE; stream->discont = TRUE; - } else { + } else if (gst_adaptive_demux_is_running (GST_ADAPTIVE_DEMUX_CAST (demux))) { GstHLSVariantStream *failover_variant = NULL; GList *failover; diff --git a/gst-libs/gst/adaptivedemux/gstadaptivedemux.c b/gst-libs/gst/adaptivedemux/gstadaptivedemux.c index 93ce1399c..7a7874a6e 100644 --- a/gst-libs/gst/adaptivedemux/gstadaptivedemux.c +++ b/gst-libs/gst/adaptivedemux/gstadaptivedemux.c @@ -176,7 +176,7 @@ enum struct _GstAdaptiveDemuxPrivate { GstAdapter *input_adapter; /* protected by manifest_lock */ - gboolean have_manifest; /* protected by manifest_lock */ + gint have_manifest; /* MT safe */ GList *old_streams; /* protected by manifest_lock */ @@ -610,25 +610,31 @@ gst_adaptive_demux_change_state (GstElement * element, GstAdaptiveDemux *demux = GST_ADAPTIVE_DEMUX_CAST (element); GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE; - GST_API_LOCK (demux); - switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: + if (g_atomic_int_compare_and_exchange (&demux->running, TRUE, FALSE)) + GST_DEBUG_OBJECT (demux, "demuxer has stopped running"); + gst_uri_downloader_cancel (demux->downloader); + + GST_API_LOCK (demux); GST_MANIFEST_LOCK (demux); - demux->running = FALSE; gst_adaptive_demux_reset (demux); GST_MANIFEST_UNLOCK (demux); + GST_API_UNLOCK (demux); break; case GST_STATE_CHANGE_READY_TO_PAUSED: + GST_API_LOCK (demux); GST_MANIFEST_LOCK (demux); gst_adaptive_demux_reset (demux); /* Clear "cancelled" flag in uridownloader since subclass might want to * use uridownloader to fetch another manifest */ gst_uri_downloader_reset (demux->downloader); - if (demux->priv->have_manifest) + if (g_atomic_int_get (&demux->priv->have_manifest)) gst_adaptive_demux_start_manifest_update_task (demux); - demux->running = TRUE; GST_MANIFEST_UNLOCK (demux); + GST_API_UNLOCK (demux); + if (g_atomic_int_compare_and_exchange (&demux->running, FALSE, TRUE)) + GST_DEBUG_OBJECT (demux, "demuxer has started running"); break; default: break; @@ -641,7 +647,6 @@ gst_adaptive_demux_change_state (GstElement * element, */ result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - GST_API_UNLOCK (demux); return result; } @@ -770,7 +775,7 @@ gst_adaptive_demux_sink_event (GstPad * pad, GstObject * parent, (NULL)); ret = FALSE; } else { - demux->priv->have_manifest = TRUE; + g_atomic_int_set (&demux->priv->have_manifest, TRUE); } gst_buffer_unref (manifest_buffer); @@ -948,7 +953,7 @@ gst_adaptive_demux_reset (GstAdaptiveDemux * demux) #endif gst_adapter_clear (demux->priv->input_adapter); - demux->priv->have_manifest = FALSE; + g_atomic_int_set (&demux->priv->have_manifest, FALSE); gst_segment_init (&demux->segment, GST_FORMAT_TIME); @@ -1233,7 +1238,7 @@ gst_adaptive_demux_prepare_streams (GstAdaptiveDemux * demux, demux->prepared_streams = demux->next_streams; demux->next_streams = NULL; - if (!demux->running) { + if (!gst_adaptive_demux_is_running (demux)) { GST_DEBUG_OBJECT (demux, "Not exposing pads due to shutdown"); return TRUE; } @@ -2025,7 +2030,7 @@ gst_adaptive_demux_src_event (GstPad * pad, GstObject * parent, stream = gst_adaptive_demux_find_stream_for_pad (demux, pad); if (stream) { - if (!stream->cancelled && demux->running && + if (!stream->cancelled && gst_adaptive_demux_is_running (demux) && stream->last_ret == GST_FLOW_NOT_LINKED) { stream->last_ret = GST_FLOW_OK; stream->restart_download = TRUE; @@ -2098,9 +2103,8 @@ gst_adaptive_demux_src_query (GstPad * pad, GstObject * parent, gst_query_parse_duration (query, &fmt, NULL); - GST_MANIFEST_LOCK (demux); - - if (fmt == GST_FORMAT_TIME && demux->priv->have_manifest) { + if (fmt == GST_FORMAT_TIME + && g_atomic_int_get (&demux->priv->have_manifest)) { duration = demux_class->get_duration (demux); if (GST_CLOCK_TIME_IS_VALID (duration) && duration > 0) { @@ -2109,8 +2113,6 @@ gst_adaptive_demux_src_query (GstPad * pad, GstObject * parent, } } - GST_MANIFEST_UNLOCK (demux); - GST_LOG_OBJECT (demux, "GST_QUERY_DURATION returns %s with duration %" GST_TIME_FORMAT, ret ? "TRUE" : "FALSE", GST_TIME_ARGS (duration)); break; @@ -2125,15 +2127,14 @@ gst_adaptive_demux_src_query (GstPad * pad, GstObject * parent, gint64 stop = -1; gint64 start = 0; - GST_MANIFEST_LOCK (demux); - - if (!demux->priv->have_manifest) { - GST_MANIFEST_UNLOCK (demux); + if (!g_atomic_int_get (&demux->priv->have_manifest)) { GST_INFO_OBJECT (demux, "Don't have manifest yet, can't answer seeking query"); return FALSE; /* can't answer without manifest */ } + GST_MANIFEST_LOCK (demux); + gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL); GST_INFO_OBJECT (demux, "Received GST_QUERY_SEEKING with format %d", fmt); if (fmt == GST_FORMAT_TIME) { @@ -2222,7 +2223,7 @@ gst_adaptive_demux_start_tasks (GstAdaptiveDemux * demux, { GList *iter; - if (!demux->running) { + if (!gst_adaptive_demux_is_running (demux)) { GST_DEBUG_OBJECT (demux, "Not starting tasks due to shutdown"); return; } @@ -4787,6 +4788,20 @@ gst_adaptive_demux_get_client_now_utc (GstAdaptiveDemux * demux) return g_date_time_new_from_timeval_utc (>v); } +/** + * gst_adaptive_demux_is_running + * @demux: #GstAdaptiveDemux + * Returns: whether the demuxer is processing data + * + * Returns FALSE if shutdown has started (transitioning down from + * PAUSED), otherwise TRUE. + */ +gboolean +gst_adaptive_demux_is_running (GstAdaptiveDemux * demux) +{ + return g_atomic_int_get (&demux->running); +} + static GstAdaptiveDemuxTimer * gst_adaptive_demux_timer_new (GCond * cond, GMutex * mutex) { diff --git a/gst-libs/gst/adaptivedemux/gstadaptivedemux.h b/gst-libs/gst/adaptivedemux/gstadaptivedemux.h index 1c09c264a..03e4e756c 100644 --- a/gst-libs/gst/adaptivedemux/gstadaptivedemux.h +++ b/gst-libs/gst/adaptivedemux/gstadaptivedemux.h @@ -222,7 +222,7 @@ struct _GstAdaptiveDemux /*< private >*/ GstBin bin; - gboolean running; + gint running; gsize stream_struct_size; @@ -553,6 +553,9 @@ GstClockTime gst_adaptive_demux_get_monotonic_time (GstAdaptiveDemux * demux); GST_ADAPTIVE_DEMUX_API GDateTime *gst_adaptive_demux_get_client_now_utc (GstAdaptiveDemux * demux); +GST_ADAPTIVE_DEMUX_API +gboolean gst_adaptive_demux_is_running (GstAdaptiveDemux * demux); + #ifdef TIZEN_FEATURE_AVOID_PAD_SWITCHING gboolean gst_adaptive_demux_stream_check_switch_pad (GstAdaptiveDemuxStream * stream, GstCaps * caps, GstAdaptiveDemuxStreamCreatePadFunc create_pad_func);