summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlessandro Decina <alessandro.d@gmail.com>2015-10-13 13:02:51 +1100
committerSebastian Dröge <sebastian@centricular.com>2015-10-20 13:08:45 +0300
commit7dcde21f48e9e17c9763fd6882aa41022d443a23 (patch)
treebf1d99127afb1eca92d7738aee57dcb192ce53de
parentabf2f203e5d47ae1ebecf8357c5ff96a1cdf7b8f (diff)
libnice: integrate patch to spin the agent's mainloop in a separate thread
https://github.com/EricssonResearch/cerbero/pull/32
-rw-r--r--recipes/libnice-static.recipe3
-rw-r--r--recipes/libnice.recipe3
-rw-r--r--recipes/libnice/0001-nicesrc-spin-the-agent-mainloop-in-a-separate-thread.patch253
3 files changed, 259 insertions, 0 deletions
diff --git a/recipes/libnice-static.recipe b/recipes/libnice-static.recipe
index b7a140cc..634e2a91 100644
--- a/recipes/libnice-static.recipe
+++ b/recipes/libnice-static.recipe
@@ -11,6 +11,9 @@ class Recipe(custom.GStreamerStatic):
extra_configure_options = ' --without-gstreamer-0.10 \
--enable-compile-warnings=maximum'
deps = ['glib', 'gtk-doc-lite', 'gstreamer-1.0']
+ patches = [
+ "libnice/0001-nicesrc-spin-the-agent-mainloop-in-a-separate-thread.patch"
+ ]
files_plugins_net_devel = ['libgstnice']
# FIXME - if_arp.h? (iOS)
diff --git a/recipes/libnice.recipe b/recipes/libnice.recipe
index d590d79a..41dd6d89 100644
--- a/recipes/libnice.recipe
+++ b/recipes/libnice.recipe
@@ -10,6 +10,9 @@ class Recipe(recipe.Recipe):
--without-gstreamer-0.10 --enable-compile-warnings=maximum \
--disable-gtk-doc'
deps = ['glib', 'gtk-doc-lite', 'gstreamer-1.0']
+ patches = [
+ "libnice/0001-nicesrc-spin-the-agent-mainloop-in-a-separate-thread.patch"
+ ]
files_bins = ['stunbdc', 'stund']
files_libs = ['libnice']
diff --git a/recipes/libnice/0001-nicesrc-spin-the-agent-mainloop-in-a-separate-thread.patch b/recipes/libnice/0001-nicesrc-spin-the-agent-mainloop-in-a-separate-thread.patch
new file mode 100644
index 00000000..6af57e8b
--- /dev/null
+++ b/recipes/libnice/0001-nicesrc-spin-the-agent-mainloop-in-a-separate-thread.patch
@@ -0,0 +1,253 @@
+From 3196a96a408a90f707dff3f31fa3d05d64aeb68a Mon Sep 17 00:00:00 2001
+From: Alessandro Decina <alessandro.d@gmail.com>
+Date: Tue, 13 Oct 2015 12:49:19 +1100
+Subject: [PATCH] nicesrc: spin the agent mainloop in a separate thread
+
+Don't run the mainloop from the srcpad task, since that can get blocked in the
+pipeline and cause unnecessary STUN retrasmissions (at best) and completely
+block the agent (at worst).
+---
+ gst/gstnicesrc.c | 158 ++++++++++++++++++++++++++++++++-----------------------
+ gst/gstnicesrc.h | 4 +-
+ 2 files changed, 93 insertions(+), 69 deletions(-)
+
+diff --git a/gst/gstnicesrc.c b/gst/gstnicesrc.c
+index d369e09..eb59fe9 100644
+--- a/gst/gstnicesrc.c
++++ b/gst/gstnicesrc.c
+@@ -48,6 +48,14 @@ GST_DEBUG_CATEGORY_STATIC (nicesrc_debug);
+
+ #define BUFFER_SIZE (65536)
+
++static gboolean
++gst_nice_src_start (
++ GstBaseSrc *basesrc);
++
++static gboolean
++gst_nice_src_stop (
++ GstBaseSrc *basesrc);
++
+ static GstFlowReturn
+ gst_nice_src_create (
+ GstPushSrc *basesrc,
+@@ -57,10 +65,6 @@ static gboolean
+ gst_nice_src_unlock (
+ GstBaseSrc *basesrc);
+
+-static gboolean
+-gst_nice_src_unlock_stop (
+- GstBaseSrc *basesrc);
+-
+ static void
+ gst_nice_src_set_property (
+ GObject *object,
+@@ -116,8 +120,9 @@ gst_nice_src_class_init (GstNiceSrcClass *klass)
+ gstpushsrc_class->create = GST_DEBUG_FUNCPTR (gst_nice_src_create);
+
+ gstbasesrc_class = (GstBaseSrcClass *) klass;
++ gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_nice_src_start);
++ gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_nice_src_stop);
+ gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_nice_src_unlock);
+- gstbasesrc_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_nice_src_unlock_stop);
+
+ gobject_class = (GObjectClass *) klass;
+ gobject_class->set_property = gst_nice_src_set_property;
+@@ -179,9 +184,83 @@ gst_nice_src_init (GstNiceSrc *src)
+ src->component_id = 0;
+ src->mainctx = g_main_context_new ();
+ src->mainloop = g_main_loop_new (src->mainctx, FALSE);
+- src->unlocked = FALSE;
+- src->idle_source = NULL;
+ src->outbufs = g_queue_new ();
++ src->agent_io_thread = NULL;
++ g_cond_init (&src->outcond);
++}
++
++static gpointer
++gst_nice_src_agent_io_thread (gpointer data)
++{
++ GstNiceSrc *nicesrc = GST_NICE_SRC (data);
++
++ GST_INFO_OBJECT (nicesrc, "starting agent io thread");
++ g_main_loop_run (nicesrc->mainloop);
++ GST_INFO_OBJECT (nicesrc, "exiting agent io thread");
++
++ return NULL;
++}
++
++static gboolean
++main_loop_running_cb (gpointer data)
++{
++ GstNiceSrc *nicesrc = GST_NICE_SRC (data);
++
++ GST_OBJECT_LOCK (nicesrc);
++ /* _start() and _stop() could both be waiting for the mainloop to start so we
++ * need to broadcast */
++ g_cond_broadcast (&nicesrc->outcond);
++ GST_OBJECT_UNLOCK (nicesrc);
++
++ return FALSE;
++}
++
++static gboolean
++gst_nice_src_start (GstBaseSrc * basesrc)
++{
++ GstNiceSrc *nicesrc = GST_NICE_SRC (basesrc);
++ GSource *source;
++ gchar *thread_name;
++
++ GST_OBJECT_LOCK (nicesrc);
++ source = g_idle_source_new ();
++ g_source_set_callback (source,
++ (GSourceFunc) main_loop_running_cb, nicesrc, NULL);
++ g_source_attach (source, nicesrc->mainctx);
++ g_source_unref (source);
++
++ thread_name = g_strdup_printf ("%s:agent_io", GST_OBJECT_NAME (nicesrc));
++ nicesrc->agent_io_thread = g_thread_new (thread_name, gst_nice_src_agent_io_thread, nicesrc);
++ g_free (thread_name);
++ /* wait until the agent thread starts spinning the mainloop or _stop() is
++ * called */
++ while (GST_BASE_SRC_IS_STARTING (basesrc) &&
++ !g_main_loop_is_running (nicesrc->mainloop))
++ g_cond_wait (&nicesrc->outcond, GST_OBJECT_GET_LOCK (nicesrc));
++ GST_OBJECT_UNLOCK (nicesrc);
++
++ return TRUE;
++}
++
++static gboolean
++gst_nice_src_stop (GstBaseSrc * basesrc)
++{
++ GstNiceSrc *nicesrc = GST_NICE_SRC (basesrc);
++ GThread *agent_io_thread = NULL;
++
++ GST_OBJECT_LOCK (nicesrc);
++ /* here we wait for the agent thread created in _start() to be scheduled so
++ * that we don't risk calling _quit() first and then _run() on the mainloop */
++ while (!g_main_loop_is_running (nicesrc->mainloop))
++ g_cond_wait (&nicesrc->outcond, GST_OBJECT_GET_LOCK (nicesrc));
++ g_main_loop_quit (nicesrc->mainloop);
++ agent_io_thread = nicesrc->agent_io_thread;
++ nicesrc->agent_io_thread = NULL;
++ GST_OBJECT_UNLOCK (nicesrc);
++
++ g_thread_join (agent_io_thread);
++
++ return TRUE;
+ }
+
+ static void
+@@ -207,62 +286,17 @@ gst_nice_src_read_callback (NiceAgent *agent,
+ #endif
+ GST_OBJECT_LOCK (nicesrc);
+ g_queue_push_tail (nicesrc->outbufs, buffer);
+- g_main_loop_quit (nicesrc->mainloop);
++ g_cond_signal (&nicesrc->outcond);
+ GST_OBJECT_UNLOCK (nicesrc);
+ }
+
+ static gboolean
+-gst_nice_src_unlock_idler (gpointer data)
+-{
+- GstNiceSrc *nicesrc = GST_NICE_SRC (data);
+-
+- GST_OBJECT_LOCK (nicesrc);
+- if (nicesrc->unlocked)
+- g_main_loop_quit (nicesrc->mainloop);
+-
+- if (nicesrc->idle_source) {
+- g_source_destroy (nicesrc->idle_source);
+- g_source_unref (nicesrc->idle_source);
+- nicesrc->idle_source = NULL;
+- }
+- GST_OBJECT_UNLOCK (nicesrc);
+-
+- return FALSE;
+-}
+-
+-static gboolean
+ gst_nice_src_unlock (GstBaseSrc *src)
+ {
+ GstNiceSrc *nicesrc = GST_NICE_SRC (src);
+
+ GST_OBJECT_LOCK (src);
+- nicesrc->unlocked = TRUE;
+-
+- g_main_loop_quit (nicesrc->mainloop);
+-
+- if (!nicesrc->idle_source) {
+- nicesrc->idle_source = g_idle_source_new ();
+- g_source_set_priority (nicesrc->idle_source, G_PRIORITY_HIGH);
+- g_source_set_callback (nicesrc->idle_source, gst_nice_src_unlock_idler, src, NULL);
+- g_source_attach (nicesrc->idle_source, g_main_loop_get_context (nicesrc->mainloop));
+- }
+- GST_OBJECT_UNLOCK (src);
+-
+- return TRUE;
+-}
+-
+-static gboolean
+-gst_nice_src_unlock_stop (GstBaseSrc *src)
+-{
+- GstNiceSrc *nicesrc = GST_NICE_SRC (src);
+-
+- GST_OBJECT_LOCK (src);
+- nicesrc->unlocked = FALSE;
+- if (nicesrc->idle_source) {
+- g_source_destroy (nicesrc->idle_source);
+- g_source_unref(nicesrc->idle_source);
+- }
+- nicesrc->idle_source = NULL;
++ g_cond_signal (&nicesrc->outcond);
+ GST_OBJECT_UNLOCK (src);
+
+ return TRUE;
+@@ -278,19 +312,8 @@ gst_nice_src_create (
+ GST_LOG_OBJECT (nicesrc, "create called");
+
+ GST_OBJECT_LOCK (basesrc);
+- if (nicesrc->unlocked) {
+- GST_OBJECT_UNLOCK (basesrc);
+-#if GST_CHECK_VERSION (1,0,0)
+- return GST_FLOW_FLUSHING;
+-#else
+- return GST_FLOW_WRONG_STATE;
+-#endif
+- }
+- if (g_queue_is_empty (nicesrc->outbufs)) {
+- GST_OBJECT_UNLOCK (basesrc);
+- g_main_loop_run (nicesrc->mainloop);
+- GST_OBJECT_LOCK (basesrc);
+- }
++ if (g_queue_is_empty (nicesrc->outbufs))
++ g_cond_wait (&nicesrc->outcond, GST_OBJECT_GET_LOCK (nicesrc));
+
+ *buffer = g_queue_pop_head (nicesrc->outbufs);
+ GST_OBJECT_UNLOCK (basesrc);
+@@ -331,6 +354,7 @@ gst_nice_src_dispose (GObject *object)
+ g_queue_free (src->outbufs);
+ }
+ src->outbufs = NULL;
++ g_cond_clear (&src->outcond);
+
+ G_OBJECT_CLASS (gst_nice_src_parent_class)->dispose (object);
+ }
+diff --git a/gst/gstnicesrc.h b/gst/gstnicesrc.h
+index 5d3f554..2d9f674 100644
+--- a/gst/gstnicesrc.h
++++ b/gst/gstnicesrc.h
+@@ -68,8 +68,8 @@ struct _GstNiceSrc
+ GMainContext *mainctx;
+ GMainLoop *mainloop;
+ GQueue *outbufs;
+- gboolean unlocked;
+- GSource *idle_source;
++ GCond outcond;
++ GThread *agent_io_thread;
+ };
+
+ typedef struct _GstNiceSrcClass GstNiceSrcClass;
+--
+2.3.4
+