summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wtaymans@redhat.com>2015-07-16 18:47:20 +0200
committerWim Taymans <wtaymans@redhat.com>2015-07-16 18:54:50 +0200
commiteedd9cb7b7ecb50f538f70cd1269ca767bf62140 (patch)
tree6db3444fdf81393fc1718c8d9cb491a8290e05c2
parentb4dbb9d7427c27a2297287b5d29b36bd50eb356e (diff)
devicemonitor: do start and stop outside of the lock
Release the monitor lock when calling the provider start/stop methods. Because we release the lock now, We need to make sure we check the cookie again and keep track of started and removed providers.
-rw-r--r--gst/gstdevicemonitor.c84
1 files changed, 71 insertions, 13 deletions
diff --git a/gst/gstdevicemonitor.c b/gst/gstdevicemonitor.c
index 994263a45..a07c6d8f0 100644
--- a/gst/gstdevicemonitor.c
+++ b/gst/gstdevicemonitor.c
@@ -343,7 +343,8 @@ again:
gboolean
gst_device_monitor_start (GstDeviceMonitor * monitor)
{
- guint i;
+ guint cookie, i;
+ GList *pending = NULL, *started = NULL, *removed = NULL;
g_return_val_if_fail (GST_IS_DEVICE_MONITOR (monitor), FALSE);
@@ -365,28 +366,73 @@ gst_device_monitor_start (GstDeviceMonitor * monitor)
gst_bus_set_flushing (monitor->priv->bus, FALSE);
+again:
+ cookie = monitor->priv->cookie;
+
+ g_list_free_full (pending, gst_object_unref);
+ pending = NULL;
+ removed = started;
+ started = NULL;
+
for (i = 0; i < monitor->priv->providers->len; i++) {
- GstDeviceProvider *provider =
- g_ptr_array_index (monitor->priv->providers, i);
+ GstDeviceProvider *provider;
+ GList *find;
+
+ provider = g_ptr_array_index (monitor->priv->providers, i);
+
+ find = g_list_find (removed, provider);
+ if (find) {
+ /* this was already started, move to started list */
+ removed = g_list_remove_link (removed, find);
+ started = g_list_concat (started, find);
+ } else {
+ /* not started, add to pending list */
+ pending = g_list_append (pending, gst_object_ref (provider));
+ }
+ }
+ g_list_free_full (removed, gst_object_unref);
+ removed = NULL;
+
+ while (pending) {
+ GstDeviceProvider *provider = pending->data;
if (gst_device_provider_can_monitor (provider)) {
- if (!gst_device_provider_start (provider)) {
- gst_bus_set_flushing (monitor->priv->bus, TRUE);
+ GST_OBJECT_UNLOCK (monitor);
- for (; i != 0; i--)
- gst_device_provider_stop (g_ptr_array_index (monitor->priv->providers,
- i - 1));
+ if (!gst_device_provider_start (provider))
+ goto start_failed;
- GST_OBJECT_UNLOCK (monitor);
- return FALSE;
- }
+ GST_OBJECT_LOCK (monitor);
}
- }
+ started = g_list_prepend (started, provider);
+ pending = g_list_delete_link (pending, pending);
+ if (monitor->priv->cookie != cookie)
+ goto again;
+ }
monitor->priv->started = TRUE;
GST_OBJECT_UNLOCK (monitor);
+ g_list_free_full (started, gst_object_unref);
+
return TRUE;
+
+start_failed:
+ {
+ GST_OBJECT_LOCK (monitor);
+ gst_bus_set_flushing (monitor->priv->bus, TRUE);
+ GST_OBJECT_UNLOCK (monitor);
+
+ while (started) {
+ GstDeviceProvider *provider = started->data;
+
+ gst_device_provider_stop (provider);
+ gst_object_unref (provider);
+
+ started = g_list_delete_link (started, started);
+ }
+ return FALSE;
+ }
}
/**
@@ -401,6 +447,7 @@ void
gst_device_monitor_stop (GstDeviceMonitor * monitor)
{
guint i;
+ GList *started = NULL;
g_return_if_fail (GST_IS_DEVICE_MONITOR (monitor));
@@ -411,9 +458,21 @@ gst_device_monitor_stop (GstDeviceMonitor * monitor)
GstDeviceProvider *provider =
g_ptr_array_index (monitor->priv->providers, i);
+ started = g_list_prepend (started, gst_object_ref (provider));
+ }
+ GST_OBJECT_UNLOCK (monitor);
+
+ while (started) {
+ GstDeviceProvider *provider = started->data;
+
if (gst_device_provider_can_monitor (provider))
gst_device_provider_stop (provider);
+
+ started = g_list_delete_link (started, started);
+ gst_object_unref (provider);
}
+
+ GST_OBJECT_LOCK (monitor);
monitor->priv->started = FALSE;
GST_OBJECT_UNLOCK (monitor);
@@ -463,7 +522,6 @@ gst_device_monitor_add_filter (GstDeviceMonitor * monitor,
while (factories) {
GstDeviceProviderFactory *factory = factories->data;
-
if (gst_device_provider_factory_has_classesv (factory, filter->classesv)) {
GstDeviceProvider *provider;