11/*
2- * Copyright (c) 2010, 2018 , Oracle and/or its affiliates. All rights reserved.
2+ * Copyright (c) 2010, 2020 , Oracle and/or its affiliates. All rights reserved.
33 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44 *
55 * This code is free software; you can redistribute it and/or modify it
@@ -434,6 +434,7 @@ void CGstAVPlaybackPipeline::on_pad_added(GstElement *element, GstPad *pad, CGst
434434 const gchar* pstrName = gst_structure_get_name (pStructure);
435435 GstPad *pPad = NULL ;
436436 GstPadLinkReturn ret = GST_PAD_LINK_OK;
437+ GstStateChangeReturn stateRet = GST_STATE_CHANGE_FAILURE;
437438
438439 if (g_str_has_prefix (pstrName, " audio" ))
439440 {
@@ -453,7 +454,20 @@ void CGstAVPlaybackPipeline::on_pad_added(GstElement *element, GstPad *pad, CGst
453454 {
454455 pPad = gst_element_get_static_pad (pPipeline->m_Elements [AUDIO_BIN], " sink" );
455456 gst_bin_add (GST_BIN (pPipeline->m_Elements [PIPELINE]), pPipeline->m_Elements [AUDIO_BIN]);
456- gst_element_set_state (pPipeline->m_Elements [AUDIO_BIN], GST_STATE_READY);
457+ stateRet = gst_element_set_state (pPipeline->m_Elements [AUDIO_BIN], GST_STATE_READY);
458+ if (stateRet == GST_STATE_CHANGE_FAILURE)
459+ {
460+ gst_object_ref (pPipeline->m_Elements [AUDIO_BIN]);
461+ gst_bin_remove (GST_BIN (pPipeline->m_Elements [PIPELINE]), pPipeline->m_Elements [AUDIO_BIN]);
462+ // Remove handles, so we do not receive any more notifications about pads being added or
463+ // when we done adding new pads. Since we fail to switch bin state we got fatal error and
464+ // bus callback will move pipeline into GST_STATE_NULL while holding dispose lock and
465+ // demux (qtdemux) might deadlock since it will call on_pad_added or no_more_pads
466+ // and these callback will hold dispose lock as well.
467+ g_signal_handlers_disconnect_by_func (element, (void *)G_CALLBACK (on_pad_added), pPipeline);
468+ g_signal_handlers_disconnect_by_func (element, (void *)G_CALLBACK (no_more_pads), pPipeline);
469+ goto Error;
470+ }
457471 if (pPad != NULL )
458472 {
459473 ret = gst_pad_link (pad, pPad);
@@ -462,6 +476,8 @@ void CGstAVPlaybackPipeline::on_pad_added(GstElement *element, GstPad *pad, CGst
462476 gst_element_set_state (pPipeline->m_Elements [AUDIO_BIN], GST_STATE_NULL);
463477 gst_object_ref (pPipeline->m_Elements [AUDIO_BIN]);
464478 gst_bin_remove (GST_BIN (pPipeline->m_Elements [PIPELINE]), pPipeline->m_Elements [AUDIO_BIN]);
479+ // We might need to remove callbacks here as well, but it was not necessary before,
480+ // so to avoid any regression we will not do it here.
465481 goto Error;
466482 }
467483 }
@@ -476,7 +492,15 @@ void CGstAVPlaybackPipeline::on_pad_added(GstElement *element, GstPad *pad, CGst
476492 {
477493 pPad = gst_element_get_static_pad (pPipeline->m_Elements [VIDEO_BIN], " sink" );
478494 gst_bin_add (GST_BIN (pPipeline->m_Elements [PIPELINE]), pPipeline->m_Elements [VIDEO_BIN]);
479- gst_element_set_state (pPipeline->m_Elements [VIDEO_BIN], GST_STATE_READY);
495+ stateRet = gst_element_set_state (pPipeline->m_Elements [VIDEO_BIN], GST_STATE_READY);
496+ if (stateRet == GST_STATE_CHANGE_FAILURE)
497+ {
498+ gst_object_ref (pPipeline->m_Elements [VIDEO_BIN]);
499+ gst_bin_remove (GST_BIN (pPipeline->m_Elements [PIPELINE]), pPipeline->m_Elements [VIDEO_BIN]);
500+ g_signal_handlers_disconnect_by_func (element, (void *)G_CALLBACK (on_pad_added), pPipeline);
501+ g_signal_handlers_disconnect_by_func (element, (void *)G_CALLBACK (no_more_pads), pPipeline);
502+ goto Error;
503+ }
480504 if (pPad != NULL )
481505 {
482506 ret = gst_pad_link (pad, pPad);
0 commit comments