mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 09:10:36 +00:00
bin: Add method to find elements by factory name
A common use case of a dynamically built pipeline is that you want to (conditionally) find a certain element, e.g. the `rtpbin`s in a `uridecodebin`. If that element has a fixed name inside its parent bin (and only has a single instance) this can be easily done by `gst_bin_get_by_name()`. If there are multiple instances of the element however, you can only use `gst_bin_iterate_all_by_interface()`, but this doesn't work if you don't have the specific `GType` (which is often the case, due to plugins being dynamically loaded). As such, another fallback could be to use the well-known name of the element's factory (in case of our example, this is of course `"rtpbin"`).
This commit is contained in:
parent
1d549ea324
commit
0cb3940c94
3 changed files with 133 additions and 0 deletions
53
gst/gstbin.c
53
gst/gstbin.c
|
@ -4630,3 +4630,56 @@ gst_bin_iterate_all_by_interface (GstBin * bin, GType iface)
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
static gint
|
||||
compare_factory_names (const GValue * velement, GValue * factory_name_val)
|
||||
{
|
||||
GstElement *element = g_value_get_object (velement);
|
||||
GstElementFactory *factory = gst_element_get_factory (element);
|
||||
const gchar *factory_name = g_value_get_string (factory_name_val);
|
||||
|
||||
if (factory == NULL)
|
||||
return -1;
|
||||
|
||||
return g_strcmp0 (GST_OBJECT_NAME (factory), factory_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_bin_iterate_all_by_element_factory_name:
|
||||
* @bin: a #GstBin
|
||||
* @factory_name: (not nullable): the name of the #GstElementFactory
|
||||
*
|
||||
* Looks for all elements inside the bin with the given element factory name.
|
||||
* The function recurses inside child bins. The iterator will yield a series of
|
||||
* #GstElement that should be unreffed after use.
|
||||
*
|
||||
* MT safe. Caller owns returned value.
|
||||
*
|
||||
* Returns: (transfer full) (nullable): a #GstIterator of #GstElement
|
||||
* for all elements in the bin with the given element factory name,
|
||||
* or %NULL.
|
||||
*
|
||||
* Since: 1.18
|
||||
*/
|
||||
GstIterator *
|
||||
gst_bin_iterate_all_by_element_factory_name (GstBin * bin,
|
||||
const gchar * factory_name)
|
||||
{
|
||||
GstIterator *children;
|
||||
GstIterator *result;
|
||||
GValue factory_name_val = G_VALUE_INIT;
|
||||
|
||||
g_return_val_if_fail (GST_IS_BIN (bin), NULL);
|
||||
g_return_val_if_fail (factory_name && *factory_name, NULL);
|
||||
|
||||
g_value_init (&factory_name_val, G_TYPE_STRING);
|
||||
g_value_set_string (&factory_name_val, factory_name);
|
||||
|
||||
children = gst_bin_iterate_recurse (bin);
|
||||
result = gst_iterator_filter (children, (GCompareFunc) compare_factory_names,
|
||||
&factory_name_val);
|
||||
|
||||
g_value_unset (&factory_name_val);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -237,6 +237,9 @@ GstIterator* gst_bin_iterate_sources (GstBin *bin);
|
|||
GST_API
|
||||
GstIterator* gst_bin_iterate_all_by_interface (GstBin *bin, GType iface);
|
||||
|
||||
GST_API
|
||||
GstIterator* gst_bin_iterate_all_by_element_factory_name (GstBin * bin, const gchar * factory_name);
|
||||
|
||||
/* latency */
|
||||
|
||||
GST_API
|
||||
|
|
|
@ -153,6 +153,82 @@ GST_START_TEST (test_interface)
|
|||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_iterate_all_by_element_factory_name)
|
||||
{
|
||||
GstBin *bin, *bin2;
|
||||
GstElement *filesrc;
|
||||
GstIterator *it;
|
||||
GValue item = { 0, };
|
||||
|
||||
bin = GST_BIN (gst_bin_new (NULL));
|
||||
fail_unless (bin != NULL, "Could not create bin");
|
||||
|
||||
filesrc = gst_element_factory_make ("filesrc", NULL);
|
||||
fail_unless (filesrc != NULL, "Could not create filesrc");
|
||||
gst_bin_add (bin, filesrc);
|
||||
|
||||
/* Test bin with single element */
|
||||
it = gst_bin_iterate_all_by_element_factory_name (bin, "filesrc");
|
||||
fail_unless (it != NULL);
|
||||
fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
|
||||
fail_unless (g_value_get_object (&item) == (gpointer) filesrc);
|
||||
g_value_reset (&item);
|
||||
fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
|
||||
gst_iterator_free (it);
|
||||
|
||||
/* Negative test bin with single element */
|
||||
it = gst_bin_iterate_all_by_element_factory_name (bin, "filesink");
|
||||
fail_unless (it != NULL);
|
||||
fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
|
||||
gst_iterator_free (it);
|
||||
|
||||
/* Test bin with multiple other elements, 1 layer */
|
||||
gst_bin_add_many (bin,
|
||||
gst_element_factory_make ("identity", NULL),
|
||||
gst_element_factory_make ("identity", NULL),
|
||||
gst_element_factory_make ("identity", NULL), NULL);
|
||||
it = gst_bin_iterate_all_by_element_factory_name (bin, "filesrc");
|
||||
fail_unless (it != NULL);
|
||||
fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
|
||||
fail_unless (g_value_get_object (&item) == (gpointer) filesrc);
|
||||
g_value_reset (&item);
|
||||
fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
|
||||
gst_iterator_free (it);
|
||||
|
||||
/* Test bin with multiple other elements in subbins */
|
||||
bin2 = bin;
|
||||
bin = GST_BIN (gst_bin_new (NULL));
|
||||
fail_unless (bin != NULL);
|
||||
gst_bin_add_many (bin,
|
||||
gst_element_factory_make ("identity", NULL),
|
||||
gst_element_factory_make ("identity", NULL),
|
||||
GST_ELEMENT (bin2), gst_element_factory_make ("identity", NULL), NULL);
|
||||
it = gst_bin_iterate_all_by_element_factory_name (bin, "filesrc");
|
||||
fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
|
||||
fail_unless (g_value_get_object (&item) == (gpointer) filesrc);
|
||||
g_value_reset (&item);
|
||||
fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
|
||||
gst_iterator_free (it);
|
||||
|
||||
/* Test bin with multiple other elements, multiple occurrences in subbins */
|
||||
gst_bin_add (bin, gst_element_factory_make ("filesrc", NULL));
|
||||
gst_bin_add (bin2, gst_element_factory_make ("filesrc", NULL));
|
||||
it = gst_bin_iterate_all_by_element_factory_name (bin, "filesrc");
|
||||
fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
|
||||
g_value_reset (&item);
|
||||
fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
|
||||
g_value_reset (&item);
|
||||
fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
|
||||
g_value_reset (&item);
|
||||
fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
|
||||
g_value_unset (&item);
|
||||
gst_iterator_free (it);
|
||||
|
||||
gst_object_unref (bin);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_eos)
|
||||
{
|
||||
GstBus *bus;
|
||||
|
@ -1789,6 +1865,7 @@ gst_bin_suite (void)
|
|||
|
||||
suite_add_tcase (s, tc_chain);
|
||||
tcase_add_test (tc_chain, test_interface);
|
||||
tcase_add_test (tc_chain, test_iterate_all_by_element_factory_name);
|
||||
tcase_add_test (tc_chain, test_eos);
|
||||
tcase_add_test (tc_chain, test_stream_start);
|
||||
tcase_add_test (tc_chain, test_children_state_change_order_flagged_sink);
|
||||
|
|
Loading…
Reference in a new issue