diff options
author | Alessandro Decina <alessandro.d@gmail.com> | 2015-10-13 13:02:51 +1100 |
---|---|---|
committer | Sebastian Dröge <sebastian@centricular.com> | 2015-10-20 13:08:45 +0300 |
commit | 7dcde21f48e9e17c9763fd6882aa41022d443a23 (patch) | |
tree | bf1d99127afb1eca92d7738aee57dcb192ce53de | |
parent | abf2f203e5d47ae1ebecf8357c5ff96a1cdf7b8f (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.recipe | 3 | ||||
-rw-r--r-- | recipes/libnice.recipe | 3 | ||||
-rw-r--r-- | recipes/libnice/0001-nicesrc-spin-the-agent-mainloop-in-a-separate-thread.patch | 253 |
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 + |