mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-26 04:26:14 +00:00
decodebin: Shut down all elements explicitly to NULL state before freeing the decode chain
Due to transient locked state during autoplugging, some elements might be ignored by the GstBin::change_state() and might still be running. Which could then cause pad-added and similar accessing decodebin state that does not exist anymore, and crash. https://bugzilla.gnome.org/show_bug.cgi?id=763625
This commit is contained in:
parent
65390b5129
commit
9c2d76fb9f
1 changed files with 75 additions and 0 deletions
|
@ -5165,6 +5165,80 @@ unblock_pads (GstDecodeBin * dbin)
|
||||||
dbin->blocked_pads = NULL;
|
dbin->blocked_pads = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_decode_chain_stop (GstDecodeBin * dbin, GstDecodeChain * chain,
|
||||||
|
GQueue * elements)
|
||||||
|
{
|
||||||
|
GQueue *internal_elements, internal_elements_ = G_QUEUE_INIT;
|
||||||
|
GList *l;
|
||||||
|
|
||||||
|
CHAIN_MUTEX_LOCK (chain);
|
||||||
|
if (elements) {
|
||||||
|
internal_elements = elements;
|
||||||
|
} else {
|
||||||
|
internal_elements = &internal_elements_;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (l = chain->next_groups; l; l = l->next) {
|
||||||
|
GstDecodeGroup *group = l->data;
|
||||||
|
GList *m;
|
||||||
|
|
||||||
|
for (m = group->children; m; m = m->next) {
|
||||||
|
GstDecodeChain *chain2 = m->data;
|
||||||
|
gst_decode_chain_stop (dbin, chain2, internal_elements);
|
||||||
|
}
|
||||||
|
if (group->multiqueue)
|
||||||
|
g_queue_push_head (internal_elements, gst_object_ref (group->multiqueue));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chain->active_group) {
|
||||||
|
for (l = chain->active_group->children; l; l = l->next) {
|
||||||
|
GstDecodeChain *chain2 = l->data;
|
||||||
|
gst_decode_chain_stop (dbin, chain2, internal_elements);
|
||||||
|
}
|
||||||
|
if (chain->active_group->multiqueue)
|
||||||
|
g_queue_push_head (internal_elements,
|
||||||
|
gst_object_ref (chain->active_group->multiqueue));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (l = chain->old_groups; l; l = l->next) {
|
||||||
|
GstDecodeGroup *group = l->data;
|
||||||
|
GList *m;
|
||||||
|
|
||||||
|
for (m = group->children; m; m = m->next) {
|
||||||
|
GstDecodeChain *chain2 = m->data;
|
||||||
|
gst_decode_chain_stop (dbin, chain2, internal_elements);
|
||||||
|
}
|
||||||
|
if (group->multiqueue)
|
||||||
|
g_queue_push_head (internal_elements, gst_object_ref (group->multiqueue));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (l = chain->elements; l; l = l->next) {
|
||||||
|
GstDecodeElement *delem = l->data;
|
||||||
|
|
||||||
|
if (delem->capsfilter)
|
||||||
|
g_queue_push_head (internal_elements, gst_object_ref (delem->capsfilter));
|
||||||
|
g_queue_push_head (internal_elements, gst_object_ref (delem->element));
|
||||||
|
}
|
||||||
|
|
||||||
|
CHAIN_MUTEX_UNLOCK (chain);
|
||||||
|
|
||||||
|
if (!elements) {
|
||||||
|
GstElement *element;
|
||||||
|
|
||||||
|
EXPOSE_UNLOCK (dbin);
|
||||||
|
/* Shut down from bottom to top */
|
||||||
|
while ((element = g_queue_pop_tail (internal_elements))) {
|
||||||
|
/* The bin must never ever change the state of this element anymore */
|
||||||
|
gst_element_set_locked_state (element, TRUE);
|
||||||
|
gst_element_set_state (element, GST_STATE_NULL);
|
||||||
|
gst_object_unref (element);
|
||||||
|
}
|
||||||
|
g_queue_clear (internal_elements);
|
||||||
|
EXPOSE_LOCK (dbin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static GstStateChangeReturn
|
static GstStateChangeReturn
|
||||||
gst_decode_bin_change_state (GstElement * element, GstStateChange transition)
|
gst_decode_bin_change_state (GstElement * element, GstStateChange transition)
|
||||||
{
|
{
|
||||||
|
@ -5229,6 +5303,7 @@ gst_decode_bin_change_state (GstElement * element, GstStateChange transition)
|
||||||
do_async_done (dbin);
|
do_async_done (dbin);
|
||||||
EXPOSE_LOCK (dbin);
|
EXPOSE_LOCK (dbin);
|
||||||
if (dbin->decode_chain) {
|
if (dbin->decode_chain) {
|
||||||
|
gst_decode_chain_stop (dbin, dbin->decode_chain, NULL);
|
||||||
chain_to_free = dbin->decode_chain;
|
chain_to_free = dbin->decode_chain;
|
||||||
gst_decode_chain_free_internal (dbin->decode_chain, TRUE);
|
gst_decode_chain_free_internal (dbin->decode_chain, TRUE);
|
||||||
dbin->decode_chain = NULL;
|
dbin->decode_chain = NULL;
|
||||||
|
|
Loading…
Reference in a new issue