mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
gst/playback/gstdecodebin.c: Handle the case where an element has multiple pads with unfixed caps as well as still po...
Original commit message from CVS: * gst/playback/gstdecodebin.c: (find_dynamic), (dynamic_add), (close_pad_link), (elem_is_dynamic), (unlinked), (close_link): Handle the case where an element has multiple pads with unfixed caps as well as still possibly producing more dynamic pads by storing each case as a distinct entry in the dynamic list. Fixes #38223 again.
This commit is contained in:
parent
bdd8747c6c
commit
35fa7a7fbd
2 changed files with 108 additions and 22 deletions
|
@ -1,3 +1,12 @@
|
||||||
|
2006-12-05 Jan Schmidt <thaytan@mad.scientist.com>
|
||||||
|
|
||||||
|
* gst/playback/gstdecodebin.c: (find_dynamic), (dynamic_add),
|
||||||
|
(close_pad_link), (elem_is_dynamic), (unlinked), (close_link):
|
||||||
|
Handle the case where an element has multiple pads with
|
||||||
|
unfixed caps as well as still possibly producing more dynamic
|
||||||
|
pads by storing each case as a distinct entry in the dynamic list.
|
||||||
|
Fixes #38223 again.
|
||||||
|
|
||||||
2006-12-04 Wim Taymans <wim@fluendo.com>
|
2006-12-04 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
* gst/playback/gstdecodebin.c: (close_pad_link):
|
* gst/playback/gstdecodebin.c: (close_pad_link):
|
||||||
|
|
|
@ -384,27 +384,59 @@ gst_decode_bin_finalize (GObject * object)
|
||||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstDynamic *
|
struct DynFind
|
||||||
dynamic_create (GstElement * element, GstPad * pad, GstDecodeBin * decode_bin)
|
{
|
||||||
|
GstElement *elem;
|
||||||
|
GstPad *pad;
|
||||||
|
};
|
||||||
|
|
||||||
|
static gint
|
||||||
|
find_dynamic (GstDynamic * dyn, struct DynFind *info)
|
||||||
|
{
|
||||||
|
if (dyn->element == info->elem && dyn->pad == info->pad)
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add either an element (for dynamic pads/pad-added watching) or a
|
||||||
|
* pad (for delayed caps/notify::caps watching) to the dynamic list,
|
||||||
|
* taking care to ignore repeat entries so we don't end up handling a
|
||||||
|
* pad twice, for example */
|
||||||
|
static void
|
||||||
|
dynamic_add (GstElement * element, GstPad * pad, GstDecodeBin * decode_bin)
|
||||||
{
|
{
|
||||||
GstDynamic *dyn;
|
GstDynamic *dyn;
|
||||||
|
struct DynFind find_info;
|
||||||
|
GList *found;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (element, "dynamic create");
|
g_return_if_fail (element != NULL || pad != NULL);
|
||||||
|
|
||||||
|
/* do a search that this entry doesn't already exist */
|
||||||
|
find_info.elem = element;
|
||||||
|
find_info.pad = pad;
|
||||||
|
found = g_list_find_custom (decode_bin->dynamics, &find_info,
|
||||||
|
(GCompareFunc) find_dynamic);
|
||||||
|
if (found != NULL)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
/* take refs */
|
/* take refs */
|
||||||
|
|
||||||
dyn = g_new0 (GstDynamic, 1);
|
dyn = g_new0 (GstDynamic, 1);
|
||||||
dyn->element = element;
|
dyn->element = element;
|
||||||
dyn->pad = pad;
|
dyn->pad = pad;
|
||||||
dyn->decode_bin = gst_object_ref (decode_bin);
|
dyn->decode_bin = gst_object_ref (decode_bin);
|
||||||
if (element) {
|
if (element) {
|
||||||
|
GST_DEBUG_OBJECT (decode_bin, "dynamic create for element %"
|
||||||
|
GST_PTR_FORMAT, element);
|
||||||
|
|
||||||
gst_object_ref (element);
|
gst_object_ref (element);
|
||||||
dyn->np_sig_id = g_signal_connect (G_OBJECT (element), "pad-added",
|
dyn->np_sig_id = g_signal_connect (G_OBJECT (element), "pad-added",
|
||||||
G_CALLBACK (new_pad), dyn);
|
G_CALLBACK (new_pad), dyn);
|
||||||
dyn->nmp_sig_id = g_signal_connect (G_OBJECT (element), "no-more-pads",
|
dyn->nmp_sig_id = g_signal_connect (G_OBJECT (element), "no-more-pads",
|
||||||
G_CALLBACK (no_more_pads), dyn);
|
G_CALLBACK (no_more_pads), dyn);
|
||||||
}
|
} else {
|
||||||
if (pad) {
|
GST_DEBUG_OBJECT (decode_bin, "dynamic create for pad %" GST_PTR_FORMAT,
|
||||||
|
pad);
|
||||||
|
|
||||||
gst_object_ref (pad);
|
gst_object_ref (pad);
|
||||||
dyn->caps_sig_id = g_signal_connect (G_OBJECT (pad), "notify::caps",
|
dyn->caps_sig_id = g_signal_connect (G_OBJECT (pad), "notify::caps",
|
||||||
G_CALLBACK (new_caps), dyn);
|
G_CALLBACK (new_caps), dyn);
|
||||||
|
@ -413,7 +445,15 @@ dynamic_create (GstElement * element, GstPad * pad, GstDecodeBin * decode_bin)
|
||||||
/* and add this element to the dynamic elements */
|
/* and add this element to the dynamic elements */
|
||||||
decode_bin->dynamics = g_list_prepend (decode_bin->dynamics, dyn);
|
decode_bin->dynamics = g_list_prepend (decode_bin->dynamics, dyn);
|
||||||
|
|
||||||
return dyn;
|
return;
|
||||||
|
exit:
|
||||||
|
if (element) {
|
||||||
|
GST_DEBUG_OBJECT (decode_bin, "Dynamic element already added: %"
|
||||||
|
GST_PTR_FORMAT, element);
|
||||||
|
} else {
|
||||||
|
GST_DEBUG_OBJECT (decode_bin, "Dynamic pad already added: %"
|
||||||
|
GST_PTR_FORMAT, pad);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -754,7 +794,7 @@ many_types:
|
||||||
setup_caps_delay:
|
setup_caps_delay:
|
||||||
{
|
{
|
||||||
GST_LOG_OBJECT (pad, "setting up a delayed link");
|
GST_LOG_OBJECT (pad, "setting up a delayed link");
|
||||||
dynamic_create (element, pad, decode_bin);
|
dynamic_add (NULL, pad, decode_bin);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1296,23 +1336,61 @@ is_our_kid (GstElement * e, GstDecodeBin * decode_bin)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gint
|
static gboolean
|
||||||
find_dynamic (GstDynamic * dyn, GstElement * elem)
|
elem_is_dynamic (GstElement * element, GstDecodeBin * decode_bin)
|
||||||
{
|
{
|
||||||
return (dyn->element == elem ? 0 : 1);
|
GList *pads;
|
||||||
|
|
||||||
|
/* loop over all the padtemplates */
|
||||||
|
for (pads = GST_ELEMENT_GET_CLASS (element)->padtemplates; pads;
|
||||||
|
pads = g_list_next (pads)) {
|
||||||
|
GstPadTemplate *templ = GST_PAD_TEMPLATE (pads->data);
|
||||||
|
const gchar *templ_name;
|
||||||
|
|
||||||
|
/* we are only interested in source pads */
|
||||||
|
if (GST_PAD_TEMPLATE_DIRECTION (templ) != GST_PAD_SRC)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
templ_name = GST_PAD_TEMPLATE_NAME_TEMPLATE (templ);
|
||||||
|
GST_DEBUG_OBJECT (decode_bin, "got a source pad template %s", templ_name);
|
||||||
|
|
||||||
|
/* figure out what kind of pad this is */
|
||||||
|
switch (GST_PAD_TEMPLATE_PRESENCE (templ)) {
|
||||||
|
case GST_PAD_SOMETIMES:
|
||||||
|
{
|
||||||
|
/* try to get the pad to see if it is already created or
|
||||||
|
* not */
|
||||||
|
GstPad *pad = gst_element_get_pad (element, templ_name);
|
||||||
|
|
||||||
|
if (pad) {
|
||||||
|
GST_DEBUG_OBJECT (decode_bin, "got the pad for sometimes template %s",
|
||||||
|
templ_name);
|
||||||
|
gst_object_unref (pad);
|
||||||
|
} else {
|
||||||
|
GST_DEBUG_OBJECT (decode_bin,
|
||||||
|
"did not get the sometimes pad of template %s", templ_name);
|
||||||
|
/* we have an element that will create dynamic pads */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
/* Don't care about ALWAYS or REQUEST pads */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function will be called when a pad is disconnected for some reason */
|
/* This function will be called when a pad is disconnected for some reason */
|
||||||
static void
|
static void
|
||||||
unlinked (GstPad * pad, GstPad * peerpad, GstDecodeBin * decode_bin)
|
unlinked (GstPad * pad, GstPad * peerpad, GstDecodeBin * decode_bin)
|
||||||
{
|
{
|
||||||
GstDynamic *dyn;
|
|
||||||
GstElement *element, *peer;
|
GstElement *element, *peer;
|
||||||
|
|
||||||
/* inactivate pad */
|
/* inactivate pad */
|
||||||
gst_pad_set_active (pad, GST_ACTIVATE_NONE);
|
gst_pad_set_active (pad, GST_ACTIVATE_NONE);
|
||||||
|
|
||||||
element = gst_pad_get_parent_element (pad);
|
|
||||||
peer = gst_pad_get_parent_element (peerpad);
|
peer = gst_pad_get_parent_element (peerpad);
|
||||||
|
|
||||||
if (!is_our_kid (peer, decode_bin))
|
if (!is_our_kid (peer, decode_bin))
|
||||||
|
@ -1324,15 +1402,16 @@ unlinked (GstPad * pad, GstPad * peerpad, GstDecodeBin * decode_bin)
|
||||||
/* remove all elements linked to the peerpad */
|
/* remove all elements linked to the peerpad */
|
||||||
remove_element_chain (decode_bin, peerpad);
|
remove_element_chain (decode_bin, peerpad);
|
||||||
|
|
||||||
/* if an element removes two pads, then we don't want this twice */
|
/* Re-add as a dynamic element if needed, via close_link */
|
||||||
if (g_list_find_custom (decode_bin->dynamics, element,
|
element = gst_pad_get_parent_element (pad);
|
||||||
(GCompareFunc) find_dynamic) != NULL)
|
if (element) {
|
||||||
goto exit;
|
if (elem_is_dynamic (element, decode_bin))
|
||||||
|
dynamic_add (element, NULL, decode_bin);
|
||||||
|
|
||||||
dyn = dynamic_create (element, NULL, decode_bin);
|
gst_object_unref (element);
|
||||||
|
}
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
gst_object_unref (element);
|
|
||||||
gst_object_unref (peer);
|
gst_object_unref (peer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1410,13 +1489,11 @@ close_link (GstElement * element, GstDecodeBin * decode_bin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (dynamic) {
|
if (dynamic) {
|
||||||
GstDynamic *dyn;
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (decode_bin, "got a dynamic element here");
|
GST_DEBUG_OBJECT (decode_bin, "got a dynamic element here");
|
||||||
/* ok, this element has dynamic pads, set up the signal handlers to be
|
/* ok, this element has dynamic pads, set up the signal handlers to be
|
||||||
* notified of them */
|
* notified of them */
|
||||||
|
|
||||||
dyn = dynamic_create (element, NULL, decode_bin);
|
dynamic_add (element, NULL, decode_bin);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if this is an element with more than 1 pad. If this element
|
/* Check if this is an element with more than 1 pad. If this element
|
||||||
|
|
Loading…
Reference in a new issue